diff --git a/Src/CPU/PowerPC/ppc.cpp b/Src/CPU/PowerPC/ppc.cpp index d5501dd..ed8fdf5 100644 --- a/Src/CPU/PowerPC/ppc.cpp +++ b/Src/CPU/PowerPC/ppc.cpp @@ -155,8 +155,8 @@ static UINT32 ppc_field_xlat[256]; #define TSR_ENW 0x80000000 #define TSR_WIS 0x40000000 -#define BYTE_REVERSE16(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00)) -#define BYTE_REVERSE32(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000)) +#define BYTE_REVERSE16(x) (((x >> 8) | (x << 8)) & 0xFFFF) +#define BYTE_REVERSE32(x) ((x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24)) typedef union { UINT64 id; diff --git a/Src/Model3/DSB.cpp b/Src/Model3/DSB.cpp index 78f001b..6202007 100644 --- a/Src/Model3/DSB.cpp +++ b/Src/Model3/DSB.cpp @@ -669,6 +669,10 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte) else if (byte == 0x74 || byte == 0x75) // "start play" { + usingLoopStart = 0; + usingLoopEnd = 0; + usingMPEGStart = mpegStart; + usingMPEGEnd = mpegEnd; MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart); printf("playing %X\n", mpegStart); mpegState = ST_IDLE; @@ -715,7 +719,9 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte) if (playing) { printf("Setting loop point to %x\n", mpegStart); - MPEG_SetLoop((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart); + usingLoopStart = mpegStart; + usingLoopEnd = mpegEnd-mpegStart; + MPEG_SetLoop((const char *) &mpegROM[usingLoopStart], usingLoopEnd); } printf("mpegStart=%x\n", mpegStart); @@ -751,6 +757,10 @@ void CDSB2::WriteMPEGFIFO(UINT8 byte) mpegState = ST_IDLE; if (byte == 0x75) { + usingLoopStart = 0; + usingLoopEnd = 0; + usingMPEGStart = mpegStart; + usingMPEGEnd = mpegEnd; MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart); printf("playing %X (from st_gota4)\n", mpegStart); playing = 1; @@ -991,10 +1001,77 @@ void CDSB2::Reset(void) void CDSB2::SaveState(CBlockFile *StateFile) { + UINT32 mpegPos; + UINT8 isPlaying; + + StateFile->NewBlock("DSB2", __FILE__); + + // MPEG playback state + isPlaying = (UINT8) MPEG_IsPlaying(); + mpegPos = MPEG_GetProgress(); + StateFile->Write(&isPlaying, sizeof(isPlaying)); + StateFile->Write(&mpegPos, sizeof(mpegPos)); + StateFile->Write(&usingMPEGStart, sizeof(usingMPEGStart)); + StateFile->Write(&usingMPEGEnd, sizeof(usingMPEGEnd)); + StateFile->Write(&usingLoopStart, sizeof(usingLoopStart)); + StateFile->Write(&usingLoopEnd, sizeof(usingLoopEnd)); + + // MPEG board state + StateFile->Write(ram, 0x20000); + StateFile->Write(fifo, sizeof(fifo)); + StateFile->Write(&fifoIdxR, sizeof(fifoIdxR)); + StateFile->Write(&fifoIdxW, sizeof(fifoIdxW)); + StateFile->Write(&cmdLatch, sizeof(cmdLatch)); + StateFile->Write(&mpegState, sizeof(mpegState)); + StateFile->Write(&mpegStart, sizeof(mpegStart)); + StateFile->Write(&mpegEnd, sizeof(mpegEnd)); + StateFile->Write(&playing, sizeof(playing)); + StateFile->Write(volume, sizeof(volume)); + + // 68K CPU state + M68KSaveState(StateFile, "DSB2 68K"); } void CDSB2::LoadState(CBlockFile *StateFile) { + UINT32 mpegPos; + UINT8 isPlaying; + + if (OKAY != StateFile->FindBlock("DSB2")) + { + ErrorLog("Unable to load Digital Sound Board state. Save state file is corrupted."); + return; + } + + StateFile->Read(&isPlaying, sizeof(isPlaying)); + StateFile->Read(&mpegPos, sizeof(mpegPos)); + StateFile->Read(&usingMPEGStart, sizeof(usingMPEGStart)); + StateFile->Read(&usingMPEGEnd, sizeof(usingMPEGEnd)); + StateFile->Read(&usingLoopStart, sizeof(usingLoopStart)); + StateFile->Read(&usingLoopEnd, sizeof(usingLoopEnd)); + + StateFile->Read(ram, 0x20000); + StateFile->Read(fifo, sizeof(fifo)); + StateFile->Read(&fifoIdxR, sizeof(fifoIdxR)); + StateFile->Read(&fifoIdxW, sizeof(fifoIdxW)); + StateFile->Read(&cmdLatch, sizeof(cmdLatch)); + StateFile->Read(&mpegState, sizeof(mpegState)); + StateFile->Read(&mpegStart, sizeof(mpegStart)); + StateFile->Read(&mpegEnd, sizeof(mpegEnd)); + StateFile->Read(&playing, sizeof(playing)); + StateFile->Read(volume, sizeof(volume)); + + M68KLoadState(StateFile, "DSB2 68K"); + + // Restart MPEG audio at the appropriate position + if (isPlaying) + { + MPEG_PlayMemory((const char *) &mpegROM[usingMPEGStart], usingMPEGEnd-usingMPEGStart); + MPEG_SetLoop((const char *) &mpegROM[usingLoopStart], usingLoopEnd); + MPEG_SetOffset(mpegPos); + } + else + MPEG_StopPlaying(); } // Offsets of memory regions within DSB2's pool diff --git a/Src/Model3/DSB.h b/Src/Model3/DSB.h index 3a992cd..86bf725 100644 --- a/Src/Model3/DSB.h +++ b/Src/Model3/DSB.h @@ -264,10 +264,10 @@ private: INT16 *mpegL, *mpegR; // DSB memory - const UINT8 *progROM; // Z80 program ROM (passed in from parent object) + const UINT8 *progROM; // 68K program ROM (passed in from parent object) const UINT8 *mpegROM; // MPEG music ROM UINT8 *memoryPool; // all memory allocated here - UINT8 *ram; // Z80 RAM + UINT8 *ram; // 68K RAM // Command FIFO UINT8 fifo[128]; @@ -280,6 +280,12 @@ private: int mpegStart, mpegEnd, playing; UINT8 volume[2]; // left, right volume (0x00-0xFF) + // Settings of currently playing stream (may not match the playback register variables above) + UINT32 usingLoopStart; // what was last set by MPEG_SetLoop() or MPEG_PlayMemory() + UINT32 usingLoopEnd; + UINT32 usingMPEGStart; // what was last set by MPEG_PlayMemory() + UINT32 usingMPEGEnd; + // M68K CPU M68KCtx M68K; };