commodore64: VIC, SID, CIA0, CIA1, RAM have their own domains now, Memory is what is visible to the CPU

This commit is contained in:
saxxonpike 2012-11-12 15:52:31 +00:00
parent 86baf94dd4
commit 2c5f179da2
8 changed files with 315 additions and 134 deletions

View File

@ -81,6 +81,7 @@
<Compile Include="Buffer.cs" /> <Compile Include="Buffer.cs" />
<Compile Include="Computers\Commodore64\C64.core.cs" /> <Compile Include="Computers\Commodore64\C64.core.cs" />
<Compile Include="Computers\Commodore64\C64.cs" /> <Compile Include="Computers\Commodore64\C64.cs" />
<Compile Include="Computers\Commodore64\C64.PeekPoke.cs" />
<Compile Include="Computers\Commodore64\Cartridge.cs" /> <Compile Include="Computers\Commodore64\Cartridge.cs" />
<Compile Include="Computers\Commodore64\CartridgeMappers.cs" /> <Compile Include="Computers\Commodore64\CartridgeMappers.cs" />
<Compile Include="Computers\Commodore64\Cia.cs" /> <Compile Include="Computers\Commodore64\Cia.cs" />

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class C64 : IEmulator
{
public byte PeekCia0(int addr)
{
return cia0.Peek(addr);
}
public byte PeekCia1(int addr)
{
return cia1.Peek(addr);
}
public byte PeekColorRAM(int addr)
{
return (byte)((mem.colorRam[addr & 0x3FF] & 0xF) | mem.busData);
}
public byte PeekMemory(ushort addr)
{
return mem.Peek(addr);
}
public byte PeekMemoryInt(int addr)
{
return mem.Peek((ushort)(addr & 0xFFFF));
}
public byte PeekRAM(int addr)
{
return mem.PeekRam(addr);
}
public byte PeekSid(int addr)
{
return sid.Peek(addr);
}
public byte PeekVic(int addr)
{
return vic.Peek(addr);
}
public void PokeCia0(int addr, byte val)
{
cia0.Poke(addr, val);
}
public void PokeCia1(int addr, byte val)
{
cia1.Poke(addr, val);
}
public void PokeColorRAM(int addr, byte val)
{
mem.colorRam[addr & 0x3FF] = (byte)(val & 0xF);
}
public void PokeMemoryInt(int addr, byte val)
{
mem.Poke((ushort)(addr & 0xFFFF), val);
}
public void PokeRAM(int addr, byte val)
{
mem.PokeRam(addr, val);
}
public void PokeSid(int addr, byte val)
{
sid.Poke(addr, val);
}
public void PokeVic(int addr, byte val)
{
vic.Poke(addr, val);
}
}
}

View File

@ -7,6 +7,12 @@ using BizHawk.Emulation.CPUs.M6502;
namespace BizHawk.Emulation.Computers.Commodore64 namespace BizHawk.Emulation.Computers.Commodore64
{ {
public enum Region
{
NTSC,
PAL
}
public partial class C64 : IEmulator public partial class C64 : IEmulator
{ {
// input // input
@ -36,16 +42,16 @@ namespace BizHawk.Emulation.Computers.Commodore64
cpu.DummyReadMemory = PeekMemory; cpu.DummyReadMemory = PeekMemory;
// initialize cia timers // initialize cia timers
cia0 = new Cia(signal); cia0 = new Cia(signal, Region.NTSC);
cia0.ports[0] = new DirectionalDataPort(0x00, 0x00, 0xFF); cia0.ports[0] = new DirectionalDataPort(0x00, 0x00, 0xFF);
cia0.ports[1] = new DirectionalDataPort(0x00, 0x00, 0xFF); cia0.ports[1] = new DirectionalDataPort(0x00, 0x00, 0xFF);
cia1 = new Cia(signal); cia1 = new Cia(signal, Region.NTSC);
cia1.ports[0] = new DirectionalDataPort(0x00, 0x00, 0xFF); cia1.ports[0] = new DirectionalDataPort(0x00, 0x00, 0xFF);
cia1.ports[1] = new DirectionalDataPort(0x00, 0x00, 0xFF); cia1.ports[1] = new DirectionalDataPort(0x00, 0x00, 0xFF);
// initialize vic // initialize vic
signal = new ChipSignals(); signal = new ChipSignals();
vic = new VicII(signal, VicIIMode.NTSC); vic = new VicII(signal, Region.NTSC);
// initialize sid // initialize sid
sid = new Sid(); sid = new Sid();
@ -83,21 +89,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
} }
public byte PeekMemory(ushort addr)
{
return mem.Peek(addr);
}
public byte PeekMemoryInt(int addr)
{
return mem.Peek((ushort)(addr & 0xFFFF));
}
public void PokeMemoryInt(int addr, byte val)
{
// todo
}
public void PollInput() public void PollInput()
{ {
input.Poll(); input.Poll();

View File

@ -113,7 +113,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
private void SetupMemoryDomains() private void SetupMemoryDomains()
{ {
var domains = new List<MemoryDomain>(1); var domains = new List<MemoryDomain>(1);
domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func<int, byte>(PeekMemoryInt), new Action<int,byte>(PokeMemoryInt))); //TODO domains.Add(new MemoryDomain("Memory", 0x10000, Endian.Little, new Func<int, byte>(PeekMemoryInt), new Action<int, byte>(PokeMemoryInt)));
domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func<int, byte>(PeekRAM), new Action<int, byte>(PokeRAM)));
domains.Add(new MemoryDomain("CIA0", 0x10, Endian.Little, new Func<int, byte>(PeekCia0), new Action<int, byte>(PokeCia0)));
domains.Add(new MemoryDomain("CIA1", 0x10, Endian.Little, new Func<int, byte>(PeekCia1), new Action<int, byte>(PokeCia1)));
domains.Add(new MemoryDomain("SID", 0x20, Endian.Little, new Func<int, byte>(PeekSid), new Action<int, byte>(PokeSid)));
domains.Add(new MemoryDomain("VIC", 0x40, Endian.Little, new Func<int, byte>(PeekVic), new Action<int, byte>(PokeVic)));
domains.Add(new MemoryDomain("CRAM", 0x400, Endian.Little, new Func<int, byte>(PeekColorRAM), new Action<int, byte>(PokeColorRAM)));
memoryDomains = domains.AsReadOnly(); memoryDomains = domains.AsReadOnly();
} }

View File

@ -7,42 +7,38 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
public class CiaRegs public class CiaRegs
{ {
public bool ALARM; public bool ALARM; // alarm enabled
public int ALARM10; public int ALARM10; // alarm 10ths of a second
public int ALARMHR; public int ALARMHR; // alarm hours
public int ALARMMIN; public int ALARMMIN; // alarm minutes
public bool ALARMPM; public bool ALARMPM; // alarm AM/PM
public int ALARMSEC; public int ALARMSEC; // alarm seconds
public int[] DOR = new int[2]; public bool IALARM; // alarm interrupt triggered
public bool IALARM; public bool IFLG; // interrupt triggered on FLAG pin
public bool IFLG; public int[] INMODE = new int[2]; // timer input mode
public int[] INMODE = new int[2]; public bool IRQ; // interrupt triggered
public bool IRQ; public bool ISP; // shift register interrupt
public bool ISP; public bool[] IT = new bool[2]; // timer interrupt
public bool[] IT = new bool[2]; public bool[] LOAD = new bool[2]; // force load timer
public bool[] LOAD = new bool[2]; public bool[] OUTMODE = new bool[2]; // timer output mode
public bool[] OUTMODE = new bool[2]; public bool[] PBON = new bool[2]; // port bit modify on
public bool[] PBON = new bool[2]; public bool[] RUNMODE = new bool[2]; // running mode
public int[] PR = new int[2]; public int SDR; // serial shift register
public bool[] RUNMODE = new bool[2]; public bool SPMODE; // shift register mode
public int SDR; public bool[] START = new bool[2]; // timer enabled
public bool SPMODE; public int[] T = new int[2]; // timer counter
public bool[] START = new bool[2]; public int[] TLATCH = new int[2]; // timer latch (internal)
public int[] T = new int[2]; public int TOD10; // time of day 10ths of a second
public int[] TLATCH = new int[2]; public bool TODIN; // time of day/alarm set
public int TOD10; public int TODHR; // time of day hour
public bool TODIN; public int TODMIN; // time of day minute
public int TODHR; public bool TODPM; // time of day AM/PM
public int TODMIN; public int TODSEC; // time of day seconds
public bool TODPM;
public int TODSEC;
private DirectionalDataPort[] ports;
private ChipSignals signal; private ChipSignals signal;
public CiaRegs(ChipSignals newSignal, DirectionalDataPort[] newPorts) public CiaRegs(ChipSignals newSignal)
{ {
ports = newPorts;
signal = newSignal; signal = newSignal;
// power on state // power on state
@ -64,18 +60,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
addr &= 0x0F; addr &= 0x0F;
switch (addr) switch (addr)
{ {
case 0x00:
result = ports[0].Data;
break;
case 0x01:
result = ports[1].Data;
break;
case 0x02:
result = ports[0].Direction;
break;
case 0x03:
result = ports[1].Direction;
break;
case 0x04: case 0x04:
result = (T[0] & 0xFF); result = (T[0] & 0xFF);
break; break;
@ -145,18 +129,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
addr &= 0x0F; addr &= 0x0F;
switch (addr) switch (addr)
{ {
case 0x00:
ports[0].Data = val;
break;
case 0x01:
ports[1].Data = val;
break;
case 0x02:
ports[0].Direction = val;
break;
case 0x03:
ports[1].Direction = val;
break;
case 0x04: case 0x04:
T[0] &= 0xFF00; T[0] &= 0xFF00;
T[0] |= val; T[0] |= val;
@ -236,7 +208,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
public Func<bool> ReadSerial; public Func<bool> ReadSerial;
public Action<bool> WriteSerial; public Action<bool> WriteSerial;
public Cia(ChipSignals newSignal) public Cia(ChipSignals newSignal, Region newRegion)
{ {
signal = newSignal; signal = newSignal;
ReadSerial = ReadSerialDummy; ReadSerial = ReadSerialDummy;
@ -248,10 +220,28 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
outputBitMask = new byte[] { 0x40, 0x80 }; outputBitMask = new byte[] { 0x40, 0x80 };
ports = new DirectionalDataPort[2]; ports = new DirectionalDataPort[2];
regs = new CiaRegs(signal, ports); regs = new CiaRegs(signal);
underflow = new bool[2]; underflow = new bool[2];
} }
public byte Peek(int addr)
{
addr &= 0xF;
switch (addr)
{
case 0x00:
return ports[0].Data;
case 0x01:
return ports[1].Data;
case 0x02:
return ports[0].Direction;
case 0x03:
return ports[1].Direction;
default:
return regs[addr];
}
}
public void PerformCycle() public void PerformCycle()
{ {
lastCNT = thisCNT; lastCNT = thisCNT;
@ -289,12 +279,43 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
} }
public void Poke(int addr, byte val)
{
addr &= 0xF;
switch (addr)
{
case 0x00:
ports[0].Data = val;
break;
case 0x01:
ports[1].Data = val;
break;
case 0x02:
ports[0].Direction = val;
break;
case 0x03:
ports[1].Direction = val;
break;
default:
regs[addr] = val;
break;
}
}
public byte Read(ushort addr) public byte Read(ushort addr)
{ {
byte result; byte result;
switch (addr) switch (addr)
{ {
case 0x00:
return ports[0].Data;
case 0x01:
return ports[1].Data;
case 0x02:
return ports[0].Direction;
case 0x03:
return ports[1].Direction;
case 0x0D: case 0x0D:
// reading this reg clears it // reading this reg clears it
result = regs[0x0D]; result = regs[0x0D];
@ -358,6 +379,18 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
switch (addr) switch (addr)
{ {
case 0x00:
ports[0].Data = val;
break;
case 0x01:
ports[1].Data = val;
break;
case 0x02:
ports[0].Direction = val;
break;
case 0x03:
ports[1].Direction = val;
break;
case 0x04: case 0x04:
regs.TLATCH[0] &= 0xFF00; regs.TLATCH[0] &= 0xFF00;
regs.TLATCH[0] |= val; regs.TLATCH[0] |= val;

View File

@ -260,6 +260,68 @@ namespace BizHawk.Emulation.Computers.Commodore64
return result; return result;
} }
public byte PeekRam(int addr)
{
return ram[addr & 0xFFFF];
}
public void Poke(ushort addr, byte val)
{
if (addr == 0x0000)
{
cpuPort.Direction = val;
}
else if (addr == 0x0001)
{
cpuPort.Data = val;
UpdateLayout();
}
else
{
MemoryDesignation des = GetDesignation(addr);
switch (des)
{
case MemoryDesignation.Vic:
vic.Poke(addr, val);
break;
case MemoryDesignation.Sid:
sid.Poke(addr, val);
break;
case MemoryDesignation.ColorRam:
colorRam[addr & 0x03FF] = (byte)(val & 0x0F);
break;
case MemoryDesignation.Cia0:
cia0.Poke(addr, val);
break;
case MemoryDesignation.Cia1:
cia1.Poke(addr, val);
break;
case MemoryDesignation.Expansion0:
if (cart != null)
cart.WritePort(addr, val);
break;
case MemoryDesignation.Expansion1:
break;
case MemoryDesignation.RAM:
break;
default:
break;
}
// write through to ram
if (des != MemoryDesignation.Disabled)
{
ram[addr] = val;
}
}
}
public void PokeRam(int addr, byte val)
{
ram[addr & 0xFFFF] = val;
}
public byte Read(ushort addr) public byte Read(ushort addr)
{ {
byte result; byte result;

View File

@ -298,6 +298,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
regs = new SidRegs(); regs = new SidRegs();
} }
public byte Peek(int addr)
{
return regs[addr & 0x1F];
}
public void PerformCycle() public void PerformCycle()
{ {
// accumulator is 24 bits // accumulator is 24 bits
@ -315,6 +320,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
} }
public void Poke(int addr, byte val)
{
regs[addr & 0x1F] = val;
}
private void ProcessEnvelope(int index) private void ProcessEnvelope(int index)
{ {
// envelope counter is 15 bits // envelope counter is 15 bits

View File

@ -5,63 +5,57 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64 namespace BizHawk.Emulation.Computers.Commodore64
{ {
public enum VicIIMode
{
NTSC,
PAL
}
public class VicIIRegs public class VicIIRegs
{ {
public bool BMM; public bool BMM; // bitmap mode
public int[] BxC = new int[4]; public int[] BxC = new int[4]; // background colors
public int CB; public int CB; // character bitmap offset
public bool CSEL; public bool CSEL; // column select
public bool DEN; public bool DEN; // display enabled
public int EC; public int EC; // border color
public bool ECM; public bool ECM; // extra color mode
public bool ELP; public bool ELP; // enable lightpen interrupt
public bool EMBC; public bool EMBC; // enable sprite-data interrupt
public bool EMMC; public bool EMMC; // enable sprite-sprite interrupt
public bool ERST; public bool ERST; // enable raster line interrupt
public bool ILP; public bool ILP; // light pen interrupt active
public bool IMBC; public bool IMBC; // sprite-data interrupt active
public bool IMMC; public bool IMMC; // sprite-sprite interrupt active
public bool IRQ; public bool IRQ; // interrupt was triggered
public bool IRST; public bool IRST; // raster line interrupt active
public int LPX; public int LPX; // lightpen X coordinate
public int LPY; public int LPY; // lightpen Y coordinate
public int[] MC = new int[8]; // (internal) public int[] MC = new int[8]; // (internal)
public int[] MCBASE = new int[8]; // (internal) public int[] MCBASE = new int[8]; // (internal)
public bool MCM; public bool MCM; // multicolor mode
public bool[] MD = new bool[8]; // (internal) public bool[] MD = new bool[8]; // (internal)
public bool[] MDMA = new bool[8]; // (internal) public bool[] MDMA = new bool[8]; // (internal)
public int[] MMx = new int[2]; public int[] MMx = new int[2]; // sprite extra color
public int[] MPTR = new int[8]; // (internal) public int[] MPTR = new int[8]; // (internal)
public Int32[] MSR = new Int32[8]; // (internal) public Int32[] MSR = new Int32[8]; // (internal)
public bool[] MSRA = new bool[8]; // (internal) public bool[] MSRA = new bool[8]; // (internal)
public int[] MSRC = new int[8]; // (internal) public int[] MSRC = new int[8]; // (internal)
public int[] MxC = new int[8]; public int[] MxC = new int[8]; // sprite color
public bool[] MxD = new bool[8]; public bool[] MxD = new bool[8]; // sprite-data collision
public bool[] MxDP = new bool[8]; public bool[] MxDP = new bool[8]; // sprite priority
public bool[] MxE = new bool[8]; public bool[] MxE = new bool[8]; // sprite enabled
public bool[] MxM = new bool[8]; public bool[] MxM = new bool[8]; // sprite-sprite collision
public bool[] MxMC = new bool[8]; public bool[] MxMC = new bool[8]; // sprite multicolor
public int[] MxX = new int[8]; public int[] MxX = new int[8]; // sprite X coordinate
public bool[] MxXE = new bool[8]; public bool[] MxXE = new bool[8]; // sprite X expansion
public int[] MxY = new int[8]; public int[] MxY = new int[8]; // sprite Y coordinate
public bool[] MxYE = new bool[8]; public bool[] MxYE = new bool[8]; // sprite Y expansion
public bool[] MYE = new bool[8]; // (internal) public bool[] MYE = new bool[8]; // (internal)
public int RASTER; public int RASTER; // current raster line
public int RC; // (internal) public int RC; // (internal)
public bool RES; public bool RES; // reset bit (does nothing in this version of the VIC)
public bool RSEL; public bool RSEL; // row select
public int VC; // (internal) public int VC; // (internal)
public int VCBASE; // (internal) public int VCBASE; // (internal)
public int VM; public int VM; // video memory offset
public int VMLI; // (internal) public int VMLI; // (internal)
public int XSCROLL; public int XSCROLL; // X scroll position
public int YSCROLL; public int YSCROLL; // Y scroll position
public VicIIRegs() public VicIIRegs()
{ {
@ -441,16 +435,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
} }
public enum VicIITask
{
Idle,
VideoMatrix,
CharGen,
SpritePointer,
SpriteData,
DramRefresh
}
public partial class VicII : IVideoProvider public partial class VicII : IVideoProvider
{ {
// graphics buffer // graphics buffer
@ -516,7 +500,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int spriteFetchStartCycle; public int spriteFetchStartCycle;
public int spriteFetchIndex; public int spriteFetchIndex;
public bool spriteForeground; public bool spriteForeground;
public VicIITask task;
public int totalCycles; public int totalCycles;
public bool vBlank; public bool vBlank;
public int visibleBottom; public int visibleBottom;
@ -536,13 +519,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
private Action FetchG; private Action FetchG;
private Func<int> Plotter; private Func<int> Plotter;
public VicII(ChipSignals newSignal, VicIIMode videoMode) public VicII(ChipSignals newSignal, Region newRegion)
{ {
signal = newSignal; signal = newSignal;
switch (videoMode) switch (newRegion)
{ {
case VicIIMode.NTSC: case Region.NTSC:
totalCycles = 65; totalCycles = 65;
rasterTotalLines = 263; rasterTotalLines = 263;
rasterLineLeft = 0x19C; rasterLineLeft = 0x19C;
@ -558,7 +541,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
visibleHeight = 232; visibleHeight = 232;
renderOffset = 0; renderOffset = 0;
break; break;
case VicIIMode.PAL: case Region.PAL:
break; break;
default: default:
break; break;
@ -670,6 +653,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
spriteFetchIndex = 17; spriteFetchIndex = 17;
} }
public byte Peek(int addr)
{
return regs[addr & 0x3F];
}
public void PerformCycle() public void PerformCycle()
{ {
if (cycle >= totalCycles) if (cycle >= totalCycles)
@ -687,6 +675,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
signal.VicIRQ = regs.IRQ; signal.VicIRQ = regs.IRQ;
} }
public void Poke(int addr, byte val)
{
regs[addr & 0x3F] = val;
}
private void ProcessDisplayRegisters() private void ProcessDisplayRegisters()
{ {
// display enable check on line 030 (this must be run every cycle) // display enable check on line 030 (this must be run every cycle)