From: notaz Date: Mon, 27 Jul 2009 21:24:25 +0000 (+0000) Subject: anti-tear modes for Wiz X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b79118011b8b1ac835efed1ac5a9ce3bdc55c158;p=libpicofe.git anti-tear modes for Wiz git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@717 be3aeb3a-fb24-0410-a615-afba39da0efa --- diff --git a/common/arm_utils.h b/common/arm_utils.h index 12802a3..ae5ae24 100644 --- a/common/arm_utils.h +++ b/common/arm_utils.h @@ -1,4 +1,4 @@ -// (c) Copyright 2006 notaz, All rights reserved. +// (c) Copyright 2006-2009 notaz, All rights reserved. // Free for non-commercial use. // For commercial use, separate licencing terms must be obtained. @@ -6,8 +6,9 @@ void vidConvCpyRGB32 (void *to, void *from, int pixels); void vidConvCpyRGB32sh(void *to, void *from, int pixels); void vidConvCpyRGB32hi(void *to, void *from, int pixels); -void vidCpyM2_40col(void *dest, void *src); -void vidCpyM2_32col(void *dest, void *src); -void vidCpyM2_32col_nobord(void *dest, void *src); +void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border); +void vidcpy_m2_rot(void *dest, void *src, int m32col, int with_32c_border); void spend_cycles(int c); // utility +void rotated_blit8 (void *dst, void *linesx4, int y, int is_32col); +void rotated_blit16(void *dst, void *linesx4, int y, int is_32col); diff --git a/common/arm_utils.s b/common/arm_utils.s index 9d51649..b93b99f 100644 --- a/common/arm_utils.s +++ b/common/arm_utils.s @@ -137,69 +137,201 @@ vidConvCpyRGB32hi: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@ mode2 blitter for 40 cols -.global vidCpyM2_40col @ void *dest, void *src - -vidCpyM2_40col: +@ mode2 blitter +.global vidcpy_m2 @ void *dest, void *src, int m32col, int with_32c_border +vidcpy_m2: stmfd sp!, {r4-r6,lr} mov r12, #224 @ lines + add r0, r0, #320*8 add r1, r1, #8 + mov lr, #0 + + tst r2, r2 + movne lr, #64 + tstne r3, r3 + addne r0, r0, #32 -vidCpyM2_40_loop_out: +vidCpyM2_loop_out: mov r6, #10 -vidCpyM2_40_loop: + sub r6, r6, lr, lsr #5 @ -= 2 in 32col mode +vidCpyM2_loop: subs r6, r6, #1 - ldmia r1!, {r2-r5} - stmia r0!, {r2-r5} - ldmia r1!, {r2-r5} - stmia r0!, {r2-r5} - bne vidCpyM2_40_loop + ldmia r1!, {r2-r5} + stmia r0!, {r2-r5} + ldmia r1!, {r2-r5} + stmia r0!, {r2-r5} + bne vidCpyM2_loop + subs r12,r12,#1 + add r0, r0, lr add r1, r1, #8 - bne vidCpyM2_40_loop_out - - ldmfd sp!, {r4-r6,lr} - bx lr + add r1, r1, lr + bne vidCpyM2_loop_out + ldmfd sp!, {r4-r6,pc} -@ mode2 blitter for 32 cols -.global vidCpyM2_32col @ void *dest, void *src -vidCpyM2_32col: - stmfd sp!, {r4-r6,lr} - - mov r12, #224 @ lines +.global vidcpy_m2_rot @ void *dest, void *src, int m32col, int with_32c_border +vidcpy_m2_rot: + stmfd sp!,{r4-r8,lr} add r1, r1, #8 - add r0, r0, #32 - -vidCpyM2_32_loop_out: - mov r6, #8 -vidCpyM2_32_loop: - subs r6, r6, #1 - ldmia r1!, {r2-r5} - stmia r0!, {r2-r5} - ldmia r1!, {r2-r5} - stmia r0!, {r2-r5} - bne vidCpyM2_32_loop - subs r12,r12,#1 - add r0, r0, #64 - add r1, r1, #8+64 - bne vidCpyM2_32_loop_out - - ldmfd sp!, {r4-r6,lr} - bx lr - - -@ mode2 blitter for 32 cols with no borders -.global vidCpyM2_32col_nobord @ void *dest, void *src + tst r2, r2 + subne r1, r1, #32 @ adjust + + mov r4, r0 + mov r5, r1 + mov r6, r2 + mov r7, #8+4 + +vidcpy_m2_rot_loop: + @ a bit lame but oh well.. + mov r0, r4 + mov r1, r5 + mov r2, r7 + mov r3, r6 + mov r8, #328 + adr lr, after_rot_blit8 + stmfd sp!,{r4-r8,lr} + b rotated_blit8_2 + +after_rot_blit8: + add r5, r5, #328*4 + add r7, r7, #4 + cmp r7, #224+8+4 + ldmgefd sp!,{r4-r8,pc} + b vidcpy_m2_rot_loop + + +.global rotated_blit8 @ void *dst, void *linesx4, u32 y, int is_32col +rotated_blit8: + stmfd sp!,{r4-r8,lr} + mov r8, #320 + +rotated_blit8_2: + add r0, r0, #(240*320) + sub r0, r0, #(240+4) @ y starts from 4 + add r0, r0, r2 + + tst r3, r3 + subne r0, r0, #(240*32) + addne r1, r1, #32 + movne lr, #256/4 + moveq lr, #320/4 + +rotated_blit_loop8: + mov r6, r1 + ldr r2, [r6], r8 + ldr r3, [r6], r8 + ldr r4, [r6], r8 + ldr r5, [r6], r8 + + mov r6, r2, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r3, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r4, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r5, lsl #24 + str r6, [r0], #-240 + + and r6, r3, #0xff00 + and r7, r2, #0xff00 + orr r6, r6, r7, lsr #8 + and r7, r4, #0xff00 + orr r6, r6, r7, lsl #8 + and r7, r5, #0xff00 + orr r6, r6, r7, lsl #16 + str r6, [r0], #-240 + + and r6, r4, #0xff0000 + and r7, r2, #0xff0000 + orr r6, r6, r7, lsr #16 + and r7, r3, #0xff0000 + orr r6, r6, r7, lsr #8 + and r7, r5, #0xff0000 + orr r6, r6, r7, lsl #8 + str r6, [r0], #-240 + + mov r6, r5, lsr #24 + mov r6, r6, lsl #8 + orr r6, r6, r4, lsr #24 + mov r6, r6, lsl #8 + orr r6, r6, r3, lsr #24 + mov r6, r6, lsl #8 + orr r6, r6, r2, lsr #24 + str r6, [r0], #-240 + + subs lr, lr, #1 + add r1, r1, #4 + bne rotated_blit_loop8 + + ldmfd sp!,{r4-r8,pc} + + +@ input: r2-r5 +@ output: r7,r8 +@ trash: r6 +.macro rb_line_low + mov r6, r2, lsl #16 + mov r7, r3, lsl #16 + orr r7, r7, r6, lsr #16 + mov r6, r4, lsl #16 + mov r8, r5, lsl #16 + orr r8, r8, r6, lsr #16 +.endm -vidCpyM2_32col_nobord: - stmfd sp!, {r4-r6,lr} +.macro rb_line_hi + mov r6, r2, lsr #16 + mov r7, r3, lsr #16 + orr r7, r6, r7, lsl #16 + mov r6, r4, lsr #16 + mov r8, r5, lsr #16 + orr r8, r6, r8, lsl #16 +.endm - mov r12, #224 @ lines +.global rotated_blit16 @ void *dst, void *linesx4, u32 y, int is_32col +rotated_blit16: + stmfd sp!,{r4-r8,lr} + + add r0, r0, #(240*320)*2 + sub r0, r0, #(240+4)*2 @ y starts from 4 + add r0, r0, r2, lsl #1 + + tst r3, r3 + subne r0, r0, #(240*32)*2 + addne r1, r1, #32*2 + movne lr, #256/4 + moveq lr, #320/4 + +rotated_blit_loop16: + ldr r2, [r1, #320*0*2] + ldr r3, [r1, #320*1*2] + ldr r4, [r1, #320*2*2] + ldr r5, [r1, #320*3*2] + rb_line_low + stmia r0, {r7,r8} + sub r0, r0, #240*2 + rb_line_hi + stmia r0, {r7,r8} + sub r0, r0, #240*2 + + ldr r2, [r1, #320*0*2+4] + ldr r3, [r1, #320*1*2+4] + ldr r4, [r1, #320*2*2+4] + ldr r5, [r1, #320*3*2+4] + rb_line_low + stmia r0, {r7,r8} + sub r0, r0, #240*2 + rb_line_hi + stmia r0, {r7,r8} + sub r0, r0, #240*2 + + subs lr, lr, #1 add r1, r1, #8 - b vidCpyM2_32_loop_out + bne rotated_blit_loop16 + + ldmfd sp!,{r4-r8,pc} .global spend_cycles @ c @@ -213,4 +345,3 @@ spend_cycles: bx lr - diff --git a/common/emu.c b/common/emu.c index 8548bdc..1c7d1b7 100644 --- a/common/emu.c +++ b/common/emu.c @@ -662,32 +662,36 @@ int emu_write_config(int is_game) /* always using built-in font */ -#define mk_text_out(name, type, val) \ +#define mk_text_out(name, type, val, topleft, step_x, step_y) \ void name(int x, int y, const char *text) \ { \ int i, l, len = strlen(text); \ - type *screen = (type *)g_screen_ptr + x + y * g_screen_width; \ + type *screen = (type *)(topleft) + x * step_x + y * step_y; \ \ - for (i = 0; i < len; i++, screen += 8) \ + for (i = 0; i < len; i++, screen += 8 * step_x) \ { \ for (l = 0; l < 8; l++) \ { \ unsigned char fd = fontdata8x8[text[i] * 8 + l];\ - type *s = screen + l * g_screen_width; \ - if (fd&0x80) s[0] = val; \ - if (fd&0x40) s[1] = val; \ - if (fd&0x20) s[2] = val; \ - if (fd&0x10) s[3] = val; \ - if (fd&0x08) s[4] = val; \ - if (fd&0x04) s[5] = val; \ - if (fd&0x02) s[6] = val; \ - if (fd&0x01) s[7] = val; \ + type *s = screen + l * step_y; \ + if (fd&0x80) s[step_x * 0] = val; \ + if (fd&0x40) s[step_x * 1] = val; \ + if (fd&0x20) s[step_x * 2] = val; \ + if (fd&0x10) s[step_x * 3] = val; \ + if (fd&0x08) s[step_x * 4] = val; \ + if (fd&0x04) s[step_x * 5] = val; \ + if (fd&0x02) s[step_x * 6] = val; \ + if (fd&0x01) s[step_x * 7] = val; \ } \ } \ } -mk_text_out(emu_textOut8, unsigned char, 0xf0) -mk_text_out(emu_textOut16, unsigned short, 0xffff) +mk_text_out(emu_text_out8, unsigned char, 0xf0, g_screen_ptr, 1, g_screen_width) +mk_text_out(emu_text_out16, unsigned short, 0xffff, g_screen_ptr, 1, g_screen_width) +mk_text_out(emu_text_out8_rot, unsigned char, 0xf0, + (char *)g_screen_ptr + (g_screen_width - 1) * g_screen_height, -g_screen_height, 1) +mk_text_out(emu_text_out16_rot, unsigned short, 0xffff, + (short *)g_screen_ptr + (g_screen_width - 1) * g_screen_height, -g_screen_height, 1) #undef mk_text_out diff --git a/common/emu.h b/common/emu.h index a2d5eb6..28aed4f 100644 --- a/common/emu.h +++ b/common/emu.h @@ -33,6 +33,12 @@ extern int g_screen_height; #define EOPT_CONFIRM_LOAD (1<<11) #define EOPT_A_SN_GAMMA (1<<12) #define EOPT_PSYNC (1<<13) +#define EOPT_GIZ_SCANLN (1<<14) +#define EOPT_GIZ_DBLBUF (1<<15) +#define EOPT_VSYNC_MODE (1<<16) +#define EOPT_SHOW_RTC (1<<17) +#define EOPT_NO_FRMLIMIT (1<<18) +#define EOPT_WIZ_TEAR_FIX (1<<19) enum { EOPT_SCALE_NONE = 0, @@ -42,13 +48,8 @@ enum { }; typedef struct _currentConfig_t { - // char lastRomFile[512]; - int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves, - // mmuhack, no_save_cfg_on_exit, , 16_bit_mode - // craigix_ram, confirm_save, show_cd_leds, confirm_load - // A_SNs_gamma, perfect_vsync, giz_scanlines, giz_dblbuff - // vsync_mode, show_clock, no_frame_limitter - int s_PicoOpt; // for old cfg files only + int EmuOpt; + int s_PicoOpt; int s_PsndRate; int s_PicoRegion; int s_PicoAutoRgnOrder; @@ -111,10 +112,13 @@ char *emu_get_save_fname(int load, int is_sram, int slot); int emu_check_save_file(int slot); void emu_setSaveStateCbs(int gz); +void emu_text_out8 (int x, int y, const char *text); +void emu_text_out16(int x, int y, const char *text); +void emu_text_out8_rot (int x, int y, const char *text); +void emu_text_out16_rot(int x, int y, const char *text); + void emu_make_path(char *buff, const char *end, int size); void emu_update_input(void); -void emu_textOut8 (int x, int y, const char *text); -void emu_textOut16(int x, int y, const char *text); void emu_get_game_name(char *str150); void emu_set_fastforward(int set_on); int emu_cd_check(int *pregion, char *fname_in); diff --git a/common/menu.c b/common/menu.c index bc22e1e..d8dd50c 100644 --- a/common/menu.c +++ b/common/menu.c @@ -1495,6 +1495,7 @@ static menu_entry e_menu_gfx_options[] = { mee_cust ("Renderer", MA_OPT_RENDERER, mh_opt_render, mgn_opt_renderer), mee_range_cust("Scaling", MA_OPT_SCALING, currentConfig.scaling, 0, 3, mgn_opt_scaling), + mee_onoff ("Tearing Fix", MA_OPT_TEARING_FIX, currentConfig.EmuOpt, EOPT_WIZ_TEAR_FIX), mee_range_cust("Gamma correction", MA_OPT2_GAMMA, currentConfig.gamma, 1, 300, mgn_aopt_gamma), mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, EOPT_A_SN_GAMMA), mee_onoff ("Perfect vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, EOPT_PSYNC), diff --git a/common/menu.h b/common/menu.h index 588bfb9..f3d1859 100644 --- a/common/menu.h +++ b/common/menu.h @@ -46,6 +46,7 @@ typedef enum MA_OPT_LOADCFG, MA_OPT_INTERLACED, /* giz */ MA_OPT_ROTATION, /* uiq */ + MA_OPT_TEARING_FIX, /* wiz */ MA_OPT2_GAMMA, MA_OPT2_A_SN_GAMMA, MA_OPT2_DBLBUFF, /* giz */ diff --git a/gp2x/940ctl.c b/gp2x/940ctl.c index 921922c..38a9f9d 100644 --- a/gp2x/940ctl.c +++ b/gp2x/940ctl.c @@ -17,6 +17,7 @@ #include "../common/arm_utils.h" #include "../common/menu.h" #include "../common/emu.h" +#include "../common/input.h" #include "../../pico/pico_int.h" #include "../../pico/sound/ym2612.h" #include "../../pico/sound/mix.h" @@ -294,7 +295,7 @@ void YM2612Init_940(int baseclock, int rate) if (crashed_940) { unsigned char ucData[1024]; - int nRead, i, nLen = 0; + int nRead, nLen = 0; char binpath[512]; FILE *fp; @@ -306,6 +307,7 @@ void YM2612Init_940(int baseclock, int rate) text_out16(10, 100, "failed to open required file:"); text_out16(10, 110, CODE940_FILE); gp2x_video_flip2(); + in_menu_wait(PBTN_MOK|PBTN_MBACK, 100); printf("failed to open %s\n", binpath); exit(1); } diff --git a/gp2x/emu.c b/gp2x/emu.c index 64b439c..d83cd56 100644 --- a/gp2x/emu.c +++ b/gp2x/emu.c @@ -37,12 +37,12 @@ extern int crashed_940; static short __attribute__((aligned(4))) sndBuffer[2*44100/50]; static struct timeval noticeMsgTime = { 0, 0 }; // when started showing -static int osd_fps_x; -static int gp2x_old_gamma = 100; static char noticeMsg[40]; static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)]; unsigned char *PicoDraw2FB = PicoDraw2FB_; +static int osd_fps_x; +extern void *gp2x_screens[4]; void plat_status_msg(const char *format, ...) { @@ -92,7 +92,7 @@ void pemu_prep_defconfig(void) gp2x_soc_t soc; memset(&defaultConfig, 0, sizeof(defaultConfig)); - defaultConfig.EmuOpt = 0x9d | EOPT_RAM_TIMINGS | 0x600; // | <- confirm_save, cd_leds + defaultConfig.EmuOpt = 0x9d | EOPT_RAM_TIMINGS|EOPT_CONFIRM_SAVE|EOPT_EN_CD_LEDS; defaultConfig.s_PicoOpt = 0x0f | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_SVP_DRC|POPT_ACC_SPRITES; defaultConfig.s_PsndRate = 44100; defaultConfig.s_PicoRegion = 0; // auto @@ -108,77 +108,129 @@ void pemu_prep_defconfig(void) soc = soc_detect(); if (soc == SOCID_MMSP2) defaultConfig.s_PicoOpt |= POPT_EXT_FM; + else if (soc == SOCID_POLLUX) + defaultConfig.EmuOpt |= EOPT_WIZ_TEAR_FIX; } -static void osd_text(int x, int y, const char *text) +static void (*osd_text)(int x, int y, const char *text); + +static void osd_text8(int x, int y, const char *text) { int len = strlen(text)*8; int *p, i, h, offs; - if ((PicoOpt&0x10)||!(currentConfig.EmuOpt&0x80)) { - len = (len+3) >> 2; - for (h = 0; h < 8; h++) { - offs = (x + g_screen_width * (y+h)) & ~3; - p = (int *) ((char *)g_screen_ptr + offs); - for (i = len; i; i--, p++) - *p = 0xe0e0e0e0; - } - emu_textOut8(x, y, text); - } else { - len = (len+1) >> 1; - for (h = 0; h < 8; h++) { - offs = (x + g_screen_width * (y+h)) & ~1; - p = (int *) ((short *)g_screen_ptr + offs); - for (i = len; i; i--, p++) - *p = (*p >> 2) & 0x39e7; - } - emu_textOut16(x, y, text); + len = (len+3) >> 2; + for (h = 0; h < 8; h++) { + offs = (x + g_screen_width * (y+h)) & ~3; + p = (int *) ((char *)g_screen_ptr + offs); + for (i = len; i; i--, p++) + *p = 0xe0e0e0e0; + } + emu_text_out8(x, y, text); +} + +static void osd_text16(int x, int y, const char *text) +{ + int len = strlen(text)*8; + int *p, i, h, offs; + + len = (len+1) >> 1; + for (h = 0; h < 8; h++) { + offs = (x + g_screen_width * (y+h)) & ~1; + p = (int *) ((short *)g_screen_ptr + offs); + for (i = len; i; i--, p++) + *p = (*p >> 2) & 0x39e7; + } + emu_text_out16(x, y, text); +} + +static void osd_text8_rot(int x, int y, const char *text) +{ + int len = strlen(text) * 8; + char *p = (char *)g_screen_ptr + 240*(320-x) + y; + + while (len--) { + memset(p, 0xe0, 8); + p -= 240; } + + emu_text_out8_rot(x, y, text); +} + +static void osd_text16_rot(int x, int y, const char *text) +{ + int len = strlen(text) * 8; + short *p = (short *)g_screen_ptr + 240*(320-x) + y; + + while (len--) { + memset(p, 0, 8*2); + p -= 240; + } + + emu_text_out16_rot(x, y, text); } static void draw_cd_leds(void) { - int old_reg; - old_reg = Pico_mcd->s68k_regs[0]; + int led_reg, pitch, scr_offs, led_offs; + led_reg = Pico_mcd->s68k_regs[0]; + + if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { + pitch = 240; + led_offs = -pitch * 6; + scr_offs = pitch * (320 - 4); + } else { + pitch = 320; + led_offs = 4; + scr_offs = pitch * 2 + 4; + } if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) { + #define p(x) px[(x) >> 2] // 8-bit modes - unsigned int col_g = (old_reg & 2) ? 0xc0c0c0c0 : 0xe0e0e0e0; - unsigned int col_r = (old_reg & 1) ? 0xd0d0d0d0 : 0xe0e0e0e0; - *(unsigned int *)((char *)g_screen_ptr + 320*2+ 4) = - *(unsigned int *)((char *)g_screen_ptr + 320*3+ 4) = - *(unsigned int *)((char *)g_screen_ptr + 320*4+ 4) = col_g; - *(unsigned int *)((char *)g_screen_ptr + 320*2+12) = - *(unsigned int *)((char *)g_screen_ptr + 320*3+12) = - *(unsigned int *)((char *)g_screen_ptr + 320*4+12) = col_r; + unsigned int *px = (unsigned int *)((char *)g_screen_ptr + scr_offs); + unsigned int col_g = (led_reg & 2) ? 0xc0c0c0c0 : 0xe0e0e0e0; + unsigned int col_r = (led_reg & 1) ? 0xd0d0d0d0 : 0xe0e0e0e0; + p(pitch*0) = p(pitch*1) = p(pitch*2) = col_g; + p(pitch*0 + led_offs) = p(pitch*1 + led_offs) = p(pitch*2 + led_offs) = col_r; + #undef p } else { + #define p(x) px[(x)*2 >> 2] = px[((x)*2 >> 2) + 1] // 16-bit modes - unsigned int *p = (unsigned int *)((short *)g_screen_ptr + 320*2+4); - unsigned int col_g = (old_reg & 2) ? 0x06000600 : 0; - unsigned int col_r = (old_reg & 1) ? 0xc000c000 : 0; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 320/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 320/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; + unsigned int *px = (unsigned int *)((short *)g_screen_ptr + scr_offs); + unsigned int col_g = (led_reg & 2) ? 0x06000600 : 0; + unsigned int col_r = (led_reg & 1) ? 0xc000c000 : 0; + p(pitch*0) = p(pitch*1) = p(pitch*2) = col_g; + p(pitch*0 + led_offs) = p(pitch*1 + led_offs) = p(pitch*2 + led_offs) = col_r; + #undef p } } static void draw_pico_ptr(void) { unsigned short *p = (unsigned short *)g_screen_ptr; + int x, y, pitch = 320; // only if pen enabled and for 16bit modes - if (pico_inp_mode == 0 || (PicoOpt&0x10) || !(currentConfig.EmuOpt&0x80)) return; + if (pico_inp_mode == 0 || (PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) + return; - if (!(Pico.video.reg[12]&1) && !(PicoOpt&POPT_DIS_32C_BORDER)) - p += 32; + x = pico_pen_x + PICO_PEN_ADJUST_X; + y = pico_pen_y + PICO_PEN_ADJUST_Y; + if (!(Pico.video.reg[12]&1) && !(PicoOpt & POPT_DIS_32C_BORDER)) + x += 32; - p += 320 * (pico_pen_y + PICO_PEN_ADJUST_Y); - p += pico_pen_x + PICO_PEN_ADJUST_X; - p[0] ^= 0xffff; - p[319] ^= 0xffff; - p[320] ^= 0xffff; - p[321] ^= 0xffff; - p[640] ^= 0xffff; + if (EOPT_WIZ_TEAR_FIX) { + pitch = 240; + p += (319 - x) * pitch + y; + } else + p += x + y * pitch; + + p[0] ^= 0xffff; + p[pitch-1] ^= 0xffff; + p[pitch] ^= 0xffff; + p[pitch+1] ^= 0xffff; + p[pitch*2] ^= 0xffff; } static int EmuScanBegin16(unsigned int num) @@ -197,8 +249,45 @@ static int EmuScanBegin8(unsigned int num) return 0; } +/* rot thing for Wiz */ +static unsigned char __attribute__((aligned(4))) rot_buff[320*4*2]; + +static int EmuScanBegin16_rot(unsigned int num) +{ + DrawLineDest = rot_buff + (num & 3) * 320 * 2; + return 0; +} + +static int EmuScanEnd16_rot(unsigned int num) +{ + if ((num & 3) != 3) + return 0; + if (!(Pico.video.reg[1] & 8)) + num += 8; + rotated_blit16(g_screen_ptr, rot_buff, num + 1, + !(Pico.video.reg[12] & 1) && !(PicoOpt & POPT_EN_SOFTSCALE)); + return 0; +} + +static int EmuScanBegin8_rot(unsigned int num) +{ + DrawLineDest = rot_buff + (num & 3) * 320; + return 0; +} + +static int EmuScanEnd8_rot(unsigned int num) +{ + if ((num & 3) != 3) + return 0; + if (!(Pico.video.reg[1] & 8)) + num += 8; + rotated_blit8(g_screen_ptr, rot_buff, num + 1, + !(Pico.video.reg[12] & 1)); + return 0; +} + int localPal[0x100]; -static void (*vidCpyM2)(void *dest, void *src) = NULL; +static void (*vidcpyM2)(void *dest, void *src, int m32col, int with_32c_border) = NULL; static void blit(const char *fps, const char *notice) { @@ -217,7 +306,8 @@ static void blit(const char *fps, const char *notice) if (PicoRead16Hook == PicoSVPRead16) memset32((int *)(PicoDraw2FB+328*8+328*223), 0xe0e0e0e0, 328); // do actual copy - vidCpyM2((unsigned char *)g_screen_ptr+320*8, PicoDraw2FB+328*8); + vidcpyM2(g_screen_ptr, PicoDraw2FB+328*8, + !(Pico.video.reg[12] & 1), !(PicoOpt & POPT_DIS_32C_BORDER)); } else if (!(emu_opt & EOPT_16BPP)) { @@ -268,23 +358,32 @@ static void blit(const char *fps, const char *notice) draw_pico_ptr(); gp2x_video_flip(); - - if (!(PicoOpt & POPT_ALT_RENDERER)) { - if (!(Pico.video.reg[1]&8)) { - if (currentConfig.EmuOpt & EOPT_16BPP) - DrawLineDest = (unsigned short *) g_screen_ptr + 320*8; - else - DrawLineDest = (unsigned char *) g_screen_ptr + 320*8; - } else { - DrawLineDest = g_screen_ptr; - } - } } // clears whole screen or just the notice area (in all buffers) static void clearArea(int full) { - if ((PicoOpt&0x10)||!(currentConfig.EmuOpt&0x80)) { + int is_8bit = (PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP); + if (!full && (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)) { + /* ugh.. */ + int i, u, *p; + if (is_8bit) { + for (i = 0; i < 4; i++) { + p = (int *)gp2x_screens[i] + (240-8) / 4; + for (u = 320; u > 0; u--, p += 240/4) + p[0] = p[1] = 0xe0e0e0e0; + } + } else { + for (i = 0; i < 4; i++) { + p = (int *)gp2x_screens[i] + (240-8)*2 / 4; + for (u = 320; u > 0; u--, p += 240*2/4) + p[0] = p[1] = p[2] = p[3] = 0; + } + } + return; + } + + if (is_8bit) { // 8-bit renderers if (full) gp2x_memset_all_buffers(0, 0xe0, 320*240); else gp2x_memset_all_buffers(320*232, 0xe0, 320*8); @@ -313,17 +412,46 @@ void plat_status_msg_busy_first(const char *msg) static void vidResetMode(void) { + PicoScanEnd = NULL; + if (PicoOpt & POPT_ALT_RENDERER) { - gp2x_video_changemode(8); - } else if (currentConfig.EmuOpt & EOPT_16BPP) { - gp2x_video_changemode(16); + if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { + gp2x_video_changemode(-8); + vidcpyM2 = vidcpy_m2_rot; + osd_text = osd_text8_rot; + } else { + gp2x_video_changemode(8); + vidcpyM2 = vidcpy_m2; + osd_text = osd_text8; + } + } + else if (currentConfig.EmuOpt & EOPT_16BPP) { PicoDrawSetColorFormat(1); - PicoScanBegin = EmuScanBegin16; - } else { - gp2x_video_changemode(8); + if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { + gp2x_video_changemode(-16); + PicoScanBegin = EmuScanBegin16_rot; + PicoScanEnd = EmuScanEnd16_rot; + osd_text = osd_text16_rot; + } else { + gp2x_video_changemode(16); + PicoScanBegin = EmuScanBegin16; + osd_text = osd_text16; + } + } + else { PicoDrawSetColorFormat(2); - PicoScanBegin = EmuScanBegin8; + if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { + gp2x_video_changemode(-8); + PicoScanBegin = EmuScanBegin8_rot; + PicoScanEnd = EmuScanEnd8_rot; + osd_text = osd_text8_rot; + } else { + gp2x_video_changemode(8); + PicoScanBegin = EmuScanBegin8; + osd_text = osd_text8; + } } + if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) { // setup pal for 8-bit modes localPal[0xc0] = 0x0000c000; // MCD LEDs @@ -335,6 +463,7 @@ static void vidResetMode(void) gp2x_video_flip(); } Pico.m.dirtyPal = 1; + // reset scaling if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(Pico.video.reg[1]&8)) gp2x_video_RGB_setscaling(8, (PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 224); @@ -516,19 +645,10 @@ void pemu_forced_frame(int opts) PicoDrawSetColorFormat(1); PicoScanBegin = EmuScanBegin16; + PicoScanEnd = NULL; Pico.m.dirtyPal = 1; PicoFrameDrawOnly(); -/* - if (!(Pico.video.reg[12]&1)) { - vidCpyM2 = vidCpyM2_32col; - clearArea(1); - } else vidCpyM2 = vidCpyM2_40col; - - vidCpyM2((unsigned char *)g_screen_ptr+320*8, PicoDraw2FB+328*8); - vidConvCpyRGB32(localPal, Pico.cram, 0x40); - gp2x_video_setpalette(localPal, 0x40); -*/ PicoOpt = po_old; currentConfig.EmuOpt = eo_old; } @@ -605,7 +725,8 @@ static void tga_dump(void) void pemu_loop(void) { - static int gp2x_old_clock = -1, EmuOpt_old = 0; + static int gp2x_old_clock = -1, EmuOpt_old = 0, pal_old = 0; + static int gp2x_old_gamma = 100; char fpsbuff[24]; // fps count c string struct timeval tval; // timing int pframes_done, pframes_shown, pthissec; // "period" frames, used for sync @@ -637,7 +758,7 @@ void pemu_loop(void) printf("updated gamma to %i, A_SN's curve: %i\n", currentConfig.gamma, !!(currentConfig.EmuOpt&0x1000)); } - if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_PSYNC) { + if (((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_PSYNC) || Pico.m.pal != pal_old) { if (currentConfig.EmuOpt & EOPT_PSYNC) set_lcd_custom_rate(Pico.m.pal); else @@ -648,6 +769,7 @@ void pemu_loop(void) gp2x_make_fb_bufferable(currentConfig.EmuOpt & EOPT_MMUHACK); EmuOpt_old = currentConfig.EmuOpt; + pal_old = Pico.m.pal; fpsbuff[0] = 0; // make sure we are in correct mode @@ -667,7 +789,7 @@ void pemu_loop(void) if (PicoAHW & PAHW_MCD) PicoCDBufferInit(); // calc vsync offset to sync timing code with vsync - if (currentConfig.EmuOpt&0x2000) { + if (currentConfig.EmuOpt & EOPT_PSYNC) { gettimeofday(&tval, 0); gp2x_video_wait_vsync(); gettimeofday(&tval, 0); @@ -715,16 +837,9 @@ void pemu_loop(void) { int scalex = 320; osd_fps_x = OSD_FPS_X; - if (modes & 4) { - vidCpyM2 = vidCpyM2_40col; - } else { - if (PicoOpt & 0x100) { - vidCpyM2 = vidCpyM2_32col_nobord; - scalex = 256; - osd_fps_x = OSD_FPS_X - 64; - } else { - vidCpyM2 = vidCpyM2_32col; - } + if (!(modes & 4) && (PicoOpt & POPT_DIS_32C_BORDER)) { + scalex = 256; + osd_fps_x = OSD_FPS_X - 64; } /* want vertical scaling and game is not in 240 line mode */ if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(modes&8)) @@ -853,9 +968,8 @@ void pemu_loop(void) SRam.changed = 0; } - // if in 8bit mode, generate 16bit image for menu background - if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) - pemu_forced_frame(POPT_EN_SOFTSCALE); + // do menu background to be sure it's right + pemu_forced_frame(POPT_EN_SOFTSCALE); } const char *plat_get_credits(void) diff --git a/gp2x/in_gp2x.c b/gp2x/in_gp2x.c index 51c9bf5..273c03b 100644 --- a/gp2x/in_gp2x.c +++ b/gp2x/in_gp2x.c @@ -258,7 +258,7 @@ static const struct { { BTN_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */ { BTN_START, IN_BINDTYPE_PLAYER12, 7 }, { BTN_SELECT, IN_BINDTYPE_EMU, PEVB_MENU }, - { BTN_Y, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, +// { BTN_Y, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, { BTN_L, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, { BTN_R, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, { BTN_VOL_UP, IN_BINDTYPE_EMU, PEVB_VOL_UP }, diff --git a/gp2x/plat.c b/gp2x/plat.c index 8b9e0ae..aa60412 100644 --- a/gp2x/plat.c +++ b/gp2x/plat.c @@ -86,13 +86,20 @@ void plat_video_menu_enter(int is_rom_loaded) memset(g_screen_ptr, 0, 320*240*2); } - // copy to buffer2 + // copy to buffer2, switch to black gp2x_memcpy_buffers((1<<2), g_screen_ptr, 0, 320*240*2); + /* try to switch nicely avoiding tearing on Wiz */ + gp2x_video_wait_vsync(); + memset(gp2x_screens[0], 0, 320*240*2); + memset(gp2x_screens[1], 0, 320*240*2); + gp2x_video_flip2(); + gp2x_video_wait_vsync(); + gp2x_video_wait_vsync(); + // switch to 16bpp gp2x_video_changemode_ll(16); gp2x_video_RGB_setscaling(0, 320, 240); - gp2x_video_flip2(); } void plat_video_menu_begin(void) @@ -114,6 +121,8 @@ void plat_validate_config(void) soc = soc_detect(); if (soc != SOCID_MMSP2) PicoOpt &= ~POPT_EXT_FM; + if (soc != SOCID_POLLUX) + currentConfig.EmuOpt &= ~EOPT_WIZ_TEAR_FIX; if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100; diff --git a/gp2x/soc.h b/gp2x/soc.h index 35fe804..46667e8 100644 --- a/gp2x/soc.h +++ b/gp2x/soc.h @@ -14,6 +14,7 @@ void pollux_finish(void); /* SoC specific functions */ extern void (*gp2x_video_flip)(void); extern void (*gp2x_video_flip2)(void); +/* negative bpp means rotated mode (for Wiz) */ extern void (*gp2x_video_changemode_ll)(int bpp); extern void (*gp2x_video_setpalette)(int *pal, int len); extern void (*gp2x_video_RGB_setscaling)(int ln_offs, int W, int H); diff --git a/gp2x/soc_pollux.c b/gp2x/soc_pollux.c index 6bea317..64971a2 100644 --- a/gp2x/soc_pollux.c +++ b/gp2x/soc_pollux.c @@ -30,6 +30,7 @@ static int fbdev = -1; static char cpuclk_was_changed = 0; static unsigned short memtimex_old[2]; static unsigned int pllsetreg0; +static int last_pal_setting = 0; /* video stuff */ @@ -56,9 +57,30 @@ static void gp2x_video_flip2_(void) static void gp2x_video_changemode_ll_(int bpp) { + static int prev_bpp = 0; int code = 0, bytes = 2; + int rot_cmd[2] = { 0, 0 }; unsigned int r; - switch (bpp) + int ret; + + if (bpp == prev_bpp) + return; + prev_bpp = bpp; + + printf("changemode: %dbpp rot=%d\n", abs(bpp), bpp < 0); + + /* negative bpp means rotated mode */ + rot_cmd[0] = (bpp < 0) ? 6 : 5; + ret = ioctl(fbdev, _IOW('D', 90, int[2]), rot_cmd); + if (ret < 0) + perror("rot ioctl failed"); + memregl[0x4004>>2] = (bpp < 0) ? 0x013f00ef : 0x00ef013f; + memregl[0x4000>>2] |= 1 << 3; + + /* the above ioctl resets LCD timings, so set them here */ + set_lcd_custom_rate(last_pal_setting); + + switch (abs(bpp)) { case 8: code = 0x443a; @@ -72,12 +94,12 @@ static void gp2x_video_changemode_ll_(int bpp) break; default: - printf("unhandled bpp request: %d\n", bpp); + printf("unhandled bpp request: %d\n", abs(bpp)); return; } memregl[0x405c>>2] = bytes; - memregl[0x4060>>2] = bytes * 320; + memregl[0x4060>>2] = bytes * (bpp < 0 ? 240 : 320); r = memregl[0x4058>>2]; r = (r & 0xffff) | (code << 16) | 0x10; @@ -156,6 +178,7 @@ static void set_lcd_custom_rate_(int is_pal) snprintf(buff, sizeof(buff), "POLLUX_LCD_TIMINGS_%s", is_pal ? "PAL" : "NTSC"); pollux_set_fromenv(buff); + last_pal_setting = is_pal; } static void unset_lcd_custom_rate_(void) @@ -245,7 +268,6 @@ void pollux_finish(void) /* switch to default fb mem, turn portrait off */ memregl[0x406C>>2] = fb_paddr[0]; memregl[0x4058>>2] |= 0x10; -// wiz_lcd_set_portrait(0); close(fbdev); gp2x_video_changemode_ll_(16); diff --git a/gp2x/version.h b/gp2x/version.h index fd2082f..c3189c5 100644 --- a/gp2x/version.h +++ b/gp2x/version.h @@ -1,2 +1,2 @@ -#define VERSION "1.52" +#define VERSION "1.55" diff --git a/pandora/emu.c b/pandora/emu.c index 0425075..d409b57 100644 --- a/pandora/emu.c +++ b/pandora/emu.c @@ -134,7 +134,7 @@ static void osd_text(int x, int y, const char *text) p = (int *) ((unsigned char *) g_screen_ptr+x+g_screen_width*(y+h)); for (i = len; i; i--, p++) *p = 0xe0e0e0e0; } - emu_textOut8(x, y, text); + emu_text_out8(x, y, text); } else { int *p, i, h; x &= ~1; // align x @@ -143,7 +143,7 @@ static void osd_text(int x, int y, const char *text) p = (int *) ((unsigned short *) g_screen_ptr+x+g_screen_width*(y+h)); for (i = len; i; i--, p++) *p = 0;//(*p>>2)&0x39e7; } - textOut16(x, y, text); + text_out16(x, y, text); } } diff --git a/psp/emu.c b/psp/emu.c index 21abfca..929c608 100644 --- a/psp/emu.c +++ b/psp/emu.c @@ -76,7 +76,7 @@ static void osd_text(int x, const char *text, int is_active, int clear_all) memset32_uncached(p, 0, len); } if (is_active) { tmp = psp_screen; psp_screen = screen; } // nasty pointer tricks - emu_textOut16(x, 264, text); + emu_text_out16(x, 264, text); if (is_active) psp_screen = tmp; } @@ -409,7 +409,7 @@ static void dbg_text(void) p = (int *) ((int)p & ~3); // align memset32_uncached(p, 0, len); } - emu_textOut16(2, 256, text); + emu_text_out16(2, 256, text); } #endif