diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.core.cs b/BizHawk.Emulation/Computers/Commodore64/C64.core.cs index 72f5c9c7ed..959f1f55f4 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.core.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.core.cs @@ -54,7 +54,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 vic = new VicII(signal, Region.NTSC); // initialize sid - sid = new Sid(); + sid = new Sid(Region.NTSC, 88200); // initialize memory (this must be done AFTER all other chips are initialized) string romPath = CoreInputComm.C64_FirmwaresPath; diff --git a/BizHawk.Emulation/Computers/Commodore64/Sid.cs b/BizHawk.Emulation/Computers/Commodore64/Sid.cs index e37a14dc6c..1d4f87ed9a 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Sid.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Sid.cs @@ -271,6 +271,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 public Func ReadPotY; public int clock; + public int cyclesPerSample; public bool[] envEnable = new bool[3]; public int[] envExpCounter = new int[3]; public int[] envRate = new int[3]; @@ -281,10 +282,20 @@ namespace BizHawk.Emulation.Computers.Commodore64 public SidRegs regs; public int[] waveClock = new int[3]; - public Sid() + public Sid(Region newRegion, int sampleRate) { ReadPotX = DummyReadPot; ReadPotY = DummyReadPot; + switch (newRegion) + { + case Region.NTSC: + cyclesPerSample = 14318181 / 14 / sampleRate; + break; + case Region.PAL: + cyclesPerSample = 14318181 / 18 / sampleRate; + break; + } + InitSound(sampleRate); HardReset(); } @@ -298,6 +309,18 @@ namespace BizHawk.Emulation.Computers.Commodore64 regs = new SidRegs(); } + private short Mix(int input, short mixSource) + { + input &= 0xFFF; + input -= 0x800; + input += mixSource; + if (input > 32767) + input = 32767; + else if (input < -32768) + input = -32768; + return (short)input; + } + public byte Peek(int addr) { return regs[addr & 0x1F]; @@ -312,6 +335,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 ProcessVoice(1); ProcessVoice(2); + SubmitSample(); + // query pots every 512 cycles if ((clock & 0x1FF) == 0x000) { @@ -364,19 +389,20 @@ namespace BizHawk.Emulation.Computers.Commodore64 int sawOutput; int squOutput; int noiseOutput; - int finalOutput = 0xFFFFFF; + int finalOutput = 0xFFF; bool outputEnabled = false; // triangle waveform if (regs.TRI[index]) { - triOutput = waveClock[index] >> 12; + triOutput = (waveClock[index] >> 12) & 0xFFF; if (regs.SYNC[index]) triOutput ^= regs.OSC[syncIndex[index]] & 0x800; if ((triOutput & 0x800) != 0x000) - triOutput &= 0xFFF; + triOutput ^= 0x7FF; + triOutput &= 0x7FF; triOutput <<= 1; finalOutput &= triOutput; outputEnabled = true; @@ -385,7 +411,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 // saw waveform if (regs.SAW[index]) { - sawOutput = waveClock[index] >> 12; + sawOutput = (waveClock[index] >> 12) & 0xFFF; finalOutput &= sawOutput; outputEnabled = true; } @@ -399,7 +425,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 } else { - if (regs.PW[index] >= (waveClock[index] >> 12)) + if (regs.PW[index] >= ((waveClock[index] >> 12) & 0xFFF)) squOutput = 0xFFF; else squOutput = 0x000; @@ -447,7 +473,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 if (outputEnabled) regs.OSC[index] = finalOutput; else - regs.OSC[index] = 0x000000; + regs.OSC[index] = 0x000; } public byte Read(ushort addr) diff --git a/BizHawk.Emulation/Computers/Commodore64/SidSoundProvider.cs b/BizHawk.Emulation/Computers/Commodore64/SidSoundProvider.cs index 621d675ff6..c7d33510a1 100644 --- a/BizHawk.Emulation/Computers/Commodore64/SidSoundProvider.cs +++ b/BizHawk.Emulation/Computers/Commodore64/SidSoundProvider.cs @@ -7,12 +7,37 @@ namespace BizHawk.Emulation.Computers.Commodore64 { public partial class Sid : ISoundProvider { + private short[] sampleBuffer; + private int sampleBufferCapacity; + private int sampleBufferIndex; + private int sampleBufferReadIndex; + private int sampleCounter; + public void GetSamples(short[] samples) { + int count = samples.Length; + int copied = 0; + + while ((sampleBufferIndex != sampleBufferReadIndex) && (copied < count)) + { + samples[copied] = sampleBuffer[sampleBufferReadIndex++]; + copied++; + if (sampleBufferReadIndex == sampleBufferCapacity) + sampleBufferReadIndex = 0; + } + } + + private void InitSound(int initSampleRate) + { + sampleBufferCapacity = initSampleRate; + DiscardSamples(); } public void DiscardSamples() { + sampleBuffer = new short[sampleBufferCapacity]; + sampleBufferReadIndex = 0; + sampleBufferIndex = 0; } public int MaxVolume @@ -25,5 +50,26 @@ namespace BizHawk.Emulation.Computers.Commodore64 { } } + + private void SubmitSample() + { + if (sampleCounter == 0) + { + short output; + output = Mix(regs.OSC[0], 0); + output = Mix(regs.OSC[1], output); + if (!regs.D3 && !regs.FILT[2]) + output = Mix(regs.OSC[2], output); + + // disable sound for now... + output = 0; + sampleCounter = cyclesPerSample; + sampleBuffer[sampleBufferIndex] = output; + sampleBufferIndex++; + if (sampleBufferIndex == sampleBufferCapacity) + sampleBufferIndex = 0; + } + sampleCounter--; + } } }