commodore64: connect the 1541 disk drive to the system, memory domains also available
This commit is contained in:
parent
526ad358d1
commit
e3082b206b
|
@ -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();
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
|
|
@ -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; });
|
||||
|
|
|
@ -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<int, byte>(board.cia1.Peek), new Action<int, byte>(board.cia1.Poke)));
|
||||
domains.Add(new MemoryDomain("VIC", 0x40, Endian.Little, new Func<int, byte>(board.vic.Peek), new Action<int, byte>(board.vic.Poke)));
|
||||
domains.Add(new MemoryDomain("SID", 0x20, Endian.Little, new Func<int, byte>(board.sid.Peek), new Action<int, byte>(board.sid.Poke)));
|
||||
domains.Add(new MemoryDomain("1541 Bus", 0x10000, Endian.Little, new Func<int, byte>(disk.Peek), new Action<int, byte>(disk.Poke)));
|
||||
domains.Add(new MemoryDomain("1541 VIA0", 0x10, Endian.Little, new Func<int, byte>(disk.PeekVia0), new Action<int, byte>(disk.PokeVia0)));
|
||||
domains.Add(new MemoryDomain("1541 VIA1", 0x10, Endian.Little, new Func<int, byte>(disk.PeekVia1), new Action<int, byte>(disk.PokeVia1)));
|
||||
domains.Add(new MemoryDomain("1541 RAM", 0x1000, Endian.Little, new Func<int, byte>(disk.PeekRam), new Action<int, byte>(disk.PokeRam)));
|
||||
memoryDomains = domains.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,5 +7,73 @@ namespace BizHawk.Emulation.Computers.Commodore64.Disk
|
|||
{
|
||||
public class VIC1541PLA
|
||||
{
|
||||
public Func<int, byte> PeekRam;
|
||||
public Func<int, byte> PeekRom;
|
||||
public Func<int, byte> PeekVia0;
|
||||
public Func<int, byte> PeekVia1;
|
||||
public Action<int, byte> PokeRam;
|
||||
public Action<int, byte> PokeRom;
|
||||
public Action<int, byte> PokeVia0;
|
||||
public Action<int, byte> PokeVia1;
|
||||
public Func<ushort, byte> ReadRam;
|
||||
public Func<ushort, byte> ReadRom;
|
||||
public Func<ushort, byte> ReadVia0;
|
||||
public Func<ushort, byte> ReadVia1;
|
||||
public Action<ushort, byte> WriteRam;
|
||||
public Action<ushort, byte> WriteRom;
|
||||
public Action<ushort, byte> WriteVia0;
|
||||
public Action<ushort, byte> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,51 +9,155 @@ namespace BizHawk.Emulation.Computers.Commodore64.Disk
|
|||
{
|
||||
public class VIC1541
|
||||
{
|
||||
public Action<SerialPort> Connect;
|
||||
public Action Execute;
|
||||
public Action HardReset;
|
||||
|
||||
public Func<int, byte> Peek;
|
||||
public Func<int, byte> PeekRom;
|
||||
public Func<int, byte> PeekRam;
|
||||
public Func<int, byte> PeekVia0;
|
||||
public Func<int, byte> PeekVia1;
|
||||
public Action<int, byte> Poke;
|
||||
public Action<int, byte> PokeRam;
|
||||
public Action<int, byte> PokeRom;
|
||||
public Action<int, byte> PokeVia0;
|
||||
public Action<int, byte> PokeVia1;
|
||||
public Func<ushort, byte> Read;
|
||||
public Func<ushort, byte> ReadRam;
|
||||
public Func<ushort, byte> ReadRom;
|
||||
public Func<ushort, byte> ReadVia0;
|
||||
public Func<ushort, byte> ReadVia1;
|
||||
public Action<ushort, byte> Write;
|
||||
public Action<ushort, byte> WriteRam;
|
||||
public Action<ushort, byte> WriteRom;
|
||||
public Action<ushort, byte> WriteVia0;
|
||||
public Action<ushort, byte> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
|
Loading…
Reference in New Issue