From: notaz <notasas@gmail.com>
Date: Mon, 9 Oct 2023 21:39:57 +0000 (+0300)
Subject: add a nasty hack for gpu busy timing
X-Git-Tag: r24l~140
X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=55ff71307db44c3122500104b83c21273853025c;p=pcsx_rearmed.git

add a nasty hack for gpu busy timing

with a hope to remove it someday
notaz/pcsx_rearmed#225
---

diff --git a/libpcsxcore/database.c b/libpcsxcore/database.c
index dc3144cf..481be6d3 100644
--- a/libpcsxcore/database.c
+++ b/libpcsxcore/database.c
@@ -36,6 +36,12 @@ static const char * const gpu_slow_llist_db[] =
 	"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) }
 
@@ -50,6 +56,7 @@ hack_db[] =
 {
 	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
diff --git a/libpcsxcore/new_dynarec/pcsxmem.c b/libpcsxcore/new_dynarec/pcsxmem.c
index fc19494e..f4b1d90e 100644
--- a/libpcsxcore/new_dynarec/pcsxmem.c
+++ b/libpcsxcore/new_dynarec/pcsxmem.c
@@ -218,27 +218,6 @@ static void io_spu_write32(u32 value)
 	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;
@@ -385,7 +364,7 @@ void new_dyna_pcsx_mem_init(void)
 	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);
 
@@ -438,7 +417,7 @@ void new_dyna_pcsx_mem_init(void)
 	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);
 
@@ -489,6 +468,10 @@ void new_dyna_pcsx_mem_reset(void)
 	// 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)
diff --git a/libpcsxcore/psxcommon.h b/libpcsxcore/psxcommon.h
index 4c78255e..f978a583 100644
--- a/libpcsxcore/psxcommon.h
+++ b/libpcsxcore/psxcommon.h
@@ -150,6 +150,7 @@ typedef struct {
 	struct {
 		boolean cdr_read_timing;
 		boolean gpu_slow_list_walking;
+		boolean gpu_busy_hack;
 	} hacks;
 } PcsxConfig;
 
diff --git a/libpcsxcore/psxhw.c b/libpcsxcore/psxhw.c
index 60ff6c4c..254693e1 100644
--- a/libpcsxcore/psxhw.c
+++ b/libpcsxcore/psxhw.c
@@ -32,6 +32,8 @@
 #define PAD_LOG(...)
 #endif
 
+static u32 (*psxHwReadGpuSRptr)(void) = psxHwReadGpuSR;
+
 void psxHwReset() {
 	memset(psxH, 0, 0x10000);
 
@@ -39,6 +41,8 @@ void psxHwReset() {
 	cdrReset();
 	psxRcntInit();
 	HW_GPU_STATUS = SWAP32(0x14802000);
+	psxHwReadGpuSRptr = Config.hacks.gpu_busy_hack
+		? psxHwReadGpuSRbusyHack : psxHwReadGpuSR;
 }
 
 void psxHwWriteIstat(u32 value)
@@ -78,6 +82,39 @@ void psxHwWriteDmaIcr32(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;
 
@@ -302,10 +339,7 @@ u32 psxHwRead32(u32 add) {
 #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
@@ -771,8 +805,7 @@ void psxHwWrite32(u32 add, u32 value) {
 #ifdef PSXHW_LOG
 			PSXHW_LOG("GPU STATUS 32bit write %x\n", value);
 #endif
-			GPU_writeStatus(value);
-			gpuSyncPluginSR();
+			psxHwWriteGpuSR(value);
 			return;
 
 		case 0x1f801820:
diff --git a/libpcsxcore/psxhw.h b/libpcsxcore/psxhw.h
index 2bde9edc..91256ce3 100644
--- a/libpcsxcore/psxhw.h
+++ b/libpcsxcore/psxhw.h
@@ -85,6 +85,9 @@ int psxHwFreeze(void *f, int Mode);
 void psxHwWriteIstat(u32 value);
 void psxHwWriteImask(u32 value);
 void psxHwWriteDmaIcr32(u32 value);
+void psxHwWriteGpuSR(u32 value);
+u32  psxHwReadGpuSR(void);
+u32  psxHwReadGpuSRbusyHack(void);
 
 #ifdef __cplusplus
 }