C64: Implement more CIA features and CIA/VIA defaults.

This commit is contained in:
SaxxonPike 2019-07-04 00:31:48 -05:00
parent 32d59e8514
commit 2dd80eb0f4
7 changed files with 420 additions and 424 deletions

View File

@ -28,7 +28,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
private int Cia1_ReadPortB()
{
return 0xFF;
// Ordinarily these are connected to the userport.
return 0x00;
}
private int Cpu_ReadPort()
@ -111,16 +112,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
private bool SerPort_ReadAtnOut()
{
// inverted PA3 (input NOT pulled up)
return !((Cia1.DdrA & 0x08) != 0 && (Cia1.PrA & 0x08) != 0);
}
private bool SerPort_ReadClockOut()
{
// inverted PA4 (input NOT pulled up)
return !((Cia1.DdrA & 0x10) != 0 && (Cia1.PrA & 0x10) != 0);
}
private bool SerPort_ReadDataOut()
{
// inverted PA5 (input NOT pulled up)
return !((Cia1.DdrA & 0x20) != 0 && (Cia1.PrA & 0x20) != 0);
}

View File

@ -9,27 +9,27 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
// * A low RES pin is emulated via HardReset().
public static class Chip6526
{
public static Cia Create(C64.CiaType type, Func<int> readIec)
public static Cia Create(C64.CiaType type, Func<int> readIec, Func<int> readUserPort)
{
switch (type)
{
case C64.CiaType.Ntsc:
return new Cia(14318181, 14 * 60, readIec)
return new Cia(14318181, 14 * 60, readIec, readUserPort)
{
DelayedInterrupts = true
};
case C64.CiaType.NtscRevA:
return new Cia(14318181, 14 * 60, readIec)
return new Cia(14318181, 14 * 60, readIec, readUserPort)
{
DelayedInterrupts = false
};
case C64.CiaType.Pal:
return new Cia(17734472, 18 * 50, readIec)
return new Cia(17734472, 18 * 50, readIec, readUserPort)
{
DelayedInterrupts = true
};
case C64.CiaType.PalRevA:
return new Cia(17734472, 18 * 50, readIec)
return new Cia(17734472, 18 * 50, readIec, readUserPort)
{
DelayedInterrupts = false
};

View File

@ -131,10 +131,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private sealed class IecPort : IPort
{
private readonly Func<int> _readIec;
private readonly Func<int> _readUserPort;
public IecPort(Func<int> readIec)
public IecPort(Func<int> readIec, Func<int> readUserPort)
{
_readIec = readIec;
_readUserPort = readUserPort;
}
public int ReadPra(int pra, int ddra, int prb, int ddrb)
@ -144,7 +146,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public int ReadPrb(int pra, int ddra, int prb, int ddrb)
{
return (prb | ~ddrb) & 0xFF;
return (prb | ~ddrb) | (~ddrb & _readUserPort());
}
}
}

View File

@ -252,15 +252,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
case 0xE:
_hasNewCra = true;
_newCra = val;
_taCntPhi2 = ((val & 0x20) == 0);
_taCntCnt = ((val & 0x20) == 0x20);
_taCntPhi2 = (val & 0x20) == 0;
_taCntCnt = (val & 0x20) == 0x20;
break;
case 0xF:
_hasNewCrb = true;
_newCrb = val;
_tbCntPhi2 = ((val & 0x60) == 0);
_tbCntTa = ((val & 0x40) == 0x40);
_tbCntCnt = ((val & 0x20) == 0x20);
_tbCntPhi2 = (val & 0x60) == 0;
_tbCntCnt = (val & 0x60) == 0x20;
_tbCntTa = (val & 0x60) == 0x40;
_tbCntTaCnt = (val & 0x60) == 0x60;
break;
}
}

View File

@ -33,6 +33,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
}
public Func<bool> ReadFlag = () => true;
public Func<bool> ReadCnt = () => true;
public Func<bool> ReadSp = () => true;
public bool DelayedInterrupts = true;
private int _pra;
@ -79,6 +81,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private bool _flagLatch;
private bool _flagInput;
private bool _taUnderflow;
private bool _lastCnt;
private bool _thisCnt;
private bool _tbCntTaCnt;
private readonly IPort _port;
private int _todlo;
@ -98,9 +103,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_port = new JoystickKeyboardPort(joysticks, keyboard);
}
public Cia(int todNum, int todDen, Func<int> readIec) : this(todNum, todDen)
public Cia(int todNum, int todDen, Func<int> readIec, Func<int> readUserPort) : this(todNum, todDen)
{
_port = new IecPort(readIec);
_port = new IecPort(readIec, readUserPort);
}
public void HardReset()
@ -136,6 +141,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_tbIrqNextCycle = false;
_taState = TimerState.Stop;
_tbState = TimerState.Stop;
_lastCnt = true;
}
private void CheckIrqs()
@ -145,7 +151,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_taIrqNextCycle = false;
TriggerInterrupt(1);
}
if (_tbIrqNextCycle)
{
_tbIrqNextCycle = false;
@ -155,6 +160,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void ExecutePhase()
{
_thisCnt = ReadCnt();
_taUnderflow = false;
if (DelayedInterrupts)
{
@ -166,13 +172,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_prb &= 0xBF;
_taPrb6NegativeNextCycle = false;
}
if (_tbPrb7NegativeNextCycle)
{
_prb &= 0x7F;
_tbPrb7NegativeNextCycle = false;
}
switch (_taState)
{
case TimerState.WaitThenCount:
@ -203,7 +209,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
_ta = _latcha;
}
Ta_Idle();
break;
case TimerState.Count:
@ -244,7 +249,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
_tb = _latchb;
}
Tb_Idle();
break;
case TimerState.Count:
@ -271,7 +275,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
TriggerInterrupt(16);
}
_flagLatch = _flagInput;
if (!DelayedInterrupts)
@ -280,19 +283,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
}
if ((_cra & 0x02) != 0)
{
_ddra |= 0x40;
}
if ((_crb & 0x02) != 0)
{
_ddrb |= 0x80;
}
_lastCnt = _thisCnt;
}
private void Ta_Count()
{
if (_taCntPhi2)
if (_taCntPhi2 || (_taCntCnt && !_lastCnt && _thisCnt))
{
if (_ta <= 0 || --_ta == 0)
{
@ -300,11 +300,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
Ta_Interrupt();
}
_taUnderflow = true;
}
}
Ta_Idle();
}
@ -336,7 +334,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
_prb ^= 0x40;
}
_ddrb |= 0x40;
}
}
@ -362,7 +359,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_taState = TimerState.LoadThenStop;
}
}
break;
case TimerState.Count:
if ((_newCra & 0x01) != 0)
@ -378,7 +374,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
? TimerState.LoadThenStop
: TimerState.CountThenStop;
}
break;
case TimerState.LoadThenCount:
case TimerState.WaitThenCount:
@ -398,10 +393,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
_taState = TimerState.Stop;
}
break;
}
_cra = _newCra & 0xEF;
_hasNewCra = false;
}
@ -409,7 +402,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private void Tb_Count()
{
if (_tbCntPhi2 || (_tbCntTa && _taUnderflow))
if (_tbCntPhi2 || (_tbCntTa && _taUnderflow) || (_tbCntTaCnt && _taUnderflow && _thisCnt) || (_tbCntCnt && !_lastCnt && _thisCnt))
{
if (_tb <= 0 || --_tb == 0)
{
@ -419,7 +412,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
}
}
}
Tb_Idle();
}
@ -475,7 +467,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_tbState = TimerState.LoadThenStop;
}
}
break;
case TimerState.Count:
if ((_newCrb & 0x01) != 0)
@ -491,7 +482,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
? TimerState.LoadThenStop
: TimerState.CountThenStop;
}
break;
case TimerState.LoadThenCount:
case TimerState.WaitThenCount:
@ -511,10 +501,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
_tbState = TimerState.Stop;
}
break;
}
_crb = _newCrb & 0xEF;
_hasNewCrb = false;
}
@ -523,11 +511,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private void TriggerInterrupt(int bit)
{
_icr |= bit;
if ((_intMask & bit) == 0)
{
return;
}
if ((_intMask & bit) == 0) return;
_icr |= 0x80;
}
@ -578,6 +562,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
ser.Sync(nameof(_flagLatch), ref _flagLatch);
ser.Sync(nameof(_todCounter), ref _todCounter);
ser.Sync(nameof(_lastCnt), ref _lastCnt);
ser.Sync(nameof(_thisCnt), ref _thisCnt);
}
}
}

View File

@ -110,11 +110,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_prb = 0;
_ddra = 0;
_ddrb = 0;
_t1C = 0;
_t1L = 0;
_t2C = 0;
_t2L = 0;
_sr = 0;
_t1C = 0xFFFF;
_t1L = 0xFFFF;
_t2C = 0xFFFF;
_t2L = 0xFFFF;
_sr = 0xFF;
_acr = 0;
_pcr = 0;
_ifr = 0;

View File

@ -163,8 +163,11 @@
public override bool ReadDeviceData()
{
// PB1 (input not pulled up)
var viaOutputData = (Via0.DdrB & 0x02) != 0 && (Via0.PrB & 0x02) != 0;
// inverted from c64, input, not pulled up to PB7/CA1
var viaInputAtn = ViaReadAtn();
// PB4 (input not pulled up)
var viaOutputAtna = (Via0.DdrB & 0x10) != 0 && (Via0.PrB & 0x10) != 0;
return !(viaOutputAtna ^ viaInputAtn) && !viaOutputData;