From: kub Date: Fri, 22 Mar 2019 22:03:26 +0000 (+0100) Subject: reworked palette and buffer handling due to some 32X bugs X-Git-Tag: v2.00~876 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b1a047c9267065bb85095761a3192ce2874d7383;p=picodrive.git reworked palette and buffer handling due to some 32X bugs --- diff --git a/pico/32x/draw.c b/pico/32x/draw.c index 2287e246..4bdbc89a 100644 --- a/pico/32x/draw.c +++ b/pico/32x/draw.c @@ -11,6 +11,9 @@ int (*PicoScan32xBegin)(unsigned int num); int (*PicoScan32xEnd)(unsigned int num); int Pico32xDrawMode; +void *DrawLineDestBase32x; +int DrawLineDestIncrement32x; + static void convert_pal555(int invert_prio) { unsigned int *ps = (void *)Pico32xMem->pal; @@ -228,13 +231,11 @@ void PicoDraw32xLayer(int offs, int lines, int md_bg) int lines_sft_offs; int which_func; - Pico.est.DrawLineDest = (char *)DrawLineDestBase + offs * DrawLineDestIncrement; + Pico.est.DrawLineDest = (char *)DrawLineDestBase32x + offs * DrawLineDestIncrement32x; dram = Pico32xMem->dram[Pico32x.vdp_regs[0x0a/2] & P32XV_FS]; - if (Pico32xDrawMode == PDM32X_BOTH) { - if (Pico.m.dirtyPal) - PicoDrawUpdateHighPal(); - } + if (Pico32xDrawMode == PDM32X_BOTH) + PicoDrawUpdateHighPal(); if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 2) { @@ -273,20 +274,21 @@ do_it: void PicoDraw32xLayerMdOnly(int offs, int lines) { int have_scan = PicoScan32xBegin != NULL && PicoScan32xEnd != NULL; - unsigned short *dst = (void *)((char *)DrawLineDestBase + offs * DrawLineDestIncrement); + unsigned short *dst = (void *)((char *)DrawLineDestBase32x + offs * DrawLineDestIncrement32x); unsigned char *pmd = Pico.est.Draw2FB + 328 * offs + 8; unsigned short *pal = Pico.est.HighPal; int poffs = 0, plen = 320; int l, p; if (!(Pico.video.reg[12] & 1)) { - // 32col mode + // 32col mode. for some render modes MD pixel data carries an offset + if (!(PicoIn.opt & (POPT_ALT_RENDERER|POPT_DIS_32C_BORDER))) + pmd += 32; poffs = 32; plen = 256; } - if (Pico.m.dirtyPal) - PicoDrawUpdateHighPal(); + PicoDrawUpdateHighPal(); dst += poffs; for (l = 0; l < lines; l++) { @@ -300,7 +302,7 @@ void PicoDraw32xLayerMdOnly(int offs, int lines) dst[p + 2] = pal[*pmd++]; dst[p + 3] = pal[*pmd++]; } - dst = (void *)((char *)dst + DrawLineDestIncrement); + dst = (void *)((char *)dst + DrawLineDestIncrement32x); pmd += 328 - plen; if (have_scan) PicoScan32xEnd(l + offs); @@ -314,16 +316,32 @@ void PicoDrawSetOutFormat32x(pdso_t which, int use_32x_line_mode) Pico32xNativePal = Pico32xMem->pal_native; #endif - if (which == PDF_RGB555 && use_32x_line_mode) { - // we'll draw via FinalizeLine32xRGB555 (rare) + if (which == PDF_RGB555) { + // need CLUT pixels in PicoDraw2FB for layer transparency + PicoDrawSetInternalBuf(Pico.est.Draw2FB, 328); + PicoDrawSetOutBufMD(DrawLineDestBase32x, DrawLineDestIncrement32x); + } else { + // use the same layout as alt renderer PicoDrawSetInternalBuf(NULL, 0); - Pico32xDrawMode = PDM32X_OFF; - return; + PicoDrawSetOutBufMD(Pico.est.Draw2FB + 8, 328); } - // use the same layout as alt renderer - PicoDrawSetInternalBuf(Pico.est.Draw2FB, 328); - Pico32xDrawMode = (which == PDF_RGB555) ? PDM32X_32X_ONLY : PDM32X_BOTH; + if (use_32x_line_mode) + // we'll draw via FinalizeLine32xRGB555 (rare) + Pico32xDrawMode = PDM32X_OFF; + else + // in RGB555 mode the 32x layer is drawn over the MD layer, in the other + // modes 32x and MD layer are merged together by the 32x renderer + Pico32xDrawMode = (which == PDF_RGB555) ? PDM32X_32X_ONLY : PDM32X_BOTH; +} + +void PicoDrawSetOutBuf32X(void *dest, int increment) +{ + DrawLineDestBase32x = dest; + DrawLineDestIncrement32x = increment; + // in RGB555 mode this buffer is also used by the MD renderer + if (Pico32xDrawMode != PDM32X_BOTH) + PicoDrawSetOutBufMD(DrawLineDestBase32x, DrawLineDestIncrement32x); } // vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/draw.c b/pico/draw.c index 680de3da..e345a28d 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1239,6 +1239,49 @@ void BackFill(int reg7, int sh, struct PicoEState *est) // -------------------------------------------- +void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est) +{ + unsigned int *spal, *dpal; + unsigned int cnt = (sh ? 1 : est->SonicPalCount+1); + unsigned int t, i; + + // reset dirty only if there are no outstanding changes + if (Pico.m.dirtyPal == 2) + Pico.m.dirtyPal = 0; + + // In Sonic render mode palettes were backuped in SonicPal + spal = (void *)est->SonicPal; + dpal = (void *)est->HighPal; + + // additional palettes stored after in-frame changes + for (i = 0; i < cnt * 0x40 / 2; i++) { + t = spal[i]; +#ifdef USE_BGR555 + t = ((t & 0x000e000e)<< 1) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)<<4); +#else + t = ((t & 0x000e000e)<<12) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)>>7); +#endif + // treat it like it was 4-bit per channel, since in s/h mode it somewhat is that. + // otherwise intensity difference between this and s/h will be wrong + t |= (t >> 4) & 0x08610861; // 0x18e318e3 + dpal[i] = t; + } + + // norm: xxx0, sh: 0xxx, hi: 0xxx + 7 + if (sh) + { + // shadowed pixels + for (i = 0; i < 0x40 / 2; i++) + dpal[0x40/2 | i] = dpal[0xc0/2 | i] = (dpal[i] >> 1) & 0x738e738e; + // hilighted pixels + for (i = 0; i < 0x40 / 2; i++) { + t = ((dpal[i] >> 1) & 0x738e738e) + 0x738e738e; // 0x7bef7bef; + t |= (t >> 4) & 0x08610861; + dpal[0x80/2 | i] = t; + } + } +} + #ifndef _ASM_DRAW_C void PicoDoHighPal555(int sh, int line, struct PicoEState *est) { @@ -1285,8 +1328,7 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) unsigned short *pal=est->HighPal; int len; - if (Pico.m.dirtyPal) - PicoDoHighPal555(sh, line, est); + PicoDrawUpdateHighPal(); if (Pico.video.reg[12]&1) { len = 320; @@ -1315,22 +1357,21 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) static void FinalizeLine8bit(int sh, int line, struct PicoEState *est) { unsigned char *pd = est->DrawLineDest; - int len, rs = est->rendstatus; - static int dirty_count; + int len; + static int dirty_line; - if (!sh && Pico.m.dirtyPal == 1) + if (Pico.m.dirtyPal == 1) { // a hack for mid-frame palette changes - if (!(rs & PDRAW_SONIC_MODE)) - dirty_count = 1; - else dirty_count++; - rs |= PDRAW_SONIC_MODE; - est->rendstatus = rs; - if (dirty_count == 3) { - blockcpy(est->HighPal, PicoMem.cram, 0x40*2); - } else if (dirty_count == 11) { - blockcpy(est->HighPal+0x40, PicoMem.cram, 0x40*2); + if (!(est->rendstatus & PDRAW_SONIC_MODE) || line - dirty_line > 4) { + // store a maximum of 3 additional palettes in SonicPal + if (est->SonicPalCount < 3) + est->SonicPalCount ++; + dirty_line = line; + est->rendstatus |= PDRAW_SONIC_MODE; } + blockcpy(est->SonicPal+est->SonicPalCount*0x40, PicoMem.cram, 0x40*2); + Pico.m.dirtyPal = 2; } if (Pico.video.reg[12]&1) { @@ -1341,12 +1382,9 @@ static void FinalizeLine8bit(int sh, int line, struct PicoEState *est) len = 256; } - if (!sh && (rs & PDRAW_SONIC_MODE)) { - if (dirty_count >= 11) { - blockcpy_or(pd, est->HighCol+8, len, 0x80); - } else { - blockcpy_or(pd, est->HighCol+8, len, 0x40); - } + if (!sh && (est->rendstatus & PDRAW_SONIC_MODE)) { + // select active backup palette + blockcpy_or(pd, est->HighCol+8, len, est->SonicPalCount*0x40); } else { blockcpy(pd, est->HighCol+8, len); } @@ -1478,6 +1516,7 @@ static int DrawDisplay(int sh) PICO_INTERNAL void PicoFrameStart(void) { int offs = 8, lines = 224; + int dirty = ((Pico.est.rendstatus & PDRAW_SONIC_MODE) || Pico.m.dirtyPal); // prepare to do this frame Pico.est.rendstatus = 0; @@ -1503,11 +1542,16 @@ PICO_INTERNAL void PicoFrameStart(void) Pico.est.DrawScanline = 0; skip_next_line = 0; + if (FinalizeLine == FinalizeLine8bit) { + // make a backup of the current palette in case Sonic mode is detected later + Pico.est.SonicPalCount = 0; + Pico.m.dirtyPal = (dirty ? 2 : 0); // mark as dirty but already copied + blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2); + } + if (PicoIn.opt & POPT_ALT_RENDERER) return; - if (Pico.m.dirtyPal) - Pico.m.dirtyPal = 2; // reset dirty if needed PrepareSprites(1); } @@ -1598,15 +1642,21 @@ void PicoDrawSync(int to, int blank_last_line) void PicoDrawUpdateHighPal(void) { struct PicoEState *est = &Pico.est; - int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight? - if (PicoIn.opt & POPT_ALT_RENDERER) - sh = 0; // no s/h support + if (Pico.m.dirtyPal) { + int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight? + if ((PicoIn.opt & POPT_ALT_RENDERER) | (est->rendstatus & PDRAW_SONIC_MODE)) + sh = 0; // no s/h support + + if (FinalizeLine == FinalizeLine8bit) + PicoDoHighPal555_8bit(sh, 0, est); + else + PicoDoHighPal555(sh, 0, est); - PicoDoHighPal555(sh, 0, &Pico.est); - if (est->rendstatus & PDRAW_SONIC_MODE) { - // FIXME? - memcpy(est->HighPal + 0x40, est->HighPal, 0x40*2); - memcpy(est->HighPal + 0x80, est->HighPal, 0x40*2); + // cover for sprite priority bits if not in s/h or sonic mode + if (!sh && !(est->rendstatus & PDRAW_SONIC_MODE)) { + blockcpy(est->HighPal+0x40, est->HighPal, 0x40*2); + blockcpy(est->HighPal+0x80, est->HighPal, 0x80*2); + } } } @@ -1629,17 +1679,33 @@ void PicoDrawSetOutFormat(pdso_t which, int use_32x_line_mode) FinalizeLine = NULL; break; } - PicoDrawSetOutFormat32x(which, use_32x_line_mode); + if (PicoIn.AHW & PAHW_32X) + PicoDrawSetOutFormat32x(which, use_32x_line_mode); PicoDrawSetOutputMode4(which); rendstatus_old = -1; } +void PicoDrawSetOutBufMD(void *dest, int increment) +{ + if (dest != NULL) { + DrawLineDestBase = dest; + DrawLineDestIncrement = increment; + Pico.est.DrawLineDest = DrawLineDestBase + Pico.est.DrawScanline * increment; + } + else { + DrawLineDestBase = DefOutBuff; + DrawLineDestIncrement = 0; + Pico.est.DrawLineDest = DefOutBuff; + } +} + // note: may be called on the middle of frame void PicoDrawSetOutBuf(void *dest, int increment) { - DrawLineDestBase = dest; - DrawLineDestIncrement = increment; - Pico.est.DrawLineDest = (char *)DrawLineDestBase + Pico.est.DrawScanline * increment; + if (PicoIn.AHW & PAHW_32X) + PicoDrawSetOutBuf32X(dest, increment); + else + PicoDrawSetOutBufMD(dest, increment); } void PicoDrawSetInternalBuf(void *dest, int increment) @@ -1652,6 +1718,7 @@ void PicoDrawSetInternalBuf(void *dest, int increment) else { HighColBase = DefHighCol; HighColIncrement = 0; + Pico.est.HighCol = DefHighCol; } } diff --git a/pico/draw_arm.S b/pico/draw_arm.S index 29af1c13..3bc27033 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -1498,11 +1498,9 @@ vidConvCpyRGB565: @ void *to, void *from, int pixels PicoDoHighPal555: stmfd sp!, {r4-r10,lr} mov r10,r2 @ est - mov r1, #0 ldr r8, [r10, #OFS_EST_Pico] -PicoDoHighPal555_nopush: - orr r9, r1, r0, lsl #31 @ 0:called from FinalizeLine555, 31: s/h + mov r9, r0 add r0, r10, #OFS_EST_HighPal @@ -1517,7 +1515,7 @@ PicoDoHighPal555_nopush: vidConvCpyRGB565_local - tst r9, #(1<<31) + cmp r9, #0 beq PicoDoHighPal555_end add r3, r10, #OFS_EST_HighPal @@ -1560,11 +1558,7 @@ PicoDoHighPal555_nopush: mov r0, #1 PicoDoHighPal555_end: - tst r9, #1 - ldmeqfd sp!, {r4-r10,pc} - - ldr r8, [r10, #OFS_EST_Pico] - b FinalizeLineRGB555_pal_done + ldmfd sp!, {r4-r10,pc} @ void FinalizeLine555(int sh, int line, struct PicoEState *est) @@ -1576,19 +1570,11 @@ FinalizeLine555: mov r10,r2 @ est ldr r8, [r10, #OFS_EST_Pico] - ldrb r2, [r8, #OFS_Pico_m_dirtyPal] - mov r1, #1 - tst r2, r2 - bne PicoDoHighPal555_nopush + bl PicoDrawUpdateHighPal -FinalizeLineRGB555_pal_done: add r3, r10, #OFS_EST_HighPal - ldr r12, [r10, #OFS_EST_rendstatus] - eors r0, r0, #1 @ sh is 0 mov lr, #0xff - tstne r12,#PDRAW_ACC_SPRITES - movne lr, #0x3f ldr r1, [r10, #OFS_EST_HighCol] ldr r0, [r10, #OFS_EST_DrawLineDest] diff --git a/pico/pico_int.h b/pico/pico_int.h index cca7f954..f6d8b37f 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -356,6 +356,8 @@ struct PicoEState unsigned int *PicoOpt; unsigned char *Draw2FB; unsigned short HighPal[0x100]; + unsigned short SonicPal[0x100]; + int SonicPalCount; }; struct PicoMem @@ -923,6 +925,7 @@ void p32x_sh2_poll_event(SH2 *sh2, unsigned int flags, unsigned int m68k_cycles) // 32x/draw.c void PicoDrawSetOutFormat32x(pdso_t which, int use_32x_line_mode); +void PicoDrawSetOutBuf32X(void *dest, int increment); void FinalizeLine32xRGB555(int sh, int line, struct PicoEState *est); void PicoDraw32xLayer(int offs, int lines, int mdbg); void PicoDraw32xLayerMdOnly(int offs, int lines); diff --git a/pico/videoport.c b/pico/videoport.c index cd76dc04..d18c2cf9 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -41,7 +41,7 @@ static void VideoWrite(u16 d) if (a - ((unsigned)(Pico.video.reg[5]&0x7f) << 9) < 0x400) Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; break; - case 3: Pico.m.dirtyPal = 1; + case 3: if (PicoMem.cram [(a >> 1) & 0x3f] != d) Pico.m.dirtyPal = 1; PicoMem.cram [(a >> 1) & 0x3f] = d; break; case 5: PicoMem.vsram[(a >> 1) & 0x3f] = d; break; case 0x81: @@ -441,7 +441,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) break; case 0x0c: // renderers should update their palettes if sh/hi mode is changed - if ((d^dold)&8) Pico.m.dirtyPal = 2; + if ((d^dold)&8) Pico.m.dirtyPal = 1; break; } return; diff --git a/platform/common/common.mak b/platform/common/common.mak index 197e8677..2f676abc 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -70,7 +70,7 @@ SRCS_COMMON += $(R)pico/cd/memory_arm.S endif ifeq "$(asm_32xdraw)" "1" DEFINES += _ASM_32X_DRAW -SRCS_COMMON += $(R)pico/32x/draw_arm.s +SRCS_COMMON += $(R)pico/32x/draw_arm.S endif ifeq "$(asm_mix)" "1" SRCS_COMMON += $(R)pico/sound/mix_arm.S diff --git a/platform/common/emu.c b/platform/common/emu.c index 0a9f0890..da03bff1 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1407,8 +1407,10 @@ void emu_loop(void) { notice_msg_time = 0; plat_status_msg_clear(); +#ifndef __GP2X__ plat_video_flip(); plat_status_msg_clear(); /* Do it again in case of double buffering */ +#endif notice_msg = NULL; } else { diff --git a/platform/gizmondo/emu.c b/platform/gizmondo/emu.c index 86c473c2..fcf27125 100644 --- a/platform/gizmondo/emu.c +++ b/platform/gizmondo/emu.c @@ -155,7 +155,7 @@ static void blit(const char *fps, const char *notice) } // a hack for VR if (PicoIn.AHW & PAHW_SVP) - memset32((int *)(Pico.est.Draw2FB+328*8+328*223), 0xe0e0e0e0, 328); + memset((int *)(Pico.est.Draw2FB+328*8+328*223), 0xe0e0e0e0, 328*4); if (!(Pico.video.reg[12]&1)) lines_flags|=0x10000; if (currentConfig.EmuOpt&0x4000) lines_flags|=0x40000; // (Pico.m.frame_count&1)?0x20000:0x40000; @@ -166,22 +166,25 @@ static void blit(const char *fps, const char *notice) int lines_flags; // 8bit accurate renderer if (Pico.m.dirtyPal) { - Pico.m.dirtyPal = 0; - vidConvCpyRGB565(localPal, Pico.cram, 0x40); + if (Pico.m.dirtyPal == 2) + Pico.m.dirtyPal = 0; + /* no support + switch (Pico.est.SonicPalCount) { + case 3: vidConvCpyRGB565(localPal+0xc0, Pico.est.SonicPal+0xc0, 0x40); + case 2: vidConvCpyRGB565(localPal+0x80, Pico.est.SonicPal+0x80, 0x40); + case 1: vidConvCpyRGB565(localPal+0x40, Pico.est.SonicPal+0x40, 0x40); + default://vidConvCpyRGB565(localPal, Pico.est.SonicPal, 0x40); + } */ + vidConvCpyRGB565(localPal, Pico.est.SonicPal, 0x40); if (Pico.video.reg[0xC]&8) { // shadow/hilight mode - //vidConvCpyRGB32sh(localPal+0x40, Pico.cram, 0x40); - //vidConvCpyRGB32hi(localPal+0x80, Pico.cram, 0x40); // TODO? - memcpy32((void *)(localPal+0xc0), (void *)(localPal+0x40), 0x40*2/4); + //vidConvCpyRGB32sh(localPal+0x40, Pico.est.SonicPal, 0x40); + //vidConvCpyRGB32hi(localPal+0x80, Pico.est.SonicPal, 0x40); // TODO? + memcpy((void *)(localPal+0xc0), (void *)(localPal+0x40), 0x40*2); localPal[0xc0] = 0x0600; localPal[0xd0] = 0xc000; localPal[0xe0] = 0x0000; // reserved pixels for OSD localPal[0xf0] = 0xffff; } - /* no support - else if (rendstatus & 0x20) { // mid-frame palette changes - vidConvCpyRGB565(localPal+0x40, HighPal, 0x40); - vidConvCpyRGB565(localPal+0x80, HighPal+0x40, 0x40); - } */ } lines_flags = (Pico.video.reg[1]&8) ? 240 : 224; if (!(Pico.video.reg[12]&1)) lines_flags|=0x10000; diff --git a/platform/gizmondo/menu.c b/platform/gizmondo/menu.c index 51f032f0..1045f47b 100644 --- a/platform/gizmondo/menu.c +++ b/platform/gizmondo/menu.c @@ -54,7 +54,7 @@ static unsigned int inp_prev = 0; void menu_draw_begin(int use_bgbuff) { if (use_bgbuff) - memcpy32((int *)menu_screen, (int *)bg_buffer, 321*240*2/4); + memcpy((int *)menu_screen, (int *)bg_buffer, 321*240*2); } @@ -66,7 +66,7 @@ void menu_draw_end(void) lprintf("%s: Framework2D_LockBuffer() returned NULL\n", __FUNCTION__); return; } - memcpy32(giz_screen, (int *)menu_screen, 321*240*2/4); + memcpy(giz_screen, (int *)menu_screen, 321*240*2); fb_unlock(); giz_screen = NULL; fb_flip(); diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 18d8a57e..450ac080 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -291,32 +291,45 @@ static int EmuScanEnd16_ld(unsigned int num) } static int localPal[0x100]; +static int localPalSize; + static void (*vidcpyM2)(void *dest, void *src, int m32col, int with_32c_border); static int (*make_local_pal)(int fast_mode); static int make_local_pal_md(int fast_mode) { - int pallen = 0xc0; - - bgr444_to_rgb32(localPal, PicoMem.cram); - if (fast_mode) - return 0x40; + int pallen = 0x100; - if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode - bgr444_to_rgb32_sh(localPal, PicoMem.cram); - localPal[0xc0] = 0x0000c000; - localPal[0xd0] = 0x00c00000; - localPal[0xe0] = 0x00000000; // reserved pixels for OSD - localPal[0xf0] = 0x00ffffff; - pallen = 0x100; + if (fast_mode) { + bgr444_to_rgb32(localPal, PicoMem.cram); + pallen = 0x40; + Pico.m.dirtyPal = 0; } else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes - bgr444_to_rgb32(localPal+0x40, Pico.est.HighPal); - bgr444_to_rgb32(localPal+0x80, Pico.est.HighPal+0x40); + switch (Pico.est.SonicPalCount) { + case 3: bgr444_to_rgb32(localPal+0xc0, Pico.est.SonicPal+0xc0); + case 2: bgr444_to_rgb32(localPal+0x80, Pico.est.SonicPal+0x80); + case 1: bgr444_to_rgb32(localPal+0x40, Pico.est.SonicPal+0x40); + default:bgr444_to_rgb32(localPal, Pico.est.SonicPal); + } + pallen = (Pico.est.SonicPalCount+1)*0x40; } - else - memcpy(localPal + 0x80, localPal, 0x40 * 4); // for spr prio mess + else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode + bgr444_to_rgb32(localPal, Pico.est.SonicPal); + bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal); + } + else { + bgr444_to_rgb32(localPal, Pico.est.SonicPal); + memcpy(localPal+0x40, localPal, 0x40*4); // for spr prio mess + memcpy(localPal+0x80, localPal, 0x80*4); // for spr prio mess + } + localPal[0xc0] = 0x0000c000; + localPal[0xd0] = 0x00c00000; + localPal[0xe0] = 0x00000000; // reserved pixels for OSD + localPal[0xf0] = 0x00ffffff; + if (Pico.m.dirtyPal == 2) + Pico.m.dirtyPal = 0; return pallen; } @@ -334,25 +347,21 @@ static int make_local_pal_sms(int fast_mode) *dpal++ = t; } + Pico.m.dirtyPal = 0; return 0x40; } void pemu_finalize_frame(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; - int ret; if (PicoIn.AHW & PAHW_32X) - ; // nothing to do + localPalSize = 0; // nothing to do else if (get_renderer() == RT_8BIT_FAST) { // 8bit fast renderer - if (Pico.m.dirtyPal) { - Pico.m.dirtyPal = 0; - ret = make_local_pal(1); - // feed new palette to our device - gp2x_video_setpalette(localPal, ret); - } + if (Pico.m.dirtyPal) + localPalSize = make_local_pal(1); // a hack for VR if (PicoIn.AHW & PAHW_SVP) memset32((int *)(Pico.est.Draw2FB+328*8+328*223), 0xe0e0e0e0, 328); @@ -364,12 +373,9 @@ void pemu_finalize_frame(const char *fps, const char *notice) { // 8bit accurate renderer if (Pico.m.dirtyPal) - { - Pico.m.dirtyPal = 0; - ret = make_local_pal(0); - gp2x_video_setpalette(localPal, ret); - } + localPalSize = make_local_pal(0); } + else localPalSize = 0; // no palette in 16bit mode if (notice) osd_text(4, osd_y, notice); @@ -385,6 +391,10 @@ void plat_video_flip(void) { int stride = g_screen_width; gp2x_video_flip(); + // switching the palette takes immediate effect, whilst flipping only + // takes effect with the next vsync; unavoidable flicker may occur! + if (localPalSize) + gp2x_video_setpalette(localPal, localPalSize); if (is_16bit_mode()) stride *= 2; @@ -502,9 +512,6 @@ static void vid_reset_mode(void) if (renderer == RT_16BIT && (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)) { PicoDrawSetOutFormat(PDF_RGB555, 1); } - else { - PicoDrawSetOutFormat(PDF_NONE, 0); - } PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2); gp2x_mode = 16; } @@ -537,10 +544,7 @@ static void vid_reset_mode(void) localPal[0xe0] = 0x00000000; // reserved pixels for OSD localPal[0xf0] = 0x00ffffff; gp2x_video_setpalette(localPal, 0x100); - gp2x_memset_all_buffers(0, 0xe0, 320*240); } - else - gp2x_memset_all_buffers(0, 0, 320*240*2); if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) gp2x_mode = -gp2x_mode; @@ -723,6 +727,8 @@ void pemu_forced_frame(int no_scale, int do_emu) PicoDrawSetCallbacks(NULL, NULL); Pico.m.dirtyPal = 1; + if (!no_scale) + no_scale = currentConfig.scaling == EOPT_SCALE_NONE; emu_cmn_forced_frame(no_scale, do_emu); g_menubg_src_ptr = g_screen_ptr; diff --git a/platform/linux/emu.c b/platform/linux/emu.c index 5d4432fa..8af5afa8 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -71,8 +71,8 @@ void pemu_finalize_frame(const char *fps, const char *notice) unsigned char *ps = Pico.est.Draw2FB + 328*8 + 8; unsigned short *pal = Pico.est.HighPal; int i, x; - if (Pico.m.dirtyPal) - PicoDrawUpdateHighPal(); + + PicoDrawUpdateHighPal(); for (i = 0; i < 224; i++, ps += 8) for (x = 0; x < 320; x++) *pd++ = pal[*ps++]; @@ -109,6 +109,8 @@ static void apply_renderer(void) if (PicoIn.AHW & PAHW_32X) PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2); + + Pico.m.dirtyPal = 1; } void plat_video_toggle_renderer(int change, int is_menu) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 5c0cb57f..917ecc8d 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -201,13 +201,22 @@ static void do_pal_update(int allow_sh, int allow_as) //for (i = 0x3f/2; i >= 0; i--) // dpal[i] = ((spal[i]&0x000f000f)<< 1)|((spal[i]&0x00f000f0)<<3)|((spal[i]&0x0f000f00)<<4); - do_pal_convert(localPal, Pico.cram, currentConfig.gamma, currentConfig.gamma2); - - Pico.m.dirtyPal = 0; - need_pal_upload = 1; - - if (allow_sh && (Pico.video.reg[0xC]&8)) // shadow/hilight? + if ((currentConfig.EmuOpt&0x80) || (PicoOpt&0x10)) { + do_pal_convert(localPal, Pico.cram, currentConfig.gamma, currentConfig.gamma2); + Pico.m.dirtyPal = 0; + } + else if (Pico.est.rendstatus&0x20) + { + switch (Pico.est.SonicPalCount) { + case 3: do_pal_convert(localPal+0xc0, Pico.est.SonicPal+0xc0, currentConfig.gamma, currentConfig.gamma2); + case 2: do_pal_convert(localPal+0x80, Pico.est.SonicPal+0x80, currentConfig.gamma, currentConfig.gamma2); + case 1: do_pal_convert(localPal+0x40, Pico.est.SonicPal+0x40, currentConfig.gamma, currentConfig.gamma2); + default:do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2); + } + } + else if (allow_sh && (Pico.video.reg[0xC]&8)) // shadow/hilight? { + do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2); // shadowed pixels for (i = 0x3f/2; i >= 0; i--) dpal[0x20|i] = dpal[0x60|i] = (dpal[i]>>1)&0x7bcf7bcf; @@ -223,6 +232,16 @@ static void do_pal_update(int allow_sh, int allow_as) localPal[0xe0] = 0; localPal[0xf0] = 0x001f; } + else if (allow_as && (Pico.est.rendstatus & PDRAW_SPR_LO_ON_HI)) + { + do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2); + memcpy((int *)dpal+0x40/2, (void *)localPal, 0x40*2); + memcpy((int *)dpal+0x80/2, (void *)localPal, 0x80*2); + } + + if (Pico.m.dirtyPal == 2) + Pico.m.dirtyPal = 0; + need_pal_upload = 1; } static void do_slowmode_lines(int line_to) @@ -639,7 +658,7 @@ static void writeSound(int len) PicoIn.sndOut += len / 2; /*if (PicoIn.sndOut > sndBuffer_endptr) { - memcpy32((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) / 2); + memcpy((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) * 2); PicoIn.sndOut = &sndBuffer[PicoIn.sndOut - endptr]; lprintf("mov\n"); } diff --git a/platform/psp/menu.c b/platform/psp/menu.c index ab022f97..fc31b8e7 100644 --- a/platform/psp/menu.c +++ b/platform/psp/menu.c @@ -59,7 +59,7 @@ void menu_draw_begin(void) // int i; // for (i = 272; i >= 0; i--, dst += 512, src += 480) - // memcpy32((int *)dst, (int *)src, 480*2/4); + // memcpy((int *)dst, (int *)src, 480*2); sceGuSync(0,0); // sync with prev sceGuStart(GU_DIRECT, guCmdList);