diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibSameboy.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibSameboy.cs index 5c13e48d23..c9ba9cc16b 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibSameboy.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibSameboy.cs @@ -3,6 +3,7 @@ using BizHawk.Emulation.Cores.Waterbox; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -10,6 +11,26 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy { public abstract class LibSameboy : LibWaterboxCore { + [Flags] + public enum Buttons : uint + { + A = 0x01, + B = 0x02, + SELECT = 0x04, + START = 0x08, + RIGHT = 0x10, + LEFT = 0x20, + UP = 0x40, + DOWN = 0x80 + } + + [StructLayout(LayoutKind.Sequential)] + public new class FrameInfo : LibWaterboxCore.FrameInfo + { + public long Time; + public Buttons Keys; + } + [BizImport(CC)] public abstract bool Init(bool cgb); } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs index 8d93b7521f..a052576634 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs @@ -32,6 +32,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy private LibSameboy _core; private bool _cgb; + private bool _sgb; [CoreConstructor("GB")] public Sameboy(CoreComm comm, byte[] rom) @@ -76,10 +77,65 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy PostInit(); } + #region Controller + + private static readonly ControllerDefinition _gbDefinition; + private static readonly ControllerDefinition _sgbDefinition; + public override ControllerDefinition ControllerDefinition => _sgb ? _sgbDefinition : _gbDefinition; + + private static ControllerDefinition CreateControllerDefinition(int p) + { + var ret = new ControllerDefinition { Name = "Gameboy Controller" }; + for (int i = 0; i < p; i++) + { + ret.BoolButtons.AddRange( + new[] { "Up", "Down", "Left", "Right", "A", "B", "Select", "Start" } + .Select(s => $"P{i + 1} {s}")); + } + return ret; + } + + static Sameboy() + { + _gbDefinition = CreateControllerDefinition(1); + _sgbDefinition = CreateControllerDefinition(4); + } + + private LibSameboy.Buttons GetButtons(IController c) + { + LibSameboy.Buttons b = 0; + for (int i = _sgb ? 4 : 1; i > 0; i--) + { + if (c.IsPressed($"P{i} Up")) + b |= LibSameboy.Buttons.UP; + if (c.IsPressed($"P{i} Down")) + b |= LibSameboy.Buttons.DOWN; + if (c.IsPressed($"P{i} Left")) + b |= LibSameboy.Buttons.LEFT; + if (c.IsPressed($"P{i} Right")) + b |= LibSameboy.Buttons.RIGHT; + if (c.IsPressed($"P{i} A")) + b |= LibSameboy.Buttons.A; + if (c.IsPressed($"P{i} B")) + b |= LibSameboy.Buttons.B; + if (c.IsPressed($"P{i} Select")) + b |= LibSameboy.Buttons.SELECT; + if (c.IsPressed($"P{i} Start")) + b |= LibSameboy.Buttons.START; + if (i != 1) + b = (LibSameboy.Buttons)((uint)b << 8); + } + return b; + } + + #endregion + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) { return new LibSameboy.FrameInfo { + Time = 0, + Keys = GetButtons(controller) }; } diff --git a/waterbox/sameboy/bizhawk.cpp b/waterbox/sameboy/bizhawk.cpp index 187c668a5b..c704aaf13a 100644 --- a/waterbox/sameboy/bizhawk.cpp +++ b/waterbox/sameboy/bizhawk.cpp @@ -91,6 +91,8 @@ ECL_EXPORT bool Init(bool cgb) struct MyFrameInfo : public FrameInfo { + int64_t Time; + uint32_t Keys; }; static int FrameOverflow; @@ -98,8 +100,7 @@ static int FrameOverflow; ECL_EXPORT void FrameAdvance(MyFrameInfo &f) { GB_set_pixels_output(&GB, f.VideoBuffer); - for (int i = 0; i < (int)GB_KEY_MAX; i++) - GB_set_key_state(&GB, (GB_key_t)i, false); + GB_set_key_state(&GB, f.Keys & 0xff); sound_start_clock = GB_epoch(&GB); diff --git a/waterbox/sameboy/gb.c b/waterbox/sameboy/gb.c index 986a5623c6..0f6b298b07 100644 --- a/waterbox/sameboy/gb.c +++ b/waterbox/sameboy/gb.c @@ -252,14 +252,12 @@ void GB_run(GB_gameboy_t *gb) uint64_t GB_run_cycles(GB_gameboy_t *gb, uint32_t cycles) { + GB_update_joyp(gb); + GB_rtc_run(gb); uint64_t start = gb->cycles_since_epoch; uint64_t target = start + cycles; while (gb->cycles_since_epoch < target) { GB_run(gb); - if (gb->vblank_just_occured) { - GB_update_joyp(gb); - GB_rtc_run(gb); - } } return gb->cycles_since_epoch - start; } diff --git a/waterbox/sameboy/gb.h b/waterbox/sameboy/gb.h index 5eb644d20a..d1fb323d3e 100644 --- a/waterbox/sameboy/gb.h +++ b/waterbox/sameboy/gb.h @@ -380,7 +380,7 @@ struct GB_gameboy_internal_s { /* I/O */ uint32_t *screen; - bool keys[GB_KEY_MAX]; + int keys; /* Timing */ uint64_t cycles_since_epoch; diff --git a/waterbox/sameboy/joypad.c b/waterbox/sameboy/joypad.c index 21e6d666b0..0cad7ab084 100644 --- a/waterbox/sameboy/joypad.c +++ b/waterbox/sameboy/joypad.c @@ -9,7 +9,7 @@ void GB_update_joyp(GB_gameboy_t *gb) /* Todo: add delay to key selection */ previous_state = gb->io_registers[GB_IO_JOYP] & 0xF; - key_selection = (gb->io_registers[GB_IO_JOYP] >> 4) & 3; + key_selection = gb->io_registers[GB_IO_JOYP] >> 4 & 3; gb->io_registers[GB_IO_JOYP] &= 0xF0; switch (key_selection) { case 3: @@ -19,24 +19,17 @@ void GB_update_joyp(GB_gameboy_t *gb) case 2: /* Direction keys */ - for (uint8_t i = 0; i < 4; i++) { - gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i]) << i; - } + gb->io_registers[GB_IO_JOYP] |= ~gb->keys >> 4 & 0xf; break; case 1: /* Other keys */ - for (uint8_t i = 0; i < 4; i++) { - gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i + 4]) << i; - } + gb->io_registers[GB_IO_JOYP] |= ~gb->keys & 0xf; break; case 0: /* Todo: verifiy this is correct */ - for (uint8_t i = 0; i < 4; i++) { - gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i]) << i; - gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i + 4]) << i; - } + gb->io_registers[GB_IO_JOYP] |= ~(gb->keys >> 4 & gb->keys) & 0xf; break; default: @@ -49,8 +42,7 @@ void GB_update_joyp(GB_gameboy_t *gb) gb->io_registers[GB_IO_JOYP] |= 0xC0; // No SGB support } -void GB_set_key_state(GB_gameboy_t *gb, GB_key_t index, bool pressed) +void GB_set_key_state(GB_gameboy_t *gb, int keys) { - assert(index >= 0 && index < GB_KEY_MAX); - gb->keys[index] = pressed; + gb->keys = keys; } diff --git a/waterbox/sameboy/joypad.h b/waterbox/sameboy/joypad.h index def4b9ac82..f7ffdfdec4 100644 --- a/waterbox/sameboy/joypad.h +++ b/waterbox/sameboy/joypad.h @@ -2,19 +2,7 @@ #define joypad_h #include "gb_struct_def.h" -typedef enum { - GB_KEY_RIGHT, - GB_KEY_LEFT, - GB_KEY_UP, - GB_KEY_DOWN, - GB_KEY_A, - GB_KEY_B, - GB_KEY_SELECT, - GB_KEY_START, - GB_KEY_MAX -} GB_key_t; - -void GB_set_key_state(GB_gameboy_t *gb, GB_key_t index, bool pressed); +void GB_set_key_state(GB_gameboy_t *gb, int keys); #ifdef GB_INTERNAL void GB_update_joyp(GB_gameboy_t *gb);