From 7114ecd914d9ce75d64f3924fee355f31834ca98 Mon Sep 17 00:00:00 2001 From: saxxonpike Date: Wed, 21 Nov 2012 20:39:51 +0000 Subject: [PATCH] commodore64: more work on new video code --- BizHawk.Emulation/BizHawk.Emulation.csproj | 3 +- .../Computers/Commodore64/Vic.cs | 43 +++- .../Computers/Commodore64/VicFunction.cs | 206 +++++++++++++++++- .../Computers/Commodore64/VicMem.cs | 27 +++ .../Computers/Commodore64/VicRegs.cs | 111 +++++++++- .../Computers/Commodore64/VicVideoProvider.cs | 99 +++++++++ .../Commodore64/{VicState.cs => _VicState.cs} | 0 7 files changed, 477 insertions(+), 12 deletions(-) create mode 100644 BizHawk.Emulation/Computers/Commodore64/VicVideoProvider.cs rename BizHawk.Emulation/Computers/Commodore64/{VicState.cs => _VicState.cs} (100%) diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index dcbcd9e577..e569763ffd 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -108,12 +108,13 @@ + - + diff --git a/BizHawk.Emulation/Computers/Commodore64/Vic.cs b/BizHawk.Emulation/Computers/Commodore64/Vic.cs index 54d10549c1..29c1a374f3 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Vic.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Vic.cs @@ -9,12 +9,15 @@ namespace BizHawk.Emulation.Computers.Commodore64 { private uint cyclesTotal; private uint linesTotal; + private Memory mem; + private uint rasterLeft; private Region region; private Action Execute; - public VicII(Region vicRegion) + public VicII(Region vicRegion, Memory vicMem) { + mem = vicMem; region = vicRegion; switch (region) @@ -22,14 +25,40 @@ namespace BizHawk.Emulation.Computers.Commodore64 case Region.NTSC: cyclesTotal = 65; linesTotal = 263; + rasterLeft = 0x19C; Execute = ExecuteNTSC; break; case Region.PAL: cyclesTotal = 63; linesTotal = 312; + rasterLeft = 0x194; Execute = ExecutePAL; break; } + + // initalize screen properties + screenWidth = cyclesTotal * 8; + screenHeight = linesTotal; + + // initialize viewport properties + visibleWidth = screenWidth; + visibleHeight = screenHeight; + visibleRight = visibleLeft + visibleWidth; + visibleBottom = visibleTop + visibleHeight; + + // initialize screen buffer + screenBuffer = new int[visibleWidth * visibleHeight]; + } + + private void ExecuteCommon() + { + if (!badlineEnabled && rasterLine == 0x30) + badlineEnabled = displayEnable; + + if (badlineEnabled) + CheckBadline(); + + Execute(); } private void ExecuteNTSC() @@ -174,7 +203,15 @@ namespace BizHawk.Emulation.Computers.Commodore64 } } - - + public void PerformCycle() + { + ExecuteCommon(); + rasterCycle++; + if (rasterCycle == cyclesTotal) + { + rasterCycle = 0; + NextRasterLine(); + } + } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/VicFunction.cs b/BizHawk.Emulation/Computers/Commodore64/VicFunction.cs index 24beec7698..1f0e7ce44a 100644 --- a/BizHawk.Emulation/Computers/Commodore64/VicFunction.cs +++ b/BizHawk.Emulation/Computers/Commodore64/VicFunction.cs @@ -19,6 +19,25 @@ namespace BizHawk.Emulation.Computers.Commodore64 { } + private void CheckBadline() + { + if ((rasterLine & 0x07) == ySmooth) + { + badline = true; + idle = false; + } + else + { + badline = false; + } + } + + private void CheckBorderBottom() + { + if (rasterLine == borderBottom) + borderOnVerticalEnable = true; + } + private void CheckBorderLeft0() { } @@ -35,34 +54,166 @@ namespace BizHawk.Emulation.Computers.Commodore64 { } + private void CheckBorderTop() + { + if (rasterLine == borderTop) + { + borderOnVertical = false; + borderOnVerticalEnable = false; + } + } + private void CheckSpriteCrunch() { } private void CheckSpriteDisplay() { + for (int i = 0; i < 8; i++) + { + Sprite spr = sprites[i]; + spr.mc = spr.mcBase; + + if (spr.dma) + { + if ((spr.enable) && (spr.y == (rasterLine & 0xFF))) + spr.display = true; + } + else + spr.display = false; + } } private void CheckSpriteDma() { + for (int i = 0; i < 8; i++) + { + Sprite spr = sprites[i]; + if (spr.enable && (spr.y == (rasterLine & 0xFF)) && !spr.dma) + { + spr.dma = true; + spr.mcBase = 0; + spr.exp = true; + } + } } private void CheckSpriteExpansion() { + for (int i = 0; i < 8; i++) + { + Sprite spr = sprites[i]; + if (spr.dma && spr.exp) + { + spr.exp = !spr.exp; + } + } } - private void FetchC() + private ushort FetchAddrG() { + ushort addr; + + if (bitmapMode) + addr = (ushort)((vc << 3) | rc | ((bitmapRam & 0x8) << 10)); + else + addr = (ushort)((videoBuffer[vmli] << 3) | rc | ((bitmapRam & 0xE) << 10)); + + if (extraColorMode) + addr &= (ushort)0x39FF; + + return addr; } - private void FetchG() + private uint Fetch0(ushort addr) { + if (cycleFetchG) + { + if (!idle) + return FetchG(); + else + return FetchGIdle(); + } + else if (cycleFetchP) + { + return FetchP(); + } + else if (cycleFetchS) + { + return FetchS(); + } + else if (cycleFetchR) + { + return FetchR(); + } + return FetchIdle(); + } + + private uint Fetch1(ushort addr) + { + phaseRead1 = mem.VicRead(addr); + return phaseRead1; + } + + private ushort FetchAddrV(uint offset) + { + return (ushort)((videoRam << 10) | offset); + } + + private ushort FetchC() + { + return 0; + } + + private ushort FetchG() + { + return 0; + } + + private ushort FetchGIdle() + { + return 0; + } + + private ushort FetchIdle() + { + return 0; + } + + private ushort FetchP() + { + return 0; + } + + private ushort FetchR() + { + return 0; + } + + private ushort FetchS() + { + return 0; } private void Idle() { } + private void LineStart() + { + if ((rasterLine == 0x30) && (!badlineEnabled) && (displayEnable)) + badlineEnabled = true; + + if (rasterLine == 0xF8) + badlineEnabled = false; + + badline = false; + } + + private void NextRasterLine() + { + } + private void Phase0() { } @@ -75,32 +226,75 @@ namespace BizHawk.Emulation.Computers.Commodore64 { } - private void SpritePointer() + private void SpritePointer(int index) { } - private void SpriteDma0() + private void SpriteDma0(uint index) { } - private void SpriteDma1() + private void SpriteDma1(int index) { } - private void SpriteDma2() + private void SpriteDma2(int index) { } + private void UpdateBorder() + { + borderBottom = rowSelect ? (uint)0xFA : (uint)0xF6; + borderLeft = columnSelect ? (uint)0x018 : (uint)0x01F; + borderRight = columnSelect ? (uint)0x157 : (uint)0x14E; + borderTop = rowSelect ? (uint)0x33 : (uint)0x37; + } + + private void UpdateInterrupts() + { + irq = + (irqDataCollision & enableIrqDataCollision) | + (irqLightPen & enableIrqLightPen) | + (irqRaster & enableIrqRaster) | + (irqSpriteCollision & enableIrqSpriteCollision); + } + private void UpdateMCBASE() { + for (int i = 0; i < 8; i++) + { + Sprite spr = sprites[i]; + if (spr.exp) + { + spr.mcBase = spr.mc; + if (spr.mcBase == 63) + { + spr.dma = false; + } + } + } } private void UpdateRC() { + if (rc == 7) + { + idle = true; + vcbase = vc; + } + if (!idle || badline) + { + idle = false; + rc = (rc + 1) & 0x7; + } } private void UpdateVC() { + vc = vcbase; + vmli = 0; + if (badline) + rc = 0; } private void Vis(uint index) diff --git a/BizHawk.Emulation/Computers/Commodore64/VicMem.cs b/BizHawk.Emulation/Computers/Commodore64/VicMem.cs index c9f78acb9b..635327106a 100644 --- a/BizHawk.Emulation/Computers/Commodore64/VicMem.cs +++ b/BizHawk.Emulation/Computers/Commodore64/VicMem.cs @@ -26,6 +26,18 @@ namespace BizHawk.Emulation.Computers.Commodore64 addr &= 0x3F; switch (addr) { + case 0x1E: + // clear after read + result = this[addr]; + this[addr] = 0x00; + irqSpriteCollision = false; + break; + case 0x1F: + // clear after read + result = this[addr]; + this[addr] = 0x00; + irqDataCollision = false; + break; default: result = this[addr]; break; @@ -39,6 +51,21 @@ namespace BizHawk.Emulation.Computers.Commodore64 addr &= 0x3F; switch (addr) { + case 0x19: + // interrupt reg + if ((val & 0x01) != 0x00) + irqRaster = false; + if ((val & 0x02) != 0x00) + irqDataCollision = false; + if ((val & 0x04) != 0x00) + irqSpriteCollision = false; + if ((val & 0x08) != 0x00) + irqLightPen = false; + break; + case 0x1E: + case 0x1F: + // non writeable regs + break; default: this[addr] = val; break; diff --git a/BizHawk.Emulation/Computers/Commodore64/VicRegs.cs b/BizHawk.Emulation/Computers/Commodore64/VicRegs.cs index b43231004a..ab768a8358 100644 --- a/BizHawk.Emulation/Computers/Commodore64/VicRegs.cs +++ b/BizHawk.Emulation/Computers/Commodore64/VicRegs.cs @@ -7,10 +7,11 @@ namespace BizHawk.Emulation.Computers.Commodore64 { public partial class VicII { - private struct Sprite + private class Sprite { public uint color; public bool dataCollision; + public bool display; public bool dma; public bool enable; public bool exp; @@ -28,16 +29,53 @@ namespace BizHawk.Emulation.Computers.Commodore64 public bool xExpand; public uint y; public bool yExpand; + + public void SyncState(Serializer ser) + { + ser.Sync("color", ref color); + ser.Sync("dataCollision", ref dataCollision); + ser.Sync("display", ref display); + ser.Sync("dma", ref dma); + ser.Sync("enable", ref enable); + ser.Sync("exp", ref exp); + ser.Sync("mc", ref mc); + ser.Sync("mcBase", ref mcBase); + ser.Sync("mcChange", ref mcChange); + ser.Sync("multicolor", ref multicolor); + ser.Sync("priority", ref priority); + ser.Sync("ptr", ref ptr); + ser.Sync("ptrinc", ref ptrinc); + ser.Sync("spriteCollision", ref spriteCollision); + ser.Sync("x", ref x); + ser.Sync("xShift", ref xShift); + ser.Sync("xShiftSum", ref xShiftSum); + ser.Sync("xExpand", ref xExpand); + ser.Sync("y", ref y); + ser.Sync("yExpand", ref yExpand); + } } private uint backgroundColor0; private uint backgroundColor1; private uint backgroundColor2; private uint backgroundColor3; + private bool badline; + private bool badlineEnabled; private bool bitmapMode; private uint bitmapRam; + private uint borderBottom; private uint borderColor; + private uint borderLeft; + private bool borderOnMain; + private bool borderOnVertical; + private bool borderOnVerticalEnable; + private uint borderRight; + private uint borderTop; private bool columnSelect; + private bool cycleFetchG; + private bool cycleFetchP; + private bool cycleFetchR; + private bool cycleFetchS; private bool displayEnable; private bool enableIrqDataCollision; private bool enableIrqLightPen; @@ -53,22 +91,90 @@ namespace BizHawk.Emulation.Computers.Commodore64 private uint lightPenX; private uint lightPenY; private bool multiColorMode; - private uint phaseRead; + private uint phaseRead0; + private uint phaseRead1; private uint rasterCycle; private uint rasterIrqLine; private uint rasterLine; private uint rc; + private ushort refreshAddr; private bool reset; private bool rowSelect; + private uint spriteIndex; private uint spriteMultiColor0; private uint spriteMultiColor1; private Sprite[] sprites; private uint vc; private uint vcbase; + private uint[] videoBuffer; private uint videoRam; private uint vmli; private uint xScroll; private uint yScroll; + private uint ySmooth; + + public void SyncState(Serializer ser) + { + ser.Sync("backgroundColor0", ref backgroundColor0); + ser.Sync("backgroundColor1", ref backgroundColor1); + ser.Sync("backgroundColor2", ref backgroundColor2); + ser.Sync("backgroundColor3", ref backgroundColor3); + ser.Sync("badline", ref badline); + ser.Sync("badlineEnabled", ref badlineEnabled); + ser.Sync("bitmapMode", ref bitmapMode); + ser.Sync("bitmapRam", ref bitmapRam); + ser.Sync("borderBottom", ref borderBottom); + ser.Sync("borderColor", ref borderColor); + ser.Sync("borderLeft", ref borderLeft); + ser.Sync("borderOnMain", ref borderOnMain); + ser.Sync("borderOnVertical", ref borderOnVertical); + ser.Sync("borderOnVerticalEnable", ref borderOnVerticalEnable); + ser.Sync("borderRight", ref borderRight); + ser.Sync("borderTop", ref borderTop); + ser.Sync("columnSelect", ref columnSelect); + ser.Sync("displayEnable", ref displayEnable); + ser.Sync("enableIrqDataCollision", ref enableIrqDataCollision); + ser.Sync("enableIrqLightPen", ref enableIrqLightPen); + ser.Sync("enableIrqRaster", ref enableIrqRaster); + ser.Sync("enableIrqSpriteCollision", ref enableIrqSpriteCollision); + ser.Sync("extraColorMode", ref extraColorMode); + ser.Sync("idle", ref idle); + ser.Sync("irq", ref irq); + ser.Sync("irqDataCollision", ref irqDataCollision); + ser.Sync("irqLightPen", ref irqLightPen); + ser.Sync("irqRaster", ref irqRaster); + ser.Sync("irqSpriteCollision", ref irqSpriteCollision); + ser.Sync("lightPenX", ref lightPenX); + ser.Sync("lightPenY", ref lightPenY); + ser.Sync("multiColorMode", ref multiColorMode); + ser.Sync("phaseRead0", ref phaseRead0); + ser.Sync("phaseRead1", ref phaseRead1); + ser.Sync("rasterCycle", ref rasterCycle); + ser.Sync("rasterIrqLine", ref rasterIrqLine); + ser.Sync("rasterLine", ref rasterLine); + ser.Sync("rc", ref rc); + ser.Sync("refreshAddr", ref refreshAddr); + ser.Sync("reset", ref reset); + ser.Sync("rowSelect", ref rowSelect); + ser.Sync("spriteIndex", ref spriteIndex); + ser.Sync("spriteMultiColor0", ref spriteMultiColor0); + ser.Sync("spriteMultiColor1", ref spriteMultiColor1); + ser.Sync("vc", ref vc); + ser.Sync("vcbase", ref vcbase); + ser.Sync("videoBuffer", ref videoBuffer, false); + ser.Sync("videoRam", ref videoRam); + ser.Sync("vmli", ref vmli); + ser.Sync("xScroll", ref xScroll); + ser.Sync("yScroll", ref yScroll); + ser.Sync("ySmooth", ref ySmooth); + + for (int i = 0; i < 8; i++) + { + ser.BeginSection("sprite" + i.ToString()); + sprites[i].SyncState(ser); + ser.EndSection(); + } + } private byte this[uint addr] { @@ -599,6 +705,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 get { return (byte)sprites[7].color; } set { sprites[7].color = value; } } + } } diff --git a/BizHawk.Emulation/Computers/Commodore64/VicVideoProvider.cs b/BizHawk.Emulation/Computers/Commodore64/VicVideoProvider.cs new file mode 100644 index 0000000000..6368b31f3f --- /dev/null +++ b/BizHawk.Emulation/Computers/Commodore64/VicVideoProvider.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Computers.Commodore64 +{ + public partial class VicII : IVideoProvider + { + private static int[] palette = + { + Colors.ARGB(0x00, 0x00, 0x00), + Colors.ARGB(0xFF, 0xFF, 0xFF), + Colors.ARGB(0x68, 0x37, 0x2B), + Colors.ARGB(0x70, 0xA4, 0xB2), + Colors.ARGB(0x6F, 0x3D, 0x86), + Colors.ARGB(0x58, 0x8D, 0x43), + Colors.ARGB(0x35, 0x28, 0x79), + Colors.ARGB(0xB8, 0xC7, 0x6F), + Colors.ARGB(0x6F, 0x4F, 0x25), + Colors.ARGB(0x43, 0x39, 0x00), + Colors.ARGB(0x9A, 0x67, 0x59), + Colors.ARGB(0x44, 0x44, 0x44), + Colors.ARGB(0x6C, 0x6C, 0x6C), + Colors.ARGB(0x9A, 0xD2, 0x84), + Colors.ARGB(0x6C, 0x5E, 0xB5), + Colors.ARGB(0x95, 0x95, 0x95) + }; + + private int[] screenBuffer; + private uint screenHeight; + private uint screenOffset; + private uint screenOffsetX; + private uint screenOffsetY; + private bool screenOffsetVisibleX; + private bool screenOffsetVisibleY; + private uint screenWidth; + private uint visibleBottom; + private uint visibleHeight; + private uint visibleLeft; + private uint visibleRight; + private uint visibleTop; + private uint visibleWidth; + + public int BackgroundColor + { + get { return Colors.ARGB(0, 0, 0); } + } + + public int BufferHeight + { + get { return (int)visibleHeight; } + } + + public int BufferWidth + { + get { return (int)visibleWidth; } + } + + public int[] GetVideoBuffer() + { + return screenBuffer; + } + + public int VirtualWidth + { + get { return BufferWidth; } + } + + private void WritePixel(uint pixel) + { + if (screenOffsetX == visibleLeft) + screenOffsetVisibleX = true; + else if (screenOffsetX == visibleRight) + screenOffsetVisibleX = false; + + if (screenOffsetY == visibleTop) + screenOffsetVisibleY = true; + else if (screenOffsetY == visibleBottom) + screenOffsetVisibleY = false; + + if (screenOffsetVisibleX && screenOffsetVisibleY) + screenBuffer[screenOffset] = palette[pixel]; + + screenOffset++; + screenOffsetX++; + if (screenOffsetX == screenWidth) + { + screenOffsetX = 0; + screenOffsetY++; + if (screenOffsetY == screenHeight) + { + screenOffsetY = 0; + screenOffset = 0; + } + } + } + } +} diff --git a/BizHawk.Emulation/Computers/Commodore64/VicState.cs b/BizHawk.Emulation/Computers/Commodore64/_VicState.cs similarity index 100% rename from BizHawk.Emulation/Computers/Commodore64/VicState.cs rename to BizHawk.Emulation/Computers/Commodore64/_VicState.cs