* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
-/*
+/*
* Handles all CD-ROM registers and functions.
*/
#include "cdrom.h"
#include "ppf.h"
#include "psxdma.h"
+#include "arm_features.h"
/* logging */
#if 0
#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;
+ }
Find_CurTrack(cdr.SetSectorPlay);
ReadTrack(cdr.SetSectorPlay);
cdr.TrackChanged = FALSE;
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;
+ }
// BIOS CD Player
// - Pause player, hit Track 01/02/../xx (Setloc issued!!)
break;
case CdlStop:
+ if (cdr.Play) {
+ // grab time for current track
+ CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
+
+ cdr.SetSectorPlay[0] = cdr.ResultTD[2];
+ cdr.SetSectorPlay[1] = cdr.ResultTD[1];
+ cdr.SetSectorPlay[2] = cdr.ResultTD[0];
+ }
+
+ StopCdda();
+ StopReading();
+
delay = 0x800;
if (cdr.DriveState == DRIVESTATE_STANDBY)
delay = cdReadTime * 30 / 2;
break;
case CdlMute:
+ cdr.Muted = TRUE;
break;
case CdlDemute:
+ cdr.Muted = FALSE;
break;
case CdlSetfilter:
+ cdr.File = cdr.Param[0];
+ cdr.Channel = cdr.Param[1];
break;
case CdlSetmode:
case CdlSeekL:
case CdlSeekP:
+ StopCdda();
+ StopReading();
cdr.StatP |= STATUS_SEEK;
/*
case CdlReadN:
case CdlReadS:
- if (!cdr.Reading) return;
+ if (cdr.SetlocPending) {
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
+ cdr.SetlocPending = 0;
+ }
+ 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
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.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]++;
}
}
}
// update for CdlGetlocP
- ReadTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSectorPlay);
}
/*
AddIrqQueue(cdr.Cmd, 0x800);
switch (cdr.Cmd) {
- case CdlSync:
- case CdlNop:
- case CdlForward:
- case CdlBackward:
- case CdlReadT:
- case CdlTest:
- case CdlID:
- case CdlReadToc:
- case CdlGetmode:
- case CdlGetlocL:
- case CdlGetlocP:
- case CdlGetTD:
- break;
-
case CdlSetloc:
- StopReading();
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;
- break;
-
- case CdlPlay:
- // Vib Ribbon: try same track again
- StopCdda();
-
- // Vib Ribbon - decoded buffer IRQ for CDDA reading
- // - fixes ribbon timing + music CD mode
- //CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
-
- cdr.Play = TRUE;
-
- cdr.StatP |= STATUS_SEEK;
- cdr.StatP &= ~STATUS_ROTATING;
+ cdr.SetlocPending = 1;
break;
case CdlReadN:
- StopReading();
- cdr.Reading = 1;
- cdr.FirstSector = 1;
- cdr.Readed = 0xff;
- break;
-
- case CdlStandby:
- StopCdda();
- StopReading();
- break;
-
- case CdlStop:
- // GameShark CD Player: Reset CDDA to track start
- if (cdr.Play) {
- // grab time for current track
- CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
-
- cdr.SetSectorPlay[0] = cdr.ResultTD[2];
- cdr.SetSectorPlay[1] = cdr.ResultTD[1];
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
- }
-
- StopCdda();
- StopReading();
- break;
-
+ case CdlReadS:
case CdlPause:
- /*
- GameShark CD Player: save time for resume
-
- Twisted Metal - World Tour: don't mix Setloc / CdlPlay cursors
- */
-
StopCdda();
StopReading();
break;
StopReading();
break;
- case CdlMute:
- cdr.Muted = TRUE;
- // Duke Nukem - Time to Kill
- // - do not directly set cd-xa volume
- //SPU_writeRegister( H_CDLeft, 0x0000 );
- //SPU_writeRegister( H_CDRight, 0x0000 );
- break;
-
- case CdlDemute:
- cdr.Muted = FALSE;
-
- // Duke Nukem - Time to Kill
- // - do not directly set cd-xa volume
- //SPU_writeRegister( H_CDLeft, 0x7f00 );
- //SPU_writeRegister( H_CDRight, 0x7f00 );
- break;
-
- case CdlSetfilter:
- cdr.File = cdr.Param[0];
- cdr.Channel = cdr.Param[1];
- break;
-
case CdlSetmode:
CDR_LOG("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]);
if( cdr.Play && (cdr.Mode & MODE_CDDA) == 0 )
StopCdda();
break;
-
- case CdlGetTN:
- //AddIrqQueue(cdr.Cmd, 0x800);
-
- // GameShark CDX CD Player: very long time
- AddIrqQueue(cdr.Cmd, 0x100000);
- break;
-
- case CdlSeekL:
- case CdlSeekP:
- // Tomb Raider 2 - reset cdda
- StopCdda();
- StopReading();
- break;
-
- case CdlReadS:
- StopReading();
- cdr.Reading = 2;
- cdr.FirstSector = 1;
- cdr.Readed = 0xff;
- break;
-
- default:
- cdr.ParamC = 0;
- CDR_LOG_I("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
- return;
}
}
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.Reg2 = 0x1f;
cdr.Stat = NoIntr;
cdr.DriveState = DRIVESTATE_STANDBY;
+ cdr.StatP = STATUS_ROTATING;
pTransfer = cdr.Transfer;
// BIOS player - default values
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;
+ }
}
}