C64 - reorg some core code

This commit is contained in:
adelikat 2014-12-18 18:39:55 +00:00
parent aaf3d0a559
commit b416645768
10 changed files with 336 additions and 283 deletions

View File

@ -109,11 +109,25 @@
<DependentUpon>TI83.cs</DependentUpon>
</Compile>
<Compile Include="Calculator\TI83LinkPort.cs" />
<Compile Include="Computers\Commodore64\C64.Core.cs" />
<Compile Include="Computers\Commodore64\C64.cs" />
<Compile Include="Computers\Commodore64\C64.IStatable.cs" />
<Compile Include="Computers\Commodore64\C64.IDebuggable.cs">
<DependentUpon>C64.cs</DependentUpon>
</Compile>
<Compile Include="Computers\Commodore64\C64.IDriveLight.cs">
<DependentUpon>C64.cs</DependentUpon>
</Compile>
<Compile Include="Computers\Commodore64\C64.IInputPollable.cs">
<DependentUpon>C64.cs</DependentUpon>
</Compile>
<Compile Include="Computers\Commodore64\C64.IMemoryDomains.cs">
<DependentUpon>C64.cs</DependentUpon>
</Compile>
<Compile Include="Computers\Commodore64\C64.IStatable.cs">
<DependentUpon>C64.cs</DependentUpon>
</Compile>
<Compile Include="Computers\Commodore64\C64.Motherboard.cs" />
<Compile Include="Computers\Commodore64\C64.MotherboardInterface.cs" />
<Compile Include="Computers\Commodore64\C64Util.cs" />
<Compile Include="Computers\Commodore64\Cartridge\Mapper0000.cs" />
<Compile Include="Computers\Commodore64\C64.Input.cs" />
<Compile Include="Computers\Commodore64\Cartridge\Mapper0005.cs" />

View File

@ -1,178 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Computers.Commodore64.MOS;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
public enum Region
{
NTSC,
PAL
}
sealed public partial class C64 : IEmulator, IDebuggable
{
private Motherboard board;
private bool loadPrg;
private byte[] GetFirmware(string name, int length)
{
byte[] result = CoreComm.CoreFileProvider.GetFirmware("C64", name, true);
if (result.Length != length)
throw new MissingFirmwareException(string.Format("Firmware {0} was {1} bytes, should be {2} bytes", name, result.Length, length));
return result;
}
private void Init(Region initRegion)
{
board = new Motherboard(this, initRegion);
InitRoms();
board.Init();
InitMedia();
// configure video
CoreComm.VsyncDen = board.vic.CyclesPerFrame;
CoreComm.VsyncNum = board.vic.CyclesPerSecond;
}
private void InitMedia()
{
switch (inputFileInfo.Extension.ToUpper())
{
case @".CRT":
Cart cart = Cart.Load(inputFileInfo.Data);
if (cart != null)
{
board.cartPort.Connect(cart);
}
break;
case @".PRG":
if (inputFileInfo.Data.Length > 2)
loadPrg = true;
break;
}
}
private void InitRoms()
{
byte[] basicRom = GetFirmware("Basic", 0x2000);
byte[] charRom = GetFirmware("Chargen", 0x1000);
byte[] kernalRom = GetFirmware("Kernal", 0x2000);
board.basicRom = new Chip23XX(Chip23XXmodel.Chip2364, basicRom);
board.kernalRom = new Chip23XX(Chip23XXmodel.Chip2364, kernalRom);
board.charRom = new Chip23XX(Chip23XXmodel.Chip2332, charRom);
}
// ------------------------------------
public bool DriveLED
{
get
{
//return (disk.PeekVia1(0x00) & 0x08) != 0;
return false;
}
}
public void HardReset()
{
board.HardReset();
//disk.HardReset();
}
public IDictionary<string, int> GetCpuFlagsAndRegisters()
{
return new Dictionary<string, int>
{
{ "A", board.cpu.A },
{ "X", board.cpu.X },
{ "Y", board.cpu.Y },
{ "S", board.cpu.S },
{ "PC", board.cpu.PC },
{ "Flag C", board.cpu.FlagC ? 1 : 0 },
{ "Flag Z", board.cpu.FlagZ ? 1 : 0 },
{ "Flag I", board.cpu.FlagI ? 1 : 0 },
{ "Flag D", board.cpu.FlagD ? 1 : 0 },
{ "Flag B", board.cpu.FlagB ? 1 : 0 },
{ "Flag V", board.cpu.FlagV ? 1 : 0 },
{ "Flag N", board.cpu.FlagN ? 1 : 0 },
{ "Flag T", board.cpu.FlagT ? 1 : 0 }
};
}
public void SetCpuRegister(string register, int value)
{
switch (register)
{
default:
throw new InvalidOperationException();
case "A":
board.cpu.A = (byte)value;
break;
case "X":
board.cpu.X = (byte)value;
break;
case "Y":
board.cpu.Y = (byte)value;
break;
case "S":
board.cpu.S = (byte)value;
break;
case "PC":
board.cpu.PC = (ushort)value;
break;
}
}
[FeatureNotImplemented]
public void Step(StepType type) { throw new NotImplementedException(); }
public ITracer Tracer
{
[FeatureNotImplemented]
get { throw new NotImplementedException(); }
}
public IMemoryCallbackSystem MemoryCallbacks
{
[FeatureNotImplemented]
get { throw new NotImplementedException(); }
}
}
static public class C64Util
{
static public string ToBinary(int n, int charsmin)
{
string result = "";
while (n > 0 || charsmin > 0)
{
result = (((n & 0x1) != 0) ? "1" : "0") + result;
n >>= 1;
if (charsmin > 0)
charsmin--;
}
return result;
}
static public string ToHex(int n, int charsmin)
{
string result = "";
while (n > 0 || charsmin > 0)
{
result = "0123456789ABCDEF".Substring((n & 0xF), 1) + result;
n >>= 4;
if (charsmin > 0)
charsmin--;
}
return result;
}
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
public partial class C64 : IDebuggable
{
public IDictionary<string, int> GetCpuFlagsAndRegisters()
{
return new Dictionary<string, int>
{
{ "A", board.cpu.A },
{ "X", board.cpu.X },
{ "Y", board.cpu.Y },
{ "S", board.cpu.S },
{ "PC", board.cpu.PC },
{ "Flag C", board.cpu.FlagC ? 1 : 0 },
{ "Flag Z", board.cpu.FlagZ ? 1 : 0 },
{ "Flag I", board.cpu.FlagI ? 1 : 0 },
{ "Flag D", board.cpu.FlagD ? 1 : 0 },
{ "Flag B", board.cpu.FlagB ? 1 : 0 },
{ "Flag V", board.cpu.FlagV ? 1 : 0 },
{ "Flag N", board.cpu.FlagN ? 1 : 0 },
{ "Flag T", board.cpu.FlagT ? 1 : 0 }
};
}
public void SetCpuRegister(string register, int value)
{
switch (register)
{
default:
throw new InvalidOperationException();
case "A":
board.cpu.A = (byte)value;
break;
case "X":
board.cpu.X = (byte)value;
break;
case "Y":
board.cpu.Y = (byte)value;
break;
case "S":
board.cpu.S = (byte)value;
break;
case "PC":
board.cpu.PC = (ushort)value;
break;
}
}
public ITracer Tracer
{
[FeatureNotImplemented]
get { throw new NotImplementedException(); }
}
public IMemoryCallbackSystem MemoryCallbacks
{
[FeatureNotImplemented]
get { throw new NotImplementedException(); }
}
[FeatureNotImplemented]
public void Step(StepType type) { throw new NotImplementedException(); }
}
}

View File

@ -0,0 +1,19 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
public partial class C64 : IDriveLight
{
public bool DriveLightEnabled { get { return true; } }
public bool DriveLightOn { get; private set; }
public bool DriveLED
{
get
{
//return (disk.PeekVia1(0x00) & 0x08) != 0;
return false;
}
}
}
}

View File

@ -0,0 +1,23 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
public partial class C64 : IInputPollable
{
public bool IsLagFrame
{
get { return _islag; }
}
public int LagCount
{
get { return _lagcount; }
set { _lagcount = value; }
}
public IInputCallbackSystem InputCallbacks { get; private set; }
private bool _islag = true;
private int _lagcount = 0;
}
}

View File

@ -0,0 +1,33 @@
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
public partial class C64 : IMemoryDomains
{
public MemoryDomainList MemoryDomains
{
get { return memoryDomains; }
}
private MemoryDomainList memoryDomains;
private void SetupMemoryDomains()
{
// chips must be initialized before this code runs!
var domains = new List<MemoryDomain>(1);
domains.Add(new MemoryDomain("System Bus", 0x10000, MemoryDomain.Endian.Little, board.cpu.Peek, board.cpu.Poke));
domains.Add(new MemoryDomain("RAM", 0x10000, MemoryDomain.Endian.Little, board.ram.Peek, board.ram.Poke));
domains.Add(new MemoryDomain("CIA0", 0x10, MemoryDomain.Endian.Little, board.cia0.Peek, board.cia0.Poke));
domains.Add(new MemoryDomain("CIA1", 0x10, MemoryDomain.Endian.Little, board.cia1.Peek, board.cia1.Poke));
domains.Add(new MemoryDomain("VIC", 0x40, MemoryDomain.Endian.Little, board.vic.Peek, board.vic.Poke));
domains.Add(new MemoryDomain("SID", 0x20, MemoryDomain.Endian.Little, board.sid.Peek, board.sid.Poke));
//domains.Add(new MemoryDomain("1541 Bus", 0x10000, MemoryDomain.Endian.Little, new Func<int, byte>(disk.Peek), new Action<int, byte>(disk.Poke)));
//domains.Add(new MemoryDomain("1541 VIA0", 0x10, MemoryDomain.Endian.Little, new Func<int, byte>(disk.PeekVia0), new Action<int, byte>(disk.PokeVia0)));
//domains.Add(new MemoryDomain("1541 VIA1", 0x10, MemoryDomain.Endian.Little, new Func<int, byte>(disk.PeekVia1), new Action<int, byte>(disk.PokeVia1)));
//domains.Add(new MemoryDomain("1541 RAM", 0x1000, MemoryDomain.Endian.Little, new Func<int, byte>(disk.PeekRam), new Action<int, byte>(disk.PokeRam)));
memoryDomains = new MemoryDomainList(domains);
}
}
}

View File

@ -7,6 +7,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
sealed public partial class C64 : IStatable
{
public bool BinarySaveStatesPreferred { get { return false; } }
public void LoadStateBinary(BinaryReader br)
{
SyncState(new Serializer(br));
@ -27,7 +29,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
SyncState(new Serializer(writer));
}
void SyncState(Serializer ser)
public byte[] SaveStateBinary()
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.BeginSection("core");
board.SyncState(ser);

View File

@ -7,6 +7,13 @@ using BizHawk.Emulation.Cores.Computers.Commodore64.MOS;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
// TODO: use the EMulation.Common Region enum
public enum Region
{
NTSC,
PAL
}
[CoreAttributes(
"C64Hawk",
"SaxxonPIke",
@ -14,11 +21,25 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
isReleased: false
)]
[ServiceNotApplicable(typeof(ISettable<,>))]
sealed public partial class C64 : IEmulator, IMemoryDomains, IStatable, IInputPollable, IDriveLight
sealed public partial class C64 : IEmulator, IMemoryDomains, IStatable, IInputPollable, IDriveLight, IDebuggable
{
// framework
public C64(CoreComm comm, GameInfo game, byte[] rom, string romextension)
{
ServiceProvider = new BasicServiceProvider(this);
InputCallbacks = new InputCallbackSystem();
inputFileInfo = new InputFileInfo();
inputFileInfo.Data = rom;
inputFileInfo.Extension = romextension;
CoreComm = comm;
Init(Region.PAL);
cyclesPerFrame = board.vic.CyclesPerFrame;
SetupMemoryDomains();
HardReset();
}
// internal variables
private bool _islag = true;
private int _lagcount = 0;
private int _frame = 0;
private int cyclesPerFrame;
private InputFileInfo inputFileInfo;
@ -32,15 +53,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public string BoardName { get { return null; } }
// memory domains
private MemoryDomainList memoryDomains;
public MemoryDomainList MemoryDomains { get { return memoryDomains; } }
// running state
public bool DeterministicEmulation { get { return true; } set { ; } }
public int Frame { get { return _frame; } set { _frame = value; } }
public bool IsLagFrame { get { return _islag; } }
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
public void ResetCounters()
{
_frame = 0;
@ -74,23 +89,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
}
};
// framework
public C64(CoreComm comm, GameInfo game, byte[] rom, string romextension)
{
ServiceProvider = new BasicServiceProvider(this);
inputFileInfo = new InputFileInfo();
inputFileInfo.Data = rom;
inputFileInfo.Extension = romextension;
CoreComm = comm;
Init(Region.PAL);
cyclesPerFrame = board.vic.CyclesPerFrame;
SetupMemoryDomains();
HardReset();
}
public bool DriveLightEnabled { get { return true; } }
public bool DriveLightOn { get; private set; }
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public void Dispose()
@ -180,35 +178,64 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
throw new FileNotFoundException();
}
public byte[] SaveStateBinary()
private Motherboard board;
private bool loadPrg;
private byte[] GetFirmware(string name, int length)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
byte[] result = CoreComm.CoreFileProvider.GetFirmware("C64", name, true);
if (result.Length != length)
throw new MissingFirmwareException(string.Format("Firmware {0} was {1} bytes, should be {2} bytes", name, result.Length, length));
return result;
}
public bool BinarySaveStatesPreferred { get { return false; } }
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } }
private void SetupMemoryDomains()
private void Init(Region initRegion)
{
// chips must be initialized before this code runs!
var domains = new List<MemoryDomain>(1);
domains.Add(new MemoryDomain("System Bus", 0x10000, MemoryDomain.Endian.Little, board.cpu.Peek, board.cpu.Poke));
domains.Add(new MemoryDomain("RAM", 0x10000, MemoryDomain.Endian.Little, board.ram.Peek, board.ram.Poke));
domains.Add(new MemoryDomain("CIA0", 0x10, MemoryDomain.Endian.Little, board.cia0.Peek, board.cia0.Poke));
domains.Add(new MemoryDomain("CIA1", 0x10, MemoryDomain.Endian.Little, board.cia1.Peek, board.cia1.Poke));
domains.Add(new MemoryDomain("VIC", 0x40, MemoryDomain.Endian.Little, board.vic.Peek, board.vic.Poke));
domains.Add(new MemoryDomain("SID", 0x20, MemoryDomain.Endian.Little, board.sid.Peek, board.sid.Poke));
//domains.Add(new MemoryDomain("1541 Bus", 0x10000, MemoryDomain.Endian.Little, new Func<int, byte>(disk.Peek), new Action<int, byte>(disk.Poke)));
//domains.Add(new MemoryDomain("1541 VIA0", 0x10, MemoryDomain.Endian.Little, new Func<int, byte>(disk.PeekVia0), new Action<int, byte>(disk.PokeVia0)));
//domains.Add(new MemoryDomain("1541 VIA1", 0x10, MemoryDomain.Endian.Little, new Func<int, byte>(disk.PeekVia1), new Action<int, byte>(disk.PokeVia1)));
//domains.Add(new MemoryDomain("1541 RAM", 0x1000, MemoryDomain.Endian.Little, new Func<int, byte>(disk.PeekRam), new Action<int, byte>(disk.PokeRam)));
memoryDomains = new MemoryDomainList(domains);
board = new Motherboard(this, initRegion);
InitRoms();
board.Init();
InitMedia();
// configure video
CoreComm.VsyncDen = board.vic.CyclesPerFrame;
CoreComm.VsyncNum = board.vic.CyclesPerSecond;
}
private void InitMedia()
{
switch (inputFileInfo.Extension.ToUpper())
{
case @".CRT":
Cart cart = Cart.Load(inputFileInfo.Data);
if (cart != null)
{
board.cartPort.Connect(cart);
}
break;
case @".PRG":
if (inputFileInfo.Data.Length > 2)
loadPrg = true;
break;
}
}
private void InitRoms()
{
byte[] basicRom = GetFirmware("Basic", 0x2000);
byte[] charRom = GetFirmware("Chargen", 0x1000);
byte[] kernalRom = GetFirmware("Kernal", 0x2000);
board.basicRom = new Chip23XX(Chip23XXmodel.Chip2364, basicRom);
board.kernalRom = new Chip23XX(Chip23XXmodel.Chip2364, kernalRom);
board.charRom = new Chip23XX(Chip23XXmodel.Chip2332, charRom);
}
// ------------------------------------
public void HardReset()
{
board.HardReset();
//disk.HardReset();
}
}
}

View File

@ -0,0 +1,35 @@
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
public static class C64Util
{
static public string ToBinary(int n, int charsmin)
{
string result = "";
while (n > 0 || charsmin > 0)
{
result = (((n & 0x1) != 0) ? "1" : "0") + result;
n >>= 1;
if (charsmin > 0)
charsmin--;
}
return result;
}
static public string ToHex(int n, int charsmin)
{
string result = "";
while (n > 0 || charsmin > 0)
{
result = "0123456789ABCDEF".Substring((n & 0xF), 1) + result;
n >>= 4;
if (charsmin > 0)
charsmin--;
}
return result;
}
}
}

View File

@ -7,9 +7,9 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
static class SaveState
internal static class SaveState
{
static private Encoding encoding = Encoding.Unicode;
static private Encoding encoding = Encoding.Unicode;
static public void SyncObject(Serializer ser, object obj)
{
@ -70,13 +70,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
ser.Sync(member.Name, ref refBool);
currentValue = refBool;
break;
case "Boolean[]":
{
bool[] tmp = (bool[])currentValue;
case "Boolean[]":
{
bool[] tmp = (bool[])currentValue;
ser.Sync(member.Name, ref tmp, false);
currentValue = tmp;
}
break;
}
break;
case "Byte":
refByte = (Byte)currentValue;
ser.Sync(member.Name, ref refByte);
@ -92,8 +92,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
ser.Sync(member.Name, ref refByteBuffer);
currentValue = refByteBuffer;
break;
case "Func`1":
break;
case "Func`1":
break;
case "Int16":
refInt16 = (Int16)currentValue;
ser.Sync(member.Name, ref refInt16);
@ -137,14 +137,14 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
ser.Sync(member.Name, ref refSByte);
currentValue = refSByte;
break;
case "String":
{
var refString = (String)currentValue;
var refVal = new ByteBuffer(encoding.GetBytes(refString));
ser.Sync(member.Name, ref refVal);
currentValue = encoding.GetString(refVal.Arr);
}
break;
case "String":
{
var refString = (String)currentValue;
var refVal = new ByteBuffer(encoding.GetBytes(refString));
ser.Sync(member.Name, ref refVal);
currentValue = encoding.GetString(refVal.Arr);
}
break;
case "UInt16":
refUInt16 = (UInt16)currentValue;
ser.Sync(member.Name, ref refUInt16);
@ -155,40 +155,40 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
ser.Sync(member.Name, ref refUInt32);
currentValue = refUInt32;
break;
default:
{
Type t = currentValue.GetType();
if (t.IsEnum)
{
refInt32 = (Int32)currentValue;
ser.Sync(member.Name, ref refInt32);
currentValue = refInt32;
}
else if (t.IsValueType)
{
fail = true;
}
else if (t.IsClass)
{
fail = true;
foreach (var method in t.GetMethods())
{
if (method.Name == "SyncState")
{
ser.BeginSection(fieldInfo.Name);
method.Invoke(currentValue, new object[] {(Serializer)ser});
ser.EndSection();
fail = false;
break;
}
}
}
else
{
fail = true;
}
}
break;
default:
{
Type t = currentValue.GetType();
if (t.IsEnum)
{
refInt32 = (Int32)currentValue;
ser.Sync(member.Name, ref refInt32);
currentValue = refInt32;
}
else if (t.IsValueType)
{
fail = true;
}
else if (t.IsClass)
{
fail = true;
foreach (var method in t.GetMethods())
{
if (method.Name == "SyncState")
{
ser.BeginSection(fieldInfo.Name);
method.Invoke(currentValue, new object[] { (Serializer)ser });
ser.EndSection();
fail = false;
break;
}
}
}
else
{
fail = true;
}
}
break;
}
}