diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index 3a4b1d69a6..f06cf75020 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -973,7 +973,14 @@ namespace BizHawk.Client.Common if (preference == "neshawk") { - core = CoreInventory.Instance["NES", "NesHawk"]; + if (Global.Config.UseSubNESHawk) + { + core = CoreInventory.Instance["NES", "SubNESHawk"]; + } + else + { + core = CoreInventory.Instance["NES", "NesHawk"]; + } } else { diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs index b7f72ab639..60c0071725 100644 --- a/BizHawk.Client.Common/config/Config.cs +++ b/BizHawk.Client.Common/config/Config.cs @@ -554,6 +554,7 @@ namespace BizHawk.Client.Common // as this setting spans multiple cores and doesn't actually affect the behavior of any core, // it hasn't been absorbed into the new system public bool GB_AsSGB = false; + public bool UseSubNESHawk = false; public bool NES_InQuickNES = true; public bool SNES_InSnes9x = true; public bool GBA_UsemGBA = true; diff --git a/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/BizHawk.Client.EmuHawk/MainForm.Designer.cs index 092908ba95..b7df5e2f76 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -199,6 +199,7 @@ this.GBGambatteMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.GBGBHawkMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.GBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SubNESHawkMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripSeparator(); this.allowGameDBCoreOverridesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); @@ -1845,6 +1846,7 @@ this.SGBCoreSubmenu, this.GBCoreSubmenu, this.GBInSGBMenuItem, + this.SubNESHawkMenuItem, this.toolStripMenuItem16, this.allowGameDBCoreOverridesToolStripMenuItem, this.toolStripSeparator8, @@ -1982,6 +1984,13 @@ this.GBInSGBMenuItem.Text = "GB in SGB"; this.GBInSGBMenuItem.Click += new System.EventHandler(this.GbInSgbMenuItem_Click); // + // SubNESHawkMenuItem + // + this.SubNESHawkMenuItem.Name = "SubNESHawkMenuItem"; + this.SubNESHawkMenuItem.Size = new System.Drawing.Size(239, 22); + this.SubNESHawkMenuItem.Text = "SubNESHawk"; + this.SubNESHawkMenuItem.Click += new System.EventHandler(this.SubNESHawkMenuItem_Click); + // // toolStripMenuItem16 // this.toolStripMenuItem16.Name = "toolStripMenuItem16"; @@ -4532,6 +4541,7 @@ private System.Windows.Forms.ToolStripMenuItem MovieSettingsMenuItem; private System.Windows.Forms.ToolStripMenuItem CoresSubMenu; private System.Windows.Forms.ToolStripMenuItem GBInSGBMenuItem; + private System.Windows.Forms.ToolStripMenuItem SubNESHawkMenuItem; private System.Windows.Forms.ToolStripMenuItem batchRunnerToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem DisplayConfigMenuItem; private System.Windows.Forms.ToolStripMenuItem PCEtileViewerToolStripMenuItem; diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index e9bce5e5aa..f524b4bb13 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -1215,6 +1215,7 @@ namespace BizHawk.Client.EmuHawk private void CoresSubMenu_DropDownOpened(object sender, EventArgs e) { GBInSGBMenuItem.Checked = Global.Config.GB_AsSGB; + SubNESHawkMenuItem.Checked = Global.Config.UseSubNESHawk; allowGameDBCoreOverridesToolStripMenuItem.Checked = Global.Config.CoreForcingViaGameDB; } @@ -1308,6 +1309,16 @@ namespace BizHawk.Client.EmuHawk } } + private void SubNESHawkMenuItem_Click(object sender, EventArgs e) + { + Global.Config.UseSubNESHawk ^= true; + + if (!Emulator.IsNull()) + { + FlagNeedsReboot(); + } + } + private void AllowGameDBCoreOverridesToolStripMenuItem_Click(object sender, EventArgs e) { Global.Config.CoreForcingViaGameDB ^= true; diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 28f0311d31..a7a40b17aa 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -2997,7 +2997,7 @@ namespace BizHawk.Client.EmuHawk } bool render = !_throttle.skipNextFrame || (_currAviWriter?.UsesVideo ?? false); - Emulator.FrameAdvance(Global.ControllerOutput, render, renderSound); + bool new_frame = Emulator.FrameAdvance(Global.ControllerOutput, render, renderSound); Global.MovieSession.HandleMovieAfterFrameLoop(); @@ -3036,7 +3036,7 @@ namespace BizHawk.Client.EmuHawk UpdateToolsAfter(SuppressLua); } - if (!PauseAvi) + if (!PauseAvi && new_frame) { AvFrameAdvance(); } diff --git a/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs b/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs index 034d1dfbaf..0983f9651c 100644 --- a/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs +++ b/BizHawk.Emulation.Common/Base Implementations/NullEmulator.cs @@ -33,23 +33,23 @@ namespace BizHawk.Emulation.Common public ControllerDefinition ControllerDefinition => NullController.Instance.Definition; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { if (render == false) { - return; + return true; } if (!_settings.SnowyDisplay) { if (_frameBufferClear) { - return; + return true; } _frameBufferClear = true; Array.Clear(_frameBuffer, 0, 256 * 192); - return; + return true; } _frameBufferClear = false; @@ -70,6 +70,8 @@ namespace BizHawk.Emulation.Common } Frame++; + + return true; } public int Frame { get; private set; } diff --git a/BizHawk.Emulation.Common/Interfaces/IEmulator.cs b/BizHawk.Emulation.Common/Interfaces/IEmulator.cs index 4d3926d6fc..6920136d94 100644 --- a/BizHawk.Emulation.Common/Interfaces/IEmulator.cs +++ b/BizHawk.Emulation.Common/Interfaces/IEmulator.cs @@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Common /// Whether or not to render video, cores will pass false here in cases such as frame skipping /// Whether or not to render audio, cores will pass here false here in cases such as fast forwarding where bypassing sound may improve speed /// - void FrameAdvance(IController controller, bool render, bool rendersound = true); + bool FrameAdvance(IController controller, bool render, bool rendersound = true); /// /// Gets the current frame count diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 744a7d8c27..dda627b813 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -1201,6 +1201,30 @@ + + + SubNESHawk.cs + + + SubNESHawk.cs + + + SubNESHawk.cs + + + SubNESHawk.cs + + + SubNESHawk.cs + + + SubNESHawk.cs + + + SubNESHawk.cs + + + diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs index 622664bcc7..ba1f2efde3 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Calculators public ControllerDefinition ControllerDefinition => TI83Controller; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; _lagged = true; @@ -59,6 +59,8 @@ namespace BizHawk.Emulation.Cores.Calculators } _isLag = _lagged; + + return true; } public int Frame diff --git a/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IEmulator.cs b/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IEmulator.cs index 23a2bfb521..bb7fe9b5f3 100644 --- a/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IEmulator.cs @@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC public ControllerDefinition ControllerDefinition { get; set; } - public void FrameAdvance(IController controller, bool render, bool renderSound) + public bool FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; @@ -42,6 +42,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { _lagCount++; } + + return true; } public int Frame diff --git a/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IEmulator.cs b/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IEmulator.cs index 8e41c8ba8c..903fc365bd 100644 --- a/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IEmulator.cs @@ -14,9 +14,11 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII public bool DeterministicEmulation => true; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { FrameAdv(controller, render, rendersound); + + return true; } public void ResetCounters() diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IEmulator.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IEmulator.cs index 358a02fcff..29aea5b261 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IEmulator.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public ControllerDefinition ControllerDefinition => C64ControllerDefinition; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _board.Controller = controller; @@ -47,6 +47,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 DoCycle(); } while (_frameCycles != 0); + + return true; } public int Frame => _frame; diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IEmulator.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IEmulator.cs index 1276521373..56e9f0d376 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IEmulator.cs @@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum public ControllerDefinition ControllerDefinition { get; set; } - public void FrameAdvance(IController controller, bool render, bool renderSound) + public bool FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; @@ -42,6 +42,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { _lagCount++; } + + return true; } public int Frame diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs index 1dad16b1d3..23585fb39f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs @@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; @@ -75,6 +75,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 } _tia.LineCount = 0; + + return true; } public int Frame => _frame; diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs index 11ce9c8f23..667ee16c13 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs @@ -57,7 +57,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public bool slow_access = false; public int slow_countdown; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { if (_tracer.Enabled) { @@ -88,6 +88,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { _lagcount++; } + + return true; } public void RunCPUCycle() diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs index e234ae4455..24fb8a0095 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs @@ -120,7 +120,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx public IEmulatorServiceProvider ServiceProvider { get; } - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { Frame++; if (controller.IsPressed("Power")) @@ -135,6 +135,8 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx { LagCount++; } + + return true; } public int Frame { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs index 6d9dda125f..8d8c7b8b48 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs @@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision public ControllerDefinition ControllerDefinition => ControllerDeck.Definition; - public void FrameAdvance(IController controller, bool render, bool renderSound) + public bool FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; @@ -163,6 +163,8 @@ namespace BizHawk.Emulation.Cores.ColecoVision { _lagCount++; } + + return true; } public bool use_SGM = false; diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IEmulator.cs index 7f7c1e717d..0d0dd5dee2 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IEmulator.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Intellivision public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { if (_tracer.Enabled) { @@ -124,6 +124,8 @@ namespace BizHawk.Emulation.Cores.Intellivision { SoftReset(); } + + return true; } public int Frame => _frame; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs index 0028c7b4e9..264d658e98 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs @@ -67,7 +67,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public ControllerDefinition ControllerDefinition => GBA.GBAController; - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { Frame++; if (controller.IsPressed("Power")) @@ -97,6 +97,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA // this should be called in hblank on the appropriate line, but until we implement that, just do it here _scanlinecb?.Invoke(); + + return true; } public int Frame { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs index 676210608f..247d7fd68d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs @@ -95,7 +95,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public IEmulatorServiceProvider ServiceProvider { get; private set; } - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { Frame++; @@ -108,6 +108,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA if (IsLagFrame) LagCount++; + + return true; } public int Frame { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index e0aa0baeef..ca42c1472e 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public bool in_vblank; public bool vblank_rise; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { //Console.WriteLine("-----------------------FRAME-----------------------"); @@ -74,6 +74,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { _lagcount++; } + + return true; } public void do_frame() diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs index 1cebe9f5b4..dc431a50fc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs @@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { //Console.WriteLine("-----------------------FRAME-----------------------"); //Update the color palette if a setting changed @@ -86,6 +86,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink { _lagcount++; } + + return true; } public void do_frame() diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs index 2b55424647..c0b371b389 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs @@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy public ControllerDefinition ControllerDefinition => GbController; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { FrameAdvancePrep(controller); if (_syncSettings.EqualLengthFrames) @@ -68,6 +68,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy } FrameAdvancePost(); + + return true; } public int Frame { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index 1f1891e1a5..b0bdd405d9 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -344,7 +344,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy LibGambatte.gambatte_setlayers(GambatteState, (_settings.DisplayBG ? 1 : 0) | (_settings.DisplayOBJ ? 2 : 0) | (_settings.DisplayWindow ? 4 : 0)); } - internal void FrameAdvancePost() + internal bool FrameAdvancePost() { if (IsLagFrame) { @@ -352,6 +352,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy } endofframecallback?.Invoke(LibGambatte.gambatte_cpuread(GambatteState, 0xff40)); + + return true; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs index 3a835ee5a2..c10f340eae 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs @@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy public ControllerDefinition ControllerDefinition => DualGbController; - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { LCont.Clear(); RCont.Clear(); @@ -148,6 +148,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { LagCount++; } + + return true; } public int Frame { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs index b4c68bf03f..342eaef8c4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs @@ -221,7 +221,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64 RunThreadAction(() => { _pendingThreadTerminate = true; }); } - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _inputProvider.Controller = controller; @@ -258,6 +258,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64 if(!api.IsCrashed) Frame++; + + return true; } public string SystemId { get { return "N64"; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs index 61a0c5fe7c..ce0e72510f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs @@ -244,7 +244,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES int bank_1k = addr >> 10; int ofs = addr & ((1 << 10) - 1); - if (exram_mode == 1 && NES.ppu.ppuphase == PPU.PPUPHASE.BG) + if (exram_mode == 1 && NES.ppu.ppuphase == PPU.PPU_PHASE_BG) { int exram_addr = last_nt_read; int bank_4k = EXRAM[exram_addr] & 0x3F; @@ -261,9 +261,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (NES.ppu.reg_2000.obj_size_16) { bool isPattern = NES.ppu.PPUON; - if (NES.ppu.ppuphase == PPU.PPUPHASE.OBJ && isPattern) + if (NES.ppu.ppuphase == PPU.PPU_PHASE_OBJ && isPattern) bank_1k = a_banks_1k[bank_1k]; - else if (NES.ppu.ppuphase == PPU.PPUPHASE.BG && isPattern) + else if (NES.ppu.ppuphase == PPU.PPU_PHASE_BG && isPattern) bank_1k = b_banks_1k[bank_1k]; else { diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL-TF1201.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL-TF1201.cs index 04df29aadc..c8df6cac0d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL-TF1201.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL-TF1201.cs @@ -80,7 +80,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES case 0xF003: IRQa = value.Bit(1); IRQSignal = false; - if (NES.ppu.ppuphase !=PPU.PPUPHASE.VBL) + if (NES.ppu.ppuphase !=PPU.PPU_PHASE_VBL) IRQCount -= 8; break; } @@ -88,7 +88,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public override void ClockPPU() { - if ((NES.ppu.ppuphase != PPU.PPUPHASE.VBL))// && IRQa) + if ((NES.ppu.ppuphase != PPU.PPU_PHASE_VBL))// && IRQa) { IRQpre--; if (IRQpre==0) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs index 5d5a01ed83..851291e2a1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs @@ -79,7 +79,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES magicSoundProvider = null; } - class MagicSoundProvider : ISoundProvider, IDisposable + public class MagicSoundProvider : ISoundProvider, IDisposable { BlipBuffer blip; NES nes; @@ -157,7 +157,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES } } } - MagicSoundProvider magicSoundProvider; + public MagicSoundProvider magicSoundProvider; public void HardReset() { @@ -311,7 +311,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES bool resetSignal; bool hardResetSignal; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; @@ -377,12 +377,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES } else { - ppu.ppu_init_frame(); - - ppu.do_vbl = true; - ppu.do_active_sl = true; - ppu.do_pre_vbl = true; - // do the vbl ticks seperate, that will save us a few checks that don't happen in active region while (ppu.do_vbl) { @@ -415,6 +409,50 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES // turn off all cheats // any cheats still active will be re-applied by the buspoke at the start of the next frame num_cheats = 0; + + return true; + } + + // these variables are for subframe input control + public bool controller_was_latched; + public bool frame_is_done; + public bool current_strobe; + public bool new_strobe; + public bool alt_lag; + public byte ctrl_1 = 0; + public byte ctrl_2 = 0; + public byte ctrl_1_new = 0; + public byte ctrl_2_new = 0; + public int shift_1; + public int shift_2; + public bool use_sub_input = false; + // this function will run one step of the ppu + // it will return whether the controller is read or not. + public void do_single_step(out bool cont_read, out bool frame_done) + { + controller_was_latched = false; + frame_is_done = false; + + current_strobe = new_strobe; + if (ppu.ppudead > 0) + { + ppu.NewDeadPPU(); + } + else if (ppu.do_vbl) + { + ppu.TickPPU_VBL(); + } + else if (ppu.do_active_sl) + { + ppu.TickPPU_active(); + } + else if (ppu.do_pre_vbl) + { + ppu.TickPPU_preVBL(); + } + + cont_read = controller_was_latched; + frame_done = frame_is_done; } //PAL: @@ -736,6 +774,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES var si = new StrobeInfo(latched4016, value); ControllerDeck.Strobe(si, _controller); latched4016 = value; + new_strobe = (value & 1) > 0; + if (current_strobe && !new_strobe) + { + controller_was_latched = true; + alt_lag = false; + + if (use_sub_input) + { + shift_1 = 7; + shift_2 = 7; + + ctrl_1 = ctrl_1_new; + ctrl_2 = ctrl_2_new; + } + } + + if (use_sub_input && new_strobe) + { + shift_1 = 7; + shift_2 = 7; + } } byte read_joyport(int addr) @@ -743,14 +802,35 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES InputCallbacks.Call(); lagged = false; byte ret = 0; - if (_isVS) + + if (use_sub_input) { - // for whatever reason, in VS left and right controller have swapped regs - ret = addr == 0x4017 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller); + if (addr == 0x4016) + { + if (shift_1 >= 0) { ret = (byte)((ctrl_1 >> shift_1) & 1); } + else { ret = 1; } + + if (!current_strobe) { shift_1 -= 1; } + } + else + { + if (shift_2 >= 0) { ret = (byte)((ctrl_2 >> shift_2) & 1); } + else { ret = 1; } + + if (!current_strobe) { shift_2 -= 1; } + } } else { - ret = addr == 0x4016 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller); + if (_isVS) + { + // for whatever reason, in VS left and right controller have swapped regs + ret = addr == 0x4017 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller); + } + else + { + ret = addr == 0x4016 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller); + } } ret &= 0x1f; @@ -810,7 +890,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public byte DummyReadMemory(ushort addr) { return 0; } - private void ApplySystemBusPoke(int addr, byte value) + public void ApplySystemBusPoke(int addr, byte value) { if (addr < 0x2000) { diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs index e2dd212602..7c7b3f7f17 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs @@ -82,7 +82,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES ser.Sync("VS_Coin", ref VS_coin_inserted); ser.Sync("VS_ROM_Control", ref VS_ROM_control); - ser.BeginSection("Board"); + // single cycle execution related + ser.Sync("current_strobe", ref current_strobe); + ser.Sync("new_strobe", ref new_strobe); + ser.Sync("ctrl_1", ref ctrl_1); + ser.Sync("ctrl_2", ref ctrl_2); + ser.Sync("shift_1", ref shift_1); + ser.Sync("shift_2", ref shift_2); + ser.Sync("use_sub_input", ref use_sub_input); + + ser.BeginSection("Board"); Board.SyncState(ser); if (Board is NESBoardBase && !((NESBoardBase)Board).SyncStateFlag) throw new InvalidOperationException("the current NES mapper didnt call base.SyncState"); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs index 5da37f44c4..62d534f935 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs @@ -126,7 +126,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public DisplayType Region { get { return _display_type; } } - class MyVideoProvider : IVideoProvider + public class MyVideoProvider : IVideoProvider { //public int ntsc_top = 8; //public int ntsc_bottom = 231; @@ -246,7 +246,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public int VsyncDenominator => emu.VsyncDen; } - MyVideoProvider videoProvider; + public MyVideoProvider videoProvider; [Obsolete] // with the changes to both nes and quicknes cores, nothing uses this anymore public static readonly ControllerDefinition NESController = diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs index 36df0ab4c3..b04744f5f8 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs @@ -158,11 +158,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return nes.Board.PeekPPU(addr); } - public enum PPUPHASE - { - VBL, BG, OBJ - }; - public PPUPHASE ppuphase; + public static int PPU_PHASE_VBL = 0; + public static int PPU_PHASE_BG = 1; + public static int PPU_PHASE_OBJ = 2; + + public int ppuphase; private readonly NES nes; public PPU(NES nes) @@ -247,6 +247,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES ser.Sync("OAM", ref OAM, false); ser.Sync("soam", ref soam, false); ser.Sync("PALRAM", ref PALRAM, false); + ser.Sync("ppuphase", ref ppuphase); ser.Sync("Reg2002_objoverflow", ref Reg2002_objoverflow); ser.Sync("Reg2002_objhit", ref Reg2002_objhit); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs index 0fa0bc98cd..739338840a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs @@ -551,7 +551,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES //does this take 4x longer? nestopia indicates so perhaps... int addr = ppur.get_2007access(); - if (ppuphase == PPUPHASE.BG) + if (ppuphase == PPU_PHASE_BG) { if (show_bg_new) { diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs index 3b2199bf06..ead5ce61b5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs @@ -151,7 +151,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES // These things happen at the start of every frame //Reg2002_vblank_active = true; //Reg2002_vblank_active_pending = true; - ppuphase = PPUPHASE.VBL; + ppuphase = PPU_PHASE_VBL; bgdata = new BGDataRecord[34]; } @@ -194,6 +194,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { do_vbl = false; ppur.status.sl = 0; + do_active_sl = true; } } } @@ -216,7 +217,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES sprite_zero_in_range = false; yp = ppur.status.sl - 1; - ppuphase = PPUPHASE.BG; + ppuphase = PPU_PHASE_BG; // "If PPUADDR is not less then 8 when rendering starts, the first 8 bytes in OAM are written to from // the current location of PPUADDR" @@ -615,7 +616,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (soam_index_prev > 8 && !nes.Settings.AllowMoreThanEightSprites) soam_index_prev = 8; - ppuphase = PPUPHASE.OBJ; + ppuphase = PPU_PHASE_OBJ; spriteHeight = reg_2000.obj_size_16 ? 16 : 8; @@ -926,7 +927,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { if (ppur.status.cycle == 320) { - ppuphase = PPUPHASE.BG; + ppuphase = PPU_PHASE_BG; xt = 0; xp = 0; } @@ -992,6 +993,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (ppur.status.sl == 241) { do_active_sl = false; + do_pre_vbl = true; } } } @@ -1012,6 +1014,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (ppur.status.sl == 241 + preNMIlines) { do_pre_vbl = false; + do_vbl = true; + + ppu_init_frame(); + nes.frame_is_done = true; } } } @@ -1033,6 +1039,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (ppur.status.cycle == 241 * 341 - start_up_offset) { ppudead--; + + ppu_init_frame(); + + do_vbl = true; + + nes.frame_is_done = true; } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs index 899ae0254f..aad8579a37 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs @@ -179,7 +179,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES #endregion - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { CheckDisposed(); using (FP.Save()) @@ -211,6 +211,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES if (CB1 != null) CB1(); if (CB2 != null) CB2(); } + + return true; } IntPtr Context; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs index a245fbdbbf..e16511cbaa 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs @@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; @@ -80,6 +80,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES { LagCount++; } + + return true; } public int Frame diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/ReadMe.txt b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/ReadMe.txt new file mode 100644 index 0000000000..bc60bf4b01 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/ReadMe.txt @@ -0,0 +1 @@ +TODO: diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IDebuggable.cs new file mode 100644 index 0000000000..fe41918f23 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IDebuggable.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public partial class SubNESHawk : IDebuggable + { + public IDictionary GetCpuFlagsAndRegisters() + { + return new Dictionary + { + /* + ["A"] = cpu.A, + ["X"] = cpu.X, + ["Y"] = cpu.Y, + ["S"] = cpu.S, + ["PC"] = cpu.PC, + ["Flag C"] = cpu.FlagC, + ["Flag Z"] = cpu.FlagZ, + ["Flag I"] = cpu.FlagI, + ["Flag D"] = cpu.FlagD, + ["Flag B"] = cpu.FlagB, + ["Flag V"] = cpu.FlagV, + ["Flag N"] = cpu.FlagN, + ["Flag T"] = cpu.FlagT + */ + }; + } + + public void SetCpuRegister(string register, int value) + { + switch (register) + { + default: + throw new InvalidOperationException(); + case "A": + //cpu.A = (byte)value; + break; + case "X": + //cpu.X = (byte)value; + break; + case "Y": + //cpu.Y = (byte)value; + break; + case "S": + //cpu.S = (byte)value; + break; + case "PC": + //cpu.PC = (ushort)value; + break; + case "Flag I": + //cpu.FlagI = value > 0; + break; + } + } + + public bool CanStep(StepType type) + { + return false; + } + + public IMemoryCallbackSystem MemoryCallbacks { get; private set; } + + [FeatureNotImplemented] + public void Step(StepType type) { throw new NotImplementedException(); } + + public long TotalExecutedCycles + { + get { return subnes.cpu.TotalExecutedCycles; } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IEmulator.cs new file mode 100644 index 0000000000..3fef3f0d45 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IEmulator.cs @@ -0,0 +1,215 @@ +using System; + +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Nintendo.NES; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public partial class SubNESHawk : IEmulator + { + public IEmulatorServiceProvider ServiceProvider { get; } + + public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; + + public bool FrameAdvance(IController controller, bool render, bool rendersound) + { + //Console.WriteLine("-----------------------FRAME-----------------------"); + if (_tracer.Enabled) + { + subnes.cpu.TraceCallback = s => _tracer.Put(s); + } + else + { + subnes.cpu.TraceCallback = null; + } + + _frame++; + + if (controller.IsPressed("Power")) + { + HardReset(); + } + + if (controller.IsPressed("Reset")) + { + SoftReset(); + } + + _islag = true; + subnes.alt_lag = true; + + GetControllerState(controller); + + do_frame(); + + bool ret = pass_a_frame; + + if (pass_a_frame) + { + subnes.videoProvider.FillFrameBuffer(); + } + + _islag = subnes.alt_lag; + + if (_islag) + { + _lagcount++; + } + + return ret; + } + + public bool stop_cur_frame; + public bool pass_new_input; + public bool pass_a_frame; + public byte ctrl_byte_1; + public byte ctrl_byte_2; + + public void do_frame() + { + stop_cur_frame = false; + while (!stop_cur_frame) + { + subnes.do_single_step(out pass_new_input, out pass_a_frame); + stop_cur_frame |= pass_a_frame; + stop_cur_frame |= pass_new_input; + } + } + + public void GetControllerState(IController controller) + { + InputCallbacks.Call(); + + ctrl_byte_1 = _controllerDeck.ReadPort1(controller); + ctrl_byte_2 = _controllerDeck.ReadPort2(controller); + + subnes.ctrl_1_new = ctrl_byte_1; + subnes.ctrl_2_new = ctrl_byte_2; + } + + public int Frame => _frame; + + public string SystemId => "NES"; + + public bool DeterministicEmulation { get; set; } + + public void ResetCounters() + { + _frame = 0; + _lagcount = 0; + _islag = false; + } + + public CoreComm CoreComm { get; } + + public void Dispose() + { + subnes.Dispose(); + } + /* + #region Video provider + + public int _frameHz = 60; + + public int[] _vidbuffer = new int[160 * 2 * 144]; + public int[] buff_L = new int[160 * 144]; + public int[] buff_R = new int[160 * 144]; + + public int[] GetVideoBuffer() + { + // combine the 2 video buffers from the instances + for (int i = 0; i < 144; i++) + { + for (int j = 0; j < 160; j++) + { + _vidbuffer[i * 320 + j] = buff_L[i * 160 + j]; + _vidbuffer[i * 320 + j + 160] = buff_R[i * 160 + j]; + } + } + + return _vidbuffer; + } + + public int VirtualWidth => 160 * 2; + public int VirtualHeight => 144; + public int BufferWidth => 160 * 2; + public int BufferHeight => 144; + public int BackgroundColor => unchecked((int)0xFF000000); + public int VsyncNumerator => _frameHz; + public int VsyncDenominator => 1; + + public static readonly uint[] color_palette_BW = { 0xFFFFFFFF , 0xFFAAAAAA, 0xFF555555, 0xFF000000 }; + public static readonly uint[] color_palette_Gr = { 0xFFA4C505, 0xFF88A905, 0xFF1D551D, 0xFF052505 }; + + public uint[] color_palette = new uint[4]; + + #endregion + + #region audio + + public bool CanProvideAsync => false; + + public void SetSyncMode(SyncSoundMode mode) + { + if (mode != SyncSoundMode.Sync) + { + throw new InvalidOperationException("Only Sync mode is supported_"); + } + } + + public SyncSoundMode SyncMode => SyncSoundMode.Sync; + + public void GetSamplesSync(out short[] samples, out int nsamp) + { + short[] temp_samp_L; + short[] temp_samp_R; + + int nsamp_L; + int nsamp_R; + + L.audio.GetSamplesSync(out temp_samp_L, out nsamp_L); + R.audio.GetSamplesSync(out temp_samp_R, out nsamp_R); + + if (linkSettings.AudioSet == GBLinkSettings.AudioSrc.Left) + { + samples = temp_samp_L; + nsamp = nsamp_L; + } + else if (linkSettings.AudioSet == GBLinkSettings.AudioSrc.Right) + { + samples = temp_samp_R; + nsamp = nsamp_R; + } + else + { + samples = new short[0]; + nsamp = 0; + } + } + + public void GetSamplesAsync(short[] samples) + { + throw new NotSupportedException("Async is not available"); + } + + public void DiscardSamples() + { + L.audio.DiscardSamples(); + R.audio.DiscardSamples(); + } + + private void GetSamples(short[] samples) + { + + } + + public void DisposeSound() + { + L.audio.DisposeSound(); + R.audio.DisposeSound(); + } + + #endregion + */ + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IInputPollable.cs new file mode 100644 index 0000000000..04c6faea5c --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IInputPollable.cs @@ -0,0 +1,24 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public partial class SubNESHawk : IInputPollable + { + public int LagCount + { + get { return _lagcount; } + set { _lagcount = value; } + } + + public bool IsLagFrame + { + get { return _islag; } + set { _islag = value; } + } + + public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem(); + + public bool _islag = true; + private int _lagcount; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IMemoryDomains.cs new file mode 100644 index 0000000000..b1aafedaf7 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IMemoryDomains.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public partial class SubNESHawk + { + private MemoryDomainList _memoryDomains; + private bool _memoryDomainsSetup = false; + + private void SetupMemoryDomains() + { + var domains = new List(); + var RAM = new MemoryDomainByteArray("RAM", MemoryDomain.Endian.Little, subnes.ram, true, 1); + var SystemBus = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little, + addr => subnes.PeekMemory((ushort)addr), (addr, value) => subnes.ApplySystemBusPoke((int)addr, value), 1); + var PPUBus = new MemoryDomainDelegate("PPU Bus", 0x4000, MemoryDomain.Endian.Little, + addr => subnes.ppu.ppubus_peek((int)addr), (addr, value) => subnes.ppu.ppubus_write((int)addr, value), 1); + var CIRAMdomain = new MemoryDomainByteArray("CIRAM (nametables)", MemoryDomain.Endian.Little, subnes.CIRAM, true, 1); + var OAMdoman = new MemoryDomainByteArray("OAM", MemoryDomain.Endian.Unknown, subnes.ppu.OAM, true, 1); + + domains.Add(RAM); + domains.Add(SystemBus); + domains.Add(PPUBus); + domains.Add(CIRAMdomain); + domains.Add(OAMdoman); + + if (!(subnes.Board is NES.FDS) && subnes.Board.SaveRam != null) + { + var BatteryRam = new MemoryDomainByteArray("Battery RAM", MemoryDomain.Endian.Little, subnes.Board.SaveRam, true, 1); + domains.Add(BatteryRam); + } + + if (subnes.Board.ROM != null) + { + var PRGROM = new MemoryDomainByteArray("PRG ROM", MemoryDomain.Endian.Little, subnes.Board.ROM, true, 1); + domains.Add(PRGROM); + } + + if (subnes.Board.VROM != null) + { + var CHRROM = new MemoryDomainByteArray("CHR VROM", MemoryDomain.Endian.Little, subnes.Board.VROM, true, 1); + domains.Add(CHRROM); + } + + if (subnes.Board.VRAM != null) + { + var VRAM = new MemoryDomainByteArray("VRAM", MemoryDomain.Endian.Little, subnes.Board.VRAM, true, 1); + domains.Add(VRAM); + } + + if (subnes.Board.WRAM != null) + { + var WRAM = new MemoryDomainByteArray("WRAM", MemoryDomain.Endian.Little, subnes.Board.WRAM, true, 1); + domains.Add(WRAM); + } + + // if there were more boards with special ram sets, we'd want to do something more general + if (subnes.Board is NES.FDS) + { + domains.Add((subnes.Board as NES.FDS).GetDiskPeeker()); + } + else if (subnes.Board is NES.ExROM) + { + domains.Add((subnes.Board as NES.ExROM).GetExRAM()); + } + + if (!_memoryDomainsSetup) + { + _memoryDomains = new MemoryDomainList(domains); + (ServiceProvider as BasicServiceProvider).Register(_memoryDomains); + _memoryDomainsSetup = true; + } + else + { + var src = new MemoryDomainList(domains); + _memoryDomains.MergeList(src); + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.ISaveRam.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.ISaveRam.cs new file mode 100644 index 0000000000..1d61877e5b --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.ISaveRam.cs @@ -0,0 +1,42 @@ +using System; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public partial class SubNESHawk : ISaveRam + { + public bool SaveRamModified + { + get + { + if (subnes.Board == null) return false; + if (subnes.Board is NES.FDS) return true; + if (subnes.Board.SaveRam == null) return false; + return true; + } + } + + public byte[] CloneSaveRam() + { + if (subnes.Board is NES.FDS) + return (subnes.Board as NES.FDS).ReadSaveRam(); + + if (subnes.Board == null || subnes.Board.SaveRam == null) + return null; + return (byte[])subnes.Board.SaveRam.Clone(); + } + + public void StoreSaveRam(byte[] data) + { + if (subnes.Board is NES.FDS) + { + (subnes.Board as NES.FDS).StoreSaveRam(data); + return; + } + + if (subnes.Board == null || subnes.Board.SaveRam == null) + return; + Array.Copy(data, subnes.Board.SaveRam, data.Length); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.ISettable.cs new file mode 100644 index 0000000000..9db3f0acc1 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.ISettable.cs @@ -0,0 +1,58 @@ +using System; + +using BizHawk.Common; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Nintendo.NES; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public partial class SubNESHawk : IEmulator, IStatable, ISettable + { + public SubNESHawkSettings GetSettings() + { + return subnesSettings.Clone(); + } + + public SubNESHawkSyncSettings GetSyncSettings() + { + return subnesSyncSettings.Clone(); + } + + public bool PutSettings(SubNESHawkSettings o) + { + subnesSettings = o; + return false; + } + + public bool PutSyncSettings(SubNESHawkSyncSettings o) + { + bool ret = SubNESHawkSyncSettings.NeedsReboot(subnesSyncSettings, o); + subnesSyncSettings = o; + return ret; + } + + private SubNESHawkSettings subnesSettings = new SubNESHawkSettings(); + public SubNESHawkSyncSettings subnesSyncSettings = new SubNESHawkSyncSettings(); + + public class SubNESHawkSettings + { + public SubNESHawkSettings Clone() + { + return (SubNESHawkSettings)MemberwiseClone(); + } + } + + public class SubNESHawkSyncSettings + { + public SubNESHawkSyncSettings Clone() + { + return (SubNESHawkSyncSettings)MemberwiseClone(); + } + + public static bool NeedsReboot(SubNESHawkSyncSettings x, SubNESHawkSyncSettings y) + { + return !DeepEquality.DeepEquals(x, y); + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IStatable.cs new file mode 100644 index 0000000000..d6a092971e --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IStatable.cs @@ -0,0 +1,63 @@ +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Nintendo.NES; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public partial class SubNESHawk : IStatable + { + public bool BinarySaveStatesPreferred => true; + + public void SaveStateText(TextWriter writer) + { + subnes.SaveStateText(writer); + SyncState(new Serializer(writer)); + } + + public void LoadStateText(TextReader reader) + { + subnes.LoadStateText(reader); + SyncState(new Serializer(reader)); + } + + public void SaveStateBinary(BinaryWriter bw) + { + subnes.SaveStateBinary(bw); + // other variables + SyncState(new Serializer(bw)); + } + + public void LoadStateBinary(BinaryReader br) + { + subnes.LoadStateBinary(br); + // other variables + SyncState(new Serializer(br)); + } + + public byte[] SaveStateBinary() + { + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + SaveStateBinary(bw); + bw.Flush(); + return ms.ToArray(); + } + + //private JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented }; + + private void SyncState(Serializer ser) + { + ser.Sync("Lag", ref _lagcount); + ser.Sync("Frame", ref _frame); + ser.Sync("IsLag", ref _islag); + ser.Sync("pass_a_frame", ref pass_a_frame); + ser.Sync("pass_new_input", ref pass_new_input); + ser.Sync("ctrl_byte_1", ref ctrl_byte_1); + ser.Sync("ctrl_byte_2", ref ctrl_byte_2); + + _controllerDeck.SyncState(ser); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs new file mode 100644 index 0000000000..a04a68f7f8 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs @@ -0,0 +1,80 @@ +using System; + +using BizHawk.Emulation.Common; + +using BizHawk.Emulation.Cores.Nintendo.NES; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + [Core( + "SubNESHawk", + "", + isPorted: false, + isReleased: false)] + [ServiceNotApplicable(typeof(IDriveLight))] + public partial class SubNESHawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable, + ISettable + { + public NES.NES subnes; + + [CoreConstructor("NES")] + public SubNESHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings) + { + var ser = new BasicServiceProvider(this); + + subnesSettings = (SubNESHawkSettings)settings ?? new SubNESHawkSettings(); + subnesSyncSettings = (SubNESHawkSyncSettings)syncSettings ?? new SubNESHawkSyncSettings(); + _controllerDeck = new SubNESHawkControllerDeck(SubNESHawkControllerDeck.DefaultControllerName, SubNESHawkControllerDeck.DefaultControllerName); + + CoreComm = comm; + + var temp_set = new NES.NES.NESSettings(); + + var temp_sync = new NES.NES.NESSyncSettings(); + + subnes = new NES.NES(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider }, + game, rom, temp_set, temp_sync); + + ser.Register(subnes.videoProvider); + ser.Register(subnes.magicSoundProvider); + + _tracer = new TraceBuffer { Header = subnes.cpu.TraceHeader }; + ser.Register(_tracer); + + ServiceProvider = ser; + + SetupMemoryDomains(); + + HardReset(); + + // input override for subframe input + subnes.use_sub_input = true; + } + + public void HardReset() + { + subnes.HardReset(); + } + + public void SoftReset() + { + subnes.Board.NESSoftReset(); + subnes.cpu.NESSoftReset(); + subnes.apu.NESSoftReset(); + subnes.ppu.NESSoftReset(); + } + + public DisplayType Region => DisplayType.NTSC; + + public int _frame = 0; + + private readonly SubNESHawkControllerDeck _controllerDeck; + + private readonly ITraceable _tracer; + + private void ExecFetch(ushort addr) + { + MemoryCallbacks.CallExecutes(addr, "System Bus"); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawkControllerDeck.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawkControllerDeck.cs new file mode 100644 index 0000000000..7f2ecfae40 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawkControllerDeck.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using BizHawk.Common; +using BizHawk.Common.ReflectionExtensions; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + public class SubNESHawkControllerDeck + { + public SubNESHawkControllerDeck(string controller1Name, string controller2Name) + { + if (!ValidControllerTypes.ContainsKey(controller1Name)) + { + throw new InvalidOperationException("Invalid controller type: " + controller1Name); + } + + if (!ValidControllerTypes.ContainsKey(controller2Name)) + { + throw new InvalidOperationException("Invalid controller type: " + controller2Name); + } + + Port1 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller1Name], 1); + Port2 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller2Name], 2); + + Definition = new ControllerDefinition + { + Name = Port1.Definition.Name, + BoolButtons = Port1.Definition.BoolButtons + .Concat(Port2.Definition.BoolButtons) + .Concat(new[] + { + "Power", + "Reset", + }) + .ToList() + }; + } + + public byte ReadPort1(IController c) + { + return Port1.Read(c); + } + + public byte ReadPort2(IController c) + { + return Port2.Read(c); + } + + public ControllerDefinition Definition { get; } + + public void SyncState(Serializer ser) + { + ser.BeginSection("Port1"); + Port1.SyncState(ser); + ser.EndSection(); + + ser.BeginSection("Port2"); + Port2.SyncState(ser); + ser.EndSection(); + } + + private readonly IPort Port1; + private readonly IPort Port2; + + private static Dictionary _controllerTypes; + + public static Dictionary ValidControllerTypes + { + get + { + if (_controllerTypes == null) + { + _controllerTypes = typeof(SubNESHawkControllerDeck).Assembly + .GetTypes() + .Where(t => typeof(IPort).IsAssignableFrom(t)) + .Where(t => !t.IsAbstract && !t.IsInterface) + .ToDictionary(tkey => tkey.DisplayName()); + } + + return _controllerTypes; + } + } + + public static string DefaultControllerName => typeof(StandardControls).DisplayName(); + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawkControllers.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawkControllers.cs new file mode 100644 index 0000000000..44e9e5e98d --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawkControllers.cs @@ -0,0 +1,94 @@ +using System; + +using System.ComponentModel; +using System.Linq; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk +{ + /// + /// Represents a Standard Nintendo Controller + /// + public interface IPort + { + byte Read(IController c); + + ControllerDefinition Definition { get; } + + void SyncState(Serializer ser); + + int PortNum { get; } + } + + [DisplayName("NES Controller")] + public class StandardControls : IPort + { + public StandardControls(int portNum) + { + PortNum = portNum; + Definition = new ControllerDefinition + { + Name = "NES Controller", + BoolButtons = BaseDefinition + .Select(b => "P" + PortNum + " " + b) + .ToList() + }; + } + + public int PortNum { get; } + + public ControllerDefinition Definition { get; } + + public byte Read(IController c) + { + byte result = 0; + + if (c.IsPressed(Definition.BoolButtons[0])) + { + result |= 8; + } + if (c.IsPressed(Definition.BoolButtons[1])) + { + result |= 4; + } + if (c.IsPressed(Definition.BoolButtons[2])) + { + result |= 2; + } + if (c.IsPressed(Definition.BoolButtons[3])) + { + result |= 1; + } + if (c.IsPressed(Definition.BoolButtons[4])) + { + result |= 16; + } + if (c.IsPressed(Definition.BoolButtons[5])) + { + result |= 32; + } + if (c.IsPressed(Definition.BoolButtons[6])) + { + result |= 64; + } + if (c.IsPressed(Definition.BoolButtons[7])) + { + result |= 128; + } + + return result; + } + + private static readonly string[] BaseDefinition = + { + "Up", "Down", "Left", "Right", "Start", "Select", "B", "A" + }; + + public void SyncState(Serializer ser) + { + //nothing + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs index 5fa7f01d7e..6b46010327 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.PCEngine public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; _lagged = true; @@ -39,6 +39,8 @@ namespace BizHawk.Emulation.Cores.PCEngine { _isLag = false; } + + return true; } public int Frame diff --git a/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs b/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs index 462b62fbee..ae20720922 100644 --- a/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs +++ b/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs @@ -47,7 +47,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK _serviceProvider.Register(_videoProvider); } - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { var t1 = Task.Run(() => { @@ -67,6 +67,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK Frame++; _soundProvider.Fetch(); _videoProvider.Fetch(); + + return true; } #region link cable diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs index 1ac7e86924..d3fbefd440 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs @@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } } - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; _lagged = true; @@ -86,6 +86,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { _isLag = false; } + + return true; } public int Frame => _frame; diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs index e0a3ac20b1..475d1562fc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs @@ -7,45 +7,45 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { public IEmulatorServiceProvider ServiceProvider { get; private set; } - public ControllerDefinition ControllerDefinition { get; private set; } - - // TODO: use render and rendersound - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public ControllerDefinition ControllerDefinition { get; private set; } + + // TODO: use render and rendersound + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { if (controller.IsPressed("Reset")) Core.gpgx_reset(false); if (controller.IsPressed("Power")) - Core.gpgx_reset(true); - if (_cds != null) - { - var prev = controller.IsPressed("Previous Disk"); - var next = controller.IsPressed("Next Disk"); - int newDisk = _discIndex; - if (prev && !_prevDiskPressed) - newDisk--; - if (next && !_nextDiskPressed) - newDisk++; - - _prevDiskPressed = prev; - _nextDiskPressed = next; - - if (newDisk < -1) - newDisk = -1; - if (newDisk >= _cds.Length) - newDisk = _cds.Length - 1; - - if (newDisk != _discIndex) - { - _discIndex = newDisk; - Core.gpgx_swap_disc(_discIndex == -1 ? null : GetCDDataStruct(_cds[_discIndex])); - Console.WriteLine("IMMA CHANGING MAH DISKS"); - } - } - - // this shouldn't be needed, as nothing has changed - // if (!Core.gpgx_get_control(input, inputsize)) - // throw new Exception("gpgx_get_control() failed!"); - + Core.gpgx_reset(true); + if (_cds != null) + { + var prev = controller.IsPressed("Previous Disk"); + var next = controller.IsPressed("Next Disk"); + int newDisk = _discIndex; + if (prev && !_prevDiskPressed) + newDisk--; + if (next && !_nextDiskPressed) + newDisk++; + + _prevDiskPressed = prev; + _nextDiskPressed = next; + + if (newDisk < -1) + newDisk = -1; + if (newDisk >= _cds.Length) + newDisk = _cds.Length - 1; + + if (newDisk != _discIndex) + { + _discIndex = newDisk; + Core.gpgx_swap_disc(_discIndex == -1 ? null : GetCDDataStruct(_cds[_discIndex])); + Console.WriteLine("IMMA CHANGING MAH DISKS"); + } + } + + // this shouldn't be needed, as nothing has changed + // if (!Core.gpgx_get_control(input, inputsize)) + // throw new Exception("gpgx_get_control() failed!"); + ControlConverter.ScreenWidth = vwidth; ControlConverter.ScreenHeight = vheight; ControlConverter.Convert(controller, input); @@ -66,6 +66,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx if (_cds != null) DriveLightOn = _drivelight; + + return true; } public int Frame { get; private set; } @@ -96,7 +98,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx if (_elf != null) _elf.Dispose(); if (_cds != null) - foreach (var cd in _cds) + foreach (var cd in _cds) cd.Dispose(); _disposed = true; } diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSP/PSP.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSP/PSP.cs index 5c43900826..55157f7abe 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sony/PSP/PSP.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSP/PSP.cs @@ -131,7 +131,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSP } - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { Frame++; UpdateInput(controller); @@ -147,6 +147,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSP //nsampavail = PPSSPPDll.mixsound(audiobuffer, audiobuffer.Length / 2); LogFlush(); //Console.WriteLine("Audio Service: {0}", nsampavail); + + return true; } public int Frame diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs index 807558d6b3..eca318a577 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs @@ -743,7 +743,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX private IController _controller; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; FrameAdvance_PrepDiscState(); @@ -801,7 +801,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX LagCount++; //what happens to sound in this case? - if (render == false) return; + if (render == false) return true; OctoshockDll.ShockFramebufferInfo fb = new OctoshockDll.ShockFramebufferInfo(); @@ -843,6 +843,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSX if (sbuffcontains * 2 > sbuff.Length) throw new InvalidOperationException("shock_GetSamples returned too many samples: " + sbuffcontains); OctoshockDll.shock_GetSamples(psx, samples); } + + return true; } public ControllerDefinition ControllerDefinition { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs b/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs index 49f91a1824..b5224065ea 100644 --- a/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs +++ b/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs @@ -61,7 +61,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan } } - public void FrameAdvance(IController controller, bool render, bool rendersound = true) + public bool FrameAdvance(IController controller, bool render, bool rendersound = true) { Frame++; IsLagFrame = true; @@ -79,6 +79,8 @@ namespace BizHawk.Emulation.Cores.WonderSwan if (IsLagFrame) LagCount++; + + return true; } public CoreComm CoreComm { get; private set; } diff --git a/BizHawk.Emulation.Cores/Libretro/LibretroCore.cs b/BizHawk.Emulation.Cores/Libretro/LibretroCore.cs index f52709963b..3d3fca7bb9 100644 --- a/BizHawk.Emulation.Cores/Libretro/LibretroCore.cs +++ b/BizHawk.Emulation.Cores/Libretro/LibretroCore.cs @@ -154,11 +154,13 @@ namespace BizHawk.Emulation.Cores.Libretro private IController _controller; - public void FrameAdvance(IController controller, bool render, bool rendersound) + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; api.CMD_Run(); timeFrameCounter++; + + return true; } GCHandle vidBufferHandle; diff --git a/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs b/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs index 3c717bb65f..f202a6b3dd 100644 --- a/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs +++ b/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs @@ -191,7 +191,7 @@ namespace BizHawk.Emulation.Cores.Waterbox protected virtual void FrameAdvancePost() { } - public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true) + public unsafe bool FrameAdvance(IController controller, bool render, bool rendersound = true) { using (_exe.EnterExit()) { @@ -218,6 +218,8 @@ namespace BizHawk.Emulation.Cores.Waterbox FrameAdvancePost(); } } + + return true; } private bool _disposed = false;