cdrom: handle old savestates better
[pcsx_rearmed.git] / libpcsxcore / cdrom.c
index ab56734..b686855 100644 (file)
  *   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.
 */
 
@@ -205,7 +205,7 @@ static void sec2msf(unsigned int s, u8 *msf) {
                cdr.Reading = 0; \
                psxRegs.interrupt &= ~(1 << PSXINT_CDREAD); \
        } \
-       cdr.StatP &= ~STATUS_READ;\
+       cdr.StatP &= ~(STATUS_READ|STATUS_SEEK);\
 }
 
 #define StopCdda() { \
@@ -492,7 +492,10 @@ void cdrPlayInterrupt()
                        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;
@@ -574,12 +577,17 @@ void cdrInterrupt() {
                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!!)
@@ -669,6 +677,18 @@ void cdrInterrupt() {
                        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;
@@ -715,12 +735,16 @@ void cdrInterrupt() {
                        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:
@@ -789,6 +813,8 @@ void cdrInterrupt() {
 
                case CdlSeekL:
                case CdlSeekP:
+                       StopCdda();
+                       StopReading();
                        cdr.StatP |= STATUS_SEEK;
 
                        /*
@@ -881,12 +907,22 @@ void cdrInterrupt() {
 
                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
@@ -1037,7 +1073,7 @@ void cdrReadInterrupt() {
        cdr.Result[0] = cdr.StatP;
        cdr.Seeked = SEEK_DONE;
 
-       ReadTrack(cdr.SetSector);
+       ReadTrack(cdr.SetSectorPlay);
 
        buf = CDR_getBuffer();
        if (buf == NULL)
@@ -1078,13 +1114,13 @@ void cdrReadInterrupt() {
                }
        }
 
-       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]++;
                }
        }
 
@@ -1104,7 +1140,7 @@ void cdrReadInterrupt() {
        }
 
        // update for CdlGetlocP
-       ReadTrack(cdr.SetSector);
+       ReadTrack(cdr.SetSectorPlay);
 }
 
 /*
@@ -1194,87 +1230,23 @@ void cdrWrite1(unsigned char rt) {
        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;
@@ -1286,28 +1258,6 @@ void cdrWrite1(unsigned char rt) {
                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]);
 
@@ -1318,32 +1268,6 @@ void cdrWrite1(unsigned char rt) {
                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;
        }
 }
 
@@ -1536,6 +1460,7 @@ void cdrReset() {
        cdr.Reg2 = 0x1f;
        cdr.Stat = NoIntr;
        cdr.DriveState = DRIVESTATE_STANDBY;
+       cdr.StatP = STATUS_ROTATING;
        pTransfer = cdr.Transfer;
 
        // BIOS player - default values
@@ -1554,7 +1479,7 @@ int cdrFreeze(void *f, int Mode) {
        if (Mode == 0 && !Config.Cdda)
                CDR_stop();
        
-       cdr.freeze_ver = 0x63647201;
+       cdr.freeze_ver = 0x63647202;
        gzfreeze(&cdr, sizeof(cdr));
        
        if (Mode == 1) {
@@ -1575,6 +1500,9 @@ int cdrFreeze(void *f, int Mode) {
                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);
@@ -1586,6 +1514,12 @@ int cdrFreeze(void *f, int Mode) {
                                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;
+                       }
                }
        }