c64- CIA register class, data port class
This commit is contained in:
parent
ef4bb14d59
commit
4f2cd1263c
|
@ -83,6 +83,7 @@
|
|||
<Compile Include="Computers\Commodore64\C64.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cartridge.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cia.cs" />
|
||||
<Compile Include="Computers\Commodore64\DataPort.cs" />
|
||||
<Compile Include="Computers\Commodore64\MemBus.cs" />
|
||||
<Compile Include="Computers\Commodore64\Sid.cs" />
|
||||
<Compile Include="Computers\Commodore64\VicII.cs" />
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public byte[] inputFile;
|
||||
|
||||
// chipset
|
||||
public Cia cia0;
|
||||
public Cia cia1;
|
||||
public Cia cia2;
|
||||
public MOS6502X cpu;
|
||||
public Memory mem;
|
||||
public Sid sid;
|
||||
|
@ -31,8 +31,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
cpu.DummyReadMemory = PeekMemory;
|
||||
|
||||
// initialize cia timers
|
||||
cia1 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort);
|
||||
cia2 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort);
|
||||
cia0 = new Cia(signal);
|
||||
cia1 = new Cia(signal);
|
||||
|
||||
// initialize vic
|
||||
signal = new ChipSignals();
|
||||
|
@ -43,15 +43,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
// initialize memory (this must be done AFTER all other chips are initialized)
|
||||
string romPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "C64Kernal");
|
||||
mem = new Memory(romPath, vic, sid, cia1, cia2);
|
||||
mem = new Memory(romPath, vic, sid, cia0, cia1);
|
||||
vic.mem = mem;
|
||||
|
||||
// initialize ports
|
||||
cia2.ReadPortA = mem.CIA2ReadPortA;
|
||||
cia2.ReadPortB = mem.CIA2ReadPortB;
|
||||
cia2.WritePortA = mem.CIA2WritePortA;
|
||||
cia2.WritePortB = mem.CIA2WritePortB;
|
||||
|
||||
// initialize media
|
||||
Cartridge cart = new Cartridge(inputFile);
|
||||
if (cart.valid)
|
||||
|
@ -91,12 +85,17 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
public class ChipSignals
|
||||
{
|
||||
private bool[] _CiaSerialInput = new bool[2];
|
||||
private bool[] _CiaIRQOutput = new bool[2];
|
||||
private bool _VicAECOutput;
|
||||
private bool _VicBAOutput;
|
||||
private bool _VicIRQOutput;
|
||||
private bool _VicLPInput;
|
||||
|
||||
public bool CiaIRQ0 { get { return _CiaIRQOutput[0]; } set { _CiaIRQOutput[0] = value; } }
|
||||
public bool CiaIRQ1 { get { return _CiaIRQOutput[1]; } set { _CiaIRQOutput[1] = value; } }
|
||||
public bool CiaSerial0 { get { return _CiaSerialInput[0]; } }
|
||||
public bool CiaSerial1 { get { return _CiaSerialInput[1]; } }
|
||||
public bool CpuAEC { get { return _VicAECOutput; } }
|
||||
public bool CpuIRQ { get { return _VicIRQOutput | _CiaIRQOutput[0] | _CiaIRQOutput[1]; } }
|
||||
public bool CpuRDY { get { return _VicBAOutput; } }
|
||||
|
|
|
@ -102,8 +102,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
}
|
||||
vic.PerformCycle();
|
||||
sid.PerformCycle();
|
||||
cia0.PerformCycle();
|
||||
cia1.PerformCycle();
|
||||
cia2.PerformCycle();
|
||||
}
|
||||
|
||||
if (_islag)
|
||||
|
|
|
@ -5,259 +5,305 @@ using System.Text;
|
|||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public class CiaRegs
|
||||
{
|
||||
public bool ALARM;
|
||||
public int ALARM10;
|
||||
public int ALARMHR;
|
||||
public int ALARMMIN;
|
||||
public bool ALARMPM;
|
||||
public int ALARMSEC;
|
||||
public int[] DOR = new int[2];
|
||||
public bool IALARM;
|
||||
public bool IFLG;
|
||||
public int[] INMODE = new int[2];
|
||||
public bool IRQ;
|
||||
public bool ISP;
|
||||
public bool[] IT = new bool[2];
|
||||
public bool[] LOAD = new bool[2];
|
||||
public bool[] OUTMODE = new bool[2];
|
||||
public bool[] PBON = new bool[2];
|
||||
public int[] PR = new int[2];
|
||||
public bool[] RUNMODE = new bool[2];
|
||||
public int SDR;
|
||||
public bool SPMODE;
|
||||
public bool[] START = new bool[2];
|
||||
public int[] T = new int[2];
|
||||
public int TOD10;
|
||||
public bool TODIN;
|
||||
public int TODHR;
|
||||
public int TODMIN;
|
||||
public bool TODPM;
|
||||
public int TODSEC;
|
||||
|
||||
private DirectionalDataPort[] ports;
|
||||
private ChipSignals signal;
|
||||
|
||||
public CiaRegs(ChipSignals newSignal, DirectionalDataPort[] newPorts)
|
||||
{
|
||||
ports = newPorts;
|
||||
signal = newSignal;
|
||||
|
||||
// power on state
|
||||
this[0x04] = 0xFF;
|
||||
this[0x05] = 0xFF;
|
||||
this[0x06] = 0xFF;
|
||||
this[0x07] = 0xFF;
|
||||
this[0x0B] = 0x01;
|
||||
}
|
||||
|
||||
public byte this[int addr]
|
||||
{
|
||||
get
|
||||
{
|
||||
// value of open bits
|
||||
int result = 0x00;
|
||||
|
||||
addr &= 0x0F;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
result = ports[0].Data;
|
||||
break;
|
||||
case 0x01:
|
||||
result = ports[1].Data;
|
||||
break;
|
||||
case 0x02:
|
||||
result = ports[0].Direction;
|
||||
break;
|
||||
case 0x03:
|
||||
result = ports[1].Direction;
|
||||
break;
|
||||
case 0x04:
|
||||
result = (T[0] & 0xFF);
|
||||
break;
|
||||
case 0x05:
|
||||
result = ((T[0] >> 8) & 0xFF);
|
||||
break;
|
||||
case 0x06:
|
||||
result = (T[1] & 0xFF);
|
||||
break;
|
||||
case 0x07:
|
||||
result = ((T[1] >> 8) & 0xFF);
|
||||
break;
|
||||
case 0x08:
|
||||
result |= (TOD10 & 0x0F);
|
||||
break;
|
||||
case 0x09:
|
||||
result &= 0x80;
|
||||
result |= (TODSEC & 0x7F);
|
||||
break;
|
||||
case 0x0A:
|
||||
result &= 0x80;
|
||||
result |= (TODMIN & 0x7F);
|
||||
break;
|
||||
case 0x0B:
|
||||
result &= 0x40;
|
||||
result |= ((TODHR & 0x3F) | (TODPM ? 0x80 : 0x00));
|
||||
break;
|
||||
case 0x0C:
|
||||
result = SDR;
|
||||
break;
|
||||
case 0x0D:
|
||||
result &= 0x9F;
|
||||
result |= (IT[0] ? 0x01 : 0x00);
|
||||
result |= (IT[1] ? 0x02 : 0x00);
|
||||
result |= (IALARM ? 0x04 : 0x00);
|
||||
result |= (ISP ? 0x08 : 0x00);
|
||||
result |= (IFLG ? 0x10 : 0x00);
|
||||
result |= (IRQ ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x0E:
|
||||
result = (START[0] ? 0x01 : 0x00);
|
||||
result = (PBON[0] ? 0x02 : 0x00);
|
||||
result = (OUTMODE[0] ? 0x04 : 0x00);
|
||||
result = (RUNMODE[0] ? 0x08 : 0x00);
|
||||
result = (LOAD[0] ? 0x10 : 0x00);
|
||||
result = ((INMODE[0] & 0x01) << 5);
|
||||
result = (SPMODE ? 0x40 : 0x00);
|
||||
result = (TODIN ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x0F:
|
||||
result = (START[1] ? 0x01 : 0x00);
|
||||
result = (PBON[1] ? 0x02 : 0x00);
|
||||
result = (OUTMODE[1] ? 0x04 : 0x00);
|
||||
result = (RUNMODE[1] ? 0x08 : 0x00);
|
||||
result = (LOAD[1] ? 0x10 : 0x00);
|
||||
result = ((INMODE[1] & 0x03) << 5);
|
||||
result = (ALARM ? 0x80 : 0x00);
|
||||
break;
|
||||
}
|
||||
|
||||
return (byte)(result & 0xFF);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
byte val = value;
|
||||
addr &= 0x0F;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
ports[0].Data = val;
|
||||
break;
|
||||
case 0x01:
|
||||
ports[1].Data = val;
|
||||
break;
|
||||
case 0x02:
|
||||
ports[0].Direction = val;
|
||||
break;
|
||||
case 0x03:
|
||||
ports[1].Direction = val;
|
||||
break;
|
||||
case 0x04:
|
||||
T[0] &= 0xFF00;
|
||||
T[0] |= val;
|
||||
break;
|
||||
case 0x05:
|
||||
T[0] &= 0x00FF;
|
||||
T[0] |= ((int)val << 8);
|
||||
break;
|
||||
case 0x06:
|
||||
T[1] &= 0xFF00;
|
||||
T[1] |= val;
|
||||
break;
|
||||
case 0x07:
|
||||
T[1] &= 0x00FF;
|
||||
T[1] |= ((int)val << 8);
|
||||
break;
|
||||
case 0x08:
|
||||
TOD10 = val & 0x0F;
|
||||
break;
|
||||
case 0x09:
|
||||
TODSEC = val & 0x7F;
|
||||
break;
|
||||
case 0x0A:
|
||||
TODMIN = val & 0x7F;
|
||||
break;
|
||||
case 0x0B:
|
||||
val &= 0x9F;
|
||||
TODHR = val;
|
||||
TODPM = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x0C:
|
||||
SDR = val;
|
||||
break;
|
||||
case 0x0D:
|
||||
IT[0] = ((val & 0x01) != 0x00);
|
||||
IT[1] = ((val & 0x02) != 0x00);
|
||||
IALARM = ((val & 0x04) != 0x00);
|
||||
ISP = ((val & 0x08) != 0x00);
|
||||
IFLG = ((val & 0x10) != 0x00);
|
||||
IRQ = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x0E:
|
||||
START[0] = ((val & 0x01) != 0x00);
|
||||
PBON[0] = ((val & 0x02) != 0x00);
|
||||
OUTMODE[0] = ((val & 0x04) != 0x00);
|
||||
RUNMODE[0] = ((val & 0x08) != 0x00);
|
||||
LOAD[0] = ((val & 0x10) != 0x00);
|
||||
INMODE[0] = ((val & 0x20) >> 5);
|
||||
SPMODE = ((val & 0x40) != 0x00);
|
||||
TODIN = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x0F:
|
||||
START[1] = ((val & 0x01) != 0x00);
|
||||
PBON[1] = ((val & 0x02) != 0x00);
|
||||
OUTMODE[1] = ((val & 0x04) != 0x00);
|
||||
RUNMODE[1] = ((val & 0x08) != 0x00);
|
||||
LOAD[1] = ((val & 0x10) != 0x00);
|
||||
INMODE[1] = ((val & 0x60) >> 5);
|
||||
ALARM = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Cia
|
||||
{
|
||||
public int alarmTime;
|
||||
public bool alarmWriteEnabled;
|
||||
public int cycles;
|
||||
public bool flagPin;
|
||||
public bool flagPinInterrupt;
|
||||
public bool flagPinInterruptEnabled;
|
||||
public bool[] generatePositiveEdgeOnUnderflow = new bool[2];
|
||||
public bool interrupt;
|
||||
public bool[] loadStartValue = new bool[2];
|
||||
public bool palMode;
|
||||
public byte[] regs;
|
||||
public int shiftRegisterCycles;
|
||||
public bool shiftRegisterInterrupt;
|
||||
public bool shiftRegisterInterruptEnabled;
|
||||
public bool shiftRegisterIsOutput;
|
||||
public bool[] stopOnUnderflow = new bool[2];
|
||||
public int timeOfDay;
|
||||
public bool timeOfDayAlarmInterrupt;
|
||||
public bool timeOfDayAlarmInterruptEnabled;
|
||||
public int[] timerConfig = new int[2];
|
||||
public bool[] timerEnabled = new bool[2];
|
||||
public bool[] timerInterruptEnabled = new bool[2];
|
||||
public ushort[] timerLatch = new ushort[2];
|
||||
public bool[] timerUnderflowMonitor = new bool[2];
|
||||
public ushort[] timerValue = new ushort[2];
|
||||
public bool[] underflowTimerInterrupt = new bool[2];
|
||||
public bool[] underflowTimerInterruptEnabled = new bool[2];
|
||||
public int intMask;
|
||||
public DirectionalDataPort[] ports;
|
||||
public CiaRegs regs;
|
||||
public ChipSignals signal;
|
||||
|
||||
public Func<byte> ReadPortA;
|
||||
public Func<byte> ReadPortB;
|
||||
public Action<byte, byte> WritePortA;
|
||||
public Action<byte, byte> WritePortB;
|
||||
|
||||
public Cia(Func<byte> funcReadPortA, Func<byte> funcReadPortB, Action<byte, byte> actWritePortA, Action<byte, byte> actWritePortB)
|
||||
public Cia(ChipSignals newSignal)
|
||||
{
|
||||
ReadPortA = funcReadPortA;
|
||||
ReadPortB = funcReadPortB;
|
||||
WritePortA = actWritePortA;
|
||||
WritePortB = actWritePortB;
|
||||
signal = newSignal;
|
||||
HardReset();
|
||||
}
|
||||
|
||||
static public byte DummyReadPort()
|
||||
{
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static public void DummyWritePort(byte val, byte direction)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void HardReset()
|
||||
{
|
||||
regs = new byte[0x10];
|
||||
Write(0x0004, 0xFF);
|
||||
Write(0x0005, 0xFF);
|
||||
Write(0x0006, 0xFF);
|
||||
Write(0x0007, 0xFF);
|
||||
Write(0x000B, 0x01);
|
||||
|
||||
ports = new DirectionalDataPort[2];
|
||||
regs = new CiaRegs(signal, ports);
|
||||
}
|
||||
|
||||
public void PerformCycle()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (timerConfig[i] == 0)
|
||||
TimerTick(i);
|
||||
}
|
||||
}
|
||||
|
||||
regs[0x04] = (byte)(timerValue[0] & 0xFF);
|
||||
regs[0x05] = (byte)(timerValue[0] >> 8);
|
||||
regs[0x06] = (byte)(timerValue[1] & 0xFF);
|
||||
regs[0x07] = (byte)(timerValue[1] >> 8);
|
||||
}
|
||||
|
||||
public void PollSerial(ref bool bit)
|
||||
{
|
||||
// this has the same effect as raising CNT
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
switch (timerConfig[i])
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
TimerTick(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shiftRegisterIsOutput)
|
||||
{
|
||||
bit = ((regs[0x0C] & 0x01) != 0x00);
|
||||
regs[0x0C] >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
regs[0x0C] >>= 1;
|
||||
if (bit)
|
||||
regs[0x0C] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
{
|
||||
byte result = 0;
|
||||
addr &= 0x0F;
|
||||
byte result;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
result = ReadPortA();
|
||||
regs[addr] = result;
|
||||
break;
|
||||
case 0x01:
|
||||
result = ReadPortB();
|
||||
regs[addr] = result;
|
||||
break;
|
||||
case 0x0D:
|
||||
result = regs[addr];
|
||||
shiftRegisterInterrupt = false;
|
||||
timeOfDayAlarmInterrupt = false;
|
||||
underflowTimerInterrupt[0] = false;
|
||||
underflowTimerInterrupt[1] = false;
|
||||
interrupt = false;
|
||||
UpdateInterruptReg();
|
||||
break;
|
||||
// reading this reg clears it
|
||||
result = regs[0x0D];
|
||||
regs[0x0D] = 0x00;
|
||||
return result;
|
||||
default:
|
||||
result = regs[addr];
|
||||
break;
|
||||
return regs[addr];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void TimerTick(int index)
|
||||
{
|
||||
if (timerEnabled[index])
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
timerValue[index]--;
|
||||
}
|
||||
if (timerValue[index] == 0xFFFF)
|
||||
{
|
||||
if (underflowTimerInterruptEnabled[index])
|
||||
{
|
||||
underflowTimerInterrupt[index] = true;
|
||||
interrupt = true;
|
||||
}
|
||||
|
||||
// timer B can count on timer A's underflows
|
||||
if (index == 0)
|
||||
{
|
||||
switch (timerConfig[1])
|
||||
{
|
||||
case 2:
|
||||
case 3:
|
||||
TimerTick(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateInterruptReg()
|
||||
{
|
||||
byte result;
|
||||
result = (byte)(shiftRegisterInterrupt ? 0x01 : 0x00);
|
||||
result |= (byte)(timeOfDayAlarmInterrupt ? 0x02 : 0x00);
|
||||
result |= (byte)(underflowTimerInterrupt[0] ? 0x04 : 0x00);
|
||||
result |= (byte)(underflowTimerInterrupt[1] ? 0x08 : 0x00);
|
||||
result |= (byte)(flagPinInterrupt ? 0x10 : 0x00);
|
||||
result |= (byte)(interrupt ? 0x80 : 0x00);
|
||||
regs[0x0D] = result;
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
bool allowWrite = true;
|
||||
addr &= 0x0F;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
WritePortA(val, regs[0x02]);
|
||||
allowWrite = false;
|
||||
case 0x08:
|
||||
if (regs.ALARM)
|
||||
regs.ALARM10 = val & 0x0F;
|
||||
else
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case 0x01:
|
||||
WritePortB(val, regs[0x03]);
|
||||
allowWrite = false;
|
||||
case 0x09:
|
||||
if (regs.ALARM)
|
||||
regs.ALARMSEC = val & 0x7F;
|
||||
else
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case 0x04:
|
||||
timerValue[0] &= 0xFF00;
|
||||
timerValue[0] |= val;
|
||||
case 0x0A:
|
||||
if (regs.ALARM)
|
||||
regs.ALARMMIN = val & 0x7F;
|
||||
else
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case 0x05:
|
||||
timerValue[0] &= 0xFF;
|
||||
timerValue[0] |= (ushort)(val << 8);
|
||||
break;
|
||||
case 0x06:
|
||||
timerValue[1] &= 0xFF00;
|
||||
timerValue[1] |= val;
|
||||
break;
|
||||
case 0x07:
|
||||
timerValue[1] &= 0xFF;
|
||||
timerValue[1] |= (ushort)(val << 8);
|
||||
case 0x0B:
|
||||
if (regs.ALARM)
|
||||
{
|
||||
regs.ALARMHR = val & 0x1F;
|
||||
regs.ALARMPM = ((val & 0x80) != 0x00);
|
||||
}
|
||||
else
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case 0x0D:
|
||||
if ((val & 0x01) != 0x00)
|
||||
timerInterruptEnabled[0] = ((val & 0x80) != 0x00);
|
||||
if ((val & 0x02) != 0x00)
|
||||
timerInterruptEnabled[1] = ((val & 0x80) != 0x00);
|
||||
if ((val & 0x04) != 0x00)
|
||||
timeOfDayAlarmInterruptEnabled = ((val & 0x80) != 0x00);
|
||||
if ((val & 0x08) != 0x00)
|
||||
shiftRegisterInterruptEnabled = ((val & 0x80) != 0x00);
|
||||
if ((val & 0x10) != 0x00)
|
||||
flagPinInterruptEnabled = ((val & 0x80) != 0x00);
|
||||
allowWrite = false;
|
||||
break;
|
||||
case 0x0E:
|
||||
timerEnabled[0] = ((val & 0x01) != 0x00);
|
||||
timerUnderflowMonitor[0] = ((val & 0x02) != 0x00);
|
||||
generatePositiveEdgeOnUnderflow[0] = ((val & 0x04) != 0x00);
|
||||
stopOnUnderflow[0] = ((val & 0x08) != 0x00);
|
||||
loadStartValue[0] = ((val & 0x10) != 0x00);
|
||||
timerConfig[0] = ((val & 0x20) >> 5);
|
||||
shiftRegisterIsOutput = ((val & 0x40) != 0x00);
|
||||
palMode = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x0F:
|
||||
timerEnabled[1] = ((val & 0x01) != 0x00);
|
||||
timerUnderflowMonitor[1] = ((val & 0x02) != 0x00);
|
||||
generatePositiveEdgeOnUnderflow[1] = ((val & 0x04) != 0x00);
|
||||
stopOnUnderflow[1] = ((val & 0x08) != 0x00);
|
||||
loadStartValue[1] = ((val & 0x10) != 0x00);
|
||||
timerConfig[1] = ((val & 0x60) >> 5);
|
||||
alarmWriteEnabled = ((val & 0x80) != 0x00);
|
||||
intMask &= ~val;
|
||||
if ((val & 0x80) != 0x00)
|
||||
intMask ^= val;
|
||||
break;
|
||||
default:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
|
||||
if (allowWrite)
|
||||
regs[addr] = val;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public class DirectionalDataPort
|
||||
{
|
||||
private int _data;
|
||||
public byte Direction;
|
||||
|
||||
public DirectionalDataPort(byte initData, byte initDirection)
|
||||
{
|
||||
_data = initData;
|
||||
Direction = initDirection;
|
||||
}
|
||||
|
||||
public byte Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return (byte)(_data);
|
||||
}
|
||||
set
|
||||
{
|
||||
_data &= ~Direction;
|
||||
_data |= (value & Direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,8 +64,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
// registers
|
||||
public byte busData;
|
||||
public byte cpu00; // register $00
|
||||
public byte cpu01; // register $01
|
||||
public DirectionalDataPort cpuPort;
|
||||
public bool readTrigger = true;
|
||||
public bool writeTrigger = true;
|
||||
|
||||
|
@ -87,8 +86,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
sid = newSid;
|
||||
cia1 = newCia1;
|
||||
cia2 = newCia2;
|
||||
cpu00 = 0x2F;
|
||||
cpu01 = 0x37;
|
||||
cpuPort = new DirectionalDataPort(0x2F, 0x37);
|
||||
|
||||
layout = new MemoryLayout();
|
||||
UpdateLayout();
|
||||
|
@ -202,11 +200,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
if (addr == 0x0000)
|
||||
{
|
||||
result = cpu00;
|
||||
result = cpuPort.Direction;
|
||||
}
|
||||
else if (addr == 0x0001)
|
||||
{
|
||||
result = cpu01;
|
||||
result = cpuPort.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -268,11 +266,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
if (addr == 0x0000)
|
||||
{
|
||||
result = cpu00;
|
||||
result = cpuPort.Direction;
|
||||
}
|
||||
else if (addr == 0x0001)
|
||||
{
|
||||
result = cpu01;
|
||||
result = cpuPort.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -335,9 +333,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
public void UpdateLayout()
|
||||
{
|
||||
bool loRom = ((cpu01 & 0x01) != 0);
|
||||
bool hiRom = ((cpu01 & 0x02) != 0);
|
||||
bool ioEnable = ((cpu01 & 0x04) != 0);
|
||||
byte cpuData = cpuPort.Data;
|
||||
bool loRom = ((cpuData & 0x01) != 0);
|
||||
bool hiRom = ((cpuData & 0x02) != 0);
|
||||
bool ioEnable = ((cpuData & 0x04) != 0);
|
||||
|
||||
if (loRom && hiRom && exRomPin && gamePin)
|
||||
{
|
||||
|
@ -446,12 +445,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
{
|
||||
if (addr == 0x0000)
|
||||
{
|
||||
cpu00 = val;
|
||||
cpuPort.Direction = val;
|
||||
}
|
||||
else if (addr == 0x0001)
|
||||
{
|
||||
cpu01 &= (byte)(~cpu00);
|
||||
cpu01 |= (byte)(cpu00 & val);
|
||||
cpuPort.Data = val;
|
||||
UpdateLayout();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -44,7 +44,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public int[] MxY = new int[8];
|
||||
public bool[] MxYE = new bool[8];
|
||||
public int RASTER;
|
||||
public int RASTERX;
|
||||
public int RC;
|
||||
public bool RES;
|
||||
public bool RSEL;
|
||||
|
@ -465,11 +464,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public int characterFetchOffset;
|
||||
|
||||
// raster
|
||||
public int[] backgroundColor; // B0C
|
||||
public bool backgroundMode; // ECM
|
||||
public bool bitmapMode; // BMM
|
||||
public int borderBottom;
|
||||
public int borderColor;
|
||||
public int borderLeft;
|
||||
public bool borderOnHorizontal;
|
||||
public bool borderOnVertical;
|
||||
|
@ -479,13 +474,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public int rasterLineLeft;
|
||||
public int rasterOffset;
|
||||
public int rasterOffsetX;
|
||||
public int rasterOffsetY; // RASTER, RST8
|
||||
public int rasterTotalLines;
|
||||
public int rasterWidth;
|
||||
public int renderOffset;
|
||||
public bool resetBit; // RES
|
||||
public bool screenEnabled; // DEN
|
||||
public int verticalScroll; // YSCROLL
|
||||
public int visibleBottom;
|
||||
public int visibleHeight;
|
||||
public int visibleLeft;
|
||||
|
@ -495,9 +486,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public int visibleTop;
|
||||
public int visibleWidth;
|
||||
|
||||
public ChipSignals signal;
|
||||
public Memory mem;
|
||||
public VicIIRegs regs;
|
||||
public ChipSignals signal;
|
||||
|
||||
public VicII(ChipSignals newSignal, VicIIMode videoMode)
|
||||
{
|
||||
|
@ -527,9 +518,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
}
|
||||
|
||||
// initialize raster
|
||||
backgroundColor = new int[4];
|
||||
rasterOffsetX = rasterLineLeft;
|
||||
rasterOffsetY = 0;
|
||||
|
||||
// initialize buffer
|
||||
buffer = new int[rasterWidth * rasterTotalLines];
|
||||
|
@ -547,6 +536,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
public void PerformCycle()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
|
|
Loading…
Reference in New Issue