SCSP: added more detail to comment explaining 68K clock speed as recommended by Brian Troha

This commit is contained in:
Bart Trzynadlowski 2023-09-02 20:32:11 -07:00
parent b2fee4242c
commit ebff9a8b2d

View file

@ -7,7 +7,7 @@
** This file is part of Supermodel. ** This file is part of Supermodel.
** **
** Supermodel is free software: you can redistribute it and/or modify it under ** 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) ** Software Foundation, either version 3 of the License, or (at your option)
** any later version. ** any later version.
** **
@ -19,17 +19,17 @@
** You should have received a copy of the GNU General Public License along ** You should have received a copy of the GNU General Public License along
** with Supermodel. If not, see <http://www.gnu.org/licenses/>. ** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
**/ **/
/* /*
* SCSP.cpp * SCSP.cpp
* *
* WARNING: Here be dragons! Tread carefully. Enabling/disabling things may * WARNING: Here be dragons! Tread carefully. Enabling/disabling things may
* break save state support. * break save state support.
* *
* SCSP (Sega Custom Sound Processor) emulation. This code was generously * SCSP (Sega Custom Sound Processor) emulation. This code was generously
* donated by ElSemi. Interfaces directly to the 68K processor through * donated by ElSemi. Interfaces directly to the 68K processor through
* callbacks. Some minor interface changes were made (external global variables * 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 * 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. * actual size) in order to accommodate Model 3's PowerPC/68K communication.
@ -44,7 +44,7 @@
*/ */
/* /*
SEGA Custom Sound Processor (SCSP) Emulation SEGA Custom Sound Processor (SCSP) Emulation
by ElSemi. by ElSemi.
Driven by MC68000 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 const Util::Config::Node *s_config = 0;
static bool s_multiThreaded = false; static bool s_multiThreaded = false;
bool legacySound; // For LegacySound (SCSP DSP) config option. bool legacySound; // For LegacySound (SCSP DSP) config option.
#define USEDSP #define USEDSP
//#define RB_VOLUME //#define RB_VOLUME
@ -212,7 +212,7 @@ static int TimCnt[3];
#define PLFOWS(slot) ((slot->data[0x9] >> 0x8) & 0x0003) #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 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 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 ISEL(slot) ((slot->data[0xA] >> 0x3) & 0x000F)
#define IMXL(slot) ((slot->data[0xA] >> 0x0) & 0x0007) #define IMXL(slot) ((slot->data[0xA] >> 0x0) & 0x0007)
@ -347,7 +347,7 @@ void CheckPendingIRQ()
{ {
DWORD pend=SCSPs->data[0x20/2]; DWORD pend=SCSPs->data[0x20/2];
DWORD en=SCSPs->data[0x1e/2]; DWORD en=SCSPs->data[0x1e/2];
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
* *
@ -361,20 +361,20 @@ void CheckPendingIRQ()
{ {
//if (g_Config.multiThreaded) //if (g_Config.multiThreaded)
// MIDILock->Unlock(); // MIDILock->Unlock();
//SCSP.data[0x20/2]|=0x8; //Hold midi line while there are commands pending //SCSP.data[0x20/2]|=0x8; //Hold midi line while there are commands pending
//Int68kCB(IrqMidi); //Int68kCB(IrqMidi);
//printf("68K: MIDI IRQ\n"); //printf("68K: MIDI IRQ\n");
//ErrorLogMessage("Midi"); //ErrorLogMessage("Midi");
SCSP->data[0x20 / 2] |= 8; SCSP->data[0x20 / 2] |= 8;
pend |= 8; pend |= 8;
} }
//if (g_Config.multiThreaded) //if (g_Config.multiThreaded)
// MIDILock->Unlock(); // MIDILock->Unlock();
if(!pend) if(!pend)
return; return;
if(pend&0x40) if(pend&0x40)
@ -629,7 +629,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
MidiOutR=MidiOutW=0; MidiOutR=MidiOutW=0;
MidiOutFill=0; MidiOutFill=0;
MidiInFill=0; MidiInFill=0;
for(int i=0;i<0x400;++i) 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); fcent=(double) 44100.0*exp2(fcent/1200.0);
FNS_Table[i]=(UINT32)((float) (1<<SHIFT) *fcent); FNS_Table[i]=(UINT32)((float) (1<<SHIFT) *fcent);
//FNS_Table[i]=(i>>(10-SHIFT))|(1<<SHIFT); //FNS_Table[i]=(i>>(10-SHIFT))|(1<<SHIFT);
} }
for (int i = 0; i < 0x400; ++i) { for (int i = 0; i < 0x400; ++i) {
float envDB = ((float)(3 * (i - 0x3ff))) / 32.0f; float envDB = ((float)(3 * (i - 0x3ff))) / 32.0f;
@ -721,7 +721,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
// int a=1; // int a=1;
//if(iTL==0x3a) //if(iTL==0x3a)
// int a=1; // int a=1;
LPANTABLE[i]=FIX((4.0*LPAN*TL*SDL)); LPANTABLE[i]=FIX((4.0*LPAN*TL*SDL));
RPANTABLE[i]=FIX((4.0*RPAN*TL*SDL)); RPANTABLE[i]=FIX((4.0*RPAN*TL*SDL));
} }
@ -746,7 +746,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
scale=(double) (1<<EG_SHIFT); scale=(double) (1<<EG_SHIFT);
DRTABLE[i]=(int) (step*scale); DRTABLE[i]=(int) (step*scale);
} }
for(int i=0;i<32;++i) for(int i=0;i<32;++i)
SCSPs[0].Slots[i].slot=i; SCSPs[0].Slots[i].slot=i;
@ -761,14 +761,14 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
TimCnt[0] = 0xffff; TimCnt[0] = 0xffff;
TimCnt[1] = 0xffff; TimCnt[1] = 0xffff;
TimCnt[2] = 0xffff; TimCnt[2] = 0xffff;
// MIDI FIFO mutex // MIDI FIFO mutex
MIDILock = CThread::CreateMutex(); MIDILock = CThread::CreateMutex();
if (NULL == MIDILock) if (NULL == MIDILock)
{ {
return ErrorLog("Unable to create MIDI mutex!"); return ErrorLog("Unable to create MIDI mutex!");
} }
return OKAY; return OKAY;
} }
@ -850,7 +850,7 @@ void SCSP_UpdateReg(int reg)
case 8: case 8:
case 9: case 9:
SCSP->data[0x8 / 2] &= 0xf800; SCSP->data[0x8 / 2] &= 0xf800;
break; break;
case 0x12: case 0x12:
case 0x13: case 0x13:
@ -864,7 +864,7 @@ void SCSP_UpdateReg(int reg)
break; break;
case 0x18: case 0x18:
case 0x19: case 0x19:
if(SCSP->Master) if(SCSP->Master)
{ {
TimPris[0]=1<<((SCSPs->data[0x18/2]>>8)&0x7); TimPris[0]=1<<((SCSPs->data[0x18/2]>>8)&0x7);
TimCnt[0]=((SCSPs->data[0x18/2]&0xfe)<<8)/*|(TimCnt[0]&0xff)*/; TimCnt[0]=((SCSPs->data[0x18/2]&0xfe)<<8)/*|(TimCnt[0]&0xff)*/;
@ -872,7 +872,7 @@ void SCSP_UpdateReg(int reg)
break; break;
case 0x1a: case 0x1a:
case 0x1b: case 0x1b:
if(SCSP->Master) if(SCSP->Master)
{ {
TimPris[1]=1<<((SCSPs->data[0x1A/2]>>8)&0x7); TimPris[1]=1<<((SCSPs->data[0x1A/2]>>8)&0x7);
TimCnt[1]=((SCSPs->data[0x1A/2]&0xfe)<<8)/*|(TimCnt[1]&0xff)*/; TimCnt[1]=((SCSPs->data[0x1A/2]&0xfe)<<8)/*|(TimCnt[1]&0xff)*/;
@ -880,7 +880,7 @@ void SCSP_UpdateReg(int reg)
break; break;
case 0x1C: case 0x1C:
case 0x1D: case 0x1D:
if(SCSP->Master) if(SCSP->Master)
{ {
TimPris[2]=1<<((SCSPs->data[0x1C/2]>>8)&0x7); TimPris[2]=1<<((SCSPs->data[0x1C/2]>>8)&0x7);
TimCnt[2]=((SCSPs->data[0x1C/2]&0xfe)<<8)/*|(TimCnt[2]&0xff)*/; TimCnt[2]=((SCSPs->data[0x1C/2]&0xfe)<<8)/*|(TimCnt[2]&0xff)*/;
@ -888,7 +888,7 @@ void SCSP_UpdateReg(int reg)
break; break;
case 0x22: //SCIRE case 0x22: //SCIRE
case 0x23: case 0x23:
if(SCSP->Master) if(SCSP->Master)
{ {
SCSP->data[0x20 / 2] &= ~SCSP->data[0x22 / 2]; SCSP->data[0x20 / 2] &= ~SCSP->data[0x22 / 2];
//ResetInterrupts(); //ResetInterrupts();
@ -1026,7 +1026,7 @@ void SCSP_w8(unsigned int addr,unsigned char val)
{ {
*(unsigned char *) &(SCSP->datab[(addr&0xff)^1]) = val; *(unsigned char *) &(SCSP->datab[(addr&0xff)^1]) = val;
SCSP_UpdateReg((addr^1)&0xff); SCSP_UpdateReg((addr^1)&0xff);
} }
else if(addr<0x700) else if(addr<0x700)
SCSP->RINGBUF[(addr-0x600)/2]=val; SCSP->RINGBUF[(addr-0x600)/2]=val;
else else
@ -1093,7 +1093,7 @@ void SCSP_w16(unsigned int addr,unsigned short val)
*((unsigned short *)(SCSP->datab + ((addr & 0x3f)))) = val; *((unsigned short *)(SCSP->datab + ((addr & 0x3f)))) = val;
SCSP_UpdateReg(addr & 0x3f); SCSP_UpdateReg(addr & 0x3f);
} }
} }
else if (addr < 0x700) else if (addr < 0x700)
SCSP->RINGBUF[(addr - 0x600) / 2] = val; SCSP->RINGBUF[(addr - 0x600) / 2] = val;
else else
@ -1159,7 +1159,7 @@ void SCSP_w32(unsigned int addr,unsigned int val)
*(unsigned int *) &(SCSP->datab[addr&0xff]) = val; *(unsigned int *) &(SCSP->datab[addr&0xff]) = val;
SCSP_UpdateReg(addr&0xff); SCSP_UpdateReg(addr&0xff);
SCSP_UpdateReg((addr&0xff)+2); SCSP_UpdateReg((addr&0xff)+2);
} }
else if(addr<0x700) else if(addr<0x700)
int a=1; int a=1;
else else
@ -1193,7 +1193,7 @@ unsigned char SCSP_r8(unsigned int addr)
int slot=addr/0x20; int slot=addr/0x20;
addr&=0x1f; addr&=0x1f;
SCSP_UpdateSlotRegR(slot,(addr^1)&0x1f); SCSP_UpdateSlotRegR(slot,(addr^1)&0x1f);
v=*(unsigned char *) &(SCSP->Slots[slot].datab[addr^1]); v=*(unsigned char *) &(SCSP->Slots[slot].datab[addr^1]);
//DebugLog("Slot %02X Reg %02X Read byte %02X",slot,addr^1,v); //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); SCSP_UpdateRegR(addr&0xff);
v= *(unsigned char *) &(SCSP->datab[(addr&0xff)^1]); 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) else if(addr<0x700)
v=0; v=0;
return v; return v;
@ -1230,7 +1230,7 @@ unsigned short SCSP_r16(unsigned int addr)
SCSP_UpdateRegR(addr & 0x3f); SCSP_UpdateRegR(addr & 0x3f);
v = *((UINT16 *)(SCSP->datab + ((addr & 0x3f)))); v = *((UINT16 *)(SCSP->datab + ((addr & 0x3f))));
} }
} }
else if (addr < 0x700) else if (addr < 0x700)
v = SCSP->RINGBUF[(addr - 0x600) / 2]; v = SCSP->RINGBUF[(addr - 0x600) / 2];
else else
@ -1473,7 +1473,7 @@ signed int inline SCSP_UpdateSlot(_SLOT *slot)
if (!SDIR(slot)) if (!SDIR(slot))
{ {
if (ALFOS(slot) != 0) if (ALFOS(slot) != 0)
{ {
sample = sample * ALFO_Step(&(slot->ALFO)); sample = sample * ALFO_Step(&(slot->ALFO));
sample >>= (SHIFT); sample >>= (SHIFT);
@ -1513,7 +1513,7 @@ void SCSP_CpuRunScanline()
void SCSP_DoMasterSamples(int nsamples) 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; static int lastdiff = 0;
/* /*
@ -1560,7 +1560,7 @@ void SCSP_DoMasterSamples(int nsamples)
#ifdef RB_VOLUME #ifdef RB_VOLUME
smpfl += (sample * volume[TL(slot) + pan_left[DIPAN(slot)]]) >> 17; smpfl += (sample * volume[TL(slot) + pan_left[DIPAN(slot)]]) >> 17;
smpfr += (sample * volume[TL(slot) + pan_right[DIPAN(slot)]]) >> 17; smpfr += (sample * volume[TL(slot) + pan_right[DIPAN(slot)]]) >> 17;
#else #else
{ {
smpfl += (sample*LPANTABLE[Enc]) >> SHIFT; smpfl += (sample*LPANTABLE[Enc]) >> SHIFT;
smpfr += (sample*RPANTABLE[Enc]) >> SHIFT; smpfr += (sample*RPANTABLE[Enc]) >> SHIFT;
@ -1597,7 +1597,7 @@ void SCSP_DoMasterSamples(int nsamples)
#ifdef RB_VOLUME #ifdef RB_VOLUME
smprl += (sample * volume[TL(slot) + pan_left[DIPAN(slot)]]) >> 17; smprl += (sample * volume[TL(slot) + pan_left[DIPAN(slot)]]) >> 17;
smprr += (sample * volume[TL(slot) + pan_right[DIPAN(slot)]]) >> 17; smprr += (sample * volume[TL(slot) + pan_right[DIPAN(slot)]]) >> 17;
#else #else
smprl += (sample*LPANTABLE[Enc]) >> SHIFT; smprl += (sample*LPANTABLE[Enc]) >> SHIFT;
smprr += (sample*RPANTABLE[Enc]) >> SHIFT; smprr += (sample*RPANTABLE[Enc]) >> SHIFT;
} }
@ -1740,7 +1740,7 @@ void SCSP_MidiIn(BYTE val)
*/ */
if (s_multiThreaded) if (s_multiThreaded)
MIDILock->Lock(); MIDILock->Lock();
//DebugLog("Midi Buffer push %02X",val); //DebugLog("Midi Buffer push %02X",val);
MidiStack[MidiW++]=val; MidiStack[MidiW++]=val;
MidiW&=MIDI_STACK_SIZE_MASK; 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... if(MidiOutR==MidiOutW) // I don't think this needs to be a critical section...
return 0xff; return 0xff;
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
@ -1788,17 +1788,17 @@ unsigned char SCSP_MidiOutR()
//DebugLog("Midi Out Buffer pop %02X",val); //DebugLog("Midi Out Buffer pop %02X",val);
MidiOutR&=31; MidiOutR&=31;
--MidiOutFill; --MidiOutFill;
if (s_multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
return val; return val;
} }
unsigned char SCSP_MidiOutFill() unsigned char SCSP_MidiOutFill()
{ {
unsigned char v; unsigned char v;
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
@ -1806,17 +1806,17 @@ unsigned char SCSP_MidiOutFill()
MIDILock->Lock(); MIDILock->Lock();
v = MidiOutFill; v = MidiOutFill;
if (s_multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
return v; return v;
} }
unsigned char SCSP_MidiInFill() unsigned char SCSP_MidiInFill()
{ {
unsigned char v; unsigned char v;
/* /*
* MIDI FIFO critical section * MIDI FIFO critical section
*/ */
@ -1824,10 +1824,10 @@ unsigned char SCSP_MidiInFill()
MIDILock->Lock(); MIDILock->Lock();
v = MidiInFill; v = MidiInFill;
if (s_multiThreaded) if (s_multiThreaded)
MIDILock->Unlock(); MIDILock->Unlock();
return v; return v;
} }
@ -1934,13 +1934,13 @@ unsigned int SCSP_Slave_r32(unsigned int addr)
void SCSP_SaveState(CBlockFile *StateFile) void SCSP_SaveState(CBlockFile *StateFile)
{ {
StateFile->NewBlock("SCSP x 2", __FILE__); StateFile->NewBlock("SCSP x 2", __FILE__);
/* /*
* Save global variables. * Save global variables.
* *
* Difficult to say exactly what is necessary given that many things are * 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 * commented out and should not be enabled but I try to save as much as
* possible. * possible.
* *
* Things not saved: * Things not saved:
* *
@ -1962,7 +1962,7 @@ void SCSP_SaveState(CBlockFile *StateFile)
StateFile->Write(&MidiR, sizeof(MidiR)); StateFile->Write(&MidiR, sizeof(MidiR));
StateFile->Write(TimPris, sizeof(TimPris)); StateFile->Write(TimPris, sizeof(TimPris));
StateFile->Write(TimCnt, sizeof(TimCnt)); StateFile->Write(TimCnt, sizeof(TimCnt));
// Save both SCSP states // Save both SCSP states
for (int i = 0; i < 2; i++) 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].DELAYBUF), sizeof(SCSPs[i].DELAYBUF));
StateFile->Write(&(SCSPs[i].DELAYPTR), sizeof(SCSPs[i].DELAYPTR)); StateFile->Write(&(SCSPs[i].DELAYPTR), sizeof(SCSPs[i].DELAYPTR));
#endif #endif
// Save each slot // Save each slot
for (int j = 0; j < 32; j++) for (int j = 0; j < 32; j++)
{ {
UINT64 baseOffset; UINT64 baseOffset;
UINT8 egState; UINT8 egState;
StateFile->Write(SCSPs[i].Slots[j].datab, sizeof(SCSPs[i].Slots[j].datab)); 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)); StateFile->Write(&(SCSPs[i].Slots[j].active), sizeof(SCSPs[i].Slots[j].active));
baseOffset = (UINT64) (SCSPs[i].Slots[j].base - SCSPs[i].SCSPRAM); 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].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].slot), sizeof(SCSPs[i].Slots[j].slot));
StateFile->Write(&(SCSPs[i].Slots[j].Prev), sizeof(SCSPs[i].Slots[j].Prev)); StateFile->Write(&(SCSPs[i].Slots[j].Prev), sizeof(SCSPs[i].Slots[j].Prev));
// EG // EG
StateFile->Write(&(SCSPs[i].Slots[j].EG.volume), sizeof(SCSPs[i].Slots[j].EG.volume)); StateFile->Write(&(SCSPs[i].Slots[j].EG.volume), sizeof(SCSPs[i].Slots[j].EG.volume));
egState = SCSPs[i].Slots[j].EG.state; 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.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.EGHOLD), sizeof(SCSPs[i].Slots[j].EG.EGHOLD));
StateFile->Write(&(SCSPs[i].Slots[j].EG.LPLINK), sizeof(SCSPs[i].Slots[j].EG.LPLINK)); StateFile->Write(&(SCSPs[i].Slots[j].EG.LPLINK), sizeof(SCSPs[i].Slots[j].EG.LPLINK));
// PLFO // PLFO
StateFile->Write(&(SCSPs[i].Slots[j].PLFO.phase), sizeof(SCSPs[i].Slots[j].PLFO.phase)); 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)); StateFile->Write(&(SCSPs[i].Slots[j].PLFO.phase_step), sizeof(SCSPs[i].Slots[j].PLFO.phase_step));
// ALFO // ALFO
StateFile->Write(&(SCSPs[i].Slots[j].ALFO.phase), sizeof(SCSPs[i].Slots[j].ALFO.phase)); 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)); StateFile->Write(&(SCSPs[i].Slots[j].ALFO.phase_step), sizeof(SCSPs[i].Slots[j].ALFO.phase_step));
//when loading, make sure to compute lfo //when loading, make sure to compute lfo
} }
// DSP // DSP
StateFile->Write(&(SCSPs[i].DSP.RBP), sizeof(SCSPs[i].DSP.RBP)); StateFile->Write(&(SCSPs[i].DSP.RBP), sizeof(SCSPs[i].DSP.RBP));
StateFile->Write(&(SCSPs[i].DSP.RBL), sizeof(SCSPs[i].DSP.RBL)); 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."); ErrorLog("Unable to load SCSP state. Save state file is corrupt.");
return; return;
} }
// Load global variables // Load global variables
StateFile->Read(&IrqTimA, sizeof(IrqTimA)); StateFile->Read(&IrqTimA, sizeof(IrqTimA));
StateFile->Read(&IrqTimBC, sizeof(IrqTimBC)); StateFile->Read(&IrqTimBC, sizeof(IrqTimBC));
@ -2054,7 +2054,7 @@ void SCSP_LoadState(CBlockFile *StateFile)
StateFile->Read(&MidiR, sizeof(MidiR)); StateFile->Read(&MidiR, sizeof(MidiR));
StateFile->Read(TimPris, sizeof(TimPris)); StateFile->Read(TimPris, sizeof(TimPris));
StateFile->Read(TimCnt, sizeof(TimCnt)); StateFile->Read(TimCnt, sizeof(TimCnt));
// Load both SCSP states // Load both SCSP states
for (int i = 0; i < 2; i++) 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].DELAYBUF), sizeof(SCSPs[i].DELAYBUF));
StateFile->Read(&(SCSPs[i].DELAYPTR), sizeof(SCSPs[i].DELAYPTR)); StateFile->Read(&(SCSPs[i].DELAYPTR), sizeof(SCSPs[i].DELAYPTR));
#endif #endif
// Load each slot // Load each slot
for (int j = 0; j < 32; j++) for (int j = 0; j < 32; j++)
{ {
UINT64 baseOffset; UINT64 baseOffset;
UINT8 egState; UINT8 egState;
StateFile->Read(SCSPs[i].Slots[j].datab, sizeof(SCSPs[i].Slots[j].datab)); 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(&(SCSPs[i].Slots[j].active), sizeof(SCSPs[i].Slots[j].active));
StateFile->Read(&baseOffset, sizeof(baseOffset)); 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].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].slot), sizeof(SCSPs[i].Slots[j].slot));
StateFile->Read(&(SCSPs[i].Slots[j].Prev), sizeof(SCSPs[i].Slots[j].Prev)); StateFile->Read(&(SCSPs[i].Slots[j].Prev), sizeof(SCSPs[i].Slots[j].Prev));
// EG // EG
StateFile->Read(&(SCSPs[i].Slots[j].EG.volume), sizeof(SCSPs[i].Slots[j].EG.volume)); StateFile->Read(&(SCSPs[i].Slots[j].EG.volume), sizeof(SCSPs[i].Slots[j].EG.volume));
StateFile->Read(&egState, sizeof(egState)); 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.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.EGHOLD), sizeof(SCSPs[i].Slots[j].EG.EGHOLD));
StateFile->Read(&(SCSPs[i].Slots[j].EG.LPLINK), sizeof(SCSPs[i].Slots[j].EG.LPLINK)); StateFile->Read(&(SCSPs[i].Slots[j].EG.LPLINK), sizeof(SCSPs[i].Slots[j].EG.LPLINK));
// PLFO // PLFO
StateFile->Read(&(SCSPs[i].Slots[j].PLFO.phase), sizeof(SCSPs[i].Slots[j].PLFO.phase)); 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)); StateFile->Read(&(SCSPs[i].Slots[j].PLFO.phase_step), sizeof(SCSPs[i].Slots[j].PLFO.phase_step));
// ALFO // ALFO
StateFile->Read(&(SCSPs[i].Slots[j].ALFO.phase), sizeof(SCSPs[i].Slots[j].ALFO.phase)); 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)); 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 // Recompute LFOs
Compute_LFO(&(SCSPs[i].Slots[j])); Compute_LFO(&(SCSPs[i].Slots[j]));
} }
// DSP // DSP
StateFile->Read(&(SCSPs[i].DSP.RBP), sizeof(SCSPs[i].DSP.RBP)); StateFile->Read(&(SCSPs[i].DSP.RBP), sizeof(SCSPs[i].DSP.RBP));
StateFile->Read(&(SCSPs[i].DSP.RBL), sizeof(SCSPs[i].DSP.RBL)); StateFile->Read(&(SCSPs[i].DSP.RBL), sizeof(SCSPs[i].DSP.RBL));