commodore64: time of day counter implemented in CIA timer
This commit is contained in:
parent
e95efcb91b
commit
2a4a4bbc57
|
@ -33,6 +33,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
public int TODHR; // time of day hour
|
public int TODHR; // time of day hour
|
||||||
public int TODMIN; // time of day minute
|
public int TODMIN; // time of day minute
|
||||||
public bool TODPM; // time of day AM/PM
|
public bool TODPM; // time of day AM/PM
|
||||||
|
public bool TODREADLATCH; // read latch (internal)
|
||||||
|
public int TODREADLATCH10; // tod read latch (internal)
|
||||||
|
public int TODREADLATCHSEC; // tod read latch (internal)
|
||||||
|
public int TODREADLATCHMIN; // tod read latch (internal)
|
||||||
|
public int TODREADLATCHHR; // tod read latch (internal)
|
||||||
public int TODSEC; // time of day seconds
|
public int TODSEC; // time of day seconds
|
||||||
|
|
||||||
private ChipSignals signal;
|
private ChipSignals signal;
|
||||||
|
@ -203,6 +208,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
public CiaRegs regs;
|
public CiaRegs regs;
|
||||||
public ChipSignals signal;
|
public ChipSignals signal;
|
||||||
public bool thisCNT;
|
public bool thisCNT;
|
||||||
|
public int todCounter;
|
||||||
|
public int todFrequency;
|
||||||
public bool[] underflow;
|
public bool[] underflow;
|
||||||
|
|
||||||
public Func<bool> ReadSerial;
|
public Func<bool> ReadSerial;
|
||||||
|
@ -213,15 +220,86 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
signal = newSignal;
|
signal = newSignal;
|
||||||
ReadSerial = ReadSerialDummy;
|
ReadSerial = ReadSerialDummy;
|
||||||
WriteSerial = WriteSerialDummy;
|
WriteSerial = WriteSerialDummy;
|
||||||
|
switch (newRegion)
|
||||||
|
{
|
||||||
|
case Region.NTSC:
|
||||||
|
todFrequency = 14318181 / 14 / 10;
|
||||||
|
break;
|
||||||
|
case Region.PAL:
|
||||||
|
todFrequency = 14318181 / 18 / 10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
HardReset();
|
HardReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AdvanceTOD()
|
||||||
|
{
|
||||||
|
bool overflow;
|
||||||
|
int tenths = regs.TOD10;
|
||||||
|
int seconds = regs.TODSEC;
|
||||||
|
int minutes = regs.TODMIN;
|
||||||
|
int hours = regs.TODHR;
|
||||||
|
bool ampm = regs.TODPM;
|
||||||
|
todCounter = todFrequency;
|
||||||
|
|
||||||
|
tenths = BCDAdd(tenths, 1, out overflow);
|
||||||
|
if (tenths >= 10)
|
||||||
|
{
|
||||||
|
tenths = 0;
|
||||||
|
seconds = BCDAdd(seconds, 1, out overflow);
|
||||||
|
if (overflow)
|
||||||
|
{
|
||||||
|
seconds = 0;
|
||||||
|
minutes = BCDAdd(minutes, 1, out overflow);
|
||||||
|
if (overflow)
|
||||||
|
{
|
||||||
|
minutes = 0;
|
||||||
|
hours = BCDAdd(hours, 1, out overflow);
|
||||||
|
if (hours > 12)
|
||||||
|
{
|
||||||
|
hours = 1;
|
||||||
|
ampm = !ampm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.TOD10 = tenths;
|
||||||
|
regs.TODSEC = seconds;
|
||||||
|
regs.TODMIN = minutes;
|
||||||
|
regs.TODHR = hours;
|
||||||
|
regs.TODPM = ampm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int BCDAdd(int i, int j, out bool overflow)
|
||||||
|
{
|
||||||
|
int lo;
|
||||||
|
int hi;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
lo = (i & 0x0F) + (j & 0x0F);
|
||||||
|
hi = (i & 0x70) + (j & 0x70);
|
||||||
|
if (lo > 0x09)
|
||||||
|
{
|
||||||
|
hi += 0x10;
|
||||||
|
lo += 0x06;
|
||||||
|
}
|
||||||
|
if (hi > 0x50)
|
||||||
|
{
|
||||||
|
hi += 0xA0;
|
||||||
|
}
|
||||||
|
overflow = hi >= 0x60;
|
||||||
|
result = (hi & 0x70) + (lo & 0x0F);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public void HardReset()
|
public void HardReset()
|
||||||
{
|
{
|
||||||
outputBitMask = new byte[] { 0x40, 0x80 };
|
outputBitMask = new byte[] { 0x40, 0x80 };
|
||||||
ports = new DirectionalDataPort[2];
|
ports = new DirectionalDataPort[2];
|
||||||
regs = new CiaRegs(signal);
|
regs = new CiaRegs(signal);
|
||||||
underflow = new bool[2];
|
underflow = new bool[2];
|
||||||
|
todCounter = todFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Peek(int addr)
|
public byte Peek(int addr)
|
||||||
|
@ -247,6 +325,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
lastCNT = thisCNT;
|
lastCNT = thisCNT;
|
||||||
thisCNT = ReadSerial();
|
thisCNT = ReadSerial();
|
||||||
|
|
||||||
|
// process time of day counter
|
||||||
|
todCounter--;
|
||||||
|
if (todCounter <= 0)
|
||||||
|
AdvanceTOD();
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (regs.START[i])
|
if (regs.START[i])
|
||||||
|
@ -317,6 +400,26 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
return ports[0].Direction;
|
return ports[0].Direction;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
return ports[1].Direction;
|
return ports[1].Direction;
|
||||||
|
case 0x08:
|
||||||
|
regs.TODREADLATCH = false;
|
||||||
|
return (byte)regs.TODREADLATCH10;
|
||||||
|
case 0x09:
|
||||||
|
if (!regs.TODREADLATCH)
|
||||||
|
return regs[addr];
|
||||||
|
else
|
||||||
|
return (byte)regs.TODREADLATCHSEC;
|
||||||
|
case 0x0A:
|
||||||
|
if (!regs.TODREADLATCH)
|
||||||
|
return regs[addr];
|
||||||
|
else
|
||||||
|
return (byte)regs.TODREADLATCHMIN;
|
||||||
|
case 0x0B:
|
||||||
|
regs.TODREADLATCH = true;
|
||||||
|
regs.TODREADLATCH10 = regs.TOD10;
|
||||||
|
regs.TODREADLATCHSEC = regs.TODSEC;
|
||||||
|
regs.TODREADLATCHMIN = regs.TODMIN;
|
||||||
|
regs.TODREADLATCHHR = regs.TODHR;
|
||||||
|
return (byte)regs.TODREADLATCHHR;
|
||||||
case 0x0D:
|
case 0x0D:
|
||||||
// reading this reg clears it
|
// reading this reg clears it
|
||||||
result = regs[0x0D];
|
result = regs[0x0D];
|
||||||
|
@ -442,7 +545,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
regs.ALARMPM = ((val & 0x80) != 0x00);
|
regs.ALARMPM = ((val & 0x80) != 0x00);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
regs[addr] = val;
|
regs[addr] = val;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0D:
|
case 0x0D:
|
||||||
intMask &= ~val;
|
intMask &= ~val;
|
||||||
|
|
|
@ -43,9 +43,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
public bool[] MxMC = new bool[8]; // sprite multicolor
|
public bool[] MxMC = new bool[8]; // sprite multicolor
|
||||||
public int[] MxX = new int[8]; // sprite X coordinate
|
public int[] MxX = new int[8]; // sprite X coordinate
|
||||||
public bool[] MxXE = new bool[8]; // sprite X expansion
|
public bool[] MxXE = new bool[8]; // sprite X expansion
|
||||||
|
public bool[] MxXEToggle = new bool[8]; // (internal)
|
||||||
|
public int[] MxXLatch = new int[8]; // (internal)
|
||||||
public int[] MxY = new int[8]; // sprite Y coordinate
|
public int[] MxY = new int[8]; // sprite Y coordinate
|
||||||
public bool[] MxYE = new bool[8]; // sprite Y expansion
|
public bool[] MxYE = new bool[8]; // sprite Y expansion
|
||||||
public bool[] MYE = new bool[8]; // (internal)
|
public bool[] MxYEToggle = new bool[8]; // (internal)
|
||||||
public int RASTER; // current raster line
|
public int RASTER; // current raster line
|
||||||
public int RC; // (internal)
|
public int RC; // (internal)
|
||||||
public bool RES; // reset bit (does nothing in this version of the VIC)
|
public bool RES; // reset bit (does nothing in this version of the VIC)
|
||||||
|
@ -705,7 +707,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
// sprite Y stretch flipflop
|
// sprite Y stretch flipflop
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
if (!regs.MxYE[i])
|
if (!regs.MxYE[i])
|
||||||
regs.MYE[i] = true;
|
regs.MxYEToggle[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// operations timed to NTSC
|
// operations timed to NTSC
|
||||||
|
@ -965,19 +967,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
// sprite comparison
|
// sprite comparison
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (regs.MYE[i] && regs.MCBASE[i] == 63)
|
|
||||||
{
|
|
||||||
regs.MD[i] = false;
|
|
||||||
regs.MDMA[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (regs.MxE[i] == true && regs.MxY[i] == (regs.RASTER & 0xFF) && regs.MDMA[i] == false)
|
if (regs.MxE[i] == true && regs.MxY[i] == (regs.RASTER & 0xFF) && regs.MDMA[i] == false)
|
||||||
{
|
{
|
||||||
regs.MDMA[i] = true;
|
regs.MDMA[i] = true;
|
||||||
regs.MCBASE[i] = 0;
|
regs.MCBASE[i] = 0;
|
||||||
if (regs.MxYE[i])
|
if (regs.MxYE[i])
|
||||||
regs.MYE[i] = false;
|
regs.MxYEToggle[i] = false;
|
||||||
}
|
}
|
||||||
|
regs.MxXEToggle[i] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,7 +999,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
regs.MC[i] = regs.MCBASE[i];
|
regs.MC[i] = regs.MCBASE[i];
|
||||||
if (regs.MDMA[i] && regs.MxY[i] == (regs.RASTER & 0xFF))
|
if (regs.MDMA[i] && regs.MxY[i] == (regs.RASTER & 0xFF))
|
||||||
|
{
|
||||||
regs.MD[i] = true;
|
regs.MD[i] = true;
|
||||||
|
regs.MxXEToggle[i] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,11 +1010,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (regs.MYE[i])
|
if (regs.MxYEToggle[i])
|
||||||
{
|
{
|
||||||
if (regs.MD[i])
|
regs.MCBASE[i] += 3;
|
||||||
|
if (regs.MxYEToggle[i] && regs.MCBASE[i] == 63)
|
||||||
{
|
{
|
||||||
regs.MCBASE[i] += 3;
|
regs.MD[i] = false;
|
||||||
|
regs.MDMA[i] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1040,7 +1042,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
if (regs.MxYE[i])
|
if (regs.MxYE[i])
|
||||||
regs.MYE[i] = !regs.MYE[i];
|
regs.MxYEToggle[i] = !regs.MxYEToggle[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PerformVCReset()
|
private void PerformVCReset()
|
||||||
|
@ -1293,6 +1295,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
if (regs.MxX[j] == rasterOffsetX)
|
if (regs.MxX[j] == rasterOffsetX)
|
||||||
{
|
{
|
||||||
regs.MSRA[j] = true;
|
regs.MSRA[j] = true;
|
||||||
|
regs.MxXLatch[j] = rasterOffsetX;
|
||||||
}
|
}
|
||||||
if (regs.MSRA[j])
|
if (regs.MSRA[j])
|
||||||
{
|
{
|
||||||
|
@ -1300,23 +1303,25 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
if (regs.MxMC[j])
|
if (regs.MxMC[j])
|
||||||
{
|
{
|
||||||
spriteBits = (int)((regs.MSR[j] >> 22) & 0x3);
|
spriteBits = (int)((regs.MSR[j] >> 22) & 0x3);
|
||||||
if ((rasterOffsetX & 0x1) != (regs.MxX[j] & 0x1))
|
if ((rasterOffsetX & 0x1) != (regs.MxXLatch[j] & 0x1))
|
||||||
{
|
{
|
||||||
if ((!regs.MxXE[j]) || ((rasterOffsetX & 0x2) != (regs.MxX[j] & 0x2)))
|
if (!regs.MxXE[j] || regs.MxXEToggle[j])
|
||||||
{
|
{
|
||||||
regs.MSR[j] <<= 2;
|
regs.MSR[j] <<= 2;
|
||||||
regs.MSRC[j]--;
|
regs.MSRC[j]--;
|
||||||
}
|
}
|
||||||
|
regs.MxXEToggle[j] = !regs.MxXEToggle[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spriteBits = (int)((regs.MSR[j] >> 22) & 0x2);
|
spriteBits = (int)((regs.MSR[j] >> 22) & 0x2);
|
||||||
if ((!regs.MxXE[j]) || ((rasterOffsetX & 0x1) != (regs.MxX[j] & 0x1)))
|
if (!regs.MxXE[j] || regs.MxXEToggle[j])
|
||||||
{
|
{
|
||||||
regs.MSR[j] <<= 1;
|
regs.MSR[j] <<= 1;
|
||||||
regs.MSRC[j]--;
|
regs.MSRC[j]--;
|
||||||
}
|
}
|
||||||
|
regs.MxXEToggle[j] = !regs.MxXEToggle[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
// if not transparent, process collisions and color
|
// if not transparent, process collisions and color
|
||||||
|
|
Loading…
Reference in New Issue