commodore64: connect the 1541 disk drive to the system, memory domains also available

This commit is contained in:
saxxonpike 2012-12-07 05:24:00 +00:00
parent 526ad358d1
commit e3082b206b
6 changed files with 250 additions and 55 deletions

View File

@ -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();
}
// ------------------------------------

View File

@ -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; });

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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));
}
}
}

View File

@ -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;
}
}
// ------------------------------------