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 TODMIN; // time of day minute
|
||||
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
|
||||
|
||||
private ChipSignals signal;
|
||||
|
@ -203,6 +208,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public CiaRegs regs;
|
||||
public ChipSignals signal;
|
||||
public bool thisCNT;
|
||||
public int todCounter;
|
||||
public int todFrequency;
|
||||
public bool[] underflow;
|
||||
|
||||
public Func<bool> ReadSerial;
|
||||
|
@ -213,15 +220,86 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
signal = newSignal;
|
||||
ReadSerial = ReadSerialDummy;
|
||||
WriteSerial = WriteSerialDummy;
|
||||
switch (newRegion)
|
||||
{
|
||||
case Region.NTSC:
|
||||
todFrequency = 14318181 / 14 / 10;
|
||||
break;
|
||||
case Region.PAL:
|
||||
todFrequency = 14318181 / 18 / 10;
|
||||
break;
|
||||
}
|
||||
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()
|
||||
{
|
||||
outputBitMask = new byte[] { 0x40, 0x80 };
|
||||
ports = new DirectionalDataPort[2];
|
||||
regs = new CiaRegs(signal);
|
||||
underflow = new bool[2];
|
||||
todCounter = todFrequency;
|
||||
}
|
||||
|
||||
public byte Peek(int addr)
|
||||
|
@ -247,6 +325,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
lastCNT = thisCNT;
|
||||
thisCNT = ReadSerial();
|
||||
|
||||
// process time of day counter
|
||||
todCounter--;
|
||||
if (todCounter <= 0)
|
||||
AdvanceTOD();
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (regs.START[i])
|
||||
|
@ -317,6 +400,26 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
return ports[0].Direction;
|
||||
case 0x03:
|
||||
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:
|
||||
// reading this reg clears it
|
||||
result = regs[0x0D];
|
||||
|
@ -442,7 +545,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
regs.ALARMPM = ((val & 0x80) != 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
regs[addr] = val;
|
||||
}
|
||||
break;
|
||||
case 0x0D:
|
||||
intMask &= ~val;
|
||||
|
|
|
@ -43,9 +43,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public bool[] MxMC = new bool[8]; // sprite multicolor
|
||||
public int[] MxX = new int[8]; // sprite X coordinate
|
||||
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 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 RC; // (internal)
|
||||
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
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (!regs.MxYE[i])
|
||||
regs.MYE[i] = true;
|
||||
regs.MxYEToggle[i] = true;
|
||||
}
|
||||
|
||||
// operations timed to NTSC
|
||||
|
@ -965,19 +967,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
// sprite comparison
|
||||
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)
|
||||
{
|
||||
regs.MDMA[i] = true;
|
||||
regs.MCBASE[i] = 0;
|
||||
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];
|
||||
if (regs.MDMA[i] && regs.MxY[i] == (regs.RASTER & 0xFF))
|
||||
{
|
||||
regs.MD[i] = true;
|
||||
regs.MxXEToggle[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1010,11 +1010,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
{
|
||||
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++)
|
||||
if (regs.MxYE[i])
|
||||
regs.MYE[i] = !regs.MYE[i];
|
||||
regs.MxYEToggle[i] = !regs.MxYEToggle[i];
|
||||
}
|
||||
|
||||
private void PerformVCReset()
|
||||
|
@ -1293,6 +1295,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
if (regs.MxX[j] == rasterOffsetX)
|
||||
{
|
||||
regs.MSRA[j] = true;
|
||||
regs.MxXLatch[j] = rasterOffsetX;
|
||||
}
|
||||
if (regs.MSRA[j])
|
||||
{
|
||||
|
@ -1300,23 +1303,25 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
if (regs.MxMC[j])
|
||||
{
|
||||
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.MSRC[j]--;
|
||||
}
|
||||
regs.MxXEToggle[j] = !regs.MxXEToggle[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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.MSRC[j]--;
|
||||
}
|
||||
regs.MxXEToggle[j] = !regs.MxXEToggle[j];
|
||||
}
|
||||
|
||||
// if not transparent, process collisions and color
|
||||
|
|
Loading…
Reference in New Issue