From 0f65351e136a3be9e96529b8e916493673c216fb Mon Sep 17 00:00:00 2001 From: nattthebear Date: Fri, 22 May 2020 18:01:48 -0400 Subject: [PATCH] Marching onward --- src/BizHawk.BizInvoke/BizInvoker.cs | 4 +- .../Consoles/NEC/PCE/TerboGrafix.cs | 19 ++ .../Consoles/PC Engine/PCEngine.cs | 2 +- .../Waterbox/LibNymaCore.cs | 270 ++++++++++++++++++ .../Waterbox/NymaCore.cs | 247 ++++++++++++++++ .../Waterbox/WaterboxCore.cs | 2 +- waterbox/nyma/Interfaces.cpp | 4 +- waterbox/nyma/NymaCore.cpp | 54 +++- waterbox/nyma/pce.cpp | 13 + waterbox/nyma/pce.mak | 17 ++ 10 files changed, 613 insertions(+), 19 deletions(-) create mode 100644 src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs create mode 100644 src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs create mode 100644 src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs create mode 100644 waterbox/nyma/pce.cpp create mode 100644 waterbox/nyma/pce.mak diff --git a/src/BizHawk.BizInvoke/BizInvoker.cs b/src/BizHawk.BizInvoke/BizInvoker.cs index 3177d7a147..3d99af00b4 100644 --- a/src/BizHawk.BizInvoke/BizInvoker.cs +++ b/src/BizHawk.BizInvoke/BizInvoker.cs @@ -287,7 +287,7 @@ namespace BizHawk.BizInvoke var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray(); var nativeParamTypes = new List(); var returnType = baseMethod.ReturnType; - if (returnType != typeof(void) && !returnType.IsPrimitive) + if (returnType != typeof(void) && !returnType.IsPrimitive && !returnType.IsPointer) { throw new InvalidOperationException("Only primitive return types are supported"); } @@ -527,7 +527,7 @@ namespace BizHawk.BizInvoke return typeof(IntPtr); } - if (type.IsPrimitive || type.IsEnum) + if (type.IsPrimitive || type.IsEnum || type.IsPointer) { il.Emit(OpCodes.Ldarg, (short)idx); return type; diff --git a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs new file mode 100644 index 0000000000..2b893e62ea --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TerboGrafix.cs @@ -0,0 +1,19 @@ +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; + +namespace BizHawk.Emulation.Cores.Consoles.NEC.PCE +{ + [Core("Terbo Grafix", "Mednafen Team", true, false, "", "", false)] + public class TerboGrafix : NymaCore, IRegionable + { + [CoreConstructor("PCE")] + public TerboGrafix(GameInfo game, byte[] rom, CoreComm comm) + : base(game, rom, comm, new Configuration + { + // TODO: This stuff isn't used so much + }) + { + DoInit(game, rom, "pce.wbx"); + } + } +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs index b11a4bd28c..823393cd9a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs @@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.PCEngine public sealed partial class PCEngine : IEmulator, ISaveRam, IInputPollable, IVideoLogicalOffsets, IRomInfo, IDebuggable, ISettable, IDriveLight, ICodeDataLogger { - [CoreConstructor(new[] { "PCE", "SGX" })] + // [CoreConstructor(new[] { "PCE", "SGX" })] public PCEngine(GameInfo game, byte[] rom, object settings, object syncSettings) { switch (game.System) diff --git a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs new file mode 100644 index 0000000000..bd3f8668ea --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs @@ -0,0 +1,270 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using BizHawk.BizInvoke; + +namespace BizHawk.Emulation.Cores.Waterbox +{ + public abstract unsafe class LibNymaCore : LibWaterboxCore + { + [StructLayout(LayoutKind.Sequential)] + public class InitData + { + /// + /// Filename without extension. Used in autodetect + /// + public string FileNameBase; + /// + /// Just the extension. Used in autodetect. LOWERCASE PLEASE. + /// + public string FileNameExt; + /// + /// Full filename. This will be fopen()ed by the core + /// + public string FileNameFull; + } + + [BizImport(CC, Compatibility = true)] + public abstract bool Init([In]InitData data); + + public enum CommandType : int + { + NONE = 0x00, + RESET = 0x01, + POWER = 0x02, + + INSERT_COIN = 0x07, + + TOGGLE_DIP0 = 0x10, + TOGGLE_DIP1, + TOGGLE_DIP2, + TOGGLE_DIP3, + TOGGLE_DIP4, + TOGGLE_DIP5, + TOGGLE_DIP6, + TOGGLE_DIP7, + TOGGLE_DIP8, + TOGGLE_DIP9, + TOGGLE_DIP10, + TOGGLE_DIP11, + TOGGLE_DIP12, + TOGGLE_DIP13, + TOGGLE_DIP14, + TOGGLE_DIP15, + } + + [StructLayout(LayoutKind.Sequential)] + public new class FrameInfo : LibWaterboxCore.FrameInfo + { + /// + /// true to skip video rendering + /// + public int SkipRendering; + /// + /// a single command to run at the start of this frame + /// + public CommandType Command; + /// + /// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long + /// + public byte* InputPortData; + } + + [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 + /// + 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 + [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... + } + + [Flags] + public enum AxisFlags: byte + { + NONE = 0, + // Denotes analog data that may need to be scaled to ensure a more squareish logical range(for emulated analog sticks) + SQLR = 0x01, + // Invert config order of the two components(neg,pos) of the axis + INVERT_CO = 0x02, + SETTINGS_UNDOC = 0x80, + } + + [Flags] + public enum DeviceFlags: uint + { + NONE = 0, + KEYBOARD = 1 + } + + [StructLayout(LayoutKind.Sequential)] + public class NPortInfos + { + [MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] + public NPortInfo[] Infos; + } + [StructLayout(LayoutKind.Sequential)] + public class NPortInfo + { + public string ShortName; + public string FullName; + public string DefaultDeviceShortName; + + [StructLayout(LayoutKind.Sequential)] + public class NDeviceInfo + { + 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; + } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public NDeviceInfo[] Devices; + } + + [BizImport(CC, Compatibility = true)] + public abstract NPortInfos GetInputDevices(); + + [BizImport(CC, Compatibility = true)] + public abstract void SetInputDevices(string[] devices); + + public enum VideoSystem : int + { + NONE, + PAL, + PAL_M, + NTSC, + SECAM + } + + [StructLayout(LayoutKind.Sequential)] + public class SystemInfo + { + public int MaxWidth; + public int MaxHeight; + public int NominalWidth; + public int NominalHeight; + public VideoSystem VideoSystem; + public int FpsFixed; + } + + [BizImport(CC, Compatibility = true)] + public abstract SystemInfo GetSystemInfo(); + } +} diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs new file mode 100644 index 0000000000..d463f34c9b --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs @@ -0,0 +1,247 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using BizHawk.Common; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Waterbox +{ + public unsafe abstract class NymaCore : WaterboxCore + { + protected NymaCore(GameInfo game, byte[] rom, CoreComm comm, Configuration c) + : base(comm, c) + { + } + + private LibNymaCore _nyma; + private ControllerAdapter _controllerAdapter; + private readonly byte[] _inputPortData = new byte[16 * 16]; + + protected T DoInit(GameInfo game, byte[] rom, string filename) + where T : LibNymaCore + { + var t = PreInit(new WaterboxOptions + { + // TODO cfg and stuff + Filename = filename, + SbrkHeapSizeKB = 1024 * 16, + SealedHeapSizeKB = 1024 * 16, + InvisibleHeapSizeKB = 1024 * 16, + PlainHeapSizeKB = 1024 * 16, + StartAddress = WaterboxHost.CanonicalStart, + SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), + SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), + }); + _nyma = t; + + using (_exe.EnterExit()) + { + var fn = game.FilesystemSafeName(); + + _exe.AddReadonlyFile(rom, fn); + + var didInit = _nyma.Init(new LibNymaCore.InitData + { + // TODO: Set these as some cores need them + FileNameBase = "", + FileNameExt = "", + FileNameFull = fn + }); + + if (!didInit) + throw new InvalidOperationException("Core rejected the rom!"); + + _exe.RemoveReadonlyFile(fn); + + var info = _nyma.GetSystemInfo(); + _videoBuffer = new int[info.MaxWidth * info.MaxHeight]; + BufferWidth = info.NominalWidth; + BufferHeight = info.NominalHeight; + switch (info.VideoSystem) + { + // TODO: There seriously isn't any region besides these? + case LibNymaCore.VideoSystem.PAL: + case LibNymaCore.VideoSystem.SECAM: + Region = DisplayType.PAL; + break; + case LibNymaCore.VideoSystem.PAL_M: + Region = DisplayType.Dendy; // sort of... + break; + default: + Region = DisplayType.NTSC; + break; + } + VsyncNumerator = info.FpsFixed; + VsyncDenominator = 1 << 24; + + _controllerAdapter = new ControllerAdapter(_nyma.GetInputDevices().Infos, new string[0]); + _nyma.SetInputDevices(_controllerAdapter.Devices); + + PostInit(); + } + + return t; + } + + // todo: bleh + private GCHandle _frameAdvanceInputLock; + + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) + { + _controllerAdapter.SetBits(controller, _inputPortData); + _frameAdvanceInputLock = GCHandle.Alloc(_inputPortData, GCHandleType.Pinned); + var ret = new LibNymaCore.FrameInfo + { + SkipRendering = render ? 0 : 1, + Command = LibNymaCore.CommandType.NONE, + InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject() + }; + return ret; + } + protected override void FrameAdvancePost() + { + _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) + { + var ret = new ControllerDefinition + { + Name = "TODO" + }; + + var finalDevices = new List(); + + for (int i = 0, devByteStart = 0; i < portInfos.Length && portInfos[i].ShortName != null; i++) + { + var port = portInfos[i]; + var devName = i < devices.Length ? devices[i] : port.DefaultDeviceShortName; + finalDevices.Add(devName); + + var dev = port.Devices.SingleOrDefault(d => d.ShortName == devName); + var category = port.FullName + " - " + dev.FullName; + + foreach (var input in dev.Inputs.OrderBy(i => i.ConfigOrder)) + { + var bitSize = (int)input.BitSize; + var bitOffset = (int)input.BitOffset; + var byteStart = devByteStart + bitOffset / 8; + bitOffset %= 8; + var name = input.Name; + switch (input.Type) + { + case LibNymaCore.InputType.PADDING: + { + break; + } + case LibNymaCore.InputType.BUTTON: + case LibNymaCore.InputType.BUTTON_CAN_RAPID: + { + var data = ControllerData(input.UnionData); + // TODO: Wire up data.ExcludeName + ret.BoolButtons.Add(name); + _thunks.Add((c, b) => + { + if (c.IsPressed(name)) + b[byteStart] |= (byte)(1 << bitOffset); + }); + break; + } + case LibNymaCore.InputType.SWITCH: + { + var data = ControllerData(input.UnionData); + // TODO: Possibly bulebutton for 2 states? + ret.AxisControls.Add(name); + ret.AxisRanges.Add(new ControllerDefinition.AxisRange( + 0, (int)data.DefaultPosition, (int)data.NumPositions - 1)); + _thunks.Add((c, b) => + { + var val = (int)Math.Round(c.AxisValue(name)); + b[byteStart] |= (byte)(1 << bitOffset); + }); + break; + } + case LibNymaCore.InputType.AXIS: + { + var data = ControllerData(input.UnionData); + ret.AxisControls.Add(name); + ret.AxisRanges.Add(new ControllerDefinition.AxisRange( + 0, 0x8000, 0xffff, (input.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0 + )); + _thunks.Add((c, b) => + { + var val = (ushort)Math.Round(c.AxisValue(name)); + b[byteStart] = (byte)val; + b[byteStart + 1] = (byte)(val >> 8); + }); + break; + } + case LibNymaCore.InputType.AXIS_REL: + { + var data = ControllerData(input.UnionData); + ret.AxisControls.Add(name); + ret.AxisRanges.Add(new ControllerDefinition.AxisRange( + -0x8000, 0, 0x7fff, (input.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0 + )); + _thunks.Add((c, b) => + { + var val = (short)Math.Round(c.AxisValue(name)); + b[byteStart] = (byte)val; + b[byteStart + 1] = (byte)(val >> 8); + }); + break; + } + case LibNymaCore.InputType.POINTER_X: + { + throw new Exception("TODO: Axis ranges are ints????"); + // ret.AxisControls.Add(name); + // ret.AxisRanges.Add(new ControllerDefinition.AxisRange(0, 0.5, 1)); + // break; + } + case LibNymaCore.InputType.POINTER_Y: + { + throw new Exception("TODO: Axis ranges are ints????"); + // ret.AxisControls.Add(name); + // ret.AxisRanges.Add(new ControllerDefinition.AxisRange(0, 0.5, 1, true)); + // break; + } + default: + throw new NotImplementedException($"Unimplemented button type {input.Type}"); + } + ret.CategoryLabels[name] = category; + } + + devByteStart += (int)dev.ByteLength; + } + Definition = ret; + Devices = finalDevices.ToArray(); + } + + private readonly List> _thunks = new List>(); + + public void SetBits(IController src, byte[] dest) + { + Array.Clear(dest, 0, dest.Length); + foreach (var t in _thunks) + t(src, dest); + } + } + + public DisplayType Region { get; protected set; } + } +} diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs index 70d3d86422..605e88f004 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs @@ -329,7 +329,7 @@ namespace BizHawk.Emulation.Cores.Waterbox return _videoBuffer; } - protected readonly int[] _videoBuffer; + protected int[] _videoBuffer; public virtual int VirtualWidth => BufferWidth; public virtual int VirtualHeight => BufferHeight; public int BufferWidth { get; protected set; } diff --git a/waterbox/nyma/Interfaces.cpp b/waterbox/nyma/Interfaces.cpp index 3f05ff2d30..851a42a6a5 100644 --- a/waterbox/nyma/Interfaces.cpp +++ b/waterbox/nyma/Interfaces.cpp @@ -54,7 +54,7 @@ namespace Mednafen va_start(argp, format); vfprintf(t == MDFN_NOTICE_ERROR ? stderr : stdout, format, argp); } - void MDFND_MidSync(EmulateSpecStruct *espec, const unsigned flags) + void MDFN_MidSync(EmulateSpecStruct *espec, const unsigned flags) {} bool MDFNSS_StateAction(StateMem *sm, const unsigned load, const bool data_only, const SFORMAT *sf, const char *sname, const bool optional) noexcept @@ -100,6 +100,8 @@ namespace Mednafen {} void MDFNMP_ApplyPeriodicCheats(void) {} + std::vector SubCheats[8]; + bool SubCheatsOn; // player.h void Player_Init(int tsongs, const std::string &album, const std::string &artist, const std::string ©right, const std::vector &snames, bool override_gi) diff --git a/waterbox/nyma/NymaCore.cpp b/waterbox/nyma/NymaCore.cpp index 6bbf070a03..c2f563fe91 100644 --- a/waterbox/nyma/NymaCore.cpp +++ b/waterbox/nyma/NymaCore.cpp @@ -113,6 +113,33 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame) } } +struct SystemInfo +{ + int32_t MaxWidth; + int32_t MaxHeight; + int32_t NominalWidth; + int32_t NominalHeight; + int32_t VideoSystem; + int32_t FpsFixed; +}; +SystemInfo SI; + +ECL_EXPORT SystemInfo* GetSystemInfo() +{ + SI.MaxWidth = Game->fb_width; + SI.MaxHeight = Game->fb_height; + SI.NominalWidth = Game->nominal_width; + SI.NominalHeight = Game->nominal_height; + SI.VideoSystem = Game->VideoSystem; + SI.FpsFixed = Game->fps; + return &SI; +} + +ECL_EXPORT const char* GetLayerData() +{ + return Game->LayerNames; +} + ECL_EXPORT void SetLayers(uint64_t layers) { Game->SetLayerEnableMask(layers); @@ -127,20 +154,20 @@ ECL_EXPORT void SetInputCallback(void (*cb)()) // same information as PortInfo, but easier to marshal struct NPortInfo { - const char *ShortName; - const char *FullName; - const char *DefaultDeviceShortName; + const char* ShortName; + const char* FullName; + const char* DefaultDeviceShortName; struct NDeviceInfo { - const char *ShortName; - const char *FullName; - const char *Description; + const char* ShortName; + const char* FullName; + const char* Description; uint32_t Flags; uint32_t ByteLength; struct NInput { - const char *SettingName; - const char *Name; + const char* SettingName; + const char* Name; int16_t ConfigOrder; uint16_t BitOffset; InputDeviceInputType Type; // uint8_t @@ -166,7 +193,7 @@ struct NPortInfo const char* SettingName; const char* Name; const char* Description; - }* Positions; + } Positions[16]; uint32_t NumPositions; uint32_t DefaultPosition; } Switch; @@ -178,9 +205,10 @@ struct NPortInfo const char* Name; int32_t Color; // (msb)0RGB(lsb), -1 for unused. int32_t _Padding; - }* States; + } States[16]; uint32_t NumStates; } Status; + uint8_t _Padding2[400]; }; } Inputs[256]; } Devices[32]; @@ -226,8 +254,7 @@ ECL_EXPORT NPortInfo* GetInputDevices() case IDIT_SWITCH: c.Switch.NumPositions = z.Switch.NumPos; c.Switch.DefaultPosition = z.Switch.DefPos; - c.Switch.Positions = (decltype(c.Switch.Positions))calloc(z.Switch.NumPos, sizeof(*c.Switch.Positions)); - for (unsigned i = 0; i < z.Switch.NumPos; i++) + 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; @@ -236,8 +263,7 @@ ECL_EXPORT NPortInfo* GetInputDevices() break; case IDIT_STATUS: c.Status.NumStates = z.Status.NumStates; - c.Status.States = (decltype(c.Status.States))calloc(z.Status.NumStates, sizeof(*c.Status.States)); - for (unsigned i = 0; i < z.Status.NumStates; i++) + 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; diff --git a/waterbox/nyma/pce.cpp b/waterbox/nyma/pce.cpp new file mode 100644 index 0000000000..80637d85f5 --- /dev/null +++ b/waterbox/nyma/pce.cpp @@ -0,0 +1,13 @@ +#include "mednafen/src/types.h" +#include "nyma.h" +#include +#include "mednafen/src/pce/pce.h" + +using namespace MDFN_IEN_PCE; + +extern Mednafen::MDFNGI EmulatedPCE; + +void SetupMDFNGameInfo() +{ + Mednafen::MDFNGameInfo = &EmulatedPCE; +} diff --git a/waterbox/nyma/pce.mak b/waterbox/nyma/pce.mak new file mode 100644 index 0000000000..fb39ef5b55 --- /dev/null +++ b/waterbox/nyma/pce.mak @@ -0,0 +1,17 @@ +include common.mak + +# $(call cppdir,hw_video/huc6270) +# $(call cppdir,hw_sound/pce_psg) + +SRCS += \ + $(filter-out %debug.cpp,$(call cppdir,pce)) \ + $(filter-out %CDAFReader_SF.cpp,$(call cppdir,cdrom)) \ + $(call cdir,tremor) \ + $(call cdir,mpcdec) \ + mednafen/src/mthreading/MThreading_POSIX.cpp \ + $(call cppdir,hw_sound/pce_psg) \ + $(call cppdir,hw_misc/arcade_card) \ + $(call cppdir,hw_video/huc6270) \ + pce.cpp + +include ../common.mak