From 48fc9762de700ffce656edcf9883147f66a51916 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 Nov 2023 21:00:56 +0100 Subject: [PATCH] psp, fix GU hardware rendering --- platform/psp/emu.c | 168 ++++++++++++++++++++++---------------------- platform/psp/emu.h | 2 + platform/psp/plat.c | 23 +++++- platform/psp/psp.c | 6 +- 4 files changed, 111 insertions(+), 88 deletions(-) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 18eb388b..a1c44cae 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "psp.h" #include "emu.h" @@ -48,7 +49,9 @@ static struct Vertex __attribute__((aligned(4))) g_vertices[2]; static u16 __attribute__((aligned(16))) localPal[0x100]; static int need_pal_upload = 0; -static u16 __attribute__((aligned(16))) osd_buf[512*8]; // buffer for osd text +u16 __attribute__((aligned(16))) osd_buf[512*8]; // buffer for osd text +int osd_buf_x[4], osd_buf_l[4]; // store for x and length for blitting +int osd_buf_cnt, osd_cdleds; static int out_x, out_y; static int out_w, out_h; @@ -105,6 +108,7 @@ static void change_renderer(int diff) static void apply_renderer(void) { PicoIn.opt &= ~(POPT_ALT_RENDERER|POPT_EN_SOFTSCALE); + PicoIn.opt |= POPT_DIS_32C_BORDER; switch (get_renderer()) { case RT_16BIT: @@ -120,32 +124,6 @@ static void apply_renderer(void) } } -static void osd_text(int x, const char *text) -{ - struct Vertex* vx; - int len = strlen(text) * 8 / 2; - int *p, h; - void *tmp = g_screen_ptr; - - g_screen_ptr = osd_buf; - for (h = 0; h < 8; h++) { - p = (int *) (osd_buf+x+512*h); - p = (int *) ((int)p & ~3); // align - memset32_uncached(p, 0, len); - } - emu_text_out16(x, 0, text); - g_screen_ptr = tmp; - - vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); - vx[0].u = x, vx[0].v = 0; - vx[1].u = x + len*2, vx[1].v = 8; - vx[0].x = x, vx[0].y = 264; - vx[1].x = x + len*2, vx[1].y = 272; - sceGuTexMode(GU_PSM_5650,0,0,0); - sceGuTexImage(0,512,8,512,osd_buf); - sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); -} - static void set_scaling_params(void) { @@ -276,7 +254,79 @@ static void do_pal_update(void) need_pal_upload = 1; } -static void blitscreen_clut(void) +static void osd_text(int x, const char *text) +{ + int len = strlen(text) * 8; + int *p, h; + void *tmp = g_screen_ptr; + + g_screen_ptr = osd_buf; + for (h = 0; h < 8; h++) { + p = (int *) (osd_buf+x+512*h); + p = (int *) ((int)p & ~3); // align + memset32_uncached(p, 0, len/2); + } + emu_text_out16(x, 0, text); + g_screen_ptr = tmp; + + osd_buf_x[osd_buf_cnt] = x; + osd_buf_l[osd_buf_cnt] = len; + osd_buf_cnt ++; +} + +static void blit_osd(void) +{ + struct Vertex* vx; + int x, len; + + while (osd_buf_cnt > 0) { + osd_buf_cnt --; + x = osd_buf_x[osd_buf_cnt]; + len = osd_buf_l[osd_buf_cnt]; + vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); + vx[0].u = x, vx[0].v = 0; + vx[1].u = x + len, vx[1].v = 8; + vx[0].x = x, vx[0].y = 264; + vx[1].x = x + len, vx[1].y = 272; + sceGuTexMode(GU_PSM_5650,0,0,0); + sceGuTexImage(0,512,8,512,osd_buf); + sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); + } +} + +static void cd_leds(void) +{ + unsigned int reg, col_g, col_r, *p; + + reg = Pico_mcd->s68k_regs[0]; + + p = (unsigned int *)((short *)osd_buf + 512*2+498); + col_g = (reg & 2) ? 0x06000600 : 0; + col_r = (reg & 1) ? 0x00180018 : 0; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; + + osd_cdleds = 1; +} + +static void blit_cdleds(void) +{ + struct Vertex* vx; + + if (!osd_cdleds) return; + + vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); + vx[0].u = 497, vx[0].v = 1; + vx[1].u = 497+14, vx[1].v = 6; + vx[0].x = 4, vx[0].y = 1; + vx[1].x = 4+14, vx[1].y = 6; + sceGuTexMode(GU_PSM_5650,0,0,0); + sceGuTexImage(0,512,8,512,osd_buf); + sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); +} + +void blitscreen_clut(void) { sceGuTexMode(is_16bit_mode() ? GU_PSM_5650:GU_PSM_T8,0,0,0); sceGuTexImage(0,512,512,512,g_screen_ptr); @@ -314,33 +364,12 @@ static void blitscreen_clut(void) else #endif sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,g_vertices); -} - - -static void cd_leds(void) -{ - struct Vertex* vx; - unsigned int reg, col_g, col_r, *p; - - reg = Pico_mcd->s68k_regs[0]; - - p = (unsigned int *)((short *)osd_buf + 512*2+498); - col_g = (reg & 2) ? 0x06000600 : 0; - col_r = (reg & 1) ? 0x00180018 : 0; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; - vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); - vx[0].u = 497, vx[0].v = 1; - vx[1].u = 497+14, vx[1].v = 6; - vx[0].x = 4, vx[0].y = 1; - vx[1].x = 4+14, vx[1].y = 6; - sceGuTexMode(GU_PSM_5650,0,0,0); - sceGuTexImage(0,512,8,512,osd_buf); - sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); + blit_osd(); + blit_cdleds(); } + static void draw_pico_ptr(void) { unsigned char *p = (unsigned char *)g_screen_ptr + 8; @@ -359,23 +388,6 @@ static void draw_pico_ptr(void) } -// clears whole screen or just the notice area (in all buffers) -static void clearArea(int full) -{ - void *fb = psp_video_get_active_fb(); - - if (full) { - u32 val = (is_16bit_mode() ? 0x00000000 : 0xe0e0e0e0); - long sz = 512*272*2; - memset32_uncached(psp_screen, 0, 512*272*2/4); // frame buffer - memset32_uncached(fb, 0, 512*272*2/4); // frame buff on display - memset32(VRAM_CACHED_STUFF, val, 2*sz/4); // 2 draw buffers - } else { - memset32_uncached((int *)((char *)psp_screen + 512*264*2), 0, 512*8*2/4); - memset32_uncached((int *)((char *)fb + 512*264*2), 0, 512*8*2/4); - } -} - static void vidResetMode(void) { // setup GU @@ -614,25 +626,19 @@ void pemu_validate_config(void) void pemu_finalize_frame(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; - int offs = (psp_screen == VRAM_FB0) ? VRAMOFFS_FB0 : VRAMOFFS_FB1; if (PicoIn.AHW & PAHW_PICO) draw_pico_ptr(); - sceGuSync(0,0); // sync with prev - sceGuStart(GU_DIRECT, guCmdList); - sceGuDrawBuffer(GU_PSM_5650, (void *)offs, 512); // point to back buffer - - blitscreen_clut(); - + osd_buf_cnt = 0; if (notice) osd_text(4, notice); if (emu_opt & 2) osd_text(OSD_FPS_X, fps); + osd_cdleds = 0; if ((emu_opt & 0x400) && (PicoIn.AHW & PAHW_MCD)) cd_leds(); sceKernelDcacheWritebackAll(); - sceGuFinish(); } /* FIXME: move plat_* to plat? */ @@ -676,7 +682,7 @@ void plat_status_msg_busy_next(const char *msg) /* clear status message area */ void plat_status_msg_clear(void) { - clearArea(0); + // not needed since the screen buf is cleared through the GU } /* change the audio volume setting */ @@ -690,7 +696,7 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co out_y = start_line; out_x = start_col; out_h = line_count; out_w = col_count; - if (col_count == 248) // mind aspect ration when blanking 1st column + if (col_count == 248) // mind aspect ratio when blanking 1st column col_count = 256; switch (currentConfig.vscaling) { @@ -723,8 +729,6 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co } vidResetMode(); - if (col_count < 320) // clear borders from h40 remnants - clearArea(1); } /* render one frame in RGB */ @@ -741,7 +745,6 @@ void pemu_forced_frame(int no_scale, int do_emu) void plat_video_toggle_renderer(int change, int is_menu_call) { change_renderer(change); - clearArea(1); if (is_menu_call) return; @@ -770,7 +773,6 @@ void plat_video_loop_prepare(void) { apply_renderer(); vidResetMode(); - clearArea(1); } /* prepare for entering the emulator loop */ diff --git a/platform/psp/emu.h b/platform/psp/emu.h index e9202745..7eed9f9c 100644 --- a/platform/psp/emu.h +++ b/platform/psp/emu.h @@ -3,6 +3,8 @@ extern int engineStateSuspend; void emu_handle_resume(void); +void blitscreen_clut(void); + // actually comes from Pico/Misc_amips.s void memset32_uncached(int *dest, int c, int count); diff --git a/platform/psp/plat.c b/platform/psp/plat.c index 0232b1d0..9832bd10 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -70,8 +70,23 @@ void plat_target_finish(void) /* display a completed frame buffer and prepare a new render buffer */ void plat_video_flip(void) { + int offs = (psp_screen == VRAM_FB0) ? VRAMOFFS_FB0 : VRAMOFFS_FB1; + g_menubg_src_ptr = psp_screen; - psp_video_flip(currentConfig.EmuOpt & EOPT_VSYNC, 1); + + sceGuSync(0, 0); // sync with prev + psp_video_flip(currentConfig.EmuOpt & EOPT_VSYNC, 0); + + sceGuStart(GU_DIRECT, guCmdList); + sceGuDrawBuffer(GU_PSM_5650, (void *)offs, 512); // point to back buffer + sceGuClearColor(0); + sceGuClearDepth(0); + sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT); + + blitscreen_clut(); + + sceGuFinish(); + g_screen_ptr = VRAM_CACHED_STUFF + (psp_screen - VRAM_FB0); plat_video_set_buffer(g_screen_ptr); } @@ -96,13 +111,15 @@ void plat_video_menu_begin(void) /* display a completed menu screen */ void plat_video_menu_end(void) { - plat_video_wait_vsync(); - psp_video_flip(0, 0); + g_menuscreen_ptr = NULL; + psp_video_flip(1, 0); } /* terminate menu display */ void plat_video_menu_leave(void) { + g_screen_ptr = VRAM_CACHED_STUFF + (psp_screen - VRAM_FB0); + plat_video_set_buffer(g_screen_ptr); } /* Preliminary initialization needed at program start */ diff --git a/platform/psp/psp.c b/platform/psp/psp.c index e719e469..081723af 100644 --- a/platform/psp/psp.c +++ b/platform/psp/psp.c @@ -155,6 +155,8 @@ void psp_init(void) sceGuDrawBuffer(GU_PSM_5650, (void *)VRAMOFFS_FB0, 512); sceGuDispBuffer(480, 272, (void *)VRAMOFFS_FB1, 512); // don't care sceGuDepthBuffer((void *)VRAMOFFS_DEPTH, 512); + sceGuClearColor(0); + sceGuClearDepth(0); sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT); sceGuOffset(2048 - (480 / 2), 2048 - (272 / 2)); sceGuViewport(2048, 2048, 480, 272); @@ -195,9 +197,9 @@ void psp_video_flip(int wait_vsync, int other) { unsigned long fb = (unsigned long)psp_screen & ~0x40000000; if (other) fb ^= 0x44000; - //if (wait_vsync) sceDisplayWaitVblankStart(); + if (wait_vsync) sceDisplayWaitVblankStart(); sceDisplaySetFrameBuf((void *)fb, 512, PSP_DISPLAY_PIXEL_FORMAT_565, - wait_vsync ? PSP_DISPLAY_SETBUF_NEXTFRAME : PSP_DISPLAY_SETBUF_IMMEDIATE); + PSP_DISPLAY_SETBUF_IMMEDIATE); current_screen ^= 1; psp_screen = current_screen ? VRAM_FB0 : VRAM_FB1; } -- 2.39.2