From 8708fc3e3588eb0218ddeab2dc09b6f532dd9730 Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:35:04 -0800 Subject: [PATCH] c# side changes for ST-V with Saturnus --- .../Consoles/Sega/Saturn/Saturnus.cs | 9 ++- .../Waterbox/LibNymaCore.cs | 16 +++-- .../Waterbox/NymaCore.Controller.cs | 5 ++ .../Waterbox/NymaCore.Settings.cs | 2 + .../Waterbox/NymaCore.cs | 66 +++++++++++++++---- 5 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs index d7b6f02942..8a81dc3fd4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs @@ -34,7 +34,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn : base(lp.Comm, VSystemID.Raw.SAT, "Saturn Controller", lp.Settings, lp.SyncSettings) { if (lp.Roms.Count > 0) - throw new InvalidOperationException("To load a Saturn game, please load the CUE file and not the BIN file."); + { + // roms might be valid (ST-V Arcade ROMs) + if (lp.Roms.Exists(rom => rom.FileData.Length > 0x3000000)) + { + throw new InvalidOperationException("To load a Saturn game, please load the CUE file and not the BIN file."); + } + } + var firmwareIDMap = new Dictionary { { "FIRMWARE:$J", new("SAT", "J") }, diff --git a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs index b99f42677e..11655d607e 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs @@ -142,6 +142,13 @@ namespace BizHawk.Emulation.Cores.Waterbox SECAM } + public enum GameMediumTypes : int + { + GMT_NONE = 0, + GMT_ARCADE, + GMT_PLAYER + } + [StructLayout(LayoutKind.Sequential)] public struct SystemInfo { @@ -150,14 +157,15 @@ namespace BizHawk.Emulation.Cores.Waterbox public int NominalWidth; public int NominalHeight; public VideoSystem VideoSystem; + public GameMediumTypes GameType; public int FpsFixed; public long MasterClock; public int LcmWidth; public int LcmHeight; - public int PointerScaleX; - public int PointerScaleY; - public int PointerOffsetX; - public int PointerOffsetY; + public int PointerScaleX; + public int PointerScaleY; + public int PointerOffsetX; + public int PointerOffsetY; } [BizImport(CC, Compatibility = true)] diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs index ffcd6f10ee..13336b18c0 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs @@ -76,6 +76,7 @@ namespace BizHawk.Emulation.Cores.Waterbox { { "Power", "System" }, { "Reset", "System" }, + { "Insert Coin", "System" }, { "Open Tray", "System" }, { "Close Tray", "System" }, { "Disk Index", "System" }, @@ -325,6 +326,10 @@ namespace BizHawk.Emulation.Cores.Waterbox } ret.BoolButtons.Add("Power"); ret.BoolButtons.Add("Reset"); + if (systemInfo.GameType == GameMediumTypes.GMT_ARCADE) + { + ret.BoolButtons.Add("Insert Coin"); + } if (numCds > 0) { ret.BoolButtons.Add("Open Tray"); diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs index b4a6bd828d..a9c3dbb698 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs @@ -321,6 +321,8 @@ namespace BizHawk.Emulation.Cores.Waterbox private static readonly IReadOnlyDictionary ExtraOverrides = new Dictionary { { "nyma.constantfb", new() { NonSync = true, NoRestart = true } }, + // global setting... needs a value set if it gets used (only use case in practice is ST-V with Saturnus) + { "filesys.untrusted_fip_check", new() { Hide = true, Default = "0" } }, }; private static readonly IReadOnlyCollection ExtraSettings = new List diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs index 3720188c96..69dd2f1da5 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; + using BizHawk.BizInvoke; using BizHawk.Common; using BizHawk.Emulation.Common; @@ -45,6 +46,7 @@ namespace BizHawk.Emulation.Cores.Waterbox } private LibNymaCore _nyma; + protected T DoInit( CoreLoadParameters lp, string wbxFilename, @@ -53,8 +55,8 @@ namespace BizHawk.Emulation.Cores.Waterbox where T : LibNymaCore { return DoInit( - lp.Game, - lp.Roms.FirstOrDefault()?.RomData, + lp.Roms.Select(r => (r.RomData, + Path.GetFileName(r.RomPath[(r.RomPath.LastIndexOf('|') + 1)..])!.ToLowerInvariant())).ToArray(), lp.Discs.Select(d => d.DiscData).ToArray(), wbxFilename, lp.Roms.FirstOrDefault()?.Extension, @@ -62,8 +64,24 @@ namespace BizHawk.Emulation.Cores.Waterbox firmwareIDMap ); } - protected T DoInit(GameInfo game, byte[] rom, Disc[] discs, string wbxFilename, string extension, bool deterministic, - IDictionary firmwareIDMap = null) + + protected T DoInit( + GameInfo game, byte[] rom, Disc[] discs, string wbxFilename, + string romExtension, bool deterministic, IDictionary firmwareIDMap = null) + where T : LibNymaCore + { + return DoInit( + [ (Data: rom, Filename: game.FilesystemSafeName() + romExtension.ToLowerInvariant()) ], + discs, + wbxFilename, + romExtension, + deterministic, + firmwareIDMap + ); + } + + protected T DoInit((byte[] Data, string Filename)[] roms, Disc[] discs, string wbxFilename, + string romExtension, bool deterministic, IDictionary firmwareIDMap = null) where T : LibNymaCore { _settingsQueryDelegate = SettingsQuery; @@ -72,7 +90,7 @@ namespace BizHawk.Emulation.Cores.Waterbox var filesToRemove = new List(); - var firmwareDelegate = new LibNymaCore.FrontendFirmwareNotify((name) => + var firmwareDelegate = new LibNymaCore.FrontendFirmwareNotify(name => { if (firmwareIDMap != null && firmwareIDMap.TryGetValue(name, out var id)) { @@ -123,21 +141,25 @@ namespace BizHawk.Emulation.Cores.Waterbox } else { - var fn = game.FilesystemSafeName(); - _exe.AddReadonlyFile(rom, fn); + foreach (var (data, filename) in roms) + { + _exe.AddReadonlyFile(data, filename); + } var didInit = _nyma.InitRom(new LibNymaCore.InitData { - // TODO: Set these as some cores need them - FileNameBase = "", - FileNameExt = extension.Trim('.').ToLowerInvariant(), - FileNameFull = fn + FileNameBase = Path.GetFileNameWithoutExtension(roms[0].Filename), + FileNameExt = romExtension.Trim('.').ToLowerInvariant(), + FileNameFull = roms[0].Filename }); if (!didInit) throw new InvalidOperationException("Core rejected the rom!"); - _exe.RemoveReadonlyFile(fn); + foreach (var (_, filename) in roms) + { + _exe.RemoveReadonlyFile(filename); + } } foreach (var s in filesToRemove) @@ -171,6 +193,7 @@ namespace BizHawk.Emulation.Cores.Waterbox VsyncDenominator = 1 << 24; ClockRate = info.MasterClock / (double)0x100000000; _soundBuffer = new short[22050 * 2]; + _isArcade = info.GameType == LibNymaCore.GameMediumTypes.GMT_ARCADE; InitControls(portData, discs?.Length ?? 0, ref info); PostInit(); @@ -232,12 +255,18 @@ namespace BizHawk.Emulation.Cores.Waterbox private IController _currentController; + private bool _isArcade; + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) { DriveLightOn = false; _currentController = controller; // need to remember this for rumble _controllerAdapter.SetBits(controller, _inputPortData); - _frameAdvanceInputLock = GCHandle.Alloc(_inputPortData, GCHandleType.Pinned); + if (!_frameAdvanceInputLock.IsAllocated) + { + _frameAdvanceInputLock = GCHandle.Alloc(_inputPortData, GCHandleType.Pinned); + } + LibNymaCore.BizhawkFlags flags = 0; if (!render) flags |= LibNymaCore.BizhawkFlags.SkipRendering; @@ -260,7 +289,9 @@ namespace BizHawk.Emulation.Cores.Waterbox ? LibNymaCore.CommandType.POWER : controller.IsPressed("Reset") ? LibNymaCore.CommandType.RESET - : LibNymaCore.CommandType.NONE, + : _isArcade && controller.IsPressed("Insert Coin") + ? LibNymaCore.CommandType.INSERT_COIN + : LibNymaCore.CommandType.NONE, InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject(), FrontendTime = GetRtcTime(SettingsQuery("nyma.rtcrealtime") != "0"), DiskIndex = diskIndex, @@ -271,6 +302,7 @@ namespace BizHawk.Emulation.Cores.Waterbox } return ret; } + protected override void FrameAdvancePost() { _controllerAdapter.DoRumble(_currentController, _inputPortData); @@ -350,6 +382,12 @@ namespace BizHawk.Emulation.Cores.Waterbox disk.Dispose(); } } + + if (_frameAdvanceInputLock.IsAllocated) + { + _frameAdvanceInputLock.Free(); + } + base.Dispose(); } }