mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
401 lines
12 KiB
C#
401 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Mesen.Localization;
|
|
using Mesen.Config.Shortcuts;
|
|
using Mesen.Utilities;
|
|
using Avalonia.Media.Imaging;
|
|
|
|
namespace Mesen.Interop
|
|
{
|
|
public class EmuApi
|
|
{
|
|
public const string DllName = "MesenCore.dll";
|
|
private const string DllPath = EmuApi.DllName;
|
|
|
|
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool TestDll();
|
|
[DllImport(DllPath)] public static extern void InitDll();
|
|
|
|
[DllImport(DllPath, EntryPoint = "GetMesenVersion")] private static extern UInt32 GetMesenVersionWrapper();
|
|
public static Version GetMesenVersion()
|
|
{
|
|
UInt32 version = GetMesenVersionWrapper();
|
|
UInt32 revision = version & 0xFF;
|
|
UInt32 minor = (version >> 8) & 0xFF;
|
|
UInt32 major = (version >> 16) & 0xFFFF;
|
|
return new Version((int)major, (int)minor, (int)revision);
|
|
}
|
|
|
|
[DllImport(DllPath, EntryPoint = "GetMesenBuildDate")] private static extern IntPtr GetMesenBuildDateWrapper();
|
|
public static string GetMesenBuildDate()
|
|
{
|
|
return Utf8Utilities.PtrToStringUtf8(GetMesenBuildDateWrapper());
|
|
}
|
|
|
|
[DllImport(DllPath)] public static extern IntPtr RegisterNotificationCallback(NotificationListener.NotificationCallback callback);
|
|
[DllImport(DllPath)] public static extern void UnregisterNotificationCallback(IntPtr notificationListener);
|
|
|
|
[DllImport(DllPath)] public static extern void InitializeEmu([MarshalAs(UnmanagedType.LPUTF8Str)]string homeFolder, IntPtr windowHandle, IntPtr dxViewerHandle, [MarshalAs(UnmanagedType.I1)] bool useSoftwareRenderer, [MarshalAs(UnmanagedType.I1)]bool noAudio, [MarshalAs(UnmanagedType.I1)]bool noVideo, [MarshalAs(UnmanagedType.I1)]bool noInput);
|
|
|
|
[DllImport(DllPath)] public static extern void Release();
|
|
|
|
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsRunning();
|
|
[DllImport(DllPath)] public static extern void Stop();
|
|
[DllImport(DllPath)] public static extern Int32 GetStopCode();
|
|
|
|
public static void Reset() { Task.Run(() => EmuApi.ExecuteShortcut(new ExecuteShortcutParams() { Shortcut = EmulatorShortcut.ExecReset })); }
|
|
public static void PowerCycle() { Task.Run(() => EmuApi.ExecuteShortcut(new ExecuteShortcutParams() { Shortcut = EmulatorShortcut.ExecPowerCycle })); }
|
|
public static void PowerOff() { Task.Run(() => EmuApi.ExecuteShortcut(new ExecuteShortcutParams() { Shortcut = EmulatorShortcut.ExecPowerOff })); }
|
|
public static void ReloadRom() { Task.Run(() => EmuApi.ExecuteShortcut(new ExecuteShortcutParams() { Shortcut = EmulatorShortcut.ExecReloadRom })); }
|
|
|
|
[DllImport(DllPath)] public static extern void Pause();
|
|
[DllImport(DllPath)] public static extern void Resume();
|
|
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsPaused();
|
|
|
|
[DllImport(DllPath)] public static extern void TakeScreenshot();
|
|
|
|
[DllImport(DllPath)] public static extern void ProcessAudioPlayerAction(AudioPlayerActionParams p);
|
|
|
|
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool LoadRom(
|
|
[MarshalAs(UnmanagedType.LPUTF8Str)]string filepath,
|
|
[MarshalAs(UnmanagedType.LPUTF8Str)]string? patchFile = null
|
|
);
|
|
|
|
[DllImport(DllPath, EntryPoint = "GetRomInfo")] private static extern void GetRomInfoWrapper(out InteropRomInfo romInfo);
|
|
public static RomInfo GetRomInfo()
|
|
{
|
|
InteropRomInfo info;
|
|
EmuApi.GetRomInfoWrapper(out info);
|
|
return new RomInfo(info);
|
|
}
|
|
|
|
[DllImport(DllPath)] public static extern void LoadRecentGame([MarshalAs(UnmanagedType.LPUTF8Str)]string filepath, [MarshalAs(UnmanagedType.I1)]bool resetGame);
|
|
|
|
[DllImport(DllPath)] public static extern void AddKnownGameFolder([MarshalAs(UnmanagedType.LPUTF8Str)]string folder);
|
|
|
|
[DllImport(DllPath)] public static extern void SetExclusiveFullscreenMode([MarshalAs(UnmanagedType.I1)]bool fullscreen, IntPtr windowHandle);
|
|
|
|
[DllImport(DllPath)] public static extern TimingInfo GetTimingInfo(CpuType cpuType);
|
|
|
|
[DllImport(DllPath)] public static extern double GetAspectRatio();
|
|
[DllImport(DllPath)] public static extern FrameInfo GetBaseScreenSize();
|
|
[DllImport(DllPath)] public static extern Int32 GetGameMemorySize(MemoryType type);
|
|
|
|
[DllImport(DllPath)] public static extern void SetRendererSize(UInt32 width, UInt32 height);
|
|
|
|
[DllImport(DllPath)] public static extern void ExecuteShortcut(ExecuteShortcutParams p);
|
|
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsShortcutAllowed(EmulatorShortcut shortcut, UInt32 shortcutParam = 0);
|
|
|
|
[DllImport(DllPath, EntryPoint = "GetLog")] private static extern void GetLogWrapper(IntPtr outLog, Int32 maxLength);
|
|
public static string GetLog() { return Utf8Utilities.CallStringApi(GetLogWrapper, 100000); }
|
|
|
|
[DllImport(DllPath)] public static extern void WriteLogEntry([MarshalAs(UnmanagedType.LPUTF8Str)]string message);
|
|
[DllImport(DllPath)] public static extern void DisplayMessage([MarshalAs(UnmanagedType.LPUTF8Str)]string title, [MarshalAs(UnmanagedType.LPUTF8Str)]string message, [MarshalAs(UnmanagedType.LPUTF8Str)]string? param1 = null);
|
|
|
|
[DllImport(DllPath, EntryPoint = "GetRomHash")] private static extern void GetRomHashWrapper(HashType hashType, IntPtr outLog, Int32 maxLength);
|
|
public static string GetRomHash(HashType hashType) { return Utf8Utilities.CallStringApi((IntPtr outLog, Int32 maxLength) => {
|
|
GetRomHashWrapper(hashType, outLog, maxLength);
|
|
}, 1000000); }
|
|
|
|
[DllImport(DllPath)] public static extern IntPtr GetArchiveRomList([MarshalAs(UnmanagedType.LPUTF8Str)]string filename, IntPtr outFileList, Int32 maxLength);
|
|
|
|
[DllImport(DllPath)] public static extern void SaveState(UInt32 stateIndex);
|
|
[DllImport(DllPath)] public static extern void LoadState(UInt32 stateIndex);
|
|
[DllImport(DllPath)] public static extern void SaveStateFile([MarshalAs(UnmanagedType.LPUTF8Str)]string filepath);
|
|
[DllImport(DllPath)] public static extern void LoadStateFile([MarshalAs(UnmanagedType.LPUTF8Str)]string filepath);
|
|
|
|
[DllImport(DllPath, EntryPoint = "GetSaveStatePreview")] private static extern Int32 GetSaveStatePreviewWrapper([MarshalAs(UnmanagedType.LPUTF8Str)]string saveStatePath, [Out]byte[] imgData);
|
|
public static Bitmap? GetSaveStatePreview(string saveStatePath)
|
|
{
|
|
if(File.Exists(saveStatePath)) {
|
|
byte[] buffer = new byte[512*478*4];
|
|
Int32 size = EmuApi.GetSaveStatePreviewWrapper(saveStatePath, buffer);
|
|
if(size > 0) {
|
|
Array.Resize(ref buffer, size);
|
|
using(MemoryStream stream = new MemoryStream(buffer)) {
|
|
return new Bitmap(stream);
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool GetConvertedCheat([In]InteropCheatCode input, ref InteropInternalCheatCode output);
|
|
[DllImport(DllPath)] public static extern void SetCheats([In]InteropCheatCode[] cheats, UInt32 cheatCount);
|
|
[DllImport(DllPath)] public static extern void ClearCheats();
|
|
|
|
[DllImport(DllPath)] public static extern void InputBarcode(UInt64 barcode, UInt32 digitCount);
|
|
[DllImport(DllPath)] public static extern void ProcessTapeRecorderAction(TapeRecorderAction action, [MarshalAs(UnmanagedType.LPUTF8Str)] string filename = "");
|
|
}
|
|
|
|
public struct TimingInfo
|
|
{
|
|
public double Fps;
|
|
public UInt64 MasterClock;
|
|
public UInt32 MasterClockRate;
|
|
public UInt32 FrameCount;
|
|
|
|
public UInt32 ScanlineCount;
|
|
public Int32 FirstScanline;
|
|
public UInt32 CycleCount;
|
|
}
|
|
|
|
public struct FrameInfo
|
|
{
|
|
public UInt32 Width;
|
|
public UInt32 Height;
|
|
}
|
|
|
|
public enum RomFormat
|
|
{
|
|
Unknown,
|
|
|
|
Sfc,
|
|
Spc,
|
|
|
|
Gb,
|
|
Gbs,
|
|
|
|
iNes,
|
|
Unif,
|
|
Fds,
|
|
VsSystem,
|
|
VsDualSystem,
|
|
Nsf,
|
|
StudyBox,
|
|
|
|
Pce,
|
|
PceCdRom,
|
|
PceHes,
|
|
|
|
Sms,
|
|
GameGear,
|
|
Sg,
|
|
ColecoVision,
|
|
|
|
Gba,
|
|
|
|
Ws
|
|
}
|
|
|
|
public enum ConsoleType
|
|
{
|
|
Snes = 0,
|
|
Gameboy = 1,
|
|
Nes = 2,
|
|
PcEngine = 3,
|
|
Sms = 4,
|
|
Gba = 5,
|
|
Ws = 6,
|
|
}
|
|
|
|
public struct InteropDipSwitchInfo
|
|
{
|
|
public UInt32 DatabaseId;
|
|
public UInt32 DipSwitchCount;
|
|
}
|
|
|
|
public struct InteropRomInfo
|
|
{
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2000)]
|
|
public byte[] RomPath;
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2000)]
|
|
public byte[] PatchPath;
|
|
|
|
public RomFormat Format;
|
|
public ConsoleType ConsoleType;
|
|
public InteropDipSwitchInfo DipSwitches;
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
|
public CpuType[] CpuTypes;
|
|
public UInt32 CpuTypeCount;
|
|
}
|
|
|
|
public class RomInfo
|
|
{
|
|
public string RomPath = "";
|
|
public string PatchPath = "";
|
|
public RomFormat Format = RomFormat.Unknown;
|
|
public ConsoleType ConsoleType = ConsoleType.Snes;
|
|
public InteropDipSwitchInfo DipSwitches;
|
|
public HashSet<CpuType> CpuTypes = new HashSet<CpuType>();
|
|
|
|
public RomInfo() { }
|
|
|
|
public RomInfo(InteropRomInfo romInfo)
|
|
{
|
|
RomPath = (ResourcePath)Utf8Utilities.GetStringFromArray(romInfo.RomPath);
|
|
PatchPath = (ResourcePath)Utf8Utilities.GetStringFromArray(romInfo.PatchPath);
|
|
Format = romInfo.Format;
|
|
ConsoleType = romInfo.ConsoleType;
|
|
DipSwitches = romInfo.DipSwitches;
|
|
|
|
for(int i = 0; i < romInfo.CpuTypeCount; i++) {
|
|
CpuTypes.Add(romInfo.CpuTypes[i]);
|
|
}
|
|
}
|
|
|
|
public string GetRomName()
|
|
{
|
|
return Path.GetFileNameWithoutExtension(((ResourcePath)RomPath).FileName);
|
|
}
|
|
}
|
|
|
|
public enum FirmwareType
|
|
{
|
|
DSP1,
|
|
DSP1B,
|
|
DSP2,
|
|
DSP3,
|
|
DSP4,
|
|
ST010,
|
|
ST011,
|
|
ST018,
|
|
Satellaview,
|
|
SufamiTurbo,
|
|
Gameboy,
|
|
GameboyColor,
|
|
GameboyAdvance,
|
|
Sgb1GameboyCpu,
|
|
Sgb2GameboyCpu,
|
|
SGB1,
|
|
SGB2,
|
|
FDS,
|
|
StudyBox,
|
|
PceSuperCd,
|
|
PceGamesExpress,
|
|
ColecoVision,
|
|
WonderSwan,
|
|
WonderSwanColor,
|
|
SwanCrystal,
|
|
Ymf288AdpcmRom,
|
|
SmsBootRom,
|
|
GgBootRom
|
|
}
|
|
|
|
public struct MissingFirmwareMessage
|
|
{
|
|
public IntPtr Filename;
|
|
public FirmwareType Firmware;
|
|
public UInt32 Size;
|
|
public UInt32 AltSize;
|
|
}
|
|
|
|
public struct SufamiTurboFilePromptMessage
|
|
{
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5000)]
|
|
public byte[] Filename;
|
|
}
|
|
|
|
public struct ExecuteShortcutParams
|
|
{
|
|
public EmulatorShortcut Shortcut;
|
|
public UInt32 Param;
|
|
public IntPtr ParamPtr;
|
|
};
|
|
|
|
public enum AudioPlayerAction
|
|
{
|
|
NextTrack,
|
|
PrevTrack,
|
|
SelectTrack,
|
|
}
|
|
|
|
public struct AudioPlayerActionParams
|
|
{
|
|
public AudioPlayerAction Action;
|
|
public UInt32 TrackNumber;
|
|
}
|
|
|
|
public enum TapeRecorderAction
|
|
{
|
|
Play,
|
|
StartRecord,
|
|
StopRecord
|
|
}
|
|
|
|
public enum CheatType : byte
|
|
{
|
|
NesGameGenie = 0,
|
|
NesProActionRocky,
|
|
NesCustom,
|
|
GbGameGenie,
|
|
GbGameShark,
|
|
SnesGameGenie,
|
|
SnesProActionReplay,
|
|
PceRaw,
|
|
PceAddress,
|
|
SmsProActionReplay,
|
|
SmsGameGenie
|
|
}
|
|
|
|
public static class CheatTypeExtensions
|
|
{
|
|
public static CpuType ToCpuType(this CheatType cheatType)
|
|
{
|
|
return cheatType switch {
|
|
CheatType.NesGameGenie or CheatType.NesProActionRocky or CheatType.NesCustom => CpuType.Nes,
|
|
CheatType.SnesGameGenie or CheatType.SnesProActionReplay => CpuType.Snes,
|
|
CheatType.GbGameGenie or CheatType.GbGameShark => CpuType.Gameboy,
|
|
CheatType.PceRaw or CheatType.PceAddress => CpuType.Pce,
|
|
CheatType.SmsGameGenie or CheatType.SmsProActionReplay => CpuType.Sms,
|
|
_ => throw new NotImplementedException("unsupported cheat type")
|
|
};
|
|
}
|
|
}
|
|
|
|
public struct InteropCheatCode
|
|
{
|
|
public CheatType Type;
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
|
public byte[] Code;
|
|
|
|
public InteropCheatCode(CheatType type, string code)
|
|
{
|
|
Type = type;
|
|
|
|
Code = new byte[16];
|
|
byte[] codeBytes = Encoding.UTF8.GetBytes(code);
|
|
Array.Copy(codeBytes, Code, Math.Min(codeBytes.Length, 15));
|
|
}
|
|
}
|
|
|
|
public struct InteropInternalCheatCode
|
|
{
|
|
public MemoryType MemType;
|
|
public UInt32 Address;
|
|
public Int16 Compare;
|
|
public byte Value;
|
|
public CheatType Type;
|
|
public CpuType Cpu;
|
|
[MarshalAs(UnmanagedType.I1)] public bool IsRamCode;
|
|
[MarshalAs(UnmanagedType.I1)] public bool IsAbsoluteAddress;
|
|
}
|
|
|
|
public enum HashType
|
|
{
|
|
Sha1,
|
|
Sha1Cheat
|
|
}
|
|
|
|
public struct SoftwareRendererSurface
|
|
{
|
|
public IntPtr FrameBuffer;
|
|
public UInt32 Width;
|
|
public UInt32 Height;
|
|
[MarshalAs(UnmanagedType.I1)] public bool IsDirty;
|
|
}
|
|
|
|
public struct SoftwareRendererFrame
|
|
{
|
|
public SoftwareRendererSurface Frame;
|
|
public SoftwareRendererSurface EmuHud;
|
|
public SoftwareRendererSurface ScriptHud;
|
|
}
|
|
}
|