From 7924fed36930cc2fa7ae9882a2e739ae68ba2b25 Mon Sep 17 00:00:00 2001 From: gm-matthew <108370479+gm-matthew@users.noreply.github.com> Date: Wed, 5 Jul 2023 02:45:35 +0100 Subject: [PATCH 1/5] Set soundboard CPU to correct clock speed The 68K on the soundboard is rated at 12 MHz but runs at 11.2896 MHz, which is 256 cycles/sample with a 44100 Hz sample rate. Removed SoundClock and Freq as they are not needed --- Src/Sound/SCSP.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp index 249fd8c..89e2c99 100644 --- a/Src/Sound/SCSP.cpp +++ b/Src/Sound/SCSP.cpp @@ -88,8 +88,6 @@ bool legacySound; // For LegacySound (SCSP DSP) config option. //#define CORRECT_FOR_18BIT_DAC // These globals control the operation of the SCSP, they are no longer extern and are set through SCSP_SetBuffers(). --Bart -static double SoundClock; // Originally titled SysFPS; seems to be for the sound CPU. -static const double Freq = 76; static float* bufferfl; static float* bufferfr; static float* bufferrl; @@ -606,7 +604,6 @@ bool SCSP_Init(const Util::Config::Node &config, int n) s_config = &config; s_multiThreaded = config["MultiThreaded"].ValueAs(); legacySound = config["LegacySoundDSP"].ValueAs(); - SoundClock = Freq; if(n==2) { @@ -1516,7 +1513,7 @@ void SCSP_CpuRunScanline() void SCSP_DoMasterSamples(int nsamples) { - int slice = (int)(12000000. / (SoundClock*nsamples)); // 68K cycles/sample + const int slice = 11289600 / 44100; // 68K runs at 256 cycles/sample static int lastdiff = 0; /* @@ -2130,7 +2127,6 @@ void SCSP_LoadState(CBlockFile *StateFile) void SCSP_SetBuffers(float *leftBufferPtr, float *rightBufferPtr, float* leftRearBufferPtr, float* rightRearBufferPtr, int bufferLength) { - SoundClock = Freq; bufferfl = leftBufferPtr; bufferfr = rightBufferPtr; bufferrl = leftRearBufferPtr; From b2fee4242cd061a55e8f3bb2f6dfafbf9f87403f Mon Sep 17 00:00:00 2001 From: gm-matthew <108370479+gm-matthew@users.noreply.github.com> Date: Sat, 19 Aug 2023 23:47:00 +0100 Subject: [PATCH 2/5] DMA device register always returns Step 1.x PCI ID Step 2.x games by AM3 request PCI ID this way and expect to see 0x16c311db --- Src/Model3/Model3.cpp | 7 +------ Src/Model3/Real3D.cpp | 15 ++++++++------- Src/Model3/Real3D.h | 18 +++++++----------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/Src/Model3/Model3.cpp b/Src/Model3/Model3.cpp index 7b38e55..20acae9 100644 --- a/Src/Model3/Model3.cpp +++ b/Src/Model3/Model3.cpp @@ -2949,12 +2949,7 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set) // Initialize Real3D int stepping = ((game.stepping[0] - '0') << 4) | (game.stepping[2] - '0'); - uint32_t real3DPCIID = game.real3d_pci_id; - if (0 == real3DPCIID) - { - real3DPCIID = stepping >= 0x20 ? CReal3D::PCIID::Step2x : CReal3D::PCIID::Step1x; - } - GPU.SetStepping(stepping, real3DPCIID); + GPU.SetStepping(stepping); // MPEG board (if present) if (rom_set.get_rom("mpeg_program").size) diff --git a/Src/Model3/Real3D.cpp b/Src/Model3/Real3D.cpp index a15ac6b..622dcda 100644 --- a/Src/Model3/Real3D.cpp +++ b/Src/Model3/Real3D.cpp @@ -27,10 +27,10 @@ * * PCI IDs * ------- - * It appears that Step 2.0 returns a different PCI ID depending on whether - * the PCI configuration space or DMA register are accessed. For example, - * Virtual On 2 expects 0x178611DB from the PCI configuration header but - * 0x16C311DB from the DMA device. + * It appears that accessing the PCI configuration space returns the PCI ID + * of Mercury (0x16C311DB) on Step 1.x and the DMA device (0x178611DB) on + * Step 2.x, while accessing the Step 2.x DMA device register returns the + * PCI ID of Mercury. Step 2.x games by AM3 expect this behavior. * * To-Do List * ---------- @@ -628,7 +628,8 @@ void CReal3D::WriteDMARegister32(unsigned reg, uint32_t data) case 0x10: // command register if ((data&0x20000000)) // DMA ID command { - dmaData = pciID; + // Games requesting PCI ID via the DMA device expect 0x16C311DB, even on step 2.x boards + dmaData = PCIID::Step1x; DebugLog("Real3D: DMA ID command issued (ATTENTION: make sure we're returning the correct value), PC=%08X, LR=%08X\n", ppc_get_pc(), ppc_get_lr()); } else if ((data&0x80000000)) @@ -921,7 +922,7 @@ uint32_t CReal3D::GetASICIDCode(ASIC asic) const return it == m_asicID.end() ? 0 : it->second; } -void CReal3D::SetStepping(int stepping, uint32_t pciIDValue) +void CReal3D::SetStepping(int stepping) { step = stepping; if ((step!=0x10) && (step!=0x15) && (step!=0x20) && (step!=0x21)) @@ -931,7 +932,7 @@ void CReal3D::SetStepping(int stepping, uint32_t pciIDValue) } // Set PCI ID - pciID = pciIDValue; + pciID = stepping >= 0x20 ? PCIID::Step2x : PCIID::Step1x; // Pass to renderer if (Render3D != NULL) diff --git a/Src/Model3/Real3D.h b/Src/Model3/Real3D.h index 3013924..7eddb66 100644 --- a/Src/Model3/Real3D.h +++ b/Src/Model3/Real3D.h @@ -68,10 +68,11 @@ public: /* * PCI IDs * - * The CReal3D object must be configured with the desired ID. Some Step 2.x - * appear to defy this and expect the 1.x ID. The symptom of this is that - * VBL is enabled briefly then disabled. This should be investigated further. - * Perhaps a different ASIC's PCI ID is being read in these situations? + * The CReal3D object must be configured with the PCI ID of the ASIC directly + * connected to the PCI slot; 0x16c311db for Step 1.x, 0x178611db for Step + * 2.x. Requesting PCI ID via the DMA device on Step 2.x appears to return + * the PCI ID of Mercury which is the ASIC connected to the PCI slot on Step + * 1.x, hence why some Step 2.x games appear to expect the 1.x ID. * * The vendor ID code 0x11db is Sega's. */ @@ -374,7 +375,7 @@ public: uint32_t GetASICIDCode(ASIC asic) const; /* - * SetStepping(stepping, pciIDValue): + * SetStepping(stepping): * * Sets the Model 3 hardware stepping, which also determines the Real3D * functionality. The default is Step 1.0. This should be called prior to @@ -383,13 +384,8 @@ public: * Parameters: * stepping 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, or * 0x21 for Step 2.1. Anything else defaults to 1.0. - * pciIDValue The PCI ID code to return. This should be one of the PCIID - * enum values otherwise games may fail to boot. Although the - * PCI ID depends on stepping, there are a few games that - * have to be explicitly configured with an older ID code, - * which is why this parameter is exposed. */ - void SetStepping(int stepping, uint32_t pciIDValue); + void SetStepping(int stepping); /* From ebff9a8b2d1c6ac60c88afa07ce574cf51abdef0 Mon Sep 17 00:00:00 2001 From: Bart Trzynadlowski Date: Sat, 2 Sep 2023 20:32:11 -0700 Subject: [PATCH 3/5] SCSP: added more detail to comment explaining 68K clock speed as recommended by Brian Troha --- Src/Sound/SCSP.cpp | 124 ++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp index 89e2c99..517ac1b 100644 --- a/Src/Sound/SCSP.cpp +++ b/Src/Sound/SCSP.cpp @@ -7,7 +7,7 @@ ** This file is part of Supermodel. ** ** Supermodel is free software: you can redistribute it and/or modify it under - ** the terms of the GNU General Public License as published by the Free + ** the terms of the GNU General Public License as published by the Free ** Software Foundation, either version 3 of the License, or (at your option) ** any later version. ** @@ -19,17 +19,17 @@ ** You should have received a copy of the GNU General Public License along ** with Supermodel. If not, see . **/ - + /* * SCSP.cpp - * + * * WARNING: Here be dragons! Tread carefully. Enabling/disabling things may * break save state support. * * SCSP (Sega Custom Sound Processor) emulation. This code was generously * donated by ElSemi. Interfaces directly to the 68K processor through * callbacks. Some minor interface changes were made (external global variables - * were removed). + * were removed). * * The MIDI input buffer has been increased from 8 (which I assume is the * actual size) in order to accommodate Model 3's PowerPC/68K communication. @@ -44,7 +44,7 @@ */ -/* +/* SEGA Custom Sound Processor (SCSP) Emulation by ElSemi. Driven by MC68000 @@ -78,7 +78,7 @@ Anyways credit to R. Belmont and ElSemi for the code, and for being awesome emul static const Util::Config::Node *s_config = 0; static bool s_multiThreaded = false; -bool legacySound; // For LegacySound (SCSP DSP) config option. +bool legacySound; // For LegacySound (SCSP DSP) config option. #define USEDSP //#define RB_VOLUME @@ -212,7 +212,7 @@ static int TimCnt[3]; #define PLFOWS(slot) ((slot->data[0x9] >> 0x8) & 0x0003) #define PLFOS(slot) ((slot->data[0x9] >> 0x5) & 0x000E) // Setting this to 14 seems to make FM more precise #define ALFOWS(slot) ((slot->data[0x9] >> 0x3) & 0x0003) -#define ALFOS(slot) ((slot->data[0x9] >> 0x0) & 0x0007) +#define ALFOS(slot) ((slot->data[0x9] >> 0x0) & 0x0007) #define ISEL(slot) ((slot->data[0xA] >> 0x3) & 0x000F) #define IMXL(slot) ((slot->data[0xA] >> 0x0) & 0x0007) @@ -347,7 +347,7 @@ void CheckPendingIRQ() { DWORD pend=SCSPs->data[0x20/2]; DWORD en=SCSPs->data[0x1e/2]; - + /* * MIDI FIFO critical section * @@ -361,20 +361,20 @@ void CheckPendingIRQ() { //if (g_Config.multiThreaded) // MIDILock->Unlock(); - + //SCSP.data[0x20/2]|=0x8; //Hold midi line while there are commands pending //Int68kCB(IrqMidi); //printf("68K: MIDI IRQ\n"); //ErrorLogMessage("Midi"); - + SCSP->data[0x20 / 2] |= 8; pend |= 8; } - + //if (g_Config.multiThreaded) // MIDILock->Unlock(); - + if(!pend) return; if(pend&0x40) @@ -629,7 +629,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n) MidiOutR=MidiOutW=0; MidiOutFill=0; MidiInFill=0; - + for(int i=0;i<0x400;++i) { @@ -638,7 +638,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n) fcent=(double) 44100.0*exp2(fcent/1200.0); FNS_Table[i]=(UINT32)((float) (1<>(10-SHIFT))|(1<data[0x8 / 2] &= 0xf800; + SCSP->data[0x8 / 2] &= 0xf800; break; case 0x12: case 0x13: @@ -864,7 +864,7 @@ void SCSP_UpdateReg(int reg) break; case 0x18: case 0x19: - if(SCSP->Master) + if(SCSP->Master) { TimPris[0]=1<<((SCSPs->data[0x18/2]>>8)&0x7); TimCnt[0]=((SCSPs->data[0x18/2]&0xfe)<<8)/*|(TimCnt[0]&0xff)*/; @@ -872,7 +872,7 @@ void SCSP_UpdateReg(int reg) break; case 0x1a: case 0x1b: - if(SCSP->Master) + if(SCSP->Master) { TimPris[1]=1<<((SCSPs->data[0x1A/2]>>8)&0x7); TimCnt[1]=((SCSPs->data[0x1A/2]&0xfe)<<8)/*|(TimCnt[1]&0xff)*/; @@ -880,7 +880,7 @@ void SCSP_UpdateReg(int reg) break; case 0x1C: case 0x1D: - if(SCSP->Master) + if(SCSP->Master) { TimPris[2]=1<<((SCSPs->data[0x1C/2]>>8)&0x7); TimCnt[2]=((SCSPs->data[0x1C/2]&0xfe)<<8)/*|(TimCnt[2]&0xff)*/; @@ -888,7 +888,7 @@ void SCSP_UpdateReg(int reg) break; case 0x22: //SCIRE case 0x23: - if(SCSP->Master) + if(SCSP->Master) { SCSP->data[0x20 / 2] &= ~SCSP->data[0x22 / 2]; //ResetInterrupts(); @@ -1026,7 +1026,7 @@ void SCSP_w8(unsigned int addr,unsigned char val) { *(unsigned char *) &(SCSP->datab[(addr&0xff)^1]) = val; SCSP_UpdateReg((addr^1)&0xff); - } + } else if(addr<0x700) SCSP->RINGBUF[(addr-0x600)/2]=val; else @@ -1093,7 +1093,7 @@ void SCSP_w16(unsigned int addr,unsigned short val) *((unsigned short *)(SCSP->datab + ((addr & 0x3f)))) = val; SCSP_UpdateReg(addr & 0x3f); } - } + } else if (addr < 0x700) SCSP->RINGBUF[(addr - 0x600) / 2] = val; else @@ -1159,7 +1159,7 @@ void SCSP_w32(unsigned int addr,unsigned int val) *(unsigned int *) &(SCSP->datab[addr&0xff]) = val; SCSP_UpdateReg(addr&0xff); SCSP_UpdateReg((addr&0xff)+2); - } + } else if(addr<0x700) int a=1; else @@ -1193,7 +1193,7 @@ unsigned char SCSP_r8(unsigned int addr) int slot=addr/0x20; addr&=0x1f; SCSP_UpdateSlotRegR(slot,(addr^1)&0x1f); - + v=*(unsigned char *) &(SCSP->Slots[slot].datab[addr^1]); //DebugLog("Slot %02X Reg %02X Read byte %02X",slot,addr^1,v); } @@ -1201,8 +1201,8 @@ unsigned char SCSP_r8(unsigned int addr) { SCSP_UpdateRegR(addr&0xff); v= *(unsigned char *) &(SCSP->datab[(addr&0xff)^1]); - //ErrorLogMessage("SCSP Reg %02X Read byte %02X",addr&0xff,v); - } + //ErrorLogMessage("SCSP Reg %02X Read byte %02X",addr&0xff,v); + } else if(addr<0x700) v=0; return v; @@ -1230,7 +1230,7 @@ unsigned short SCSP_r16(unsigned int addr) SCSP_UpdateRegR(addr & 0x3f); v = *((UINT16 *)(SCSP->datab + ((addr & 0x3f)))); } - } + } else if (addr < 0x700) v = SCSP->RINGBUF[(addr - 0x600) / 2]; else @@ -1473,7 +1473,7 @@ signed int inline SCSP_UpdateSlot(_SLOT *slot) if (!SDIR(slot)) { - if (ALFOS(slot) != 0) + if (ALFOS(slot) != 0) { sample = sample * ALFO_Step(&(slot->ALFO)); sample >>= (SHIFT); @@ -1513,7 +1513,7 @@ void SCSP_CpuRunScanline() void SCSP_DoMasterSamples(int nsamples) { - const int slice = 11289600 / 44100; // 68K runs at 256 cycles/sample + const int slice = 11289600 / 44100; // 68K clocked at 11.2896MHz (45.1584MHz OSC / 4), which is 256 cycles/sample static int lastdiff = 0; /* @@ -1560,7 +1560,7 @@ void SCSP_DoMasterSamples(int nsamples) #ifdef RB_VOLUME smpfl += (sample * volume[TL(slot) + pan_left[DIPAN(slot)]]) >> 17; smpfr += (sample * volume[TL(slot) + pan_right[DIPAN(slot)]]) >> 17; -#else +#else { smpfl += (sample*LPANTABLE[Enc]) >> SHIFT; smpfr += (sample*RPANTABLE[Enc]) >> SHIFT; @@ -1597,7 +1597,7 @@ void SCSP_DoMasterSamples(int nsamples) #ifdef RB_VOLUME smprl += (sample * volume[TL(slot) + pan_left[DIPAN(slot)]]) >> 17; smprr += (sample * volume[TL(slot) + pan_right[DIPAN(slot)]]) >> 17; -#else +#else smprl += (sample*LPANTABLE[Enc]) >> SHIFT; smprr += (sample*RPANTABLE[Enc]) >> SHIFT; } @@ -1740,7 +1740,7 @@ void SCSP_MidiIn(BYTE val) */ if (s_multiThreaded) MIDILock->Lock(); - + //DebugLog("Midi Buffer push %02X",val); MidiStack[MidiW++]=val; MidiW&=MIDI_STACK_SIZE_MASK; @@ -1777,7 +1777,7 @@ unsigned char SCSP_MidiOutR() if(MidiOutR==MidiOutW) // I don't think this needs to be a critical section... return 0xff; - + /* * MIDI FIFO critical section */ @@ -1788,17 +1788,17 @@ unsigned char SCSP_MidiOutR() //DebugLog("Midi Out Buffer pop %02X",val); MidiOutR&=31; --MidiOutFill; - + if (s_multiThreaded) MIDILock->Unlock(); - + return val; } unsigned char SCSP_MidiOutFill() { unsigned char v; - + /* * MIDI FIFO critical section */ @@ -1806,17 +1806,17 @@ unsigned char SCSP_MidiOutFill() MIDILock->Lock(); v = MidiOutFill; - + if (s_multiThreaded) MIDILock->Unlock(); - + return v; } unsigned char SCSP_MidiInFill() { unsigned char v; - + /* * MIDI FIFO critical section */ @@ -1824,10 +1824,10 @@ unsigned char SCSP_MidiInFill() MIDILock->Lock(); v = MidiInFill; - + if (s_multiThreaded) MIDILock->Unlock(); - + return v; } @@ -1934,13 +1934,13 @@ unsigned int SCSP_Slave_r32(unsigned int addr) void SCSP_SaveState(CBlockFile *StateFile) { StateFile->NewBlock("SCSP x 2", __FILE__); - + /* * Save global variables. * * Difficult to say exactly what is necessary given that many things are * commented out and should not be enabled but I try to save as much as - * possible. + * possible. * * Things not saved: * @@ -1962,7 +1962,7 @@ void SCSP_SaveState(CBlockFile *StateFile) StateFile->Write(&MidiR, sizeof(MidiR)); StateFile->Write(TimPris, sizeof(TimPris)); StateFile->Write(TimCnt, sizeof(TimCnt)); - + // Save both SCSP states for (int i = 0; i < 2; i++) { @@ -1973,13 +1973,13 @@ void SCSP_SaveState(CBlockFile *StateFile) StateFile->Write(&(SCSPs[i].DELAYBUF), sizeof(SCSPs[i].DELAYBUF)); StateFile->Write(&(SCSPs[i].DELAYPTR), sizeof(SCSPs[i].DELAYPTR)); #endif - + // Save each slot for (int j = 0; j < 32; j++) { UINT64 baseOffset; UINT8 egState; - + StateFile->Write(SCSPs[i].Slots[j].datab, sizeof(SCSPs[i].Slots[j].datab)); StateFile->Write(&(SCSPs[i].Slots[j].active), sizeof(SCSPs[i].Slots[j].active)); baseOffset = (UINT64) (SCSPs[i].Slots[j].base - SCSPs[i].SCSPRAM); @@ -1990,7 +1990,7 @@ void SCSP_SaveState(CBlockFile *StateFile) StateFile->Write(&(SCSPs[i].Slots[j].Back), sizeof(SCSPs[i].Slots[j].Back)); StateFile->Write(&(SCSPs[i].Slots[j].slot), sizeof(SCSPs[i].Slots[j].slot)); StateFile->Write(&(SCSPs[i].Slots[j].Prev), sizeof(SCSPs[i].Slots[j].Prev)); - + // EG StateFile->Write(&(SCSPs[i].Slots[j].EG.volume), sizeof(SCSPs[i].Slots[j].EG.volume)); egState = SCSPs[i].Slots[j].EG.state; @@ -2003,18 +2003,18 @@ void SCSP_SaveState(CBlockFile *StateFile) StateFile->Write(&(SCSPs[i].Slots[j].EG.DL), sizeof(SCSPs[i].Slots[j].EG.DL)); StateFile->Write(&(SCSPs[i].Slots[j].EG.EGHOLD), sizeof(SCSPs[i].Slots[j].EG.EGHOLD)); StateFile->Write(&(SCSPs[i].Slots[j].EG.LPLINK), sizeof(SCSPs[i].Slots[j].EG.LPLINK)); - + // PLFO StateFile->Write(&(SCSPs[i].Slots[j].PLFO.phase), sizeof(SCSPs[i].Slots[j].PLFO.phase)); StateFile->Write(&(SCSPs[i].Slots[j].PLFO.phase_step), sizeof(SCSPs[i].Slots[j].PLFO.phase_step)); - + // ALFO StateFile->Write(&(SCSPs[i].Slots[j].ALFO.phase), sizeof(SCSPs[i].Slots[j].ALFO.phase)); StateFile->Write(&(SCSPs[i].Slots[j].ALFO.phase_step), sizeof(SCSPs[i].Slots[j].ALFO.phase_step)); - + //when loading, make sure to compute lfo } - + // DSP StateFile->Write(&(SCSPs[i].DSP.RBP), sizeof(SCSPs[i].DSP.RBP)); StateFile->Write(&(SCSPs[i].DSP.RBL), sizeof(SCSPs[i].DSP.RBL)); @@ -2039,7 +2039,7 @@ void SCSP_LoadState(CBlockFile *StateFile) ErrorLog("Unable to load SCSP state. Save state file is corrupt."); return; } - + // Load global variables StateFile->Read(&IrqTimA, sizeof(IrqTimA)); StateFile->Read(&IrqTimBC, sizeof(IrqTimBC)); @@ -2054,7 +2054,7 @@ void SCSP_LoadState(CBlockFile *StateFile) StateFile->Read(&MidiR, sizeof(MidiR)); StateFile->Read(TimPris, sizeof(TimPris)); StateFile->Read(TimCnt, sizeof(TimCnt)); - + // Load both SCSP states for (int i = 0; i < 2; i++) { @@ -2065,13 +2065,13 @@ void SCSP_LoadState(CBlockFile *StateFile) StateFile->Read(&(SCSPs[i].DELAYBUF), sizeof(SCSPs[i].DELAYBUF)); StateFile->Read(&(SCSPs[i].DELAYPTR), sizeof(SCSPs[i].DELAYPTR)); #endif - + // Load each slot for (int j = 0; j < 32; j++) { UINT64 baseOffset; UINT8 egState; - + StateFile->Read(SCSPs[i].Slots[j].datab, sizeof(SCSPs[i].Slots[j].datab)); StateFile->Read(&(SCSPs[i].Slots[j].active), sizeof(SCSPs[i].Slots[j].active)); StateFile->Read(&baseOffset, sizeof(baseOffset)); @@ -2082,7 +2082,7 @@ void SCSP_LoadState(CBlockFile *StateFile) StateFile->Read(&(SCSPs[i].Slots[j].Back), sizeof(SCSPs[i].Slots[j].Back)); StateFile->Read(&(SCSPs[i].Slots[j].slot), sizeof(SCSPs[i].Slots[j].slot)); StateFile->Read(&(SCSPs[i].Slots[j].Prev), sizeof(SCSPs[i].Slots[j].Prev)); - + // EG StateFile->Read(&(SCSPs[i].Slots[j].EG.volume), sizeof(SCSPs[i].Slots[j].EG.volume)); StateFile->Read(&egState, sizeof(egState)); @@ -2095,11 +2095,11 @@ void SCSP_LoadState(CBlockFile *StateFile) StateFile->Read(&(SCSPs[i].Slots[j].EG.DL), sizeof(SCSPs[i].Slots[j].EG.DL)); StateFile->Read(&(SCSPs[i].Slots[j].EG.EGHOLD), sizeof(SCSPs[i].Slots[j].EG.EGHOLD)); StateFile->Read(&(SCSPs[i].Slots[j].EG.LPLINK), sizeof(SCSPs[i].Slots[j].EG.LPLINK)); - + // PLFO StateFile->Read(&(SCSPs[i].Slots[j].PLFO.phase), sizeof(SCSPs[i].Slots[j].PLFO.phase)); StateFile->Read(&(SCSPs[i].Slots[j].PLFO.phase_step), sizeof(SCSPs[i].Slots[j].PLFO.phase_step)); - + // ALFO StateFile->Read(&(SCSPs[i].Slots[j].ALFO.phase), sizeof(SCSPs[i].Slots[j].ALFO.phase)); StateFile->Read(&(SCSPs[i].Slots[j].ALFO.phase_step), sizeof(SCSPs[i].Slots[j].ALFO.phase_step)); @@ -2107,7 +2107,7 @@ void SCSP_LoadState(CBlockFile *StateFile) // Recompute LFOs Compute_LFO(&(SCSPs[i].Slots[j])); } - + // DSP StateFile->Read(&(SCSPs[i].DSP.RBP), sizeof(SCSPs[i].DSP.RBP)); StateFile->Read(&(SCSPs[i].DSP.RBL), sizeof(SCSPs[i].DSP.RBL)); From c9b718e89a4b0142e2b12cf29ffd07d231fd5d99 Mon Sep 17 00:00:00 2001 From: gm-matthew <108370479+gm-matthew@users.noreply.github.com> Date: Fri, 1 Sep 2023 13:52:13 +0100 Subject: [PATCH 4/5] Fix Z80Debug.cpp compile with C++20 String literals should not be used to initialize char* but C++17 and earlier were letting it slide --- Src/Debugger/CPU/Z80Debug.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Src/Debugger/CPU/Z80Debug.cpp b/Src/Debugger/CPU/Z80Debug.cpp index 1d0f4b5..17cb723 100755 --- a/Src/Debugger/CPU/Z80Debug.cpp +++ b/Src/Debugger/CPU/Z80Debug.cpp @@ -33,7 +33,7 @@ namespace Debugger { // Instruction templates - static char *templates[5][256] = { + static const char *templates[5][256] = { { // Table 0: single byte instructions "NOP","LD BC,@a","LD (BC),A","INC BC","INC B","DEC B","LD B,@d","RLCA", @@ -393,10 +393,10 @@ namespace Debugger switch (opcode) { case 0xCB: - templ = templates[1][m_bus->Read8(dAddr++)]; + templ = (char*)templates[1][m_bus->Read8(dAddr++)]; break; case 0xED: - templ = templates[2][m_bus->Read8(dAddr++)]; + templ = (char*)templates[2][m_bus->Read8(dAddr++)]; break; case 0xDD: xyChr = 'X'; @@ -405,10 +405,10 @@ namespace Debugger { offs = m_bus->Read8(dAddr++); notJump = true; - templ = templates[4][m_bus->Read8(dAddr++)]; + templ = (char*)templates[4][m_bus->Read8(dAddr++)]; } else - templ = templates[3][nextCode]; + templ = (char*)templates[3][nextCode]; break; case 0xFD: xyChr = 'Y'; @@ -417,13 +417,13 @@ namespace Debugger { offs = m_bus->Read8(dAddr++); notJump = true; - templ = templates[4][m_bus->Read8(dAddr++)]; + templ = (char*)templates[4][m_bus->Read8(dAddr++)]; } else - templ = templates[3][nextCode]; + templ = (char*)templates[3][nextCode]; break; default: - templ = templates[0][opcode]; + templ = (char*)templates[0][opcode]; break; } From 38a95088e8278e8a2b6c50d7f8a7e187819de449 Mon Sep 17 00:00:00 2001 From: gm-matthew <108370479+gm-matthew@users.noreply.github.com> Date: Mon, 28 Aug 2023 03:12:43 +0100 Subject: [PATCH 5/5] Prevent "ROLLING START" scrolling glitch in Scud Race There is a quirk of the tilegen chip that causes this glitch not to occur on real hardware, but we can't be sure what it is without testing Much easier to just patch all the Scud Race ROM sets --- Config/Games.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Config/Games.xml b/Config/Games.xml index 411001a..82ec982 100644 --- a/Config/Games.xml +++ b/Config/Games.xml @@ -1443,6 +1443,10 @@ + + + + @@ -1531,6 +1535,8 @@ + + @@ -1563,6 +1569,10 @@ + + + + @@ -1636,6 +1646,10 @@ + + + + @@ -1684,6 +1698,10 @@ + + + +