commodore64: SID waveform data is now in a lookup table, increases performance and startup time

This commit is contained in:
saxxonpike 2012-11-15 06:56:19 +00:00
parent b4ed1fa822
commit 94beebdbde
3 changed files with 4230 additions and 239 deletions

View File

@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
public VoiceRegs()
{
Envelope = new EnvelopeGenerator();
Generator = new WaveformGenerator(WaveformCalculator.BuildTable());
Generator = new WaveformGenerator();
}
public void Clock()
@ -119,31 +119,35 @@ namespace BizHawk.Emulation.Computers.Commodore64
case 0x07:
case 0x0E:
index = addr / 7;
Voices[index].Generator.WriteFreqLo(value);
Voices[index].Generator.Frequency &= 0xFF00;
Voices[index].Generator.Frequency |= value;
break;
case 0x01:
case 0x08:
case 0x0F:
index = addr / 7;
Voices[index].Generator.WriteFreqHi(value);
Voices[index].Generator.Frequency &= 0xFF;
Voices[index].Generator.Frequency |= (int)value << 8;
break;
case 0x02:
case 0x09:
case 0x10:
index = addr / 7;
Voices[index].Generator.WritePWLo(value);
Voices[index].Generator.PulseWidth &= 0x0F00;
Voices[index].Generator.PulseWidth |= value;
break;
case 0x03:
case 0x0A:
case 0x11:
index = addr / 7;
Voices[index].Generator.WritePWHi(value);
Voices[index].Generator.PulseWidth &= 0xFF;
Voices[index].Generator.PulseWidth |= (int)(value & 0xF) << 8;
break;
case 0x04:
case 0x0B:
case 0x12:
index = addr / 7;
Voices[index].Generator.WriteControl(value);
Voices[index].Generator.Control = value;
Voices[index].Envelope.Gate = ((value & 0x01) != 0x00);
break;
case 0x05:
@ -241,6 +245,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
voices[0].Clock();
voices[1].Clock();
voices[2].Clock();
// sync voices
voices[0].Generator.Synchronize(voices[1].Generator, voices[2].Generator);
voices[1].Generator.Synchronize(voices[2].Generator, voices[0].Generator);
voices[2].Generator.Synchronize(voices[0].Generator, voices[1].Generator);
// finalize sample and put into buffer
SubmitSample();
// query pots every 512 cycles

View File

@ -9,32 +9,33 @@ namespace BizHawk.Emulation.Computers.Commodore64
// constants for the WaveformGenerator and calculation
// methods come from the libsidplayfp residfp library.
public class WaveformGenerator
public partial class WaveformGenerator
{
private int accumulator;
private byte control;
private int floatingOutputTtl;
private int freq;
private short[][] modelWave;
private bool msbRising;
private int noiseOutput;
private int noNoise;
private int noNoiseOrNoiseOutput;
private int noPulse;
private int pulseOutput;
private int pw;
private int ringMsbMask;
private int shiftPipeline;
private int shiftRegister;
private int shiftRegisterReset;
private int shiftRegisterDelay;
private int shiftRegisterResetDelay;
private bool sync;
private bool test;
private short[] wave;
private int waveform;
private int waveformOutput;
public WaveformGenerator(short[][] newModelWave)
// these are temp values used to speed up calculation
private int noNoise;
private int noNoiseOrNoiseOutput;
private int noPulse;
public WaveformGenerator()
{
modelWave = newModelWave;
Reset();
}
@ -42,11 +43,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
if (test)
{
if (shiftRegisterReset != 0 && --shiftRegisterReset == 0)
pulseOutput = 0xFFF;
if (shiftRegisterResetDelay != 0 && --shiftRegisterResetDelay == 0)
{
ResetShiftRegister();
}
pulseOutput = 0xFFF;
}
else
{
@ -58,9 +59,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
if ((accumulatorBitsSet & 0x080000) != 0)
{
shiftPipeline = 2;
shiftRegisterDelay = 2;
}
else if (shiftPipeline != 0 && --shiftPipeline == 0)
else if (shiftRegisterDelay != 0 && --shiftRegisterDelay == 0)
{
ClockShiftRegister();
}
@ -71,7 +72,62 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
int bit0 = ((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1;
shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF;
SetNoiseOutput();
UpdateNoiseOutput();
}
public byte Control
{
get
{
return control;
}
set
{
control = value;
int waveformPrev = waveform;
bool testPrev = test;
waveform = (control >> 4) & 0x0F;
test = (control & 0x08) != 0;
sync = (control & 0x02) != 0;
wave = WaveformSamples[waveform & 0x7];
ringMsbMask = ((~control >> 5) & (control >> 2) & 0x1) << 23;
noNoise = (waveform & 0x8) != 0 ? 0x000 : 0xFFF;
noNoiseOrNoiseOutput = noNoise | noiseOutput;
noPulse = (waveform & 0x4) != 0 ? 0x000 : 0xFFF;
if (!testPrev && test)
{
accumulator = 0;
shiftRegisterDelay = 0;
shiftRegisterResetDelay = 0x8000;
}
else if (testPrev && !test)
{
int bit0 = (~shiftRegister >> 17) & 0x1;
shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF;
UpdateNoiseOutput();
}
if (waveform == 0 && waveformPrev != 0)
{
floatingOutputTtl = 0x28000;
}
}
}
public int Frequency
{
get
{
return freq;
}
set
{
freq = value;
}
}
public short Output(WaveformGenerator ringModulator)
@ -96,47 +152,39 @@ namespace BizHawk.Emulation.Computers.Commodore64
return (short)waveformOutput;
}
public int ReadAccumulator()
public int PulseWidth
{
return accumulator;
}
public int ReadFreq()
{
return freq;
}
public byte ReadOsc()
{
return (byte)(waveformOutput >> 4);
}
public bool ReadSync()
{
return sync;
}
public bool ReadTest()
{
return test;
get
{
return pw;
}
set
{
pw = value;
}
}
public void Reset()
{
accumulator = 0;
control = 0;
waveform = 0;
freq = 0;
pw = 0;
msbRising = false;
waveform = 0;
accumulator = 0;
test = false;
sync = false;
wave = modelWave[0];
msbRising = false;
wave = WaveformSamples[0];
ringMsbMask = 0;
noNoise = 0xFFF;
noPulse = 0xFFF;
pulseOutput = 0xFFF;
ResetShiftRegister();
shiftPipeline = 0;
shiftRegisterDelay = 0;
waveformOutput = 0;
floatingOutputTtl = 0;
}
@ -144,11 +192,19 @@ namespace BizHawk.Emulation.Computers.Commodore64
private void ResetShiftRegister()
{
shiftRegister = 0x7FFFFF;
shiftRegisterReset = 0;
SetNoiseOutput();
shiftRegisterResetDelay = 0;
UpdateNoiseOutput();
}
private void SetNoiseOutput()
public void Synchronize(WaveformGenerator syncDest, WaveformGenerator syncSource)
{
if (msbRising && syncDest.sync && !(sync && syncSource.msbRising))
{
syncDest.accumulator = 0;
}
}
private void UpdateNoiseOutput()
{
noiseOutput =
((shiftRegister & 0x100000) >> 9) |
@ -162,71 +218,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
noNoiseOrNoiseOutput = noNoise | noiseOutput;
}
public void Synchronize(WaveformGenerator syncDest, WaveformGenerator syncSource)
{
if (msbRising && syncDest.sync && !(sync && syncSource.msbRising))
{
syncDest.accumulator = 0;
}
}
public void WriteControl(byte control)
{
int waveformPrev = waveform;
bool testPrev = test;
waveform = (control >> 4) & 0x0F;
test = (control & 0x08) != 0;
sync = (control & 0x02) != 0;
wave = modelWave[waveform & 0x7];
ringMsbMask = ((~control >> 5) & (control >> 2) & 0x1) << 23;
noNoise = (waveform & 0x8) != 0 ? 0x000 : 0xFFF;
noNoiseOrNoiseOutput = noNoise | noiseOutput;
noPulse = (waveform & 0x4) != 0 ? 0x000 : 0xFFF;
if (!testPrev && test)
{
accumulator = 0;
shiftPipeline = 0;
shiftRegisterReset = 0x8000;
}
else if (testPrev && !test)
{
int bit0 = (~shiftRegister >> 17) & 0x1;
shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF;
SetNoiseOutput();
}
if (waveform == 0 && waveformPrev != 0)
{
floatingOutputTtl = 0x28000;
}
}
public void WriteFreqLo(byte freqLo)
{
freq &= 0xFF00;
freq |= freqLo;
}
public void WriteFreqHi(byte freqHi)
{
freq &= 0x00FF;
freq |= (int)(freqHi << 8) & 0xFF00;
}
public void WritePWLo(byte pwLo)
{
pw &= 0x0F00;
pw |= pwLo;
}
public void WritePWHi(byte pwHi)
{
pw &= 0x00FF;
pw |= (int)(pwHi << 8) & 0x0F00;
}
private void WriteShiftRegister()
{
shiftRegister &=