static unsigned char *pTransfer;
/* CD-ROM magic numbers */
-#define CdlSync 0
+#define CdlSync 0 /* nocash documentation : "Uh, actually, returns error code 40h = Invalid Command...?" */
#define CdlNop 1
#define CdlSetloc 2
#define CdlPlay 3
#define CdlStandby 7
#define CdlStop 8
#define CdlPause 9
-#define CdlInit 10
+#define CdlReset 10
#define CdlMute 11
#define CdlDemute 12
#define CdlSetfilter 13
#define CdlSetmode 14
-#define CdlGetmode 15
+#define CdlGetparam 15
#define CdlGetlocL 16
#define CdlGetlocP 17
#define CdlReadT 18
#define CdlTest 25
#define CdlID 26
#define CdlReadS 27
-#define CdlReset 28
+#define CdlInit 28
#define CdlGetQ 29
#define CdlReadToc 30
char *CmdName[0x100]= {
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby",
- "CdlStop", "CdlPause", "CdlInit", "CdlMute",
- "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode",
+ "CdlStop", "CdlPause", "CdlReset", "CdlMute",
+ "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetparam",
"CdlGetlocL", "CdlGetlocP", "CdlReadT", "CdlGetTN",
"CdlGetTD", "CdlSeekL", "CdlSeekP", "CdlSetclock",
"CdlGetclock", "CdlTest", "CdlID", "CdlReadS",
- "CdlReset", NULL, "CDlReadToc", NULL
+ "CdlInit", NULL, "CDlReadToc", NULL
};
unsigned char Test04[] = { 0 };
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" );
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];
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;
cdr.Irq = 0;
switch (Irq) {
- case CdlSync:
- // TOOD: sometimes/always return error?
- break;
-
case CdlNop:
if (cdr.DriveState != DRIVESTATE_LID_OPEN)
cdr.StatP &= ~STATUS_SHELLOPEN;
InuYasha - Feudal Fairy Tale: slower
- Fixes battles
*/
- AddIrqQueue(CdlPause + 0x100, cdReadTime * 3);
+ /* Gameblabla - Tightening the timings (as taken from Duckstation).
+ * The timings from Duckstation are based upon hardware tests.
+ * Mednafen's timing don't work for Gundam Battle Assault 2 in PAL/50hz mode,
+ * seems to be timing sensitive as it can depend on the CPU's clock speed.
+ * */
+ if (cdr.DriveState != DRIVESTATE_STANDBY)
+ {
+ delay = 7000;
+ }
+ else
+ {
+ delay = (((cdr.Mode & MODE_SPEED) ? 2 : 1) * (1000000));
+ CDRMISC_INT((cdr.Mode & MODE_SPEED) ? cdReadTime / 2 : cdReadTime);
+ }
+ AddIrqQueue(CdlPause + 0x100, delay);
cdr.Ctrl |= 0x80;
break;
cdr.Stat = Complete;
break;
- case CdlInit:
- AddIrqQueue(CdlInit + 0x100, cdReadTime * 6);
+ case CdlReset:
+ cdr.Muted = FALSE;
+ cdr.Mode = 0x20; /* This fixes This is Football 2, Pooh's Party lockups */
+ AddIrqQueue(CdlReset + 0x100, 4100000);
no_busy_error = 1;
start_rotating = 1;
break;
- case CdlInit + 0x100:
+ case CdlReset + 0x100:
cdr.Stat = Complete;
break;
no_busy_error = 1;
break;
- case CdlGetmode:
- SetResultSize(6);
+ case CdlGetparam:
+ /* Gameblabla : According to mednafen, Result size should be 5 and done this way. */
+ SetResultSize(5);
cdr.Result[1] = cdr.Mode;
- cdr.Result[2] = cdr.File;
- cdr.Result[3] = cdr.Channel;
- cdr.Result[4] = 0;
- cdr.Result[5] = 0;
+ cdr.Result[2] = 0;
+ cdr.Result[3] = cdr.File;
+ cdr.Result[4] = cdr.Channel;
no_busy_error = 1;
break;
cdr.Result[0] = cdr.StatP;
cdr.Result[1] = itob(cdr.ResultTD[2]);
cdr.Result[2] = itob(cdr.ResultTD[1]);
- cdr.Result[3] = itob(cdr.ResultTD[0]);
+ /* According to Nocash's documentation, the function doesn't care about ff.
+ * This can be seen also in Mednafen's implementation. */
+ //cdr.Result[3] = itob(cdr.ResultTD[0]);
}
break;
cdr.Stat = Complete;
break;
- case CdlReset:
+ case CdlInit:
// yes, it really sets STATUS_SHELLOPEN
cdr.StatP |= STATUS_SHELLOPEN;
cdr.DriveState = DRIVESTATE_RESCAN_CD;
break;
case CdlGetQ:
- // TODO?
- CDR_LOG_I("got CdlGetQ\n");
+ no_busy_error = 1;
break;
case CdlReadToc:
cdr.Result[0] = cdr.StatP;
start_rotating = 1;
break;
-
+ case CdlSync:
default:
CDR_LOG_I("Invalid command: %02x\n", Irq);
error = ERROR_INVALIDCMD;
switch (cdr.Cmd) {
case CdlSetloc:
- for (i = 0; i < 3; i++)
- set_loc[i] = btoi(cdr.Param[i]);
+ CDR_LOG("CDROM setloc command (%02X, %02X, %02X)\n", cdr.Param[0], cdr.Param[1], cdr.Param[2]);
- i = msf2sec(cdr.SetSectorPlay);
- i = abs(i - msf2sec(set_loc));
- if (i > 16)
- cdr.Seeked = SEEK_PENDING;
+ // MM must be BCD, SS must be BCD and <0x60, FF must be BCD and <0x75
+ if (((cdr.Param[0] & 0x0F) > 0x09) || (cdr.Param[0] > 0x99) || ((cdr.Param[1] & 0x0F) > 0x09) || (cdr.Param[1] >= 0x60) || ((cdr.Param[2] & 0x0F) > 0x09) || (cdr.Param[2] >= 0x75))
+ {
+ CDR_LOG("Invalid/out of range seek to %02X:%02X:%02X\n", cdr.Param[0], cdr.Param[1], cdr.Param[2]);
+ }
+ else
+ {
+ for (i = 0; i < 3; i++)
+ {
+ set_loc[i] = btoi(cdr.Param[i]);
+ }
+
+ i = msf2sec(cdr.SetSectorPlay);
+ i = abs(i - msf2sec(set_loc));
+ if (i > 16)
+ cdr.Seeked = SEEK_PENDING;
- memcpy(cdr.SetSector, set_loc, 3);
- cdr.SetSector[3] = 0;
- cdr.SetlocPending = 1;
+ memcpy(cdr.SetSector, set_loc, 3);
+ cdr.SetSector[3] = 0;
+ cdr.SetlocPending = 1;
+ }
break;
case CdlReadN:
StopReading();
break;
- case CdlReset:
case CdlInit:
+ case CdlReset:
cdr.Seeked = SEEK_DONE;
StopCdda();
StopReading();