diff --git a/output/dll/libsnes.wbx.gz b/output/dll/libsnes.wbx.gz
index 6852fce6c2..9e1cb78aa8 100644
Binary files a/output/dll/libsnes.wbx.gz and b/output/dll/libsnes.wbx.gz differ
diff --git a/src/BizHawk.Client.Common/RomLoader.cs b/src/BizHawk.Client.Common/RomLoader.cs
index ffd2fc1c4c..237c90f829 100644
--- a/src/BizHawk.Client.Common/RomLoader.cs
+++ b/src/BizHawk.Client.Common/RomLoader.cs
@@ -978,7 +978,9 @@ namespace BizHawk.Client.Common
if (core != null)
{
// use CoreInventory
- nextEmulator = core.Create(nextComm, game, rom.RomData, rom.FileData, Deterministic, GetCoreSettings(core.Type), GetCoreSyncSettings(core.Type));
+ nextEmulator = core.Create(
+ nextComm, game, rom.RomData, rom.FileData, Deterministic,
+ GetCoreSettings(core.Type), GetCoreSyncSettings(core.Type), rom.Extension);
}
}
diff --git a/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
index b76f3cac65..cc8e43e1dd 100755
--- a/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
+++ b/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
@@ -7,7 +7,7 @@
app.manifest
$(DefineConstants);EXE_PROJECT
$(ProjectDir)../../output
- WinExe
+ Exe
net48
EmuHawk
None
diff --git a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs
index 2b893e62ea..d0cf6e317d 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs
@@ -7,13 +7,14 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCE
public class TerboGrafix : NymaCore, IRegionable
{
[CoreConstructor("PCE")]
- public TerboGrafix(GameInfo game, byte[] rom, CoreComm comm)
+ public TerboGrafix(GameInfo game, byte[] rom, CoreComm comm, string extension)
: base(game, rom, comm, new Configuration
{
+ SystemId = "PCE" // whatever
// TODO: This stuff isn't used so much
})
{
- DoInit(game, rom, "pce.wbx");
+ DoInit(game, rom, "pce.wbx", extension);
}
}
}
diff --git a/src/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs b/src/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs
index 042402bd1b..548061fb28 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/SNK/DualNeoGeoPort.cs
@@ -28,20 +28,21 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK
[CoreConstructor("DNGP")]
public DualNeoGeoPort(CoreComm comm, byte[] rom, bool deterministic)
{
- // this will throw on construct: we need to compile two different copies of ngp at different starts
- CoreComm = comm;
- _left = new NeoGeoPort(comm, rom, new NeoGeoPort.SyncSettings { Language = LibNeoGeoPort.Language.English }, deterministic, WaterboxHost.CanonicalStart);
- _right = new NeoGeoPort(comm, rom, new NeoGeoPort.SyncSettings { Language = LibNeoGeoPort.Language.English }, deterministic, WaterboxHost.CanonicalStart);
- _linkCable = new LinkCable();
- _leftEnd = new LinkInterop(_left, _linkCable.LeftIn, _linkCable.LeftOut);
- _rightEnd = new LinkInterop(_right, _linkCable.RightIn, _linkCable.RightOut);
+ throw new NotImplementedException();
+ // // this will throw on construct: we need to compile two different copies of ngp at different starts
+ // CoreComm = comm;
+ // _left = new NeoGeoPort(comm, rom, new NeoGeoPort.SyncSettings { Language = LibNeoGeoPort.Language.English }, deterministic, WaterboxHost.CanonicalStart);
+ // _right = new NeoGeoPort(comm, rom, new NeoGeoPort.SyncSettings { Language = LibNeoGeoPort.Language.English }, deterministic, WaterboxHost.CanonicalStart);
+ // _linkCable = new LinkCable();
+ // _leftEnd = new LinkInterop(_left, _linkCable.LeftIn, _linkCable.LeftOut);
+ // _rightEnd = new LinkInterop(_right, _linkCable.RightIn, _linkCable.RightOut);
- _serviceProvider = new BasicServiceProvider(this);
- _soundProvider = new DualSyncSound(_left, _right);
- _serviceProvider.Register(_soundProvider);
- _videoProvider = new SideBySideVideo(_left, _right);
- _serviceProvider.Register(_videoProvider);
+ // _serviceProvider = new BasicServiceProvider(this);
+ // _soundProvider = new DualSyncSound(_left, _right);
+ // _serviceProvider.Register(_soundProvider);
+ // _videoProvider = new SideBySideVideo(_left, _right);
+ // _serviceProvider.Register(_videoProvider);
}
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
diff --git a/src/BizHawk.Emulation.Cores/CoreInventory.cs b/src/BizHawk.Emulation.Cores/CoreInventory.cs
index ac49603eac..db1e4a8562 100644
--- a/src/BizHawk.Emulation.Cores/CoreInventory.cs
+++ b/src/BizHawk.Emulation.Cores/CoreInventory.cs
@@ -80,7 +80,8 @@ namespace BizHawk.Emulation.Cores
byte[] file,
bool deterministic,
object settings,
- object syncSettings
+ object syncSettings,
+ string extension
)
{
object[] o = new object[_paramMap.Count];
@@ -91,6 +92,7 @@ namespace BizHawk.Emulation.Cores
Bp(o, "deterministic", deterministic);
Bp(o, "settings", settings);
Bp(o, "syncsettings", syncSettings);
+ Bp(o, "extension", extension);
return (IEmulator)CTor.Invoke(o);
}
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs b/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs
index 94ca1110b3..9605630ed6 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs
@@ -137,7 +137,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
var actuallySaved = allocated.Where(a => a.LoadAddress + a.Size > _saveStart);
var oopsSaved = actuallySaved.Except(saveable);
foreach (var s in oopsSaved)
- throw new InvalidOperationException($"ElfLoader: Section {s.Name} will be saved, but that was not expected");
+ {
+ Console.WriteLine($"ElfLoader: Section {s.Name} will be saved, but that was not expected");
+ }
}
PrintSections();
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs
index bd3f8668ea..3620a918fa 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs
@@ -70,69 +70,36 @@ namespace BizHawk.Emulation.Cores.Waterbox
public byte* InputPortData;
}
+ ///
+ /// Gets raw layer data to be handled by NymaCore.GetLayerData
+ ///
[BizImport(CC)]
public abstract byte* GetLayerData();
///
- /// Gets a string array of valid layers to pass to SetLayers, or null if that method should not be called
- /// TODO: This needs to be in NymaCore under a monitor lock
+ /// Set enabled layers (or is it disabled layers?). Only call if NymaCore.GetLayerData() returned non null
///
- public string[] GetLayerDataReal()
- {
- var p = GetLayerData();
- if (p == null)
- return null;
- var ret = new List();
- var q = p;
- while (true)
- {
- if (*q == 0)
- {
- if (q > p)
- ret.Add(Marshal.PtrToStringAnsi((IntPtr)p));
- else
- break;
- p = ++q;
- }
- q++;
- }
- return ret.ToArray();
- }
-
- ///
- /// Set enabled layers (or is it disabled layers?). Only call if GetLayerDataReal() returned non null
- ///
- /// bitmask in order defined by GetLayerDataReal
+ /// bitmask in order defined by NymaCore.GetLayerData
[BizImport(CC)]
public abstract void SetLayers(ulong layers);
public enum InputType : byte
{
PADDING = 0, // n-bit, zero
-
BUTTON, // 1-bit
BUTTON_CAN_RAPID, // 1-bit
-
SWITCH, // ceil(log2(n))-bit
// Current switch position(default 0).
// Persistent, and bidirectional communication(can be modified driver side, and Mednafen core and emulation module side)
-
STATUS, // ceil(log2(n))-bit
// emulation module->driver communication
-
AXIS, // 16-bits; 0 through 65535; 32768 is centered position
-
POINTER_X, // mouse pointer, 16-bits, signed - in-screen/window range before scaling/offseting normalized coordinates: [0.0, 1.0)
POINTER_Y, // see: mouse_scale_x, mouse_scale_y, mouse_offs_x, mouse_offs_y
-
AXIS_REL, // mouse relative motion, 16-bits, signed
-
BYTE_SPECIAL,
-
RESET_BUTTON, // 1-bit
-
BUTTON_ANALOG, // 16-bits, 0 - 65535
-
RUMBLE, // 16-bits, lower 8 bits are weak rumble(0-255), next 8 bits are strong rumble(0-255), 0=no rumble, 255=max rumble. Somewhat subjective, too...
}
@@ -155,91 +122,119 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
[StructLayout(LayoutKind.Sequential)]
- public class NPortInfos
+ public struct NPortInfo
{
- [MarshalAs(UnmanagedType.LPArray, SizeConst = 16)]
- public NPortInfo[] Infos;
+ public IntPtr _shortName;
+ public IntPtr _fullName;
+ public IntPtr _defaultDeviceShortName;
+ public uint NumDevices;
+
+ public string ShortName => Marshal.PtrToStringAnsi(_shortName);
+ public string FullName => Marshal.PtrToStringAnsi(_fullName);
+ public string DefaultDeviceShortName => Marshal.PtrToStringAnsi(_defaultDeviceShortName);
}
[StructLayout(LayoutKind.Sequential)]
- public class NPortInfo
+ public struct NDeviceInfo
{
- public string ShortName;
- public string FullName;
- public string DefaultDeviceShortName;
+ public IntPtr _shortName;
+ public IntPtr _fullName;
+ public IntPtr _description;
+ public DeviceFlags Flags;
+ public uint ByteLength;
+ public uint NumInputs;
+ public string ShortName => Marshal.PtrToStringAnsi(_shortName);
+ public string FullName => Marshal.PtrToStringAnsi(_fullName);
+ public string Description => Marshal.PtrToStringAnsi(_description);
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NInputInfo
+ {
+ public IntPtr _settingName;
+ public IntPtr _name;
+ public short ConfigOrder;
+ public ushort BitOffset;
+ public InputType Type;
+ public AxisFlags Flags;
+ public byte BitSize;
+
+ public string SettingName => Marshal.PtrToStringAnsi(_settingName);
+ public string Name => Marshal.PtrToStringAnsi(_name);
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NButtonInfo
+ {
+ public IntPtr _excludeName;
+
+ public string ExcludeName => Marshal.PtrToStringAnsi(_excludeName);
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NAxisInfo
+ {
+ public IntPtr _settingsNameNeg;
+ public IntPtr _settingsNamePos;
+ public IntPtr _nameNeg;
+ public IntPtr _namePos;
+
+ public string SettingsNameNeg => Marshal.PtrToStringAnsi(_settingsNameNeg);
+ public string SettingsNamePos => Marshal.PtrToStringAnsi(_settingsNamePos);
+ public string NameNeg => Marshal.PtrToStringAnsi(_nameNeg);
+ public string NamePos => Marshal.PtrToStringAnsi(_namePos);
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NSwitchInfo
+ {
+ public uint NumPositions;
+ public uint DefaultPosition;
[StructLayout(LayoutKind.Sequential)]
- public class NDeviceInfo
+ public struct Position
{
- public string ShortName;
- public string FullName;
- public string Description;
- public DeviceFlags Flags;
- public uint ByteLength;
- [StructLayout(LayoutKind.Sequential)]
- public class NInput
- {
- public string SettingName;
- public string Name;
- public short ConfigOrder;
- public ushort BitOffset;
- public InputType Type;
- public AxisFlags Flags;
- public byte BitSize;
- public byte _Padding;
- [StructLayout(LayoutKind.Sequential)]
- public class Button
- {
- public string ExcludeName;
- }
- [StructLayout(LayoutKind.Sequential)]
- public class Axis
- {
- public string SettingsNameNeg;
- public string SettingsNamePos;
- public string NameNeg;
- public string NamePos;
- }
- [StructLayout(LayoutKind.Sequential)]
- public class Switch
- {
- [StructLayout(LayoutKind.Sequential)]
- public class Position
- {
- public string SettingName;
- public string Name;
- public string Description;
- }
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
- public Position[] Positions;
- public uint NumPositions;
- public uint DefaultPosition;
- }
- [StructLayout(LayoutKind.Sequential)]
- public class Status
- {
- public class State
- {
- public IntPtr ShortName;
- public IntPtr Name;
- public int Color; // (msb)0RGB(lsb), -1 for unused.
- public int _Padding;
- }
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
- public State[] States;
- public uint NumStates;
- }
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 400)]
- public byte[] UnionData;
- }
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
- public NInput[] Inputs;
+ public IntPtr _settingName;
+ public IntPtr _name;
+ public IntPtr _description;
+
+ public string SettingName => Marshal.PtrToStringAnsi(_settingName);
+ public string Name => Marshal.PtrToStringAnsi(_name);
+ public string Description => Marshal.PtrToStringAnsi(_description);
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NStatusInfo
+ {
+ public uint NumStates;
+ [StructLayout(LayoutKind.Sequential)]
+ public struct State
+ {
+ public IntPtr _shortName;
+ public IntPtr _name;
+ public int Color; // (msb)0RGB(lsb), -1 for unused.
+ public int _Padding;
+
+ public string ShortName => Marshal.PtrToStringAnsi(_shortName);
+ public string Name => Marshal.PtrToStringAnsi(_name);
}
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
- public NDeviceInfo[] Devices;
}
[BizImport(CC, Compatibility = true)]
- public abstract NPortInfos GetInputDevices();
+ public abstract uint GetNumPorts();
+ [BizImport(CC, Compatibility = true)]
+ public abstract NPortInfo* GetPort(uint port);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NDeviceInfo* GetDevice(uint port, uint dev);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NInputInfo* GetInput(uint port, uint dev, uint input);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NButtonInfo* GetButton(uint port, uint dev, uint input);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NSwitchInfo* GetSwitch(uint port, uint dev, uint input);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NSwitchInfo.Position* GetSwitchPosition(uint port, uint dev, uint input, int i);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NStatusInfo* GetStatus(uint port, uint dev, uint input);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NStatusInfo.State* GetStatusState(uint port, uint dev, uint input, int i);
+ [BizImport(CC, Compatibility = true)]
+ public abstract NAxisInfo* GetAxis(uint port, uint dev, uint input);
[BizImport(CC, Compatibility = true)]
public abstract void SetInputDevices(string[] devices);
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs
index e543930fd0..ead96696b5 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs
@@ -18,7 +18,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
private ControllerAdapter _controllerAdapter;
private readonly byte[] _inputPortData = new byte[16 * 16];
- protected T DoInit(GameInfo game, byte[] rom, string filename)
+ protected T DoInit(GameInfo game, byte[] rom, string filename, string extension)
where T : LibNymaCore
{
var t = PreInit(new WaterboxOptions
@@ -46,7 +46,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
// TODO: Set these as some cores need them
FileNameBase = "",
- FileNameExt = "",
+ FileNameExt = extension.Trim('.').ToLowerInvariant(),
FileNameFull = fn
});
@@ -76,7 +76,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
VsyncNumerator = info.FpsFixed;
VsyncDenominator = 1 << 24;
- _controllerAdapter = new ControllerAdapter(_nyma.GetInputDevices().Infos, new string[0]);
+ _controllerAdapter = new ControllerAdapter(_nyma, new string[0]);
_nyma.SetInputDevices(_controllerAdapter.Devices);
PostInit();
@@ -105,21 +105,13 @@ namespace BizHawk.Emulation.Cores.Waterbox
_frameAdvanceInputLock.Free();
}
- private static T ControllerData(byte[] data)
- {
- fixed(byte *p = data)
- {
- return (T)Marshal.PtrToStructure((IntPtr)p, typeof(T));
- }
- }
-
protected delegate void ControllerThunk(IController c, byte[] b);
protected class ControllerAdapter
{
public string[] Devices { get; }
public ControllerDefinition Definition { get; }
- public ControllerAdapter(LibNymaCore.NPortInfo[] portInfos, string[] devices)
+ public ControllerAdapter(LibNymaCore core, string[] config)
{
var ret = new ControllerDefinition
{
@@ -128,17 +120,36 @@ namespace BizHawk.Emulation.Cores.Waterbox
var finalDevices = new List();
- for (int i = 0, devByteStart = 0; i < portInfos.Length && portInfos[i].ShortName != null; i++)
+ var numPorts = core.GetNumPorts();
+ for (uint i = 0, devByteStart = 0; i < numPorts; i++)
{
- var port = portInfos[i];
- var devName = i < devices.Length ? devices[i] : port.DefaultDeviceShortName;
+ var port = *core.GetPort(i);
+ var devName = i < config.Length ? config[i] : port.DefaultDeviceShortName;
finalDevices.Add(devName);
- var dev = port.Devices.SingleOrDefault(d => d.ShortName == devName);
+ var devices = Enumerable.Range(0, (int)port.NumDevices)
+ .Select(j => new { Index = (uint)j, Device = *core.GetDevice(i, (uint)j) })
+ .ToList();
+
+ var device = devices.FirstOrDefault(a => a.Device.ShortName == devName);
+ if (device == null)
+ {
+ Console.WriteLine($"Warn: unknown controller device {devName}");
+ device = devices.FirstOrDefault(a => a.Device.ShortName == port.DefaultDeviceShortName);
+ if (device == null)
+ throw new InvalidOperationException($"Fail: unknown controller device {port.DefaultDeviceShortName}");
+ }
+
+ var dev = device.Device;
var category = port.FullName + " - " + dev.FullName;
- foreach (var input in dev.Inputs.OrderBy(i => i.ConfigOrder))
+ var inputs = Enumerable.Range(0, (int)dev.NumInputs)
+ .Select(iix => new { Index = iix, Data = *core.GetInput(i, device.Index, (uint)iix) })
+ .OrderBy(a => a.Data.ConfigOrder);
+
+ foreach (var inputzz in inputs)
{
+ var input = inputzz.Data;
var bitSize = (int)input.BitSize;
var bitOffset = (int)input.BitOffset;
var byteStart = devByteStart + bitOffset / 8;
@@ -153,7 +164,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
case LibNymaCore.InputType.BUTTON:
case LibNymaCore.InputType.BUTTON_CAN_RAPID:
{
- var data = ControllerData(input.UnionData);
+ var data = *core.GetButton(i, device.Index, (uint)inputzz.Index);
// TODO: Wire up data.ExcludeName
ret.BoolButtons.Add(name);
_thunks.Add((c, b) =>
@@ -165,7 +176,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
case LibNymaCore.InputType.SWITCH:
{
- var data = ControllerData(input.UnionData);
+ var data = *core.GetSwitch(i, device.Index, (uint)inputzz.Index);
// TODO: Possibly bulebutton for 2 states?
ret.AxisControls.Add(name);
ret.AxisRanges.Add(new ControllerDefinition.AxisRange(
@@ -179,7 +190,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
case LibNymaCore.InputType.AXIS:
{
- var data = ControllerData(input.UnionData);
+ var data = core.GetAxis(i, device.Index, (uint)inputzz.Index);
ret.AxisControls.Add(name);
ret.AxisRanges.Add(new ControllerDefinition.AxisRange(
0, 0x8000, 0xffff, (input.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0
@@ -194,7 +205,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
case LibNymaCore.InputType.AXIS_REL:
{
- var data = ControllerData(input.UnionData);
+ var data = core.GetAxis(i, device.Index, (uint)inputzz.Index);
ret.AxisControls.Add(name);
ret.AxisRanges.Add(new ControllerDefinition.AxisRange(
-0x8000, 0, 0x7fff, (input.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0
@@ -221,13 +232,14 @@ namespace BizHawk.Emulation.Cores.Waterbox
// ret.AxisRanges.Add(new ControllerDefinition.AxisRange(0, 0.5, 1, true));
// break;
}
+ // TODO: wire up statuses to something (not controller, of course)
default:
throw new NotImplementedException($"Unimplemented button type {input.Type}");
}
ret.CategoryLabels[name] = category;
}
- devByteStart += (int)dev.ByteLength;
+ devByteStart += dev.ByteLength;
}
Definition = ret;
Devices = finalDevices.ToArray();
@@ -244,5 +256,33 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
public DisplayType Region { get; protected set; }
+
+ ///
+ /// Gets a string array of valid layers to pass to SetLayers, or null if that method should not be called
+ ///
+ private string[] GetLayerData()
+ {
+ using (_exe.EnterExit())
+ {
+ var p = _nyma.GetLayerData();
+ if (p == null)
+ return null;
+ var ret = new List();
+ var q = p;
+ while (true)
+ {
+ if (*q == 0)
+ {
+ if (q > p)
+ ret.Add(Marshal.PtrToStringAnsi((IntPtr)p));
+ else
+ break;
+ p = ++q;
+ }
+ q++;
+ }
+ return ret.ToArray();
+ }
+ }
}
}
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs
index 3019ae46a0..0093f2439e 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs
@@ -229,7 +229,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
_disposeList.Add(_mmapheap);
}
- Console.WriteLine("About to enter unmanaged code");
+ System.Diagnostics.Debug.WriteLine($"About to enter unmanaged code for {opt.Filename}");
if (!OSTailoredCode.IsUnixHost && !System.Diagnostics.Debugger.IsAttached && Win32Imports.IsDebuggerPresent())
{
// this means that GDB or another unconventional debugger is attached.
diff --git a/waterbox/nyma/.vscode/c_cpp_properties.json b/waterbox/nyma/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000000..cd457e90ca
--- /dev/null
+++ b/waterbox/nyma/.vscode/c_cpp_properties.json
@@ -0,0 +1,20 @@
+{
+ "configurations": [
+ {
+ "name": "Waterbox",
+ "includePath": [
+ "${workspaceFolder}",
+ "${workspaceFolder}/mednafen/include",
+ "${workspaceFolder}/common",
+ "${workspaceFolder}/mednafen/src/trio",
+ "${workspaceFolder}/../sysroot/include",
+ "${workspaceFolder}/../sysroot/include/c++/v1",
+ "${workspaceFolder}/../emulibc"
+ ],
+ "defines": [
+ ],
+ "intelliSenseMode": "gcc-x64"
+ }
+ ],
+ "version": 4
+}
\ No newline at end of file
diff --git a/waterbox/nyma/Interfaces.cpp b/waterbox/nyma/Interfaces.cpp
index 851a42a6a5..f3e7970369 100644
--- a/waterbox/nyma/Interfaces.cpp
+++ b/waterbox/nyma/Interfaces.cpp
@@ -62,24 +62,50 @@ namespace Mednafen
abort();
}
+ static const MDFNSetting* GetSetting(const char* name)
+ {
+ const MDFNSetting* s;
+ for (int i = 0; s = &MDFNGameInfo->Settings[i], s->name; i++)
+ {
+ if (strcmp(s->name, name) == 0)
+ return s;
+ }
+ return nullptr;
+ }
+
uint64 MDFN_GetSettingUI(const char *name)
{
+ auto s = GetSetting(name);
+ if (s)
+ return strtoul(s->default_value, nullptr, 10);
return 0;
}
int64 MDFN_GetSettingI(const char *name)
{
+ auto s = GetSetting(name);
+ if (s)
+ return strtol(s->default_value, nullptr, 10);
return 0;
}
double MDFN_GetSettingF(const char *name)
{
+ auto s = GetSetting(name);
+ if (s)
+ return strtod(s->default_value, nullptr);
return 0;
}
bool MDFN_GetSettingB(const char *name)
{
- return false;
+ auto s = GetSetting(name);
+ if (s)
+ return strtol(s->default_value, nullptr, 10) != 0;
+ return 0;
}
std::string MDFN_GetSettingS(const char *name)
{
+ auto s = GetSetting(name);
+ if (s)
+ return s->default_value;
return "";
}
diff --git a/waterbox/nyma/NymaCore.cpp b/waterbox/nyma/NymaCore.cpp
index c2f563fe91..e80aee4b77 100644
--- a/waterbox/nyma/NymaCore.cpp
+++ b/waterbox/nyma/NymaCore.cpp
@@ -146,7 +146,12 @@ ECL_EXPORT void SetLayers(uint64_t layers)
}
ECL_EXPORT void GetMemoryAreas(MemoryArea* m)
-{}
+{
+ m[0].Data = (void*)pixels;
+ m[0].Name = "PEWP";
+ m[0].Size = Game->fb_width * Game->fb_height * 4;
+ m[0].Flags = MEMORYAREA_FLAGS_PRIMARY | MEMORYAREA_FLAGS_WORDSIZE4;
+}
ECL_EXPORT void SetInputCallback(void (*cb)())
{}
@@ -157,140 +162,155 @@ struct NPortInfo
const char* ShortName;
const char* FullName;
const char* DefaultDeviceShortName;
- struct NDeviceInfo
+ uint32_t NumDevices;
+};
+struct NDeviceInfo
+{
+ const char* ShortName;
+ const char* FullName;
+ const char* Description;
+ uint32_t Flags;
+ uint32_t ByteLength;
+ uint32_t NumInputs;
+};
+struct NInputInfo
+{
+ const char* SettingName;
+ const char* Name;
+ int16_t ConfigOrder;
+ uint16_t BitOffset;
+ InputDeviceInputType Type; // uint8_t
+ uint8_t Flags;
+ uint8_t BitSize;
+};
+struct NButtonInfo
+{
+ const char* ExcludeName;
+};
+struct NAxisInfo
+{
+ // negative, then positive
+ const char* SettingName[2];
+ const char* Name[2];
+};
+struct NSwitchInfo
+{
+ uint32_t NumPositions;
+ uint32_t DefaultPosition;
+ struct Position
+ {
+ const char* SettingName;
+ const char* Name;
+ const char* Description;
+ };
+};
+struct NStatusInfo
+{
+ uint32_t NumStates;
+ struct State
{
const char* ShortName;
- const char* FullName;
- const char* Description;
- uint32_t Flags;
- uint32_t ByteLength;
- struct NInput
- {
- const char* SettingName;
- const char* Name;
- int16_t ConfigOrder;
- uint16_t BitOffset;
- InputDeviceInputType Type; // uint8_t
- uint8_t Flags;
- uint8_t BitSize;
- uint8_t _Padding;
- union
- {
- struct
- {
- const char* ExcludeName;
- } Button;
- struct
- {
- // negative, then positive
- const char* SettingName[2];
- const char* Name[2];
- } Axis;
- struct
- {
- struct
- {
- const char* SettingName;
- const char* Name;
- const char* Description;
- } Positions[16];
- uint32_t NumPositions;
- uint32_t DefaultPosition;
- } Switch;
- struct
- {
- struct
- {
- const char* ShortName;
- const char* Name;
- int32_t Color; // (msb)0RGB(lsb), -1 for unused.
- int32_t _Padding;
- } States[16];
- uint32_t NumStates;
- } Status;
- uint8_t _Padding2[400];
- };
- } Inputs[256];
- } Devices[32];
+ const char* Name;
+ int32_t Color; // (msb)0RGB(lsb), -1 for unused.
+ int32_t _Padding;
+ };
};
-NPortInfo PortInfos[MAX_PORTS] = {};
-
-ECL_EXPORT NPortInfo* GetInputDevices()
+ECL_EXPORT uint32_t GetNumPorts()
{
- for (unsigned port = 0; port < MAX_PORTS && port < Game->PortInfo.size(); port++)
- {
- auto& a = PortInfos[port];
- auto& x = Game->PortInfo[port];
- a.ShortName = x.ShortName;
- a.FullName = x.FullName;
- a.DefaultDeviceShortName = x.DefaultDevice;
- for (unsigned dev = 0; dev < 32 && dev < x.DeviceInfo.size(); dev++)
- {
- auto& b = a.Devices[dev];
- auto& y = x.DeviceInfo[dev];
- b.ShortName = y.ShortName;
- b.FullName = y.FullName;
- b.Description = y.Description;
- b.Flags = y.Flags;
- b.ByteLength = y.IDII.InputByteSize;
- for (unsigned input = 0; input < 256 && input < y.IDII.size(); input++)
- {
- auto& c = b.Inputs[input];
- auto& z = y.IDII[input];
- c.SettingName = z.SettingName;
- c.Name = z.Name;
- c.ConfigOrder = z.ConfigOrder;
- c.BitOffset = z.BitOffset;
- c.Type = z.Type;
- c.Flags = z.Flags;
- c.BitSize = z.BitSize;
- switch (z.Type)
- {
- case IDIT_BUTTON:
- case IDIT_BUTTON_CAN_RAPID:
- c.Button.ExcludeName = z.Button.ExcludeName;
- break;
- case IDIT_SWITCH:
- c.Switch.NumPositions = z.Switch.NumPos;
- c.Switch.DefaultPosition = z.Switch.DefPos;
- for (unsigned i = 0; i < 16 && i < z.Switch.NumPos; i++)
- {
- c.Switch.Positions[i].SettingName = z.Switch.Pos[i].SettingName;
- c.Switch.Positions[i].Name = z.Switch.Pos[i].Name;
- c.Switch.Positions[i].Description = z.Switch.Pos[i].Description;
- }
- break;
- case IDIT_STATUS:
- c.Status.NumStates = z.Status.NumStates;
- for (unsigned i = 0; i < 16 && i < z.Status.NumStates; i++)
- {
- c.Status.States[i].ShortName = z.Status.States[i].ShortName;
- c.Status.States[i].Name = z.Status.States[i].Name;
- c.Status.States[i].Color = z.Status.States[i].Color;
- }
- break;
- case IDIT_AXIS:
- case IDIT_AXIS_REL:
- c.Axis.SettingName[0] = z.Axis.sname_dir[0];
- c.Axis.SettingName[1] = z.Axis.sname_dir[1];
- c.Axis.Name[0] = z.Axis.name_dir[0];
- c.Axis.Name[1] = z.Axis.name_dir[1];
- break;
- default:
- // other types have no extended information
- break;
- }
- }
- }
- }
- return PortInfos;
+ return Game->PortInfo.size();
+}
+ECL_EXPORT NPortInfo& GetPort(uint32_t port)
+{
+ auto& a = *(NPortInfo*)InputPortData;
+ auto& x = Game->PortInfo[port];
+ a.ShortName = x.ShortName;
+ a.FullName = x.FullName;
+ a.DefaultDeviceShortName = x.DefaultDevice;
+ a.NumDevices = x.DeviceInfo.size();
+ return a;
+}
+ECL_EXPORT NDeviceInfo& GetDevice(uint32_t port, uint32_t dev)
+{
+ auto& b = *(NDeviceInfo*)InputPortData;
+ auto& y = Game->PortInfo[port].DeviceInfo[dev];
+ b.ShortName = y.ShortName;
+ b.FullName = y.FullName;
+ b.Description = y.Description;
+ b.Flags = y.Flags;
+ b.ByteLength = y.IDII.InputByteSize;
+ b.NumInputs = y.IDII.size();
+ return b;
+}
+ECL_EXPORT NInputInfo& GetInput(uint32_t port, uint32_t dev, uint32_t input)
+{
+ auto& c = *(NInputInfo*)InputPortData;
+ auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input];
+ c.SettingName = z.SettingName;
+ c.Name = z.Name;
+ c.ConfigOrder = z.ConfigOrder;
+ c.BitOffset = z.BitOffset;
+ c.Type = z.Type;
+ c.Flags = z.Flags;
+ c.BitSize = z.BitSize;
+ return c;
+}
+ECL_EXPORT NButtonInfo& GetButton(uint32_t port, uint32_t dev, uint32_t input)
+{
+ auto& c = *(NButtonInfo*)InputPortData;
+ auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Button;
+ c.ExcludeName = z.ExcludeName;
+ return c;
+}
+ECL_EXPORT NSwitchInfo& GetSwitch(uint32_t port, uint32_t dev, uint32_t input)
+{
+ auto& c = *(NSwitchInfo*)InputPortData;
+ auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Switch;
+ c.NumPositions = z.NumPos;
+ c.DefaultPosition = z.DefPos;
+ return c;
+}
+ECL_EXPORT NSwitchInfo::Position& GetSwitchPosition(uint32_t port, uint32_t dev, uint32_t input, int i)
+{
+ auto& c = *(NSwitchInfo::Position*)InputPortData;
+ auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Switch;
+ c.SettingName = z.Pos[i].SettingName;
+ c.Name = z.Pos[i].Name;
+ c.Description = z.Pos[i].Description;
+ return c;
+}
+ECL_EXPORT NStatusInfo& GetStatus(uint32_t port, uint32_t dev, uint32_t input)
+{
+ auto& c = *(NStatusInfo*)InputPortData;
+ auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Status;
+ c.NumStates = z.NumStates;
+ return c;
+}
+ECL_EXPORT NStatusInfo::State& GetStatusState(uint32_t port, uint32_t dev, uint32_t input, int i)
+{
+ auto& c = *(NStatusInfo::State*)InputPortData;
+ auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Status;
+ c.ShortName = z.States[i].ShortName;
+ c.Name = z.States[i].Name;
+ c.Color = z.States[i].Color;
+ return c;
+}
+ECL_EXPORT NAxisInfo& GetAxis(uint32_t port, uint32_t dev, uint32_t input)
+{
+ auto& c = *(NAxisInfo*)InputPortData;
+ auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Axis;
+ c.SettingName[0] = z.sname_dir[0];
+ c.SettingName[1] = z.sname_dir[1];
+ c.Name[0] = z.name_dir[0];
+ c.Name[1] = z.name_dir[1];
+ return c;
}
ECL_EXPORT void SetInputDevices(const char** devices)
{
for (unsigned port = 0; port < MAX_PORTS && devices[port]; port++)
{
- Game->SetInput(port, devices[port], &InputPortData[port * MAX_PORT_DATA]);
+ std::string dev(devices[port]);
+ Game->SetInput(port, dev.c_str(), &InputPortData[port * MAX_PORT_DATA]);
}
}