From 7dc58087715c298ede645bdf359913b32fc78e37 Mon Sep 17 00:00:00 2001 From: goyuken Date: Wed, 31 Oct 2012 18:25:46 +0000 Subject: [PATCH] NES: preliminary support for PAL, Dendy, and RGB (part 1). at the moment, it's all determined from gamedb, and not at all saved to movies or savestates --- .../Consoles/Nintendo/NES/Core.cs | 48 ++++++++++++++++++- .../Consoles/Nintendo/NES/FDS/FDS.cs | 2 +- .../Consoles/Nintendo/NES/PPU.cs | 24 +++++++++- .../Consoles/Nintendo/NES/PPU.run.cs | 19 +++----- 4 files changed, 78 insertions(+), 15 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs index 4ad6f48924..647be6750c 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs @@ -129,6 +129,51 @@ namespace BizHawk.Emulation.Consoles.Nintendo apu = new APU(this); if (magicSoundProvider != null) magicSoundProvider.Dispose(); magicSoundProvider = new MagicSoundProvider(this); + + // set up region + if (!string.IsNullOrEmpty(cart.system)) + { + switch (cart.system) + { + case "NES-PAL": + case "NES-PAL-A": + case "NES-PAL-B": + ppu.region = PPU.Region.PAL; + CoreOutputComm.VsyncNum = 50; + CoreOutputComm.VsyncDen = 1; + cpu_sequence = cpu_sequence_PAL; + break; + case "NES-NTSC": + case "Famicom": + ppu.region = PPU.Region.NTSC; + cpu_sequence = cpu_sequence_NTSC; + break; + // there's no official name for these in bootgod, not sure what we should use + case "PC10": + case "VS": + ppu.region = PPU.Region.RGB; + cpu_sequence = cpu_sequence_NTSC; + break; + // this is in bootgod, but not used at all + case "Dendy": + ppu.region = PPU.Region.Dendy; + CoreOutputComm.VsyncNum = 50; + CoreOutputComm.VsyncDen = 1; + cpu_sequence = cpu_sequence_NTSC; + break; + default: + Console.WriteLine("Unrecognized NES region \"{0}\"! Defaulting to NTSC."); + ppu.region = PPU.Region.NTSC; + cpu_sequence = cpu_sequence_NTSC; + break; + } + } + else + { + Console.WriteLine("Unknown NES region! Defaulting to NTSC."); + ppu.region = PPU.Region.NTSC; + cpu_sequence = cpu_sequence_NTSC; + } //fceux uses this technique, which presumably tricks some games into thinking the memory is randomized for (int i = 0; i < 0x800; i++) @@ -186,13 +231,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo //sequence of ppu clocks per cpu clock: 4,3,3,3,3 //NTSC: //sequence of ppu clocks per cpu clock: 3 + ByteBuffer cpu_sequence; static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[]{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}); static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[]{4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3}); public int cpu_step, cpu_stepcounter, cpu_deadcounter; protected void RunCpuOne() { cpu_stepcounter++; - if (cpu_stepcounter == cpu_sequence_NTSC[cpu_step]) + if (cpu_stepcounter == cpu_sequence[cpu_step]) { cpu_step++; cpu_step &= 31; diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs index 8b365905b5..30fb10263c 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs @@ -99,7 +99,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo Cart.vram_size = 8; Cart.wram_size = 32; Cart.wram_battery = false; - Cart.system = "FDS"; + Cart.system = "Famicom"; Cart.board_type = "FAMICOM_DISK_SYSTEM"; diskdrive = new RamAdapter(); diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs index 305097e889..113f1cf1b4 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs @@ -13,6 +13,28 @@ namespace BizHawk.Emulation.Consoles.Nintendo { public partial class PPU { + // this only handles region differences within the PPU + int preNMIlines; + int postNMIlines; + bool chopdot; + public enum Region { NTSC, PAL, Dendy, RGB }; + Region _region; + public Region region { set { _region = value; SyncRegion(); } get { return _region; } } + void SyncRegion() + { + switch (region) + { + case Region.NTSC: + preNMIlines = 1; postNMIlines = 20; chopdot = true; break; + case Region.PAL: + preNMIlines = 1; postNMIlines = 70; chopdot = false; break; + case Region.Dendy: + preNMIlines = 51; postNMIlines = 20; chopdot = false; break; + case Region.RGB: + preNMIlines = 1; postNMIlines = 20; chopdot = false; break; + } + } + public class DebugCallback { public int Scanline; @@ -169,7 +191,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo } //hack - public bool PAL = false; + //public bool PAL = false; //bool SPRITELIMIT = true; } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs index a1cd1faefa..5094196640 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs @@ -132,10 +132,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo bool nmi_destiny = reg_2000.vblank_nmi_gen && Reg2002_vblank_active; runppu(3); if (nmi_destiny) TriggerNMI(); - if (PAL) - runppu(70 * (kLineTime) - delay); - else - runppu(20 * (kLineTime) - delay); + runppu(postNMIlines * kLineTime - delay); //this seems to run just before the dummy scanline begins clear_2002(); @@ -441,7 +438,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo //equivelant of half a memory access cycle) before repeating the whole //pixel/scanline rendering process. If the scanline being rendered is the very //first one on every second frame, then this delay simply doesn't exist. - if (sl == 0 && idleSynch && evenOddDestiny && !PAL) + if (sl == 0 && idleSynch && evenOddDestiny && chopdot) { } else runppu(1); @@ -449,8 +446,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo ppur.status.sl = 241; - //idle for one line - runppu(kLineTime); + //idle for pre NMI lines + runppu(preNMIlines * kLineTime); } //FrameAdvance @@ -463,12 +460,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo //should write to those regs during that time, it needs //to wait for vblank ppur.status.sl = 241; - if (PAL) - runppu(70 * kLineTime); - else - runppu(20 * kLineTime); + runppu(postNMIlines * kLineTime); ppur.status.sl = 0; - runppu(242 * kLineTime); + runppu(241 * kLineTime); + runppu(preNMIlines * kLineTime); --ppudead; } }