From 5440b88ee29ee5b8929fcf338dfc8f476468514d Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 4 Jan 2012 23:26:32 +0200 Subject: [PATCH] gpu_neon: add some intelace mode handling a bit of refactoring too --- frontend/main.c | 1 + frontend/menu.c | 32 ++++++++++++++-- frontend/plugin_lib.h | 3 ++ plugins/gpu_neon/gpu.c | 69 ++++++++++++++++++++++++++++++++--- plugins/gpu_neon/gpu.h | 11 ++++-- plugins/gpu_neon/peops_if.c | 4 ++ plugins/gpu_neon/psx_gpu_if.c | 9 +++++ plugins/gpu_neon/test.c | 2 + plugins/gpu_neon/unai_if.cpp | 4 ++ plugins/gpu_neon/vout_fb.c | 29 +-------------- plugins/gpu_neon/vout_sdl.c | 23 +----------- 11 files changed, 127 insertions(+), 60 deletions(-) diff --git a/frontend/main.c b/frontend/main.c index fd4674bf..7b3aac53 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -150,6 +150,7 @@ void emu_set_default_config(void) pl_rearmed_cbs.gpu_unai.abe_hack = pl_rearmed_cbs.gpu_unai.no_light = pl_rearmed_cbs.gpu_unai.no_blend = 0; + pl_rearmed_cbs.gpu_neon.allow_interlace = 2; // auto iUseReverb = 2; iUseInterpolation = 1; diff --git a/frontend/menu.c b/frontend/menu.c index ce5c3eb6..c6a52ded 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -290,6 +290,7 @@ static const struct { CE_INTVAL_P(gpu_unai.abe_hack), CE_INTVAL_P(gpu_unai.no_light), CE_INTVAL_P(gpu_unai.no_blend), + CE_INTVAL_P(gpu_neon.allow_interlace), CE_INTVAL_V(iUseReverb, 3), CE_INTVAL_V(iXAPitch, 3), CE_INTVAL_V(iUseInterpolation, 3), @@ -1193,6 +1194,26 @@ static int menu_loop_gfx_options(int id, int keys) // ------------ bios/plugins ------------ +#ifdef __ARM_NEON__ + +static const char h_gpu_neon[] = "Configure built-in NEON GPU plugin"; +static const char *men_gpu_interlace[] = { "Off", "On", "Auto", NULL }; + +static menu_entry e_menu_plugin_gpu_neon[] = +{ + mee_enum ("Enable interlace mode", 0, pl_rearmed_cbs.gpu_neon.allow_interlace, men_gpu_interlace), + mee_end, +}; + +static int menu_loop_plugin_gpu_neon(int id, int keys) +{ + int sel = 0; + me_loop(e_menu_plugin_gpu_neon, &sel); + return 0; +} + +#endif + static menu_entry e_menu_plugin_gpu_unai[] = { mee_onoff ("Skip every 2nd line", 0, pl_rearmed_cbs.gpu_unai.lineskip, 1), @@ -1210,12 +1231,12 @@ static int menu_loop_plugin_gpu_unai(int id, int keys) } static const char *men_gpu_dithering[] = { "None", "Game dependant", "Always", NULL }; -static const char h_gpu_0[] = "Needed for Chrono Cross"; +//static const char h_gpu_0[] = "Needed for Chrono Cross"; static const char h_gpu_1[] = "Capcom fighting games"; static const char h_gpu_2[] = "Black screens in Lunar"; static const char h_gpu_3[] = "Compatibility mode"; static const char h_gpu_6[] = "Pandemonium 2"; -static const char h_gpu_7[] = "Skip every second frame"; +//static const char h_gpu_7[] = "Skip every second frame"; static const char h_gpu_8[] = "Needed by Dark Forces"; static const char h_gpu_9[] = "better g-colors, worse textures"; static const char h_gpu_10[] = "Toggle busy flags after drawing"; @@ -1223,12 +1244,12 @@ static const char h_gpu_10[] = "Toggle busy flags after drawing"; static menu_entry e_menu_plugin_gpu_peops[] = { mee_enum ("Dithering", 0, pl_rearmed_cbs.gpu_peops.iUseDither, men_gpu_dithering), - mee_onoff_h ("Odd/even bit hack", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0), +// mee_onoff_h ("Odd/even bit hack", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0), mee_onoff_h ("Expand screen width", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<1, h_gpu_1), mee_onoff_h ("Ignore brightness color", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<2, h_gpu_2), mee_onoff_h ("Disable coordinate check", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<3, h_gpu_3), mee_onoff_h ("Lazy screen update", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<6, h_gpu_6), - mee_onoff_h ("Old frame skipping", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7), +// mee_onoff_h ("Old frame skipping", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7), mee_onoff_h ("Repeated flat tex triangles ",0,pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<8, h_gpu_8), mee_onoff_h ("Draw quads with triangles", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<9, h_gpu_9), mee_onoff_h ("Fake 'gpu busy' states", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<10, h_gpu_10), @@ -1279,6 +1300,9 @@ static menu_entry e_menu_plugin_options[] = mee_enum_h ("BIOS", 0, bios_sel, bioses, h_bios), mee_enum_h ("GPU plugin", 0, gpu_plugsel, gpu_plugins, h_plugin_xpu), mee_enum_h ("SPU plugin", 0, spu_plugsel, spu_plugins, h_plugin_xpu), +#ifdef __ARM_NEON__ + mee_handler_h ("Configure built-in GPU plugin", menu_loop_plugin_gpu_neon, h_gpu_neon), +#endif mee_handler_h ("Configure gpu_peops plugin", menu_loop_plugin_gpu_peops, h_gpu_peops), mee_handler_h ("Configure PCSX4ALL GPU plugin", menu_loop_plugin_gpu_unai, h_gpu_unai), mee_handler_h ("Configure built-in SPU plugin", menu_loop_plugin_spu, h_spu), diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h index 2806056f..44c56302 100644 --- a/frontend/plugin_lib.h +++ b/frontend/plugin_lib.h @@ -61,6 +61,9 @@ struct rearmed_cbs { int no_light, no_blend; int lineskip; } gpu_unai; + struct { + int allow_interlace; // 0 off, 1 on, 2 guess + } gpu_neon; }; extern struct rearmed_cbs pl_rearmed_cbs; diff --git a/plugins/gpu_neon/gpu.c b/plugins/gpu_neon/gpu.c index 02dd3721..339cdfdc 100644 --- a/plugins/gpu_neon/gpu.c +++ b/plugins/gpu_neon/gpu.c @@ -29,6 +29,7 @@ struct psx_gpu gpu __attribute__((aligned(2048))); static noinline void do_reset(void) { memset(gpu.regs, 0, sizeof(gpu.regs)); + memset(gpu.ex_regs, 0, sizeof(gpu.ex_regs)); gpu.status.reg = 0x14802000; gpu.gp0 = 0; gpu.regs[3] = 1; @@ -264,10 +265,10 @@ static void start_vram_transfer(uint32_t pos_word, uint32_t size_word, int is_re if (gpu.dma.h) log_anomaly("start_vram_transfer while old unfinished\n"); - gpu.dma.x = pos_word & 1023; - gpu.dma.y = (pos_word >> 16) & 511; - gpu.dma.w = size_word & 0xffff; // ? - gpu.dma.h = size_word >> 16; + gpu.dma.x = pos_word & 0x3ff; + gpu.dma.y = (pos_word >> 16) & 0x1ff; + gpu.dma.w = size_word & 0x3ff; + gpu.dma.h = (size_word >> 16) & 0x1ff; gpu.dma.offset = 0; renderer_flush_queues(); @@ -275,6 +276,7 @@ static void start_vram_transfer(uint32_t pos_word, uint32_t size_word, int is_re gpu.status.img = 1; // XXX: wrong for width 1 memcpy(&gpu.gp0, VRAM_MEM_XY(gpu.dma.x, gpu.dma.y), 4); + gpu.state.last_vram_read_frame = *gpu.state.frame_count; } else { renderer_invalidate_caches(gpu.dma.x, gpu.dma.y, gpu.dma.w, gpu.dma.h); @@ -362,7 +364,7 @@ static int check_cmd(uint32_t *data, int count) return count - pos; } -void flush_cmd_buffer(void) +static void flush_cmd_buffer(void) { int left = check_cmd(gpu.cmd_buffer, gpu.cmd_len); if (left > 0) @@ -533,8 +535,65 @@ long GPUfreeze(uint32_t type, struct GPUFreeze *freeze) return 1; } +void GPUupdateLace(void) +{ + if (gpu.cmd_len > 0) + flush_cmd_buffer(); + renderer_flush_queues(); + + if (gpu.status.blanking || !gpu.state.fb_dirty) + return; + + if (gpu.frameskip.set) { + if (!gpu.frameskip.frame_ready) { + if (*gpu.state.frame_count - gpu.frameskip.last_flip_frame < 9) + return; + gpu.frameskip.active = 0; + } + gpu.frameskip.frame_ready = 0; + } + + vout_update(); + gpu.state.fb_dirty = 0; +} + void GPUvBlank(int is_vblank, int lcf) { + int interlace = gpu.state.allow_interlace + && gpu.status.interlace && gpu.status.dheight; + // interlace doesn't look nice on progressive displays, + // so we have this "auto" mode here for games that don't read vram + if (gpu.state.allow_interlace == 2 + && *gpu.state.frame_count - gpu.state.last_vram_read_frame > 1) + { + interlace = 0; + } + if (interlace || interlace != gpu.state.old_interlace) { + gpu.state.old_interlace = interlace; + + if (gpu.cmd_len > 0) + flush_cmd_buffer(); + renderer_flush_queues(); + renderer_set_interlace(interlace, !lcf); + } +} + +#include "../../frontend/plugin_lib.h" + +void GPUrearmedCallbacks(const struct rearmed_cbs *cbs) +{ + gpu.frameskip.set = cbs->frameskip; + gpu.frameskip.advice = &cbs->fskip_advice; + gpu.frameskip.active = 0; + gpu.frameskip.frame_ready = 1; + gpu.state.hcnt = cbs->gpu_hcnt; + gpu.state.frame_count = cbs->gpu_frame_count; + gpu.state.allow_interlace = cbs->gpu_neon.allow_interlace; + + if (cbs->pl_vout_set_raw_vram) + cbs->pl_vout_set_raw_vram(gpu.vram); + renderer_set_config(cbs); + vout_set_config(cbs); } // vim:shiftwidth=2:expandtab diff --git a/plugins/gpu_neon/gpu.h b/plugins/gpu_neon/gpu.h index 6aa933e3..36fdef8e 100644 --- a/plugins/gpu_neon/gpu.h +++ b/plugins/gpu_neon/gpu.h @@ -64,6 +64,8 @@ struct psx_gpu { uint32_t zero; struct { uint32_t fb_dirty:1; + uint32_t old_interlace:1; + uint32_t allow_interlace:2; uint32_t *frame_count; uint32_t *hcnt; /* hsync count */ struct { @@ -72,6 +74,7 @@ struct psx_gpu { uint32_t frame; uint32_t hcnt; } last_list; + uint32_t last_vram_read_frame; } state; struct { int32_t set:3; /* -1 auto, 0 off, 1-3 fixed */ @@ -87,7 +90,6 @@ struct psx_gpu { extern struct psx_gpu gpu; extern const unsigned char cmd_lengths[256]; -void flush_cmd_buffer(void); void do_cmd_list(uint32_t *list, int count); @@ -97,10 +99,13 @@ int renderer_init(void); void renderer_sync_ecmds(uint32_t * ecmds); void renderer_invalidate_caches(int x, int y, int w, int h); void renderer_flush_queues(void); +void renderer_set_interlace(int enable, int is_odd); void renderer_set_config(const struct rearmed_cbs *config); -int vout_init(void); -int vout_finish(void); +int vout_init(void); +int vout_finish(void); +void vout_update(void); +void vout_set_config(const struct rearmed_cbs *config); /* listing these here for correct linkage if rasterizer uses c++ */ struct GPUFreeze; diff --git a/plugins/gpu_neon/peops_if.c b/plugins/gpu_neon/peops_if.c index 48fd431b..2e967f24 100644 --- a/plugins/gpu_neon/peops_if.c +++ b/plugins/gpu_neon/peops_if.c @@ -385,6 +385,10 @@ void renderer_flush_queues(void) { } +void renderer_set_interlace(int enable, int is_odd) +{ +} + #include "../../frontend/plugin_lib.h" void renderer_set_config(const struct rearmed_cbs *cbs) diff --git a/plugins/gpu_neon/psx_gpu_if.c b/plugins/gpu_neon/psx_gpu_if.c index 8907ac02..470f68e7 100644 --- a/plugins/gpu_neon/psx_gpu_if.c +++ b/plugins/gpu_neon/psx_gpu_if.c @@ -48,6 +48,15 @@ void renderer_flush_queues(void) flush_render_block_buffer(&egpu); } +void renderer_set_interlace(int enable, int is_odd) +{ + egpu.interlace_mode &= ~(RENDER_INTERLACE_ENABLED|RENDER_INTERLACE_ODD); + if (enable) + egpu.interlace_mode |= RENDER_INTERLACE_ENABLED; + if (is_odd) + egpu.interlace_mode |= RENDER_INTERLACE_ODD; +} + void renderer_set_config(const struct rearmed_cbs *cbs) { } diff --git a/plugins/gpu_neon/test.c b/plugins/gpu_neon/test.c index be271b65..e523e209 100644 --- a/plugins/gpu_neon/test.c +++ b/plugins/gpu_neon/test.c @@ -89,6 +89,8 @@ int main(int argc, char *argv[]) pcnt_init(); renderer_init(); memcpy(gpu.vram, state.vram, sizeof(gpu.vram)); + if ((state.gpu_register[8] & 0x24) == 0x24) + renderer_set_interlace(1, !(state.status >> 31)); start_cycles = pcnt_get(); diff --git a/plugins/gpu_neon/unai_if.cpp b/plugins/gpu_neon/unai_if.cpp index 4e3e7f91..072993af 100644 --- a/plugins/gpu_neon/unai_if.cpp +++ b/plugins/gpu_neon/unai_if.cpp @@ -272,6 +272,10 @@ void renderer_flush_queues(void) { } +void renderer_set_interlace(int enable, int is_odd) +{ +} + #ifndef TEST #include "../../frontend/plugin_lib.h" diff --git a/plugins/gpu_neon/vout_fb.c b/plugins/gpu_neon/vout_fb.c index a45b5f14..20c8ff39 100644 --- a/plugins/gpu_neon/vout_fb.c +++ b/plugins/gpu_neon/vout_fb.c @@ -88,28 +88,13 @@ static void blit(void) screen_buf = cbs->pl_vout_flip(); } -void GPUupdateLace(void) +void vout_update(void) { - if (gpu.status.blanking || !gpu.state.fb_dirty) - return; - - if (gpu.frameskip.set) { - if (!gpu.frameskip.frame_ready) { - if (*gpu.state.frame_count - gpu.frameskip.last_flip_frame < 9) - return; - } - gpu.frameskip.frame_ready = 0; - } - - if (gpu.cmd_len > 0) - flush_cmd_buffer(); - renderer_flush_queues(); check_mode_change(); if (cbs->pl_vout_raw_flip) cbs->pl_vout_raw_flip(gpu.screen.x, gpu.screen.y); else blit(); - gpu.state.fb_dirty = 0; } long GPUopen(void **unused) @@ -128,19 +113,9 @@ long GPUclose(void) return 0; } -void GPUrearmedCallbacks(const struct rearmed_cbs *cbs_) +void vout_set_config(const struct rearmed_cbs *cbs_) { cbs = cbs_; - gpu.frameskip.set = cbs->frameskip; - gpu.frameskip.advice = &cbs->fskip_advice; - gpu.frameskip.active = 0; - gpu.frameskip.frame_ready = 1; - gpu.state.hcnt = cbs->gpu_hcnt; - gpu.state.frame_count = cbs->gpu_frame_count; - - if (cbs->pl_vout_set_raw_vram) - cbs->pl_vout_set_raw_vram(gpu.vram); - renderer_set_config(cbs_); } // vim:shiftwidth=2:expandtab diff --git a/plugins/gpu_neon/vout_sdl.c b/plugins/gpu_neon/vout_sdl.c index 0830c56d..db1ae96e 100644 --- a/plugins/gpu_neon/vout_sdl.c +++ b/plugins/gpu_neon/vout_sdl.c @@ -48,7 +48,7 @@ int vout_finish(void) return 0; } -static void blit(void) +void vout_update(void) { uint32_t *d; int i; @@ -77,17 +77,6 @@ static void blit(void) SDL_UpdateRect(screen, 0, 0, 1024, 512); } -void GPUupdateLace(void) -{ - if (!gpu.status.blanking && gpu.state.fb_dirty) { - if (gpu.cmd_len > 0) - flush_cmd_buffer(); - renderer_flush_queues(); - blit(); - gpu.state.fb_dirty = 0; - } -} - long GPUopen(void **dpy) { *dpy = x11_display; @@ -99,16 +88,8 @@ long GPUclose(void) return 0; } -#include "../../frontend/plugin_lib.h" - -void GPUrearmedCallbacks(const struct rearmed_cbs *cbs) +void vout_set_config(const struct rearmed_cbs *cbs) { - gpu.state.hcnt = cbs->gpu_hcnt; - gpu.state.frame_count = cbs->gpu_frame_count; - - if (cbs->pl_vout_set_raw_vram) - cbs->pl_vout_set_raw_vram(gpu.vram); - renderer_set_config(cbs); } // vim:shiftwidth=2:expandtab -- 2.39.2