From 1c18da52b3207a438a82a8e9a322181e75358952 Mon Sep 17 00:00:00 2001 From: saxxonpike Date: Sat, 24 Aug 2013 20:13:16 +0000 Subject: [PATCH] Commodore64: Border unit implemented fully, timing is much better now and works for both PAL and NTSC. --- .../Computers/Commodore64/C64.Core.cs | 2 +- .../Computers/Commodore64/C64.Motherboard.cs | 2 +- .../Commodore64/C64.MotherboardInterface.cs | 2 +- .../Computers/Commodore64/C64.Savestate.cs | 2 +- .../Computers/Commodore64/C64.cs | 2 +- .../Computers/Commodore64/MOS/MOS6567.cs | 24 ++++++-- .../Computers/Commodore64/MOS/MOS6569.cs | 24 ++++++-- .../Computers/Commodore64/MOS/Sid.cs | 10 +++- .../Computers/Commodore64/MOS/Vic.Parse.cs | 6 +- .../Computers/Commodore64/MOS/Vic.Render.cs | 58 ++++++++++--------- .../Computers/Commodore64/MOS/Vic.State.cs | 10 ++++ .../Commodore64/MOS/Vic.TimingBuilder.cs | 36 +++++++++++- .../Commodore64/MOS/Vic.VideoProvider.cs | 8 +-- .../Computers/Commodore64/MOS/Vic.cs | 27 ++++----- .../Computers/Commodore64/Sync.cs | 1 - 15 files changed, 149 insertions(+), 65 deletions(-) diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs b/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs index 4cb533811b..aaf040add4 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.Core.cs @@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 PAL } - public partial class C64 : IEmulator + sealed public partial class C64 : IEmulator { private Motherboard board; private bool loadPrg; diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs b/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs index c2f3534a70..eaaf3c5c01 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.Motherboard.cs @@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 /// /// Contains the onboard chipset and glue. /// - public partial class Motherboard + sealed public partial class Motherboard { // chips public Chip23XX basicRom; diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs b/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs index 0c395f4e17..f8650b0fdc 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.MotherboardInterface.cs @@ -7,7 +7,7 @@ using System.Text; namespace BizHawk.Emulation.Computers.Commodore64 { - public partial class Motherboard + sealed public partial class Motherboard { bool CassPort_ReadDataOutput() { diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.Savestate.cs b/BizHawk.Emulation/Computers/Commodore64/C64.Savestate.cs index e33f4466b1..cce2af2d93 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.Savestate.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.Savestate.cs @@ -2,7 +2,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 { - public partial class C64 : IEmulator + sealed public partial class C64 : IEmulator { public void ClearSaveRam() { diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.cs b/BizHawk.Emulation/Computers/Commodore64/C64.cs index 76e8dd50f5..21337542e9 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.cs @@ -5,7 +5,7 @@ using System.IO; namespace BizHawk.Emulation.Computers.Commodore64 { - public partial class C64 : IEmulator + sealed public partial class C64 : IEmulator { // internal variables private bool _islag = true; diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6567.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6567.cs index 036a7ef21b..6a827eeb5c 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6567.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6567.cs @@ -1,12 +1,22 @@ -namespace BizHawk.Emulation.Computers.Commodore64.MOS +using System.Drawing; + +namespace BizHawk.Emulation.Computers.Commodore64.MOS { // vic ntsc static public class MOS6567 { - static int[] timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, 0x208, 0x18C, 8); + static int cycles = 65; + static int lines = 263; + static int vblankstart = 0x00D; + static int vblankend = 0x018; + static int hblankstart = 0x18C; + static int hblankend = 0x1F0; + static int scanwidth = cycles * 8; + + static int[] timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, scanwidth, 0x18C, 8); static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x174); static int[] ba = Vic.TimingBuilder_BA(fetch); - static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C); + static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C, hblankstart, hblankend); static int[][] pipeline = new int[][] { @@ -18,7 +28,13 @@ static public Vic Create() { - return new Vic(65, 263, pipeline, 14318181 / 14); + return new Vic( + cycles, lines, + pipeline, + 14318181 / 14, + hblankstart, hblankend, + vblankstart, vblankend + ); } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs index 5780272afa..3ed96d82b3 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs @@ -1,12 +1,22 @@ -namespace BizHawk.Emulation.Computers.Commodore64.MOS +using System.Drawing; + +namespace BizHawk.Emulation.Computers.Commodore64.MOS { // vic pal static public class MOS6569 { - static int[] timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, 0x1F8, -1, -1); + static int cycles = 63; + static int lines = 312; + static int vblankstart = 0x12C; + static int vblankend = 0x00F; + static int hblankstart = 0x17C; + static int hblankend = 0x1E0; + static int scanwidth = cycles * 8; + + static int[] timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, scanwidth, -1, -1); static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x164); static int[] ba = Vic.TimingBuilder_BA(fetch); - static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C); + static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C, hblankstart, hblankend); static int[][] pipeline = new int[][] { @@ -18,7 +28,13 @@ static public Vic Create() { - return new Vic(63, 312, pipeline, 17734472 / 18); + return new Vic( + cycles, lines, + pipeline, + 17734472 / 18, + hblankstart, hblankend, + vblankstart, vblankend + ); } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs index 64f0ea1ae8..88dda110bf 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs @@ -613,11 +613,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public Sid(int[][] newWaveformTable, int newSampleRate, Region newRegion) { uint cyclesPerSec = 0; + uint cyclesNum; + uint cyclesDen; + uint sampleRate = 44100; switch (newRegion) { - case Region.NTSC: cyclesPerSec = 14318181 / 14; break; - case Region.PAL: cyclesPerSec = 17734472 / 18; break; + case Region.NTSC: cyclesNum = 14318181; cyclesDen = 14; break; + case Region.PAL: cyclesNum = 17734472; cyclesDen = 18; break; + default: return; } waveformTable = newWaveformTable; @@ -636,7 +640,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS for (int i = 0; i < 3; i++) filterEnable[i] = false; - resampler = new Sound.Utilities.SpeexResampler(0, cyclesPerSec, 44100, cyclesPerSec, 44100, null, null); + resampler = new Sound.Utilities.SpeexResampler(0, cyclesNum, sampleRate * cyclesDen, cyclesNum, sampleRate * cyclesDen, null, null); } public void Dispose() diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Parse.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Parse.cs index 6758e386c3..6002ce5714 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Parse.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Parse.cs @@ -19,6 +19,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public const int pipelineChkBrdR1 = 256; public const int pipelineChkSprDisp = 512; public const int pipelineUpdateRc = 1024; + public const int pipelineHBlankL = 0x10000000; + public const int pipelineHBlankR = 0x20000000; public const int pipelineHoldX = 0x40000000; public const int rasterIrqLine0Cycle = 1; public const int rasterIrqLineXCycle = 0; @@ -43,6 +45,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS // apply X location rasterX = pipeline[0][cycleIndex]; + rasterXHold = ((parseact & pipelineHoldX) != 0); // perform fetch parsefetchType = parsefetch & 0xFF00; @@ -158,7 +161,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS // perform actions borderCheckLEnable = ((parseact & (pipelineChkBrdL0 | pipelineChkBrdL1)) != 0); borderCheckREnable = ((parseact & (pipelineChkBrdR0 | pipelineChkBrdR1)) != 0); - rasterXHold = ((parseact & pipelineHoldX) != 0); + hblankCheckEnableL = ((parseact & pipelineHBlankL) != 0); + hblankCheckEnableR = ((parseact & pipelineHBlankR) != 0); if (parseact != 0) { diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Render.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Render.cs index e06a671993..db5a9e1899 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Render.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Render.cs @@ -7,6 +7,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { sealed public partial class Vic { + int borderSR; int ecmPixel; int pixel; int[] pixelBackgroundBuffer; @@ -33,47 +34,52 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private void Render() { - renderEnabled = bufRect.Contains(bufPoint); + if (hblankCheckEnableL) + { + if (rasterX == hblankEnd) + hblank = false; + } + else if (hblankCheckEnableR) + { + if (rasterX == hblankStart) + hblank = true; + } + renderEnabled = !hblank && !vblank; //bufRect.Contains(bufPoint); for (int i = 0; i < 4; i++) { - if (borderCheckLEnable) + if (borderCheckLEnable && (rasterX == borderL)) { - if (rasterX == borderL) - { - if (rasterLine == borderB) - borderOnVertical = true; - if (rasterLine == borderT && displayEnable) - borderOnVertical = false; - if (!borderOnVertical) - borderOnMain = false; - } - } - if (borderCheckREnable) - { - if (rasterX == borderR) - borderOnMain = true; + if (rasterLine == borderB) + borderOnVertical = true; + if (rasterLine == borderT && displayEnable) + borderOnVertical = false; + if (!borderOnVertical) + borderOnMain = false; } + if (borderCheckREnable && (rasterX == borderR)) + borderOnMain = true; + // recall pixel from buffer pixel = pixelBuffer[pixelBufferIndex]; + // border doesn't work with the background buffer + borderSR <<= 1; + if (borderOnMain || borderOnVertical) + borderSR |= 1; + if ((borderSR & 0x100) != 0) + pixel = borderColor; + // plot pixel if within viewing area if (renderEnabled) { + buf[bufOffset] = palette[pixel]; bufOffset++; if (bufOffset == bufLength) bufOffset = 0; } - bufPoint.X++; - if (bufPoint.X == bufWidth) - { - bufPoint.X = 0; - bufPoint.Y++; - if (bufPoint.Y == bufHeight) - bufPoint.Y = 0; - } // put the pixel from the background buffer into the main buffer pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex]; @@ -143,10 +149,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS } } - // border doesn't work with the background buffer - if (borderOnMain || borderOnVertical) - pixel = borderColor; - // store pixel in buffer pixelBuffer[pixelBufferIndex] = pixel; diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.State.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.State.cs index 88536da368..9eb7a1d135 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.State.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.State.cs @@ -42,11 +42,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS bool enableIntSpriteCollision; bool enableIntSpriteDataCollision; bool extraColorMode; + bool hblank; bool idle; bool intLightPen; bool intRaster; bool intSpriteCollision; bool intSpriteDataCollision; + int hblankEnd; + int hblankStart; + bool hblankCheckEnableL; + bool hblankCheckEnableR; int lastRasterLine; int lightPenX; int lightPenY; @@ -69,6 +74,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS int spriteMulticolor1; Sprite[] sprites; int sr; + bool vblank; + int vblankEnd; + int vblankStart; int vc; int vcbase; int vmli; @@ -105,6 +113,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS enableIntSpriteCollision = false; enableIntSpriteDataCollision = false; extraColorMode = false; + hblank = true; idle = true; intLightPen = false; intRaster = false; @@ -127,6 +136,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS spriteMulticolor0 = 0; spriteMulticolor1 = 0; sr = 0; + vblank = true; vc = 0; vcbase = 0; vmli = 0; diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.TimingBuilder.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.TimingBuilder.cs index 687679b7f6..a7030f07b9 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.TimingBuilder.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.TimingBuilder.cs @@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS pipelineChkSprDisp, pipelineUpdateRc }; - static public int[] TimingBuilder_Act(int[] timing, int cycle14, int cycle55) + static public int[] TimingBuilder_Act(int[] timing, int cycle14, int cycle55, int hblankStart, int hblankEnd) { List result = new List(); @@ -39,6 +39,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS result.Add(0); } + bool hBlankL = false; + bool hBlankR = false; for (int i = 0; i < length; i++) { // pipeline raster X delay @@ -54,6 +56,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS result[i] |= pipelineChkBrdR0; if (timing[i] == 0x15C) result[i] |= pipelineChkBrdR1; + if (timing[i] == (hblankStart & 0xFFD)) + result[i] |= pipelineHBlankR; + if (timing[i] == (hblankEnd & 0xFFD)) + result[i] |= pipelineHBlankL; } return result.ToArray(); @@ -196,6 +202,34 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS return result.ToArray(); } + static public int TimingBuilder_ScreenHeight(int vblankStart, int vblankEnd, int lines) + { + int offset = vblankEnd; + int result = 0; + while (true) + { + if (offset >= lines) + offset -= lines; + if (offset == vblankStart) + return result; + offset++; + result++; + } + } + + static public int TimingBuilder_ScreenWidth(int[] timing, int hblankStart, int hblankEnd) + { + int length = timing.Length; + int result = 0; + int offset = 0; + + while (timing[offset] != hblankEnd) { offset = (offset + 1) % length; } + while (timing[offset] != hblankStart) { offset = (offset + 1) % length; result++; } + //while (timing[offset] == hblankStart) { offset = (offset + 1) % length; result++; } + + return (result * 4); + } + static public int[] TimingBuilder_XRaster(int start, int width, int count, int delayOffset, int delayAmount) { List result = new List(); diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.VideoProvider.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.VideoProvider.cs index 0cb281254a..74b1b34dfa 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.VideoProvider.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.VideoProvider.cs @@ -8,8 +8,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS int bufHeight; int bufLength; int bufOffset; - Point bufPoint; - Rectangle bufRect; int bufWidth; // palette @@ -40,12 +38,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public int BufferHeight { - get { return bufRect.Height; } + get { return bufHeight; } } public int BufferWidth { - get { return bufRect.Width; } + get { return bufWidth; } } public int[] GetVideoBuffer() @@ -55,7 +53,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public int VirtualWidth { - get { return bufRect.Width; } + get { return bufWidth; } } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs index 1aa22d420d..e6473cd411 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs @@ -18,12 +18,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS int totalCycles; int totalLines; - public Vic(int newCycles, int newLines, int[][] newPipeline, int newCyclesPerSec) + public Vic(int newCycles, int newLines, int[][] newPipeline, int newCyclesPerSec, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd) { - { debugScreen = false; + this.hblankStart = hblankStart; + this.hblankEnd = hblankEnd; + this.vblankStart = vblankStart; + this.vblankEnd = vblankEnd; + totalCycles = newCycles; totalLines = newLines; pipeline = newPipeline; @@ -31,19 +35,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS pixelBufferDelay = 12; pixelBackgroundBufferDelay = 4; - if (debugScreen) - { - bufRect = new Rectangle(0, 0, totalCycles * 8, totalLines); - } - else - { - bufRect = new Rectangle(136 - 24, 51 - 24, 320 + 48, 200 + 48); - } + bufWidth = TimingBuilder_ScreenWidth(pipeline[0], hblankStart, hblankEnd); + bufHeight = TimingBuilder_ScreenHeight(vblankStart, vblankEnd, newLines); - buf = new int[bufRect.Width * bufRect.Height]; + buf = new int[bufWidth * bufHeight]; bufLength = buf.Length; - bufWidth = (totalCycles * 8); - bufHeight = (totalLines); sprites = new Sprite[8]; for (int i = 0; i < 8; i++) @@ -145,6 +141,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS if (rasterLine == borderT && displayEnable) borderOnVertical = false; + if (rasterLine == vblankStart) + vblank = true; + if (rasterLine == vblankEnd) + vblank = false; + cycleIndex = 0; cycle = 0; rasterLine++; diff --git a/BizHawk.Emulation/Computers/Commodore64/Sync.cs b/BizHawk.Emulation/Computers/Commodore64/Sync.cs index 24cb3b2102..3b80a38de8 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Sync.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Sync.cs @@ -24,7 +24,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 IntBuffer refIntBuffer; Int32 refPointX; Int32 refPointY; - Rectangle refRect; SByte refSByte; UInt16 refUInt16; UInt32 refUInt32;