Commodore64: More preparation for savestates, condensed the PLA (this is as fast as it can get)

This commit is contained in:
saxxonpike 2013-08-18 03:58:39 +00:00
parent c3605a0181
commit e9bacfd683
15 changed files with 566 additions and 463 deletions

View File

@ -104,6 +104,7 @@
<Compile Include="Computers\Commodore64\Experimental\C64PAL.cs" />
<Compile Include="Computers\Commodore64\Experimental\Chips\Internals\Cia.Interface.cs" />
<Compile Include="Computers\Commodore64\Experimental\Chips\Internals\Cia.Internal.cs" />
<Compile Include="Computers\Commodore64\Experimental\Chips\Internals\Cpu.State.cs" />
<Compile Include="Computers\Commodore64\Experimental\Chips\Internals\Sid.SoundProvider.cs" />
<Compile Include="Computers\Commodore64\Experimental\Chips\Internals\Userport.cs" />
<Compile Include="Computers\Commodore64\Experimental\Chips\Internals\Vic.Cache.cs" />

View File

@ -10,76 +10,54 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental
public void InitializeConnections()
{
cia1.InputCNT = user.OutputCNT1;
cia1.InputData = ReadData;
cia1.InputFlag = ReadCia1Flag;
cia1.InputPortA = ReadCia1PortA;
cia1.InputPortB = ReadCia1PortB;
cia1.InputRead = cpu.OutputRead;
cia1.InputReset = ReadReset;
cia1.InputSP = user.OutputSP1;
cia2.InputCNT = user.OutputCNT2;
cia2.InputData = ReadData;
cia2.InputFlag = user.OutputFLAG2;
cia2.InputPortA = ReadCia2PortA;
cia2.InputPortB = user.OutputData;
cia2.InputRead = cpu.OutputRead;
cia2.InputReset = ReadReset;
cia2.InputSP = user.OutputSP2;
colorRam.InputData = ReadData;
colorRam.InputRead = cpu.OutputRead;
cpu.InputAEC = vic.OutputAEC;
cpu.InputData = ReadData;
cpu.InputIRQ = ReadIRQ;
cpu.InputNMI = ReadNMI;
cpu.InputPort = ReadCPUPort;
cpu.InputRDY = vic.OutputBA;
cpu.InputReset = ReadReset;
cpu.ReadMemory = pla.ReadMemory;
cpu.WriteMemory = pla.WriteMemory;
expansion.InputBA = vic.OutputBA;
expansion.InputData = ReadData;
expansion.InputHiExpansion = ReadHiExpansion;
expansion.InputHiRom = pla.OutputRomHi;
expansion.InputIRQ = ReadIRQ;
expansion.InputLoExpansion = ReadLoExpansion;
expansion.InputLoRom = pla.OutputRomLo;
expansion.InputNMI = ReadNMI;
expansion.InputRead = cpu.OutputRead;
expansion.InputReset = ReadReset;
//expansion.InputBA = vic.OutputBA;
//expansion.InputData = ReadData;
//expansion.InputHiExpansion = ReadHiExpansion;
//expansion.InputHiRom = pla.OutputRomHi;
//expansion.InputIRQ = ReadIRQ;
//expansion.InputLoExpansion = ReadLoExpansion;
//expansion.InputLoRom = pla.OutputRomLo;
//expansion.InputNMI = ReadNMI;
memory.InputData = ReadData;
memory.InputRead = cpu.OutputRead;
//pla.InputAEC = vic.OutputAEC;
//pla.InputBA = vic.OutputBA;
//pla.InputCharen = ReadCharen;
//pla.InputExRom = expansion.OutputExRom;
//pla.InputGame = expansion.OutputGame;
//pla.InputHiRam = ReadHiRam;
//pla.InputLoRam = ReadLoRam;
//pla.InputVA = ReadVicAddress;
pla.InputAEC = vic.OutputAEC;
pla.InputBA = vic.OutputBA;
pla.InputCharen = ReadCharen;
pla.InputExRom = expansion.OutputExRom;
pla.InputGame = expansion.OutputGame;
pla.InputHiRam = ReadHiRam;
pla.InputLoRam = ReadLoRam;
pla.InputRead = cpu.OutputRead;
pla.InputVA = ReadVicAddress;
//serial.InputATN = ReadSerialATN;
//serial.InputClock = ReadSerialCLK;
//serial.InputData = ReadSerialDTA;
serial.InputATN = ReadSerialATN;
serial.InputClock = ReadSerialCLK;
serial.InputData = ReadSerialDTA;
serial.InputReset = ReadReset;
user.InputCNT1 = cia1.OutputCNT;
user.InputCNT2 = cia2.OutputCNT;
user.InputData = cia2.OutputPortB;
user.InputPA2 = ReadUserPA2;
user.InputPC2 = cia2.OutputPC;
user.InputReset = ReadReset;
user.InputSP1 = cia1.OutputSP;
user.InputSP2 = cia2.OutputSP;
}
bool ReadCharen()
{
return (cpu.Port & 0x4) != 0;
//user.InputCNT1 = cia1.OutputCNT;
//user.InputCNT2 = cia2.OutputCNT;
//user.InputData = cia2.OutputPortB;
//user.InputPA2 = ReadUserPA2;
//user.InputPC2 = cia2.OutputPC;
//user.InputSP1 = cia1.OutputSP;
//user.InputSP2 = cia2.OutputSP;
}
bool ReadCia1Cnt()
@ -95,12 +73,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental
int ReadCia1PortA()
{
return (joystickB.Data | 0xE0) & keyboard.Column;
return joystickB.Data & keyboard.Column;
}
int ReadCia1PortB()
{
return (joystickA.Data | 0xE0) & keyboard.Row;
return joystickA.Data & keyboard.Row;
}
int ReadCia2PortA()
@ -120,83 +98,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental
return 0xFF;
}
int ReadData()
{
int addr = 0xFFFF;
int data = 0xFF;
data &= expansion.Data;
if (pla.Basic)
{
basicRom.Precache();
data &= basicRom.Data;
}
if (pla.CharRom)
{
characterRom.Precache();
data &= characterRom.Data;
}
if (pla.GraphicsRead)
{
colorRam.Precache();
data &= colorRam.Data;
}
if (pla.IO)
{
if ((addr & 0x0F00) == 0x0C00)
{
cia1.Precache();
data &= cia1.Data;
}
if ((addr & 0x0F00) == 0x0D00)
{
cia2.Precache();
data &= cia2.Data;
}
if ((addr & 0x0C00) == 0x0800)
{
colorRam.Precache();
data &= colorRam.Data;
}
if ((addr & 0x0C00) == 0x0400)
{
sid.Precache();
data &= sid.Data;
}
if ((addr & 0x0C00) == 0x0000)
{
vic.Precache();
}
}
if (vic.BA)
{
cpu.Precache();
data &= cpu.Data;
}
if (pla.Kernal)
{
kernalRom.Precache();
data &= kernalRom.Data;
}
if (pla.CASRam)
{
memory.Precache();
data &= memory.Data;
}
return data;
}
bool ReadHiExpansion()
{
int addr = 0xFFFF;
return (addr >= 0xDF00 && addr < 0xE000);
}
bool ReadHiRam()
{
return (cpu.Port & 0x2) != 0;
}
bool ReadIRQ()
{
return (

View File

@ -7,21 +7,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public partial class Cia
{
public Func<int> InputAddress;
public Func<bool> InputCNT;
public Func<int> InputData;
public Func<bool> InputFlag;
public Func<int> InputPortA;
public Func<int> InputPortB;
public Func<bool> InputRead;
public Func<bool> InputReset;
public Func<bool> InputSP;
public bool CNT { get { return true; } }
public int Data { get { return 0xFF; } }
public bool IRQ { get { return true; } }
public bool OutputCNT() { return CNT; }
public int OutputData() { return Data; }
public bool OutputIRQ() { return IRQ; }
public bool OutputPC() { return PC; }
public int OutputPortA() { return PortA; }

View File

@ -7,5 +7,23 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public partial class Cia
{
public int Peek(int addr)
{
return 0xFF;
}
public void Poke(int addr, int val)
{
}
public int Read(int addr)
{
return Peek(addr);
}
public void Write(int addr, int val)
{
Poke(addr, val);
}
}
}

View File

@ -7,23 +7,32 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
sealed public partial class Cpu
{
public Func<int> InputAddress;
public Func<bool> InputAEC;
public Func<int> InputData;
public Func<bool> InputIRQ;
public Func<bool> InputNMI;
public Func<int> InputPort;
public Func<bool> InputRDY;
public Func<bool> InputReset;
public Func<int, int> ReadMemory;
public Action<int, int> WriteMemory;
public int Address { get { return cachedAddress; } }
public int Data { get { return cachedData; } }
public int OutputAddress() { return Address; }
public int OutputData() { return Data; }
public int OutputPort() { return Port; }
public bool OutputRead() { return Read; }
public bool OutputPort0() { return Port0; }
public bool OutputPort1() { return Port1; }
public bool OutputPort2() { return Port2; }
public bool OutputPort3() { return Port3; }
public bool OutputPort4() { return Port4; }
public bool OutputPort5() { return Port5; }
public bool OutputPort6() { return Port6; }
public bool OutputPort7() { return Port7; }
public int Port { get { return cachedPort; } }
public bool Read { get { return cachedRead; } }
public bool Port0 { get { return (cachedPort & 0x01) != 0; } }
public bool Port1 { get { return (cachedPort & 0x02) != 0; } }
public bool Port2 { get { return (cachedPort & 0x04) != 0; } }
public bool Port3 { get { return (cachedPort & 0x08) != 0; } }
public bool Port4 { get { return (cachedPort & 0x10) != 0; } }
public bool Port5 { get { return (cachedPort & 0x20) != 0; } }
public bool Port6 { get { return (cachedPort & 0x40) != 0; } }
public bool Port7 { get { return (cachedPort & 0x80) != 0; } }
public void Precache() { }
public void SyncState(Serializer ser) { }
}

View File

@ -10,14 +10,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
int cachedAddress;
int cachedData;
bool cachedNMI;
int cachedPort;
bool cachedRead;
int delayCycles;
bool nmiBuffer;
int portDirection;
int portLatch;
MOS6502X processor;
bool resetBuffer;
bool resetEdge;
int resetPC;
public Cpu()
@ -26,80 +25,47 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
processor.DummyReadMemory = CoreReadMemory;
processor.ReadMemory = CoreReadMemory;
processor.WriteMemory = CoreWriteMemory;
resetBuffer = false;
resetEdge = false;
cachedAddress = 0xFFFF;
cachedData = 0xFF;
cachedPort = 0xFF;
cachedRead = true;
Reset();
}
public void Clock()
{
bool reset = InputReset();
if (reset)
if (delayCycles > 0)
{
if (delayCycles > 0)
delayCycles--;
if (delayCycles == 1)
{
delayCycles--;
if (delayCycles == 1)
{
cachedAddress = 0xFFFC;
resetPC = InputData();
}
else if (delayCycles == 0)
{
cachedAddress = 0xFFFD;
resetPC |= InputData() << 8;
processor.PC = (ushort)resetPC;
}
resetPC = ReadMemory(0xFFFC);
}
else
else if (delayCycles == 0)
{
if (!resetBuffer)
{
// perform these actions on positive edge of /reset
processor.Reset();
processor.BCD_Enabled = true;
processor.PC = (ushort)((CoreReadMemory(0xFFFD) << 8) | CoreReadMemory(0xFFFC));
}
else if (InputAEC())
{
processor.IRQ = !InputIRQ(); //6502 core expects inverted input
processor.NMI = !InputNMI(); //6502 core expects inverted input
processor.RDY = InputRDY();
processor.ExecuteOne();
}
resetPC |= ReadMemory(0xFFFD) << 8;
processor.PC = (ushort)resetPC;
}
}
else
{
cachedAddress = 0xFFFF;
cachedData = 0xFF;
delayCycles = 8;
portDirection = 0xFF;
portLatch = 0xFF;
if (InputAEC())
{
processor.IRQ = !InputIRQ(); //6502 core expects inverted input
nmiBuffer = InputNMI();
if (!nmiBuffer && cachedNMI)
processor.NMI = true; //6502 core expects inverted input
cachedNMI = nmiBuffer;
processor.RDY = InputRDY();
processor.ExecuteOne();
}
}
resetBuffer = reset;
}
byte CoreReadMemory(ushort addr)
{
cachedAddress = addr;
cachedRead = true;
if (addr == 0x0000)
{
cachedData = portDirection;
}
return (byte)(portDirection & 0xFF);
else if (addr == 0x0001)
{
cachedData = InputPort() | (portDirection ^ 0xFF);
}
return (byte)((InputPort() | (portDirection ^ 0xFF)) & 0xFF);
else
{
cachedData = InputData();
}
return (byte)(cachedData & 0xFF);
return (byte)(ReadMemory(addr) & 0xFF);
}
void CoreWriteMemory(ushort addr, byte val)
@ -107,19 +73,19 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
cachedAddress = addr;
cachedData = val;
if (addr == 0x0000)
{
cachedRead = true;
portDirection = val;
}
else if (addr == 0x0001)
{
cachedRead = true;
portLatch = val;
}
else
{
cachedRead = false;
}
WriteMemory(addr, val);
}
public void Reset()
{
delayCycles = 6;
processor.Reset();
processor.BCD_Enabled = true;
processor.PC = (ushort)((CoreReadMemory(0xFFFD) << 8) | CoreReadMemory(0xFFFC));
}
}
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
sealed public partial class Cpu
{
}
}

View File

@ -7,216 +7,348 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
sealed public class Pla
{
#region CACHE
bool[] basicStates;
bool[] casStates;
bool[] charStates;
bool[] grStates;
bool[] ioStates;
bool[] kernalStates;
bool[] romHiStates;
bool[] romLoStates;
bool cachedBasic;
bool cachedCASRam;
bool cachedCharRom;
bool cachedGraphicsRead;
bool cachedIO;
bool cachedKernal;
bool cachedRomHi;
bool cachedRomLo;
#endregion
#region INPUTS
public Func<int> InputAddress;
public Func<bool> InputAEC;
public Func<bool> InputBA;
public Func<bool> InputCAS;
public Func<bool> InputCharen;
public Func<bool> InputExRom;
public Func<bool> InputGame;
public Func<bool> InputHiRam;
public Func<bool> InputLoRam;
public Func<bool> InputRead;
public Func<int> InputVA;
#endregion
#region OUTPUTS
public bool Basic { get { return cachedBasic; } }
public bool CASRam { get { return cachedCASRam; } }
public bool CharRom { get { return cachedCharRom; } }
public bool GraphicsRead { get { return cachedGraphicsRead; } }
public bool IO { get { return cachedIO; } }
public bool Kernal { get { return cachedKernal; } }
public bool OutputBasic() { return Basic; }
public bool OutputCASRam() { return CASRam; }
public bool OutputCharRom() { return CharRom; }
public bool OutputGraphicsRead() { return GraphicsRead; }
public bool OutputIO() { return IO; }
public bool OutputKernal() { return Kernal; }
public bool OutputRomHi() { return RomHi; }
public bool OutputRomLo() { return RomLo; }
public bool RomHi { get { return cachedRomHi; } }
public bool RomLo { get { return cachedRomLo; } }
public void SyncState(Serializer ser) { }
#endregion
public Func<int, int> PeekBasicRom;
public Func<int, int> PeekCartridgeLo;
public Func<int, int> PeekCartridgeHi;
public Func<int, int> PeekCharRom;
public Func<int, int> PeekCia1;
public Func<int, int> PeekCia2;
public Func<int, int> PeekColorRam;
public Func<int, int> PeekExpansionLo;
public Func<int, int> PeekExpansionHi;
public Func<int, int> PeekKernalRom;
public Func<int, int> PeekMemory;
public Func<int, int> PeekSid;
public Func<int, int> PeekVic;
public Action<int, int> PokeCartridgeLo;
public Action<int, int> PokeCartridgeHi;
public Action<int, int> PokeCia1;
public Action<int, int> PokeCia2;
public Action<int, int> PokeColorRam;
public Action<int, int> PokeExpansionLo;
public Action<int, int> PokeExpansionHi;
public Action<int, int> PokeMemory;
public Action<int, int> PokeSid;
public Action<int, int> PokeVic;
public Func<int, int> ReadBasicRom;
public Func<int, int> ReadCartridgeLo;
public Func<int, int> ReadCartridgeHi;
public Func<int, int> ReadCharRom;
public Func<int, int> ReadCia1;
public Func<int, int> ReadCia2;
public Func<int, int> ReadColorRam;
public Func<int, int> ReadExpansionLo;
public Func<int, int> ReadExpansionHi;
public Func<int, int> ReadKernalRom;
public Func<int, int> ReadMemory;
public Func<int, int> ReadSid;
public Func<int, int> ReadVic;
public Action<int, int> WriteCartridgeLo;
public Action<int, int> WriteCartridgeHi;
public Action<int, int> WriteCia1;
public Action<int, int> WriteCia2;
public Action<int, int> WriteColorRam;
public Action<int, int> WriteExpansionLo;
public Action<int, int> WriteExpansionHi;
public Action<int, int> WriteMemory;
public Action<int, int> WriteSid;
public Action<int, int> WriteVic;
#region LOOKUP_TABLE_GENERATOR
// PLA line information is from the PDF titled "The C64 PLA Dissected"
// Written by Thomas 'skoe' Giesel.
void GenerateLookup()
enum PLABank
{
bool a12;
bool a13;
bool a14;
bool a15;
bool aec;
bool ba;
bool cas;
bool charen;
bool exrom;
bool game;
bool hiram;
bool loram;
bool p0;
bool p1;
bool p2;
bool p3;
bool p4;
bool p5;
bool p6;
bool p7;
bool p9;
bool p10;
bool p11;
bool p12;
bool p13;
bool p14;
bool p15;
bool p16;
bool p17;
bool p18;
bool p19;
bool p20;
bool p21;
bool p22;
bool p23;
bool p24;
bool p25;
bool p26;
bool p27;
bool p28;
bool p30;
bool p31;
bool read;
bool va12;
bool va13;
bool va14;
None,
RAM,
BasicROM,
KernalROM,
CharROM,
IO,
CartridgeLo,
CartridgeHi,
Vic,
Sid,
ColorRam,
Cia1,
Cia2,
ExpansionLo,
ExpansionHi
}
basicStates = new bool[65536];
casStates = new bool[65536];
charStates = new bool[65536];
grStates = new bool[65536];
ioStates = new bool[65536];
kernalStates = new bool[65536];
romHiStates = new bool[65536];
romLoStates = new bool[65536];
bool p0;
bool p1;
bool p2;
bool p3;
bool p4;
bool p5;
bool p6;
bool p7;
bool p9;
bool p11;
bool p13;
bool p15;
bool p17;
bool p19;
bool p20;
bool p21;
bool p22;
bool p23;
bool p24;
bool p25;
bool p26;
bool p27;
bool p28;
bool loram;
bool hiram;
bool game;
bool exrom;
bool charen;
bool a15;
bool a14;
bool a13;
bool a12;
for (int i = 0; i < 65536; i++)
public int Peek(int addr)
{
switch (Resolve(addr, true))
{
aec = (i & 0x0001) != 0;
ba = (i & 0x0002) != 0;
cas = (i & 0x0004) != 0;
charen = (i & 0x0008) != 0;
exrom = (i & 0x0010) != 0;
game = (i & 0x0020) != 0;
loram = (i & 0x0040) != 0;
hiram = (i & 0x0080) != 0;
read = (i & 0x0100) != 0;
va12 = (i & 0x0200) != 0;
va13 = (i & 0x0400) != 0;
va14 = (i & 0x0800) != 0;
a12 = (i & 0x1000) != 0;
a13 = (i & 0x2000) != 0;
a14 = (i & 0x4000) != 0;
a15 = (i & 0x8000) != 0;
case PLABank.BasicROM:
return PeekBasicRom(addr);
case PLABank.CartridgeHi:
return PeekCartridgeHi(addr);
case PLABank.CartridgeLo:
return PeekCartridgeLo(addr);
case PLABank.CharROM:
return PeekCharRom(addr);
case PLABank.Cia1:
return PeekCia1(addr);
case PLABank.Cia2:
return PeekCia2(addr);
case PLABank.ColorRam:
return PeekColorRam(addr);
case PLABank.ExpansionLo:
return PeekExpansionLo(addr);
case PLABank.ExpansionHi:
return PeekExpansionHi(addr);
case PLABank.KernalROM:
return PeekKernalRom(addr);
case PLABank.RAM:
return PeekMemory(addr);
case PLABank.Sid:
return PeekSid(addr);
case PLABank.Vic:
return PeekVic(addr);
}
return 0xFF;
}
p0 = loram && hiram && a15 && !a14 && a13 && !aec && read && game;
p1 = hiram && a15 && a14 && a13 && !aec && read && game;
p2 = hiram && a15 && a14 && a13 && !aec && read && !exrom && !game;
p3 = hiram && !charen && a15 && a14 && !a13 && a12 && !aec && read && game;
p4 = loram && !charen && a15 && a14 && !a13 && a12 && !aec && read && game;
p5 = hiram && !charen && a15 && a14 && !a13 && a12 && !aec && read && !exrom && !game;
p6 = va14 && !va13 && va12 && aec && game;
p7 = va14 && !va13 && va12 && aec && !exrom && !game;
//p8 = cas && a15 && a14 && !a13 && a12 && !aec && !rd;
p9 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && ba && read && game;
p10 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && !read && game;
p11 = loram && charen && a15 && a14 && !a13 && a12 && !aec && ba && read && game;
p12 = loram && charen && a15 && a14 && !a13 && a12 && !aec && !read && game;
p13 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && ba && read && !exrom && !game;
p14 = hiram && charen && a15 && a14 && !a13 && a12 && !aec && !read && !exrom && !game;
p15 = loram && charen && a15 && a14 && !a13 && a12 && !aec && ba && read && !exrom && !game;
p16 = loram && charen && a15 && a14 && !a13 && a12 && !aec && !read && !exrom && !game;
p17 = a15 && a14 && !a13 && a12 && !aec && ba && read && exrom && !game;
p18 = a15 && a14 && !a13 && a12 && !aec && !read && exrom && !game;
p19 = loram && hiram && a15 && !a14 && !a13 && !aec && read && !exrom;
p20 = a15 && !a14 && !a13 && !aec && exrom && !game;
p21 = hiram && a15 && !a14 && a13 && !aec && read && !exrom && !game;
p22 = a15 && a14 && a13 && !aec && exrom && !game;
p23 = va13 && va12 && aec && exrom && !game;
p24 = !a15 && !a14 && a12 && exrom && !game;
p25 = !a15 && !a14 && a13 && exrom && !game;
p26 = !a15 && a14 && exrom && !game;
p27 = a15 && !a14 && a13 && exrom && !game;
p28 = a15 && a14 && !a13 && !a12 && exrom && !game;
//p29 = !cas;
p30 = cas;
p31 = !cas && a15 && a14 && !a13 && a12 && !aec && !read;
casStates[i] = (p0 || p1 || p2 || p3 || p4 || p5 || p6 || p7 || p9 || p10 || p11 || p12 || p13 || p14 || p15 || p16 || p17 || p18 || p19 || p20 || p21 || p22 || p23 || p24 || p25 || p26 || p27 || p28 || p30);
basicStates[i] = (!p0);
kernalStates[i] = (!(p1 || p2));
charStates[i] = (!(p3 || p4 || p5 || p6 || p7));
grStates[i] = (!p31);
ioStates[i] = (!(p9 || p10 || p11 || p12 || p13 || p14 || p15 || p16 || p17 || p18));
romLoStates[i] = (!(p19 || p20));
romHiStates[i] = (!(p21 || p22 || p23));
public void Poke(int addr, int val)
{
switch (Resolve(addr, false))
{
case PLABank.CartridgeHi:
PokeCartridgeHi(addr, val);
break;
case PLABank.CartridgeLo:
PokeCartridgeLo(addr, val);
break;
case PLABank.Cia1:
PokeCia1(addr, val);
break;
case PLABank.Cia2:
PokeCia2(addr, val);
break;
case PLABank.ColorRam:
PokeColorRam(addr, val);
break;
case PLABank.ExpansionLo:
PokeExpansionLo(addr, val);
break;
case PLABank.ExpansionHi:
PokeExpansionHi(addr, val);
break;
case PLABank.RAM:
PokeMemory(addr, val);
break;
case PLABank.Sid:
PokeSid(addr, val);
break;
case PLABank.Vic:
PokeVic(addr, val);
break;
}
}
#endregion
public Pla()
public int Read(int addr)
{
GenerateLookup();
switch (Resolve(addr, true))
{
case PLABank.BasicROM:
return ReadBasicRom(addr);
case PLABank.CartridgeHi:
return ReadCartridgeHi(addr);
case PLABank.CartridgeLo:
return ReadCartridgeLo(addr);
case PLABank.CharROM:
return ReadCharRom(addr);
case PLABank.Cia1:
return ReadCia1(addr);
case PLABank.Cia2:
return ReadCia2(addr);
case PLABank.ColorRam:
return ReadColorRam(addr);
case PLABank.ExpansionLo:
return ReadExpansionLo(addr);
case PLABank.ExpansionHi:
return ReadExpansionHi(addr);
case PLABank.KernalROM:
return ReadKernalRom(addr);
case PLABank.RAM:
return ReadMemory(addr);
case PLABank.Sid:
return ReadSid(addr);
case PLABank.Vic:
return ReadVic(addr);
}
return 0xFF;
}
public void Precache()
PLABank Resolve(int addr, bool read)
{
int stateIndex = (
(InputAEC() ? 0x1 : 0) |
(InputBA() ? 0x2 : 0) |
(InputCAS() ? 0x4 : 0) |
(InputCharen() ? 0x8 : 0) |
(InputExRom() ? 0x10 : 0) |
(InputGame() ? 0x20 : 0) |
(InputLoRam() ? 0x40 : 0) |
(InputHiRam() ? 0x80 : 0) |
(InputRead() ? 0x100 : 0) |
((InputVA() & 0x7000) >> 3) |
(InputAddress() & 0xF000)
);
loram = InputLoRam();
hiram = InputHiRam();
game = InputGame();
cachedBasic = basicStates[stateIndex];
cachedCASRam = casStates[stateIndex];
cachedCharRom = charStates[stateIndex];
cachedGraphicsRead = grStates[stateIndex];
cachedIO = ioStates[stateIndex];
cachedKernal = kernalStates[stateIndex];
cachedRomHi = romHiStates[stateIndex];
cachedRomLo = romLoStates[stateIndex];
a15 = (addr & 0x08000) != 0;
a14 = (addr & 0x04000) != 0;
a13 = (addr & 0x02000) != 0;
a12 = (addr & 0x01000) != 0;
// upper memory regions 8000-FFFF
if (a15)
{
// io/character access
if (a14 && !a13 && a12)
{
// character rom, banked in at D000-DFFF
charen = InputCharen();
if (read && !charen && (((hiram || loram) && game) || (hiram && !exrom && !game)))
return PLABank.CharROM;
// io block, banked in at D000-DFFF
if ((charen && (hiram || loram)) || (exrom && !game))
{
if (addr < 0xD400)
return PLABank.Vic;
if (addr < 0xD800)
return PLABank.Sid;
if (addr < 0xDC00)
return PLABank.ColorRam;
if (addr < 0xDD00)
return PLABank.Cia1;
if (addr < 0xDE00)
return PLABank.Cia2;
if (addr < 0xDF00)
return PLABank.ExpansionLo;
return PLABank.ExpansionHi;
}
}
// cartridge high, banked either at A000-BFFF or E000-FFFF depending
exrom = InputExRom();
if (a13 && !game && ((hiram && !a14 && read && !exrom) || (a14 && exrom)))
return PLABank.CartridgeHi;
// cartridge low, banked at 8000-9FFF
if (!a14 && !a13 && ((loram && hiram && read && !exrom) || (exrom && !game)))
return PLABank.CartridgeLo;
// kernal rom, banked at E000-FFFF
if (hiram && a14 && a13 && read && (game || (!exrom && !game)))
return PLABank.KernalROM;
// basic rom, banked at A000-BFFF
if (loram && hiram && !a14 && a13 && read && game)
return PLABank.BasicROM;
}
// ultimax mode ram exclusion
if (exrom && !game)
{
p24 = !a15 && !a14 && a12;
p25 = !a15 && !a14 && a13;
p26 = !a15 && a14;
p27 = a15 && !a14 && a13;
p28 = a15 && a14 && !a13 && !a12;
if (!(p24 || p25 || p26 || p27 || p28))
return PLABank.RAM;
}
else
return PLABank.RAM;
return PLABank.None;
}
public int VicRead(int addr)
{
game = InputGame();
exrom = InputExRom();
a14 = (addr & 0x04000) == 0;
a13 = (addr & 0x02000) != 0;
a12 = (addr & 0x01000) != 0;
// read char rom at 1000-1FFF and 9000-9FFF
if (a14 && !a13 && a12 && (game || !exrom))
return ReadCharRom(addr);
// read cartridge rom in ultimax mode
if (a13 && a12 && exrom && !game)
return ReadCartridgeHi(addr);
return ReadMemory(addr);
}
public void Write(int addr, int val)
{
switch (Resolve(addr, false))
{
case PLABank.CartridgeHi:
WriteCartridgeHi(addr, val);
WriteMemory(addr, val);
break;
case PLABank.CartridgeLo:
WriteCartridgeLo(addr, val);
WriteMemory(addr, val);
break;
case PLABank.Cia1:
WriteCia1(addr, val);
break;
case PLABank.Cia2:
WriteCia2(addr, val);
break;
case PLABank.ColorRam:
WriteColorRam(addr, val);
break;
case PLABank.ExpansionLo:
WriteExpansionLo(addr, val);
return;
case PLABank.ExpansionHi:
WriteExpansionHi(addr, val);
return;
case PLABank.RAM:
WriteMemory(addr, val);
break;
case PLABank.Sid:
WriteSid(addr, val);
break;
case PLABank.Vic:
WriteVic(addr, val);
break;
}
}
}
}

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public abstract partial class Vic
public partial class Vic
{
public void Precache()
{

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public abstract partial class Vic
public partial class Vic
{
public Action ClockPhi0;
public Func<int, int> ReadColorRam;

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public abstract partial class Vic
public partial class Vic
{
bool cachedAEC;
bool cachedBA;

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public abstract partial class Vic
public partial class Vic
{
public void SyncState(Serializer ser)
{

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public abstract partial class Vic
public partial class Vic
{
protected struct CycleTiming
{

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
public abstract partial class Vic : IVideoProvider
public partial class Vic : IVideoProvider
{
protected int[] videoBuffer;

View File

@ -126,76 +126,143 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
a14 = (addr & 0x04000) != 0;
a13 = (addr & 0x02000) != 0;
a12 = (addr & 0x01000) != 0;
#region OLDPLA
//// io/character access
//if (a15 && a14 && !a13 && a12)
//{
// // character rom, banked in at D000-DFFF
// charen = ReadCharen();
// if (read && !charen)
// {
// p3 = hiram && game;
// p4 = loram && game;
// p5 = hiram && !exrom && !game;
// if (p3 || p4 || p5)
// return PLABank.CharROM;
// }
// io/character access
if (a15 && a14 && !a13 && a12)
{
// character rom, banked in at D000-DFFF
charen = ReadCharen();
if (read && !charen)
{
p3 = hiram && game;
p4 = loram && game;
p5 = hiram && !exrom && !game;
if (p3 || p4 || p5)
return PLABank.CharROM;
}
// // io block, banked in at D000-DFFF
// p9 = hiram && charen && game;
// p11 = loram && charen && game;
// p13 = hiram && charen && !exrom && !game;
// p15 = loram && charen && !exrom && !game;
// p17 = exrom && !game;
// if (p9 || p11 || p13 || p15 || p17)
// {
// if (addr < 0xD400)
// return PLABank.Vic;
// if (addr < 0xD800)
// return PLABank.Sid;
// if (addr < 0xDC00)
// return PLABank.ColorRam;
// if (addr < 0xDD00)
// return PLABank.Cia0;
// if (addr < 0xDE00)
// return PLABank.Cia1;
// if (addr < 0xDF00)
// return PLABank.Expansion0;
// return PLABank.Expansion1;
// }
//}
// io block, banked in at D000-DFFF
p9 = hiram && charen && game;
p11 = loram && charen && game;
p13 = hiram && charen && !exrom && !game;
p15 = loram && charen && !exrom && !game;
p17 = exrom && !game;
if (p9 || p11 || p13 || p15 || p17)
{
if (addr < 0xD400)
return PLABank.Vic;
if (addr < 0xD800)
return PLABank.Sid;
if (addr < 0xDC00)
return PLABank.ColorRam;
if (addr < 0xDD00)
return PLABank.Cia0;
if (addr < 0xDE00)
return PLABank.Cia1;
if (addr < 0xDF00)
return PLABank.Expansion0;
return PLABank.Expansion1;
}
}
//// basic rom, banked at A000-BFFF
//p0 = loram && hiram && a15 && !a14 && a13 && read && game;
//if (p0)
// return PLABank.BasicROM;
// basic rom, banked at A000-BFFF
p0 = loram && hiram && a15 && !a14 && a13 && read && game;
if (p0)
return PLABank.BasicROM;
//// kernal rom, banked at E000-FFFF
//exrom = ReadExRom();
//if (hiram && a15 && a14 && a13 && read)
//{
// p1 = game;
// p2 = !exrom && !game;
// if (p1 || p2)
// return PLABank.KernalROM;
//}
// kernal rom, banked at E000-FFFF
//// cartridge low, banked at 8000-9FFF
//if (a15 && !a14 && !a13)
//{
// p19 = loram && hiram && read && !exrom;
// p20 = exrom && !game;
// if (p19 || p20)
// return PLABank.CartridgeLo;
//}
//// cartridge high, banked either at A000-BFFF or E000-FFFF depending
//if (a15 && a13 && !game)
//{
// p21 = hiram && !a14 && read && !exrom;
// p22 = a14 && exrom;
// if (p21 || p22)
// return PLABank.CartridgeHi;
//}
//// ultimax mode ram exclusion
//if (exrom && !game)
//{
// p24 = !a15 && !a14 && a12;
// p25 = !a15 && !a14 && a13;
// p26 = !a15 && a14;
// p27 = a15 && !a14 && a13;
// p28 = a15 && a14 && !a13 && !a12;
// if (!(p24 || p25 || p26 || p27 || p28))
// return PLABank.RAM;
//}
//else
//{
// return PLABank.RAM;
//}
//return PLABank.None;
#endregion
// upper memory regions 8000-FFFF
exrom = ReadExRom();
if (hiram && a15 && a14 && a13 && read)
if (a15)
{
p1 = game;
p2 = !exrom && !game;
if (p1 || p2)
return PLABank.KernalROM;
}
// io/character access
if (a14 && !a13 && a12)
{
// character rom, banked in at D000-DFFF
charen = ReadCharen();
if (read && !charen && (((hiram || loram) && game) || (hiram && !exrom && !game)))
return PLABank.CharROM;
// cartridge low, banked at 8000-9FFF
if (a15 && !a14 && !a13)
{
p19 = loram && hiram && read && !exrom;
p20 = exrom && !game;
if (p19 || p20)
return PLABank.CartridgeLo;
}
// io block, banked in at D000-DFFF
if ((charen && (hiram || loram)) || (exrom && !game))
{
if (addr < 0xD400)
return PLABank.Vic;
if (addr < 0xD800)
return PLABank.Sid;
if (addr < 0xDC00)
return PLABank.ColorRam;
if (addr < 0xDD00)
return PLABank.Cia0;
if (addr < 0xDE00)
return PLABank.Cia1;
if (addr < 0xDF00)
return PLABank.Expansion0;
return PLABank.Expansion1;
}
}
// cartridge high, banked either at A000-BFFF or E000-FFFF depending
if (a15 && a13 && !game)
{
p21 = hiram && !a14 && read && !exrom;
p22 = a14 && exrom;
if (p21 || p22)
// cartridge high, banked either at A000-BFFF or E000-FFFF depending
if (a13 && !game && ((hiram && !a14 && read && !exrom) || (a14 && exrom)))
return PLABank.CartridgeHi;
// cartridge low, banked at 8000-9FFF
if (!a14 && !a13 && ((loram && hiram && read && !exrom) || (exrom && !game)))
return PLABank.CartridgeLo;
// kernal rom, banked at E000-FFFF
if (hiram && a14 && a13 && read && (game || (!exrom && !game)))
return PLABank.KernalROM;
// basic rom, banked at A000-BFFF
if (loram && hiram && !a14 && a13 && read && game)
return PLABank.BasicROM;
}
// ultimax mode ram exclusion
@ -210,9 +277,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
return PLABank.RAM;
}
else
{
return PLABank.RAM;
}
return PLABank.None;
}