commodore64: implement motherboard configuration, add sprite-sprite and sprite-data collision interrupts to VIC

This commit is contained in:
saxxonpike 2012-12-05 21:07:51 +00:00
parent fc484df925
commit c64951fce8
22 changed files with 1373 additions and 1273 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.Motherboard.cs" />
<Compile Include="Computers\Commodore64\Cartridges\Mapper0000.cs" /> <Compile Include="Computers\Commodore64\Cartridges\Mapper0000.cs" />
<Compile Include="Computers\Commodore64\C64.Input.cs" /> <Compile Include="Computers\Commodore64\C64.Input.cs" />
<Compile Include="Computers\Commodore64\Cartridges\Mapper0005.cs" /> <Compile Include="Computers\Commodore64\Cartridges\Mapper0005.cs" />
@ -94,10 +95,10 @@
<Compile Include="Computers\Commodore64\Memory.cs" /> <Compile Include="Computers\Commodore64\Memory.cs" />
<Compile Include="Computers\Commodore64\Cartridges\Cartridge.cs" /> <Compile Include="Computers\Commodore64\Cartridges\Cartridge.cs" />
<Compile Include="Computers\Commodore64\MOS\CartridgePort.cs" /> <Compile Include="Computers\Commodore64\MOS\CartridgePort.cs" />
<Compile Include="Computers\Commodore64\MOS\CassettePort.cs" />
<Compile Include="Computers\Commodore64\MOS\Chip2114.cs" /> <Compile Include="Computers\Commodore64\MOS\Chip2114.cs" />
<Compile Include="Computers\Commodore64\MOS\Chip23XX.cs" /> <Compile Include="Computers\Commodore64\MOS\Chip23XX.cs" />
<Compile Include="Computers\Commodore64\MOS\Chip4864.cs" /> <Compile Include="Computers\Commodore64\MOS\Chip4864.cs" />
<Compile Include="Computers\Commodore64\MOS\IStandardIO.cs" />
<Compile Include="Computers\Commodore64\MOS\MOS6510.cs" /> <Compile Include="Computers\Commodore64\MOS\MOS6510.cs" />
<Compile Include="Computers\Commodore64\MOS\MOS6522.cs" /> <Compile Include="Computers\Commodore64\MOS\MOS6522.cs" />
<Compile Include="Computers\Commodore64\Media\D64.cs" /> <Compile Include="Computers\Commodore64\Media\D64.cs" />
@ -110,6 +111,7 @@
<Compile Include="Computers\Commodore64\C64.Savestate.cs" /> <Compile Include="Computers\Commodore64\C64.Savestate.cs" />
<Compile Include="Computers\Commodore64\MOS\MOSPLA.cs" /> <Compile Include="Computers\Commodore64\MOS\MOSPLA.cs" />
<Compile Include="Computers\Commodore64\MOS\Port.cs" /> <Compile Include="Computers\Commodore64\MOS\Port.cs" />
<Compile Include="Computers\Commodore64\MOS\SerialPort.cs" />
<Compile Include="Computers\Commodore64\MOS\Sid.cs" /> <Compile Include="Computers\Commodore64\MOS\Sid.cs" />
<Compile Include="Computers\Commodore64\MOS\Sid.SoundProvider.cs" /> <Compile Include="Computers\Commodore64\MOS\Sid.SoundProvider.cs" />
<Compile Include="Computers\Commodore64\MOS\Sid.SyncSoundProvider.cs" /> <Compile Include="Computers\Commodore64\MOS\Sid.SyncSoundProvider.cs" />

View File

@ -31,7 +31,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
// ------------------------------------ // ------------------------------------
private C64Chips chips; private Motherboard board;
// ------------------------------------ // ------------------------------------
@ -41,16 +41,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
private void Init(Region initRegion) private void Init(Region initRegion)
{ {
chips = new C64Chips(initRegion); board = new Motherboard(initRegion);
InitRoms(); InitRoms();
board.Init();
InitMedia(); InitMedia();
// configure video // configure video
CoreOutputComm.VsyncDen = chips.vic.CyclesPerFrame; CoreOutputComm.VsyncDen = board.vic.CyclesPerFrame;
CoreOutputComm.VsyncNum = chips.vic.CyclesPerSecond; CoreOutputComm.VsyncNum = board.vic.CyclesPerSecond;
// configure input
InitInput();
} }
private void InitMedia() private void InitMedia()
@ -61,7 +59,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
Cartridges.Cartridge cart = Cartridges.Cartridge.Load(inputFile); Cartridges.Cartridge cart = Cartridges.Cartridge.Load(inputFile);
if (cart != null) if (cart != null)
{ {
chips.cartPort.Connect(cart); board.cartPort.Connect(cart);
} }
break; break;
case @".PRG": case @".PRG":
@ -93,9 +91,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
byte[] charRom = File.ReadAllBytes(charPath); byte[] charRom = File.ReadAllBytes(charPath);
byte[] kernalRom = File.ReadAllBytes(kernalPath); byte[] kernalRom = File.ReadAllBytes(kernalPath);
chips.basicRom = new Chip23XX(Chip23XXmodel.Chip2364, basicRom); board.basicRom = new Chip23XX(Chip23XXmodel.Chip2364, basicRom);
chips.kernalRom = new Chip23XX(Chip23XXmodel.Chip2364, kernalRom); board.kernalRom = new Chip23XX(Chip23XXmodel.Chip2364, kernalRom);
chips.charRom = new Chip23XX(Chip23XXmodel.Chip2332, charRom); board.charRom = new Chip23XX(Chip23XXmodel.Chip2332, charRom);
} }
// ------------------------------------ // ------------------------------------
@ -108,137 +106,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
} }
public void Execute(uint count)
{
for (; count > 0; count--)
{
WriteInputPort();
chips.ExecutePhase1();
chips.ExecutePhase2();
}
}
public void HardReset() public void HardReset()
{ {
chips.HardReset(); board.HardReset();
} }
// ------------------------------------ // ------------------------------------
} }
public class C64Chips
{
public Chip23XX basicRom; //u4
public CartridgePort cartPort; //cn6
public Chip23XX charRom; //u5
public MOS6526 cia0; //u1
public MOS6526 cia1; //u2
public Chip2114 colorRam; //u19
public MOS6510 cpu; //u6
public Chip23XX kernalRom; //u4
public MOSPLA pla;
public Chip4864 ram; //u10+11
public Sid sid; //u9
public UserPort userPort; //cn2 (probably won't be needed for games)
public Vic vic; //u7
public C64Chips(Region initRegion)
{
cartPort = new CartridgePort();
cia0 = new MOS6526(initRegion);
cia1 = new MOS6526(initRegion);
pla = new MOSPLA(this);
switch (initRegion)
{
case Region.NTSC:
vic = new MOS6567(this);
break;
case Region.PAL:
vic = new MOS6569(this);
break;
}
colorRam = new Chip2114();
cpu = new MOS6510(this);
ram = new Chip4864();
sid = new MOS6581(44100, initRegion);
pla.UpdatePins();
}
public void ExecutePhase1()
{
pla.ExecutePhase1();
cia0.ExecutePhase1();
cia1.ExecutePhase1();
sid.ExecutePhase1();
vic.ExecutePhase1();
cpu.ExecutePhase1();
}
public void ExecutePhase2()
{
pla.ExecutePhase2();
cia0.ExecutePhase2();
cia1.ExecutePhase2();
sid.ExecutePhase2();
vic.ExecutePhase2();
cpu.ExecutePhase2();
}
public void HardReset()
{
// note about hard reset: NOT identical to cold start
// reset all chips
cia0.HardReset();
cia1.HardReset();
colorRam.HardReset();
pla.HardReset();
cpu.HardReset();
ram.HardReset();
sid.HardReset();
vic.HardReset();
}
public void SyncState(Serializer ser)
{
ser.BeginSection("cia0");
cia0.SyncState(ser);
ser.EndSection();
ser.BeginSection("cia1");
cia1.SyncState(ser);
ser.EndSection();
ser.BeginSection("colorram");
colorRam.SyncState(ser);
ser.EndSection();
ser.BeginSection("pla");
pla.SyncState(ser);
ser.EndSection();
ser.BeginSection("cpu");
cpu.SyncState(ser);
ser.EndSection();
ser.BeginSection("ram");
ram.SyncState(ser);
ser.EndSection();
ser.BeginSection("sid");
sid.SyncState(ser);
ser.EndSection();
ser.BeginSection("vic");
vic.SyncState(ser);
ser.EndSection();
ser.BeginSection("cart");
cartPort.SyncState(ser);
ser.EndSection();
}
}
static public class C64Util static public class C64Util
{ {
static public string ToBinary(uint n, uint charsmin) static public string ToBinary(uint n, uint charsmin)

View File

@ -6,10 +6,8 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64 namespace BizHawk.Emulation.Computers.Commodore64
{ {
public partial class C64 : IEmulator public partial class Motherboard
{ {
private PortAdapter inputAdapter0;
private PortAdapter inputAdapter1;
private bool[,] joystickPressed = new bool[2, 5]; private bool[,] joystickPressed = new bool[2, 5];
private bool[,] keyboardPressed = new bool[8, 8]; private bool[,] keyboardPressed = new bool[8, 8];
@ -34,13 +32,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
static private byte[] inputBitMask = new byte[] { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }; static private byte[] inputBitMask = new byte[] { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
static private byte[] inputBitSelect = new byte[] { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; static private byte[] inputBitSelect = new byte[] { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
private void InitInput() public void PollInput()
{
inputAdapter0 = chips.cia0.Adapter0;
inputAdapter1 = chips.cia0.Adapter1;
}
private void PollInput()
{ {
// scan joysticks // scan joysticks
for (uint i = 0; i < 2; i++) for (uint i = 0; i < 2; i++)
@ -63,11 +55,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
private void WriteInputPort() private void WriteInputPort()
{ {
inputAdapter0.Data = 0xFF; byte portA = Port.ExternalWrite(cia0DataA, 0xFF, cia0DirA);
inputAdapter1.Data = 0xFF; byte portB = Port.ExternalWrite(cia0DataB, 0xFF, cia0DirB);
byte portA = inputAdapter0.Data;
byte portB = inputAdapter1.Data;
byte resultA = 0xFF; byte resultA = 0xFF;
byte resultB = 0xFF; byte resultB = 0xFF;
byte joyA = 0xFF; byte joyA = 0xFF;
@ -96,9 +85,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
joyB &= inputBitMask[i]; joyB &= inputBitMask[i];
} }
inputAdapter0.Data = resultA; resultA &= joyA;
inputAdapter1.Data = (byte)(joyB & resultB); resultB &= joyB;
inputAdapter0.MaskWrite(joyB);
cia0DataA = Port.ExternalWrite(cia0DataA, resultA, cia0DirA);
cia0DataB = Port.ExternalWrite(cia0DataB, resultB, cia0DirB);
} }
} }
} }

View File

@ -0,0 +1,255 @@
using BizHawk.Emulation.Computers.Commodore64.MOS;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class Motherboard
{
// chips
public Chip23XX basicRom;
public Chip23XX charRom;
public MOS6526 cia0;
public MOS6526 cia1;
public Chip2114 colorRam;
public MOS6510 cpu;
public Chip23XX kernalRom;
public MOSPLA pla;
public Chip4864 ram;
public Sid sid;
public Vic vic;
// ports
public CartridgePort cartPort;
public CassettePort cassPort;
public IController controller;
public SerialPort serPort;
public UserPort userPort;
// state
public ushort address;
public byte bus;
public byte cia0DataA;
public byte cia0DataB;
public byte cia0DirA;
public byte cia0DirB;
public byte cia1DataA;
public byte cia1DataB;
public byte cia1DirA;
public byte cia1DirB;
public bool inputRead;
// cache
private ushort vicBank;
public Motherboard(Region initRegion)
{
// note: roms need to be added on their own externally
cartPort = new CartridgePort();
cassPort = new CassettePort();
cia0 = new MOS6526(initRegion);
cia1 = new MOS6526(initRegion);
colorRam = new Chip2114();
cpu = new MOS6510();
pla = new MOSPLA();
ram = new Chip4864();
serPort = new SerialPort();
sid = new MOS6581(44100, initRegion);
switch (initRegion)
{
case Region.NTSC: vic = new MOS6567(); break;
case Region.PAL: vic = new MOS6569(); break;
}
userPort = new UserPort();
}
// -----------------------------------------
public void Execute(uint count)
{
while (count > 0)
{
WriteInputPort();
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--;
}
}
// -----------------------------------------
public void HardReset()
{
address = 0xFFFF;
bus = 0xFF;
cia0DataA = 0xFF;
cia0DataB = 0xFF;
cia0DirA = 0xFF;
cia0DirB = 0xFF;
cia1DataA = 0xFF;
cia1DataB = 0xFF;
cia1DirA = 0xFF;
cia1DirB = 0xFF;
inputRead = false;
cpu.HardReset();
cia0.HardReset();
cia1.HardReset();
colorRam.HardReset();
pla.HardReset();
ram.HardReset();
serPort.HardReset();
sid.HardReset();
vic.HardReset();
userPort.HardReset();
// because of how mapping works, the cpu needs to be hard reset twice
cpu.HardReset();
// now reset the cache
UpdateVicBank();
}
public void Init()
{
cia0.ReadDirA = (() => { return cia0DirA; });
cia0.ReadDirB = (() => { return cia0DirB; });
cia0.ReadPortA = (() => { return cia0DataA; });
cia0.ReadPortB = (() => { return cia0DataB; });
cia0.WriteDirA = ((byte val) => { cia0DirA = val; });
cia0.WriteDirB = ((byte val) => { cia0DirB = val; });
cia0.WritePortA = ((byte val) => { cia0DataA = Port.CPUWrite(cia0DataA, val, cia0DirA); });
cia0.WritePortB = ((byte val) => { cia0DataB = Port.CPUWrite(cia0DataB, val, cia0DirB); });
cia1.ReadDirA = (() => { return cia1DirA; });
cia1.ReadDirB = (() => { return cia1DirB; });
cia1.ReadPortA = (() => { return cia1DataA; });
cia1.ReadPortB = (() => { return cia1DataB; });
cia1.WriteDirA = ((byte val) => { cia1DirA = val; });
cia1.WriteDirB = ((byte val) => { cia1DirB = val; });
cia1.WritePortA = ((byte val) => { cia1DataA = Port.CPUWrite(cia1DataA, val, cia1DirA); UpdateVicBank(); });
cia1.WritePortB = ((byte val) => { cia1DataB = Port.CPUWrite(cia1DataB, val, cia1DirB); });
cpu.PeekMemory = pla.Peek;
cpu.PokeMemory = pla.Poke;
cpu.ReadAEC = (() => { return vic.AEC; });
cpu.ReadIRQ = (() => { return cia0.IRQ & vic.IRQ & cartPort.IRQ; });
cpu.ReadNMI = (() => { return cia1.IRQ; });
cpu.ReadRDY = (() => { return vic.BA; });
cpu.ReadMemory = pla.Read;
cpu.WriteMemory = pla.Write;
pla.PeekBasicRom = basicRom.Peek;
pla.PeekCartridgeHi = cartPort.PeekHiRom;
pla.PeekCartridgeLo = cartPort.PeekLoRom;
pla.PeekCharRom = charRom.Peek;
pla.PeekCia0 = cia0.Peek;
pla.PeekCia1 = cia1.Peek;
pla.PeekColorRam = colorRam.Peek;
pla.PeekExpansionHi = cartPort.PeekHiExp;
pla.PeekExpansionLo = cartPort.PeekLoExp;
pla.PeekKernalRom = kernalRom.Peek;
pla.PeekMemory = ram.Peek;
pla.PeekSid = sid.Peek;
pla.PeekVic = vic.Peek;
pla.PokeCartridgeHi = cartPort.PokeHiRom;
pla.PokeCartridgeLo = cartPort.PokeLoRom;
pla.PokeCia0 = cia0.Poke;
pla.PokeCia1 = cia1.Poke;
pla.PokeColorRam = colorRam.Poke;
pla.PokeExpansionHi = cartPort.PokeHiExp;
pla.PokeExpansionLo = cartPort.PokeLoExp;
pla.PokeMemory = ram.Poke;
pla.PokeSid = sid.Poke;
pla.PokeVic = vic.Poke;
pla.ReadBasicRom = ((ushort addr) => { address = addr; bus = basicRom.Read(addr); return bus; });
pla.ReadCartridgeHi = ((ushort addr) => { address = addr; bus = cartPort.ReadHiRom(addr); return bus; });
pla.ReadCartridgeLo = ((ushort addr) => { address = addr; bus = cartPort.ReadLoRom(addr); return bus; });
pla.ReadCharen = (() => { return cpu.Charen; });
pla.ReadCharRom = ((ushort addr) => { address = addr; bus = charRom.Read(addr); return bus; });
pla.ReadCia0 = ((ushort addr) =>
{
address = addr;
bus = cia0.Read(addr);
if (!inputRead && (addr == 0xDC00 || addr == 0xDC01))
inputRead = true;
return bus;
});
pla.ReadCia1 = ((ushort addr) => { address = addr; bus = cia1.Read(addr); return bus; });
pla.ReadColorRam = ((ushort addr) => { address = addr; bus &= 0xF0; bus |= colorRam.Read(addr); return bus; });
pla.ReadExpansionHi = ((ushort addr) => { address = addr; bus = cartPort.ReadHiExp(addr); return bus; });
pla.ReadExpansionLo = ((ushort addr) => { address = addr; bus = cartPort.ReadLoExp(addr); return bus; });
pla.ReadExRom = (() => { return cartPort.ExRom; });
pla.ReadGame = (() => { return cartPort.Game; });
pla.ReadHiRam = (() => { return cpu.HiRam; });
pla.ReadKernalRom = ((ushort addr) => { address = addr; bus = kernalRom.Read(addr); return bus; });
pla.ReadLoRam = (() => { return cpu.LoRam; });
pla.ReadMemory = ((ushort addr) => { address = addr; bus = ram.Read(addr); return bus; });
pla.ReadSid = ((ushort addr) => { address = addr; bus = sid.Read(addr); return bus; });
pla.ReadVic = ((ushort addr) => { address = addr; bus = vic.Read(addr); return bus; });
pla.WriteCartridgeHi = ((ushort addr, byte val) => { address = addr; bus = val; cartPort.WriteHiRom(addr, val); });
pla.WriteCartridgeLo = ((ushort addr, byte val) => { address = addr; bus = val; cartPort.WriteLoRom(addr, val); });
pla.WriteCia0 = ((ushort addr, byte val) => { address = addr; bus = val; cia0.Write(addr, val); });
pla.WriteCia1 = ((ushort addr, byte val) => { address = addr; bus = val; cia1.Write(addr, val); });
pla.WriteColorRam = ((ushort addr, byte val) => { address = addr; bus = val; colorRam.Write(addr, val); });
pla.WriteExpansionHi = ((ushort addr, byte val) => { address = addr; bus = val; cartPort.WriteHiExp(addr, val); });
pla.WriteExpansionLo = ((ushort addr, byte val) => { address = addr; bus = val; cartPort.WriteLoExp(addr, val); });
pla.WriteMemory = ((ushort addr, byte val) => { address = addr; bus = val; ram.Write(addr, val); });
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); });
sid.ReadPotX = (() => { return 0; });
sid.ReadPotY = (() => { return 0; });
vic.ReadMemory = ((ushort addr) =>
{
addr |= vicBank;
address = addr;
if ((addr & 0x7000) == 0x1000)
bus = charRom.Read(addr);
else
bus = ram.Read(addr);
return bus;
});
vic.ReadColorRam = ((ushort addr) =>
{
address = addr;
bus &= 0xF0;
bus |= colorRam.Read(addr);
return bus;
});
}
public void SyncState(Serializer ser)
{
}
private void UpdateVicBank()
{
switch (cia1DataA & 0x3)
{
case 0: vicBank = 0xC000; break;
case 1: vicBank = 0x8000; break;
case 2: vicBank = 0x4000; break;
default: vicBank = 0x0000; break;
}
}
}
}

View File

@ -55,16 +55,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
void SyncState(Serializer ser) void SyncState(Serializer ser)
{ {
chips.SyncState(ser); board.SyncState(ser);
ser.BeginSection("core"); ser.BeginSection("core");
ser.Sync("cyclesPerFrame", ref cyclesPerFrame); ser.Sync("cyclesPerFrame", ref cyclesPerFrame);
ser.Sync("loadPrg", ref loadPrg); ser.Sync("loadPrg", ref loadPrg);
for (uint i = 0; i < 2; i++)
for (uint j = 0; j < 5; j++)
ser.Sync("joystickPressed" + i.ToString() + j.ToString(), ref joystickPressed[i, j]);
for (uint i = 0; i < 8; i++)
for (uint j = 0; j < 8; j++)
ser.Sync("keyboardPressed" + i.ToString() + j.ToString(), ref keyboardPressed[i, j]);
ser.EndSection(); ser.EndSection();
} }
} }

View File

@ -9,7 +9,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
public partial class C64 : IEmulator public partial class C64 : IEmulator
{ {
private IController controller;
private uint cyclesPerFrame; private uint cyclesPerFrame;
private string extension; private string extension;
private byte[] inputFile; private byte[] inputFile;
@ -21,7 +20,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
CoreOutputComm = new CoreOutputComm(); CoreOutputComm = new CoreOutputComm();
CoreInputComm = new CoreInputComm(); CoreInputComm = new CoreInputComm();
Init(Region.PAL); Init(Region.PAL);
cyclesPerFrame = (uint)chips.vic.CyclesPerFrame; cyclesPerFrame = (uint)board.vic.CyclesPerFrame;
CoreOutputComm.UsesDriveLed = true; CoreOutputComm.UsesDriveLed = true;
SetupMemoryDomains(); SetupMemoryDomains();
} }
@ -58,14 +57,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
// audio/video // audio/video
public void EndAsyncSound() { } //TODO public void EndAsyncSound() { } //TODO
public ISoundProvider SoundProvider { get { return chips.sid; } } public ISoundProvider SoundProvider { get { return board.sid; } }
public bool StartAsyncSound() { return true; } //TODO public bool StartAsyncSound() { return true; } //TODO
public ISyncSoundProvider SyncSoundProvider { get { return chips.sid; } } public ISyncSoundProvider SyncSoundProvider { get { return board.sid; } }
public IVideoProvider VideoProvider { get { return chips.vic; } } public IVideoProvider VideoProvider { get { return board.vic; } }
// controller // controller
public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } } public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } }
public IController Controller { get { return controller; } set { controller = value; } } public IController Controller { get { return board.controller; } set { board.controller = value; } }
public static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition public static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition
{ {
Name = "Commodore 64 Controller", //TODO Name = "Commodore 64 Controller", //TODO
@ -93,22 +92,21 @@ namespace BizHawk.Emulation.Computers.Commodore64
// load PRG file if needed // load PRG file if needed
if (loadPrg) if (loadPrg)
{ {
if (chips.pla.Peek(0x04C8) == 0x12 && if (board.pla.Peek(0x04C8) == 0x12 &&
chips.pla.Peek(0x04C9) == 0x05 && board.pla.Peek(0x04C9) == 0x05 &&
chips.pla.Peek(0x04CA) == 0x01 && board.pla.Peek(0x04CA) == 0x01 &&
chips.pla.Peek(0x04CB) == 0x04 && board.pla.Peek(0x04CB) == 0x04 &&
chips.pla.Peek(0x04CC) == 0x19 && board.pla.Peek(0x04CC) == 0x19 &&
chips.pla.Peek(0x04CD) == 0x2E) board.pla.Peek(0x04CD) == 0x2E)
{ {
Media.PRG.Load(chips.pla, inputFile); Media.PRG.Load(board.pla, inputFile);
loadPrg = false; loadPrg = false;
} }
} }
PollInput(); board.PollInput();
chips.pla.InputWasRead = false; board.Execute(cyclesPerFrame);
Execute(cyclesPerFrame); _islag = !board.inputRead;
_islag = !chips.pla.InputWasRead;
if (_islag) if (_islag)
LagCount++; LagCount++;
@ -136,12 +134,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
// chips must be initialized before this code runs! // chips must be initialized before this code runs!
var domains = new List<MemoryDomain>(1); var domains = new List<MemoryDomain>(1);
domains.Add(new MemoryDomain("System Bus", 0x10000, Endian.Little, new Func<int, byte>(chips.cpu.Peek), new Action<int, byte>(chips.cpu.Poke))); domains.Add(new MemoryDomain("System Bus", 0x10000, Endian.Little, new Func<int, byte>(board.cpu.Peek), new Action<int, byte>(board.cpu.Poke)));
domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func<int, byte>(chips.ram.Peek), new Action<int, byte>(chips.ram.Poke))); domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func<int, byte>(board.ram.Peek), new Action<int, byte>(board.ram.Poke)));
domains.Add(new MemoryDomain("CIA0", 0x10, Endian.Little, new Func<int, byte>(chips.cia0.Peek), new Action<int, byte>(chips.cia0.Poke))); domains.Add(new MemoryDomain("CIA0", 0x10, Endian.Little, new Func<int, byte>(board.cia0.Peek), new Action<int, byte>(board.cia0.Poke)));
domains.Add(new MemoryDomain("CIA1", 0x10, Endian.Little, new Func<int, byte>(chips.cia1.Peek), new Action<int, byte>(chips.cia1.Poke))); 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>(chips.vic.Peek), new Action<int, byte>(chips.vic.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>(chips.sid.Peek), new Action<int, byte>(chips.sid.Poke))); domains.Add(new MemoryDomain("SID", 0x20, Endian.Little, new Func<int, byte>(board.sid.Peek), new Action<int, byte>(board.sid.Poke)));
memoryDomains = domains.AsReadOnly(); memoryDomains = domains.AsReadOnly();
} }
} }

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public class CassettePort
{
public void HardReset()
{
}
}
}

View File

@ -7,7 +7,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
// used as Color RAM in C64 // used as Color RAM in C64
public class Chip2114 : IStandardIO public class Chip2114
{ {
private byte[] ram; private byte[] ram;

View File

@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
Chip23128 Chip23128
} }
public class Chip23XX : IStandardIO public class Chip23XX
{ {
private uint addrMask; private uint addrMask;
private byte[] rom; private byte[] rom;

View File

@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// memory is striped 00/FF at intervals of 0x40 // memory is striped 00/FF at intervals of 0x40
public class Chip4864 : IStandardIO public class Chip4864
{ {
private byte[] ram; private byte[] ram;

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public interface IStandardIO
{
byte Peek(int addr);
void Poke(int addr, byte val);
byte Read(ushort addr);
void Write(ushort addr, byte val);
}
}

View File

@ -8,11 +8,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
// an extension of the 6502 processor // an extension of the 6502 processor
public class MOS6510 : IStandardIO public class MOS6510
{ {
// ------------------------------------ // ------------------------------------
private C64Chips chips;
private MOS6502X cpu; private MOS6502X cpu;
private bool freezeCpu; private bool freezeCpu;
private bool pinCassetteButton; private bool pinCassetteButton;
@ -29,11 +28,19 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private uint unusedPinTTL1; private uint unusedPinTTL1;
private uint unusedPinTTLCycles; private uint unusedPinTTLCycles;
public Func<int, byte> PeekMemory;
public Action<int, byte> PokeMemory;
public Func<bool> ReadAEC;
public Func<bool> ReadIRQ;
public Func<bool> ReadNMI;
public Func<bool> ReadRDY;
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
// ------------------------------------ // ------------------------------------
public MOS6510(C64Chips newChips) public MOS6510()
{ {
chips = newChips;
cpu = new MOS6502X(); cpu = new MOS6502X();
// configure cpu r/w // configure cpu r/w
@ -59,7 +66,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
cpu.Reset(); cpu.Reset();
cpu.FlagI = true; cpu.FlagI = true;
cpu.BCD_Enabled = true; cpu.BCD_Enabled = true;
cpu.PC = (ushort)(chips.pla.Read(0xFFFC) | (chips.pla.Read(0xFFFD) << 8)); cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8));
} }
// ------------------------------------ // ------------------------------------
@ -70,23 +77,23 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public void ExecutePhase2() public void ExecutePhase2()
{ {
if (chips.vic.AEC && !freezeCpu) if (ReadAEC() && !freezeCpu)
{ {
// the 6502 core expects active high // the 6502 core expects active high
// so we reverse the polarity here // so we reverse the polarity here
bool thisNMI = (chips.cia1.IRQ & chips.cartPort.NMI); bool thisNMI = ReadNMI();
if (!thisNMI && pinNMILast) if (!thisNMI && pinNMILast)
cpu.NMI = true; cpu.NMI = true;
else else
cpu.NMI = false; cpu.NMI = false;
pinNMILast = thisNMI; pinNMILast = thisNMI;
cpu.IRQ = !(chips.vic.IRQ && chips.cia0.IRQ && chips.cartPort.IRQ); cpu.IRQ = !ReadIRQ();
cpu.ExecuteOne(); cpu.ExecuteOne();
} }
// unfreeze cpu if BA is high // unfreeze cpu if BA is high
if (chips.vic.BA) freezeCpu = false; if (ReadRDY()) freezeCpu = false;
// process unused pin TTL // process unused pin TTL
if (unusedPinTTL0 == 0) if (unusedPinTTL0 == 0)
@ -109,7 +116,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
else if (addr == 0x0001) else if (addr == 0x0001)
return PortData; return PortData;
else else
return chips.pla.Peek(addr); return PeekMemory(addr);
} }
public void Poke(int addr, byte val) public void Poke(int addr, byte val)
@ -119,13 +126,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
else if (addr == 0x0001) else if (addr == 0x0001)
SetPortData(val); SetPortData(val);
else else
chips.pla.Poke(addr, val); PokeMemory(addr, val);
} }
public byte Read(ushort addr) public byte Read(ushort addr)
{ {
// cpu freezes after first read when RDY is low // cpu freezes after first read when RDY is low
if (!chips.vic.BA) if (!ReadRDY())
freezeCpu = true; freezeCpu = true;
if (addr == 0x0000) if (addr == 0x0000)
@ -133,7 +140,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
else if (addr == 0x0001) else if (addr == 0x0001)
return PortData; return PortData;
else else
return chips.pla.Read(addr); return ReadMemory(addr);
} }
public void Write(ushort addr, byte val) public void Write(ushort addr, byte val)
@ -142,7 +149,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
PortDirection = val; PortDirection = val;
else if (addr == 0x0001) else if (addr == 0x0001)
PortData = val; PortData = val;
chips.pla.Write(addr, val); WriteMemory(addr, val);
} }
// ------------------------------------ // ------------------------------------
@ -194,6 +201,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
} }
public byte ReadPortData()
{
return PortData;
}
private void SetPortData(byte val) private void SetPortData(byte val)
{ {
pinCassetteOutput = ((val & 0x08) != 0); pinCassetteOutput = ((val & 0x08) != 0);
@ -235,6 +247,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
ser.Sync("unusedPinTTLCycles", ref unusedPinTTLCycles); ser.Sync("unusedPinTTLCycles", ref unusedPinTTLCycles);
} }
public void WritePortData(byte data)
{
PortData = data;
}
// ------------------------------------ // ------------------------------------
} }
} }

View File

@ -6,7 +6,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
// via // via
public class MOS6522 : Timer, IStandardIO public class MOS6522 : Timer
{ {
// ------------------------------------ // ------------------------------------

View File

@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// * CS, R/W and RS# pins are not emulated. (not needed) // * CS, R/W and RS# pins are not emulated. (not needed)
// * A low RES pin is emulated via HardReset(). // * A low RES pin is emulated via HardReset().
public class MOS6526 : Timer, IStandardIO public class MOS6526 : Timer
{ {
// ------------------------------------ // ------------------------------------
@ -104,14 +104,20 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
public void ExecutePhase2() public void ExecutePhase2()
{
{ {
pinPC = true; pinPC = true;
TODRun(); TODRun();
if (timerPulse[0]) if (timerPulse[0])
portData[0] &= PBOnMask[0]; {
WritePortA((byte)(ReadPortA() & PBOnMask[0]));
}
if (timerPulse[1]) if (timerPulse[1])
portData[1] &= PBOnMask[0]; {
WritePortB((byte)(ReadPortA() & PBOnMask[1]));
}
if (timerDelay[0] == 0) if (timerDelay[0] == 0)
TimerRun(0); TimerRun(0);
@ -142,6 +148,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
(intFlag && enableIntFlag) (intFlag && enableIntFlag)
); );
} }
}
public void HardReset() public void HardReset()
{ {
@ -209,6 +216,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// ------------------------------------ // ------------------------------------
private byte BCDAdd(byte i, byte j, out bool overflow) private byte BCDAdd(byte i, byte j, out bool overflow)
{
{ {
uint lo; uint lo;
uint hi; uint hi;
@ -229,15 +238,18 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
result = (hi & 0x70) + (lo & 0x0F); result = (hi & 0x70) + (lo & 0x0F);
return (byte)(result & 0xFF); return (byte)(result & 0xFF);
} }
}
private void TimerRun(uint index) private void TimerRun(uint index)
{
{ {
if (timerOn[index]) if (timerOn[index])
{ {
uint t = timer[index]; uint t = timer[index];
bool u = false; bool u = false;
unchecked
{ {
switch (timerInMode[index]) switch (timerInMode[index])
{ {
@ -286,15 +298,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if (timerPortEnable[index]) if (timerPortEnable[index])
{ {
// force port B bit to output // force port B bit to output
portDir[index] |= PBOnBit[index]; WriteDirB((byte)(ReadDirB() | PBOnBit[index]));
switch (timerOutMode[index]) switch (timerOutMode[index])
{ {
case OutMode.Pulse: case OutMode.Pulse:
timerPulse[index] = true; timerPulse[index] = true;
portData[index] |= PBOnBit[index]; WritePortB((byte)(ReadPortB() | PBOnBit[index]));
break; break;
case OutMode.Toggle: case OutMode.Toggle:
portData[index] ^= PBOnBit[index]; WritePortB((byte)(ReadPortB() ^ PBOnBit[index]));
break; break;
} }
} }
@ -305,8 +317,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
} }
} }
}
private void TODRun() private void TODRun()
{
{ {
bool todV; bool todV;
@ -340,6 +355,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
todCounter--; todCounter--;
} }
}
// ------------------------------------ // ------------------------------------
@ -417,16 +433,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
switch (addr) switch (addr)
{ {
case 0x0: case 0x0:
val = (byte)(portData[0] & portMask[0]); val = ReadPortA();
break; break;
case 0x1: case 0x1:
val = (byte)(portData[1] & portMask[1]); val = ReadPortB();
break; break;
case 0x2: case 0x2:
val = portDir[0]; val = ReadDirA();
break; break;
case 0x3: case 0x3:
val = portDir[1]; val = ReadDirB();
break; break;
case 0x4: case 0x4:
timerVal = ReadTimerValue(0); timerVal = ReadTimerValue(0);
@ -604,11 +620,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
switch (addr) switch (addr)
{ {
case 0x0:
WritePort0(val);
break;
case 0x1: case 0x1:
WritePort1(val); WriteRegister(addr, val);
pinPC = false; pinPC = false;
break; break;
case 0x5: case 0x5:
@ -644,16 +657,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
switch (addr) switch (addr)
{ {
case 0x0: case 0x0:
portData[0] = val; WritePortA(val);
break; break;
case 0x1: case 0x1:
portData[1] = val; WritePortB(val);
break; break;
case 0x2: case 0x2:
portDir[0] = val; WriteDirA(val);
break; break;
case 0x3: case 0x3:
portDir[1] = val; WriteDirB(val);
break; break;
case 0x4: case 0x4:
timerLatch[0] &= 0xFF00; timerLatch[0] &= 0xFF00;

View File

@ -6,12 +6,12 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
// vic ntsc // vic ntsc
public class MOS6567 : Vic, IStandardIO public class MOS6567 : Vic
{ {
static uint[][] pipeline = new uint[5][]; static uint[][] pipeline = new uint[5][];
public MOS6567(C64Chips newChips) public MOS6567()
: base(newChips, 65, 263, pipeline, 14318181 / 14) : base(65, 263, pipeline, 14318181 / 14)
{ {
} }
} }

View File

@ -6,7 +6,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
// vic pal // vic pal
public class MOS6569 : Vic, IStandardIO public class MOS6569 : Vic
{ {
static uint[][] pipeline = new uint[][] static uint[][] pipeline = new uint[][]
{ {
@ -324,8 +324,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
}; };
public MOS6569(C64Chips newChips) public MOS6569()
: base(newChips, 63, 312, pipeline, 17734472 / 18) : base(63, 312, pipeline, 17734472 / 18)
{ {
} }
} }

View File

@ -6,7 +6,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
// sid // sid
public class MOS6581 : Sid, IStandardIO, ISoundProvider, ISyncSoundProvider public class MOS6581 : Sid, ISoundProvider, ISyncSoundProvider
{ {
static uint[][] waveTable = new uint[][] static uint[][] waveTable = new uint[][]
{ {

View File

@ -8,10 +8,64 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// emulates the PLA // emulates the PLA
// which handles all bank switching // which handles all bank switching
public class MOSPLA : IStandardIO public class MOSPLA
{ {
// ------------------------------------ // ------------------------------------
public Func<int, byte> PeekBasicRom;
public Func<int, byte> PeekCartridgeLo;
public Func<int, byte> PeekCartridgeHi;
public Func<int, byte> PeekCharRom;
public Func<int, byte> PeekCia0;
public Func<int, byte> PeekCia1;
public Func<int, byte> PeekColorRam;
public Func<int, byte> PeekExpansionLo;
public Func<int, byte> PeekExpansionHi;
public Func<int, byte> PeekKernalRom;
public Func<int, byte> PeekMemory;
public Func<int, byte> PeekSid;
public Func<int, byte> PeekVic;
public Action<int, byte> PokeCartridgeLo;
public Action<int, byte> PokeCartridgeHi;
public Action<int, byte> PokeCia0;
public Action<int, byte> PokeCia1;
public Action<int, byte> PokeColorRam;
public Action<int, byte> PokeExpansionLo;
public Action<int, byte> PokeExpansionHi;
public Action<int, byte> PokeMemory;
public Action<int, byte> PokeSid;
public Action<int, byte> PokeVic;
public Func<ushort, byte> ReadBasicRom;
public Func<ushort, byte> ReadCartridgeLo;
public Func<ushort, byte> ReadCartridgeHi;
public Func<bool> ReadCharen;
public Func<ushort, byte> ReadCharRom;
public Func<ushort, byte> ReadCia0;
public Func<ushort, byte> ReadCia1;
public Func<ushort, byte> ReadColorRam;
public Func<ushort, byte> ReadExpansionLo;
public Func<ushort, byte> ReadExpansionHi;
public Func<bool> ReadExRom;
public Func<bool> ReadGame;
public Func<bool> ReadHiRam;
public Func<ushort, byte> ReadKernalRom;
public Func<bool> ReadLoRam;
public Func<ushort, byte> ReadMemory;
public Func<ushort, byte> ReadSid;
public Func<ushort, byte> ReadVic;
public Action<ushort, byte> WriteCartridgeLo;
public Action<ushort, byte> WriteCartridgeHi;
public Action<ushort, byte> WriteCia0;
public Action<ushort, byte> WriteCia1;
public Action<ushort, byte> WriteColorRam;
public Action<ushort, byte> WriteExpansionLo;
public Action<ushort, byte> WriteExpansionHi;
public Action<ushort, byte> WriteMemory;
public Action<ushort, byte> WriteSid;
public Action<ushort, byte> WriteVic;
// ------------------------------------
private enum PLABank private enum PLABank
{ {
None, None,
@ -43,21 +97,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// ------------------------------------ // ------------------------------------
private byte bus;
private C64Chips chips;
private bool cia0portRead;
private PLACpuMap map; private PLACpuMap map;
private bool pinCharenLast; private bool pinCharenLast;
private bool pinExRomLast; private bool pinExRomLast;
private bool pinGameLast; private bool pinGameLast;
private bool pinHiRamLast; private bool pinHiRamLast;
private bool pinLoRamLast; private bool pinLoRamLast;
private bool ultimax;
private ushort vicBank;
public MOSPLA(C64Chips newChips) public MOSPLA()
{ {
chips = newChips;
} }
public void HardReset() public void HardReset()
@ -79,7 +127,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public void UpdatePins() public void UpdatePins()
{ {
if ((ExRom != pinExRomLast) || (Game != pinGameLast) || (LoRam != pinLoRamLast) || (HiRam != pinHiRamLast) || (Charen != pinCharenLast)) if ((ReadExRom() != pinExRomLast) || (ReadGame() != pinGameLast) || (ReadLoRam() != pinLoRamLast) || (ReadHiRam() != pinHiRamLast) || (ReadCharen() != pinCharenLast))
{ {
UpdateMap(); UpdateMap();
} }
@ -87,51 +135,14 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// ------------------------------------ // ------------------------------------
public bool Charen
{
get { return chips.cpu.Charen; }
}
public bool ExRom
{
get { return chips.cartPort.ExRom; }
}
public bool Game
{
get { return chips.cartPort.Game; }
}
public bool HiRam
{
get { return chips.cpu.HiRam; }
}
public bool InputWasRead
{
get { return cia0portRead; }
set { cia0portRead = value; }
}
public bool LoRam
{
get { return chips.cpu.LoRam; }
}
public bool UltimaxMode
{
get { return (!Game && ExRom); }
}
private void UpdateMap() private void UpdateMap()
{ {
bool pinGame = Game; bool pinGame = ReadGame();
bool pinExRom = ExRom; bool pinExRom = ReadExRom();
bool pinCharen = Charen; bool pinCharen = ReadCharen();
bool pinHiRam = HiRam; bool pinHiRam = ReadHiRam();
bool pinLoRam = LoRam; bool pinLoRam = ReadLoRam();
ultimax = false;
if (pinCharen && pinHiRam && pinLoRam && pinGame && pinExRom) if (pinCharen && pinHiRam && pinLoRam && pinGame && pinExRom)
{ {
// 11111 // 11111
@ -311,18 +322,17 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
map.layoutC000 = PLABank.None; map.layoutC000 = PLABank.None;
map.layoutD000 = PLABank.IO; map.layoutD000 = PLABank.IO;
map.layoutE000 = PLABank.CartridgeHi; map.layoutE000 = PLABank.CartridgeHi;
ultimax = true;
} }
else else
{ {
throw new Exception("Memory configuration missing from PLA, fix this!"); throw new Exception("Memory configuration missing from PLA, fix this!");
} }
pinExRomLast = ExRom; pinExRomLast = pinExRom;
pinGameLast = Game; pinGameLast = pinGame;
pinLoRamLast = LoRam; pinLoRamLast = pinLoRam;
pinHiRamLast = HiRam; pinHiRamLast = pinHiRam;
pinCharenLast = Charen; pinCharenLast = pinCharen;
} }
// ------------------------------------ // ------------------------------------
@ -374,33 +384,33 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
switch (Bank((ushort)(addr & 0xFFFF))) switch (Bank((ushort)(addr & 0xFFFF)))
{ {
case PLABank.BasicROM: case PLABank.BasicROM:
return chips.basicRom.Peek(addr); return PeekBasicRom(addr);
case PLABank.CartridgeHi: case PLABank.CartridgeHi:
return chips.cartPort.PeekHiRom(addr); return PeekCartridgeHi(addr);
case PLABank.CartridgeLo: case PLABank.CartridgeLo:
return chips.cartPort.PeekLoRom(addr); return PeekCartridgeLo(addr);
case PLABank.CharROM: case PLABank.CharROM:
return chips.charRom.Peek(addr); return PeekCharRom(addr);
case PLABank.Cia0: case PLABank.Cia0:
return chips.cia0.Peek(addr); return PeekCia0(addr);
case PLABank.Cia1: case PLABank.Cia1:
return chips.cia1.Peek(addr); return PeekCia1(addr);
case PLABank.ColorRam: case PLABank.ColorRam:
return chips.colorRam.Peek(addr, bus); return PeekColorRam(addr);
case PLABank.Expansion0: case PLABank.Expansion0:
return chips.cartPort.PeekLoExp(addr); return PeekExpansionLo(addr);
case PLABank.Expansion1: case PLABank.Expansion1:
return chips.cartPort.PeekHiExp(addr); return PeekExpansionHi(addr);
case PLABank.KernalROM: case PLABank.KernalROM:
return chips.kernalRom.Peek(addr); return PeekKernalRom(addr);
case PLABank.None: case PLABank.None:
return 0xFF; return 0xFF;
case PLABank.RAM: case PLABank.RAM:
return chips.ram.Peek(addr); return PeekMemory(addr);
case PLABank.Sid: case PLABank.Sid:
return chips.sid.Peek(addr); return PeekSid(addr);
case PLABank.Vic: case PLABank.Vic:
return chips.vic.Peek(addr); return PeekVic(addr);
} }
return 0xFF; return 0xFF;
} }
@ -410,46 +420,42 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
switch (Bank((ushort)(addr & 0xFFFF))) switch (Bank((ushort)(addr & 0xFFFF)))
{ {
case PLABank.BasicROM: case PLABank.BasicROM:
chips.basicRom.Poke(addr, val);
break; break;
case PLABank.CartridgeHi: case PLABank.CartridgeHi:
chips.cartPort.PokeHiRom(addr, val); PokeCartridgeHi(addr, val);
break; break;
case PLABank.CartridgeLo: case PLABank.CartridgeLo:
chips.cartPort.PokeLoRom(addr, val); PokeCartridgeLo(addr, val);
break; break;
case PLABank.CharROM: case PLABank.CharROM:
chips.charRom.Poke(addr, val);
break; break;
case PLABank.Cia0: case PLABank.Cia0:
chips.cia0.Poke(addr, val); PokeCia0(addr, val);
break; break;
case PLABank.Cia1: case PLABank.Cia1:
chips.cia1.Poke(addr, val); PokeCia1(addr, val);
UpdateVicBank();
break; break;
case PLABank.ColorRam: case PLABank.ColorRam:
chips.colorRam.Poke(addr, val); PokeColorRam(addr, val);
break; break;
case PLABank.Expansion0: case PLABank.Expansion0:
chips.cartPort.PokeLoExp(addr, val); PokeExpansionLo(addr, val);
break; break;
case PLABank.Expansion1: case PLABank.Expansion1:
chips.cartPort.PokeHiExp(addr, val); PokeExpansionHi(addr, val);
break; break;
case PLABank.KernalROM: case PLABank.KernalROM:
chips.kernalRom.Poke(addr, val);
break; break;
case PLABank.None: case PLABank.None:
break; break;
case PLABank.RAM: case PLABank.RAM:
chips.ram.Poke(addr, val); PokeMemory(addr, val);
break; break;
case PLABank.Sid: case PLABank.Sid:
chips.sid.Poke(addr, val); PokeSid(addr, val);
break; break;
case PLABank.Vic: case PLABank.Vic:
chips.vic.Poke(addr, val); PokeVic(addr, val);
break; break;
} }
} }
@ -459,134 +465,76 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
switch (Bank(addr)) switch (Bank(addr))
{ {
case PLABank.BasicROM: case PLABank.BasicROM:
bus = chips.basicRom.Read(addr); return ReadBasicRom(addr);
break;
case PLABank.CartridgeHi: case PLABank.CartridgeHi:
bus = chips.cartPort.ReadHiRom(addr); return ReadCartridgeHi(addr);
break;
case PLABank.CartridgeLo: case PLABank.CartridgeLo:
bus = chips.cartPort.ReadLoRom(addr); return ReadCartridgeLo(addr);
break;
case PLABank.CharROM: case PLABank.CharROM:
bus = chips.charRom.Read(addr); return ReadCharRom(addr);
break;
case PLABank.Cia0: case PLABank.Cia0:
if (addr == 0xDC00 || addr == 0xDC01) return ReadCia0(addr);
cia0portRead = true;
bus = chips.cia0.Read(addr);
break;
case PLABank.Cia1: case PLABank.Cia1:
bus = chips.cia1.Read(addr); return ReadCia1(addr);
break;
case PLABank.ColorRam: case PLABank.ColorRam:
bus = chips.colorRam.Read(addr, bus); return ReadColorRam(addr);
break;
case PLABank.Expansion0: case PLABank.Expansion0:
bus = chips.cartPort.ReadLoExp(addr); return ReadExpansionLo(addr);
break;
case PLABank.Expansion1: case PLABank.Expansion1:
bus = chips.cartPort.ReadHiExp(addr); return ReadExpansionHi(addr);
break;
case PLABank.KernalROM: case PLABank.KernalROM:
bus = chips.kernalRom.Read(addr); return ReadKernalRom(addr);
break;
case PLABank.None:
bus = 0xFF;
break;
case PLABank.RAM: case PLABank.RAM:
bus = chips.ram.Read(addr); return ReadMemory(addr);
break;
case PLABank.Sid: case PLABank.Sid:
bus = chips.sid.Read(addr); return ReadSid(addr);
break;
case PLABank.Vic: case PLABank.Vic:
bus = chips.vic.Read(addr); return ReadVic(addr);
break;
}
return bus;
}
public byte ReadVic(ushort addr)
{
addr &= 0x3FFF;
if (ultimax)
{
if (addr >= 0x3000)
return 0; //todo: change to ROMHI
else
return chips.ram.Read(addr);
}
else
{
addr |= vicBank;
if ((addr & 0x7000) == 0x1000)
return chips.charRom.Read(addr);
else
return chips.ram.Read(addr);
} }
return 0xFF;
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
ser.Sync("bus", ref bus);
ser.Sync("cia0portRead", ref cia0portRead);
ser.Sync("pinCharenLast", ref pinCharenLast); ser.Sync("pinCharenLast", ref pinCharenLast);
ser.Sync("pinExRomLast", ref pinExRomLast); ser.Sync("pinExRomLast", ref pinExRomLast);
ser.Sync("pinGameLast", ref pinGameLast); ser.Sync("pinGameLast", ref pinGameLast);
ser.Sync("pinHiRamLast", ref pinHiRamLast); ser.Sync("pinHiRamLast", ref pinHiRamLast);
ser.Sync("pinLoRamLast", ref pinLoRamLast); ser.Sync("pinLoRamLast", ref pinLoRamLast);
ser.Sync("ultimax", ref ultimax);
ser.Sync("vicBank", ref vicBank);
if (ser.IsReader) UpdateMap(); if (ser.IsReader) UpdateMap();
} }
private void UpdateVicBank()
{
switch (chips.cia1.ReadPort0() & 0x3)
{
case 0: vicBank = 0xC000; break;
case 1: vicBank = 0x8000; break;
case 2: vicBank = 0x4000; break;
case 3: vicBank = 0x0000; break;
}
}
public void Write(ushort addr, byte val) public void Write(ushort addr, byte val)
{ {
switch (Bank(addr)) switch (Bank(addr))
{ {
case PLABank.BasicROM: case PLABank.BasicROM:
chips.basicRom.Write(addr, val);
break; break;
case PLABank.CartridgeHi: case PLABank.CartridgeHi:
chips.cartPort.WriteHiRom(addr, val); WriteCartridgeHi(addr, val);
break; break;
case PLABank.CartridgeLo: case PLABank.CartridgeLo:
chips.cartPort.WriteLoRom(addr, val); WriteCartridgeLo(addr, val);
break; break;
case PLABank.CharROM: case PLABank.CharROM:
chips.charRom.Write(addr, val);
break; break;
case PLABank.Cia0: case PLABank.Cia0:
chips.cia0.Write(addr, val); WriteCia0(addr, val);
break; break;
case PLABank.Cia1: case PLABank.Cia1:
chips.cia1.Write(addr, val); WriteCia1(addr, val);
UpdateVicBank();
break; break;
case PLABank.ColorRam: case PLABank.ColorRam:
chips.colorRam.Write(addr, val); WriteColorRam(addr, val);
break; break;
case PLABank.Expansion0: case PLABank.Expansion0:
chips.cartPort.WriteLoExp(addr, val); WriteExpansionLo(addr, val);
break; break;
case PLABank.Expansion1: case PLABank.Expansion1:
chips.cartPort.WriteHiExp(addr, val); WriteExpansionHi(addr, val);
break; break;
case PLABank.KernalROM: case PLABank.KernalROM:
chips.kernalRom.Write(addr, val);
break; break;
case PLABank.None: case PLABank.None:
break; break;
@ -594,13 +542,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// RAM is written through anyway, don't do it here // RAM is written through anyway, don't do it here
break; break;
case PLABank.Sid: case PLABank.Sid:
chips.sid.Write(addr, val); WriteSid(addr, val);
break; break;
case PLABank.Vic: case PLABank.Vic:
chips.vic.Write(addr, val); WriteVic(addr, val);
break; break;
} }
chips.ram.Write(addr, val); WriteMemory(addr, val);
} }
} }
} }

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public class SerialPort
{
public void HardReset()
{
}
}
}

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
public abstract partial class Sid : IStandardIO public abstract partial class Sid
{ {
// ------------------------------------ // ------------------------------------
@ -64,6 +64,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
public void ExecutePhase2() public void ExecutePhase2()
{
{ {
if (!delay) if (!delay)
{ {
@ -121,6 +123,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
UpdateExpCounter(); UpdateExpCounter();
} }
} }
}
public void HardReset() public void HardReset()
{ {
@ -140,6 +143,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
private void UpdateExpCounter() private void UpdateExpCounter()
{
{ {
for (uint i = 0; i < 7; i++) for (uint i = 0; i < 7; i++)
{ {
@ -149,6 +154,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if (envCounter == 0) if (envCounter == 0)
freeze = true; freeze = true;
} }
}
// ------------------------------------ // ------------------------------------
@ -318,6 +324,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
public void ExecutePhase2() public void ExecutePhase2()
{
{ {
if (test) if (test)
{ {
@ -340,24 +348,33 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
ClockShiftReg(); ClockShiftReg();
} }
} }
}
// ------------------------------------ // ------------------------------------
private void ClockShiftReg() private void ClockShiftReg()
{
{ {
uint bit0 = ((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1; uint bit0 = ((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1;
shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF; shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF;
SetNoise(); SetNoise();
} }
}
private void ResetShiftReg() private void ResetShiftReg()
{
{ {
shiftRegister = 0x7FFFFF; shiftRegister = 0x7FFFFF;
shiftRegisterReset = 0; shiftRegisterReset = 0;
SetNoise(); SetNoise();
} }
}
private void SetNoise() private void SetNoise()
{
{ {
noise = noise =
((shiftRegister & 0x100000) >> 9) | ((shiftRegister & 0x100000) >> 9) |
@ -370,8 +387,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
((shiftRegister & 0x000001) << 4); ((shiftRegister & 0x000001) << 4);
noNoiseOrNoise = noNoise | noise; noNoiseOrNoise = noNoise | noise;
} }
}
private void WriteShiftReg() private void WriteShiftReg()
{
{ {
output &= output &=
0xBB5DA | 0xBB5DA |
@ -385,6 +405,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
noise &= output; noise &= output;
noNoiseOrNoise = noNoise | noise; noNoiseOrNoise = noNoise | noise;
} }
}
// ------------------------------------ // ------------------------------------
@ -470,6 +491,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
public uint Output(Voice ringModSource) public uint Output(Voice ringModSource)
{
{ {
if (waveform != 0) if (waveform != 0)
{ {
@ -486,6 +509,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
pulse = ((accumulator >> 12) >= pulseWidth) ? (uint)0xFFF : (uint)0x000; pulse = ((accumulator >> 12) >= pulseWidth) ? (uint)0xFFF : (uint)0x000;
return output; return output;
} }
}
public uint PulseWidth public uint PulseWidth
{ {
@ -607,13 +631,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private bool filterSelectLoPass; private bool filterSelectLoPass;
private bool filterSelectHiPass; private bool filterSelectHiPass;
private uint potCounter; private uint potCounter;
private uint potX; private byte potX;
private uint potY; private byte potY;
private uint[] voiceOutput; private uint[] voiceOutput;
private Voice[] voices; private Voice[] voices;
private uint volume; private uint volume;
private uint[][] waveformTable; private uint[][] waveformTable;
public Func<byte> ReadPotX;
public Func<byte> ReadPotY;
public Sid(uint[][] newWaveformTable, uint newSampleRate, Region newRegion) public Sid(uint[][] newWaveformTable, uint newSampleRate, Region newRegion)
{ {
switch (newRegion) switch (newRegion)
@ -663,13 +690,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
public void ExecutePhase2() public void ExecutePhase2()
{
{ {
// potentiometer values refresh every 512 cycles // potentiometer values refresh every 512 cycles
if (potCounter == 0) if (potCounter == 0)
{ {
potCounter = 512; potCounter = 512;
potX = 0; //todo: implement paddles potX = ReadPotX(); //todo: implement paddles
potY = 0; potY = ReadPotY();
} }
// process voices and envelopes // process voices and envelopes
@ -713,6 +742,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
bufferCounter--; bufferCounter--;
} }
}
// ------------------------------------ // ------------------------------------

View File

@ -10,66 +10,28 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public abstract class Timer public abstract class Timer
{ {
protected bool pinIRQ; protected bool pinIRQ;
protected byte[] portData;
protected byte[] portDir;
protected byte[] portMask;
protected uint[] timer; protected uint[] timer;
protected uint[] timerLatch; protected uint[] timerLatch;
protected bool[] timerOn; protected bool[] timerOn;
protected bool[] underflow; protected bool[] underflow;
public Func<byte> ReadDirA;
public Func<byte> ReadDirB;
public Func<byte> ReadPortA;
public Func<byte> ReadPortB;
public Action<byte> WriteDirA;
public Action<byte> WriteDirB;
public Action<byte> WritePortA;
public Action<byte> WritePortB;
public Timer() public Timer()
{ {
portData = new byte[2];
portDir = new byte[2];
portMask = new byte[2];
timer = new uint[2]; timer = new uint[2];
timerLatch = new uint[2]; timerLatch = new uint[2];
timerOn = new bool[2]; timerOn = new bool[2];
underflow = new bool[2]; underflow = new bool[2];
} }
public PortAdapter Adapter0
{
get
{
return Port.GetAdapter(ReadPort0, ExternalWritePort0, ExternalWriteMask0);
}
}
public PortAdapter Adapter1
{
get
{
return Port.GetAdapter(ReadPort1, ExternalWritePort1, ExternalWriteMask1);
}
}
private void ExternalWriteMask0(byte data)
{
portMask[0] = data;
}
private void ExternalWriteMask1(byte data)
{
portMask[1] = data;
}
private void ExternalWritePort(uint index, byte data)
{
portData[index] = Port.ExternalWrite(portData[index], data, portDir[index]);
}
private void ExternalWritePort0(byte data)
{
ExternalWritePort(0, data);
}
private void ExternalWritePort1(byte data)
{
ExternalWritePort(1, data);
}
protected void HardResetInternal() protected void HardResetInternal()
{ {
timer[0] = 0xFFFF; timer[0] = 0xFFFF;
@ -77,12 +39,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
timerLatch[0] = timer[0]; timerLatch[0] = timer[0];
timerLatch[1] = timer[1]; timerLatch[1] = timer[1];
pinIRQ = true; pinIRQ = true;
portDir[0] = 0xFF;
portDir[1] = 0xFF;
portMask[0] = 0xFF;
portMask[1] = 0xFF;
portData[0] = 0xFF;
portData[1] = 0xFF;
} }
public bool IRQ public bool IRQ
@ -93,25 +49,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
} }
public byte ReadPort0()
{
return portData[0];
}
public byte ReadPort1()
{
return portData[1];
}
protected void SyncInternal(Serializer ser) protected void SyncInternal(Serializer ser)
{ {
ser.Sync("pinIRQ", ref pinIRQ); ser.Sync("pinIRQ", ref pinIRQ);
ser.Sync("portData0", ref portData[0]);
ser.Sync("portData1", ref portData[1]);
ser.Sync("portDir0", ref portDir[0]);
ser.Sync("portDir1", ref portDir[1]);
ser.Sync("portMask0", ref portMask[0]);
ser.Sync("portMask1", ref portMask[1]);
ser.Sync("timer0", ref timer[0]); ser.Sync("timer0", ref timer[0]);
ser.Sync("timer1", ref timer[1]); ser.Sync("timer1", ref timer[1]);
ser.Sync("timerLatch0", ref timerLatch[0]); ser.Sync("timerLatch0", ref timerLatch[0]);
@ -121,20 +61,5 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
ser.Sync("underflow0", ref underflow[0]); ser.Sync("underflow0", ref underflow[0]);
ser.Sync("underflow1", ref underflow[1]); ser.Sync("underflow1", ref underflow[1]);
} }
private void WritePort(uint index, byte data)
{
portData[index] = Port.CPUWrite(portData[index], data, portDir[index]);
}
public void WritePort0(byte data)
{
WritePort(0, data);
}
public void WritePort1(byte data)
{
WritePort(1, data);
}
} }
} }

View File

@ -6,7 +6,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
public abstract partial class Vic : IStandardIO public abstract partial class Vic
{ {
// ------------------------------------ // ------------------------------------
@ -103,7 +103,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private uint borderT; private uint borderT;
private uint[] bufferC; private uint[] bufferC;
private uint[] bufferG; private uint[] bufferG;
private byte bus;
private bool columnSelect; private bool columnSelect;
private uint cycle; private uint cycle;
private uint cycleIndex; private uint cycleIndex;
@ -126,12 +125,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private uint lightPenX; private uint lightPenX;
private uint lightPenY; private uint lightPenY;
private bool multicolorMode; private bool multicolorMode;
private uint[] pixelBuffer;
private uint pixelBufferDelay;
private uint pixelBufferIndex;
private uint[] pixelBackgroundBuffer; private uint[] pixelBackgroundBuffer;
private uint pixelBackgroundBufferDelay; private uint pixelBackgroundBufferDelay;
private uint pixelBackgroundBufferIndex; private uint pixelBackgroundBufferIndex;
private uint[] pixelBuffer;
private uint pixelBufferDelay;
private uint pixelBufferIndex;
private uint[] pixelDataBuffer; private uint[] pixelDataBuffer;
private uint pointerCB; private uint pointerCB;
private uint pointerVM; private uint pointerVM;
@ -153,7 +152,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// ------------------------------------ // ------------------------------------
private C64Chips chips;
private int cyclesPerSec; private int cyclesPerSec;
private bool pinAEC; private bool pinAEC;
private bool pinBA; private bool pinBA;
@ -164,9 +162,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// ------------------------------------ // ------------------------------------
public Vic(C64Chips newChips, uint newCycles, uint newLines, uint[][] newPipeline, int newCyclesPerSec) public Func<ushort, byte> ReadColorRam;
public Func<ushort, byte> ReadMemory;
// ------------------------------------
public Vic(uint newCycles, uint newLines, uint[][] newPipeline, int newCyclesPerSec)
{
{ {
chips = newChips;
totalCycles = newCycles; totalCycles = newCycles;
totalLines = newLines; totalLines = newLines;
pipeline = newPipeline; pipeline = newPipeline;
@ -190,6 +194,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
pixelDataBuffer = new uint[pixelBufferDelay]; pixelDataBuffer = new uint[pixelBufferDelay];
pixelBackgroundBuffer = new uint[pixelBackgroundBufferDelay]; pixelBackgroundBuffer = new uint[pixelBackgroundBufferDelay];
} }
}
public void HardReset() public void HardReset()
{ {
@ -273,6 +278,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
private void UpdateBA() private void UpdateBA()
{
{ {
if (pinBA) if (pinBA)
baCount = baResetCounter; baCount = baResetCounter;
@ -280,16 +287,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
baCount--; baCount--;
pinAEC = (baCount > 0); pinAEC = (baCount > 0);
} }
}
private void UpdateBorder() private void UpdateBorder()
{
{ {
borderL = columnSelect ? (uint)0x018 : (uint)0x01F; borderL = columnSelect ? (uint)0x018 : (uint)0x01F;
borderR = columnSelect ? (uint)0x158 : (uint)0x14F; borderR = columnSelect ? (uint)0x158 : (uint)0x14F;
borderT = rowSelect ? (uint)0x033 : (uint)0x037; borderT = rowSelect ? (uint)0x033 : (uint)0x037;
borderB = rowSelect ? (uint)0x0FB : (uint)0x0F7; borderB = rowSelect ? (uint)0x0FB : (uint)0x0F7;
} }
}
private void UpdatePins() private void UpdatePins()
{
{ {
pinIRQ = !( pinIRQ = !(
(enableIntRaster & intRaster) | (enableIntRaster & intRaster) |
@ -297,6 +310,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
(enableIntSpriteCollision & intSpriteCollision) | (enableIntSpriteCollision & intSpriteCollision) |
(enableIntLightPen & intLightPen)); (enableIntLightPen & intLightPen));
} }
}
// ------------------------------------ // ------------------------------------
@ -320,6 +334,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// ------------------------------------ // ------------------------------------
public void ExecutePhase1() public void ExecutePhase1()
{
{ {
// raster IRQ compare // raster IRQ compare
if ((cycle == rasterIrqLineXCycle && rasterLine > 0) || (cycle == rasterIrqLine0Cycle && rasterLine == 0)) if ((cycle == rasterIrqLineXCycle && rasterLine > 0) || (cycle == rasterIrqLine0Cycle && rasterLine == 0))
@ -371,8 +387,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// must always come last // must always come last
UpdatePins(); UpdatePins();
} }
}
public void ExecutePhase2() public void ExecutePhase2()
{
{ {
ParseCycle(); ParseCycle();
@ -401,8 +420,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// must always come last // must always come last
UpdatePins(); UpdatePins();
} }
}
private void ParseCycle() private void ParseCycle()
{
{ {
ushort addr = 0x3FFF; ushort addr = 0x3FFF;
uint cycleBAsprite0; uint cycleBAsprite0;
@ -423,7 +445,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// fetch R // fetch R
refreshCounter = (refreshCounter - 1) & 0xFF; refreshCounter = (refreshCounter - 1) & 0xFF;
addr = (ushort)(0x3F00 | refreshCounter); addr = (ushort)(0x3F00 | refreshCounter);
bus = chips.pla.ReadVic(addr); ReadMemory(addr);
break; break;
case 0x0200: case 0x0200:
// fetch C // fetch C
@ -432,10 +454,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if (badline) if (badline)
{ {
addr = (ushort)((pointerVM << 10) | vc); addr = (ushort)((pointerVM << 10) | vc);
bus = chips.pla.ReadVic(addr); dataC = ReadMemory(addr);
dataC = bus; dataC |= ((uint)ReadColorRam(addr) & 0xF) << 8;
dataC |= (uint)chips.colorRam.Read((ushort)vc) << 8;
dataC &= 0xFFF;
bufferC[vmli] = dataC; bufferC[vmli] = dataC;
} }
else else
@ -462,8 +482,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
if (extraColorMode) if (extraColorMode)
addr &= 0x39FF; addr &= 0x39FF;
bus = chips.pla.ReadVic(addr); dataG = ReadMemory(addr);
dataG = bus;
if (!idle) if (!idle)
{ {
bufferG[vmli] = dataG; bufferG[vmli] = dataG;
@ -474,8 +493,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
case 0x0400: case 0x0400:
// fetch I // fetch I
addr = (extraColorMode ? (ushort)0x39FF : (ushort)0x3FFF); addr = (extraColorMode ? (ushort)0x39FF : (ushort)0x3FFF);
bus = chips.pla.ReadVic(addr); dataG = ReadMemory(addr);
dataG = bus;
dataC = 0; dataC = 0;
break; break;
case 0x0500: case 0x0500:
@ -488,8 +506,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
case 0x00: case 0x00:
// fetch P // fetch P
addr = (ushort)(0x3F8 | (pointerVM << 10) | cycleFetchSpriteIndex); addr = (ushort)(0x3F8 | (pointerVM << 10) | cycleFetchSpriteIndex);
bus = chips.pla.ReadVic(addr); sprites[cycleFetchSpriteIndex].pointer = ReadMemory(addr);
sprites[cycleFetchSpriteIndex].pointer = bus;
sprites[cycleFetchSpriteIndex].shiftEnable = false; sprites[cycleFetchSpriteIndex].shiftEnable = false;
break; break;
case 0x10: case 0x10:
@ -500,9 +517,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
Sprite spr = sprites[cycleFetchSpriteIndex]; Sprite spr = sprites[cycleFetchSpriteIndex];
addr = (ushort)(spr.mc | (spr.pointer << 6)); addr = (ushort)(spr.mc | (spr.pointer << 6));
bus = chips.pla.ReadVic(addr);
spr.sr <<= 8; spr.sr <<= 8;
spr.sr |= bus; spr.sr |= ReadMemory(addr);
spr.mc++; spr.mc++;
} }
break; break;
@ -545,6 +561,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
spr.mcbase += 2; spr.mcbase += 2;
spr.shiftEnable = false; spr.shiftEnable = false;
spr.xCrunch = !spr.xExpand; spr.xCrunch = !spr.xExpand;
spr.multicolorCrunch = !spr.multicolor;
} }
} }
if ((act & pipelineChkSprDisp) != 0) if ((act & pipelineChkSprDisp) != 0)
@ -568,8 +585,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
spr.dma = true; spr.dma = true;
spr.mcbase = 0; spr.mcbase = 0;
if (spr.yExpand) spr.yCrunch = !spr.yExpand;
spr.yCrunch = false;
} }
} }
} }
@ -620,8 +636,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
cycleIndex++; cycleIndex++;
} }
}
private void Render() private void Render()
{
{ {
uint pixel; uint pixel;
uint pixelData; uint pixelData;
@ -700,11 +719,30 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
case 2: sprPixel = spr.color; break; case 2: sprPixel = spr.color; break;
case 3: sprPixel = spriteMulticolor1; break; case 3: sprPixel = spriteMulticolor1; break;
} }
if (sprData != 0 && pixelOwner >= 8) if (sprData != 0)
{ {
// sprite-sprite collision
if (pixelOwner >= 8)
{
if (!spr.priority || (pixelDataBuffer[pixelBackgroundBufferIndex] < 0x2))
pixel = sprPixel; pixel = sprPixel;
pixelOwner = j; pixelOwner = j;
} }
else
{
if (!borderOnVertical)
{
spr.collideSprite = true;
sprites[pixelOwner].collideSprite = true;
}
}
// sprite-data collision
if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] >= 0x2))
{
spr.collideData = true;
}
}
if (spr.sr == 0) if (spr.sr == 0)
spr.shiftEnable = false; //optimization spr.shiftEnable = false; //optimization
} }
@ -821,6 +859,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
// put the rendered pixel into the background buffer // put the rendered pixel into the background buffer
pixelDataBuffer[pixelBackgroundBufferIndex] = pixelData;
pixelBackgroundBuffer[pixelBackgroundBufferIndex] = pixel; pixelBackgroundBuffer[pixelBackgroundBufferIndex] = pixel;
pixelBackgroundBufferIndex++; pixelBackgroundBufferIndex++;
if (pixelBackgroundBufferIndex == pixelBackgroundBufferDelay) if (pixelBackgroundBufferIndex == pixelBackgroundBufferDelay)
@ -836,6 +875,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
bitmapColumn++; bitmapColumn++;
} }
} }
}
// ------------------------------------ // ------------------------------------
@ -1379,7 +1419,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
ser.Sync("borderT", ref borderT); ser.Sync("borderT", ref borderT);
ser.Sync("bufferC", ref bufferC, false); ser.Sync("bufferC", ref bufferC, false);
ser.Sync("bufferG", ref bufferG, false); ser.Sync("bufferG", ref bufferG, false);
ser.Sync("bus", ref bus);
ser.Sync("columnSelect", ref columnSelect); ser.Sync("columnSelect", ref columnSelect);
ser.Sync("cycle", ref cycle); ser.Sync("cycle", ref cycle);
ser.Sync("cycleIndex", ref cycleIndex); ser.Sync("cycleIndex", ref cycleIndex);