From bd3912939abbbc0e0d95496091b9f57a61056a3e Mon Sep 17 00:00:00 2001 From: saxxonpike Date: Thu, 15 Nov 2012 20:49:54 +0000 Subject: [PATCH] commodore64: implement serial shift register in CIA chip to prepare for disk drive I/O --- .../Computers/Commodore64/Cia.cs | 71 +++++++++++++++---- .../Computers/Commodore64/Via.cs | 17 +++++ 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/BizHawk.Emulation/Computers/Commodore64/Cia.cs b/BizHawk.Emulation/Computers/Commodore64/Cia.cs index 69f45bb91b..d4beecae76 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Cia.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Cia.cs @@ -13,10 +13,12 @@ namespace BizHawk.Emulation.Computers.Commodore64 public int ALARMMIN; // alarm minutes public bool ALARMPM; // alarm AM/PM public int ALARMSEC; // alarm seconds + public bool CNT; // external counter bit input public bool EIALARM; // enable alarm interrupt (internal) - public bool EIFLAG; // enable flag pin interrupt (internal) + public bool EIFLG; // enable flag pin interrupt (internal) public bool EISP; // enable shift register interrupt (internal) public bool[] EIT = new bool[2]; // enable timer interrupt (internal) + public bool FLG; // external flag bit input public bool IALARM; // alarm interrupt triggered public bool IFLG; // interrupt triggered on FLAG pin public int[] INMODE = new int[2]; // timer input mode @@ -28,9 +30,11 @@ namespace BizHawk.Emulation.Computers.Commodore64 public bool[] PBON = new bool[2]; // port bit modify on public bool[] RUNMODE = new bool[2]; // running mode public int SDR; // serial shift register + public int SDRCOUNT; // serial shift register bit count public bool SPMODE; // shift register mode public bool[] START = new bool[2]; // timer enabled public int[] T = new int[2]; // timer counter + public bool[] TICK = new bool[2]; // execute timer tick public int[] TLATCH = new int[2]; // timer latch (internal) public int TOD10; // time of day 10ths of a second public bool TODIN; // time of day/alarm set @@ -248,7 +252,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 public byte[] outputBitMask; private CiaRegs regs; public ChipSignals signal; - public bool thisCNT; public int todCounter; public int todFrequency; public bool[] underflow; @@ -368,9 +371,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 public void PerformCycle() { - lastCNT = thisCNT; - thisCNT = ReadSerial(); - // process time of day counter todCounter--; if (todCounter <= 0) @@ -407,6 +407,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 } } + lastCNT = regs.CNT; + regs.CNT = false; UpdateInterrupt(); } @@ -487,21 +489,23 @@ namespace BizHawk.Emulation.Computers.Commodore64 switch (regs.INMODE[index]) { case 0: - TimerDec(index); + regs.TICK[index] = true; break; case 1: - if (thisCNT & !lastCNT) - TimerDec(index); + regs.TICK[index] |= (regs.CNT && !lastCNT); break; case 2: - if (underflow[0]) - TimerDec(index); + regs.TICK[index] |= underflow[0]; break; case 3: - if (underflow[0] || (thisCNT & !lastCNT)) - TimerDec(index); + regs.TICK[index] |= (regs.CNT && !lastCNT) || underflow[0]; break; } + if (regs.TICK[index]) + { + TimerDec(index); + regs.TICK[index] = false; + } } public void UpdateInterrupt() @@ -509,7 +513,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 bool irq = false; irq |= (regs.EIT[0] & regs.IT[0]); irq |= (regs.EIT[1] & regs.IT[1]); - irq |= (regs.EIFLAG & regs.IFLG); + irq |= (regs.EIFLG & regs.IFLG); irq |= (regs.EISP & regs.ISP); irq |= (regs.EIALARM & regs.IALARM); regs.IRQ = irq; @@ -581,7 +585,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 regs.EIT[1] = ((intMask & 0x02) != 0x00); regs.EIALARM = ((intMask & 0x04) != 0x00); regs.EISP = ((intMask & 0x08) != 0x00); - regs.EIFLAG = ((intMask & 0x10) != 0x00); + regs.EIFLG = ((intMask & 0x10) != 0x00); UpdateInterrupt(); break; default: @@ -591,6 +595,45 @@ namespace BizHawk.Emulation.Computers.Commodore64 } + public void WriteCNT(bool val) + { + if (!lastCNT && val) + { + if (!regs.SPMODE) + { + // read bit into shift register + bool inputBit = ReadSerial(); + regs.SDR = ((regs.SDR << 1) | (inputBit ? 0x01 : 0x00)) & 0xFF; + + regs.SDRCOUNT = (regs.SDRCOUNT - 1) & 0x7; + if (regs.SDRCOUNT == 0) + { + regs.ISP = true; + } + } + else + { + // write bit out from shift register + bool outputBit = ((regs.SDR & 0x01) != 0); + regs.SDR >>= 1; + WriteSerial(outputBit); + + regs.SDRCOUNT = (regs.SDRCOUNT - 1) & 0x7; + if (regs.SDRCOUNT == 0) + { + regs.ISP = true; + } + } + } + regs.CNT = val; + } + + public void WriteFLG(bool val) + { + regs.FLG = val; + regs.IFLG |= val; + } + private void WriteSerialDummy(bool val) { // do nothing diff --git a/BizHawk.Emulation/Computers/Commodore64/Via.cs b/BizHawk.Emulation/Computers/Commodore64/Via.cs index cfe344f113..6d030b86bc 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Via.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Via.cs @@ -37,6 +37,23 @@ namespace BizHawk.Emulation.Computers.Commodore64 } } + // 0x0: port B + // 0x1: port A + // 0x2: port B data direction + // 0x3: port A data direction + // 0x4: timer lo + // 0x5: timer hi + // 0x6: timer latch lo + // 0x7: timer latch hi + // 0x8: unused + // 0x9: unused + // 0xA: unused + // 0xB: timer control + // 0xC: auxilary control + // 0xD: interrupt status + // 0xE: interrupt control + // 0xF: unused + public class Via { public ViaRegs regs;