From d951094e6da39d8d74e34e594c11c622249d0b51 Mon Sep 17 00:00:00 2001 From: saxxonpike Date: Sat, 1 Dec 2012 08:40:08 +0000 Subject: [PATCH] commodore64: Add 6526 2-cycle timer delay, seems to pass more tests now. CPU Dataport inputs on lower 3 bits are always high now, may fix some paging issues. Fix joystick input so that only port A is affected on pure outputs. --- .../Computers/Commodore64/C64.Input.cs | 3 +- .../Computers/Commodore64/MOS/MOS6510.cs | 24 +++++++-- .../Computers/Commodore64/MOS/MOS6526.cs | 50 ++++++++++++++++--- 3 files changed, 63 insertions(+), 14 deletions(-) diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.Input.cs b/BizHawk.Emulation/Computers/Commodore64/C64.Input.cs index 274fe1529f..ed2a739bc7 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.Input.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.Input.cs @@ -97,9 +97,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 } inputAdapter0.Data = resultA; - inputAdapter1.Data = resultB; + inputAdapter1.Data = (byte)(joyB & resultB); inputAdapter0.MaskWrite(joyB); - inputAdapter1.MaskWrite(joyA); } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs index c37ca46753..a1cd115c1b 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs @@ -21,6 +21,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private bool pinCharen; private bool pinLoram; private bool pinHiram; + private bool pinNMILast; private byte portDir; private bool unusedPin0; private bool unusedPin1; @@ -41,13 +42,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS cpu.WriteMemory = Write; // configure data port defaults - portDir = 0x2F; + portDir = 0xEF; SetPortData(0x37); // todo: verify this value (I only know that unconnected bits fade after a number of cycles) unusedPinTTLCycles = 40; unusedPinTTL0 = 0; unusedPinTTL1 = 0; + + // NMI is high on startup (todo: verify) + pinNMILast = true; } public void HardReset() @@ -73,7 +77,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { // the 6502 core expects active high // so we reverse the polarity here - cpu.NMI = !(chips.cia1.IRQ & chips.cartPort.NMI); + bool thisNMI = (chips.cia1.IRQ & chips.cartPort.NMI); + if (!thisNMI && pinNMILast) + cpu.NMI = true; + else + cpu.NMI = false; + pinNMILast = thisNMI; + cpu.IRQ = !(chips.vic.IRQ && chips.cia0.IRQ && chips.cartPort.IRQ); cpu.ExecuteOne(); } @@ -105,7 +115,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public void Poke(int addr, byte val) { if (addr == 0x0000) - portDir = val; + SetPortDir(val); else if (addr == 0x0001) SetPortData(val); else @@ -182,7 +192,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS set { Console.WriteLine("CPU write DIR: val=" + C64Util.ToBinary(value, 8)); - portDir = value; + SetPortDir(value); } } @@ -202,6 +212,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS unusedPinTTL1 = unusedPinTTLCycles; } + private void SetPortDir(byte val) + { + portDir = val; + SetPortData((byte)(PortData | ((byte)~val & 0x1F))); + } + // ------------------------------------ } } diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6526.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6526.cs index 7062014ddd..6f10f26443 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6526.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6526.cs @@ -61,6 +61,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private bool pinFlag; private bool pinPC; private byte sr; + private uint[] timerDelay; private InMode[] timerInMode; private OutMode[] timerOutMode; private bool[] timerPortEnable; @@ -82,6 +83,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS chipRegion = region; enableIntTimer = new bool[2]; intTimer = new bool[2]; + timerDelay = new uint[2]; timerInMode = new InMode[2]; timerOutMode = new OutMode[2]; timerPortEnable = new bool[2]; @@ -111,8 +113,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS if (timerPulse[1]) portData[1] &= PBOnMask[0]; - TimerRun(0); - TimerRun(1); + if (timerDelay[0] == 0) + TimerRun(0); + else + timerDelay[0]--; + + if (timerDelay[1] == 0) + TimerRun(1); + else + timerDelay[1]--; + intAlarm |= ( tod[0] == todAlarm[0] && tod[1] == todAlarm[1] && @@ -149,8 +159,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS intTimer[0] = false; intTimer[1] = false; sr = 0; - timerPortEnable[0] = false; - timerPortEnable[1] = false; + timerDelay[0] = 0; + timerDelay[1] = 0; timerInMode[0] = InMode.Phase2; timerInMode[1] = InMode.Phase2; timerOn[0] = false; @@ -402,6 +412,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private byte ReadRegister(ushort addr) { byte val = 0x00; //unused pin value + uint timerVal; switch (addr) { @@ -418,16 +429,20 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS val = portDir[1]; break; case 0x4: - val = (byte)(timer[0] & 0xFF); + timerVal = ReadTimerValue(0); + val = (byte)(timerVal & 0xFF); break; case 0x5: - val = (byte)(timer[0] >> 8); + timerVal = ReadTimerValue(0); + val = (byte)(timerVal >> 8); break; case 0x6: - val = (byte)(timer[1] & 0xFF); + timerVal = ReadTimerValue(1); + val = (byte)(timerVal & 0xFF); break; case 0x7: - val = (byte)(timer[1] >> 8); + timerVal = ReadTimerValue(1); + val = (byte)(timerVal >> 8); break; case 0x8: val = tod[0]; @@ -495,6 +510,21 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS return val; } + private uint ReadTimerValue(uint index) + { + if (timerOn[index]) + { + if (timer[index] == 0) + return timerLatch[index]; + else + return timer[index]; + } + else + { + return timer[index]; + } + } + public void Write(ushort addr, byte val) { Write(addr, val, 0xFF); @@ -622,6 +652,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS enableIntFlag = intReg; break; case 0xE: + if ((val & 0x01) != 0 && !timerOn[0]) + timerDelay[0] = 2; timerOn[0] = ((val & 0x01) != 0); timerPortEnable[0] = ((val & 0x02) != 0); timerOutMode[0] = ((val & 0x04) != 0) ? OutMode.Toggle : OutMode.Pulse; @@ -631,6 +663,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS todIn = ((val & 0x80) != 0); break; case 0xF: + if ((val & 0x01) != 0 && !timerOn[1]) + timerDelay[1] = 2; timerOn[1] = ((val & 0x01) != 0); timerPortEnable[1] = ((val & 0x02) != 0); timerOutMode[1] = ((val & 0x04) != 0) ? OutMode.Toggle : OutMode.Pulse;