commodore64: implement motherboard configuration, add sprite-sprite and sprite-data collision interrupts to VIC
This commit is contained in:
parent
fc484df925
commit
c64951fce8
|
@ -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" />
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
|
@ -105,42 +105,49 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void ExecutePhase2()
|
public void ExecutePhase2()
|
||||||
{
|
{
|
||||||
pinPC = true;
|
|
||||||
TODRun();
|
|
||||||
|
|
||||||
if (timerPulse[0])
|
{
|
||||||
portData[0] &= PBOnMask[0];
|
pinPC = true;
|
||||||
if (timerPulse[1])
|
TODRun();
|
||||||
portData[1] &= PBOnMask[0];
|
|
||||||
|
|
||||||
if (timerDelay[0] == 0)
|
if (timerPulse[0])
|
||||||
TimerRun(0);
|
{
|
||||||
else
|
WritePortA((byte)(ReadPortA() & PBOnMask[0]));
|
||||||
timerDelay[0]--;
|
}
|
||||||
|
if (timerPulse[1])
|
||||||
|
{
|
||||||
|
WritePortB((byte)(ReadPortA() & PBOnMask[1]));
|
||||||
|
}
|
||||||
|
|
||||||
if (timerDelay[1] == 0)
|
if (timerDelay[0] == 0)
|
||||||
TimerRun(1);
|
TimerRun(0);
|
||||||
else
|
else
|
||||||
timerDelay[1]--;
|
timerDelay[0]--;
|
||||||
|
|
||||||
intAlarm |= (
|
if (timerDelay[1] == 0)
|
||||||
tod[0] == todAlarm[0] &&
|
TimerRun(1);
|
||||||
tod[1] == todAlarm[1] &&
|
else
|
||||||
tod[2] == todAlarm[2] &&
|
timerDelay[1]--;
|
||||||
tod[3] == todAlarm[3] &&
|
|
||||||
todPM == todAlarmPM);
|
|
||||||
|
|
||||||
cntPos = false;
|
intAlarm |= (
|
||||||
underflow[0] = false;
|
tod[0] == todAlarm[0] &&
|
||||||
underflow[1] = false;
|
tod[1] == todAlarm[1] &&
|
||||||
|
tod[2] == todAlarm[2] &&
|
||||||
|
tod[3] == todAlarm[3] &&
|
||||||
|
todPM == todAlarmPM);
|
||||||
|
|
||||||
pinIRQ = !(
|
cntPos = false;
|
||||||
(intTimer[0] && enableIntTimer[0]) ||
|
underflow[0] = false;
|
||||||
(intTimer[1] && enableIntTimer[1]) ||
|
underflow[1] = false;
|
||||||
(intAlarm && enableIntAlarm) ||
|
|
||||||
(intSP && enableIntSP) ||
|
pinIRQ = !(
|
||||||
(intFlag && enableIntFlag)
|
(intTimer[0] && enableIntTimer[0]) ||
|
||||||
);
|
(intTimer[1] && enableIntTimer[1]) ||
|
||||||
|
(intAlarm && enableIntAlarm) ||
|
||||||
|
(intSP && enableIntSP) ||
|
||||||
|
(intFlag && enableIntFlag)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HardReset()
|
public void HardReset()
|
||||||
|
@ -210,135 +217,144 @@ 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 hi;
|
|
||||||
uint result;
|
|
||||||
|
|
||||||
lo = (i & (uint)0x0F) + (j & (uint)0x0F);
|
|
||||||
hi = (i & (uint)0x70) + (j & (uint)0x70);
|
|
||||||
if (lo > 0x09)
|
|
||||||
{
|
{
|
||||||
hi += 0x10;
|
uint lo;
|
||||||
lo += 0x06;
|
uint hi;
|
||||||
|
uint result;
|
||||||
|
|
||||||
|
lo = (i & (uint)0x0F) + (j & (uint)0x0F);
|
||||||
|
hi = (i & (uint)0x70) + (j & (uint)0x70);
|
||||||
|
if (lo > 0x09)
|
||||||
|
{
|
||||||
|
hi += 0x10;
|
||||||
|
lo += 0x06;
|
||||||
|
}
|
||||||
|
if (hi > 0x50)
|
||||||
|
{
|
||||||
|
hi += 0xA0;
|
||||||
|
}
|
||||||
|
overflow = hi >= 0x60;
|
||||||
|
result = (hi & 0x70) + (lo & 0x0F);
|
||||||
|
return (byte)(result & 0xFF);
|
||||||
}
|
}
|
||||||
if (hi > 0x50)
|
|
||||||
{
|
|
||||||
hi += 0xA0;
|
|
||||||
}
|
|
||||||
overflow = hi >= 0x60;
|
|
||||||
result = (hi & 0x70) + (lo & 0x0F);
|
|
||||||
return (byte)(result & 0xFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TimerRun(uint index)
|
private void TimerRun(uint index)
|
||||||
{
|
{
|
||||||
if (timerOn[index])
|
|
||||||
{
|
{
|
||||||
uint t = timer[index];
|
if (timerOn[index])
|
||||||
bool u = false;
|
|
||||||
|
|
||||||
unchecked
|
|
||||||
{
|
{
|
||||||
switch (timerInMode[index])
|
uint t = timer[index];
|
||||||
{
|
bool u = false;
|
||||||
case InMode.CNT:
|
|
||||||
// CNT positive
|
|
||||||
if (cntPos)
|
|
||||||
{
|
|
||||||
u = (t == 0);
|
|
||||||
t--;
|
|
||||||
intTimer[index] |= (t == 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case InMode.Phase2:
|
|
||||||
// every clock
|
|
||||||
u = (t == 0);
|
|
||||||
t--;
|
|
||||||
intTimer[index] |= (t == 0);
|
|
||||||
break;
|
|
||||||
case InMode.TimerAUnderflow:
|
|
||||||
// every underflow[0]
|
|
||||||
if (underflow[0])
|
|
||||||
{
|
|
||||||
u = (t == 0);
|
|
||||||
t--;
|
|
||||||
intTimer[index] |= (t == 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case InMode.TimerAUnderflowCNT:
|
|
||||||
// every underflow[0] while CNT high
|
|
||||||
if (underflow[0] && pinCnt)
|
|
||||||
{
|
|
||||||
u = (t == 0);
|
|
||||||
t--;
|
|
||||||
intTimer[index] |= (t == 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// underflow?
|
|
||||||
if (u)
|
|
||||||
{
|
|
||||||
t = timerLatch[index];
|
|
||||||
if (timerRunMode[index] == RunMode.Oneshot)
|
|
||||||
timerOn[index] = false;
|
|
||||||
|
|
||||||
if (timerPortEnable[index])
|
{
|
||||||
|
switch (timerInMode[index])
|
||||||
{
|
{
|
||||||
// force port B bit to output
|
case InMode.CNT:
|
||||||
portDir[index] |= PBOnBit[index];
|
// CNT positive
|
||||||
switch (timerOutMode[index])
|
if (cntPos)
|
||||||
|
{
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
intTimer[index] |= (t == 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InMode.Phase2:
|
||||||
|
// every clock
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
intTimer[index] |= (t == 0);
|
||||||
|
break;
|
||||||
|
case InMode.TimerAUnderflow:
|
||||||
|
// every underflow[0]
|
||||||
|
if (underflow[0])
|
||||||
|
{
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
intTimer[index] |= (t == 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InMode.TimerAUnderflowCNT:
|
||||||
|
// every underflow[0] while CNT high
|
||||||
|
if (underflow[0] && pinCnt)
|
||||||
|
{
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
intTimer[index] |= (t == 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// underflow?
|
||||||
|
if (u)
|
||||||
|
{
|
||||||
|
t = timerLatch[index];
|
||||||
|
if (timerRunMode[index] == RunMode.Oneshot)
|
||||||
|
timerOn[index] = false;
|
||||||
|
|
||||||
|
if (timerPortEnable[index])
|
||||||
{
|
{
|
||||||
case OutMode.Pulse:
|
// force port B bit to output
|
||||||
timerPulse[index] = true;
|
WriteDirB((byte)(ReadDirB() | PBOnBit[index]));
|
||||||
portData[index] |= PBOnBit[index];
|
switch (timerOutMode[index])
|
||||||
break;
|
{
|
||||||
case OutMode.Toggle:
|
case OutMode.Pulse:
|
||||||
portData[index] ^= PBOnBit[index];
|
timerPulse[index] = true;
|
||||||
break;
|
WritePortB((byte)(ReadPortB() | PBOnBit[index]));
|
||||||
|
break;
|
||||||
|
case OutMode.Toggle:
|
||||||
|
WritePortB((byte)(ReadPortB() ^ PBOnBit[index]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
underflow[index] = u;
|
underflow[index] = u;
|
||||||
timer[index] = t;
|
timer[index] = t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TODRun()
|
private void TODRun()
|
||||||
{
|
{
|
||||||
bool todV;
|
|
||||||
|
|
||||||
if (todCounter == 0)
|
|
||||||
{
|
{
|
||||||
todCounter = todCounterLatch;
|
bool todV;
|
||||||
tod[0] = BCDAdd(tod[0], 1, out todV);
|
|
||||||
if (tod[0] >= 10)
|
if (todCounter == 0)
|
||||||
{
|
{
|
||||||
tod[0] = 0;
|
todCounter = todCounterLatch;
|
||||||
tod[1] = BCDAdd(tod[1], 1, out todV);
|
tod[0] = BCDAdd(tod[0], 1, out todV);
|
||||||
if (todV)
|
if (tod[0] >= 10)
|
||||||
{
|
{
|
||||||
tod[1] = 0;
|
tod[0] = 0;
|
||||||
tod[2] = BCDAdd(tod[2], 1, out todV);
|
tod[1] = BCDAdd(tod[1], 1, out todV);
|
||||||
if (todV)
|
if (todV)
|
||||||
{
|
{
|
||||||
tod[2] = 0;
|
tod[1] = 0;
|
||||||
tod[3] = BCDAdd(tod[3], 1, out todV);
|
tod[2] = BCDAdd(tod[2], 1, out todV);
|
||||||
if (tod[3] > 12)
|
if (todV)
|
||||||
{
|
{
|
||||||
tod[3] = 1;
|
tod[2] = 0;
|
||||||
}
|
tod[3] = BCDAdd(tod[3], 1, out todV);
|
||||||
else if (tod[3] == 12)
|
if (tod[3] > 12)
|
||||||
{
|
{
|
||||||
todPM = !todPM;
|
tod[3] = 1;
|
||||||
|
}
|
||||||
|
else if (tod[3] == 12)
|
||||||
|
{
|
||||||
|
todPM = !todPM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[][]
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
{
|
{
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
|
@ -65,60 +65,63 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void ExecutePhase2()
|
public void ExecutePhase2()
|
||||||
{
|
{
|
||||||
if (!delay)
|
|
||||||
{
|
|
||||||
envCounter--;
|
|
||||||
delay = true;
|
|
||||||
UpdateExpCounter();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lfsr != rate)
|
|
||||||
{
|
{
|
||||||
uint feedback = ((lfsr >> 14) ^ (lfsr >> 13)) & 0x1;
|
if (!delay)
|
||||||
lfsr = ((lfsr << 1) & 0x7FFF) | feedback;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lfsr = 0x7FFF;
|
|
||||||
|
|
||||||
if (state == stateAttack || ++expCounter == expPeriod)
|
|
||||||
{
|
|
||||||
expCounter = 0;
|
|
||||||
if (freeze)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
{
|
||||||
case stateAttack:
|
envCounter--;
|
||||||
envCounter++;
|
delay = true;
|
||||||
if (envCounter == 0xFF)
|
UpdateExpCounter();
|
||||||
{
|
}
|
||||||
state = stateDecay;
|
|
||||||
rate = adsrTable[decay];
|
if (lfsr != rate)
|
||||||
}
|
{
|
||||||
break;
|
uint feedback = ((lfsr >> 14) ^ (lfsr >> 13)) & 0x1;
|
||||||
case stateDecay:
|
lfsr = ((lfsr << 1) & 0x7FFF) | feedback;
|
||||||
if (envCounter == sustainTable[sustain])
|
return;
|
||||||
{
|
}
|
||||||
return;
|
lfsr = 0x7FFF;
|
||||||
}
|
|
||||||
if (expPeriod != 1)
|
if (state == stateAttack || ++expCounter == expPeriod)
|
||||||
{
|
{
|
||||||
delay = false;
|
expCounter = 0;
|
||||||
return;
|
if (freeze)
|
||||||
}
|
return;
|
||||||
envCounter--;
|
|
||||||
break;
|
switch (state)
|
||||||
case stateRelease:
|
{
|
||||||
if (expPeriod != 1)
|
case stateAttack:
|
||||||
{
|
envCounter++;
|
||||||
delay = false;
|
if (envCounter == 0xFF)
|
||||||
return;
|
{
|
||||||
}
|
state = stateDecay;
|
||||||
envCounter--;
|
rate = adsrTable[decay];
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
case stateDecay:
|
||||||
|
if (envCounter == sustainTable[sustain])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (expPeriod != 1)
|
||||||
|
{
|
||||||
|
delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
envCounter--;
|
||||||
|
break;
|
||||||
|
case stateRelease:
|
||||||
|
if (expPeriod != 1)
|
||||||
|
{
|
||||||
|
delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
envCounter--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
envCounter &= 0xFF;
|
||||||
|
UpdateExpCounter();
|
||||||
}
|
}
|
||||||
envCounter &= 0xFF;
|
|
||||||
UpdateExpCounter();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,13 +144,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
private void UpdateExpCounter()
|
private void UpdateExpCounter()
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < 7; i++)
|
|
||||||
{
|
{
|
||||||
if (envCounter == expCounterTable[i])
|
for (uint i = 0; i < 7; i++)
|
||||||
expPeriod = expPeriodTable[i];
|
{
|
||||||
|
if (envCounter == expCounterTable[i])
|
||||||
|
expPeriod = expPeriodTable[i];
|
||||||
|
}
|
||||||
|
if (envCounter == 0)
|
||||||
|
freeze = true;
|
||||||
}
|
}
|
||||||
if (envCounter == 0)
|
|
||||||
freeze = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
@ -319,25 +325,28 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void ExecutePhase2()
|
public void ExecutePhase2()
|
||||||
{
|
{
|
||||||
if (test)
|
|
||||||
{
|
|
||||||
if (shiftRegisterReset != 0 && --shiftRegisterReset == 0)
|
|
||||||
{
|
|
||||||
ResetShiftReg();
|
|
||||||
}
|
|
||||||
pulse = 0xFFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint accNext = (accumulator + frequency) & 0xFFFFFF;
|
|
||||||
uint accBits = ~accumulator & accNext;
|
|
||||||
accumulator = accNext;
|
|
||||||
msbRising = ((accBits & 0x800000) != 0);
|
|
||||||
|
|
||||||
if ((accBits & 0x080000) != 0)
|
{
|
||||||
delay = 2;
|
if (test)
|
||||||
else if (delay != 0 && --delay == 0)
|
{
|
||||||
ClockShiftReg();
|
if (shiftRegisterReset != 0 && --shiftRegisterReset == 0)
|
||||||
|
{
|
||||||
|
ResetShiftReg();
|
||||||
|
}
|
||||||
|
pulse = 0xFFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint accNext = (accumulator + frequency) & 0xFFFFFF;
|
||||||
|
uint accBits = ~accumulator & accNext;
|
||||||
|
accumulator = accNext;
|
||||||
|
msbRising = ((accBits & 0x800000) != 0);
|
||||||
|
|
||||||
|
if ((accBits & 0x080000) != 0)
|
||||||
|
delay = 2;
|
||||||
|
else if (delay != 0 && --delay == 0)
|
||||||
|
ClockShiftReg();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,45 +354,57 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
private void ClockShiftReg()
|
private void ClockShiftReg()
|
||||||
{
|
{
|
||||||
uint bit0 = ((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1;
|
|
||||||
shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF;
|
{
|
||||||
SetNoise();
|
uint bit0 = ((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1;
|
||||||
|
shiftRegister = ((shiftRegister << 1) | bit0) & 0x7FFFFF;
|
||||||
|
SetNoise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetShiftReg()
|
private void ResetShiftReg()
|
||||||
{
|
{
|
||||||
shiftRegister = 0x7FFFFF;
|
|
||||||
shiftRegisterReset = 0;
|
{
|
||||||
SetNoise();
|
shiftRegister = 0x7FFFFF;
|
||||||
|
shiftRegisterReset = 0;
|
||||||
|
SetNoise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetNoise()
|
private void SetNoise()
|
||||||
{
|
{
|
||||||
noise =
|
|
||||||
((shiftRegister & 0x100000) >> 9) |
|
{
|
||||||
((shiftRegister & 0x040000) >> 8) |
|
noise =
|
||||||
((shiftRegister & 0x004000) >> 5) |
|
((shiftRegister & 0x100000) >> 9) |
|
||||||
((shiftRegister & 0x000800) >> 3) |
|
((shiftRegister & 0x040000) >> 8) |
|
||||||
((shiftRegister & 0x000200) >> 2) |
|
((shiftRegister & 0x004000) >> 5) |
|
||||||
((shiftRegister & 0x000020) << 1) |
|
((shiftRegister & 0x000800) >> 3) |
|
||||||
((shiftRegister & 0x000004) << 3) |
|
((shiftRegister & 0x000200) >> 2) |
|
||||||
((shiftRegister & 0x000001) << 4);
|
((shiftRegister & 0x000020) << 1) |
|
||||||
noNoiseOrNoise = noNoise | noise;
|
((shiftRegister & 0x000004) << 3) |
|
||||||
|
((shiftRegister & 0x000001) << 4);
|
||||||
|
noNoiseOrNoise = noNoise | noise;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteShiftReg()
|
private void WriteShiftReg()
|
||||||
{
|
{
|
||||||
output &=
|
|
||||||
0xBB5DA |
|
{
|
||||||
((output & 0x800) << 9) |
|
output &=
|
||||||
((output & 0x400) << 8) |
|
0xBB5DA |
|
||||||
((output & 0x200) << 5) |
|
((output & 0x800) << 9) |
|
||||||
((output & 0x100) << 3) |
|
((output & 0x400) << 8) |
|
||||||
((output & 0x040) >> 1) |
|
((output & 0x200) << 5) |
|
||||||
((output & 0x020) >> 3) |
|
((output & 0x100) << 3) |
|
||||||
((output & 0x010) >> 4);
|
((output & 0x040) >> 1) |
|
||||||
noise &= output;
|
((output & 0x020) >> 3) |
|
||||||
noNoiseOrNoise = noNoise | noise;
|
((output & 0x010) >> 4);
|
||||||
|
noise &= output;
|
||||||
|
noNoiseOrNoise = noNoise | noise;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
@ -471,20 +492,23 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public uint Output(Voice ringModSource)
|
public uint Output(Voice ringModSource)
|
||||||
{
|
{
|
||||||
if (waveform != 0)
|
|
||||||
{
|
{
|
||||||
uint index = (accumulator ^ (ringModSource.accumulator & ringMsbMask)) >> 12;
|
if (waveform != 0)
|
||||||
output = wave[index] & (noPulse | pulse) & noNoiseOrNoise;
|
{
|
||||||
if (waveform > 8)
|
uint index = (accumulator ^ (ringModSource.accumulator & ringMsbMask)) >> 12;
|
||||||
WriteShiftReg();
|
output = wave[index] & (noPulse | pulse) & noNoiseOrNoise;
|
||||||
|
if (waveform > 8)
|
||||||
|
WriteShiftReg();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (floatOutputTTL != 0 && --floatOutputTTL == 0)
|
||||||
|
output = 0x000;
|
||||||
|
}
|
||||||
|
pulse = ((accumulator >> 12) >= pulseWidth) ? (uint)0xFFF : (uint)0x000;
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (floatOutputTTL != 0 && --floatOutputTTL == 0)
|
|
||||||
output = 0x000;
|
|
||||||
}
|
|
||||||
pulse = ((accumulator >> 12) >= pulseWidth) ? (uint)0xFFF : (uint)0x000;
|
|
||||||
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)
|
||||||
|
@ -664,54 +691,57 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void ExecutePhase2()
|
public void ExecutePhase2()
|
||||||
{
|
{
|
||||||
// potentiometer values refresh every 512 cycles
|
|
||||||
if (potCounter == 0)
|
|
||||||
{
|
{
|
||||||
potCounter = 512;
|
// potentiometer values refresh every 512 cycles
|
||||||
potX = 0; //todo: implement paddles
|
if (potCounter == 0)
|
||||||
potY = 0;
|
{
|
||||||
|
potCounter = 512;
|
||||||
|
potX = ReadPotX(); //todo: implement paddles
|
||||||
|
potY = ReadPotY();
|
||||||
|
}
|
||||||
|
|
||||||
|
// process voices and envelopes
|
||||||
|
voices[0].ExecutePhase2();
|
||||||
|
voices[1].ExecutePhase2();
|
||||||
|
voices[2].ExecutePhase2();
|
||||||
|
envelopes[0].ExecutePhase2();
|
||||||
|
envelopes[1].ExecutePhase2();
|
||||||
|
envelopes[2].ExecutePhase2();
|
||||||
|
|
||||||
|
// process sync
|
||||||
|
for (uint i = 0; i < 3; i++)
|
||||||
|
voices[i].Synchronize(voices[syncNextTable[i]], voices[syncPrevTable[i]]);
|
||||||
|
|
||||||
|
// get output
|
||||||
|
voiceOutput[0] = voices[0].Output(voices[2]);
|
||||||
|
voiceOutput[1] = voices[1].Output(voices[0]);
|
||||||
|
voiceOutput[2] = voices[2].Output(voices[1]);
|
||||||
|
envelopeOutput[0] = envelopes[0].Level;
|
||||||
|
envelopeOutput[1] = envelopes[1].Level;
|
||||||
|
envelopeOutput[2] = envelopes[2].Level;
|
||||||
|
|
||||||
|
// process output
|
||||||
|
if (bufferCounter == 0)
|
||||||
|
{
|
||||||
|
uint mixer;
|
||||||
|
short sample;
|
||||||
|
bufferCounter = bufferFrequency;
|
||||||
|
|
||||||
|
// mix each channel (20 bits)
|
||||||
|
mixer = ((voiceOutput[0] * envelopeOutput[0]) >> 7);
|
||||||
|
mixer += ((voiceOutput[1] * envelopeOutput[1]) >> 7);
|
||||||
|
mixer += ((voiceOutput[2] * envelopeOutput[2]) >> 7);
|
||||||
|
mixer = (mixer * volume) >> 4;
|
||||||
|
|
||||||
|
sample = (short)mixer;
|
||||||
|
buffer[bufferIndex++] = sample;
|
||||||
|
buffer[bufferIndex++] = sample;
|
||||||
|
if (bufferIndex == bufferLength)
|
||||||
|
bufferIndex = 0;
|
||||||
|
}
|
||||||
|
bufferCounter--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process voices and envelopes
|
|
||||||
voices[0].ExecutePhase2();
|
|
||||||
voices[1].ExecutePhase2();
|
|
||||||
voices[2].ExecutePhase2();
|
|
||||||
envelopes[0].ExecutePhase2();
|
|
||||||
envelopes[1].ExecutePhase2();
|
|
||||||
envelopes[2].ExecutePhase2();
|
|
||||||
|
|
||||||
// process sync
|
|
||||||
for (uint i = 0; i < 3; i++)
|
|
||||||
voices[i].Synchronize(voices[syncNextTable[i]], voices[syncPrevTable[i]]);
|
|
||||||
|
|
||||||
// get output
|
|
||||||
voiceOutput[0] = voices[0].Output(voices[2]);
|
|
||||||
voiceOutput[1] = voices[1].Output(voices[0]);
|
|
||||||
voiceOutput[2] = voices[2].Output(voices[1]);
|
|
||||||
envelopeOutput[0] = envelopes[0].Level;
|
|
||||||
envelopeOutput[1] = envelopes[1].Level;
|
|
||||||
envelopeOutput[2] = envelopes[2].Level;
|
|
||||||
|
|
||||||
// process output
|
|
||||||
if (bufferCounter == 0)
|
|
||||||
{
|
|
||||||
uint mixer;
|
|
||||||
short sample;
|
|
||||||
bufferCounter = bufferFrequency;
|
|
||||||
|
|
||||||
// mix each channel (20 bits)
|
|
||||||
mixer = ((voiceOutput[0] * envelopeOutput[0]) >> 7);
|
|
||||||
mixer += ((voiceOutput[1] * envelopeOutput[1]) >> 7);
|
|
||||||
mixer += ((voiceOutput[2] * envelopeOutput[2]) >> 7);
|
|
||||||
mixer = (mixer * volume) >> 4;
|
|
||||||
|
|
||||||
sample = (short)mixer;
|
|
||||||
buffer[bufferIndex++] = sample;
|
|
||||||
buffer[bufferIndex++] = sample;
|
|
||||||
if (bufferIndex == bufferLength)
|
|
||||||
bufferIndex = 0;
|
|
||||||
}
|
|
||||||
bufferCounter--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue