#include "cdrom.h"
#include "ppf.h"
#include "psxdma.h"
+#include "arm_features.h"
/* logging */
#if 0
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 STATUS_ERROR (1<<0) // 0x01
/* Errors */
-#define ERROR_NOT_READY (1<<7) // 0x80
+#define ERROR_NOTREADY (1<<7) // 0x80
#define ERROR_INVALIDCMD (1<<6) // 0x40
#define ERROR_INVALIDARG (1<<5) // 0x20
cdr.Reading = 0; \
psxRegs.interrupt &= ~(1 << PSXINT_CDREAD); \
} \
- cdr.StatP &= ~STATUS_READ;\
+ cdr.StatP &= ~(STATUS_READ|STATUS_SEEK);\
}
#define StopCdda() { \
setIrq();
}
- memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
+ if (cdr.SetlocPending) {
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
+ cdr.SetlocPending = 0;
+ cdr.m_locationChanged = TRUE;
+ }
Find_CurTrack(cdr.SetSectorPlay);
ReadTrack(cdr.SetSectorPlay);
cdr.TrackChanged = FALSE;
}
}
- CDRMISC_INT(cdReadTime);
+ if (cdr.m_locationChanged)
+ {
+ CDRMISC_INT(cdReadTime * 30);
+ cdr.m_locationChanged = FALSE;
+ }
+ else
+ {
+ CDRMISC_INT(cdReadTime);
+ }
// update for CdlGetlocP/autopause
generate_subq(cdr.SetSectorPlay);
int start_rotating = 0;
int error = 0;
int delay;
+ unsigned int seekTime = 0;
// Reschedule IRQ
if (cdr.Stat) {
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;
case CdlSetloc:
break;
+ do_CdlPlay:
case CdlPlay:
StopCdda();
if (cdr.Seeked == SEEK_PENDING) {
// XXX: wrong, should seek instead..
- memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 );
cdr.Seeked = SEEK_DONE;
}
+ if (cdr.SetlocPending) {
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
+ cdr.SetlocPending = 0;
+ cdr.m_locationChanged = TRUE;
+ }
// BIOS CD Player
// - Pause player, hit Track 01/02/../xx (Setloc issued!!)
case CdlReadN:
case CdlReadS:
+ if (cdr.SetlocPending) {
+ seekTime = abs(msf2sec(cdr.SetSectorPlay) - msf2sec(cdr.SetSector)) * (cdReadTime / 200);
+ if(seekTime > 1000000) seekTime = 1000000;
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
+ cdr.SetlocPending = 0;
+ cdr.m_locationChanged = TRUE;
+ }
+ Find_CurTrack(cdr.SetSectorPlay);
+
+ if ((cdr.Mode & MODE_CDDA) && cdr.CurTrack > 1)
+ // Read* acts as play for cdda tracks in cdda mode
+ goto do_CdlPlay;
+
cdr.Reading = 1;
cdr.FirstSector = 1;
// Fighting Force 2 - update subq time immediately
// - fixes new game
- Find_CurTrack(cdr.SetSector);
- ReadTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSectorPlay);
// Crusaders of Might and Magic - update getlocl now
// - fix cutscene speech (startup)
// ??? - use more accurate seek time later
- CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1);
+ CDREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1) + seekTime);
} else {
cdr.StatP |= STATUS_READ;
cdr.StatP &= ~STATUS_SEEK;
cdr.Result[0] = cdr.StatP;
start_rotating = 1;
break;
-
+ case CdlSync:
default:
CDR_LOG_I("Invalid command: %02x\n", Irq);
error = ERROR_INVALIDCMD;
case DRIVESTATE_PREPARE_CD:
SetResultSize(2);
cdr.Result[0] = cdr.StatP | STATUS_ERROR;
- cdr.Result[1] = ERROR_NOT_READY;
+ cdr.Result[1] = ERROR_NOTREADY;
cdr.Stat = DiskError;
break;
}
#endif
}
-#ifdef __ARM_ARCH_7A__
+#ifdef HAVE_ARMV7
#define ssat32_to_16(v) \
asm("ssat %0,#16,%1" : "=r" (v) : "r" (v))
#else
cdr.Result[0] = cdr.StatP;
cdr.Seeked = SEEK_DONE;
- ReadTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSectorPlay);
buf = CDR_getBuffer();
if (buf == NULL)
cdr.Channel = cdr.Transfer[4 + 1];
}
+ /* Gameblabla
+ * Skips playing on channel 255.
+ * Fixes missing audio in Blue's Clues : Blue's Big Musical. (Should also fix Taxi 2)
+ * TODO : Check if this is the proper behaviour.
+ * */
if((cdr.Transfer[4 + 2] & 0x4) &&
(cdr.Transfer[4 + 1] == cdr.Channel) &&
- (cdr.Transfer[4 + 0] == cdr.File)) {
+ (cdr.Transfer[4 + 0] == cdr.File) && cdr.Channel != 255) {
int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
if (!ret) {
cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo);
}
}
- cdr.SetSector[2]++;
- if (cdr.SetSector[2] == 75) {
- cdr.SetSector[2] = 0;
- cdr.SetSector[1]++;
- if (cdr.SetSector[1] == 60) {
- cdr.SetSector[1] = 0;
- cdr.SetSector[0]++;
+ cdr.SetSectorPlay[2]++;
+ if (cdr.SetSectorPlay[2] == 75) {
+ cdr.SetSectorPlay[2] = 0;
+ cdr.SetSectorPlay[1]++;
+ if (cdr.SetSectorPlay[1] == 60) {
+ cdr.SetSectorPlay[1] = 0;
+ cdr.SetSectorPlay[0]++;
}
}
cdr.Readed = 0;
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
+ uint32_t delay = (cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime;
+ if (cdr.m_locationChanged) {
+ CDREAD_INT(delay * 30);
+ cdr.m_locationChanged = FALSE;
+ } else {
+ CDREAD_INT(delay);
+ }
/*
Croc 2: $40 - only FORM1 (*)
}
// update for CdlGetlocP
- ReadTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSectorPlay);
}
/*
for (i = 0; i < 3; i++)
set_loc[i] = btoi(cdr.Param[i]);
- // FIXME: clean up this SetSector/SetSectorPlay mess,
- // there should be single var tracking current sector pos
- if (cdr.Play)
- i = msf2sec(cdr.SetSectorPlay);
- else
- i = msf2sec(cdr.SetSector);
+ 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;
break;
case CdlReadN:
psxCpu->Clear(madr, cdsize / 4);
pTransfer += cdsize;
-
- // burst vs normal
if( chcr == 0x11400100 ) {
+ HW_DMA3_MADR = SWAPu32(madr + cdsize);
CDRDMA_INT( (cdsize/4) / 4 );
}
else if( chcr == 0x11000000 ) {
- CDRDMA_INT( (cdsize/4) * 1 );
+ // CDRDMA_INT( (cdsize/4) * 1 );
+ // halted
+ psxRegs.cycle += (cdsize/4) * 24/2;
+ CDRDMA_INT(16);
}
return;
cdr.DriveState = DRIVESTATE_STANDBY;
cdr.StatP = STATUS_ROTATING;
pTransfer = cdr.Transfer;
+ cdr.SetlocPending = 0;
+ cdr.m_locationChanged = FALSE;
// BIOS player - default values
cdr.AttenuatorLeftToLeft = 0x80;
if (Mode == 0 && !Config.Cdda)
CDR_stop();
- cdr.freeze_ver = 0x63647201;
+ cdr.freeze_ver = 0x63647202;
gzfreeze(&cdr, sizeof(cdr));
if (Mode == 1) {
pTransfer = cdr.Transfer + tmp;
// read right sub data
- memcpy(tmpp, cdr.Prev, 3);
+ tmpp[0] = btoi(cdr.Prev[0]);
+ tmpp[1] = btoi(cdr.Prev[1]);
+ tmpp[2] = btoi(cdr.Prev[2]);
cdr.Prev[0]++;
ReadTrack(tmpp);
if (cdr.Play) {
+ if (cdr.freeze_ver < 0x63647202)
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 3);
+
Find_CurTrack(cdr.SetSectorPlay);
if (!Config.Cdda)
CDR_play(cdr.SetSectorPlay);
SysPrintf("cdrom: fixing up old savestate\n");
cdr.Reg2 = 7;
}
+ // also did not save Attenuator..
+ if ((cdr.AttenuatorLeftToLeft | cdr.AttenuatorLeftToRight
+ | cdr.AttenuatorRightToLeft | cdr.AttenuatorRightToRight) == 0)
+ {
+ cdr.AttenuatorLeftToLeft = cdr.AttenuatorRightToRight = 0x80;
+ }
}
}