"SLES02731", "SLPS02477", "SLPS03198", "SLUS01138",
};
+static const char * const gpu_busy_hack_db[] =
+{
+ /* ToHeart (Japan) */
+ "SLPS01919", "SLPS01920",
+};
+
#define HACK_ENTRY(var, list) \
{ #var, &Config.hacks.var, list, ARRAY_SIZE(list) }
{
HACK_ENTRY(cdr_read_timing, cdr_read_hack_db),
HACK_ENTRY(gpu_slow_list_walking, gpu_slow_llist_db),
+ HACK_ENTRY(gpu_busy_hack, gpu_busy_hack_db),
};
static const struct
wfunc(a + 2, value >> 16, psxRegs.cycle);
}
-static u32 io_gpu_read_status(void)
-{
- u32 v;
-
- // meh2, syncing for img bit, might want to avoid it..
- gpuSyncPluginSR();
- v = HW_GPU_STATUS;
-
- // XXX: because of large timeslices can't use hSyncCount, using rough
- // approximization instead. Perhaps better use hcounter code here or something.
- if (hSyncCount < 240 && (HW_GPU_STATUS & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS)
- v |= PSXGPU_LCF & (psxRegs.cycle << 20);
- return v;
-}
-
-static void io_gpu_write_status(u32 value)
-{
- GPU_writeStatus(value);
- gpuSyncPluginSR();
-}
-
void new_dyna_pcsx_mem_isolate(int enable)
{
int i;
map_item(&mem_iortab[IOMEM32(0x1124)], io_rcnt_read_mode2, 1);
map_item(&mem_iortab[IOMEM32(0x1128)], io_rcnt_read_target2, 1);
// map_item(&mem_iortab[IOMEM32(0x1810)], GPU_readData, 1);
- map_item(&mem_iortab[IOMEM32(0x1814)], io_gpu_read_status, 1);
+ map_item(&mem_iortab[IOMEM32(0x1814)], psxHwReadGpuSR, 1);
map_item(&mem_iortab[IOMEM32(0x1820)], mdecRead0, 1);
map_item(&mem_iortab[IOMEM32(0x1824)], mdecRead1, 1);
map_item(&mem_iowtab[IOMEM32(0x1124)], io_rcnt_write_mode2, 1);
map_item(&mem_iowtab[IOMEM32(0x1128)], io_rcnt_write_target2, 1);
// map_item(&mem_iowtab[IOMEM32(0x1810)], GPU_writeData, 1);
- map_item(&mem_iowtab[IOMEM32(0x1814)], io_gpu_write_status, 1);
+ map_item(&mem_iowtab[IOMEM32(0x1814)], psxHwWriteGpuSR, 1);
map_item(&mem_iowtab[IOMEM32(0x1820)], mdecWrite0, 1);
map_item(&mem_iowtab[IOMEM32(0x1824)], mdecWrite1, 1);
// plugins might change so update the pointers
map_item(&mem_iortab[IOMEM32(0x1810)], GPU_readData, 1);
map_item(&mem_iowtab[IOMEM32(0x1810)], GPU_writeData, 1);
+ if (Config.hacks.gpu_busy_hack)
+ map_item(&mem_iortab[IOMEM32(0x1814)], psxHwReadGpuSRbusyHack, 1);
+ else
+ map_item(&mem_iortab[IOMEM32(0x1814)], psxHwReadGpuSR, 1);
}
void new_dyna_pcsx_mem_shutdown(void)
struct {
boolean cdr_read_timing;
boolean gpu_slow_list_walking;
+ boolean gpu_busy_hack;
} hacks;
} PcsxConfig;
#define PAD_LOG(...)
#endif
+static u32 (*psxHwReadGpuSRptr)(void) = psxHwReadGpuSR;
+
void psxHwReset() {
memset(psxH, 0, 0x10000);
cdrReset();
psxRcntInit();
HW_GPU_STATUS = SWAP32(0x14802000);
+ psxHwReadGpuSRptr = Config.hacks.gpu_busy_hack
+ ? psxHwReadGpuSRbusyHack : psxHwReadGpuSR;
}
void psxHwWriteIstat(u32 value)
HW_DMA_ICR = SWAPu32(tmp);
}
+void psxHwWriteGpuSR(u32 value)
+{
+ GPU_writeStatus(value);
+ gpuSyncPluginSR();
+}
+
+u32 psxHwReadGpuSR(void)
+{
+ u32 v;
+
+ // meh2, syncing for img bit, might want to avoid it..
+ gpuSyncPluginSR();
+ v = HW_GPU_STATUS;
+
+ // XXX: because of large timeslices can't use hSyncCount, using rough
+ // approximization instead. Perhaps better use hcounter code here or something.
+ if (hSyncCount < 240 && (HW_GPU_STATUS & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS)
+ v |= PSXGPU_LCF & (psxRegs.cycle << 20);
+ return v;
+}
+
+// a hack due to poor timing of gpu idle bit
+// to get rid of this, GPU draw times, DMAs, cpu timing has to fall within
+// certain timing window or else games like "ToHeart" softlock
+u32 psxHwReadGpuSRbusyHack(void)
+{
+ u32 v = psxHwReadGpuSR();
+ static u32 hack;
+ if (!(hack++ & 3))
+ v &= ~PSXGPU_nBUSY;
+ return v;
+}
+
u8 psxHwRead8(u32 add) {
unsigned char hard;
#endif
return hard;
case 0x1f801814:
- gpuSyncPluginSR();
- hard = SWAP32(HW_GPU_STATUS);
- if (hSyncCount < 240 && (hard & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS)
- hard |= PSXGPU_LCF & (psxRegs.cycle << 20);
+ hard = psxHwReadGpuSRptr();
#ifdef PSXHW_LOG
PSXHW_LOG("GPU STATUS 32bit read %x\n", hard);
#endif
#ifdef PSXHW_LOG
PSXHW_LOG("GPU STATUS 32bit write %x\n", value);
#endif
- GPU_writeStatus(value);
- gpuSyncPluginSR();
+ psxHwWriteGpuSR(value);
return;
case 0x1f801820:
void psxHwWriteIstat(u32 value);
void psxHwWriteImask(u32 value);
void psxHwWriteDmaIcr32(u32 value);
+void psxHwWriteGpuSR(u32 value);
+u32 psxHwReadGpuSR(void);
+u32 psxHwReadGpuSRbusyHack(void);
#ifdef __cplusplus
}