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]); } }