From 2f7ad6a676e57981783fb8b2a4fc8a665c53728e Mon Sep 17 00:00:00 2001 From: goyuken Date: Fri, 23 May 2014 15:47:48 +0000 Subject: [PATCH] 2600: more stuff towards PAL support --- BizHawk.Emulation.Common/Database/GameInfo.cs | 9 +++- .../BizHawk.Emulation.Cores.csproj | 1 + .../Consoles/Atari/2600/Atari2600.Core.cs | 14 +++++- .../Consoles/Atari/2600/Atari2600.cs | 14 ++++-- .../Consoles/Atari/2600/Tia/TIA.cs | 44 +++++++++++++++---- 5 files changed, 67 insertions(+), 15 deletions(-) diff --git a/BizHawk.Emulation.Common/Database/GameInfo.cs b/BizHawk.Emulation.Common/Database/GameInfo.cs index 37e7a8c1f7..c6912b0f17 100644 --- a/BizHawk.Emulation.Common/Database/GameInfo.cs +++ b/BizHawk.Emulation.Common/Database/GameInfo.cs @@ -34,10 +34,17 @@ namespace BizHawk.Emulation.Common public bool NotInDatabase = true; public string FirmwareHash; - readonly Dictionary Options = new Dictionary(); + Dictionary Options = new Dictionary(); public GameInfo() { } + public GameInfo Clone() + { + var ret = (GameInfo)MemberwiseClone(); + ret.Options = new Dictionary(Options); + return ret; + } + public static GameInfo GetNullGame() { return new GameInfo diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index d301d94884..abe1a599d5 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -71,6 +71,7 @@ 3.5 + 3.5 diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs index 8889530626..6709808e39 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs @@ -279,7 +279,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 OnExecFetch = this.ExecFetch }; - _tia = new TIA(this); + // TODO: add to game db so we only run DetectPal() on unknown games + bool pal; + if (_game["PAL"]) + pal = true; + else if (_game["NTSC"]) + pal = false; + else + pal = DetectPal(_game, Rom); + + _tia = new TIA(this, pal); + _tia.GetFrameRate(out CoreComm.VsyncNum, out CoreComm.VsyncDen); // dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles _dcfilter = DCFilter.AsISoundProvider(_tia, 256); @@ -326,7 +336,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 _islag = true; _tia.LineCount = 0; _tia.BeginAudioFrame(); - while (_tia.LineCount < 262) // will be 312 for PAL + while (_tia.LineCount < _tia.NominalNumScanlines) { CycleAdvance(); } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs index ff81f3836c..a1d93218af 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs @@ -255,10 +255,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 private static bool DetectPal(GameInfo game, byte[] rom) { + // force NTSC mode for the new core we instantiate + var newgame = game.Clone(); + if (newgame["PAL"]) + newgame.RemoveOption("PAL"); + if (!newgame["NTSC"]) + newgame.AddOption("NTSC"); + // give the emu a minimal of input\output connections so it doesn't crash var comm = new CoreComm(null, null); comm.InputCallback = new InputCallbackSystem(); - using (Atari2600 emu = new Atari2600(new CoreComm(null, null), game, rom, null, null)) + using (Atari2600 emu = new Atari2600(new CoreComm(null, null), newgame, rom, null, null)) { emu.Controller = new NullController(); @@ -267,8 +274,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 for (int i = 0; i < 71; i++) // run for 71 * 262 lines, since we're in NTSC mode emu.FrameAdvance(false, false); int numpal = framecounts.Count((i) => i > 287); - Console.WriteLine("{0} PAL", numpal); - return numpal >= 25; + bool pal = numpal >= 25; + Console.WriteLine("PAL Detection: {0} lines, {1}", numpal, pal); + return pal; } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs index 5d30d4f638..9c16e3564c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using BizHawk.Common; using BizHawk.Emulation.Common; +using System.Numerics; namespace BizHawk.Emulation.Cores.Atari.Atari2600 { @@ -143,6 +144,29 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 #endregion + // in all cases, the TIA has 228 clocks per scanline + // the NTSC TIA has a clock rate of 3579575hz + // the PAL/SECAM TIA has a clock rate of 3546894hz + + private bool _pal; + + public int NominalNumScanlines + { + get + { + return _pal ? 312 : 262; + } + } + + public void GetFrameRate(out int num, out int den) + { + int clockrate = _pal ? 3546894 : 3579575; + int clocksperframe = 228 * NominalNumScanlines; + int gcd = (int)BigInteger.GreatestCommonDivisor(clockrate, clocksperframe); + num = clockrate / gcd; + den = clocksperframe / gcd; + } + private const int ScreenWidth = 160; private const int MaxScreenHeight = 312; @@ -156,7 +180,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 private readonly Atari2600 _core; private int[] _scanlinebuffer = new int[ScreenWidth * MaxScreenHeight]; - private readonly int[] _palette = NTSCPalette; // todo: make this NTSC or PAL, obviously + private readonly int[] _palette; private byte _hsyncCnt; private int _capChargeStart; @@ -173,11 +197,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 public Audio[] AUD = { new Audio(), new Audio() }; - public TIA(Atari2600 core) + public TIA(Atari2600 core, bool pal) { _core = core; _player0.ScanCnt = 8; _player1.ScanCnt = 8; + _pal = pal; + _palette = _pal ? PALPalette : NTSCPalette; } public int CurrentScanLine @@ -209,6 +235,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 public int VirtualWidth { + // TODO: PAL? get { return 275; } // 275 comes from NTSC specs and the actual pixel clock of a 2600 TIA } @@ -226,11 +253,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 { get { - // TODO PAL support - //if (false) - // return _core.Settings.PALBottomLine - _core.Settings.PALTopLine; - //else - return _core.Settings.NTSCBottomLine - _core.Settings.NTSCTopLine; + if (_pal) + return _core.Settings.PALBottomLine - _core.Settings.PALTopLine; + else + return _core.Settings.NTSCBottomLine - _core.Settings.NTSCTopLine; } } @@ -595,8 +621,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 void OutputFrame(int validlines) { - int topLine = _core.Settings.NTSCTopLine; - int bottomLine = _core.Settings.NTSCBottomLine; + int topLine = _pal ? _core.Settings.PALTopLine : _core.Settings.NTSCTopLine; + int bottomLine = _pal ? _core.Settings.PALBottomLine : _core.Settings.NTSCBottomLine; // if vsync occured unexpectedly early, black out the remainer for (; validlines < bottomLine; validlines++)