diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs b/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs index 54f7ead9e2..78ada27fbf 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs @@ -28,7 +28,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 public UserPort userPort; // state - public int address; + //public int address; public byte bus; public bool inputRead; public bool irq; @@ -62,7 +62,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 { cia0.ExecutePhase1(); cia1.ExecutePhase1(); - sid.ExecutePhase1(); vic.ExecutePhase1(); cpu.ExecutePhase1(); @@ -73,11 +72,15 @@ namespace BizHawk.Emulation.Computers.Commodore64 cpu.ExecutePhase2(); } + public void Flush() + { + sid.Flush(); + } + // ----------------------------------------- public void HardReset() { - address = 0xFFFF; bus = 0xFF; inputRead = false; @@ -122,7 +125,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 cpu.ReadNMI = cia1.ReadIRQBuffer; cpu.ReadPort = Cpu_ReadPort; cpu.ReadRDY = vic.ReadBABuffer; - cpu.ReadMemory = pla.Read; + cpu.ReadMemory = pla.Read; cpu.WriteMemory = pla.Write; pla.PeekBasicRom = basicRom.Peek; diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs b/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs index 11bcc992d0..a9c724fa9f 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs @@ -60,14 +60,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 return (userPort.ReadSerial2Buffer() && cia1.ReadSPBuffer()); } - byte Cpu_ReadMemory(int addr) - { - byte result = pla.ReadMemory(addr); - address = addr; - bus = result; - return result; - } - byte Cpu_ReadPort() { byte data = 0x1F; @@ -76,13 +68,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 return data; } - void Cpu_WriteMemory(int addr, byte val) - { - pla.WriteMemory(addr, val); - address = addr; - bus = val; - } - bool Glue_ReadIRQ() { return cia0.ReadIRQBuffer() & vic.ReadIRQBuffer() & cartPort.ReadIRQBuffer(); @@ -105,10 +90,10 @@ namespace BizHawk.Emulation.Computers.Commodore64 byte Pla_ReadColorRam(int addr) { - int result; - address = addr; - result = colorRam.Read(addr) | (bus & 0xF0); - return (byte)result; + byte result = bus; + result &= 0xF0; + result |= colorRam.Read(addr); + return result; } bool Pla_ReadHiRam() @@ -148,19 +133,13 @@ namespace BizHawk.Emulation.Computers.Commodore64 byte Vic_ReadMemory(int addr) { - switch (cia1.PortAData & 0x3) - { - case 0: - addr |= 0xC000; - break; - case 1: - addr |= 0x8000; - break; - case 2: - addr |= 0x4000; - break; - } - address = addr; + //p6 = a14 && !a13 && a12 && aec && game; + //p7 = a14 && !a13 && a12 && aec && !exrom && !game; + //(char rom from pla) + + + // the system sees (cia1.PortAData & 0x3) but we use a shortcut + addr |= (0x3 - (((cia1.PortALatch & cia1.PortADirection) | (~cia1.PortADirection)) & 0x3)) << 14; if ((addr & 0x7000) == 0x1000) bus = charRom.Read(addr); else diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.cs b/BizHawk.Emulation/Computers/Commodore64/C64.cs index 9551ed9ea2..66f259bad0 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.cs @@ -115,6 +115,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 //disk.Execute(); board.Execute(); } + board.Flush(); _islag = !board.inputRead; if (_islag) diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs index 8242e8383d..8a575ebf67 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs @@ -16,6 +16,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS //private bool freezeCpu; private bool pinNMILast; private LatchedPort port; + private bool thisNMI; public Func PeekMemory; public Action PokeMemory; @@ -72,7 +73,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public void ExecutePhase1() { - } + cpu.IRQ = !ReadIRQ(); + } public void ExecutePhase2() { @@ -80,16 +82,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS // the 6502 core expects active high // so we reverse the polarity here - bool thisNMI = ReadNMI(); + thisNMI = ReadNMI(); if (!thisNMI && pinNMILast) cpu.NMI = true; - else - cpu.NMI = false; - pinNMILast = thisNMI; - cpu.IRQ = !ReadIRQ(); if (ReadAEC()) + { cpu.ExecuteOne(); + pinNMILast = thisNMI; + } } // ------------------------------------ diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOSPLA.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOSPLA.cs index 4bb71b257c..6b24d26a82 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOSPLA.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOSPLA.cs @@ -92,29 +92,20 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS bool p3; bool p4; bool p5; - bool p6; - bool p7; bool p9; - bool p10; bool p11; - bool p12; bool p13; - bool p14; bool p15; - bool p16; bool p17; - bool p18; bool p19; bool p20; bool p21; bool p22; - bool p23; bool p24; bool p25; bool p26; bool p27; bool p28; - bool p30; bool loram; bool hiram; bool game; @@ -124,8 +115,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS bool a14; bool a13; bool a12; - bool aec; - bool cas; private PLABank Bank(int addr, bool read) { @@ -137,91 +126,93 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS a14 = (addr & 0x04000) != 0; a13 = (addr & 0x02000) != 0; a12 = (addr & 0x01000) != 0; - aec = !ReadAEC(); //active low - p0 = loram && hiram && a15 && !a14 && a13 && !aec && read && game; + // io/character access + if (a15 && a14 && !a13 && a12) + { + // character rom, banked in at D000-DFFF + charen = ReadCharen(); + if (read && !charen) + { + p3 = hiram && game; + p4 = loram && game; + p5 = hiram && !exrom && !game; + if (p3 || p4 || p5) + return PLABank.CharROM; + } + + // io block, banked in at D000-DFFF + p9 = hiram && charen && game; + p11 = loram && charen && game; + p13 = hiram && charen && !exrom && !game; + p15 = loram && charen && !exrom && !game; + p17 = exrom && !game; + if (p9 || p11 || p13 || p15 || p17) + { + if (addr < 0xD400) + return PLABank.Vic; + if (addr < 0xD800) + return PLABank.Sid; + if (addr < 0xDC00) + return PLABank.ColorRam; + if (addr < 0xDD00) + return PLABank.Cia0; + if (addr < 0xDE00) + return PLABank.Cia1; + if (addr < 0xDF00) + return PLABank.Expansion0; + return PLABank.Expansion1; + } + } + + // basic rom, banked at A000-BFFF + p0 = loram && hiram && a15 && !a14 && a13 && read && game; if (p0) return PLABank.BasicROM; + // kernal rom, banked at E000-FFFF exrom = ReadExRom(); - p1 = hiram && a15 && a14 && a13 && !aec && read && game; - p2 = hiram && a15 && a14 && a13 && !aec && read && !exrom && !game; - if (p1 || p2) - return PLABank.KernalROM; - - charen = ReadCharen(); - p3 = hiram && !charen && a15 && a14 && !a13 && a12 && !aec && read && game; - p4 = loram && !charen && a15 && a14 && !a13 && a12 && !aec && read && game; - p5 = hiram && !charen && a15 && a14 && !a13 && a12 && !aec && read && !exrom && !game; - p6 = a14 && !a13 && a12 && aec && game; - p7 = a14 && !a13 && a12 && aec && !exrom && !game; - if (p3 || p4 || p5 || p6 || p7) - return PLABank.CharROM; - - p9 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && read && game; - p10 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && !read && game; - p11 = loram && charen && a15 && a14 && !a13 && a12 && !aec && read && game; - p12 = loram && charen && a15 && a14 && !a13 && a12 && !aec && !read && game; - p13 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && read && !exrom && !game; - p14 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && !read && !exrom && !game; - p15 = loram && charen && a15 && a14 && !a13 && a12 && !aec && read && !exrom && !game; - p16 = loram && charen && a15 && a14 && !a13 && a12 && !aec && !read && !exrom && !game; - p17 = a15 && a14 && !a13 && a12 && !aec && read && exrom && !game; - p18 = a15 && a14 && !a13 && a12 && !aec && !read && exrom && !game; - if (p9 || p10 || p11 || p12 || p13 || p14 || p15 || p16 || p17 || p18) + if (hiram && a15 && a14 && a13 && read) { - switch (addr & 0x0F00) - { - case 0x000: - case 0x100: - case 0x200: - case 0x300: - return PLABank.Vic; - case 0x400: - case 0x500: - case 0x600: - case 0x700: - return PLABank.Sid; - case 0x800: - case 0x900: - case 0xA00: - case 0xB00: - return PLABank.ColorRam; - case 0xC00: - return PLABank.Cia0; - case 0xD00: - return PLABank.Cia1; - case 0xE00: - return PLABank.Expansion0; - case 0xF00: - return PLABank.Expansion1; - } - return PLABank.IO; + p1 = game; + p2 = !exrom && !game; + if (p1 || p2) + return PLABank.KernalROM; } - p19 = loram && hiram && a15 && !a14 && !a13 && !aec && read && !exrom; - p20 = a15 && !a14 && !a13 && !aec && exrom && !game; - if (p19 || p20) - return PLABank.CartridgeLo; + // cartridge low, banked at 8000-9FFF + if (a15 && !a14 && !a13) + { + p19 = loram && hiram && read && !exrom; + p20 = exrom && !game; + if (p19 || p20) + return PLABank.CartridgeLo; + } - p21 = hiram && a15 && !a14 && a13 && !aec && read && !exrom && !game; - p22 = a15 && a14 && a13 && !aec && exrom && !game; - p23 = a13 && a12 && aec && exrom && !game; - if (p21 || p22 || p23) - return PLABank.CartridgeHi; + // cartridge high, banked either at A000-BFFF or E000-FFFF depending + if (a15 && a13 && !game) + { + p21 = hiram && !a14 && read && !exrom; + p22 = a14 && exrom; + if (p21 || p22) + return PLABank.CartridgeHi; + } - cas = !true; //active low - p24 = !a15 && !a14 && a12 && exrom && !game; - p25 = !a15 && !a14 && a13 && exrom && !game; - p26 = !a15 && a14 && exrom && !game; - p27 = a15 && !a14 && a13 && exrom && !game; - p28 = a15 && a14 && !a13 && !a12 && exrom && !game; - p30 = cas; - if (!(p24 || p25 || p26 || p27 || p28 || p30)) + // ultimax mode ram exclusion + if (exrom && !game) + { + p24 = !a15 && !a14 && a12; + p25 = !a15 && !a14 && a13; + p26 = !a15 && a14; + p27 = a15 && !a14 && a13; + p28 = a15 && a14 && !a13 && !a12; + if (!(p24 || p25 || p26 || p27 || p28)) + return PLABank.RAM; + } + else + { return PLABank.RAM; - - //p31 = !cas && a15 && a14 && !a13 && a12 && !aec && !read; - //grw = p31; + } return PLABank.None; } @@ -335,8 +326,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { switch (Bank(addr, false)) { - case PLABank.BasicROM: - break; case PLABank.CartridgeHi: WriteCartridgeHi(addr, val); WriteMemory(addr, val); diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs index 504d668e1f..d6ec1990ba 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs @@ -55,11 +55,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS HardReset(); } - public void ExecutePhase1() - { - // do nothing - } - public void ExecutePhase2() { @@ -266,11 +261,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private class Voice { + private int accBits; + private int accNext; private int accumulator; + private bool controlTestPrev; + private int controlWavePrev; private int delay; private int floatOutputTTL; private int frequency; - private bool msbRising; + private bool msbRising; private int noise; private int noNoise; private int noNoiseOrNoise; @@ -286,6 +285,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private bool test; private int[] wave; private int waveform; + private int waveformIndex; private int[][] waveTable; public Voice(int[][] newWaveTable) @@ -315,11 +315,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS ResetShiftReg(); } - public void ExecutePhase1() - { - // do nothing - } - public void ExecutePhase2() { @@ -334,8 +329,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS } else { - int accNext = (accumulator + frequency) & 0xFFFFFF; - int accBits = ~accumulator & accNext; + accNext = (accumulator + frequency) & 0xFFFFFF; + accBits = ~accumulator & accNext; accumulator = accNext; msbRising = ((accBits & 0x800000) != 0); @@ -353,8 +348,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { { - int bit0 = ((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1; - shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF; + shiftRegister = ((shiftRegister << 1) | + (((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1) + ) & 0x7FFFFF; SetNoise(); } } @@ -410,8 +406,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { set { - int wavePrev = waveform; - bool testPrev = test; + controlWavePrev = waveform; + controlTestPrev = test; sync = ((value & 0x02) != 0); ringMod = ((value & 0x04) != 0); @@ -423,20 +419,21 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS noNoiseOrNoise = noNoise | noise; noPulse = ((waveform & 0x4) != 0) ? 0x000 : 0xFFF; - if (!testPrev && test) + if (!controlTestPrev && test) { accumulator = 0; delay = 0; shiftRegisterReset = 0x8000; } - else if (testPrev && !test) + else if (controlTestPrev && !test) { - int bit0 = (~shiftRegister >> 17) & 0x1; - shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF; + shiftRegister = ((shiftRegister << 1) | + ((~shiftRegister >> 17) & 0x1) + ) & 0x7FFFFF; SetNoise(); } - if (waveform == 0 && wavePrev != 0) + if (waveform == 0 && controlWavePrev != 0) floatOutputTTL = 0x28000; } } @@ -493,8 +490,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { if (waveform != 0) { - int index = (accumulator ^ (ringModSource.accumulator & ringMsbMask)) >> 12; - output = wave[index] & (noPulse | pulse) & noNoiseOrNoise; + waveformIndex = (accumulator ^ (ringModSource.accumulator & ringMsbMask)) >> 12; + output = wave[waveformIndex] & (noPulse | pulse) & noNoiseOrNoise; if (waveform > 8) WriteShiftReg(); } @@ -620,6 +617,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private static int[] syncNextTable = new int[] { 1, 2, 0 }; private static int[] syncPrevTable = new int[] { 2, 0, 1 }; + private int cachedCycles; private bool disableVoice3; private int[] envelopeOutput; private Envelope[] envelopes; @@ -629,10 +627,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private bool filterSelectBandPass; private bool filterSelectLoPass; private bool filterSelectHiPass; - private int potCounter; + private int mixer; + private int potCounter; private int potX; private int potY; - private int[] voiceOutput; + private short sample; + private int[] voiceOutput; private Voice[] voices; private int volume; private int[][] waveformTable; @@ -694,66 +694,55 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS // ------------------------------------ - public void ExecutePhase1() + public void ExecutePhase2() { - // do nothing - } + cachedCycles++; - public void ExecutePhase2() - { - - { - // potentiometer values refresh every 512 cycles - if (potCounter == 0) - { - potCounter = 512; - potX = ReadPotX(); //todo: implement paddles - potY = ReadPotY(); - } + // potentiometer values refresh every 512 cycles + if (potCounter == 0) + { + potCounter = 512; + potX = ReadPotX(); + potY = ReadPotY(); + Flush(); //this is here unrelated to the pots, just to keep the buffer somewhat loaded + } + potCounter--; + } - // process voices and envelopes - voices[0].ExecutePhase2(); - voices[1].ExecutePhase2(); - voices[2].ExecutePhase2(); - envelopes[0].ExecutePhase2(); - envelopes[1].ExecutePhase2(); - envelopes[2].ExecutePhase2(); + public void Flush() + { + while (cachedCycles > 0) + { + // process voices and envelopes + voices[0].ExecutePhase2(); + voices[1].ExecutePhase2(); + voices[2].ExecutePhase2(); + envelopes[0].ExecutePhase2(); + envelopes[1].ExecutePhase2(); + envelopes[2].ExecutePhase2(); - // process sync - for (int i = 0; i < 3; i++) - voices[i].Synchronize(voices[syncNextTable[i]], voices[syncPrevTable[i]]); + // process sync + for (int i = 0; i < 3; i++) + voices[i].Synchronize(voices[syncNextTable[i]], voices[syncPrevTable[i]]); - // get output - voiceOutput[0] = voices[0].Output(voices[2]); - voiceOutput[1] = voices[1].Output(voices[0]); - voiceOutput[2] = voices[2].Output(voices[1]); - envelopeOutput[0] = envelopes[0].Level; - envelopeOutput[1] = envelopes[1].Level; - envelopeOutput[2] = envelopes[2].Level; + // get output + voiceOutput[0] = voices[0].Output(voices[2]); + voiceOutput[1] = voices[1].Output(voices[0]); + voiceOutput[2] = voices[2].Output(voices[1]); + envelopeOutput[0] = envelopes[0].Level; + envelopeOutput[1] = envelopes[1].Level; + envelopeOutput[2] = envelopes[2].Level; - // process output - //if (bufferCounter == 0) - //{ - int mixer; - short sample; - //bufferCounter = bufferFrequency; + mixer = ((voiceOutput[0] * envelopeOutput[0]) >> 7); + mixer += ((voiceOutput[1] * envelopeOutput[1]) >> 7); + mixer += ((voiceOutput[2] * envelopeOutput[2]) >> 7); + mixer = (mixer * volume) >> 4; - // mix each channel (20 bits) - mixer = ((voiceOutput[0] * envelopeOutput[0]) >> 7); - mixer += ((voiceOutput[1] * envelopeOutput[1]) >> 7); - mixer += ((voiceOutput[2] * envelopeOutput[2]) >> 7); - mixer = (mixer * volume) >> 4; - - sample = (short)mixer; - //buffer[bufferIndex++] = sample; - //buffer[bufferIndex++] = sample; - resampler.EnqueueSample(sample, sample); - //if (bufferIndex == bufferLength) - // bufferIndex = 0; - //} - //bufferCounter--; - } - } + sample = (short)mixer; + resampler.EnqueueSample(sample, sample); + cachedCycles--; + } + } // ------------------------------------ @@ -777,6 +766,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS case 0x1A: case 0x1B: case 0x1C: + Flush(); result = ReadRegister(addr); break; } @@ -907,6 +897,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS // can't write to these break; default: + Flush(); WriteRegister(addr, val); break; } diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Timer.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Timer.cs index 727c44094f..c300b47a8f 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Timer.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Timer.cs @@ -47,6 +47,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS } } + public byte PortADirection + { + get + { + return portA.Direction; + } + } + + public byte PortALatch + { + get + { + return portA.Latch; + } + } + public byte PortBData { get @@ -55,6 +71,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS } } + public byte PortBDirection + { + get + { + return portB.Direction; + } + } + + public byte PortBLatch + { + get + { + return portB.Latch; + } + } + public bool ReadIRQBuffer() { return pinIRQ; } protected void SyncInternal(Serializer ser)