#endif // NO_FRONTEND
-static void CALLBACK dummy_lace(void)
+static void CALLBACK dummy_vBlank(int is_vblank, int lcf)
{
}
void SysReset() {
// rearmed hack: EmuReset() runs some code when real BIOS is used,
// but we usually do reset from menu while GPU is not open yet,
- // so we need to prevent updateLace() call..
- void *real_lace = GPU_updateLace;
- GPU_updateLace = dummy_lace;
+ // so we need to prevent vBlank() call...
+ void *real_vbl = GPU_vBlank;
+ GPU_vBlank = dummy_vBlank;
g_emu_resetting = 1;
// reset can run code, timing must be set
EmuReset();
- GPU_updateLace = real_lace;
+ GPU_vBlank = real_vbl;
g_emu_resetting = 0;
}
for (; h > 0; h--, d += g_menuscreen_w, s += 1024)
bgr555_to_rgb565(d, s, w);
- smalltext_out16(4, 1, "build: "__DATE__ " " __TIME__ " " REV, 0xe7fc);
- snprintf(buff, sizeof(buff), "GPU sr: %08x", gpuf->ulStatus);
- smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
+ snprintf(buff, sizeof(buff), "GPU sr: %08x scn: %3d %3d", gpuf->ulStatus,
+ gpuf->ulControl[5] & 0x3ff, (gpuf->ulControl[5] >> 10) & 0x1ff);
+ smalltext_out16(4, ty, buff, 0xe7fc);
snprintf(buff, sizeof(buff), "PC/SP: %08x %08x", psxRegs.pc, psxRegs.GPR.n.sp);
smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
}
+static void debug_set_mode(int w, int h, int raw_w, int raw_h, int bpp) {}
+static void debug_flip(const void *vram_, int vram_ofs, int bgr24,
+ int x, int y, int w, int h, int dims_changed) {}
+
static void debug_menu_loop(void)
{
int inp, df_x = 0, df_y = 0;
else if (inp & PBTN_DOWN) { if (df_y < 512 - g_menuscreen_h) df_y++; }
else if (inp & PBTN_LEFT) { if (df_x > 0) df_x -= 2; }
else if (inp & PBTN_RIGHT) { if (df_x < 1024 - g_menuscreen_w) df_x += 2; }
+ else if (inp & PBTN_MOK) {
+ u32 oldframe = frame_counter;
+ void *old_set_mode = pl_rearmed_cbs.pl_vout_set_mode;
+ void *old_flip = pl_rearmed_cbs.pl_vout_flip;
+ pl_rearmed_cbs.pl_vout_set_mode = debug_set_mode;
+ pl_rearmed_cbs.pl_vout_flip = debug_flip;
+ psxRegs.stop++;
+ while (frame_counter == oldframe)
+ psxCpu->ExecuteBlock(&psxRegs, EXEC_CALLER_OTHER);
+ psxRegs.stop--;
+ pl_rearmed_cbs.pl_vout_set_mode = old_set_mode;
+ pl_rearmed_cbs.pl_vout_flip = old_flip;
+ }
}
free(gpuf);
extern uint32_t GPUreadData(void);
extern void GPUreadDataMem(uint32_t *, int);
extern long GPUdmaChain(uint32_t *, uint32_t, uint32_t *, int32_t *);
-extern void GPUupdateLace(void);
extern long GPUfreeze(uint32_t, void *, uint16_t **);
extern void GPUvBlank(int, int);
extern void GPUgetScreenInfo(int *y, int *base_hres);
DIRECT_SPU(SPUplayCDDAchannel),
DIRECT_SPU(SPUsetCDvol),
/* GPU */
- DIRECT_GPU(GPUupdateLace),
DIRECT_GPU(GPUinit),
DIRECT_GPU(GPUshutdown),
DIRECT_GPU(GPUopen),
pc_hook_func_ret(uint32_t, GPU_readData, (void), (), PCNT_GPU)
pc_hook_func (GPU_readDataMem, (uint32_t *a0, int a1), (a0, a1), PCNT_GPU)
pc_hook_func_ret(long, GPU_dmaChain, (uint32_t *a0, int32_t a1), (a0, a1), PCNT_GPU)
-pc_hook_func (GPU_updateLace, (void), (), PCNT_GPU)
pc_hook_func (SPU_writeRegister, (unsigned long a0, unsigned short a1, uint32_t a2), (a0, a1, a2), PCNT_SPU)
pc_hook_func_ret(unsigned short,SPU_readRegister, (unsigned long a0, , unsigned int a1), (a0, a1), PCNT_SPU)
hook_it(GPU_readData);
hook_it(GPU_readDataMem);
hook_it(GPU_dmaChain);
- hook_it(GPU_updateLace);
hook_it(SPU_writeRegister);
hook_it(SPU_readRegister);
hook_it(SPU_writeDMAMem);
static char IsoFile[MAXPATHLEN] = "";
static s64 cdOpenCaseTime = 0;
-GPUupdateLace GPU_updateLace;
GPUinit GPU_init;
GPUshutdown GPU_shutdown;
GPUopen GPU_open;
LoadGpuSym1(writeDataMem, "GPUwriteDataMem");
LoadGpuSym1(writeStatus, "GPUwriteStatus");
LoadGpuSym1(dmaChain, "GPUdmaChain");
- LoadGpuSym1(updateLace, "GPUupdateLace");
LoadGpuSym1(freeze, "GPUfreeze");
LoadGpuSym0(vBlank, "GPUvBlank");
LoadGpuSym0(getScreenInfo, "GPUgetScreenInfo");
typedef uint32_t (CALLBACK* GPUreadData)(void);\r
typedef void (CALLBACK* GPUreadDataMem)(uint32_t *, int);\r
typedef long (CALLBACK* GPUdmaChain)(uint32_t *, uint32_t, uint32_t *, int32_t *);\r
-typedef void (CALLBACK* GPUupdateLace)(void);\r
typedef long (CALLBACK* GPUfreeze)(uint32_t, GPUFreeze_t *, uint16_t **);\r
typedef void (CALLBACK* GPUvBlank)(int, int);\r
typedef void (CALLBACK* GPUgetScreenInfo)(int *, int *);\r
\r
// GPU function pointers\r
-extern GPUupdateLace GPU_updateLace;\r
extern GPUinit GPU_init;\r
extern GPUshutdown GPU_shutdown; \r
extern GPUopen GPU_open;\r
setIrq( 0x01 );
EmuUpdate();
- GPU_updateLace();
+ //GPU_updateLace(); // handled by GPU_vBlank() now
if( SPU_async )
{
void GPUwriteStatus(uint32_t data)
{
uint32_t cmd = data >> 24;
- uint32_t fb_dirty = 1;
+ uint32_t fb_dirty = 1, frame;
int src_x, src_y, changed;
if (cmd < ARRAY_SIZE(gpu.regs)) {
case 0x05:
src_x = data & 0x3ff; src_y = (data >> 10) & 0x1ff;
changed = src_x != gpu.screen.src_x || src_y != gpu.screen.src_y;
+ frame = *gpu.state.frame_count;
// last_flip_frame check allows frameskip on dheight games
// that always set the same display area address
- if (changed || gpu.frameskip.last_flip_frame != *gpu.state.frame_count)
+ if (changed || gpu.frameskip.last_flip_frame != frame)
{
gpu.state.fb_dirty_display_area |= gpu.state.fb_dirty;
gpu.state.fb_dirty = 0;
gpu.screen.src_y = src_y;
check_draw_to_display(&gpu);
if (gpu.frameskip.set) {
- uint32_t flip_delay = *gpu.state.frame_count - gpu.frameskip.last_flip_frame;
+ uint32_t flip_delay = frame - gpu.frameskip.last_flip_frame;
if (flip_delay)
decide_frameskip(&gpu, flip_delay);
if (!gpu.frameskip.active || !gpu.frameskip.allow)
gpu.frameskip.last_flip_frame = *gpu.state.frame_count;
}
if (changed) {
+ if (!gpu.state.vblank && !(gpu.status & PSX_GPU_STATUS_BLANKING) &&
+ !gpu.state.use_alternative_flip)
+ {
+ uint32_t fdiff = frame - gpu.state.last_adflip_frame;
+ gpu.state.last_adflip_frame = frame;
+ if (fdiff < 9u) {
+ log_anomaly(&gpu, "active display flip detected\n");
+ gpu.state.use_alternative_flip = 1;
+ }
+ }
if (gpu_async_enabled(&gpu))
gpu_async_notify_screen_change(&gpu);
else
return 1;
}
-void GPUupdateLace(void)
+static void GPUupdateLace(void)
{
int delay_vout_update = 0;
int updated = 1;
vout_blank(&gpu);
gpu.state.blanked = 1;
gpu.state.fb_dirty_display_area = 1;
+ gpu.state.use_alternative_flip = 0;
}
return;
}
void GPUvBlank(int is_vblank, int lcf)
{
- int interlace = gpu.state.allow_interlace
+ int interlace;
+ gpu.state.vblank = is_vblank;
+ interlace = gpu.state.allow_interlace
&& (gpu.status & PSX_GPU_STATUS_INTERLACE)
&& (gpu.status & PSX_GPU_STATUS_DHEIGHT);
// interlace doesn't look nice on progressive displays,
renderer_set_interlace(interlace, !lcf);
}
}
+ if ((!is_vblank) == gpu.state.use_alternative_flip)
+ GPUupdateLace();
}
void GPUgetScreenInfo(int *y, int *base_hres)
gpu.state.enhancement_enable = cbs->gpu_neon.enhancement_enable;
gpu.state.enhancement_active = 0;
gpu.state.downscale_enable = cbs->scale_hires;
+ gpu.state.use_alternative_flip = 0;
gpu.state.screen_centering_type_default = cbs->screen_centering_type_default;
if (gpu.state.screen_centering_type != cbs->screen_centering_type
|| gpu.state.screen_centering_x != cbs->screen_centering_x
uint32_t old_interlace:1;
uint32_t allow_interlace:2;
uint32_t blanked:1;
+ uint32_t vblank:1;
+ uint32_t use_alternative_flip:1;
uint32_t enhancement_enable:1;
uint32_t enhancement_active:1;
uint32_t enhancement_was_active:1;
uint32_t hcnt;
} last_list;
uint32_t last_vram_read_frame;
+ uint32_t last_adflip_frame;
uint16_t w_out_old, h_out_old, src_y_old;
uint32_t status_vo_old;
short screen_centering_type;
uint32_t GPUreadStatus(void);
void GPUwriteStatus(uint32_t data);
long GPUfreeze(uint32_t type, struct GPUFreeze *freeze, uint16_t **vram_ptr);
-void GPUupdateLace(void);
long GPUopen(unsigned long *disp, char *cap, char *cfg);
long GPUclose(void);
void GPUvBlank(int is_vblank, int lcf);