From 50a06e38cdf32e26705b8854d1e984a495d79cd8 Mon Sep 17 00:00:00 2001 From: beirich Date: Sun, 13 Mar 2011 03:20:28 +0000 Subject: [PATCH] PCE: Significant VDC timing improvements --- .../Consoles/PC Engine/Compat.txt | 54 +++++-------------- .../Consoles/PC Engine/PCEngine.cs | 9 ---- .../Consoles/PC Engine/VDC.Render.cs | 50 +++++++++-------- BizHawk.Emulation/Consoles/PC Engine/VDC.cs | 45 +++++++++------- BizHawk.Emulation/Consoles/PC Engine/VPC.cs | 10 ++-- 5 files changed, 68 insertions(+), 100 deletions(-) diff --git a/BizHawk.Emulation/Consoles/PC Engine/Compat.txt b/BizHawk.Emulation/Consoles/PC Engine/Compat.txt index 88179700d9..d9ee414e36 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/Compat.txt +++ b/BizHawk.Emulation/Consoles/PC Engine/Compat.txt @@ -1,71 +1,41 @@ ======= TurboGrafx compatibility issues ======= General: - + Noise Channel isn't right. Less obnoxious now, still not happy. - + T Flag implemented for ADC, EOR. Log warning if used by any other instructions. - Should probably just do it for the others, but I hate not having a test case. - + Video timing is off. + + Don't have a complete list of instructions affected by T flag. Currently warns if SET precedes an unrecognized instruction. + Audio volumes are probably wrong. + LFO is not implemented, though I can't tell. + Screen is too tall on several games. Obv resolution calculation is not 100% correct. -Adventure Island - Flicker on title screen sequence - timing? -Aero Blaster - Bottom of Screen possibly extends too many lines -Agmeda - Very minor timing/gfx glitches esp at bottom of screen -Air Zonk - Freezes shortly into a new game -Alice - Screen possibly too tall; glitches when scrolling up, but in pcejin also, +Aero Blaster - Bottom of Screen extends too many lines - like 3 extra or so +Air Zonk - Fully playable, doesn't freeze, but some gfx/timing issues +Alice - Screen too tall; glitches when scrolling up, but in pcejin also, but not ootake; ergo probably a timing artifact Andre Panza Kickbx- Doesn't boot. Looks like semi pedigree as Battle Royal. -Battle Ace - Some gfx glitches Battle Royale - Doesnt boot -Boxy Boy - Freezes when starting game; seems to remain broken even after rewinding (!!) -Bravoman - Is currently booting. But has been boot-problematic in the past. -Cadash - Camera is all crazy. Very sensitive to interrupt timing and timing in general. Chase HQ - Press start -"O" sprite gets left on screen. probably timing on SATB DMA -Chouzetsu Rinjin - Japanese version of Bravoman. Currently working. -College Pro Basebl- In startup sequence, sprites are crazy, game goes nuts when starting game Cross Wiber - Minor; Raster on wrong line -Cyber Dodge - Minor gfx issues -Davis Cup Tennis - Doesnt boot at all right now +Davis Cup Tennis - Some timing issue, splash screen is too slow Dead Moon - Screen is too tall -Dragon Egg - Doesn't boot at all Dungeon Explorer - Freeze in 'intro' - gfx corruption in-game Fighting Run - Corruption issues -Final Blaster - Does crazy shit with video modes; freezes if intro is not skipped -Final Solider - Graphics corruption issues - some right at the beginning that might be a good target -Ghost Mannor - Game will freeze in some circumstances mid gameplay +Final Blaster - Intro does crazy shit with video modes; not sure what if anything to do about it Griffon - Screen goes black because game changes video mode mid-frame Gunboat - Crash / CPU Break (Needs BRAM) -Hisou Kihei Serd - Doesn't boot -Idol Hanafuda Fan Club - Doesn't boot -Impossamole - Gfx issues -Jack Nicholas Golf- Doesnt boot basically -Legendary Axe - BYR updated on the wrong line of the screen, but playable. -Legendary Axe II - Fairly serious corruption issues, but playable now +Jack Nicholas Golf- Some screens are too tall and reveal bad gfx below the intended visible screen Legend of Hero Ton- Slight gfx- check top of screen Lode Runner - Freezes in new game -Madoo Granzort - Graphics issues because VPC renderer is not using new frame timing -Metal Stoker - Tearing when scrolling vertically at bottom of screen - timing +Madoo Granzort - Graphics issues because SGX VPC renderer is not using new frame timing +Metal Stoker - Tearing when scrolling vertically at bottom of screen - screen too tall? MML Demo - Echo channels are too loud (equal volume!) -Naxat Open - Crashes when you start new game -NHK Taiga Drama Ta- Sprite flicker and corruption issues -Night Creatures - Some gfx glitches Outrun - Raster issues, music slows when paused -Paranoia - MAYBE game freeze in like 5th level? not sure, didnt verify. +Paranoia - Game hits BREAK on 3rd level. need to investigate Populous - Game freezes on starting new game - *** NEEDS BATTERY SAVERAM *** Power Drift - Timing glitch... starting new game runs slower than it should -Power Tennis - Freezes in (elaborate) intro screen. decent target though -R-Type - Funky corruption after killing final boss in Stage 8 +Power Tennis - Elaborate intro screen doesnt display right Raiden - Sprites and BG get out of sync with current timing -Rastan Saga 2 - Doesn't boot - lots of invalid reads? -Sekikehara - Gfx corruption, some palette problems? Side Arms - Screen is like 4 pixels too tall -Sinistron - Raster effect errors -Soldier Blade - Freezes about 5 minutes in. Always in the same spot, fortunately. I have a savestate. -Soukoban World - J version of Boxy Boy - Same bugs -Thunder Blade - After beating the 1st 3d area, game semi-freezes +Sinistron - Much less bad raster effect errors now Tiger Road - On second level, sprites should be getting masked from the top status area somehow -Valkyrie No Densetsu - Boots now, but with pretty severe issues Stuff I Fixed That's Not In Other Docs: diff --git a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs index 93cfc3d4b3..b1185ee3c1 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs +++ b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs @@ -38,14 +38,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx // PC Engine timings: // 21,477,270 Machine clocks / sec // 7,159,090 Cpu cycles / sec - - // At 60.00 FPS - // 357,954 mclks / frame - // 119,318 Cpu cycles / frame - - // 263 lines / frame: - // 1361 mclks / line - // 454 Cpu cycles / line public PCEngine(NecSystemType type) { @@ -108,7 +100,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx public void FrameAdvance(bool render) { Controller.UpdateControls(Frame++); - //Log.Note("CPU","======== FRAME {0} =========",Frame); PSG.BeginFrame(Cpu.TotalExecutedCycles); if (SuperGrafx) diff --git a/BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs b/BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs index 297e3dae1e..53a19df6c7 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs +++ b/BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs @@ -15,10 +15,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx + BackgroundY is the current offset into the scroll plane. It is set with BYR register at certain sync points and incremented every scanline. Its values range from 0 - $1FF. - + RCRCount is the current offset into the RCR register. It is reset to $40 - on the first active display line, and incremented every line. Its effective - range is $40 - $146. - */ public int ScanLine; public int BackgroundY; @@ -27,7 +23,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx private byte[] InterSpritePriorityBuffer = new byte[512]; private int latchedDisplayStartLine; private int ActiveLine; - private int RCRCount; public void ExecFrame(bool render) { @@ -35,10 +30,16 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx ActiveLine = 0 - latchedDisplayStartLine; ScanLine = 0; - int HDS = (Registers[HSR] >> 8) & 0x7F; - int HDE = (Registers[HDR] >> 8) & 0x7F; - int hblankCycles = (HDS + HDE + 2) * 8; - //hblankCycles -= 2; + int hds = (Registers[HSR] >> 8) & 0x7F; + int hde = (Registers[HDR] >> 8) & 0x7F; + int vds = Registers[VPR] >> 8; + int vsw = Registers[VPR] & 0x1F; + + int VBlankScanline = vds + vsw + Registers[VDW] + 1; + if (VBlankScanline > 261) + VBlankScanline = 261; + + int hblankCycles = (hds + hde + 2) * 8; switch (vce.DotClock) { @@ -47,7 +48,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx case 2: hblankCycles = (hblankCycles*2)/3; break; } - for (; ScanLine < 262;) + for (; ScanLine < 263;) { //Log.Note("VDC","ScanLine {0} (ActiveLine {1}, RCR {2}, BGY {3})",ScanLine, ActiveLine, RCRCount, BackgroundY); bool InActiveDisplay = false; @@ -55,35 +56,33 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx InActiveDisplay = true; if (ActiveLine == 0) - { BackgroundY = Registers[BYR]; - RCRCount = 0x40; - //Console.WriteLine("Latched BYR {0} at scanline {1}",BackgroundY, ScanLine); - } - if ((RCRCount) == (Registers[RCR] & 0x3FF)) + if (ActiveLine == (Registers[RCR] & 0x3FF) - 0x40) { - if (IntRasterCompare) + if (RasterCompareInterruptEnabled) { - //Log.Note("VDC", "Enter RCR interrupt at scanline {0}",ScanLine); + Log.Note("VDC", "Firing RCR interrupt at {0}", ScanLine); StatusByte |= StatusRasterCompare; cpu.IRQ1Assert = true; } } - if (ActiveLine == BufferHeight && IntVerticalBlank) - { - StatusByte |= StatusVerticalBlanking; - cpu.IRQ1Assert = true; - } cpu.Execute(hblankCycles); - + if (InActiveDisplay && render) RenderScanLine(); + if (ScanLine == VBlankScanline && VBlankInterruptEnabled) + { + Log.Note("VDC", "Firing VBlank interrupt at {0}", ScanLine); + StatusByte |= StatusVerticalBlanking; + cpu.IRQ1Assert = true; + } + cpu.Execute(455-hblankCycles); - if (ScanLine == FrameHeight - 1) + if (ScanLine == VBlankScanline) UpdateSpriteAttributeTable(); if (InActiveDisplay == false && DmaRequested) @@ -91,7 +90,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx ScanLine++; ActiveLine++; - RCRCount++; BackgroundY++; BackgroundY &= 0x01FF; } @@ -115,7 +113,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx if ((Registers[DCR] & 1) > 0) { - Console.WriteLine("FIRING SATB DMA COMPLETION IRQ"); + Log.Note("VDC","FIRING SATB DMA COMPLETION IRQ"); StatusByte |= StatusVramSatDmaComplete; cpu.IRQ1Assert = true; } diff --git a/BizHawk.Emulation/Consoles/PC Engine/VDC.cs b/BizHawk.Emulation/Consoles/PC Engine/VDC.cs index 8cb297d1cf..4c3252fdfa 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/VDC.cs +++ b/BizHawk.Emulation/Consoles/PC Engine/VDC.cs @@ -35,12 +35,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx } } - public bool BackgroundEnabled { get { return (Registers[CR] & 0x80) != 0; } } - public bool SpritesEnabled { get { return (Registers[CR] & 0x40) != 0; } } - public bool IntVerticalBlank { get { return (Registers[CR] & 0x08) != 0; } } - public bool IntRasterCompare { get { return (Registers[CR] & 0x04) != 0; } } - public bool IntSpriteOverflow { get { return (Registers[CR] & 0x02) != 0; } } - public bool IntSpriteCollision { get { return (Registers[CR] & 0x01) != 0; } } + public bool BackgroundEnabled { get { return (Registers[CR] & 0x80) != 0; } } + public bool SpritesEnabled { get { return (Registers[CR] & 0x40) != 0; } } + public bool VBlankInterruptEnabled { get { return (Registers[CR] & 0x08) != 0; } } + public bool RasterCompareInterruptEnabled { get { return (Registers[CR] & 0x04) != 0; } } + public bool SpriteOverflowInterruptEnabled { get { return (Registers[CR] & 0x02) != 0; } } + public bool SpriteCollisionInterruptEnabled { get { return (Registers[CR] & 0x01) != 0; } } public int BatWidth { get { switch((Registers[MWR] >> 4) & 3) { case 0: return 32; case 1: return 64; default: return 128; } } } public int BatHeight { get { return ((Registers[MWR] & 0x40) == 0) ? 32 : 64; } } @@ -81,6 +81,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx public const byte StatusSpriteOverflow = 0x02; public const byte StatusSprite0Collision = 0x01; + private const int VramSize = 0x8000; + private HuC6280 cpu; private VCE vce; @@ -88,6 +90,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx { this.cpu = cpu; this.vce = vce; + + Registers[HSR] = 0x00FF; + Registers[HDR] = 0x00FF; + Registers[VPR] = 0xFFFF; + Registers[VCR] = 0xFFFF; + ReadBuffer = 0xFFFF; } public void WriteVDC(int port, byte value) @@ -108,37 +116,32 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx { Registers[RegisterLatch] &= 0x00FF; Registers[RegisterLatch] |= (ushort) (value << 8); - CompleteMSBWrite(); + CompleteMSBWrite(RegisterLatch); } } - private void CompleteMSBWrite() + private void CompleteMSBWrite(int register) { - switch (RegisterLatch) + switch (register) { case MARR: // Memory Address Read Register ReadBuffer = VRAM[Registers[MARR] & 0x7FFF]; break; case VWR: // VRAM Write Register - if (Registers[MAWR] < 0x8000) + if (Registers[MAWR] < VramSize) // Several games attempt to write past the end of VRAM { - VRAM[Registers[MAWR] & 0x7FFF] = Registers[VWR]; + VRAM[Registers[MAWR]] = Registers[VWR]; UpdatePatternData((ushort) (Registers[MAWR] & 0x7FFF)); UpdateSpriteData((ushort) (Registers[MAWR] & 0x7FFF)); } Registers[MAWR] += IncrementWidth; break; -case CR: -//if (Registers[CR] == 0) -//Log.Note("CPU", "****************** WRITE TO CR: {0:X}", Registers[CR]); -break; case BXR: Registers[BXR] &= 0x3FF; break; case BYR: Registers[BYR] &= 0x1FF; BackgroundY = Registers[BYR]; - //Console.WriteLine("Updating BYR to {0} at scanline {1}", BackgroundY, ScanLine); break; case HDR: // Horizontal Display Register - update framebuffer size FrameWidth = RequestedFrameWidth; @@ -190,7 +193,7 @@ break; case 1: // unused return 0; case 2: // LSB - return (byte) (ReadBuffer & 0xFF); + return (byte) ReadBuffer; case 3: // MSB retval = (byte)(ReadBuffer >> 8); if (RegisterLatch == VRR) @@ -221,7 +224,7 @@ break; if ((Registers[DCR] & 2) > 0) { - Console.WriteLine("FIRE VRAM-VRAM DMA COMPLETE IRQ"); + Log.Note("Vdc","FIRE VRAM-VRAM DMA COMPLETE IRQ"); StatusByte |= StatusVramVramDmaComplete; cpu.IRQ1Assert = true; } @@ -315,6 +318,9 @@ break; UpdatePatternData(i); UpdateSpriteData(i); } + + CompleteMSBWrite(HDR); + CompleteMSBWrite(VDW); } public void SaveStateBinary(BinaryWriter writer) @@ -345,6 +351,9 @@ break; RegisterLatch = reader.ReadByte(); ReadBuffer = reader.ReadUInt16(); StatusByte = reader.ReadByte(); + + CompleteMSBWrite(HDR); + CompleteMSBWrite(VDW); } } } diff --git a/BizHawk.Emulation/Consoles/PC Engine/VPC.cs b/BizHawk.Emulation/Consoles/PC Engine/VPC.cs index 25d3741479..5fb51e73b0 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/VPC.cs +++ b/BizHawk.Emulation/Consoles/PC Engine/VPC.cs @@ -152,7 +152,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx if ((ScanLine + 64) == (VDC1.Registers[6] & 0x3FF)) { - if (VDC1.IntRasterCompare) + if (VDC1.RasterCompareInterruptEnabled) { VDC1.StatusByte |= VDC.StatusRasterCompare; CPU.IRQ1Assert = true; @@ -161,20 +161,20 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx if ((ScanLine + 64) == (VDC2.Registers[6] & 0x3FF)) { - if (VDC2.IntRasterCompare) + if (VDC2.RasterCompareInterruptEnabled) { VDC2.StatusByte |= VDC.StatusRasterCompare; CPU.IRQ1Assert = true; } } - if (ScanLine == 240 && VDC1.IntVerticalBlank) + if (ScanLine == 240 && VDC1.VBlankInterruptEnabled) { VDC1.StatusByte |= VDC.StatusVerticalBlanking; CPU.IRQ1Assert = true; } - if (ScanLine == 240 && VDC2.IntVerticalBlank) + if (ScanLine == 240 && VDC2.VBlankInterruptEnabled) { VDC2.StatusByte |= VDC.StatusVerticalBlanking; CPU.IRQ1Assert = true; @@ -295,7 +295,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx if (width == 32) patternNo &= 0x1FE; - int yofs = 0; + int yofs; if (vflip == false) { yofs = (vdc.ScanLine - y) & 15;