From 821553cda872f2255edd473d34cc914a480afec7 Mon Sep 17 00:00:00 2001 From: saxxonpike Date: Mon, 5 Nov 2012 14:24:01 +0000 Subject: [PATCH] c64- VIC register class --- .../Computers/Commodore64/C64.core.cs | 23 +- .../Computers/Commodore64/C64.cs | 4 +- .../Computers/Commodore64/VicII.cs | 887 ++++++++++-------- 3 files changed, 499 insertions(+), 415 deletions(-) diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.core.cs b/BizHawk.Emulation/Computers/Commodore64/C64.core.cs index 58970b9cfd..457228098d 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.core.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.core.cs @@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 public Memory mem; public Sid sid; public VicII vic; - public VicSignals vicSignal; + public ChipSignals signal; private void HardReset() { @@ -35,8 +35,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 cia2 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort); // initialize vic - vicSignal = new VicSignals(); - vic = new VicII(vicSignal, VicIIMode.NTSC); + signal = new ChipSignals(); + vic = new VicII(signal, VicIIMode.NTSC); // initialize sid sid = new Sid(); @@ -88,4 +88,21 @@ namespace BizHawk.Emulation.Computers.Commodore64 mem.Write(addr, value); } } + + public class ChipSignals + { + private bool[] _CiaIRQOutput = new bool[2]; + private bool _VicAECOutput; + private bool _VicBAOutput; + private bool _VicIRQOutput; + private bool _VicLPInput; + + public bool CpuAEC { get { return _VicAECOutput; } } + public bool CpuIRQ { get { return _VicIRQOutput | _CiaIRQOutput[0] | _CiaIRQOutput[1]; } } + public bool CpuRDY { get { return _VicBAOutput; } } + public bool VicAEC { get { return _VicAECOutput; } set { _VicAECOutput = value; } } + public bool VicBA { get { return _VicBAOutput; } set { _VicBAOutput = value; } } + public bool VicIRQ { get { return _VicIRQOutput; } set { _VicIRQOutput = value; } } + public bool VicLP { get { return _VicLPInput; } } + } } diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.cs b/BizHawk.Emulation/Computers/Commodore64/C64.cs index dbfbeaa56a..76c2dcfb9f 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.cs @@ -92,11 +92,11 @@ namespace BizHawk.Emulation.Computers.Commodore64 for (int i = 0; i < cyclesPerSecond; i++) { - if (vicSignal.Interrupt || cia1.interrupt || cia2.interrupt) + if (signal.CpuIRQ) { cpu.IRQ = true; } - if (vicSignal.AllowCpu) + if (signal.CpuRDY) { cpu.ExecuteOne(); } diff --git a/BizHawk.Emulation/Computers/Commodore64/VicII.cs b/BizHawk.Emulation/Computers/Commodore64/VicII.cs index 37796dad12..df38136f7b 100644 --- a/BizHawk.Emulation/Computers/Commodore64/VicII.cs +++ b/BizHawk.Emulation/Computers/Commodore64/VicII.cs @@ -11,6 +11,429 @@ namespace BizHawk.Emulation.Computers.Commodore64 PAL } + public class VicIIRegs + { + public bool BMM; + public int[] BxC = new int[4]; + public int CB; + public bool CSEL; + public bool DEN; + public int EC; + public bool ECM; + public bool ELP; + public bool EMBC; + public bool EMMC; + public bool ERST; + public bool ILP; + public bool IMBC; + public bool IMMC; + public bool IRQ; + public bool IRST; + public int LPX; + public int LPY; + public bool MCM; + public int[] MMx = new int[2]; + public int[] MxC = new int[8]; + public bool[] MxD = new bool[8]; + public bool[] MxDP = new bool[8]; + public bool[] MxE = new bool[8]; + public bool[] MxM = new bool[8]; + public bool[] MxMC = new bool[8]; + public int[] MxX = new int[8]; + public bool[] MxXE = new bool[8]; + 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; + public int VC; + public int VCBASE; + public int VM; + public int VMLI; + public int XSCROLL; + public int YSCROLL; + + public VicIIRegs() + { + // power on state + + this[0x16] = 0xC0; + this[0x18] = 0x01; + this[0x19] = 0x71; + this[0x1A] = 0xF0; + } + + public byte this[int addr] + { + get + { + int result = 0xFF; // value for any open bits + addr &= 0x3F; + + switch (addr) + { + case 0x00: + case 0x02: + case 0x04: + case 0x06: + case 0x08: + case 0x0A: + case 0x0C: + case 0x0E: + result = MxX[addr >> 1]; + break; + case 0x01: + case 0x03: + case 0x05: + case 0x07: + case 0x09: + case 0x0B: + case 0x0D: + case 0x0F: + result = MxY[addr >> 1]; + break; + case 0x10: + result = ((MxX[0] & 0x100) != 0) ? 0x01 : 0x00; + result |= ((MxX[1] & 0x100) != 0) ? 0x02 : 0x00; + result |= ((MxX[2] & 0x100) != 0) ? 0x04 : 0x00; + result |= ((MxX[3] & 0x100) != 0) ? 0x08 : 0x00; + result |= ((MxX[4] & 0x100) != 0) ? 0x10 : 0x00; + result |= ((MxX[5] & 0x100) != 0) ? 0x20 : 0x00; + result |= ((MxX[6] & 0x100) != 0) ? 0x40 : 0x00; + result |= ((MxX[7] & 0x100) != 0) ? 0x80 : 0x00; + break; + case 0x11: + result = YSCROLL & 0x07; + result |= (RSEL ? 0x08 : 0x00); + result |= (DEN ? 0x10 : 0x00); + result |= (BMM ? 0x20 : 0x00); + result |= (ECM ? 0x40 : 0x00); + result |= ((RASTER & 0x100) >> 1); + break; + case 0x12: + result = RASTER & 0xFF; + break; + case 0x13: + result = LPX; + break; + case 0x14: + result = LPY; + break; + case 0x15: + result = (MxE[0] ? 0x01 : 0x00); + result |= (MxE[1] ? 0x02 : 0x00); + result |= (MxE[2] ? 0x04 : 0x00); + result |= (MxE[3] ? 0x08 : 0x00); + result |= (MxE[4] ? 0x10 : 0x00); + result |= (MxE[5] ? 0x20 : 0x00); + result |= (MxE[6] ? 0x40 : 0x00); + result |= (MxE[7] ? 0x80 : 0x00); + break; + case 0x16: + result &= 0xBF; + result |= XSCROLL & 0x07; + result |= (CSEL ? 0x08 : 0x00); + result |= (MCM ? 0x10 : 0x00); + result |= (RES ? 0x20 : 0x00); + break; + case 0x17: + result = (MxYE[0] ? 0x01 : 0x00); + result |= (MxYE[1] ? 0x02 : 0x00); + result |= (MxYE[2] ? 0x04 : 0x00); + result |= (MxYE[3] ? 0x08 : 0x00); + result |= (MxYE[4] ? 0x10 : 0x00); + result |= (MxYE[5] ? 0x20 : 0x00); + result |= (MxYE[6] ? 0x40 : 0x00); + result |= (MxYE[7] ? 0x80 : 0x00); + break; + case 0x18: + result &= 0x01; + result |= (CB & 0x07) << 1; + result |= (VM & 0x0F) << 4; + break; + case 0x19: + result &= 0x70; + result |= (IRST ? 0x01 : 0x00); + result |= (IMBC ? 0x02 : 0x00); + result |= (IMMC ? 0x04 : 0x00); + result |= (ILP ? 0x08 : 0x00); + result |= (IRQ ? 0x80 : 0x00); + break; + case 0x1A: + result &= 0xF0; + result |= (ERST ? 0x01 : 0x00); + result |= (EMBC ? 0x02 : 0x00); + result |= (EMMC ? 0x04 : 0x00); + result |= (ELP ? 0x08 : 0x00); + break; + case 0x1B: + result = (MxDP[0] ? 0x01 : 0x00); + result |= (MxDP[1] ? 0x02 : 0x00); + result |= (MxDP[2] ? 0x04 : 0x00); + result |= (MxDP[3] ? 0x08 : 0x00); + result |= (MxDP[4] ? 0x10 : 0x00); + result |= (MxDP[5] ? 0x20 : 0x00); + result |= (MxDP[6] ? 0x40 : 0x00); + result |= (MxDP[7] ? 0x80 : 0x00); + break; + case 0x1C: + result = (MxMC[0] ? 0x01 : 0x00); + result |= (MxMC[1] ? 0x02 : 0x00); + result |= (MxMC[2] ? 0x04 : 0x00); + result |= (MxMC[3] ? 0x08 : 0x00); + result |= (MxMC[4] ? 0x10 : 0x00); + result |= (MxMC[5] ? 0x20 : 0x00); + result |= (MxMC[6] ? 0x40 : 0x00); + result |= (MxMC[7] ? 0x80 : 0x00); + break; + case 0x1D: + result = (MxXE[0] ? 0x01 : 0x00); + result |= (MxXE[1] ? 0x02 : 0x00); + result |= (MxXE[2] ? 0x04 : 0x00); + result |= (MxXE[3] ? 0x08 : 0x00); + result |= (MxXE[4] ? 0x10 : 0x00); + result |= (MxXE[5] ? 0x20 : 0x00); + result |= (MxXE[6] ? 0x40 : 0x00); + result |= (MxXE[7] ? 0x80 : 0x00); + break; + case 0x1E: + result = (MxM[0] ? 0x01 : 0x00); + result |= (MxM[1] ? 0x02 : 0x00); + result |= (MxM[2] ? 0x04 : 0x00); + result |= (MxM[3] ? 0x08 : 0x00); + result |= (MxM[4] ? 0x10 : 0x00); + result |= (MxM[5] ? 0x20 : 0x00); + result |= (MxM[6] ? 0x40 : 0x00); + result |= (MxM[7] ? 0x80 : 0x00); + break; + case 0x1F: + result = (MxD[0] ? 0x01 : 0x00); + result |= (MxD[1] ? 0x02 : 0x00); + result |= (MxD[2] ? 0x04 : 0x00); + result |= (MxD[3] ? 0x08 : 0x00); + result |= (MxD[4] ? 0x10 : 0x00); + result |= (MxD[5] ? 0x20 : 0x00); + result |= (MxD[6] ? 0x40 : 0x00); + result |= (MxD[7] ? 0x80 : 0x00); + break; + case 0x20: + result &= 0xF0; + result |= EC & 0x0F; + break; + case 0x21: + case 0x22: + case 0x23: + case 0x24: + result &= 0xF0; + result |= BxC[addr - 0x21] & 0x0F; + break; + case 0x25: + case 0x26: + result &= 0xF0; + result |= MMx[addr - 0x25] & 0x0F; + break; + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + result &= 0xF0; + result |= MxC[addr - 0x27] & 0x0F; + break; + default: + result = 0xFF; + break; + } + + return (byte)(result); + } + set + { + int index; + int val = value; + addr &= 0x3F; + + switch (addr) + { + case 0x00: + case 0x02: + case 0x04: + case 0x06: + case 0x08: + case 0x0A: + case 0x0C: + case 0x0E: + index = addr >> 1; + MxX[index] &= 0x100; + MxX[index] |= (val & 0xFF); + break; + case 0x01: + case 0x03: + case 0x05: + case 0x07: + case 0x09: + case 0x0B: + case 0x0D: + case 0x0F: + index = addr >> 1; + MxY[index] &= 0x100; + MxY[index] |= (val & 0xFF); + break; + case 0x10: + MxX[0] = (MxX[0] & 0xFF) | ((val & 0x01) << 8); + MxX[1] = (MxX[1] & 0xFF) | ((val & 0x02) << 7); + MxX[2] = (MxX[2] & 0xFF) | ((val & 0x04) << 6); + MxX[3] = (MxX[3] & 0xFF) | ((val & 0x08) << 5); + MxX[4] = (MxX[4] & 0xFF) | ((val & 0x10) << 4); + MxX[5] = (MxX[5] & 0xFF) | ((val & 0x20) << 3); + MxX[6] = (MxX[6] & 0xFF) | ((val & 0x40) << 2); + MxX[7] = (MxX[7] & 0xFF) | ((val & 0x80) << 1); + break; + case 0x11: + YSCROLL = (val & 0x07); + RSEL = ((val & 0x08) != 0x00); + DEN = ((val & 0x10) != 0x00); + BMM = ((val & 0x20) != 0x00); + ECM = ((val & 0x40) != 0x00); + RASTER &= 0xFF; + RASTER |= ((val & 0x80) << 1); + break; + case 0x12: + RASTER &= 0x100; + RASTER |= (val & 0xFF); + break; + case 0x13: + LPX = (val & 0xFF); + break; + case 0x14: + LPY = (val & 0xFF); + break; + case 0x15: + MxE[0] = ((val & 0x01) != 0x00); + MxE[1] = ((val & 0x02) != 0x00); + MxE[2] = ((val & 0x04) != 0x00); + MxE[3] = ((val & 0x08) != 0x00); + MxE[4] = ((val & 0x10) != 0x00); + MxE[5] = ((val & 0x20) != 0x00); + MxE[6] = ((val & 0x40) != 0x00); + MxE[7] = ((val & 0x80) != 0x00); + break; + case 0x16: + XSCROLL = (val & 0x07); + CSEL = ((val & 0x08) != 0x00); + MCM = ((val & 0x10) != 0x00); + RES = ((val & 0x20) != 0x00); + break; + case 0x17: + MxYE[0] = ((val & 0x01) != 0x00); + MxYE[1] = ((val & 0x02) != 0x00); + MxYE[2] = ((val & 0x04) != 0x00); + MxYE[3] = ((val & 0x08) != 0x00); + MxYE[4] = ((val & 0x10) != 0x00); + MxYE[5] = ((val & 0x20) != 0x00); + MxYE[6] = ((val & 0x40) != 0x00); + MxYE[7] = ((val & 0x80) != 0x00); + break; + case 0x18: + CB = (val & 0x0E) >> 1; + VM = (val & 0xF0) >> 4; + break; + case 0x19: + IRST = ((val & 0x01) != 0x00); + IMBC = ((val & 0x02) != 0x00); + IMMC = ((val & 0x04) != 0x00); + ILP = ((val & 0x08) != 0x00); + IRQ = ((val & 0x80) != 0x00); + break; + case 0x1A: + ERST = ((val & 0x01) != 0x00); + EMBC = ((val & 0x02) != 0x00); + EMMC = ((val & 0x04) != 0x00); + ELP = ((val & 0x08) != 0x00); + break; + case 0x1B: + MxDP[0] = ((val & 0x01) != 0x00); + MxDP[1] = ((val & 0x02) != 0x00); + MxDP[2] = ((val & 0x04) != 0x00); + MxDP[3] = ((val & 0x08) != 0x00); + MxDP[4] = ((val & 0x10) != 0x00); + MxDP[5] = ((val & 0x20) != 0x00); + MxDP[6] = ((val & 0x40) != 0x00); + MxDP[7] = ((val & 0x80) != 0x00); + break; + case 0x1C: + MxMC[0] = ((val & 0x01) != 0x00); + MxMC[1] = ((val & 0x02) != 0x00); + MxMC[2] = ((val & 0x04) != 0x00); + MxMC[3] = ((val & 0x08) != 0x00); + MxMC[4] = ((val & 0x10) != 0x00); + MxMC[5] = ((val & 0x20) != 0x00); + MxMC[6] = ((val & 0x40) != 0x00); + MxMC[7] = ((val & 0x80) != 0x00); + break; + case 0x1D: + MxXE[0] = ((val & 0x01) != 0x00); + MxXE[1] = ((val & 0x02) != 0x00); + MxXE[2] = ((val & 0x04) != 0x00); + MxXE[3] = ((val & 0x08) != 0x00); + MxXE[4] = ((val & 0x10) != 0x00); + MxXE[5] = ((val & 0x20) != 0x00); + MxXE[6] = ((val & 0x40) != 0x00); + MxXE[7] = ((val & 0x80) != 0x00); + break; + case 0x1E: + MxM[0] = ((val & 0x01) != 0x00); + MxM[1] = ((val & 0x02) != 0x00); + MxM[2] = ((val & 0x04) != 0x00); + MxM[3] = ((val & 0x08) != 0x00); + MxM[4] = ((val & 0x10) != 0x00); + MxM[5] = ((val & 0x20) != 0x00); + MxM[6] = ((val & 0x40) != 0x00); + MxM[7] = ((val & 0x80) != 0x00); + break; + case 0x1F: + MxD[0] = ((val & 0x01) != 0x00); + MxD[1] = ((val & 0x02) != 0x00); + MxD[2] = ((val & 0x04) != 0x00); + MxD[3] = ((val & 0x08) != 0x00); + MxD[4] = ((val & 0x10) != 0x00); + MxD[5] = ((val & 0x20) != 0x00); + MxD[6] = ((val & 0x40) != 0x00); + MxD[7] = ((val & 0x80) != 0x00); + break; + case 0x20: + EC = (val & 0x0F); + break; + case 0x21: + case 0x22: + case 0x23: + case 0x24: + BxC[addr - 0x21] = val & 0x0F; + break; + case 0x25: + case 0x26: + MMx[addr - 0x25] = val & 0x0F; + break; + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + MxC[addr - 0x27] = val & 0x0F; + break; + } + } + } + } + public class VicII { // buffer @@ -38,30 +461,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 Colors.ARGB(0x95, 0x95, 0x95) }; - // interrupts - public bool interrupt = true; - public bool lightPenInterrupt = true; - public bool lightPenInterruptEnabled; - public bool rasterInterrupt = true; - public bool rasterInterruptEnabled; - public bool spriteBackgroundInterrupt = true; - public bool spriteBackgroundInterruptEnabled; - public bool spriteSpriteInterrupt = true; - public bool spriteSpriteInterruptEnabled; - // memory - public bool characterFetch; public int characterFetchOffset; - public int characterMemoryOffset; - public byte[] charBuffer; - public int charBufferOffset; - public bool fetching; - public int fetchOffsetX; - public int screenMemoryOffset; - - // lightpen - public int lightPenX; // LPX - public int lightPenY; // LPY // raster public int[] backgroundColor; // B0C @@ -74,10 +475,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 public bool borderOnVertical; public int borderRight; public int borderTop; - public bool extendHeight; // RSEL - public bool extendWidth; // CSEL - public int horizontalScroll; // XSCROLL - public bool multiColorMode; // MCM public int rasterInterruptLine; public int rasterLineLeft; public int rasterOffset; @@ -98,26 +495,13 @@ namespace BizHawk.Emulation.Computers.Commodore64 public int visibleTop; public int visibleWidth; - // sprites - public bool[] spriteBackgroundCollision; // M0D - public bool[] spriteCollision; // M0M - public int[] spriteColor; // M0C - public bool[] spriteEnabled; // M0E - public int[] spriteExtraColor; // MM0 - public bool[] spriteMultiColor; // M0MC - public bool[] spritePriority; // M0DP - public bool[] spriteStretchHorizontal; // M0XE - public bool[] spriteStretchVertical; // M0YE - public int[] spriteX; // M0X, M0X8 - public int[] spriteY; // M0Y - - public VicSignals cpuSignal; + public ChipSignals signal; public Memory mem; - public byte[] regs; + public VicIIRegs regs; - public VicII(VicSignals signals, VicIIMode videoMode) + public VicII(ChipSignals newSignal, VicIIMode videoMode) { - cpuSignal = signals; + signal = newSignal; switch (videoMode) { @@ -134,10 +518,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 visibleWidth = 418; visibleHeight = 217; renderOffset = 0; - borderLeft = 0x018; - borderRight = 0x158; - borderTop = 0x033; - borderBottom = 0x0FA; characterFetchOffset = rasterWidth - 3; break; case VicIIMode.PAL: @@ -148,23 +528,9 @@ namespace BizHawk.Emulation.Computers.Commodore64 // initialize raster backgroundColor = new int[4]; - charBuffer = new byte[40]; rasterOffsetX = rasterLineLeft; rasterOffsetY = 0; - // initialize sprites - spriteBackgroundCollision = new bool[8]; - spriteCollision = new bool[8]; - spriteColor = new int[8]; - spriteEnabled = new bool[8]; - spriteExtraColor = new int[2]; - spriteMultiColor = new bool[8]; - spritePriority = new bool[8]; - spriteStretchHorizontal = new bool[8]; - spriteStretchVertical = new bool[8]; - spriteX = new int[8]; - spriteY = new int[8]; - // initialize buffer buffer = new int[rasterWidth * rasterTotalLines]; bufferSize = buffer.Length; @@ -175,331 +541,75 @@ namespace BizHawk.Emulation.Computers.Commodore64 public void HardReset() { - // power on state - regs = new byte[0x40]; - Write(0x0016, 0xC0); - Write(0x0018, 0x01); - Write(0x0019, 0x71); - Write(0x001A, 0xF0); - for (ushort i = 0x0020; i <= 0x002E; i++) - Write(i, 0xF0); - - // unused registers always return FF - for (int i = 0x2F; i <= 0x3F; i++) - regs[i] = 0xFF; - - UpdateRegs(); - } - - public void LockBus() - { - cpuSignal.Lock(); + regs = new VicIIRegs(); + UpdateBorder(); } public void PerformCycle() { - for (int i = 0; i < 8; i++) - { - if (rasterOffsetX == visibleLeft) - visibleRenderX = true; - if (rasterOffsetX == visibleRight) - visibleRenderX = false; - if (rasterOffsetX == borderLeft) - borderOnHorizontal = false; - if (rasterOffsetX == borderRight) - borderOnHorizontal = true; - - if ((rasterOffsetX == fetchOffsetX) && ((rasterOffsetY & 0x07) == verticalScroll)) - { - cpuSignal.Lock(); - fetching = true; - characterFetchOffset = (rasterOffsetY >> 3) * 40; - charBufferOffset = 0; - } - - if (fetching) - { - if (charBufferOffset >= 0) - { - charBuffer[charBufferOffset] = mem.VicRead((ushort)(screenMemoryOffset + characterFetchOffset)); - characterFetchOffset++; - } - charBufferOffset++; - if (charBufferOffset == 40) - { - fetching = false; - cpuSignal.Unlock(); - } - } - - if (borderOnVertical || borderOnHorizontal) - { - WritePixel(borderColor); - } - else - { - WritePixel(backgroundColor[0]); - } - - rasterOffsetX++; - if (rasterOffsetX == rasterWidth) - rasterOffsetX = 0; - - if (rasterOffsetX == rasterLineLeft) - { - rasterOffsetY++; - - if (rasterOffsetY == visibleTop) - visibleRenderY = true; - if (rasterOffsetY == visibleBottom) - visibleRenderY = false; - if (rasterOffsetY == borderTop) - borderOnVertical = false; - if (rasterOffsetY == borderBottom) - borderOnVertical = true; - if (rasterOffsetY == rasterTotalLines) - { - rasterOffsetY = 0; - renderOffset = 0; - } - - if (rasterInterruptEnabled && (rasterOffsetY == rasterInterruptLine)) - { - rasterInterrupt = true; - } - } - } - - interrupt = - (rasterInterrupt & rasterInterruptEnabled) | - (spriteSpriteInterrupt & spriteSpriteInterruptEnabled) | - (spriteBackgroundInterrupt & spriteBackgroundInterruptEnabled) | - (lightPenInterrupt & lightPenInterruptEnabled); - - cpuSignal.Interrupt = interrupt; - UpdateRegs(); } public byte Read(ushort addr) { - return regs[addr & 0x3F]; - } - - public void UnlockBus() - { - cpuSignal.Unlock(); - } - - public void UpdateRegs() - { - // these registers update on their own - - regs[0x11] = (byte) - ((verticalScroll & 0x07) | - (extendHeight ? 0x08 : 0x00) | - (screenEnabled ? 0x10 : 0x00) | - (bitmapMode ? 0x20 : 0x00) | - (backgroundMode ? 0x40 : 0x00) | - ((rasterOffsetY & 0x100) >> 1)); - regs[0x12] = (byte)(rasterOffsetY & 0xFF); - regs[0x13] = (byte)(lightPenX >> 1); - regs[0x14] = (byte)(lightPenY); - regs[0x19] = (byte) - ((rasterInterrupt ? 0x01 : 0x00) | - (spriteBackgroundInterrupt ? 0x02 : 0x00) | - (spriteSpriteInterrupt ? 0x04 : 0x00) | - (lightPenInterrupt ? 0x08 : 0x00) | - (interrupt ? 0x80 : 0x00)); - } - - public void Write(ushort addr, byte val) - { - int index = 0; - bool allowWrite = true; + byte result = 0; addr &= 0x3F; switch (addr) { - case 0x00: - case 0x02: - case 0x04: - case 0x06: - case 0x08: - case 0x0A: - case 0x0C: - case 0x0E: - index = addr >> 1; - spriteX[index] &= 0xFF; - spriteX[index] |= val; - break; - case 0x01: - case 0x03: - case 0x05: - case 0x07: - case 0x09: - case 0x0B: - case 0x0D: - case 0x0F: - index = addr >> 1; - spriteY[index] &= 0xFF; - spriteY[index] |= val; - break; - case 0x10: - spriteX[0] = (spriteX[0] & 0xFF) | ((val & 0x01) << 8); - spriteX[1] = (spriteX[1] & 0xFF) | ((val & 0x02) << 7); - spriteX[2] = (spriteX[2] & 0xFF) | ((val & 0x04) << 6); - spriteX[3] = (spriteX[3] & 0xFF) | ((val & 0x08) << 5); - spriteX[4] = (spriteX[4] & 0xFF) | ((val & 0x10) << 4); - spriteX[5] = (spriteX[5] & 0xFF) | ((val & 0x20) << 3); - spriteX[6] = (spriteX[6] & 0xFF) | ((val & 0x40) << 2); - spriteX[7] = (spriteX[7] & 0xFF) | ((val & 0x80) << 1); - break; - case 0x11: - verticalScroll = val & 0x07; - extendHeight = ((val & 0x08) != 0x00); - screenEnabled = ((val & 0x10) != 0x00); - bitmapMode = ((val & 0x20) != 0x00); - backgroundMode = ((val & 0x40) != 0x00); - rasterInterruptLine = (rasterInterruptLine & 0xFF) | ((val & 0x80) << 1); - val = (byte)((val & 0x7F) | ((rasterOffsetY & 0x100) >> 1)); - break; - case 0x12: - rasterInterruptLine = (rasterInterruptLine & 0x100) | val; - allowWrite = false; - break; - case 0x15: - spriteEnabled[0] = ((val & 0x01) != 0x00); - spriteEnabled[1] = ((val & 0x02) != 0x00); - spriteEnabled[2] = ((val & 0x04) != 0x00); - spriteEnabled[3] = ((val & 0x08) != 0x00); - spriteEnabled[4] = ((val & 0x10) != 0x00); - spriteEnabled[5] = ((val & 0x20) != 0x00); - spriteEnabled[6] = ((val & 0x40) != 0x00); - spriteEnabled[7] = ((val & 0x80) != 0x00); - break; - case 0x16: - horizontalScroll = val & 0x07; - extendWidth = ((val & 0x08) != 0x00); - multiColorMode = ((val & 0x10) != 0x00); - resetBit = ((val & 0x20) != 0x00); - val |= 0xC0; - break; - case 0x17: - spriteStretchVertical[0] = ((val & 0x01) != 0x00); - spriteStretchVertical[1] = ((val & 0x02) != 0x00); - spriteStretchVertical[2] = ((val & 0x04) != 0x00); - spriteStretchVertical[3] = ((val & 0x08) != 0x00); - spriteStretchVertical[4] = ((val & 0x10) != 0x00); - spriteStretchVertical[5] = ((val & 0x20) != 0x00); - spriteStretchVertical[6] = ((val & 0x40) != 0x00); - spriteStretchVertical[7] = ((val & 0x80) != 0x00); - break; - case 0x18: - characterMemoryOffset = (int)(val & 0x0E) << 10; - screenMemoryOffset = (int)(val & 0xF0) << 6; - break; - case 0x19: - rasterInterrupt = ((val & 0x01) != 0); - spriteSpriteInterrupt = ((val & 0x02) != 0); - spriteBackgroundInterrupt = ((val & 0x04) != 0); - lightPenInterrupt = ((val & 0x08) != 0); - allowWrite = false; - break; - case 0x1A: - rasterInterruptEnabled = ((val & 0x01) != 0); - spriteSpriteInterruptEnabled = ((val & 0x02) != 0); - spriteBackgroundInterruptEnabled = ((val & 0x04) != 0); - lightPenInterruptEnabled = ((val & 0x08) != 0); - break; - case 0x1B: - spritePriority[0] = ((val & 0x01) != 0x00); - spritePriority[1] = ((val & 0x02) != 0x00); - spritePriority[2] = ((val & 0x04) != 0x00); - spritePriority[3] = ((val & 0x08) != 0x00); - spritePriority[4] = ((val & 0x10) != 0x00); - spritePriority[5] = ((val & 0x20) != 0x00); - spritePriority[6] = ((val & 0x40) != 0x00); - spritePriority[7] = ((val & 0x80) != 0x00); - break; - case 0x1C: - spriteMultiColor[0] = ((val & 0x01) != 0x00); - spriteMultiColor[1] = ((val & 0x02) != 0x00); - spriteMultiColor[2] = ((val & 0x04) != 0x00); - spriteMultiColor[3] = ((val & 0x08) != 0x00); - spriteMultiColor[4] = ((val & 0x10) != 0x00); - spriteMultiColor[5] = ((val & 0x20) != 0x00); - spriteMultiColor[6] = ((val & 0x40) != 0x00); - spriteMultiColor[7] = ((val & 0x80) != 0x00); - break; - case 0x1D: - spriteStretchHorizontal[0] = ((val & 0x01) != 0x00); - spriteStretchHorizontal[1] = ((val & 0x02) != 0x00); - spriteStretchHorizontal[2] = ((val & 0x04) != 0x00); - spriteStretchHorizontal[3] = ((val & 0x08) != 0x00); - spriteStretchHorizontal[4] = ((val & 0x10) != 0x00); - spriteStretchHorizontal[5] = ((val & 0x20) != 0x00); - spriteStretchHorizontal[6] = ((val & 0x40) != 0x00); - spriteStretchHorizontal[7] = ((val & 0x80) != 0x00); - break; case 0x1E: - spriteCollision[0] = ((val & 0x01) != 0x00); - spriteCollision[1] = ((val & 0x02) != 0x00); - spriteCollision[2] = ((val & 0x04) != 0x00); - spriteCollision[3] = ((val & 0x08) != 0x00); - spriteCollision[4] = ((val & 0x10) != 0x00); - spriteCollision[5] = ((val & 0x20) != 0x00); - spriteCollision[6] = ((val & 0x40) != 0x00); - spriteCollision[7] = ((val & 0x80) != 0x00); - break; case 0x1F: - spriteBackgroundCollision[0] = ((val & 0x01) != 0x00); - spriteBackgroundCollision[1] = ((val & 0x02) != 0x00); - spriteBackgroundCollision[2] = ((val & 0x04) != 0x00); - spriteBackgroundCollision[3] = ((val & 0x08) != 0x00); - spriteBackgroundCollision[4] = ((val & 0x10) != 0x00); - spriteBackgroundCollision[5] = ((val & 0x20) != 0x00); - spriteBackgroundCollision[6] = ((val & 0x40) != 0x00); - spriteBackgroundCollision[7] = ((val & 0x80) != 0x00); - break; - case 0x20: - borderColor = val; - break; - case 0x21: - backgroundColor[0] = val; - break; - case 0x22: - backgroundColor[1] = val; - break; - case 0x23: - backgroundColor[2] = val; - break; - case 0x24: - backgroundColor[3] = val; - break; - case 0x25: - spriteExtraColor[0] = val; - break; - case 0x26: - spriteExtraColor[1] = val; - break; - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - index = addr - 0x27; - spriteColor[index] = val; + // collision regs clear after read + result = regs[addr]; + regs[addr] = 0x00; break; default: - allowWrite = false; + result = regs[addr]; break; } - if (allowWrite) - regs[addr] = val; + return result; + } + + public void UpdateBorder() + { + borderTop = regs.RSEL ? 0x033 : 0x037; + borderBottom = regs.RSEL ? 0x0FA : 0x0F6; + borderLeft = regs.CSEL ? 0x018 : 0x01F; + borderRight = regs.CSEL ? 0x14E : 0x157; + } + + public void Write(ushort addr, byte val) + { + addr &= 0x3F; + + switch (addr) + { + case 0x11: + rasterInterruptLine &= 0xFF; + rasterInterruptLine |= (val & 0x80) << 1; + // raster upper bit can't be changed, save and restore the value + val &= 0x7F; + val |= (byte)(regs[addr] & 0x80); + regs[addr] = val; + UpdateBorder(); + break; + case 0x12: + // raster interrupt lower 8 bits + rasterInterruptLine &= 0x100; + rasterInterruptLine |= (val & 0xFF); + break; + case 0x16: + regs[addr] = val; + UpdateBorder(); + break; + case 0x1E: + case 0x1F: + // can't write to these regs + break; + default: + regs[addr] = val; + break; + } } private void WritePixel(int value) @@ -511,47 +621,4 @@ namespace BizHawk.Emulation.Computers.Commodore64 } } } - - public class VicSignals - { - public bool AllowCpu; - public bool Interrupt; - public int LockCounter; - - public VicSignals() - { - AllowCpu = true; - Interrupt = false; - LockCounter = 0; - } - - public void Lock() - { - if (AllowCpu) - { - LockCounter = 4; - } - } - - public void PerformCycle() - { - if (AllowCpu) - { - if (LockCounter > 0) - { - LockCounter--; - if (LockCounter == 0) - { - AllowCpu = false; - } - } - } - } - - public void Unlock() - { - AllowCpu = true; - } - - } }