diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs b/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs index 12a75c6146..11cdd346e3 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs @@ -17,19 +17,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 PAL } - // emulated chips: - // U1: 6526 CIA0 - // U2: 6526 CIA1 - // U4: KERNAL & BASIC ROM - // U5: CHARACTER ROM - // U6: 6510 CPU - // U7: VIC 6567 (NTSC) or 6569 (PAL) - // U8: Memory multiplexer - // U9: SID 6581 or 8580 - // U10: RAM - // U11: RAM - // U19: 2114 color RAM - public partial class C64 : IEmulator { // ------------------------------------ @@ -129,6 +116,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 public void HardReset() { board.HardReset(); + disk.HardReset(); } // ------------------------------------ diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs b/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs index 966deeb679..794f8e40c6 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs @@ -70,28 +70,23 @@ namespace BizHawk.Emulation.Computers.Commodore64 // ----------------------------------------- - public void Execute(uint count) + public void Execute() { - while (count > 0) - { - WriteInputPort(); + WriteInputPort(); - cia0.ExecutePhase1(); - cia1.ExecutePhase1(); - pla.ExecutePhase1(); - sid.ExecutePhase1(); - vic.ExecutePhase1(); - cpu.ExecutePhase1(); + cia0.ExecutePhase1(); + cia1.ExecutePhase1(); + pla.ExecutePhase1(); + sid.ExecutePhase1(); + vic.ExecutePhase1(); + cpu.ExecutePhase1(); - cia0.ExecutePhase2(); - cia1.ExecutePhase2(); - pla.ExecutePhase2(); - sid.ExecutePhase2(); - vic.ExecutePhase2(); - cpu.ExecutePhase2(); - - count--; - } + cia0.ExecutePhase2(); + cia1.ExecutePhase2(); + pla.ExecutePhase2(); + sid.ExecutePhase2(); + vic.ExecutePhase2(); + cpu.ExecutePhase2(); } // ----------------------------------------- @@ -227,13 +222,14 @@ namespace BizHawk.Emulation.Computers.Commodore64 pla.WriteSid = ((ushort addr, byte val) => { address = addr; bus = val; sid.Write(addr, val); }); pla.WriteVic = ((ushort addr, byte val) => { address = addr; bus = val; vic.Write(addr, val); }); - serPort.DeviceReadAtn = (() => { return (cia1DataA & 0x08) != 0; }); - serPort.DeviceReadClock = (() => { return (cia1DataA & 0x10) != 0; }); - serPort.DeviceReadData = (() => { return (cia1DataA & 0x20) != 0; }); + // note: c64 serport lines are inverted + serPort.DeviceReadAtn = (() => { return (cia1DataA & 0x08) == 0; }); + serPort.DeviceReadClock = (() => { return (cia1DataA & 0x10) == 0; }); + serPort.DeviceReadData = (() => { return (cia1DataA & 0x20) == 0; }); serPort.DeviceReadReset = (() => { return true; }); // this triggers hard reset on ext device when low serPort.DeviceWriteAtn = ((bool val) => { }); // currently not wired - serPort.DeviceWriteClock = ((bool val) => { cia1DataA = Port.ExternalWrite(cia1DataA, (byte)(cia1DataA | (val ? 0x40 : 0x00)), cia1DirA); }); - serPort.DeviceWriteData = ((bool val) => { cia1DataA = Port.ExternalWrite(cia1DataA, (byte)(cia1DataA | (val ? 0x80 : 0x00)), cia1DirA); }); + serPort.DeviceWriteClock = ((bool val) => { cia1DataA = Port.ExternalWrite(cia1DataA, (byte)((cia1DataA & 0xBF) | (val ? 0x00 : 0x40)), cia1DirA); }); + serPort.DeviceWriteData = ((bool val) => { cia1DataA = Port.ExternalWrite(cia1DataA, (byte)((cia1DataA & 0x7F) | (val ? 0x00 : 0x80)), cia1DirA); }); serPort.DeviceWriteSrq = ((bool val) => { cia0FlagSerial = val; cia0.FLAG = cia0FlagCassette & cia0FlagSerial; }); sid.ReadPotX = (() => { return 0; }); diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.cs b/BizHawk.Emulation/Computers/Commodore64/C64.cs index c5c743f780..416fa82776 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.cs @@ -106,7 +106,11 @@ namespace BizHawk.Emulation.Computers.Commodore64 } board.PollInput(); - board.Execute(cyclesPerFrame); + for (uint count = cyclesPerFrame; count > 0; count--) + { + disk.Execute(); + board.Execute(); + } _islag = !board.inputRead; if (_islag) @@ -141,6 +145,10 @@ namespace BizHawk.Emulation.Computers.Commodore64 domains.Add(new MemoryDomain("CIA1", 0x10, Endian.Little, new Func(board.cia1.Peek), new Action(board.cia1.Poke))); domains.Add(new MemoryDomain("VIC", 0x40, Endian.Little, new Func(board.vic.Peek), new Action(board.vic.Poke))); domains.Add(new MemoryDomain("SID", 0x20, Endian.Little, new Func(board.sid.Peek), new Action(board.sid.Poke))); + domains.Add(new MemoryDomain("1541 Bus", 0x10000, Endian.Little, new Func(disk.Peek), new Action(disk.Poke))); + domains.Add(new MemoryDomain("1541 VIA0", 0x10, Endian.Little, new Func(disk.PeekVia0), new Action(disk.PokeVia0))); + domains.Add(new MemoryDomain("1541 VIA1", 0x10, Endian.Little, new Func(disk.PeekVia1), new Action(disk.PokeVia1))); + domains.Add(new MemoryDomain("1541 RAM", 0x1000, Endian.Little, new Func(disk.PeekRam), new Action(disk.PokeRam))); memoryDomains = domains.AsReadOnly(); } } diff --git a/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.PLA.cs b/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.PLA.cs index c15c84d7e5..90566fb8ff 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.PLA.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.PLA.cs @@ -7,5 +7,73 @@ namespace BizHawk.Emulation.Computers.Commodore64.Disk { public class VIC1541PLA { + public Func PeekRam; + public Func PeekRom; + public Func PeekVia0; + public Func PeekVia1; + public Action PokeRam; + public Action PokeRom; + public Action PokeVia0; + public Action PokeVia1; + public Func ReadRam; + public Func ReadRom; + public Func ReadVia0; + public Func ReadVia1; + public Action WriteRam; + public Action WriteRom; + public Action WriteVia0; + public Action WriteVia1; + + public byte Peek(int addr) + { + addr &= 0xFFFF; + if (addr >= 0x1800 && addr < 0x1C00) + return PeekVia0(addr); + else if (addr >= 0x1C00 && addr < 0x2000) + return PeekVia1(addr); + else if (addr >= 0xC000) + return PeekRom(addr); + else + return PeekRam(addr); + } + + public void Poke(int addr, byte val) + { + addr &= 0xFFFF; + if (addr >= 0x1800 && addr < 0x1C00) + PokeVia0(addr, val); + else if (addr >= 0x1C00 && addr < 0x2000) + PokeVia1(addr, val); + else if (addr >= 0xC000) + PokeRom(addr, val); + else + PokeRam(addr, val); + } + + public byte Read(ushort addr) + { + addr &= 0xFFFF; + if (addr >= 0x1800 && addr < 0x1C00) + return ReadVia0(addr); + else if (addr >= 0x1C00 && addr < 0x2000) + return ReadVia1(addr); + else if (addr >= 0xC000) + return ReadRom(addr); + else + return ReadRam(addr); + } + + public void Write(ushort addr, byte val) + { + addr &= 0xFFFF; + if (addr >= 0x1800 && addr < 0x1C00) + WriteVia0(addr, val); + else if (addr >= 0x1C00 && addr < 0x2000) + WriteVia1(addr, val); + else if (addr >= 0xC000) + WriteRom(addr, val); + else + WriteRam(addr, val); + } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.cs b/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.cs index b0b175bf3c..a02e6bffc8 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Disk/VIC1541.cs @@ -9,51 +9,155 @@ namespace BizHawk.Emulation.Computers.Commodore64.Disk { public class VIC1541 { + public Action Connect; + public Action Execute; + public Action HardReset; + + public Func Peek; + public Func PeekRom; + public Func PeekRam; + public Func PeekVia0; + public Func PeekVia1; + public Action Poke; + public Action PokeRam; + public Action PokeRom; + public Action PokeVia0; + public Action PokeVia1; + public Func Read; + public Func ReadRam; + public Func ReadRom; + public Func ReadVia0; + public Func ReadVia1; + public Action Write; + public Action WriteRam; + public Action WriteRom; + public Action WriteVia0; + public Action WriteVia1; + public VIC1541Motherboard board; public VIC1541(Region initRegion, byte[] rom) { - board = new VIC1541Motherboard(initRegion); - } + board = new VIC1541Motherboard(initRegion, rom); + Connect = board.Connect; + Execute = board.Execute; + HardReset = board.HardReset; - public void ConnectSerial(SerialPort newSerialPort) - { - board.Connect(newSerialPort); - } - - public void Execute() - { + Peek = board.pla.Peek; + PeekRam = board.pla.PeekRam; + PeekRom = board.pla.PeekRom; + PeekVia0 = board.pla.PeekVia0; + PeekVia1 = board.pla.PeekVia1; + Poke = board.pla.Poke; + PokeRam = board.pla.PokeRam; + PokeRom = board.pla.PokeRom; + PokeVia0 = board.pla.PokeVia0; + PokeVia1 = board.pla.PokeVia1; + Read = board.pla.Read; + ReadRam = board.pla.ReadRam; + ReadRom = board.pla.ReadRom; + ReadVia0 = board.pla.ReadVia0; + ReadVia1 = board.pla.ReadVia1; + Write = board.pla.Write; + WriteRam = board.pla.WriteRam; + WriteRom = board.pla.WriteRom; + WriteVia0 = board.pla.WriteVia0; + WriteVia1 = board.pla.WriteVia1; } } + // because the VIC1541 doesn't have bank switching like the system does, + // we simplify things by processing the rom bytes directly. + public class VIC1541Motherboard { public MOS6502X cpu; public VIC1541PLA pla; + public byte[] ram; + public byte[] rom; public SerialPort serPort; public MOS6522 via0; public MOS6522 via1; - public VIC1541Motherboard(Region initRegion) + public byte via0dirA; + public byte via0dirB; + public byte via0portA; + public byte via0portB; + public byte via1dirA; + public byte via1dirB; + public byte via1portA; + public byte via1portB; + + public VIC1541Motherboard(Region initRegion, byte[] initRom) { cpu = new MOS6502X(); pla = new VIC1541PLA(); + ram = new byte[0x800]; + rom = initRom; serPort = new SerialPort(); via0 = new MOS6522(); via1 = new MOS6522(); + + cpu.DummyReadMemory = pla.Read; + cpu.ReadMemory = pla.Read; + cpu.WriteMemory = pla.Write; + + pla.PeekRam = ((int addr) => { return ram[addr & 0x07FF]; }); + pla.PeekRom = ((int addr) => { return rom[addr & 0x3FFF]; }); + pla.PeekVia0 = via0.Peek; + pla.PeekVia1 = via1.Peek; + pla.PokeRam = ((int addr, byte val) => { ram[addr & 0x07FF] = val; }); + pla.PokeRom = ((int addr, byte val) => { }); + pla.PokeVia0 = via0.Poke; + pla.PokeVia1 = via1.Poke; + pla.ReadRam = ((ushort addr) => { return ram[addr & 0x07FF]; }); + pla.ReadRom = ((ushort addr) => { return rom[addr & 0x3FFF]; }); + pla.ReadVia0 = via0.Read; + pla.ReadVia1 = via1.Read; + pla.WriteRam = ((ushort addr, byte val) => { ram[addr & 0x07FF] = val; }); + pla.WriteRom = ((ushort addr, byte val) => { }); + pla.WriteVia0 = via0.Write; + pla.WriteVia1 = via1.Write; + + via0dirA = 0x00; + via0dirB = 0x00; + via0portA = 0xFF; + via0portB = 0xFF; + via1dirA = 0x00; + via1dirB = 0x00; + via1portA = 0xFF; + via1portB = 0xFF; } public void Connect(SerialPort newSerPort) { + // TODO: verify polarity serPort = newSerPort; serPort.SystemReadAtn = (() => { return true; }); - serPort.SystemReadClock = (() => { return true; }); - serPort.SystemReadData = (() => { return true; }); + serPort.SystemReadClock = (() => { return ((via0portB & 0x8) != 0); }); // bit 3 + serPort.SystemReadData = (() => { return ((via0portB & 0x2) != 0); }); // bit 1 serPort.SystemReadSrq = (() => { return true; }); - serPort.SystemWriteAtn = ((bool val) => { }); - serPort.SystemWriteClock = ((bool val) => { }); - serPort.SystemWriteData = ((bool val) => { }); + serPort.SystemWriteAtn = ((bool val) => { via0portB = Port.ExternalWrite(via0portB, (byte)((via0portB & 0x7F) | (val ? 0x80 : 0x00)), via0dirB); }); + serPort.SystemWriteClock = ((bool val) => { via0portB = Port.ExternalWrite(via0portB, (byte)((via0portB & 0xFB) | (val ? 0x04 : 0x00)), via0dirB); }); + serPort.SystemWriteData = ((bool val) => { via0portB = Port.ExternalWrite(via0portB, (byte)((via0portB & 0xFE) | (val ? 0x01 : 0x00)), via0dirB); }); serPort.SystemWriteReset = ((bool val) => { }); } + + public void Execute() + { + via0.ExecutePhase1(); + via1.ExecutePhase1(); + + cpu.ExecuteOne(); + via0.ExecutePhase2(); + via1.ExecutePhase2(); + } + + public void HardReset() + { + for (uint i = 0; i < 0x7FF; i++) + ram[i] = 0x00; + cpu.PC = (ushort)(cpu.ReadMemory(0xFFFC) | ((ushort)cpu.ReadMemory(0xFFFD) << 8)); + } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6522.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6522.cs index 5db144f14f..e2d3354fdb 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6522.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6522.cs @@ -22,20 +22,51 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public byte Peek(int addr) { - return 0; + return ReadRegister((ushort)(addr & 0xF)); } public void Poke(int addr, byte val) { + WriteRegister((ushort)(addr & 0xF), val); } public byte Read(ushort addr) { - return 0; + addr &= 0xF; + switch (addr) + { + default: + return ReadRegister(addr); + } + } + + private byte ReadRegister(ushort addr) + { + switch (addr) + { + default: + return 0; + } } public void Write(ushort addr, byte val) { + addr &= 0xF; + switch (addr) + { + default: + WriteRegister(addr, val); + break; + } + } + + private void WriteRegister(ushort addr, byte val) + { + switch (addr) + { + default: + break; + } } // ------------------------------------