c64- clean tabs, document some regs, VIC screen memory fetch added
This commit is contained in:
parent
747c3db7cb
commit
97bdd9be9c
|
@ -9,19 +9,19 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
public partial class C64 : IEmulator
|
public partial class C64 : IEmulator
|
||||||
{
|
{
|
||||||
// source
|
// source
|
||||||
public Cartridge cart;
|
public Cartridge cart;
|
||||||
public bool cartInserted;
|
public bool cartInserted;
|
||||||
public byte[] inputFile;
|
public byte[] inputFile;
|
||||||
|
|
||||||
// chipset
|
// chipset
|
||||||
public Cia cia1;
|
public Cia cia1;
|
||||||
public Cia cia2;
|
public Cia cia2;
|
||||||
public MOS6502X cpu;
|
public MOS6502X cpu;
|
||||||
public Memory mem;
|
public Memory mem;
|
||||||
public Sid sid;
|
public Sid sid;
|
||||||
public VicII vic;
|
public VicII vic;
|
||||||
public VicSignals vicSignal;
|
public VicSignals vicSignal;
|
||||||
|
|
||||||
private void HardReset()
|
private void HardReset()
|
||||||
{
|
{
|
||||||
|
@ -30,50 +30,53 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
cpu.WriteMemory = WriteMemory;
|
cpu.WriteMemory = WriteMemory;
|
||||||
cpu.DummyReadMemory = PeekMemory;
|
cpu.DummyReadMemory = PeekMemory;
|
||||||
|
|
||||||
// initialize cia timers
|
// initialize cia timers
|
||||||
cia1 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort);
|
cia1 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort);
|
||||||
cia2 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort);
|
cia2 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort);
|
||||||
|
|
||||||
// initialize vic
|
// initialize vic
|
||||||
vicSignal = new VicSignals();
|
vicSignal = new VicSignals();
|
||||||
vic = new VicII(vicSignal, VicIIMode.NTSC);
|
vic = new VicII(vicSignal, VicIIMode.NTSC);
|
||||||
|
|
||||||
// initialize sid
|
// initialize sid
|
||||||
sid = new Sid();
|
sid = new Sid();
|
||||||
|
|
||||||
// initialize memory (this must be done AFTER all other chips are initialized)
|
// initialize memory (this must be done AFTER all other chips are initialized)
|
||||||
string romPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "C64Kernal");
|
string romPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "C64Kernal");
|
||||||
mem = new Memory(romPath, vic, sid, cia1, cia2);
|
mem = new Memory(romPath, vic, sid, cia1, cia2);
|
||||||
cia2.ReadPortA = mem.CIA2ReadPortA;
|
vic.mem = mem;
|
||||||
cia2.ReadPortB = mem.CIA2ReadPortB;
|
|
||||||
cia2.WritePortA = mem.CIA2WritePortA;
|
|
||||||
cia2.WritePortB = mem.CIA2WritePortB;
|
|
||||||
|
|
||||||
// initialize media
|
// initialize ports
|
||||||
Cartridge cart = new Cartridge(inputFile);
|
cia2.ReadPortA = mem.CIA2ReadPortA;
|
||||||
if (cart.valid)
|
cia2.ReadPortB = mem.CIA2ReadPortB;
|
||||||
{
|
cia2.WritePortA = mem.CIA2WritePortA;
|
||||||
mem.ApplyCartridge(cart);
|
cia2.WritePortB = mem.CIA2WritePortB;
|
||||||
}
|
|
||||||
|
|
||||||
// initialize cpu (hard reset vector)
|
// initialize media
|
||||||
cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8));
|
Cartridge cart = new Cartridge(inputFile);
|
||||||
|
if (cart.valid)
|
||||||
|
{
|
||||||
|
mem.ApplyCartridge(cart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize cpu (hard reset vector)
|
||||||
|
cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte PeekMemory(ushort addr)
|
public byte PeekMemory(ushort addr)
|
||||||
{
|
{
|
||||||
return mem.Peek(addr);
|
return mem.Peek(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte PeekMemoryInt(int addr)
|
public byte PeekMemoryInt(int addr)
|
||||||
{
|
{
|
||||||
return mem.Peek((ushort)(addr & 0xFFFF));
|
return mem.Peek((ushort)(addr & 0xFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PokeMemoryInt(int addr, byte val)
|
public void PokeMemoryInt(int addr, byte val)
|
||||||
{
|
{
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte ReadMemory(ushort addr)
|
public byte ReadMemory(ushort addr)
|
||||||
{
|
{
|
||||||
|
@ -82,7 +85,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
|
|
||||||
public void WriteMemory(ushort addr, byte value)
|
public void WriteMemory(ushort addr, byte value)
|
||||||
{
|
{
|
||||||
mem.Write(addr, value);
|
mem.Write(addr, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
public C64(GameInfo game, byte[] rom, string romextension)
|
public C64(GameInfo game, byte[] rom, string romextension)
|
||||||
{
|
{
|
||||||
inputFile = rom;
|
inputFile = rom;
|
||||||
SetupMemoryDomains();
|
SetupMemoryDomains();
|
||||||
CoreOutputComm = new CoreOutputComm();
|
CoreOutputComm = new CoreOutputComm();
|
||||||
CoreInputComm = new CoreInputComm();
|
CoreInputComm = new CoreInputComm();
|
||||||
HardReset();
|
HardReset();
|
||||||
videoProvider = new MyVideoProvider(vic);
|
videoProvider = new MyVideoProvider(vic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SystemId { get { return "C64"; } }
|
public string SystemId { get { return "C64"; } }
|
||||||
|
@ -88,23 +88,23 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
_frame++;
|
_frame++;
|
||||||
_islag = true;
|
_islag = true;
|
||||||
|
|
||||||
int cyclesPerSecond = (14318181 / 14 / 60);
|
int cyclesPerSecond = (14318181 / 14 / 60);
|
||||||
|
|
||||||
for (int i = 0; i < cyclesPerSecond; i++)
|
for (int i = 0; i < cyclesPerSecond; i++)
|
||||||
{
|
{
|
||||||
if (vicSignal.Interrupt || cia1.interrupt || cia2.interrupt)
|
if (vicSignal.Interrupt || cia1.interrupt || cia2.interrupt)
|
||||||
{
|
{
|
||||||
cpu.IRQ = true;
|
cpu.IRQ = true;
|
||||||
}
|
}
|
||||||
if (vicSignal.AllowCpu)
|
if (vicSignal.AllowCpu)
|
||||||
{
|
{
|
||||||
cpu.ExecuteOne();
|
cpu.ExecuteOne();
|
||||||
}
|
}
|
||||||
vic.PerformCycle();
|
vic.PerformCycle();
|
||||||
sid.PerformCycle();
|
sid.PerformCycle();
|
||||||
cia1.PerformCycle();
|
cia1.PerformCycle();
|
||||||
cia2.PerformCycle();
|
cia2.PerformCycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_islag)
|
if (_islag)
|
||||||
{
|
{
|
||||||
|
@ -129,20 +129,20 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
VicII vic;
|
VicII vic;
|
||||||
public MyVideoProvider(VicII vic)
|
public MyVideoProvider(VicII vic)
|
||||||
{
|
{
|
||||||
this.vic = vic;
|
this.vic = vic;
|
||||||
|
|
||||||
buffer = new int[vic.visibleWidth * vic.visibleHeight];
|
buffer = new int[vic.visibleWidth * vic.visibleHeight];
|
||||||
top = 0;
|
top = 0;
|
||||||
bottom = vic.visibleHeight - 1;
|
bottom = vic.visibleHeight - 1;
|
||||||
left = 0;
|
left = 0;
|
||||||
right = vic.visibleWidth - 1;
|
right = vic.visibleWidth - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] buffer;
|
int[] buffer;
|
||||||
|
|
||||||
public void FillFrameBuffer()
|
public void FillFrameBuffer()
|
||||||
{
|
{
|
||||||
Array.Copy(vic.buffer, buffer, buffer.Length);
|
Array.Copy(vic.buffer, buffer, buffer.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] GetVideoBuffer()
|
public int[] GetVideoBuffer()
|
||||||
|
@ -159,7 +159,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
private void SetupMemoryDomains()
|
private void SetupMemoryDomains()
|
||||||
{
|
{
|
||||||
var domains = new List<MemoryDomain>(1);
|
var domains = new List<MemoryDomain>(1);
|
||||||
domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func<int, byte>(PeekMemoryInt), new Action<int,byte>(PokeMemoryInt))); //TODO
|
domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func<int, byte>(PeekMemoryInt), new Action<int,byte>(PokeMemoryInt))); //TODO
|
||||||
memoryDomains = domains.AsReadOnly();
|
memoryDomains = domains.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,135 +6,135 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64
|
namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
public class CartridgeChip
|
public class CartridgeChip
|
||||||
{
|
{
|
||||||
public int address;
|
public int address;
|
||||||
public int bank;
|
public int bank;
|
||||||
public byte[] data;
|
public byte[] data;
|
||||||
public ushort romMask;
|
public ushort romMask;
|
||||||
public int type;
|
public int type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Cartridge
|
public class Cartridge
|
||||||
{
|
{
|
||||||
public List<CartridgeChip> chips;
|
public List<CartridgeChip> chips;
|
||||||
public bool exRomPin;
|
public bool exRomPin;
|
||||||
public bool gamePin;
|
public bool gamePin;
|
||||||
public int type;
|
public int type;
|
||||||
public bool valid;
|
public bool valid;
|
||||||
public int version;
|
public int version;
|
||||||
|
|
||||||
public Cartridge(byte[] rom)
|
public Cartridge(byte[] rom)
|
||||||
{
|
{
|
||||||
chips = new List<CartridgeChip>();
|
chips = new List<CartridgeChip>();
|
||||||
|
|
||||||
if (rom.Length >= 0x50)
|
if (rom.Length >= 0x50)
|
||||||
{
|
{
|
||||||
MemoryStream source = new MemoryStream(rom);
|
MemoryStream source = new MemoryStream(rom);
|
||||||
BinaryReader reader = new BinaryReader(source);
|
BinaryReader reader = new BinaryReader(source);
|
||||||
string idString;
|
string idString;
|
||||||
|
|
||||||
// note: cartridge files store values big-endian.
|
// note: cartridge files store values big-endian.
|
||||||
|
|
||||||
idString = new string(reader.ReadChars(16));
|
idString = new string(reader.ReadChars(16));
|
||||||
if (idString == "C64 CARTRIDGE ")
|
if (idString == "C64 CARTRIDGE ")
|
||||||
{
|
{
|
||||||
int headerLength = 0;
|
int headerLength = 0;
|
||||||
headerLength = reader.ReadByte();
|
headerLength = reader.ReadByte();
|
||||||
headerLength <<= 8;
|
headerLength <<= 8;
|
||||||
headerLength |= reader.ReadByte();
|
headerLength |= reader.ReadByte();
|
||||||
headerLength <<= 8;
|
headerLength <<= 8;
|
||||||
headerLength |= reader.ReadByte();
|
headerLength |= reader.ReadByte();
|
||||||
headerLength <<= 8;
|
headerLength <<= 8;
|
||||||
headerLength |= reader.ReadByte();
|
headerLength |= reader.ReadByte();
|
||||||
|
|
||||||
version = reader.ReadByte();
|
version = reader.ReadByte();
|
||||||
version <<= 8;
|
version <<= 8;
|
||||||
version |= reader.ReadByte();
|
version |= reader.ReadByte();
|
||||||
|
|
||||||
type = reader.ReadByte();
|
type = reader.ReadByte();
|
||||||
type <<= 8;
|
type <<= 8;
|
||||||
type |= reader.ReadByte();
|
type |= reader.ReadByte();
|
||||||
|
|
||||||
exRomPin = (reader.ReadByte() == 1);
|
exRomPin = (reader.ReadByte() == 1);
|
||||||
gamePin = (reader.ReadByte() == 1);
|
gamePin = (reader.ReadByte() == 1);
|
||||||
|
|
||||||
reader.ReadBytes(6); // reserved
|
reader.ReadBytes(6); // reserved
|
||||||
reader.ReadBytes(32); // name
|
reader.ReadBytes(32); // name
|
||||||
|
|
||||||
// skip the rest, don't need this info
|
// skip the rest, don't need this info
|
||||||
if (headerLength > 0x40)
|
if (headerLength > 0x40)
|
||||||
{
|
{
|
||||||
reader.ReadBytes(headerLength - 0x40);
|
reader.ReadBytes(headerLength - 0x40);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (source.Position < rom.Length)
|
while (source.Position < rom.Length)
|
||||||
{
|
{
|
||||||
string chipID = new string(reader.ReadChars(4));
|
string chipID = new string(reader.ReadChars(4));
|
||||||
|
|
||||||
if (chipID == "CHIP")
|
if (chipID == "CHIP")
|
||||||
{
|
{
|
||||||
CartridgeChip chip = new CartridgeChip();
|
CartridgeChip chip = new CartridgeChip();
|
||||||
|
|
||||||
int packetLength;
|
int packetLength;
|
||||||
packetLength = reader.ReadByte();
|
packetLength = reader.ReadByte();
|
||||||
packetLength <<= 8;
|
packetLength <<= 8;
|
||||||
packetLength |= reader.ReadByte();
|
packetLength |= reader.ReadByte();
|
||||||
packetLength <<= 8;
|
packetLength <<= 8;
|
||||||
packetLength |= reader.ReadByte();
|
packetLength |= reader.ReadByte();
|
||||||
packetLength <<= 8;
|
packetLength <<= 8;
|
||||||
packetLength |= reader.ReadByte();
|
packetLength |= reader.ReadByte();
|
||||||
packetLength -= 16;
|
packetLength -= 16;
|
||||||
|
|
||||||
chip.type = reader.ReadByte();
|
chip.type = reader.ReadByte();
|
||||||
chip.type <<= 8;
|
chip.type <<= 8;
|
||||||
chip.type |= reader.ReadByte();
|
chip.type |= reader.ReadByte();
|
||||||
|
|
||||||
chip.bank = reader.ReadByte();
|
chip.bank = reader.ReadByte();
|
||||||
chip.bank <<= 8;
|
chip.bank <<= 8;
|
||||||
chip.bank |= reader.ReadByte();
|
chip.bank |= reader.ReadByte();
|
||||||
|
|
||||||
chip.address = reader.ReadByte();
|
chip.address = reader.ReadByte();
|
||||||
chip.address <<= 8;
|
chip.address <<= 8;
|
||||||
chip.address |= reader.ReadByte();
|
chip.address |= reader.ReadByte();
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
size = reader.ReadByte();
|
size = reader.ReadByte();
|
||||||
size <<= 8;
|
size <<= 8;
|
||||||
size |= reader.ReadByte();
|
size |= reader.ReadByte();
|
||||||
|
|
||||||
chip.data = reader.ReadBytes(size);
|
chip.data = reader.ReadBytes(size);
|
||||||
chip.romMask = (ushort)(size - 1);
|
chip.romMask = (ushort)(size - 1);
|
||||||
|
|
||||||
packetLength -= size;
|
packetLength -= size;
|
||||||
if (packetLength > 0)
|
if (packetLength > 0)
|
||||||
{
|
{
|
||||||
// discard extra bytes
|
// discard extra bytes
|
||||||
reader.ReadBytes(packetLength);
|
reader.ReadBytes(packetLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
chips.Add(chip);
|
chips.Add(chip);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valid = (chips.Count > 0);
|
valid = (chips.Count > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Read(ushort addr)
|
public byte Read(ushort addr)
|
||||||
{
|
{
|
||||||
CartridgeChip currentChip = chips[0];
|
CartridgeChip currentChip = chips[0];
|
||||||
return currentChip.data[addr & currentChip.romMask];
|
return currentChip.data[addr & currentChip.romMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ushort addr, byte val)
|
public void Write(ushort addr, byte val)
|
||||||
{
|
{
|
||||||
// can't write to rom but we can process DE00/DF00 here
|
// can't write to rom but we can process DE00/DF00 here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,259 +5,259 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64
|
namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
public class Cia
|
public class Cia
|
||||||
{
|
{
|
||||||
public int alarmTime;
|
public int alarmTime;
|
||||||
public bool alarmWriteEnabled;
|
public bool alarmWriteEnabled;
|
||||||
public int cycles;
|
public int cycles;
|
||||||
public bool flagPin;
|
public bool flagPin;
|
||||||
public bool flagPinInterrupt;
|
public bool flagPinInterrupt;
|
||||||
public bool flagPinInterruptEnabled;
|
public bool flagPinInterruptEnabled;
|
||||||
public bool[] generatePositiveEdgeOnUnderflow = new bool[2];
|
public bool[] generatePositiveEdgeOnUnderflow = new bool[2];
|
||||||
public bool interrupt;
|
public bool interrupt;
|
||||||
public bool[] loadStartValue = new bool[2];
|
public bool[] loadStartValue = new bool[2];
|
||||||
public bool palMode;
|
public bool palMode;
|
||||||
public byte[] regs;
|
public byte[] regs;
|
||||||
public int shiftRegisterCycles;
|
public int shiftRegisterCycles;
|
||||||
public bool shiftRegisterInterrupt;
|
public bool shiftRegisterInterrupt;
|
||||||
public bool shiftRegisterInterruptEnabled;
|
public bool shiftRegisterInterruptEnabled;
|
||||||
public bool shiftRegisterIsOutput;
|
public bool shiftRegisterIsOutput;
|
||||||
public bool[] stopOnUnderflow = new bool[2];
|
public bool[] stopOnUnderflow = new bool[2];
|
||||||
public int timeOfDay;
|
public int timeOfDay;
|
||||||
public bool timeOfDayAlarmInterrupt;
|
public bool timeOfDayAlarmInterrupt;
|
||||||
public bool timeOfDayAlarmInterruptEnabled;
|
public bool timeOfDayAlarmInterruptEnabled;
|
||||||
public int[] timerConfig = new int[2];
|
public int[] timerConfig = new int[2];
|
||||||
public bool[] timerEnabled = new bool[2];
|
public bool[] timerEnabled = new bool[2];
|
||||||
public bool[] timerInterruptEnabled = new bool[2];
|
public bool[] timerInterruptEnabled = new bool[2];
|
||||||
public ushort[] timerLatch = new ushort[2];
|
public ushort[] timerLatch = new ushort[2];
|
||||||
public bool[] timerUnderflowMonitor = new bool[2];
|
public bool[] timerUnderflowMonitor = new bool[2];
|
||||||
public ushort[] timerValue = new ushort[2];
|
public ushort[] timerValue = new ushort[2];
|
||||||
public bool[] underflowTimerInterrupt = new bool[2];
|
public bool[] underflowTimerInterrupt = new bool[2];
|
||||||
public bool[] underflowTimerInterruptEnabled = new bool[2];
|
public bool[] underflowTimerInterruptEnabled = new bool[2];
|
||||||
|
|
||||||
public Func<byte> ReadPortA;
|
public Func<byte> ReadPortA;
|
||||||
public Func<byte> ReadPortB;
|
public Func<byte> ReadPortB;
|
||||||
public Action<byte, byte> WritePortA;
|
public Action<byte, byte> WritePortA;
|
||||||
public Action<byte, byte> WritePortB;
|
public Action<byte, byte> WritePortB;
|
||||||
|
|
||||||
public Cia(Func<byte> funcReadPortA, Func<byte> funcReadPortB, Action<byte, byte> actWritePortA, Action<byte, byte> actWritePortB)
|
public Cia(Func<byte> funcReadPortA, Func<byte> funcReadPortB, Action<byte, byte> actWritePortA, Action<byte, byte> actWritePortB)
|
||||||
{
|
{
|
||||||
ReadPortA = funcReadPortA;
|
ReadPortA = funcReadPortA;
|
||||||
ReadPortB = funcReadPortB;
|
ReadPortB = funcReadPortB;
|
||||||
WritePortA = actWritePortA;
|
WritePortA = actWritePortA;
|
||||||
WritePortB = actWritePortB;
|
WritePortB = actWritePortB;
|
||||||
HardReset();
|
HardReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static public byte DummyReadPort()
|
static public byte DummyReadPort()
|
||||||
{
|
{
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public void DummyWritePort(byte val, byte direction)
|
static public void DummyWritePort(byte val, byte direction)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HardReset()
|
public void HardReset()
|
||||||
{
|
{
|
||||||
regs = new byte[0x10];
|
regs = new byte[0x10];
|
||||||
Write(0x0004, 0xFF);
|
Write(0x0004, 0xFF);
|
||||||
Write(0x0005, 0xFF);
|
Write(0x0005, 0xFF);
|
||||||
Write(0x0006, 0xFF);
|
Write(0x0006, 0xFF);
|
||||||
Write(0x0007, 0xFF);
|
Write(0x0007, 0xFF);
|
||||||
Write(0x000B, 0x01);
|
Write(0x000B, 0x01);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PerformCycle()
|
public void PerformCycle()
|
||||||
{
|
{
|
||||||
unchecked
|
unchecked
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (timerConfig[i] == 0)
|
if (timerConfig[i] == 0)
|
||||||
TimerTick(i);
|
TimerTick(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regs[0x04] = (byte)(timerValue[0] & 0xFF);
|
regs[0x04] = (byte)(timerValue[0] & 0xFF);
|
||||||
regs[0x05] = (byte)(timerValue[0] >> 8);
|
regs[0x05] = (byte)(timerValue[0] >> 8);
|
||||||
regs[0x06] = (byte)(timerValue[1] & 0xFF);
|
regs[0x06] = (byte)(timerValue[1] & 0xFF);
|
||||||
regs[0x07] = (byte)(timerValue[1] >> 8);
|
regs[0x07] = (byte)(timerValue[1] >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PollSerial(ref bool bit)
|
public void PollSerial(ref bool bit)
|
||||||
{
|
{
|
||||||
// this has the same effect as raising CNT
|
// this has the same effect as raising CNT
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
switch (timerConfig[i])
|
switch (timerConfig[i])
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
case 3:
|
case 3:
|
||||||
TimerTick(i);
|
TimerTick(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shiftRegisterIsOutput)
|
if (shiftRegisterIsOutput)
|
||||||
{
|
{
|
||||||
bit = ((regs[0x0C] & 0x01) != 0x00);
|
bit = ((regs[0x0C] & 0x01) != 0x00);
|
||||||
regs[0x0C] >>= 1;
|
regs[0x0C] >>= 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
regs[0x0C] >>= 1;
|
regs[0x0C] >>= 1;
|
||||||
if (bit)
|
if (bit)
|
||||||
regs[0x0C] |= 0x80;
|
regs[0x0C] |= 0x80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Read(ushort addr)
|
public byte Read(ushort addr)
|
||||||
{
|
{
|
||||||
byte result = 0;
|
byte result = 0;
|
||||||
addr &= 0x0F;
|
addr &= 0x0F;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
result = ReadPortA();
|
result = ReadPortA();
|
||||||
regs[addr] = result;
|
regs[addr] = result;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
result = ReadPortB();
|
result = ReadPortB();
|
||||||
regs[addr] = result;
|
regs[addr] = result;
|
||||||
break;
|
break;
|
||||||
case 0x0D:
|
case 0x0D:
|
||||||
result = regs[addr];
|
result = regs[addr];
|
||||||
shiftRegisterInterrupt = false;
|
shiftRegisterInterrupt = false;
|
||||||
timeOfDayAlarmInterrupt = false;
|
timeOfDayAlarmInterrupt = false;
|
||||||
underflowTimerInterrupt[0] = false;
|
underflowTimerInterrupt[0] = false;
|
||||||
underflowTimerInterrupt[1] = false;
|
underflowTimerInterrupt[1] = false;
|
||||||
interrupt = false;
|
interrupt = false;
|
||||||
UpdateInterruptReg();
|
UpdateInterruptReg();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = regs[addr];
|
result = regs[addr];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TimerTick(int index)
|
public void TimerTick(int index)
|
||||||
{
|
{
|
||||||
if (timerEnabled[index])
|
if (timerEnabled[index])
|
||||||
{
|
{
|
||||||
unchecked
|
unchecked
|
||||||
{
|
{
|
||||||
timerValue[index]--;
|
timerValue[index]--;
|
||||||
}
|
}
|
||||||
if (timerValue[index] == 0xFFFF)
|
if (timerValue[index] == 0xFFFF)
|
||||||
{
|
{
|
||||||
if (underflowTimerInterruptEnabled[index])
|
if (underflowTimerInterruptEnabled[index])
|
||||||
{
|
{
|
||||||
underflowTimerInterrupt[index] = true;
|
underflowTimerInterrupt[index] = true;
|
||||||
interrupt = true;
|
interrupt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// timer B can count on timer A's underflows
|
// timer B can count on timer A's underflows
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
{
|
{
|
||||||
switch (timerConfig[1])
|
switch (timerConfig[1])
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
TimerTick(1);
|
TimerTick(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateInterruptReg()
|
public void UpdateInterruptReg()
|
||||||
{
|
{
|
||||||
byte result;
|
byte result;
|
||||||
result = (byte)(shiftRegisterInterrupt ? 0x01 : 0x00);
|
result = (byte)(shiftRegisterInterrupt ? 0x01 : 0x00);
|
||||||
result |= (byte)(timeOfDayAlarmInterrupt ? 0x02 : 0x00);
|
result |= (byte)(timeOfDayAlarmInterrupt ? 0x02 : 0x00);
|
||||||
result |= (byte)(underflowTimerInterrupt[0] ? 0x04 : 0x00);
|
result |= (byte)(underflowTimerInterrupt[0] ? 0x04 : 0x00);
|
||||||
result |= (byte)(underflowTimerInterrupt[1] ? 0x08 : 0x00);
|
result |= (byte)(underflowTimerInterrupt[1] ? 0x08 : 0x00);
|
||||||
result |= (byte)(flagPinInterrupt ? 0x10 : 0x00);
|
result |= (byte)(flagPinInterrupt ? 0x10 : 0x00);
|
||||||
result |= (byte)(interrupt ? 0x80 : 0x00);
|
result |= (byte)(interrupt ? 0x80 : 0x00);
|
||||||
regs[0x0D] = result;
|
regs[0x0D] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ushort addr, byte val)
|
public void Write(ushort addr, byte val)
|
||||||
{
|
{
|
||||||
bool allowWrite = true;
|
bool allowWrite = true;
|
||||||
addr &= 0x0F;
|
addr &= 0x0F;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
WritePortA(val, regs[0x02]);
|
WritePortA(val, regs[0x02]);
|
||||||
allowWrite = false;
|
allowWrite = false;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
WritePortB(val, regs[0x03]);
|
WritePortB(val, regs[0x03]);
|
||||||
allowWrite = false;
|
allowWrite = false;
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
timerValue[0] &= 0xFF00;
|
timerValue[0] &= 0xFF00;
|
||||||
timerValue[0] |= val;
|
timerValue[0] |= val;
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
timerValue[0] &= 0xFF;
|
timerValue[0] &= 0xFF;
|
||||||
timerValue[0] |= (ushort)(val << 8);
|
timerValue[0] |= (ushort)(val << 8);
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
timerValue[1] &= 0xFF00;
|
timerValue[1] &= 0xFF00;
|
||||||
timerValue[1] |= val;
|
timerValue[1] |= val;
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 0x07:
|
||||||
timerValue[1] &= 0xFF;
|
timerValue[1] &= 0xFF;
|
||||||
timerValue[1] |= (ushort)(val << 8);
|
timerValue[1] |= (ushort)(val << 8);
|
||||||
break;
|
break;
|
||||||
case 0x0D:
|
case 0x0D:
|
||||||
if ((val & 0x01) != 0x00)
|
if ((val & 0x01) != 0x00)
|
||||||
timerInterruptEnabled[0] = ((val & 0x80) != 0x00);
|
timerInterruptEnabled[0] = ((val & 0x80) != 0x00);
|
||||||
if ((val & 0x02) != 0x00)
|
if ((val & 0x02) != 0x00)
|
||||||
timerInterruptEnabled[1] = ((val & 0x80) != 0x00);
|
timerInterruptEnabled[1] = ((val & 0x80) != 0x00);
|
||||||
if ((val & 0x04) != 0x00)
|
if ((val & 0x04) != 0x00)
|
||||||
timeOfDayAlarmInterruptEnabled = ((val & 0x80) != 0x00);
|
timeOfDayAlarmInterruptEnabled = ((val & 0x80) != 0x00);
|
||||||
if ((val & 0x08) != 0x00)
|
if ((val & 0x08) != 0x00)
|
||||||
shiftRegisterInterruptEnabled = ((val & 0x80) != 0x00);
|
shiftRegisterInterruptEnabled = ((val & 0x80) != 0x00);
|
||||||
if ((val & 0x10) != 0x00)
|
if ((val & 0x10) != 0x00)
|
||||||
flagPinInterruptEnabled = ((val & 0x80) != 0x00);
|
flagPinInterruptEnabled = ((val & 0x80) != 0x00);
|
||||||
allowWrite = false;
|
allowWrite = false;
|
||||||
break;
|
break;
|
||||||
case 0x0E:
|
case 0x0E:
|
||||||
timerEnabled[0] = ((val & 0x01) != 0x00);
|
timerEnabled[0] = ((val & 0x01) != 0x00);
|
||||||
timerUnderflowMonitor[0] = ((val & 0x02) != 0x00);
|
timerUnderflowMonitor[0] = ((val & 0x02) != 0x00);
|
||||||
generatePositiveEdgeOnUnderflow[0] = ((val & 0x04) != 0x00);
|
generatePositiveEdgeOnUnderflow[0] = ((val & 0x04) != 0x00);
|
||||||
stopOnUnderflow[0] = ((val & 0x08) != 0x00);
|
stopOnUnderflow[0] = ((val & 0x08) != 0x00);
|
||||||
loadStartValue[0] = ((val & 0x10) != 0x00);
|
loadStartValue[0] = ((val & 0x10) != 0x00);
|
||||||
timerConfig[0] = ((val & 0x20) >> 5);
|
timerConfig[0] = ((val & 0x20) >> 5);
|
||||||
shiftRegisterIsOutput = ((val & 0x40) != 0x00);
|
shiftRegisterIsOutput = ((val & 0x40) != 0x00);
|
||||||
palMode = ((val & 0x80) != 0x00);
|
palMode = ((val & 0x80) != 0x00);
|
||||||
break;
|
break;
|
||||||
case 0x0F:
|
case 0x0F:
|
||||||
timerEnabled[1] = ((val & 0x01) != 0x00);
|
timerEnabled[1] = ((val & 0x01) != 0x00);
|
||||||
timerUnderflowMonitor[1] = ((val & 0x02) != 0x00);
|
timerUnderflowMonitor[1] = ((val & 0x02) != 0x00);
|
||||||
generatePositiveEdgeOnUnderflow[1] = ((val & 0x04) != 0x00);
|
generatePositiveEdgeOnUnderflow[1] = ((val & 0x04) != 0x00);
|
||||||
stopOnUnderflow[1] = ((val & 0x08) != 0x00);
|
stopOnUnderflow[1] = ((val & 0x08) != 0x00);
|
||||||
loadStartValue[1] = ((val & 0x10) != 0x00);
|
loadStartValue[1] = ((val & 0x10) != 0x00);
|
||||||
timerConfig[1] = ((val & 0x60) >> 5);
|
timerConfig[1] = ((val & 0x60) >> 5);
|
||||||
alarmWriteEnabled = ((val & 0x80) != 0x00);
|
alarmWriteEnabled = ((val & 0x80) != 0x00);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowWrite)
|
if (allowWrite)
|
||||||
regs[addr] = val;
|
regs[addr] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,487 +6,487 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64
|
namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
public enum MemoryDesignation
|
public enum MemoryDesignation
|
||||||
{
|
{
|
||||||
Disabled,
|
Disabled,
|
||||||
RAM,
|
RAM,
|
||||||
Basic,
|
Basic,
|
||||||
Kernal,
|
Kernal,
|
||||||
IO,
|
IO,
|
||||||
Character,
|
Character,
|
||||||
ROMLo,
|
ROMLo,
|
||||||
ROMHi,
|
ROMHi,
|
||||||
Vic,
|
Vic,
|
||||||
Sid,
|
Sid,
|
||||||
ColorRam,
|
ColorRam,
|
||||||
Cia1,
|
Cia1,
|
||||||
Cia2,
|
Cia2,
|
||||||
Expansion1,
|
Expansion1,
|
||||||
Expansion2
|
Expansion2
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MemoryLayout
|
public class MemoryLayout
|
||||||
{
|
{
|
||||||
public MemoryDesignation Mem1000 = MemoryDesignation.RAM;
|
public MemoryDesignation Mem1000 = MemoryDesignation.RAM;
|
||||||
public MemoryDesignation Mem8000 = MemoryDesignation.RAM;
|
public MemoryDesignation Mem8000 = MemoryDesignation.RAM;
|
||||||
public MemoryDesignation MemA000 = MemoryDesignation.RAM;
|
public MemoryDesignation MemA000 = MemoryDesignation.RAM;
|
||||||
public MemoryDesignation MemC000 = MemoryDesignation.RAM;
|
public MemoryDesignation MemC000 = MemoryDesignation.RAM;
|
||||||
public MemoryDesignation MemD000 = MemoryDesignation.RAM;
|
public MemoryDesignation MemD000 = MemoryDesignation.RAM;
|
||||||
public MemoryDesignation MemE000 = MemoryDesignation.RAM;
|
public MemoryDesignation MemE000 = MemoryDesignation.RAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Memory
|
public class Memory
|
||||||
{
|
{
|
||||||
// chips
|
// chips
|
||||||
public Cia cia1;
|
public Cia cia1;
|
||||||
public Cia cia2;
|
public Cia cia2;
|
||||||
public VicII vic;
|
public VicII vic;
|
||||||
public Sid sid;
|
public Sid sid;
|
||||||
|
|
||||||
// storage
|
// storage
|
||||||
public Cartridge cart;
|
public Cartridge cart;
|
||||||
public bool cartInserted = false;
|
public bool cartInserted = false;
|
||||||
|
|
||||||
// roms
|
// roms
|
||||||
public byte[] basicRom;
|
public byte[] basicRom;
|
||||||
public byte[] charRom;
|
public byte[] charRom;
|
||||||
public bool exRomPin = true;
|
public bool exRomPin = true;
|
||||||
public bool gamePin = true;
|
public bool gamePin = true;
|
||||||
public byte[] kernalRom;
|
public byte[] kernalRom;
|
||||||
public MemoryLayout layout;
|
public MemoryLayout layout;
|
||||||
|
|
||||||
// ram
|
// ram
|
||||||
public byte cia2A;
|
public byte cia2A;
|
||||||
public byte cia2B;
|
public byte cia2B;
|
||||||
public byte[] colorRam;
|
public byte[] colorRam;
|
||||||
public byte[] ram;
|
public byte[] ram;
|
||||||
public ushort vicOffset;
|
public ushort vicOffset;
|
||||||
|
|
||||||
// registers
|
// registers
|
||||||
public byte busData;
|
public byte busData;
|
||||||
public byte cpu00; // register $00
|
public byte cpu00; // register $00
|
||||||
public byte cpu01; // register $01
|
public byte cpu01; // register $01
|
||||||
public bool readTrigger = true;
|
public bool readTrigger = true;
|
||||||
public bool writeTrigger = true;
|
public bool writeTrigger = true;
|
||||||
|
|
||||||
public Memory(string sourceFolder, VicII newVic, Sid newSid, Cia newCia1, Cia newCia2)
|
public Memory(string sourceFolder, VicII newVic, Sid newSid, Cia newCia1, Cia newCia2)
|
||||||
{
|
{
|
||||||
ram = new byte[0x10000];
|
ram = new byte[0x10000];
|
||||||
WipeMemory();
|
WipeMemory();
|
||||||
|
|
||||||
string basicFile = "basic";
|
string basicFile = "basic";
|
||||||
string charFile = "chargen";
|
string charFile = "chargen";
|
||||||
string kernalFile = "kernal";
|
string kernalFile = "kernal";
|
||||||
|
|
||||||
basicRom = File.ReadAllBytes(Path.Combine(sourceFolder, basicFile));
|
basicRom = File.ReadAllBytes(Path.Combine(sourceFolder, basicFile));
|
||||||
charRom = File.ReadAllBytes(Path.Combine(sourceFolder, charFile));
|
charRom = File.ReadAllBytes(Path.Combine(sourceFolder, charFile));
|
||||||
kernalRom = File.ReadAllBytes(Path.Combine(sourceFolder, kernalFile));
|
kernalRom = File.ReadAllBytes(Path.Combine(sourceFolder, kernalFile));
|
||||||
colorRam = new byte[0x1000];
|
colorRam = new byte[0x1000];
|
||||||
|
|
||||||
vic = newVic;
|
vic = newVic;
|
||||||
sid = newSid;
|
sid = newSid;
|
||||||
cia1 = newCia1;
|
cia1 = newCia1;
|
||||||
cia2 = newCia2;
|
cia2 = newCia2;
|
||||||
cpu00 = 0x2F;
|
cpu00 = 0x2F;
|
||||||
cpu01 = 0x37;
|
cpu01 = 0x37;
|
||||||
|
|
||||||
layout = new MemoryLayout();
|
layout = new MemoryLayout();
|
||||||
UpdateLayout();
|
UpdateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyCartridge(Cartridge newCart)
|
public void ApplyCartridge(Cartridge newCart)
|
||||||
{
|
{
|
||||||
cart = newCart;
|
cart = newCart;
|
||||||
cartInserted = true;
|
cartInserted = true;
|
||||||
exRomPin = cart.exRomPin;
|
exRomPin = cart.exRomPin;
|
||||||
gamePin = cart.gamePin;
|
gamePin = cart.gamePin;
|
||||||
UpdateLayout();
|
UpdateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte CIA2ReadPortA()
|
public byte CIA2ReadPortA()
|
||||||
{
|
{
|
||||||
return cia2A;
|
return cia2A;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte CIA2ReadPortB()
|
public byte CIA2ReadPortB()
|
||||||
{
|
{
|
||||||
return cia2B;
|
return cia2B;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CIA2WritePortA(byte val, byte direction)
|
public void CIA2WritePortA(byte val, byte direction)
|
||||||
{
|
{
|
||||||
cia2A &= (byte)~direction;
|
cia2A &= (byte)~direction;
|
||||||
cia2A |= (byte)(val & direction);
|
cia2A |= (byte)(val & direction);
|
||||||
|
|
||||||
vicOffset = (ushort)((cia2A & 0x03) << 14);
|
vicOffset = (ushort)((cia2A & 0x03) << 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CIA2WritePortB(byte val, byte direction)
|
public void CIA2WritePortB(byte val, byte direction)
|
||||||
{
|
{
|
||||||
cia2B &= (byte)~direction;
|
cia2B &= (byte)~direction;
|
||||||
cia2B |= (byte)(val & direction);
|
cia2B |= (byte)(val & direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemoryDesignation GetDesignation(ushort addr)
|
public MemoryDesignation GetDesignation(ushort addr)
|
||||||
{
|
{
|
||||||
MemoryDesignation result;
|
MemoryDesignation result;
|
||||||
|
|
||||||
if (addr < 0x1000)
|
if (addr < 0x1000)
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.RAM;
|
result = MemoryDesignation.RAM;
|
||||||
}
|
}
|
||||||
else if (addr < 0x8000)
|
else if (addr < 0x8000)
|
||||||
{
|
{
|
||||||
result = layout.Mem1000;
|
result = layout.Mem1000;
|
||||||
}
|
}
|
||||||
else if (addr < 0xA000)
|
else if (addr < 0xA000)
|
||||||
{
|
{
|
||||||
result = layout.Mem8000;
|
result = layout.Mem8000;
|
||||||
}
|
}
|
||||||
else if (addr < 0xC000)
|
else if (addr < 0xC000)
|
||||||
{
|
{
|
||||||
result = layout.MemA000;
|
result = layout.MemA000;
|
||||||
}
|
}
|
||||||
else if (addr < 0xD000)
|
else if (addr < 0xD000)
|
||||||
{
|
{
|
||||||
result = layout.MemC000;
|
result = layout.MemC000;
|
||||||
}
|
}
|
||||||
else if (addr < 0xE000)
|
else if (addr < 0xE000)
|
||||||
{
|
{
|
||||||
result = layout.MemD000;
|
result = layout.MemD000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = layout.MemE000;
|
result = layout.MemE000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == MemoryDesignation.IO)
|
if (result == MemoryDesignation.IO)
|
||||||
{
|
{
|
||||||
addr &= 0x0FFF;
|
addr &= 0x0FFF;
|
||||||
if (addr < 0x0400)
|
if (addr < 0x0400)
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.Vic;
|
result = MemoryDesignation.Vic;
|
||||||
}
|
}
|
||||||
else if (addr < 0x0800)
|
else if (addr < 0x0800)
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.Sid;
|
result = MemoryDesignation.Sid;
|
||||||
}
|
}
|
||||||
else if (addr < 0x0C00)
|
else if (addr < 0x0C00)
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.ColorRam;
|
result = MemoryDesignation.ColorRam;
|
||||||
}
|
}
|
||||||
else if (addr < 0x0D00)
|
else if (addr < 0x0D00)
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.Cia1;
|
result = MemoryDesignation.Cia1;
|
||||||
}
|
}
|
||||||
else if (addr < 0x0E00)
|
else if (addr < 0x0E00)
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.Cia2;
|
result = MemoryDesignation.Cia2;
|
||||||
}
|
}
|
||||||
else if (addr < 0x0F00)
|
else if (addr < 0x0F00)
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.Expansion1;
|
result = MemoryDesignation.Expansion1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = MemoryDesignation.Expansion2;
|
result = MemoryDesignation.Expansion2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Peek(ushort addr)
|
public byte Peek(ushort addr)
|
||||||
{
|
{
|
||||||
byte result;
|
byte result;
|
||||||
|
|
||||||
if (addr == 0x0000)
|
if (addr == 0x0000)
|
||||||
{
|
{
|
||||||
result = cpu00;
|
result = cpu00;
|
||||||
}
|
}
|
||||||
else if (addr == 0x0001)
|
else if (addr == 0x0001)
|
||||||
{
|
{
|
||||||
result = cpu01;
|
result = cpu01;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryDesignation des = GetDesignation(addr);
|
MemoryDesignation des = GetDesignation(addr);
|
||||||
|
|
||||||
switch (des)
|
switch (des)
|
||||||
{
|
{
|
||||||
case MemoryDesignation.Basic:
|
case MemoryDesignation.Basic:
|
||||||
result = basicRom[addr & 0x1FFF];
|
result = basicRom[addr & 0x1FFF];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Character:
|
case MemoryDesignation.Character:
|
||||||
result = charRom[addr & 0x0FFF];
|
result = charRom[addr & 0x0FFF];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Vic:
|
case MemoryDesignation.Vic:
|
||||||
result = vic.regs[addr & 0x3F];
|
result = vic.regs[addr & 0x3F];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Sid:
|
case MemoryDesignation.Sid:
|
||||||
result = sid.regs[addr & 0x1F];
|
result = sid.regs[addr & 0x1F];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.ColorRam:
|
case MemoryDesignation.ColorRam:
|
||||||
result = colorRam[addr & 0x03FF];
|
result = colorRam[addr & 0x03FF];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Cia1:
|
case MemoryDesignation.Cia1:
|
||||||
result = cia1.regs[addr & 0x0F];
|
result = cia1.regs[addr & 0x0F];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Cia2:
|
case MemoryDesignation.Cia2:
|
||||||
result = cia2.regs[addr & 0x0F];
|
result = cia2.regs[addr & 0x0F];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Expansion1:
|
case MemoryDesignation.Expansion1:
|
||||||
result = 0;
|
result = 0;
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Expansion2:
|
case MemoryDesignation.Expansion2:
|
||||||
result = 0;
|
result = 0;
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Kernal:
|
case MemoryDesignation.Kernal:
|
||||||
result = kernalRom[addr & 0x1FFF];
|
result = kernalRom[addr & 0x1FFF];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.RAM:
|
case MemoryDesignation.RAM:
|
||||||
result = ram[addr];
|
result = ram[addr];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.ROMHi:
|
case MemoryDesignation.ROMHi:
|
||||||
result = cart.chips[0].data[addr & cart.chips[0].romMask];
|
result = cart.chips[0].data[addr & cart.chips[0].romMask];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.ROMLo:
|
case MemoryDesignation.ROMLo:
|
||||||
result = cart.chips[0].data[addr & cart.chips[0].romMask];
|
result = cart.chips[0].data[addr & cart.chips[0].romMask];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
busData = result;
|
busData = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Read(ushort addr)
|
public byte Read(ushort addr)
|
||||||
{
|
{
|
||||||
byte result;
|
byte result;
|
||||||
|
|
||||||
if (addr == 0x0000)
|
if (addr == 0x0000)
|
||||||
{
|
{
|
||||||
result = cpu00;
|
result = cpu00;
|
||||||
}
|
}
|
||||||
else if (addr == 0x0001)
|
else if (addr == 0x0001)
|
||||||
{
|
{
|
||||||
result = cpu01;
|
result = cpu01;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryDesignation des = GetDesignation(addr);
|
MemoryDesignation des = GetDesignation(addr);
|
||||||
|
|
||||||
switch (des)
|
switch (des)
|
||||||
{
|
{
|
||||||
case MemoryDesignation.Basic:
|
case MemoryDesignation.Basic:
|
||||||
result = basicRom[addr & 0x1FFF];
|
result = basicRom[addr & 0x1FFF];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Character:
|
case MemoryDesignation.Character:
|
||||||
result = charRom[addr & 0x0FFF];
|
result = charRom[addr & 0x0FFF];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Vic:
|
case MemoryDesignation.Vic:
|
||||||
result = vic.Read(addr);
|
result = vic.Read(addr);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Sid:
|
case MemoryDesignation.Sid:
|
||||||
result = sid.Read(addr);
|
result = sid.Read(addr);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.ColorRam:
|
case MemoryDesignation.ColorRam:
|
||||||
result = ReadColorRam(addr);
|
result = ReadColorRam(addr);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Cia1:
|
case MemoryDesignation.Cia1:
|
||||||
result = cia1.Read(addr);
|
result = cia1.Read(addr);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Cia2:
|
case MemoryDesignation.Cia2:
|
||||||
result = cia2.Read(addr);
|
result = cia2.Read(addr);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Expansion1:
|
case MemoryDesignation.Expansion1:
|
||||||
result = 0;
|
result = 0;
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Expansion2:
|
case MemoryDesignation.Expansion2:
|
||||||
result = 0;
|
result = 0;
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Kernal:
|
case MemoryDesignation.Kernal:
|
||||||
result = kernalRom[addr & 0x1FFF];
|
result = kernalRom[addr & 0x1FFF];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.RAM:
|
case MemoryDesignation.RAM:
|
||||||
result = ram[addr];
|
result = ram[addr];
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.ROMHi:
|
case MemoryDesignation.ROMHi:
|
||||||
result = cart.Read(addr);
|
result = cart.Read(addr);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.ROMLo:
|
case MemoryDesignation.ROMLo:
|
||||||
result = cart.Read(addr);
|
result = cart.Read(addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
busData = result;
|
busData = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte ReadColorRam(ushort addr)
|
public byte ReadColorRam(ushort addr)
|
||||||
{
|
{
|
||||||
return (byte)((busData & 0xF0) | (colorRam[addr & 0x03FF]));
|
return (byte)((busData & 0xF0) | (colorRam[addr & 0x03FF]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateLayout()
|
public void UpdateLayout()
|
||||||
{
|
{
|
||||||
bool loRom = ((cpu01 & 0x01) != 0);
|
bool loRom = ((cpu01 & 0x01) != 0);
|
||||||
bool hiRom = ((cpu01 & 0x02) != 0);
|
bool hiRom = ((cpu01 & 0x02) != 0);
|
||||||
bool ioEnable = ((cpu01 & 0x04) != 0);
|
bool ioEnable = ((cpu01 & 0x04) != 0);
|
||||||
|
|
||||||
if (loRom && hiRom && exRomPin && gamePin)
|
if (loRom && hiRom && exRomPin && gamePin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.RAM;
|
layout.Mem8000 = MemoryDesignation.RAM;
|
||||||
layout.MemA000 = MemoryDesignation.Basic;
|
layout.MemA000 = MemoryDesignation.Basic;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
||||||
layout.MemE000 = MemoryDesignation.Kernal;
|
layout.MemE000 = MemoryDesignation.Kernal;
|
||||||
}
|
}
|
||||||
else if (loRom && !hiRom && exRomPin)
|
else if (loRom && !hiRom && exRomPin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.RAM;
|
layout.Mem8000 = MemoryDesignation.RAM;
|
||||||
layout.MemA000 = MemoryDesignation.RAM;
|
layout.MemA000 = MemoryDesignation.RAM;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
||||||
layout.MemE000 = MemoryDesignation.RAM;
|
layout.MemE000 = MemoryDesignation.RAM;
|
||||||
}
|
}
|
||||||
else if (loRom && !hiRom && !exRomPin && !gamePin)
|
else if (loRom && !hiRom && !exRomPin && !gamePin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.RAM;
|
layout.Mem8000 = MemoryDesignation.RAM;
|
||||||
layout.MemA000 = MemoryDesignation.RAM;
|
layout.MemA000 = MemoryDesignation.RAM;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.RAM;
|
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.RAM;
|
||||||
layout.MemE000 = MemoryDesignation.RAM;
|
layout.MemE000 = MemoryDesignation.RAM;
|
||||||
}
|
}
|
||||||
else if ((!loRom && hiRom && gamePin) || (!loRom && !hiRom && !exRomPin))
|
else if ((!loRom && hiRom && gamePin) || (!loRom && !hiRom && !exRomPin))
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.RAM;
|
layout.Mem8000 = MemoryDesignation.RAM;
|
||||||
layout.MemA000 = MemoryDesignation.RAM;
|
layout.MemA000 = MemoryDesignation.RAM;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
||||||
layout.MemE000 = MemoryDesignation.Kernal;
|
layout.MemE000 = MemoryDesignation.Kernal;
|
||||||
}
|
}
|
||||||
else if (!loRom && !hiRom && gamePin)
|
else if (!loRom && !hiRom && gamePin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.RAM;
|
layout.Mem8000 = MemoryDesignation.RAM;
|
||||||
layout.MemA000 = MemoryDesignation.RAM;
|
layout.MemA000 = MemoryDesignation.RAM;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = MemoryDesignation.RAM;
|
layout.MemD000 = MemoryDesignation.RAM;
|
||||||
layout.MemE000 = MemoryDesignation.RAM;
|
layout.MemE000 = MemoryDesignation.RAM;
|
||||||
}
|
}
|
||||||
else if (loRom && hiRom && gamePin && !exRomPin)
|
else if (loRom && hiRom && gamePin && !exRomPin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.ROMLo;
|
layout.Mem8000 = MemoryDesignation.ROMLo;
|
||||||
layout.MemA000 = MemoryDesignation.Basic;
|
layout.MemA000 = MemoryDesignation.Basic;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
||||||
layout.MemE000 = MemoryDesignation.Kernal;
|
layout.MemE000 = MemoryDesignation.Kernal;
|
||||||
}
|
}
|
||||||
else if (!loRom && hiRom && !gamePin && !exRomPin)
|
else if (!loRom && hiRom && !gamePin && !exRomPin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.RAM;
|
layout.Mem8000 = MemoryDesignation.RAM;
|
||||||
layout.MemA000 = MemoryDesignation.ROMHi;
|
layout.MemA000 = MemoryDesignation.ROMHi;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
||||||
layout.MemE000 = MemoryDesignation.Kernal;
|
layout.MemE000 = MemoryDesignation.Kernal;
|
||||||
}
|
}
|
||||||
else if (loRom && hiRom && !gamePin && !exRomPin)
|
else if (loRom && hiRom && !gamePin && !exRomPin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.RAM;
|
layout.Mem1000 = MemoryDesignation.RAM;
|
||||||
layout.Mem8000 = MemoryDesignation.ROMLo;
|
layout.Mem8000 = MemoryDesignation.ROMLo;
|
||||||
layout.MemA000 = MemoryDesignation.ROMHi;
|
layout.MemA000 = MemoryDesignation.ROMHi;
|
||||||
layout.MemC000 = MemoryDesignation.RAM;
|
layout.MemC000 = MemoryDesignation.RAM;
|
||||||
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
layout.MemD000 = ioEnable ? MemoryDesignation.IO : MemoryDesignation.Character;
|
||||||
layout.MemE000 = MemoryDesignation.Kernal;
|
layout.MemE000 = MemoryDesignation.Kernal;
|
||||||
}
|
}
|
||||||
else if (!gamePin && exRomPin)
|
else if (!gamePin && exRomPin)
|
||||||
{
|
{
|
||||||
layout.Mem1000 = MemoryDesignation.Disabled;
|
layout.Mem1000 = MemoryDesignation.Disabled;
|
||||||
layout.Mem8000 = MemoryDesignation.ROMLo;
|
layout.Mem8000 = MemoryDesignation.ROMLo;
|
||||||
layout.MemA000 = MemoryDesignation.Disabled;
|
layout.MemA000 = MemoryDesignation.Disabled;
|
||||||
layout.MemC000 = MemoryDesignation.Disabled;
|
layout.MemC000 = MemoryDesignation.Disabled;
|
||||||
layout.MemD000 = MemoryDesignation.IO;
|
layout.MemD000 = MemoryDesignation.IO;
|
||||||
layout.MemE000 = MemoryDesignation.ROMHi;
|
layout.MemE000 = MemoryDesignation.ROMHi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte VicRead(ushort addr)
|
public byte VicRead(ushort addr)
|
||||||
{
|
{
|
||||||
addr = (ushort)(addr & 0x1FFF);
|
addr = (ushort)(addr & 0x1FFF);
|
||||||
if (addr >= 0x1000 && addr < 0x2000)
|
if (addr >= 0x1000 && addr < 0x2000)
|
||||||
return charRom[addr & 0x0FFF];
|
return charRom[addr & 0x0FFF];
|
||||||
else
|
else
|
||||||
return ram[addr | vicOffset];
|
return ram[addr | vicOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WipeMemory()
|
public void WipeMemory()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 0x10000; i += 0x80)
|
for (int i = 0; i < 0x10000; i += 0x80)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 0x40; j++)
|
for (int j = 0; j < 0x40; j++)
|
||||||
ram[i + j] = 0x00;
|
ram[i + j] = 0x00;
|
||||||
for (int j = 0x40; j < 0x80; j++)
|
for (int j = 0x40; j < 0x80; j++)
|
||||||
ram[i + j] = 0xFF;
|
ram[i + j] = 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ushort addr, byte val)
|
public void Write(ushort addr, byte val)
|
||||||
{
|
{
|
||||||
if (addr == 0x0000)
|
if (addr == 0x0000)
|
||||||
{
|
{
|
||||||
cpu00 = val;
|
cpu00 = val;
|
||||||
}
|
}
|
||||||
else if (addr == 0x0001)
|
else if (addr == 0x0001)
|
||||||
{
|
{
|
||||||
cpu01 &= (byte)(~cpu00);
|
cpu01 &= (byte)(~cpu00);
|
||||||
cpu01 |= (byte)(cpu00 & val);
|
cpu01 |= (byte)(cpu00 & val);
|
||||||
UpdateLayout();
|
UpdateLayout();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryDesignation des = GetDesignation(addr);
|
MemoryDesignation des = GetDesignation(addr);
|
||||||
|
|
||||||
switch (des)
|
switch (des)
|
||||||
{
|
{
|
||||||
case MemoryDesignation.Vic:
|
case MemoryDesignation.Vic:
|
||||||
vic.Write(addr, val);
|
vic.Write(addr, val);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Sid:
|
case MemoryDesignation.Sid:
|
||||||
sid.Write(addr, val);
|
sid.Write(addr, val);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.ColorRam:
|
case MemoryDesignation.ColorRam:
|
||||||
colorRam[addr & 0x03FF] = (byte)(val & 0x0F);
|
colorRam[addr & 0x03FF] = (byte)(val & 0x0F);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Cia1:
|
case MemoryDesignation.Cia1:
|
||||||
cia1.Write(addr, val);
|
cia1.Write(addr, val);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Cia2:
|
case MemoryDesignation.Cia2:
|
||||||
cia2.Write(addr, val);
|
cia2.Write(addr, val);
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Expansion1:
|
case MemoryDesignation.Expansion1:
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.Expansion2:
|
case MemoryDesignation.Expansion2:
|
||||||
break;
|
break;
|
||||||
case MemoryDesignation.RAM:
|
case MemoryDesignation.RAM:
|
||||||
ram[addr] = val;
|
ram[addr] = val;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
busData = val;
|
busData = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,41 +5,41 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64
|
namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
public enum SidMode
|
public enum SidMode
|
||||||
{
|
{
|
||||||
Sid6581,
|
Sid6581,
|
||||||
Sid8580
|
Sid8580
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Sid
|
public class Sid
|
||||||
{
|
{
|
||||||
public byte[] regs;
|
public byte[] regs;
|
||||||
|
|
||||||
public Sid()
|
public Sid()
|
||||||
{
|
{
|
||||||
regs = new byte[0x20];
|
regs = new byte[0x20];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PerformCycle()
|
public void PerformCycle()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Read(ushort addr)
|
public byte Read(ushort addr)
|
||||||
{
|
{
|
||||||
switch (addr & 0x1F)
|
switch (addr & 0x1F)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ushort addr, byte val)
|
public void Write(ushort addr, byte val)
|
||||||
{
|
{
|
||||||
switch (addr & 0x1F)
|
switch (addr & 0x1F)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue