From f3e9958f0780165e0091361643061e0970f29f84 Mon Sep 17 00:00:00 2001 From: goyuken Date: Sat, 1 Nov 2014 17:44:04 +0000 Subject: [PATCH] quicknes: support unplugging controllers --- BizHawk.Client.EmuHawk/MainForm.Events.cs | 7 +- .../config/GenericCoreConfig.cs | 17 ++- .../Consoles/Nintendo/NES/NES.cs | 1 + .../Consoles/Nintendo/QuickNES/QuickNES.cs | 143 ++++++++++++------ output/dll/libquicknes.dll | Bin 415545 -> 415545 bytes quicknes/nes_emu/Nes_Core.cpp | 4 +- quicknes/nes_emu/Nes_Core.h | 2 +- quicknes/nes_emu/Nes_Emu.cpp | 6 +- quicknes/nes_emu/Nes_Emu.h | 5 +- quicknes/nes_emu/nes_data.h | 2 +- 10 files changed, 131 insertions(+), 56 deletions(-) diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index 11e551e347..2f96d23e1a 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -1216,7 +1216,7 @@ namespace BizHawk.Client.EmuHawk MovieSettingsMenuItem.Enabled = Global.Emulator is NES; - NesControllerSettingsMenuItem.Enabled = Global.Emulator is NES && !Global.MovieSession.Movie.IsActive; + NesControllerSettingsMenuItem.Enabled = (Global.Emulator is NES || Global.Emulator is QuickNES) && !Global.MovieSession.Movie.IsActive; MovieSettingsMenuItem.Enabled = Global.Emulator is NES && !Global.MovieSession.Movie.IsActive; barcodeReaderToolStripMenuItem.Enabled = BarcodeEntry.HasReader(); @@ -1285,7 +1285,10 @@ namespace BizHawk.Client.EmuHawk private void NesControllerSettingsMenuItem_Click(object sender, EventArgs e) { - new NesControllerSettings().ShowDialog(); + if (Global.Emulator is NES) + new NesControllerSettings().ShowDialog(); + else if (Global.Emulator is QuickNES) + GenericCoreConfig.DoDialog(this, "QuickNES Controller Settings", true, false); } private void MovieSettingsMenuItem_Click(object sender, EventArgs e) diff --git a/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs b/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs index 4c1a738a29..9adacfe74c 100644 --- a/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs +++ b/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs @@ -18,15 +18,15 @@ namespace BizHawk.Client.EmuHawk object ss; bool syncsettingschanged = false; - GenericCoreConfig() + GenericCoreConfig(bool ignoresettings, bool ignoresyncsettings) { InitializeComponent(); var settable = new SettingsAdapter(Global.Emulator); - if (settable.HasSettings) + if (settable.HasSettings && !ignoresettings) s = settable.GetSettings(); - if (settable.HasSyncSettings) + if (settable.HasSyncSettings && !ignoresyncsettings) ss = settable.GetSyncSettings(); if (s != null) @@ -42,6 +42,11 @@ namespace BizHawk.Client.EmuHawk propertyGrid2.Enabled = false; // disable changes to sync setting when movie, so as not to confuse user } + GenericCoreConfig() + :this(false, false) + { + } + private void button1_Click(object sender, EventArgs e) { var settable = new SettingsAdapter(Global.Emulator); @@ -63,6 +68,12 @@ namespace BizHawk.Client.EmuHawk dlg.ShowDialog(owner); } + public static void DoDialog(IWin32Window owner, string title, bool hidesettings, bool hidesyncsettings) + { + using (var dlg = new GenericCoreConfig(hidesettings, hidesyncsettings) { Text = title }) + dlg.ShowDialog(owner); + } + private void propertyGrid2_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) { syncsettingschanged = true; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs index 05e2ad6021..114bb87714 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs @@ -285,6 +285,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public bool StartAsyncSound() { return true; } public void EndAsyncSound() { } + [Obsolete] // with the changes to both nes and quicknes cores, nothing uses this anymore public static readonly ControllerDefinition NESController = new ControllerDefinition { diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs index 3e730452f5..c8cf956dc2 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs @@ -62,7 +62,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES } [CoreConstructor("NES")] - public QuickNES(CoreComm comm, byte[] file, object Settings) + public QuickNES(CoreComm comm, byte[] file, object Settings, object SyncSettings) { using (FP.Save()) { @@ -88,6 +88,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES CoreComm.VsyncDen = 655171; PutSettings((QuickNESSettings)Settings ?? new QuickNESSettings()); + _SyncSettings = (QuickNESSyncSettings)SyncSettings ?? new QuickNESSyncSettings(); + _SyncSettings_next = _SyncSettings.Clone(); + + SetControllerDefinition(); ComputeBootGod(); } catch @@ -100,45 +104,71 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES #region Controller - public ControllerDefinition ControllerDefinition { get { return Emulation.Cores.Nintendo.NES.NES.NESController; } } + public ControllerDefinition ControllerDefinition { get; private set; } public IController Controller { get; set; } + void SetControllerDefinition() + { + var def = new ControllerDefinition(); + def.Name = "NES Controller"; + def.BoolButtons.AddRange(new[] { "Reset", "Power" }); // console buttons + if (_SyncSettings.LeftPortConnected || _SyncSettings.RightPortConnected) + def.BoolButtons.AddRange(PadP1.Select(p => p.Name)); + if (_SyncSettings.LeftPortConnected && _SyncSettings.RightPortConnected) + def.BoolButtons.AddRange(PadP2.Select(p => p.Name)); + ControllerDefinition = def; + } + + private struct PadEnt + { + public readonly string Name; + public readonly int Mask; + public PadEnt(string Name, int Mask) + { + this.Name = Name; + this.Mask = Mask; + } + } + + private static PadEnt[] GetPadList(int player) + { + string prefix = string.Format("P{0} ", player); + return PadNames.Zip(PadMasks, (s, i) => new PadEnt(prefix + s, i)).ToArray(); + } + + private static string[] PadNames = new[] + { + "Up", "Down", "Left", "Right", "Start", "Select", "B", "A" + }; + private static int[] PadMasks = new[] + { + 16, 32, 64, 128, 8, 4, 2, 1 + }; + + private static PadEnt[] PadP1 = GetPadList(1); + private static PadEnt[] PadP2 = GetPadList(2); + + private int GetPad(IEnumerable buttons) + { + int ret = 0; + foreach (var b in buttons) + { + if (Controller[b.Name]) + ret |= b.Mask; + } + return ret; + } + void SetPads(out int j1, out int j2) { - j1 = 0; - j2 = 0; - if (Controller["P1 A"]) - j1 |= 1; - if (Controller["P1 B"]) - j1 |= 2; - if (Controller["P1 Select"]) - j1 |= 4; - if (Controller["P1 Start"]) - j1 |= 8; - if (Controller["P1 Up"]) - j1 |= 16; - if (Controller["P1 Down"]) - j1 |= 32; - if (Controller["P1 Left"]) - j1 |= 64; - if (Controller["P1 Right"]) - j1 |= 128; - if (Controller["P2 A"]) - j2 |= 1; - if (Controller["P2 B"]) - j2 |= 2; - if (Controller["P2 Select"]) - j2 |= 4; - if (Controller["P2 Start"]) - j2 |= 8; - if (Controller["P2 Up"]) - j2 |= 16; - if (Controller["P2 Down"]) - j2 |= 32; - if (Controller["P2 Left"]) - j2 |= 64; - if (Controller["P2 Right"]) - j2 |= 128; + if (_SyncSettings.LeftPortConnected) + j1 = GetPad(PadP1) | unchecked((int)0xffffff00); + else + j1 = 0; + if (_SyncSettings.RightPortConnected) + j2 = GetPad(_SyncSettings.LeftPortConnected ? PadP2 : PadP1) | unchecked((int)0xffffff00); + else + j2 = 0; } #endregion @@ -378,7 +408,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES void ComputeBootGod() { // inefficient, sloppy, etc etc - Emulation.Cores.Nintendo.NES.NES.BootGodDB.Initialize(); + Emulation.Cores.Nintendo.NES.NES.BootGodDB.Initialize(); var chrrom = MemoryDomains["CHR VROM"]; var prgrom = MemoryDomains["PRG ROM"]; @@ -504,17 +534,42 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES } } - QuickNESSettings _Settings; - - // what is this for? public class QuickNESSyncSettings { + [DefaultValue(true)] + public bool LeftPortConnected { get; set; } + + [DefaultValue(true)] + public bool RightPortConnected { get; set; } + + public QuickNESSyncSettings() + { + SettingsUtil.SetDefaultValues(this); + } + public QuickNESSyncSettings Clone() { - return new QuickNESSyncSettings(); + return (QuickNESSyncSettings)MemberwiseClone(); + } + + public static bool NeedsReboot(QuickNESSyncSettings x, QuickNESSyncSettings y) + { + // the core can handle dynamic plugging and unplugging, but that changes + // the controllerdefinition, and we're not ready for that + return !DeepEquality.DeepEquals(x, y); } } + QuickNESSettings _Settings; + /// + /// the syncsettings that this run of emulation is using (was passed to ctor) + /// + QuickNESSyncSettings _SyncSettings; + /// + /// the syncsettings that were requested but won't be used yet + /// + QuickNESSyncSettings _SyncSettings_next; + public QuickNESSettings GetSettings() { return _Settings.Clone(); @@ -522,7 +577,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES public QuickNESSyncSettings GetSyncSettings() { - return new QuickNESSyncSettings(); + return _SyncSettings_next.Clone(); } public bool PutSettings(QuickNESSettings o) @@ -536,7 +591,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES public bool PutSyncSettings(QuickNESSyncSettings o) { - return false; + bool ret = QuickNESSyncSettings.NeedsReboot(_SyncSettings, o); + _SyncSettings_next = o; + return ret; } #endregion diff --git a/output/dll/libquicknes.dll b/output/dll/libquicknes.dll index 8310b2ed79133876aa3320f20c0614b9cb5080df..4c8bc9642aa0f8c9fb866338aed380cc63ad3faa 100644 GIT binary patch delta 37884 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 b(u#l7gyTFCe4<|5-(;w)3_iRl@>>1}r>QH5 diff --git a/quicknes/nes_emu/Nes_Core.cpp b/quicknes/nes_emu/Nes_Core.cpp index de99321189..e79d3e89cf 100644 --- a/quicknes/nes_emu/Nes_Core.cpp +++ b/quicknes/nes_emu/Nes_Core.cpp @@ -305,9 +305,9 @@ int Nes_Core::read_io( nes_addr_t addr ) // to do: to aid with recording, doesn't emulate transparent latch, // so a game that held strobe at 1 and read $4016 or $4017 would not get // the current A status as occurs on a NES - unsigned long result = joypad.joypad_latches [addr & 1]; + int32_t result = joypad.joypad_latches [addr & 1]; if ( !(joypad.w4016 & 1) ) - joypad.joypad_latches [addr & 1] = (result >> 1) | 0x80000000; + joypad.joypad_latches [addr & 1] = result >> 1; // ASR is intentional return result & 1; } diff --git a/quicknes/nes_emu/Nes_Core.h b/quicknes/nes_emu/Nes_Core.h index b4dd759703..179f9ef779 100644 --- a/quicknes/nes_emu/Nes_Core.h +++ b/quicknes/nes_emu/Nes_Core.h @@ -50,7 +50,7 @@ public: private: friend class Nes_Emu; bool sram_present; public: - unsigned long current_joypad [2]; + uint32_t current_joypad [2]; int joypad_read_count; Nes_Cart const* cart; Nes_Mapper* mapper; diff --git a/quicknes/nes_emu/Nes_Emu.cpp b/quicknes/nes_emu/Nes_Emu.cpp index 98edee5baa..6c8aa6ca9e 100644 --- a/quicknes/nes_emu/Nes_Emu.cpp +++ b/quicknes/nes_emu/Nes_Emu.cpp @@ -124,10 +124,10 @@ void Nes_Emu::set_palette_range( int begin, int end ) require( host_palette_size >= palette_alignment ); } -blargg_err_t Nes_Emu::emulate_frame( int joypad1, int joypad2 ) +blargg_err_t Nes_Emu::emulate_frame( const uint32_t joypad1, const uint32_t joypad2 ) { - emu.current_joypad [0] = (joypad1 |= ~0xFF); - emu.current_joypad [1] = (joypad2 |= ~0xFF); + emu.current_joypad [0] = joypad1; + emu.current_joypad [1] = joypad2; emu.ppu.host_pixels = NULL; diff --git a/quicknes/nes_emu/Nes_Emu.h b/quicknes/nes_emu/Nes_Emu.h index e0fee4298f..c08d1f4afe 100644 --- a/quicknes/nes_emu/Nes_Emu.h +++ b/quicknes/nes_emu/Nes_Emu.h @@ -52,7 +52,10 @@ public: // Emulate one video frame using joypad1 and joypad2 as input. Afterwards, image // and sound are available for output using the accessors below. - virtual blargg_err_t emulate_frame( int joypad1, int joypad2 = 0 ); + // A connected controller should have 0xffffff** in the high bits, or 0x000000** + // if emulating an incorrectly made third party controller. A disconnected controller + // should be 0x00000000 exactly. + virtual blargg_err_t emulate_frame( uint32_t joypad1, uint32_t joypad2 ); // Maximum size of palette that can be generated enum { max_palette_size = 256 }; diff --git a/quicknes/nes_emu/nes_data.h b/quicknes/nes_emu/nes_data.h index 4e33472502..e831866952 100644 --- a/quicknes/nes_emu/nes_data.h +++ b/quicknes/nes_emu/nes_data.h @@ -87,7 +87,7 @@ BOOST_STATIC_ASSERT( sizeof (nes_state_t) == 8 ); struct joypad_state_t { - BOOST::uint32_t joypad_latches [2]; // joypad 1 & 2 shift registers + uint32_t joypad_latches [2]; // joypad 1 & 2 shift registers byte w4016; // strobe byte unused [3];