diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs b/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs index ee90ce9fa1..0a46592896 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs @@ -9,12 +9,12 @@ namespace BizHawk.Emulation.Computers.Commodore64 { public byte PeekCia0(int addr) { - return cia0.Peek(addr); + return cia0.regs[addr]; } public byte PeekCia1(int addr) { - return cia1.Peek(addr); + return cia1.regs[addr]; } public byte PeekColorRAM(int addr) @@ -34,17 +34,17 @@ namespace BizHawk.Emulation.Computers.Commodore64 public byte PeekRAM(int addr) { - return mem.PeekRam(addr); + return mem.ram[addr]; } public byte PeekSid(int addr) { - return sid.Peek(addr); + return sid.regs[addr]; } public byte PeekVic(int addr) { - return vic.Peek(addr); + return vic.regs[addr]; } public void PokeCia0(int addr, byte val) diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.cs b/BizHawk.Emulation/Computers/Commodore64/C64.cs index 4f12476d51..b1c83681fa 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.cs @@ -113,7 +113,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 private void SetupMemoryDomains() { var domains = new List(1); - domains.Add(new MemoryDomain("Memory", 0x10000, Endian.Little, new Func(PeekMemoryInt), new Action(PokeMemoryInt))); + domains.Add(new MemoryDomain("System Bus", 0x10000, Endian.Little, new Func(PeekMemoryInt), new Action(PokeMemoryInt))); domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func(PeekRAM), new Action(PokeRAM))); domains.Add(new MemoryDomain("CIA0", 0x10, Endian.Little, new Func(PeekCia0), new Action(PokeCia0))); domains.Add(new MemoryDomain("CIA1", 0x10, Endian.Little, new Func(PeekCia1), new Action(PokeCia1))); diff --git a/BizHawk.Emulation/Computers/Commodore64/MemBus.cs b/BizHawk.Emulation/Computers/Commodore64/MemBus.cs index b58f79a774..7c129c5b1e 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MemBus.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MemBus.cs @@ -219,19 +219,19 @@ namespace BizHawk.Emulation.Computers.Commodore64 result = charRom[addr & 0x0FFF]; break; case MemoryDesignation.Vic: - result = vic.regs[addr & 0x3F]; + result = vic.Peek(addr & 0x3F); break; case MemoryDesignation.Sid: - result = sid.regs[addr & 0x1F]; + result = sid.Peek(addr & 0x1F); break; case MemoryDesignation.ColorRam: result = (byte)(colorRam[addr & 0x03FF] | (busData & 0xF0)); break; case MemoryDesignation.Cia0: - result = cia0.regs[addr & 0x0F]; + result = cia0.Peek(addr & 0x0F); break; case MemoryDesignation.Cia1: - result = cia1.regs[addr & 0x0F]; + result = cia1.Peek(addr & 0x0F); break; case MemoryDesignation.Expansion0: result = 0; diff --git a/BizHawk.Emulation/Computers/Commodore64/VicII.cs b/BizHawk.Emulation/Computers/Commodore64/VicII.cs index f21a96bd12..9fad93ac9e 100644 --- a/BizHawk.Emulation/Computers/Commodore64/VicII.cs +++ b/BizHawk.Emulation/Computers/Commodore64/VicII.cs @@ -518,6 +518,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 private Action FetchC; private Action FetchG; private Func Plotter; + private Action PerformCycleFunction; public VicII(ChipSignals newSignal, Region newRegion) { @@ -540,32 +541,13 @@ namespace BizHawk.Emulation.Computers.Commodore64 visibleWidth = 352; visibleHeight = 232; renderOffset = 0; + PerformCycleFunction = PerformCycleNTSC; break; case Region.PAL: break; default: break; } - - // initialize raster - rasterWidth = totalCycles * 8; - rasterOffsetX = rasterLineLeft; - borderOnMain = true; - borderOnVertical = true; - - // initialize buffer - buffer = new int[visibleWidth * visibleHeight]; - bufferSize = buffer.Length; - - // initialize screen buffer - characterMemory = new byte[40]; - colorMemory = new byte[40]; - pixelBuffer = new int[12]; - pixelBufferForeground = new bool[12]; - pixelBufferIndex = 0; - - // initialize registers - spriteFetchIndex = 0; HardReset(); } @@ -642,15 +624,35 @@ namespace BizHawk.Emulation.Computers.Commodore64 public void HardReset() { + // initialize raster + rasterWidth = totalCycles * 8; + rasterOffsetX = rasterLineLeft; + borderOnMain = true; + borderOnVertical = true; + + // initialize buffer + buffer = new int[visibleWidth * visibleHeight]; + bufferSize = buffer.Length; + + // initialize screen buffer + characterMemory = new byte[40]; + colorMemory = new byte[40]; + pixelBuffer = new int[12]; + pixelBufferForeground = new bool[12]; + pixelBufferIndex = 0; + + // initialize registers + spriteFetchIndex = 0; idle = true; refreshAddress = 0x3FFF; regs = new VicIIRegs(); regs.RC = 7; signal.VicAEC = true; signal.VicIRQ = false; + + // initialize screen UpdateBorder(); UpdatePlotter(); - spriteFetchIndex = 17; } public byte Peek(int addr) @@ -658,6 +660,14 @@ namespace BizHawk.Emulation.Computers.Commodore64 return regs[addr & 0x3F]; } + private void PerformBorderCheck() + { + if ((regs.RASTER == borderTop) && (regs.DEN)) + borderOnVertical = false; + if (regs.RASTER == borderBottom) + borderOnVertical = true; + } + public void PerformCycle() { if (cycle >= totalCycles) @@ -666,7 +676,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 AdvanceRaster(); } - ProcessDisplayRegisters(); + PerformCycleCommon(); + PerformCycleFunction(); RenderCycle(); // increment cycle @@ -675,12 +686,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 signal.VicIRQ = regs.IRQ; } - public void Poke(int addr, byte val) - { - regs[addr & 0x3F] = val; - } - - private void ProcessDisplayRegisters() + // these operations are done every cycle + private void PerformCycleCommon() { // display enable check on line 030 (this must be run every cycle) if (regs.RASTER == 0x030) @@ -699,163 +706,363 @@ namespace BizHawk.Emulation.Computers.Commodore64 for (int i = 0; i < 8; i++) if (!regs.MxYE[i]) regs.MYE[i] = true; + } - // these actions are exclusive - if ((regs.RASTER == 0x000 && cycle == 1) || (regs.RASTER > 0x000 && cycle == 0)) + // operations timed to NTSC + private void PerformCycleNTSC() + { + switch (cycle) { - // IRQ is processed on cycle 1 of line 0 and cycle 0 on all other lines - if (regs.RASTER == rasterInterruptLine) - regs.IRST = true; + case 0: + // rasterline IRQ happens on cycle 1 on rasterline 0 + if (regs.RASTER > 0 && regs.RASTER == rasterInterruptLine) + regs.IRST = true; + PerformSpritePointerFetch(3); + break; + case 1: + // rasterline IRQ happens on cycle 1 on rasterline 0 + if (regs.RASTER == 0 && regs.RASTER == rasterInterruptLine) + regs.IRST = true; + PerformSpriteDataFetch(3); + break; + case 2: + PerformSpritePointerFetch(4); + break; + case 3: + PerformSpriteDataFetch(4); + break; + case 4: + PerformSpritePointerFetch(5); + break; + case 5: + PerformSpriteDataFetch(5); + break; + case 6: + PerformSpritePointerFetch(6); + break; + case 7: + PerformSpriteDataFetch(6); + break; + case 8: + PerformSpritePointerFetch(7); + break; + case 9: + PerformSpriteDataFetch(7); + break; + case 10: + PerformDRAMRefresh(); + break; + case 11: + PerformDRAMRefresh(); + break; + case 12: + PerformDRAMRefresh(); + break; + case 13: + PerformVCReset(); + PerformDRAMRefresh(); + break; + case 14: + PerformDRAMRefresh(); + break; + case 15: + PerformSpriteMCBASEAdvance(); + PerformScreenCAccess(); + break; + case 16: + PerformScreenCAccess(); + break; + case 17: + PerformScreenCAccess(); + break; + case 18: + PerformScreenCAccess(); + break; + case 19: + PerformScreenCAccess(); + break; + case 20: + PerformScreenCAccess(); + break; + case 21: + PerformScreenCAccess(); + break; + case 22: + PerformScreenCAccess(); + break; + case 23: + PerformScreenCAccess(); + break; + case 24: + PerformScreenCAccess(); + break; + case 25: + PerformScreenCAccess(); + break; + case 26: + PerformScreenCAccess(); + break; + case 27: + PerformScreenCAccess(); + break; + case 28: + PerformScreenCAccess(); + break; + case 29: + PerformScreenCAccess(); + break; + case 30: + PerformScreenCAccess(); + break; + case 31: + PerformScreenCAccess(); + break; + case 32: + PerformScreenCAccess(); + break; + case 33: + PerformScreenCAccess(); + break; + case 34: + PerformScreenCAccess(); + break; + case 35: + PerformScreenCAccess(); + break; + case 36: + PerformScreenCAccess(); + break; + case 37: + PerformScreenCAccess(); + break; + case 38: + PerformScreenCAccess(); + break; + case 39: + PerformScreenCAccess(); + break; + case 40: + PerformScreenCAccess(); + break; + case 41: + PerformScreenCAccess(); + break; + case 42: + PerformScreenCAccess(); + break; + case 43: + PerformScreenCAccess(); + break; + case 44: + PerformScreenCAccess(); + break; + case 45: + PerformScreenCAccess(); + break; + case 46: + PerformScreenCAccess(); + break; + case 47: + PerformScreenCAccess(); + break; + case 48: + PerformScreenCAccess(); + break; + case 49: + PerformScreenCAccess(); + break; + case 50: + PerformScreenCAccess(); + break; + case 51: + PerformScreenCAccess(); + break; + case 52: + PerformScreenCAccess(); + break; + case 53: + PerformScreenCAccess(); + break; + case 54: + PerformScreenCAccess(); + PerformSpriteYExpansionFlip(); + PerformSpriteComparison(); + break; + case 55: + PerformSpriteComparison(); + break; + case 56: + break; + case 57: + PerformSpriteDMAEnable(); + PerformRCReset(); + break; + case 58: + break; + case 59: + PerformSpritePointerFetch(0); + break; + case 60: + PerformSpriteDataFetch(0); + break; + case 61: + PerformSpritePointerFetch(1); + break; + case 62: + PerformSpriteDataFetch(1); + break; + case 63: + PerformSpritePointerFetch(2); + PerformBorderCheck(); + break; + case 64: + PerformSpriteDataFetch(2); + break; } - else if (cycle >= 10 && cycle < 15) - { - // dram refresh - mem.VicRead((ushort)refreshAddress); - refreshAddress = (refreshAddress - 1) & 0xFF; - refreshAddress |= 0x3F00; + } - // VC reset - if (cycle == 13) + // operations timed to PAL + private void PerformCyclePAL() + { + } + + private void PerformDRAMRefresh() + { + // dram refresh + mem.VicRead((ushort)refreshAddress); + refreshAddress = (refreshAddress - 1) & 0xFF; + refreshAddress |= 0x3F00; + } + + private void PerformRCReset() + { + // row counter processing + if (regs.RC == 7) + { + idle = true; + regs.VCBASE = regs.VC; + } + if (!idle) + regs.RC = (regs.RC + 1) & 0x07; + } + + private void PerformScreenCAccess() + { + // screen memory c-access + if (badLine) + { + FetchC(); + colorMemory[regs.VMLI] = colorDataBus; + characterMemory[regs.VMLI] = characterDataBus; + } + signal.VicAEC = !badLine; + } + + private void PerformSpriteComparison() + { + // reenable cpu if disabled + signal.VicAEC = true; + + // sprite comparison + for (int i = 0; i < 8; i++) + { + if (regs.MYE[i] && regs.MCBASE[i] == 63) { - regs.VC = regs.VCBASE; - regs.VMLI = 0; - characterColumn = 0; - if (badLine) - { - regs.RC = 0; - } - bitmapData = 0; - colorData = 0; - characterData = 0; + regs.MD[i] = false; + regs.MDMA[i] = false; } - } - else if (cycle >= 15 && cycle < 55) - { - // screen memory c-access - if (badLine) - { - FetchC(); - colorMemory[regs.VMLI] = colorDataBus; - characterMemory[regs.VMLI] = characterDataBus; - } - signal.VicAEC = !badLine; - } - else if (cycle == 55) - { - // reenable cpu if disabled - signal.VicAEC = true; - // sprite comparison - for (int i = 0; i < 8; i++) + if (regs.MxE[i] == true && regs.MxY[i] == (regs.RASTER & 0xFF) && regs.MDMA[i] == false) { - if (regs.MYE[i] && regs.MCBASE[i] == 63) - { - regs.MD[i] = false; - regs.MDMA[i] = false; - } - + regs.MDMA[i] = true; + regs.MCBASE[i] = 0; if (regs.MxYE[i]) - regs.MYE[i] = !regs.MYE[i]; + regs.MYE[i] = false; + } + } + } - if (regs.MxE[i] == true && regs.MxY[i] == (regs.RASTER & 0xFF) && regs.MDMA[i] == false) + private void PerformSpriteDataFetch(int spriteIndex) + { + // second half of the fetch cycle + signal.VicAEC = !regs.MDMA[spriteIndex]; + if (regs.MDMA[spriteIndex]) + { + for (int i = 0; i < 2; i++) + { + regs.MSR[spriteIndex] <<= 8; + regs.MSR[spriteIndex] |= mem.VicRead((ushort)((regs.MPTR[spriteIndex] << 6) | (regs.MC[spriteIndex]))); + regs.MC[spriteIndex]++; + } + } + } + + private void PerformSpriteDMAEnable() + { + // sprite MC processing + for (int i = 0; i < 8; i++) + { + regs.MC[i] = regs.MCBASE[i]; + if (regs.MDMA[i] && regs.MxY[i] == (regs.RASTER & 0xFF)) + regs.MD[i] = true; + } + } + + private void PerformSpriteMCBASEAdvance() + { + for (int i = 0; i < 8; i++) + { + if (regs.MYE[i]) + { + if (regs.MD[i]) { - regs.MDMA[i] = true; - regs.MCBASE[i] = 0; - if (regs.MxYE[i]) - regs.MYE[i] = false; + regs.MCBASE[i] += 3; } } } - else if (cycle == 57) - { - // row counter processing - if (regs.RC == 7) - { - idle = true; - regs.VCBASE = regs.VC; - } - if (!idle) - regs.RC = (regs.RC + 1) & 0x07; + } - // sprite MC processing - for (int i = 0; i < 8; i++) - { - regs.MC[i] = regs.MCBASE[i]; - if (regs.MDMA[i] && regs.MxY[i] == (regs.RASTER & 0xFF)) - regs.MD[i] = true; - } - } + private void PerformSpritePointerFetch(int spriteIndex) + { + // first half of the fetch cycle, always fetch pointer + ushort pointerOffset = (ushort)((regs.VM << 10) | 0x3F8 | spriteIndex); + regs.MPTR[spriteIndex] = mem.VicRead(pointerOffset); - // MCBASE reset if applicable - if (cycle == 15) + // also fetch upper 8 bits if enabled + signal.VicAEC = !regs.MDMA[spriteIndex]; + if (regs.MDMA[spriteIndex]) { - for (int i = 0; i < 8; i++) - { - if (regs.MYE[i]) - { - if (regs.MD[i]) - { - regs.MCBASE[i] += 3; - } - } - } + regs.MSRC[spriteIndex] = 24; + regs.MSR[spriteIndex] = mem.VicRead((ushort)((regs.MPTR[spriteIndex] << 6) | (regs.MC[spriteIndex]))); + regs.MC[spriteIndex]++; } + } - // sprite fetch - if (cycle == spriteFetchStartCycle) - { - spriteFetchIndex = 0; - } - if (spriteFetchIndex < 16) - { - int spriteIndex = spriteFetchIndex >> 1; + private void PerformSpriteYExpansionFlip() + { + for (int i = 0; i < 8; i++) + if (regs.MxYE[i]) + regs.MYE[i] = !regs.MYE[i]; + } - if ((spriteFetchIndex & 1) == 0) - { - // first half of the fetch cycle, always fetch pointer - ushort pointerOffset = (ushort)((regs.VM << 10) | 0x3F8 | spriteIndex); - regs.MPTR[spriteIndex] = mem.VicRead(pointerOffset); - - // also fetch upper 8 bits if enabled - signal.VicAEC = !regs.MDMA[spriteIndex]; - if (regs.MDMA[spriteIndex]) - { - regs.MSRC[spriteIndex] = 24; - regs.MSR[spriteIndex] = mem.VicRead((ushort)((regs.MPTR[spriteIndex] << 6) | (regs.MC[spriteIndex]))); - regs.MC[spriteIndex]++; - } - } - else - { - // second half of the fetch cycle - signal.VicAEC = !regs.MDMA[spriteIndex]; - if (regs.MDMA[spriteIndex]) - { - for (int i = 0; i < 2; i++) - { - regs.MSR[spriteIndex] <<= 8; - regs.MSR[spriteIndex] |= mem.VicRead((ushort)((regs.MPTR[spriteIndex] << 6) | (regs.MC[spriteIndex]))); - regs.MC[spriteIndex]++; - } - } - } - spriteFetchIndex++; - } - else if (spriteFetchIndex == 16) + private void PerformVCReset() + { + // VC reset + regs.VC = regs.VCBASE; + regs.VMLI = 0; + characterColumn = 0; + if (badLine) { - // set AEC after sprite fetches - signal.VicAEC = true; - spriteFetchIndex++; + regs.RC = 0; } + bitmapData = 0; + colorData = 0; + characterData = 0; + } - // border check - if (cycle == 63) - { - if ((regs.RASTER == borderTop) && (regs.DEN)) - borderOnVertical = false; - if (regs.RASTER == borderBottom) - borderOnVertical = true; - } + public void Poke(int addr, byte val) + { + regs[addr & 0x3F] = val; } // standard text mode