From bf4df3ba5781db5600f1ffb3c34e4d76ef490474 Mon Sep 17 00:00:00 2001
From: gameblabla <gameblabla@users.noreply.github.com>
Date: Mon, 30 Aug 2021 22:34:02 +0000
Subject: [PATCH] Implement fix from Mednafen for Fantastic Pinball Kyuutenkai.
 (#206)

This is taken from the way Mednafen implemented it.
https://github.com/libretro-mirrors/mednafen-git/blob/563b72e377fa8284559df4df0271108d4935c9f1/src/psx/cdc.cpp#L941

This properly fixes the freeze issue in Fantastic Pinball Kyuutenkai.
---
 libpcsxcore/cdrom.c | 20 ++++++++++++++++++--
 libpcsxcore/cdrom.h |  4 ++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c
index 72361798..4e312fd6 100644
--- a/libpcsxcore/cdrom.c
+++ b/libpcsxcore/cdrom.c
@@ -431,6 +431,11 @@ static void AddIrqQueue(unsigned short irq, unsigned long ecycle) {
 
 static void cdrPlayInterrupt_Autopause()
 {
+	u32 abs_lev_max = 0;
+	boolean abs_lev_chselect;
+	u32 i;
+	s16 read_buf[CD_FRAMESIZE_RAW/2];
+	
 	if ((cdr.Mode & MODE_AUTOPAUSE) && cdr.TrackChanged) {
 		CDR_LOG( "CDDA STOP\n" );
 
@@ -446,10 +451,21 @@ static void cdrPlayInterrupt_Autopause()
 		StopCdda();
 	}
 	else if (cdr.Mode & MODE_REPORT) {
+		CDR_readCDDA(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], (u8 *)read_buf);
 
 		cdr.Result[0] = cdr.StatP;
 		cdr.Result[1] = cdr.subq.Track;
 		cdr.Result[2] = cdr.subq.Index;
+		
+		abs_lev_chselect = cdr.subq.Absolute[1] & 0x01;
+		
+		/* 8 is a hack. For accuracy, it should be 588. */
+		for (i = 0; i < 8; i++)
+		{
+			abs_lev_max = MAX_VALUE(abs_lev_max, abs(read_buf[i * 2 + abs_lev_chselect]));
+		}
+		abs_lev_max = MIN_VALUE(abs_lev_max, 32767);
+		abs_lev_max |= abs_lev_chselect << 15;
 
 		if (cdr.subq.Absolute[2] & 0x10) {
 			cdr.Result[3] = cdr.subq.Relative[0];
@@ -462,8 +478,8 @@ static void cdrPlayInterrupt_Autopause()
 			cdr.Result[5] = cdr.subq.Absolute[2];
 		}
 
-		cdr.Result[6] = 0;
-		cdr.Result[7] = 0;
+		cdr.Result[6] = abs_lev_max >> 0;
+		cdr.Result[7] = abs_lev_max >> 8;
 
 		// Rayman: Logo freeze (resultready + dataready)
 		cdr.ResultReady = 1;
diff --git a/libpcsxcore/cdrom.h b/libpcsxcore/cdrom.h
index a37f6baf..860930b1 100644
--- a/libpcsxcore/cdrom.h
+++ b/libpcsxcore/cdrom.h
@@ -34,6 +34,10 @@ extern "C" {
 #define btoi(b)     ((b) / 16 * 10 + (b) % 16) /* BCD to u_char */
 #define itob(i)     ((i) / 10 * 16 + (i) % 10) /* u_char to BCD */
 
+#define ABS_CD(x) ((x >= 0) ? x : -x)
+#define MIN_VALUE(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
+#define MAX_VALUE(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
+
 #define MSF2SECT(m, s, f)		(((m) * 60 + (s) - 2) * 75 + (f))
 
 #define CD_FRAMESIZE_RAW		2352
-- 
2.39.5