diff --git a/output/dll/faust.wbx.gz b/output/dll/faust.wbx.gz index 1cbfd5b46c..3253b74fe3 100644 Binary files a/output/dll/faust.wbx.gz and b/output/dll/faust.wbx.gz differ diff --git a/output/dll/ngp.wbx.gz b/output/dll/ngp.wbx.gz index e844a763a5..38dbebee8b 100644 Binary files a/output/dll/ngp.wbx.gz and b/output/dll/ngp.wbx.gz differ diff --git a/output/dll/pce-fast.wbx.gz b/output/dll/pce-fast.wbx.gz index 69de895163..bc8bf63579 100644 Binary files a/output/dll/pce-fast.wbx.gz and b/output/dll/pce-fast.wbx.gz differ diff --git a/output/dll/pce.wbx.gz b/output/dll/pce.wbx.gz index d74db38efa..ea92f6ba02 100644 Binary files a/output/dll/pce.wbx.gz and b/output/dll/pce.wbx.gz differ diff --git a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs index ba14511cf2..ae51b12cf8 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs @@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.Waterbox [BizImport(CC)] public abstract bool InitCd(int numdisks); - public enum CommandType : short + public enum CommandType : int { NONE = 0x00, RESET = 0x01, @@ -69,26 +69,30 @@ namespace BizHawk.Emulation.Cores.Waterbox TOGGLE_DIP15, } + [Flags] + public enum BizhawkFlags : int + { + // skip video output + SkipRendering = 1, + // skip sound output + SkipSoundening = 2, + // render at LCM * LCM instead of raw + RenderConstantSize = 4, + // switch to the previous disk, if possible + PreviousDisk = 8, + // switch to the next disk, if possible + NextDisk = 16 + } + [StructLayout(LayoutKind.Sequential)] public new class FrameInfo : LibWaterboxCore.FrameInfo { - /// - /// true to skip video rendering - /// - public short SkipRendering; - /// - /// true to skip audion rendering - /// - public short SkipSoundening; + public BizhawkFlags Flags; /// /// a single command to run at the start of this frame /// public CommandType Command; /// - /// True to render to a single framebuffer size (LCM * LCM) - /// - public short RenderConstantSize; - /// /// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long /// public byte* InputPortData; diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs index c241fb5177..eb9fb5ae2c 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs @@ -13,9 +13,9 @@ namespace BizHawk.Emulation.Cores.Waterbox private readonly byte[] _inputPortData = new byte[16 * 16]; private readonly string _controllerDeckName; - private void InitControls(List allPorts) + private void InitControls(List allPorts, bool hasCds) { - _controllerAdapter = new ControllerAdapter(allPorts, _syncSettingsActual.PortDevices, ButtonNameOverrides); + _controllerAdapter = new ControllerAdapter(allPorts, _syncSettingsActual.PortDevices, ButtonNameOverrides, hasCds); _nyma.SetInputDevices(_controllerAdapter.Devices); ControllerDefinition = _controllerAdapter.Definition; } @@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Waterbox /// public string[] Devices { get; } public ControllerDefinition Definition { get; } - public ControllerAdapter(List allPorts, IDictionary config, IDictionary overrides) + public ControllerAdapter(List allPorts, IDictionary config, IDictionary overrides, bool hasCds) { var ret = new ControllerDefinition { @@ -46,6 +46,8 @@ namespace BizHawk.Emulation.Cores.Waterbox { { "Power", "System" }, { "Reset", "System" }, + { "Previous Disk", "System" }, + { "Next Disk", "System" }, } }; @@ -210,6 +212,11 @@ namespace BizHawk.Emulation.Cores.Waterbox } ret.BoolButtons.Add("Power"); ret.BoolButtons.Add("Reset"); + if (hasCds) + { + ret.BoolButtons.Add("Previous Disk"); + ret.BoolButtons.Add("Next Disk"); + } Definition = ret; finalDevices.Add(null); Devices = finalDevices.ToArray(); diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs index 1299e2bc0e..e37ac531f9 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs @@ -119,7 +119,7 @@ namespace BizHawk.Emulation.Cores.Waterbox VsyncDenominator = 1 << 24; _soundBuffer = new short[22050 * 2]; - InitControls(portData); + InitControls(portData, discs?.Length > 0); _nyma.SetFrontendSettingQuery(null); if (_disks != null) _nyma.SetCDCallbacks(null, null); @@ -179,16 +179,26 @@ namespace BizHawk.Emulation.Cores.Waterbox DriveLightOn = false; _controllerAdapter.SetBits(controller, _inputPortData); _frameAdvanceInputLock = GCHandle.Alloc(_inputPortData, GCHandleType.Pinned); + LibNymaCore.BizhawkFlags flags = 0; + if (!render) + flags |= LibNymaCore.BizhawkFlags.SkipRendering; + if (!rendersound) + flags |= LibNymaCore.BizhawkFlags.SkipSoundening; + if (SettingsQuery("nyma.constantfb") != "0") + flags |= LibNymaCore.BizhawkFlags.RenderConstantSize; + if (controller.IsPressed("Previous Disk")) + flags |= LibNymaCore.BizhawkFlags.PreviousDisk; + if (controller.IsPressed("Next Disk")) + flags |= LibNymaCore.BizhawkFlags.NextDisk; + var ret = new LibNymaCore.FrameInfo { - SkipRendering = (short)(render ? 0 : 1), - SkipSoundening = (short)(rendersound ? 0 : 1), + Flags = flags, Command = controller.IsPressed("Power") ? LibNymaCore.CommandType.POWER : controller.IsPressed("Reset") ? LibNymaCore.CommandType.RESET : LibNymaCore.CommandType.NONE, - RenderConstantSize = (short)(SettingsQuery("nyma.constantfb") != "0" ? 1 : 0), InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject(), FrontendTime = GetRtcTime(SettingsQuery("nyma.rtcrealtime") != "0"), }; diff --git a/waterbox/nyma/NymaCore.cpp b/waterbox/nyma/NymaCore.cpp index 68377ebc62..6ed597dac1 100644 --- a/waterbox/nyma/NymaCore.cpp +++ b/waterbox/nyma/NymaCore.cpp @@ -82,8 +82,6 @@ ECL_EXPORT bool InitRom(const InitData& data) return true; } -void StartGameWithCds(int numdisks); - ECL_EXPORT bool InitCd(int numdisks) { try @@ -98,15 +96,25 @@ ECL_EXPORT bool InitCd(int numdisks) return true; } +enum BizhawkFlags +{ + // skip video output + SkipRendering = 1, + // skip sound output + SkipSoundening = 2, + // render at LCM * LCM instead of raw + RenderConstantSize = 4, + // switch to the previous disk, if possible + PreviousDisk = 8, + // switch to the next disk, if possible + NextDisk = 16 +}; + struct MyFrameInfo: public FrameInfo { - // true to skip video rendering - int16_t SkipRendering; - int16_t SkipSoundening; + int32_t BizhawkFlags; // a single MDFN_MSC_* command to run at the start of this frame; 0 if none - int16_t Command; - // true to render LCM * LCM instead of raw - int16_t RenderConstantSize; + int32_t Command; // raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long uint8_t* InputPortData; int64_t FrontendTime; @@ -116,7 +124,14 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame) { FrontendTime = frame.FrontendTime; LagFlag = true; - EES->skip = frame.SkipRendering; + EES->skip = !!(frame.BizhawkFlags & BizhawkFlags::SkipRendering); + + { + auto prev = !!(frame.BizhawkFlags & BizhawkFlags::PreviousDisk); + auto next = !!(frame.BizhawkFlags & BizhawkFlags::NextDisk); + if (prev || next) + SwitchCds(prev, next); + } if (frame.Command) Game->DoSimpleCommand(frame.Command); @@ -131,12 +146,12 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame) EES->SoundFormatChanged = false; frame.Cycles = EES->MasterCycles; frame.Lagged = LagFlag; - if (!frame.SkipSoundening) + if (!(frame.BizhawkFlags & BizhawkFlags::SkipSoundening)) { memcpy(frame.SoundBuffer, EES->SoundBuf, EES->SoundBufSize * 4); frame.Samples = EES->SoundBufSize; } - if (!frame.SkipRendering) + if (!(frame.BizhawkFlags & BizhawkFlags::SkipRendering)) { int h = EES->DisplayRect.h; int lineStart = EES->DisplayRect.y; @@ -147,7 +162,7 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame) uint32_t* src = pixels + EES->DisplayRect.x + EES->DisplayRect.y * srcp; uint32_t* dst = frame.VideoBuffer; - if (!frame.RenderConstantSize || !multiWidth && Game->lcm_width == EES->DisplayRect.w && Game->lcm_height == h) + if (!(frame.BizhawkFlags & BizhawkFlags::RenderConstantSize) || !multiWidth && Game->lcm_width == EES->DisplayRect.w && Game->lcm_height == h) { // simple non-resizing blitter // TODO: What does this do with true multiwidth? Probably not anything good diff --git a/waterbox/nyma/cdrom.cpp b/waterbox/nyma/cdrom.cpp index 4a1e525bd8..408c312228 100644 --- a/waterbox/nyma/cdrom.cpp +++ b/waterbox/nyma/cdrom.cpp @@ -110,7 +110,6 @@ void StartGameWithCds(int numdisks) } MDFNGameInfo->RMD = rmd; - // TODO: Wire up a way for the user to change disks Mednafen::MDFNGameInfo->SetMedia( 0, // drive: 0 unless there's more than one drive 2, // state: 0 = open, 1 = closed (media absent), 2 = closed (media present) @@ -118,6 +117,39 @@ void StartGameWithCds(int numdisks) 0 // orientation: flip sides on NES FDS. not used elsewhere? ); } +static bool wasPrev; +static bool wasNext; +static int cd; +void SwitchCds(bool prev, bool next) +{ + auto newCd = cd; + if (prev && !wasPrev) + { + newCd = std::max(newCd - 1, -1); + } + if (next && !wasNext) + { + newCd = std::min(newCd + 1, (int)(CDInterfaces->size() - 1)); + } + if (newCd != cd) + { + Mednafen::MDFNGameInfo->SetMedia( + 0, // drive: 0 unless there's more than one drive + 0, // state: 0 = open, 1 = closed (media absent), 2 = closed (media present) + std::max(cd, 0), // media: index into the disk list + 0 // orientation: flip sides on NES FDS. not used elsewhere? + ); + Mednafen::MDFNGameInfo->SetMedia( + 0, // drive: 0 unless there's more than one drive + newCd == -1 ? 0 : 2, // state: 0 = open, 1 = closed (media absent), 2 = closed (media present) + std::max(newCd, 0), // media: index into the disk list + 0 // orientation: flip sides on NES FDS. not used elsewhere? + ); + } + cd = newCd; + wasPrev = prev; + wasNext = next; +} // CDInterface::Load pulls in a bunch of things that we do not want, stub them out here namespace Mednafen diff --git a/waterbox/nyma/cdrom_dummy.cpp b/waterbox/nyma/cdrom_dummy.cpp index e3b36e150b..013d4b1b46 100644 --- a/waterbox/nyma/cdrom_dummy.cpp +++ b/waterbox/nyma/cdrom_dummy.cpp @@ -11,3 +11,7 @@ ECL_EXPORT void SetCDCallbacks() { abort(); } +void SwitchCds(bool prev, bool next) +{ + abort(); +} diff --git a/waterbox/nyma/common/nyma.h b/waterbox/nyma/common/nyma.h index 89d0c08ddc..f1e9010c98 100644 --- a/waterbox/nyma/common/nyma.h +++ b/waterbox/nyma/common/nyma.h @@ -25,3 +25,6 @@ typedef void (*FrameCallback)(); // The callback may not call any C standard library functions, or otherwise trigger a syscall // The callback must return before frame advance finishes void RegisterFrameThreadProc(FrameCallback threadproc); + +void StartGameWithCds(int numdisks); +void SwitchCds(bool prev, bool next);