1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.IO.Compression;
5 using System.Linq;
6 using System.Runtime.InteropServices;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
10 using Mesen.GUI.Config;
11 using Mesen.GUI.Forms;
12 
13 namespace Mesen.GUI
14 {
15 	public class InteropEmu
16 	{
17 		private const string DLLPath = "MesenCore.dll";
TestDll()18 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool TestDll();
InitDll()19 		[DllImport(DLLPath)] public static extern void InitDll();
20 
GetMesenVersionWrapper()21 		[DllImport(DLLPath, EntryPoint = "GetMesenVersion")] private static extern UInt32 GetMesenVersionWrapper();
22 
InitializeEmu([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string homeFolder, IntPtr windowHandle, IntPtr dxViewerHandle, [MarshalAs(UnmanagedType.I1)]bool noAudio, [MarshalAs(UnmanagedType.I1)]bool noVideo, [MarshalAs(UnmanagedType.I1)]bool noInput)23 		[DllImport(DLLPath)] public static extern void InitializeEmu([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string homeFolder, IntPtr windowHandle, IntPtr dxViewerHandle, [MarshalAs(UnmanagedType.I1)]bool noAudio, [MarshalAs(UnmanagedType.I1)]bool noVideo, [MarshalAs(UnmanagedType.I1)]bool noInput);
Release()24 		[DllImport(DLLPath)] public static extern void Release();
25 
InitializeDualSystem(IntPtr windowHandle, IntPtr viewerHandle)26 		[DllImport(DLLPath)] public static extern void InitializeDualSystem(IntPtr windowHandle, IntPtr viewerHandle);
ReleaseDualSystemAudioVideo()27 		[DllImport(DLLPath)] public static extern void ReleaseDualSystemAudioVideo();
28 
HistoryViewerEnabled()29 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HistoryViewerEnabled();
HistoryViewerInitialize(IntPtr windowHandle, IntPtr viewerHandle)30 		[DllImport(DLLPath)] public static extern void HistoryViewerInitialize(IntPtr windowHandle, IntPtr viewerHandle);
HistoryViewerRelease()31 		[DllImport(DLLPath)] public static extern void HistoryViewerRelease();
HistoryViewerRun()32 		[DllImport(DLLPath)] public static extern void HistoryViewerRun();
HistoryViewerStop()33 		[DllImport(DLLPath)] public static extern void HistoryViewerStop();
HistoryViewerGetHistoryLength()34 		[DllImport(DLLPath)] public static extern UInt32 HistoryViewerGetHistoryLength();
HistoryViewerSaveMovie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string movieFile, UInt32 startPosition, UInt32 endPosition)35 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HistoryViewerSaveMovie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string movieFile, UInt32 startPosition, UInt32 endPosition);
HistoryViewerCreateSaveState([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string outfileFile, UInt32 position)36 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HistoryViewerCreateSaveState([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string outfileFile, UInt32 position);
HistoryViewerSetPosition(UInt32 seekPosition)37 		[DllImport(DLLPath)] public static extern void HistoryViewerSetPosition(UInt32 seekPosition);
HistoryViewerResumeGameplay(UInt32 seekPosition)38 		[DllImport(DLLPath)] public static extern void HistoryViewerResumeGameplay(UInt32 seekPosition);
HistoryViewerGetPosition()39 		[DllImport(DLLPath)] public static extern UInt32 HistoryViewerGetPosition();
HistoryViewerGetSegmentsWrapper(IntPtr segmentBuffer, ref UInt32 bufferSize)40 		[DllImport(DLLPath, EntryPoint = "HistoryViewerGetSegments")] public static extern void HistoryViewerGetSegmentsWrapper(IntPtr segmentBuffer, ref UInt32 bufferSize);
41 
SetDisplayLanguage(Language lang)42 		[DllImport(DLLPath)] public static extern void SetDisplayLanguage(Language lang);
43 
SetFullscreenMode([MarshalAs(UnmanagedType.I1)]bool fullscreen, IntPtr windowHandle, UInt32 monitorWidth, UInt32 monitorHeight)44 		[DllImport(DLLPath)] public static extern void SetFullscreenMode([MarshalAs(UnmanagedType.I1)]bool fullscreen, IntPtr windowHandle, UInt32 monitorWidth, UInt32 monitorHeight);
45 
IsRunning()46 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsRunning();
GetStopCode()47 		[DllImport(DLLPath)] public static extern Int32 GetStopCode();
48 
LoadROM([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string patchFile)49 		[DllImport(DLLPath)] public static extern void LoadROM([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string patchFile);
AddKnownGameFolder([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string folder)50 		[DllImport(DLLPath)] public static extern void AddKnownGameFolder([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string folder);
SetFolderOverrides([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string saveDataFolder, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string saveStateFolder, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string screenshotFolder)51 		[DllImport(DLLPath)] public static extern void SetFolderOverrides([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string saveDataFolder, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string saveStateFolder, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string screenshotFolder);
LoadRecentGame([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath, [MarshalAs(UnmanagedType.I1)]bool resetGame)52 		[DllImport(DLLPath)] public static extern void LoadRecentGame([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath, [MarshalAs(UnmanagedType.I1)]bool resetGame);
53 
GetArchiveRomListWrapper([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename)54 		[DllImport(DLLPath, EntryPoint = "GetArchiveRomList")] private static extern IntPtr GetArchiveRomListWrapper([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename);
55 
SetMousePosition(double x, double y)56 		[DllImport(DLLPath)] public static extern void SetMousePosition(double x, double y);
SetMouseMovement(Int16 x, Int16 y)57 		[DllImport(DLLPath)] public static extern void SetMouseMovement(Int16 x, Int16 y);
HasZapper()58 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HasZapper();
HasArkanoidPaddle()59 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HasArkanoidPaddle();
HasFourScore()60 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HasFourScore();
61 
SetControllerType(int port, ControllerType type)62 		[DllImport(DLLPath)] public static extern void SetControllerType(int port, ControllerType type);
SetControllerKeys(int port, KeyMappingSet mapping)63 		[DllImport(DLLPath)] public static extern void SetControllerKeys(int port, KeyMappingSet mapping);
SetZapperDetectionRadius(UInt32 detectionRadius)64 		[DllImport(DLLPath)] public static extern void SetZapperDetectionRadius(UInt32 detectionRadius);
SetControllerDeadzoneSize(UInt32 deadzoneSize)65 		[DllImport(DLLPath)] public static extern void SetControllerDeadzoneSize(UInt32 deadzoneSize);
SetExpansionDevice(ExpansionPortDevice device)66 		[DllImport(DLLPath)] public static extern void SetExpansionDevice(ExpansionPortDevice device);
SetConsoleType(ConsoleType type)67 		[DllImport(DLLPath)] public static extern void SetConsoleType(ConsoleType type);
SetMouseSensitivity(MouseDevice device, double sensitivity)68 		[DllImport(DLLPath)] public static extern void SetMouseSensitivity(MouseDevice device, double sensitivity);
ClearShortcutKeys()69 		[DllImport(DLLPath)] public static extern void ClearShortcutKeys();
SetShortcutKey(EmulatorShortcut shortcut, KeyCombination keyCombination, int keySetIndex)70 		[DllImport(DLLPath)] public static extern void SetShortcutKey(EmulatorShortcut shortcut, KeyCombination keyCombination, int keySetIndex);
71 
GetControllerType(int port)72 		[DllImport(DLLPath)] public static extern ControllerType GetControllerType(int port);
GetExpansionDevice()73 		[DllImport(DLLPath)] public static extern ExpansionPortDevice GetExpansionDevice();
GetConsoleType()74 		[DllImport(DLLPath)] public static extern ConsoleType GetConsoleType();
75 
UpdateInputDevices()76 		[DllImport(DLLPath)] public static extern void UpdateInputDevices();
77 
GetAvailableFeatures()78 		[DllImport(DLLPath)] public static extern ConsoleFeatures GetAvailableFeatures();
79 
GetPressedKeysWrapper(IntPtr keyBuffer)80 		[DllImport(DLLPath, EntryPoint = "GetPressedKeys")] private static extern void GetPressedKeysWrapper(IntPtr keyBuffer);
GetKeyCode([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string keyName)81 		[DllImport(DLLPath)] public static extern UInt32 GetKeyCode([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string keyName);
GetKeyNameWrapper(UInt32 key)82 		[DllImport(DLLPath, EntryPoint = "GetKeyName")] private static extern IntPtr GetKeyNameWrapper(UInt32 key);
SetKeyState(Int32 scanCode, [MarshalAs(UnmanagedType.I1)]bool pressed)83 		[DllImport(DLLPath)] public static extern void SetKeyState(Int32 scanCode, [MarshalAs(UnmanagedType.I1)]bool pressed);
ResetKeyState()84 		[DllImport(DLLPath)] public static extern void ResetKeyState();
DisableAllKeys([MarshalAs(UnmanagedType.I1)]bool disabled)85 		[DllImport(DLLPath)] public static extern void DisableAllKeys([MarshalAs(UnmanagedType.I1)]bool disabled);
86 
Run()87 		[DllImport(DLLPath)] public static extern void Run();
Resume(ConsoleId consoleId = ConsoleId.Master)88 		[DllImport(DLLPath)] public static extern void Resume(ConsoleId consoleId = ConsoleId.Master);
Pause(ConsoleId consoleId = ConsoleId.Master)89 		[DllImport(DLLPath)] public static extern void Pause(ConsoleId consoleId = ConsoleId.Master);
IsPaused(ConsoleId consoleId = ConsoleId.Master)90 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsPaused(ConsoleId consoleId = ConsoleId.Master);
Stop()91 		[DllImport(DLLPath)] public static extern void Stop();
92 
GetRomInfoWrapper(ref InteropRomInfo romInfo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename = R)93 		[DllImport(DLLPath, EntryPoint = "GetRomInfo")] private static extern UInt32 GetRomInfoWrapper(ref InteropRomInfo romInfo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename = "");
94 
PowerCycle()95 		[DllImport(DLLPath)] public static extern void PowerCycle();
Reset()96 		[DllImport(DLLPath)] public static extern void Reset();
ResetLagCounter()97 		[DllImport(DLLPath)] public static extern void ResetLagCounter();
98 
StartServer(UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string password, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string hostPlayerName)99 		[DllImport(DLLPath)] public static extern void StartServer(UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string password, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string hostPlayerName);
StopServer()100 		[DllImport(DLLPath)] public static extern void StopServer();
IsServerRunning()101 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsServerRunning();
Connect([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string host, UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string password, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string playerName, [MarshalAs(UnmanagedType.I1)]bool spectator)102 		[DllImport(DLLPath)] public static extern void Connect([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string host, UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string password, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string playerName, [MarshalAs(UnmanagedType.I1)]bool spectator);
Disconnect()103 		[DllImport(DLLPath)] public static extern void Disconnect();
IsConnected()104 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsConnected();
105 
NetPlayGetAvailableControllers()106 		[DllImport(DLLPath)] public static extern Int32 NetPlayGetAvailableControllers();
NetPlaySelectController(Int32 controllerPort)107 		[DllImport(DLLPath)] public static extern void NetPlaySelectController(Int32 controllerPort);
NetPlayGetControllerType(Int32 controllerPort)108 		[DllImport(DLLPath)] public static extern ControllerType NetPlayGetControllerType(Int32 controllerPort);
NetPlayGetControllerPort()109 		[DllImport(DLLPath)] public static extern Int32 NetPlayGetControllerPort();
110 
TakeScreenshot()111 		[DllImport(DLLPath)] public static extern void TakeScreenshot();
112 
RegisterNotificationCallback(ConsoleId consoleId, NotificationListener.NotificationCallback callback)113 		[DllImport(DLLPath)] public static extern IntPtr RegisterNotificationCallback(ConsoleId consoleId, NotificationListener.NotificationCallback callback);
UnregisterNotificationCallback(IntPtr notificationListener)114 		[DllImport(DLLPath)] public static extern void UnregisterNotificationCallback(IntPtr notificationListener);
115 
DisplayMessage([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string title, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string message, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string param1 = null)116 		[DllImport(DLLPath)] public static extern void DisplayMessage([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string title, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string message, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string param1 = null);
GetLogWrapper()117 		[DllImport(DLLPath, EntryPoint = "GetLog")] private static extern IntPtr GetLogWrapper();
WriteLogEntry([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string message)118 		[DllImport(DLLPath)] public static extern void WriteLogEntry([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string message);
119 
MoviePlay([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename)120 		[DllImport(DLLPath)] public static extern void MoviePlay([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename);
MovieRecord(ref RecordMovieOptions options)121 		[DllImport(DLLPath)] public static extern void MovieRecord(ref RecordMovieOptions options);
MovieStop()122 		[DllImport(DLLPath)] public static extern void MovieStop();
MoviePlaying()123 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool MoviePlaying();
MovieRecording()124 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool MovieRecording();
125 
AviRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, VideoCodec codec, UInt32 compressionLevel)126 		[DllImport(DLLPath)] public static extern void AviRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, VideoCodec codec, UInt32 compressionLevel);
AviStop()127 		[DllImport(DLLPath)] public static extern void AviStop();
AviIsRecording()128 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool AviIsRecording();
129 
WaveRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename)130 		[DllImport(DLLPath)] public static extern void WaveRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename);
WaveStop()131 		[DllImport(DLLPath)] public static extern void WaveStop();
WaveIsRecording()132 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool WaveIsRecording();
133 
RunRecordedTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename)134 		[DllImport(DLLPath)] public static extern Int32 RunRecordedTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename);
RunAutomaticTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename)135 		[DllImport(DLLPath)] public static extern Int32 RunAutomaticTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename);
RomTestRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool reset)136 		[DllImport(DLLPath)] public static extern void RomTestRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool reset);
RomTestRecordFromMovie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string testFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string movieFilename)137 		[DllImport(DLLPath)] public static extern void RomTestRecordFromMovie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string testFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string movieFilename);
RomTestRecordFromTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string newTestFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string existingTestFilename)138 		[DllImport(DLLPath)] public static extern void RomTestRecordFromTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string newTestFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string existingTestFilename);
RomTestStop()139 		[DllImport(DLLPath)] public static extern void RomTestStop();
RomTestRecording()140 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool RomTestRecording();
141 
SaveState(UInt32 stateIndex)142 		[DllImport(DLLPath)] public static extern void SaveState(UInt32 stateIndex);
LoadState(UInt32 stateIndex)143 		[DllImport(DLLPath)] public static extern void LoadState(UInt32 stateIndex);
SaveStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath)144 		[DllImport(DLLPath)] public static extern void SaveStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath);
LoadStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath)145 		[DllImport(DLLPath)] public static extern void LoadStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath);
GetStateInfo(UInt32 stateIndex)146 		[DllImport(DLLPath)] public static extern Int64 GetStateInfo(UInt32 stateIndex);
147 
IsNsf()148 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsNsf();
NsfSelectTrack(Byte trackNumber)149 		[DllImport(DLLPath)] public static extern void NsfSelectTrack(Byte trackNumber);
NsfGetCurrentTrack()150 		[DllImport(DLLPath)] public static extern Int32 NsfGetCurrentTrack();
NsfGetFrameCount()151 		[DllImport(DLLPath)] public static extern UInt32 NsfGetFrameCount();
NsfGetHeaderWrapper(out NsfHeader header)152 		[DllImport(DLLPath, EntryPoint = "NsfGetHeader")] private static extern void NsfGetHeaderWrapper(out NsfHeader header);
NsfSetNsfConfig(Int32 autoDetectSilenceDelay, Int32 moveToNextTrackTime, [MarshalAs(UnmanagedType.I1)]bool disableApuIrqs)153 		[DllImport(DLLPath)] public static extern void NsfSetNsfConfig(Int32 autoDetectSilenceDelay, Int32 moveToNextTrackTime, [MarshalAs(UnmanagedType.I1)]bool disableApuIrqs);
154 
FdsGetSideCount()155 		[DllImport(DLLPath)] public static extern UInt32 FdsGetSideCount();
FdsEjectDisk()156 		[DllImport(DLLPath)] public static extern void FdsEjectDisk();
FdsInsertDisk(UInt32 diskNumber)157 		[DllImport(DLLPath)] public static extern void FdsInsertDisk(UInt32 diskNumber);
FdsSwitchDiskSide()158 		[DllImport(DLLPath)] public static extern void FdsSwitchDiskSide();
FdsIsAutoInsertDiskEnabled()159 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool FdsIsAutoInsertDiskEnabled();
160 
IsVsSystem()161 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsVsSystem();
IsVsDualSystem()162 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsVsDualSystem();
VsInsertCoin(UInt32 port)163 		[DllImport(DLLPath)] public static extern void VsInsertCoin(UInt32 port);
164 
GetDipSwitchCount()165 		[DllImport(DLLPath)] public static extern UInt32 GetDipSwitchCount();
SetDipSwitches(UInt32 dipSwitches)166 		[DllImport(DLLPath)] public static extern void SetDipSwitches(UInt32 dipSwitches);
167 
InputBarcode(UInt64 barcode, Int32 digitCount)168 		[DllImport(DLLPath)] public static extern void InputBarcode(UInt64 barcode, Int32 digitCount);
169 
LoadTapeFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath)170 		[DllImport(DLLPath)] public static extern void LoadTapeFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath);
StartRecordingTapeFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath)171 		[DllImport(DLLPath)] public static extern void StartRecordingTapeFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath);
StopRecordingTapeFile()172 		[DllImport(DLLPath)] public static extern void StopRecordingTapeFile();
IsRecordingTapeFile()173 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsRecordingTapeFile();
174 
SetCheats([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]InteropCheatInfo[] cheats, UInt32 length)175 		[DllImport(DLLPath)] public static extern void SetCheats([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]InteropCheatInfo[] cheats, UInt32 length);
176 
SetOsdState([MarshalAs(UnmanagedType.I1)]bool enabled)177 		[DllImport(DLLPath)] public static extern void SetOsdState([MarshalAs(UnmanagedType.I1)]bool enabled);
SetGameDatabaseState([MarshalAs(UnmanagedType.I1)]bool enabled)178 		[DllImport(DLLPath)] public static extern void SetGameDatabaseState([MarshalAs(UnmanagedType.I1)]bool enabled);
179 
CheckFlag(EmulationFlags flag)180 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool CheckFlag(EmulationFlags flag);
SetFlags(EmulationFlags flags)181 		[DllImport(DLLPath)] private static extern void SetFlags(EmulationFlags flags);
ClearFlags(EmulationFlags flags)182 		[DllImport(DLLPath)] private static extern void ClearFlags(EmulationFlags flags);
SetRamPowerOnState(RamPowerOnState state)183 		[DllImport(DLLPath)] public static extern void SetRamPowerOnState(RamPowerOnState state);
SetMasterVolume(double volume, double volumeReduction, ConsoleId consoleId = ConsoleId.Master)184 		[DllImport(DLLPath)] public static extern void SetMasterVolume(double volume, double volumeReduction, ConsoleId consoleId = ConsoleId.Master);
SetChannelVolume(AudioChannel channel, double volume)185 		[DllImport(DLLPath)] public static extern void SetChannelVolume(AudioChannel channel, double volume);
SetChannelPanning(AudioChannel channel, double panning)186 		[DllImport(DLLPath)] public static extern void SetChannelPanning(AudioChannel channel, double panning);
SetEqualizerFilterType(EqualizerFilterType filter)187 		[DllImport(DLLPath)] public static extern void SetEqualizerFilterType(EqualizerFilterType filter);
SetEqualizerBands([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]double[] bands, UInt32 length)188 		[DllImport(DLLPath)] public static extern void SetEqualizerBands([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]double[] bands, UInt32 length);
SetBandGain(int band, double gain)189 		[DllImport(DLLPath)] public static extern void SetBandGain(int band, double gain);
SetSampleRate(UInt32 sampleRate)190 		[DllImport(DLLPath)] public static extern void SetSampleRate(UInt32 sampleRate);
SetAudioLatency(UInt32 msLatency)191 		[DllImport(DLLPath)] public static extern void SetAudioLatency(UInt32 msLatency);
SetAudioFilterSettings(AudioFilterSettings settings)192 		[DllImport(DLLPath)] public static extern void SetAudioFilterSettings(AudioFilterSettings settings);
193 
GetNesModel()194 		[DllImport(DLLPath)] public static extern NesModel GetNesModel();
SetNesModel(NesModel model)195 		[DllImport(DLLPath)] public static extern void SetNesModel(NesModel model);
SetEmulationSpeed(UInt32 emulationSpeed)196 		[DllImport(DLLPath)] public static extern void SetEmulationSpeed(UInt32 emulationSpeed);
IncreaseEmulationSpeed()197 		[DllImport(DLLPath)] public static extern void IncreaseEmulationSpeed();
DecreaseEmulationSpeed()198 		[DllImport(DLLPath)] public static extern void DecreaseEmulationSpeed();
GetEmulationSpeed()199 		[DllImport(DLLPath)] public static extern UInt32 GetEmulationSpeed();
SetTurboRewindSpeed(UInt32 turboSpeed, UInt32 rewindSpeed)200 		[DllImport(DLLPath)] public static extern void SetTurboRewindSpeed(UInt32 turboSpeed, UInt32 rewindSpeed);
SetRewindBufferSize(UInt32 seconds)201 		[DllImport(DLLPath)] public static extern void SetRewindBufferSize(UInt32 seconds);
IsRewinding()202 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsRewinding();
SetOverclockRate(UInt32 overclockRate, [MarshalAs(UnmanagedType.I1)]bool adjustApu)203 		[DllImport(DLLPath)] public static extern void SetOverclockRate(UInt32 overclockRate, [MarshalAs(UnmanagedType.I1)]bool adjustApu);
SetPpuNmiConfig(UInt32 extraScanlinesBeforeNmi, UInt32 extraScanlineAfterNmi)204 		[DllImport(DLLPath)] public static extern void SetPpuNmiConfig(UInt32 extraScanlinesBeforeNmi, UInt32 extraScanlineAfterNmi);
SetOverscanDimensions(UInt32 left, UInt32 right, UInt32 top, UInt32 bottom)205 		[DllImport(DLLPath)] public static extern void SetOverscanDimensions(UInt32 left, UInt32 right, UInt32 top, UInt32 bottom);
SetVideoScale(double scale, ConsoleId consoleId = ConsoleId.Master)206 		[DllImport(DLLPath)] public static extern void SetVideoScale(double scale, ConsoleId consoleId = ConsoleId.Master);
SetScreenRotation(UInt32 angle)207 		[DllImport(DLLPath)] public static extern void SetScreenRotation(UInt32 angle);
SetExclusiveRefreshRate(UInt32 refreshRate)208 		[DllImport(DLLPath)] public static extern void SetExclusiveRefreshRate(UInt32 refreshRate);
SetVideoAspectRatio(VideoAspectRatio aspectRatio, double customRatio)209 		[DllImport(DLLPath)] public static extern void SetVideoAspectRatio(VideoAspectRatio aspectRatio, double customRatio);
SetVideoFilter(VideoFilterType filter)210 		[DllImport(DLLPath)] public static extern void SetVideoFilter(VideoFilterType filter);
SetVideoResizeFilter(VideoResizeFilter filter)211 		[DllImport(DLLPath)] public static extern void SetVideoResizeFilter(VideoResizeFilter filter);
SetRgbPalette(byte[] palette, UInt32 paletteSize)212 		[DllImport(DLLPath)] public static extern void SetRgbPalette(byte[] palette, UInt32 paletteSize);
SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity)213 		[DllImport(DLLPath)] public static extern void SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity);
SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, [MarshalAs(UnmanagedType.I1)]bool mergeFields, double yFilterLength, double iFilterLength, double qFilterLength, [MarshalAs(UnmanagedType.I1)]bool verticalBlend)214 		[DllImport(DLLPath)] public static extern void SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, [MarshalAs(UnmanagedType.I1)]bool mergeFields, double yFilterLength, double iFilterLength, double qFilterLength, [MarshalAs(UnmanagedType.I1)]bool verticalBlend);
SetInputDisplaySettings(byte visiblePorts, InputDisplayPosition displayPosition, [MarshalAs(UnmanagedType.I1)]bool displayHorizontally)215 		[DllImport(DLLPath)] public static extern void SetInputDisplaySettings(byte visiblePorts, InputDisplayPosition displayPosition, [MarshalAs(UnmanagedType.I1)]bool displayHorizontally);
SetAutoSaveOptions(UInt32 delayInMinutes, [MarshalAs(UnmanagedType.I1)]bool showMessage)216 		[DllImport(DLLPath)] public static extern void SetAutoSaveOptions(UInt32 delayInMinutes, [MarshalAs(UnmanagedType.I1)]bool showMessage);
SetPauseScreenMessage([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string message)217 		[DllImport(DLLPath)] public static extern void SetPauseScreenMessage([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string message);
218 
GetRgbPaletteWrapper(IntPtr paletteBuffer)219 		[DllImport(DLLPath, EntryPoint = "GetRgbPalette")] private static extern void GetRgbPaletteWrapper(IntPtr paletteBuffer);
220 
GetScreenSizeWrapper(ConsoleId consoleId, out ScreenSize size, [MarshalAs(UnmanagedType.I1)]bool ignoreScale)221 		[DllImport(DLLPath, EntryPoint = "GetScreenSize")] private static extern void GetScreenSizeWrapper(ConsoleId consoleId, out ScreenSize size, [MarshalAs(UnmanagedType.I1)]bool ignoreScale);
222 
GetAudioDevicesWrapper()223 		[DllImport(DLLPath, EntryPoint = "GetAudioDevices")] private static extern IntPtr GetAudioDevicesWrapper();
SetAudioDevice(string audioDevice)224 		[DllImport(DLLPath)] public static extern void SetAudioDevice(string audioDevice);
225 
DebugSetDebuggerConsole(ConsoleId consoleId)226 		[DllImport(DLLPath)] public static extern void DebugSetDebuggerConsole(ConsoleId consoleId);
DebugInitialize()227 		[DllImport(DLLPath)] public static extern void DebugInitialize();
DebugIsDebuggerRunning()228 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugIsDebuggerRunning();
DebugRelease()229 		[DllImport(DLLPath)] public static extern void DebugRelease();
DebugSetFlags(DebuggerFlags flags)230 		[DllImport(DLLPath)] public static extern void DebugSetFlags(DebuggerFlags flags);
DebugGetState(ref DebugState state)231 		[DllImport(DLLPath)] public static extern void DebugGetState(ref DebugState state);
DebugGetApuState(ref ApuState state)232 		[DllImport(DLLPath)] public static extern void DebugGetApuState(ref ApuState state);
DebugGetInstructionProgress(ref InstructionProgress progress)233 		[DllImport(DLLPath)] public static extern void DebugGetInstructionProgress(ref InstructionProgress progress);
DebugSetState(DebugState state)234 		[DllImport(DLLPath)] public static extern void DebugSetState(DebugState state);
DebugSetBreakpoints([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]InteropBreakpoint[] breakpoints, UInt32 length)235 		[DllImport(DLLPath)] public static extern void DebugSetBreakpoints([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]InteropBreakpoint[] breakpoints, UInt32 length);
DebugSetLabel(UInt32 address, AddressType addressType, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string label, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string comment)236 		[DllImport(DLLPath)] public static extern void DebugSetLabel(UInt32 address, AddressType addressType, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string label, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string comment);
DebugDeleteLabels()237 		[DllImport(DLLPath)] public static extern void DebugDeleteLabels();
DebugStep(UInt32 count, BreakSource source = BreakSource.CpuStep)238 		[DllImport(DLLPath)] public static extern void DebugStep(UInt32 count, BreakSource source = BreakSource.CpuStep);
DebugPpuStep(UInt32 count)239 		[DllImport(DLLPath)] public static extern void DebugPpuStep(UInt32 count);
DebugStepCycles(UInt32 count)240 		[DllImport(DLLPath)] public static extern void DebugStepCycles(UInt32 count);
DebugStepOut()241 		[DllImport(DLLPath)] public static extern void DebugStepOut();
DebugStepOver()242 		[DllImport(DLLPath)] public static extern void DebugStepOver();
DebugStepBack()243 		[DllImport(DLLPath)] public static extern void DebugStepBack();
DebugBreakOnScanline(Int32 scanline)244 		[DllImport(DLLPath)] public static extern void DebugBreakOnScanline(Int32 scanline);
DebugRun()245 		[DllImport(DLLPath)] public static extern void DebugRun();
DebugIsExecutionStopped()246 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugIsExecutionStopped();
DebugGetRelativeAddress(UInt32 absoluteAddr, AddressType type)247 		[DllImport(DLLPath)] public static extern Int32 DebugGetRelativeAddress(UInt32 absoluteAddr, AddressType type);
DebugFindSubEntryPoint(UInt16 relativeAddr)248 		[DllImport(DLLPath)] public static extern Int32 DebugFindSubEntryPoint(UInt16 relativeAddr);
DebugGetAbsoluteAddress(UInt32 relativeAddr)249 		[DllImport(DLLPath)] public static extern Int32 DebugGetAbsoluteAddress(UInt32 relativeAddr);
DebugGetAbsoluteChrAddress(UInt32 relativeAddr)250 		[DllImport(DLLPath)] public static extern Int32 DebugGetAbsoluteChrAddress(UInt32 relativeAddr);
DebugGetRelativePpuAddress(UInt32 absoluteAddr, PpuAddressType type)251 		[DllImport(DLLPath)] public static extern Int32 DebugGetRelativePpuAddress(UInt32 absoluteAddr, PpuAddressType type);
DebugGetMemorySize(DebugMemoryType type)252 		[DllImport(DLLPath)] public static extern Int32 DebugGetMemorySize(DebugMemoryType type);
DebugGetMemoryValue(DebugMemoryType type, UInt32 address)253 		[DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(DebugMemoryType type, UInt32 address);
DebugSetMemoryValue(DebugMemoryType type, UInt32 address, byte value)254 		[DllImport(DLLPath)] public static extern void DebugSetMemoryValue(DebugMemoryType type, UInt32 address, byte value);
DebugSetInputOverride(Int32 port, Int32 state)255 		[DllImport(DLLPath)] public static extern void DebugSetInputOverride(Int32 port, Int32 state);
256 
DebugGetPerformanceTrackerMode()257 		[DllImport(DLLPath)] public static extern PerfTrackerMode DebugGetPerformanceTrackerMode();
DebugSetPerformanceTracker(Int32 address, AddressType type, PerfTrackerMode mode)258 		[DllImport(DLLPath)] public static extern void DebugSetPerformanceTracker(Int32 address, AddressType type, PerfTrackerMode mode);
259 
DebugSetScriptTimeout(UInt32 timeout)260 		[DllImport(DLLPath)] public static extern void DebugSetScriptTimeout(UInt32 timeout);
DebugLoadScript([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string content, Int32 scriptId = -1)261 		[DllImport(DLLPath)] public static extern Int32 DebugLoadScript([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string content, Int32 scriptId = -1);
DebugRemoveScript(Int32 scriptId)262 		[DllImport(DLLPath)] public static extern void DebugRemoveScript(Int32 scriptId);
DebugGetScriptLogWrapper(Int32 scriptId)263 		[DllImport(DLLPath, EntryPoint = "DebugGetScriptLog")] private static extern IntPtr DebugGetScriptLogWrapper(Int32 scriptId);
DebugGetScriptLog(Int32 scriptId)264 		public static string DebugGetScriptLog(Int32 scriptId) { return PtrToStringUtf8(InteropEmu.DebugGetScriptLogWrapper(scriptId)).Replace("\n", Environment.NewLine); }
265 
DebugStartCodeRunnerWrapper(IntPtr byteCode, Int32 codeLength)266 		[DllImport(DLLPath, EntryPoint = "DebugStartCodeRunner")] private static extern void DebugStartCodeRunnerWrapper(IntPtr byteCode, Int32 codeLength);
DebugStartCodeRunner(byte[] data)267 		public static void DebugStartCodeRunner(byte[] data)
268 		{
269 			GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
270 			try {
271 				InteropEmu.DebugStartCodeRunnerWrapper(handle.AddrOfPinnedObject(), data.Length);
272 			} finally {
273 				handle.Free();
274 			}
275 		}
276 
DebugSetMemoryValuesWrapper(DebugMemoryType type, UInt32 address, IntPtr data, Int32 length)277 		[DllImport(DLLPath, EntryPoint = "DebugSetMemoryValues")] private static extern void DebugSetMemoryValuesWrapper(DebugMemoryType type, UInt32 address, IntPtr data, Int32 length);
DebugSetMemoryValues(DebugMemoryType type, UInt32 address, byte[] data)278 		public static void DebugSetMemoryValues(DebugMemoryType type, UInt32 address, byte[] data)
279 		{
280 			GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
281 			try {
282 				InteropEmu.DebugSetMemoryValuesWrapper(type, address, handle.AddrOfPinnedObject(), data.Length);
283 			} finally {
284 				handle.Free();
285 			}
286 		}
287 
DebugGetAbsoluteAddressAndType(UInt32 relativeAddr, AddressTypeInfo addressTypeInfo)288 		[DllImport(DLLPath)] public static extern void DebugGetAbsoluteAddressAndType(UInt32 relativeAddr, AddressTypeInfo addressTypeInfo);
289 
DebugGetPpuAbsoluteAddressAndTypeWrapper(UInt32 relativeAddr, PpuAddressTypeInfo addressTypeInfo)290 		[DllImport(DLLPath, EntryPoint = "DebugGetPpuAbsoluteAddressAndType")] private static extern void DebugGetPpuAbsoluteAddressAndTypeWrapper(UInt32 relativeAddr, PpuAddressTypeInfo addressTypeInfo);
DebugGetPpuAbsoluteAddressAndType(UInt32 relativeAddr)291 		public static PpuAddressTypeInfo DebugGetPpuAbsoluteAddressAndType(UInt32 relativeAddr)
292 		{
293 			PpuAddressTypeInfo addressTypeInfo = new PpuAddressTypeInfo();
294 			InteropEmu.DebugGetPpuAbsoluteAddressAndTypeWrapper(relativeAddr, addressTypeInfo);
295 			return addressTypeInfo;
296 		}
297 
DebugSetPpuViewerScanlineCycle(Int32 ppuViewerId, Int32 scanline, Int32 cycle)298 		[DllImport(DLLPath)] public static extern void DebugSetPpuViewerScanlineCycle(Int32 ppuViewerId, Int32 scanline, Int32 cycle);
DebugClearPpuViewerSettings(Int32 ppuViewerId)299 		[DllImport(DLLPath)] public static extern void DebugClearPpuViewerSettings(Int32 ppuViewerId);
300 
DebugSetFreezeState(UInt16 address, [MarshalAs(UnmanagedType.I1)]bool frozen)301 		[DllImport(DLLPath)] public static extern void DebugSetFreezeState(UInt16 address, [MarshalAs(UnmanagedType.I1)]bool frozen);
302 
DebugSetNextStatement(UInt16 addr)303 		[DllImport(DLLPath)] public static extern void DebugSetNextStatement(UInt16 addr);
DebugEvaluateExpression([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string expression, out EvalResultType resultType, [MarshalAs(UnmanagedType.I1)]bool useCache)304 		[DllImport(DLLPath)] public static extern Int32 DebugEvaluateExpression([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string expression, out EvalResultType resultType, [MarshalAs(UnmanagedType.I1)]bool useCache);
305 
DebugStartTraceLogger([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename)306 		[DllImport(DLLPath)] public static extern void DebugStartTraceLogger([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename);
DebugStopTraceLogger()307 		[DllImport(DLLPath)] public static extern void DebugStopTraceLogger();
DebugClearTraceLog()308 		[DllImport(DLLPath)] public static extern void DebugClearTraceLog();
DebugSetTraceOptions(InteropTraceLoggerOptions options)309 		[DllImport(DLLPath)] public static extern void DebugSetTraceOptions(InteropTraceLoggerOptions options);
DebugGetExecutionTraceWrapper(UInt32 lineCount)310 		[DllImport(DLLPath, EntryPoint = "DebugGetExecutionTrace")] private static extern IntPtr DebugGetExecutionTraceWrapper(UInt32 lineCount);
DebugGetExecutionTrace(UInt32 lineCount)311 		public static string DebugGetExecutionTrace(UInt32 lineCount) { return PtrToStringUtf8(InteropEmu.DebugGetExecutionTraceWrapper(lineCount)); }
312 
DebugMarkPrgBytesAs(UInt32 start, UInt32 end, CdlPrgFlags type)313 		[DllImport(DLLPath)] public static extern void DebugMarkPrgBytesAs(UInt32 start, UInt32 end, CdlPrgFlags type);
DebugLoadCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string cdlFilepath)314 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugLoadCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string cdlFilepath);
DebugSaveCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string cdlFilepath)315 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugSaveCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string cdlFilepath);
DebugGetCdlRatios(ref CdlRatios ratios)316 		[DllImport(DLLPath)] public static extern void DebugGetCdlRatios(ref CdlRatios ratios);
DebugResetCdlLog()317 		[DllImport(DLLPath)] public static extern void DebugResetCdlLog();
DebugResetMemoryAccessCounts()318 		[DllImport(DLLPath)] public static extern void DebugResetMemoryAccessCounts();
DebugResetProfiler()319 		[DllImport(DLLPath)] public static extern void DebugResetProfiler();
320 
DebugRevertPrgChrChanges()321 		[DllImport(DLLPath)] public static extern void DebugRevertPrgChrChanges();
DebugHasPrgChrChanges()322 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugHasPrgChrChanges();
323 
DebugPerformUndo()324 		[DllImport(DLLPath)] public static extern void DebugPerformUndo();
DebugHasUndoHistory()325 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugHasUndoHistory();
326 
DebugGetNesHeaderWrapper(IntPtr headerBuffer)327 		[DllImport(DLLPath, EntryPoint = "DebugGetNesHeader")] public static extern void DebugGetNesHeaderWrapper(IntPtr headerBuffer);
DebugGetNesHeader()328 		public static byte[] DebugGetNesHeader()
329 		{
330 			byte[] header = new byte[16];
331 			GCHandle handle = GCHandle.Alloc(header, GCHandleType.Pinned);
332 			try {
333 				InteropEmu.DebugGetNesHeaderWrapper(handle.AddrOfPinnedObject());
334 			} finally {
335 				handle.Free();
336 			}
337 			return header;
338 		}
339 
DebugSaveRomToDiskWrapper([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool saveAsIps, IntPtr headerBuffer, CdlStripFlag cdlStripFlag)340 		[DllImport(DLLPath, EntryPoint = "DebugSaveRomToDisk")] public static extern void DebugSaveRomToDiskWrapper([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool saveAsIps, IntPtr headerBuffer, CdlStripFlag cdlStripFlag);
DebugSaveRomToDisk(string filename, bool saveAsIps = false, byte[] header = null, CdlStripFlag cdlStripFlag = CdlStripFlag.StripNone)341 		public static void DebugSaveRomToDisk(string filename, bool saveAsIps = false, byte[] header = null, CdlStripFlag cdlStripFlag = CdlStripFlag.StripNone)
342 		{
343 			if(header != null) {
344 				GCHandle handle = GCHandle.Alloc(header, GCHandleType.Pinned);
345 				try {
346 					InteropEmu.DebugSaveRomToDiskWrapper(filename, saveAsIps, handle.AddrOfPinnedObject(), cdlStripFlag);
347 				} finally {
348 					handle.Free();
349 				}
350 			} else {
351 				InteropEmu.DebugSaveRomToDiskWrapper(filename, saveAsIps, IntPtr.Zero, cdlStripFlag);
352 			}
353 		}
354 
DebugGetCodeWrapper(ref UInt32 length)355 		[DllImport(DLLPath, EntryPoint = "DebugGetCode")] private static extern IntPtr DebugGetCodeWrapper(ref UInt32 length);
DebugGetCode(bool forceRefresh)356 		public static string DebugGetCode(bool forceRefresh)
357 		{
358 			UInt32 length = forceRefresh ? UInt32.MaxValue : 0;
359 			IntPtr ptrCodeString = InteropEmu.DebugGetCodeWrapper(ref length);
360 			if(ptrCodeString == IntPtr.Zero) {
361 				return null;
362 			} else {
363 				return PtrToStringUtf8(ptrCodeString, length);
364 			}
365 		}
366 
DebugAssembleCodeWrapper([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string code, UInt16 startAddress, IntPtr assembledCodeBuffer)367 		[DllImport(DLLPath, EntryPoint = "DebugAssembleCode")] private static extern UInt32 DebugAssembleCodeWrapper([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string code, UInt16 startAddress, IntPtr assembledCodeBuffer);
DebugAssembleCode(string code, UInt16 startAddress)368 		public static Int16[] DebugAssembleCode(string code, UInt16 startAddress)
369 		{
370 			code = code.Replace(Environment.NewLine, "\n");
371 			int lineCount = code.Count(c => c == '\n');
372 
373 			Int16[] assembledCode = new Int16[(lineCount + 1) * 4];
374 			UInt32 size = 0;
375 
376 			GCHandle hAssembledCode = GCHandle.Alloc(assembledCode, GCHandleType.Pinned);
377 			try {
378 				size = InteropEmu.DebugAssembleCodeWrapper(code, startAddress, hAssembledCode.AddrOfPinnedObject());
379 			} finally {
380 				hAssembledCode.Free();
381 			}
382 
383 			Array.Resize(ref assembledCode, (int)size);
384 			return assembledCode;
385 		}
386 
DebugGetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer)387 		[DllImport(DLLPath, EntryPoint = "DebugGetMemoryState")] private static extern UInt32 DebugGetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer);
DebugGetMemoryState(DebugMemoryType type)388 		public static byte[] DebugGetMemoryState(DebugMemoryType type)
389 		{
390 			byte[] buffer = new byte[InteropEmu.DebugGetMemorySize(type)];
391 			GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
392 			try {
393 				UInt32 memorySize = InteropEmu.DebugGetMemoryStateWrapper(type, handle.AddrOfPinnedObject());
394 				Array.Resize(ref buffer, (int)memorySize);
395 			} finally {
396 				handle.Free();
397 			}
398 			return buffer;
399 		}
400 
DebugSetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer, Int32 length)401 		[DllImport(DLLPath, EntryPoint = "DebugSetMemoryState")] private static extern void DebugSetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer, Int32 length);
DebugSetMemoryState(DebugMemoryType type, byte[] data)402 		public static void DebugSetMemoryState(DebugMemoryType type, byte[] data)
403 		{
404 			GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
405 			try {
406 				InteropEmu.DebugSetMemoryStateWrapper(type, handle.AddrOfPinnedObject(), data.Length);
407 			} finally {
408 				handle.Free();
409 			}
410 		}
411 
DebugGetInternalRam()412 		public static byte[] DebugGetInternalRam()
413 		{
414 			byte[] buffer = new byte[0x800];
415 			GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
416 			try {
417 				UInt32 memorySize = InteropEmu.DebugGetMemoryStateWrapper(DebugMemoryType.InternalRam, handle.AddrOfPinnedObject());
418 				Array.Resize(ref buffer, (int)memorySize);
419 			} finally {
420 				handle.Free();
421 			}
422 			return buffer;
423 		}
424 
DebugGetNametableWrapper(UInt32 nametableIndex, NametableDisplayMode mode, IntPtr frameBuffer, IntPtr tileData, IntPtr attributeData)425 		[DllImport(DLLPath, EntryPoint = "DebugGetNametable")] private static extern void DebugGetNametableWrapper(UInt32 nametableIndex, NametableDisplayMode mode, IntPtr frameBuffer, IntPtr tileData, IntPtr attributeData);
DebugGetNametable(int nametableIndex, NametableDisplayMode mode, out byte[] frameData, out byte[] tileData, out byte[] attributeData)426 		public static void DebugGetNametable(int nametableIndex, NametableDisplayMode mode, out byte[] frameData, out byte[] tileData, out byte[] attributeData)
427 		{
428 			frameData = new byte[256*240*4];
429 			tileData = new byte[32*30];
430 			attributeData = new byte[32*30];
431 
432 			GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
433 			GCHandle hTileData = GCHandle.Alloc(tileData, GCHandleType.Pinned);
434 			GCHandle hAttributeData = GCHandle.Alloc(attributeData, GCHandleType.Pinned);
435 			try {
436 				InteropEmu.DebugGetNametableWrapper((UInt32)nametableIndex, mode, hFrameData.AddrOfPinnedObject(), hTileData.AddrOfPinnedObject(), hAttributeData.AddrOfPinnedObject());
437 			} finally {
438 				hFrameData.Free();
439 				hTileData.Free();
440 				hAttributeData.Free();
441 			}
442 		}
443 
DebugGetChrBankWrapper(UInt32 bankIndex, IntPtr frameBuffer, Byte palette, [MarshalAs(UnmanagedType.I1)]bool largeSprites, CdlHighlightType highlightType, [MarshalAs(UnmanagedType.I1)]bool useAutoPalette, [MarshalAs(UnmanagedType.I1)]bool showSingleColorTilesInGrayscale, IntPtr paletteBuffer)444 		[DllImport(DLLPath, EntryPoint = "DebugGetChrBank")] private static extern void DebugGetChrBankWrapper(UInt32 bankIndex, IntPtr frameBuffer, Byte palette, [MarshalAs(UnmanagedType.I1)]bool largeSprites, CdlHighlightType highlightType, [MarshalAs(UnmanagedType.I1)]bool useAutoPalette, [MarshalAs(UnmanagedType.I1)]bool showSingleColorTilesInGrayscale, IntPtr paletteBuffer);
DebugGetChrBank(int bankIndex, int palette, bool largeSprites, CdlHighlightType highlightType, bool useAutoPalette, bool showSingleColorTilesInGrayscale, out UInt32[] paletteData)445 		public static byte[] DebugGetChrBank(int bankIndex, int palette, bool largeSprites, CdlHighlightType highlightType, bool useAutoPalette, bool showSingleColorTilesInGrayscale, out UInt32[] paletteData)
446 		{
447 			byte[] frameData = new byte[128*128*4];
448 			paletteData = new UInt32[16*16];
449 
450 			GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
451 			GCHandle hPaletteData = GCHandle.Alloc(paletteData, GCHandleType.Pinned);
452 			try {
453 				InteropEmu.DebugGetChrBankWrapper((UInt32)bankIndex, hFrameData.AddrOfPinnedObject(), (Byte)palette, largeSprites, highlightType, useAutoPalette, showSingleColorTilesInGrayscale, hPaletteData.AddrOfPinnedObject());
454 			} finally {
455 				hFrameData.Free();
456 				hPaletteData.Free();
457 			}
458 
459 			return frameData;
460 		}
461 
DebugGetSpritesWrapper(IntPtr frameBuffer)462 		[DllImport(DLLPath, EntryPoint = "DebugGetSprites")] private static extern void DebugGetSpritesWrapper(IntPtr frameBuffer);
DebugGetSprites()463 		public static byte[] DebugGetSprites()
464 		{
465 			byte[] frameData = new byte[64*128*4];
466 
467 			GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
468 			try {
469 				InteropEmu.DebugGetSpritesWrapper(hFrameData.AddrOfPinnedObject());
470 			} finally {
471 				hFrameData.Free();
472 			}
473 
474 			return frameData;
475 		}
476 
DebugGetPaletteWrapper(IntPtr frameBuffer)477 		[DllImport(DLLPath, EntryPoint = "DebugGetPalette")] private static extern void DebugGetPaletteWrapper(IntPtr frameBuffer);
DebugGetPalette()478 		public static int[] DebugGetPalette()
479 		{
480 			int[] frameData = new int[4*8];
481 
482 			GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
483 			try {
484 				InteropEmu.DebugGetPaletteWrapper(hFrameData.AddrOfPinnedObject());
485 			} finally {
486 				hFrameData.Free();
487 			}
488 
489 			return frameData;
490 		}
491 
DebugGetDebugEventCount([MarshalAs(UnmanagedType.I1)]bool returnPreviousFrameData)492 		[DllImport(DLLPath)] private static extern UInt32 DebugGetDebugEventCount([MarshalAs(UnmanagedType.I1)]bool returnPreviousFrameData);
DebugGetDebugEventsWrapper(IntPtr frameBuffer, IntPtr infoArray, ref UInt32 maxEventCount, [MarshalAs(UnmanagedType.I1)]bool returnPreviousFrameData)493 		[DllImport(DLLPath, EntryPoint = "DebugGetDebugEvents")] private static extern void DebugGetDebugEventsWrapper(IntPtr frameBuffer, IntPtr infoArray, ref UInt32 maxEventCount, [MarshalAs(UnmanagedType.I1)]bool returnPreviousFrameData);
DebugGetDebugEvents(bool returnPreviousFrameData, out byte[] pictureData, out DebugEventInfo[] debugEvents)494 		public static void DebugGetDebugEvents(bool returnPreviousFrameData, out byte[] pictureData, out DebugEventInfo[] debugEvents)
495 		{
496 			pictureData = new byte[256 * 240 * 4];
497 			UInt32 maxEventCount = DebugGetDebugEventCount(returnPreviousFrameData);
498 			debugEvents = new DebugEventInfo[maxEventCount];
499 
500 			GCHandle hPictureData = GCHandle.Alloc(pictureData, GCHandleType.Pinned);
501 			GCHandle hDebugEvents = GCHandle.Alloc(debugEvents, GCHandleType.Pinned);
502 			try {
503 				InteropEmu.DebugGetDebugEventsWrapper(hPictureData.AddrOfPinnedObject(), hDebugEvents.AddrOfPinnedObject(), ref maxEventCount, returnPreviousFrameData);
504 			} finally {
505 				hPictureData.Free();
506 				hDebugEvents.Free();
507 			}
508 
509 			if(maxEventCount < debugEvents.Length) {
510 				//Remove the excess from the array if needed
511 				Array.Resize(ref debugEvents, (int)maxEventCount);
512 			}
513 		}
514 
DebugGetProfilerDataWrapper(IntPtr profilerData, ProfilerDataType dataType)515 		[DllImport(DLLPath, EntryPoint = "DebugGetProfilerData")] private static extern void DebugGetProfilerDataWrapper(IntPtr profilerData, ProfilerDataType dataType);
DebugGetProfilerData(ProfilerDataType dataType)516 		public static Int64[] DebugGetProfilerData(ProfilerDataType dataType)
517 		{
518 			Int64[] profileData = new Int64[InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom) + 2];
519 
520 			GCHandle hProfilerData = GCHandle.Alloc(profileData, GCHandleType.Pinned);
521 			try {
522 				InteropEmu.DebugGetProfilerDataWrapper(hProfilerData.AddrOfPinnedObject(), dataType);
523 			} finally {
524 				hProfilerData.Free();
525 			}
526 
527 			return profileData;
528 		}
529 
DebugGetMemoryAccessCounts(DebugMemoryType type, MemoryOperationType operationType)530 		public static Int32[] DebugGetMemoryAccessCounts(DebugMemoryType type, MemoryOperationType operationType)
531 		{
532 			int size = InteropEmu.DebugGetMemorySize(type);
533 			return InteropEmu.DebugGetMemoryAccessCounts(0, (uint)size, type, operationType);
534 		}
535 
DebugGetMemoryAccessStamps(DebugMemoryType type, MemoryOperationType operationType)536 		public static UInt64[] DebugGetMemoryAccessStamps(DebugMemoryType type, MemoryOperationType operationType)
537 		{
538 			int size = InteropEmu.DebugGetMemorySize(type);
539 			return InteropEmu.DebugGetMemoryAccessStamps(0, (uint)size, type, operationType);
540 		}
541 
DebugGetUninitMemoryReadsWrapper(DebugMemoryType type, IntPtr counts)542 		[DllImport(DLLPath, EntryPoint = "DebugGetUninitMemoryReads")] private static extern void DebugGetUninitMemoryReadsWrapper(DebugMemoryType type, IntPtr counts);
DebugGetUninitMemoryReads(DebugMemoryType type)543 		public static Int32[] DebugGetUninitMemoryReads(DebugMemoryType type)
544 		{
545 			int size = InteropEmu.DebugGetMemorySize(type);
546 			if(type == DebugMemoryType.InternalRam) {
547 				size = 0x2000;
548 			}
549 
550 			Int32[] counts = new Int32[size];
551 
552 			if(size > 0) {
553 				GCHandle hCounts = GCHandle.Alloc(counts, GCHandleType.Pinned);
554 				try {
555 					InteropEmu.DebugGetUninitMemoryReadsWrapper(type, hCounts.AddrOfPinnedObject());
556 				} finally {
557 					hCounts.Free();
558 				}
559 			}
560 
561 			return counts;
562 		}
563 
DebugGetMemoryAccessStampsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr stamps)564 		[DllImport(DLLPath, EntryPoint = "DebugGetMemoryAccessStamps")] private static extern void DebugGetMemoryAccessStampsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr stamps);
DebugGetMemoryAccessStamps(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType)565 		public static UInt64[] DebugGetMemoryAccessStamps(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType)
566 		{
567 			UInt64[] stamps = new UInt64[length];
568 
569 			GCHandle hStamps = GCHandle.Alloc(stamps, GCHandleType.Pinned);
570 			try {
571 				InteropEmu.DebugGetMemoryAccessStampsWrapper(offset, length, type, operationType, hStamps.AddrOfPinnedObject());
572 			} finally {
573 				hStamps.Free();
574 			}
575 
576 			return stamps;
577 		}
578 
DebugGetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr counts)579 		[DllImport(DLLPath, EntryPoint = "DebugGetMemoryAccessCounts")] private static extern void DebugGetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr counts);
DebugGetMemoryAccessCounts(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType)580 		public static Int32[] DebugGetMemoryAccessCounts(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType)
581 		{
582 			Int32[] counts = new Int32[length];
583 
584 			GCHandle hResult = GCHandle.Alloc(counts, GCHandleType.Pinned);
585 			try {
586 				InteropEmu.DebugGetMemoryAccessCountsWrapper(offset, length, type, operationType, hResult.AddrOfPinnedObject());
587 			} finally {
588 				hResult.Free();
589 			}
590 
591 			return counts;
592 		}
593 
DebugGetNametableChangedDataWrapper(IntPtr ntChangedData)594 		[DllImport(DLLPath, EntryPoint = "DebugGetNametableChangedData")] private static extern void DebugGetNametableChangedDataWrapper(IntPtr ntChangedData);
DebugGetNametableChangedData()595 		public static bool[] DebugGetNametableChangedData()
596 		{
597 			bool[] ntChangedData = new bool[0x1000];
598 
599 			GCHandle hNtChangedData = GCHandle.Alloc(ntChangedData, GCHandleType.Pinned);
600 			try {
601 				InteropEmu.DebugGetNametableChangedDataWrapper(hNtChangedData.AddrOfPinnedObject());
602 			} finally {
603 				hNtChangedData.Free();
604 			}
605 
606 			return ntChangedData;
607 		}
608 
DebugGetFreezeStateWrapper(UInt16 startAddress, UInt16 length, IntPtr freezeState)609 		[DllImport(DLLPath, EntryPoint = "DebugGetFreezeState")] private static extern void DebugGetFreezeStateWrapper(UInt16 startAddress, UInt16 length, IntPtr freezeState);
DebugGetFreezeState(UInt16 startAddress, UInt16 length)610 		public static bool[] DebugGetFreezeState(UInt16 startAddress, UInt16 length)
611 		{
612 			bool[] freezeState = new bool[length];
613 
614 			GCHandle hFreezeState = GCHandle.Alloc(freezeState, GCHandleType.Pinned);
615 			try {
616 				InteropEmu.DebugGetFreezeStateWrapper(startAddress, length, hFreezeState.AddrOfPinnedObject());
617 			} finally {
618 				hFreezeState.Free();
619 			}
620 
621 			return freezeState;
622 		}
623 
DebugSetCdlDataWrapper(IntPtr cdlData, UInt32 length)624 		[DllImport(DLLPath, EntryPoint = "DebugSetCdlData")] private static extern void DebugSetCdlDataWrapper(IntPtr cdlData, UInt32 length);
DebugSetCdlData(byte[] cdlData)625 		public static void DebugSetCdlData(byte[] cdlData)
626 		{
627 			GCHandle hResult = GCHandle.Alloc(cdlData, GCHandleType.Pinned);
628 			try {
629 				InteropEmu.DebugSetCdlDataWrapper(hResult.AddrOfPinnedObject(), (UInt32)cdlData.Length);
630 			} finally {
631 				hResult.Free();
632 			}
633 		}
634 
DebugGetCdlDataWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, IntPtr counts)635 		[DllImport(DLLPath, EntryPoint = "DebugGetCdlData")] private static extern void DebugGetCdlDataWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, IntPtr counts);
636 
DebugGetPrgCdlData()637 		public static byte[] DebugGetPrgCdlData()
638 		{
639 			return DebugGetCdlData(0, (uint)InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom), DebugMemoryType.PrgRom);
640 		}
641 
DebugGetCdlData(UInt32 offset, UInt32 length, DebugMemoryType type)642 		public static byte[] DebugGetCdlData(UInt32 offset, UInt32 length, DebugMemoryType type)
643 		{
644 			byte[] cdlData = new byte[length];
645 
646 			GCHandle hResult = GCHandle.Alloc(cdlData, GCHandleType.Pinned);
647 			try {
648 				InteropEmu.DebugGetCdlDataWrapper(offset, length, type, hResult.AddrOfPinnedObject());
649 			} finally {
650 				hResult.Free();
651 			}
652 
653 			return cdlData;
654 		}
655 
DebugGetCallstackWrapper(IntPtr callstackArray, ref UInt32 callstackSize)656 		[DllImport(DLLPath, EntryPoint = "DebugGetCallstack")] private static extern void DebugGetCallstackWrapper(IntPtr callstackArray, ref UInt32 callstackSize);
DebugGetCallstack()657 		public static StackFrameInfo[] DebugGetCallstack()
658 		{
659 			StackFrameInfo[] callstack = new StackFrameInfo[512];
660 			UInt32 callstackSize = 0;
661 
662 			GCHandle hCallstack = GCHandle.Alloc(callstack, GCHandleType.Pinned);
663 			try {
664 				InteropEmu.DebugGetCallstackWrapper(hCallstack.AddrOfPinnedObject(), ref callstackSize);
665 			} finally {
666 				hCallstack.Free();
667 			}
668 			Array.Resize(ref callstack, (int)callstackSize);
669 
670 			return callstack;
671 		}
672 
DebugGetFunctionEntryPointCount()673 		[DllImport(DLLPath)] private static extern Int32 DebugGetFunctionEntryPointCount();
DebugGetFunctionEntryPointsWrapper(IntPtr callstackAbsolute, Int32 maxCount)674 		[DllImport(DLLPath, EntryPoint = "DebugGetFunctionEntryPoints")] private static extern void DebugGetFunctionEntryPointsWrapper(IntPtr callstackAbsolute, Int32 maxCount);
DebugGetFunctionEntryPoints()675 		public static Int32[] DebugGetFunctionEntryPoints()
676 		{
677 			int maxCount = DebugGetFunctionEntryPointCount();
678 			Int32[] entryPoints = new Int32[maxCount+1];
679 
680 			GCHandle hEntryPoints = GCHandle.Alloc(entryPoints, GCHandleType.Pinned);
681 			try {
682 				InteropEmu.DebugGetFunctionEntryPointsWrapper(hEntryPoints.AddrOfPinnedObject(), maxCount+1);
683 			} finally {
684 				hEntryPoints.Free();
685 			}
686 
687 			return entryPoints;
688 		}
689 
DebugGetPpuScrollWrapper()690 		[DllImport(DLLPath, EntryPoint = "DebugGetPpuScroll")] private static extern UInt32 DebugGetPpuScrollWrapper();
DebugGetPpuScroll(out int xScroll, out int yScroll)691 		public static void DebugGetPpuScroll(out int xScroll, out int yScroll)
692 		{
693 			UInt32 ppuScroll = InteropEmu.DebugGetPpuScrollWrapper();
694 			xScroll = (int)ppuScroll & 0xFFFF;
695 			yScroll = (int)(ppuScroll >> 16) & 0xFFFF;
696 		}
697 
IsHdPpu()698 		[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsHdPpu();
699 
HdBuilderStartRecording( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string saveFolder, ScaleFilterType filterType, UInt32 scale, HdPackRecordFlags flags, UInt32 chrRamBankSize)700 		[DllImport(DLLPath)] public static extern void HdBuilderStartRecording(
701 			[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string saveFolder,
702 			ScaleFilterType filterType,
703 			UInt32 scale,
704 			HdPackRecordFlags flags,
705 			UInt32 chrRamBankSize);
706 
HdBuilderStopRecording()707 		[DllImport(DLLPath)] public static extern void HdBuilderStopRecording();
708 
HdBuilderGetBankPreviewWrapper(UInt32 bankNumber, UInt32 pageNumber, IntPtr rgbBuffer)709 		[DllImport(DLLPath, EntryPoint = "HdBuilderGetBankPreview")] private static extern void HdBuilderGetBankPreviewWrapper(UInt32 bankNumber, UInt32 pageNumber, IntPtr rgbBuffer);
HdBuilderGetBankPreview(UInt32 bankNumber, int scale, UInt32 pageNumber)710 		public static byte[] HdBuilderGetBankPreview(UInt32 bankNumber, int scale, UInt32 pageNumber)
711 		{
712 			byte[] frameData = new byte[128*128*4*scale*scale];
713 
714 			GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
715 			try {
716 				InteropEmu.HdBuilderGetBankPreviewWrapper(bankNumber, pageNumber, hFrameData.AddrOfPinnedObject());
717 			} finally {
718 				hFrameData.Free();
719 			}
720 
721 			return frameData;
722 		}
723 
HdBuilderGetChrBankListWrapper(IntPtr bankList)724 		[DllImport(DLLPath, EntryPoint = "HdBuilderGetChrBankList")] private static extern void HdBuilderGetChrBankListWrapper(IntPtr bankList);
HdBuilderGetChrBankList()725 		public static UInt32[] HdBuilderGetChrBankList()
726 		{
727 			UInt32[] bankList = new UInt32[1024];
728 			GCHandle hBankList = GCHandle.Alloc(bankList, GCHandleType.Pinned);
729 			try {
730 				InteropEmu.HdBuilderGetChrBankListWrapper(hBankList.AddrOfPinnedObject());
731 				for(int i = 0; i < bankList.Length; i++) {
732 					if(bankList[i] == UInt32.MaxValue) {
733 						Array.Resize(ref bankList, i);
734 						break;
735 					}
736 				}
737 			} finally {
738 				hBankList.Free();
739 			}
740 
741 			return bankList;
742 		}
743 
GetPressedKeys()744 		public static List<UInt32> GetPressedKeys()
745 		{
746 			UInt32[] keyBuffer = new UInt32[3];
747 			GCHandle handle = GCHandle.Alloc(keyBuffer, GCHandleType.Pinned);
748 			try {
749 				InteropEmu.GetPressedKeysWrapper(handle.AddrOfPinnedObject());
750 			} finally {
751 				handle.Free();
752 			}
753 
754 			List<UInt32> keys = new List<UInt32>();
755 			for(int i = 0; i < 3; i++) {
756 				if(keyBuffer[i] != 0) {
757 					keys.Add(keyBuffer[i]);
758 				}
759 			}
760 			return keys;
761 		}
762 
NsfGetHeader()763 		public static NsfHeader NsfGetHeader()
764 		{
765 			NsfHeader header = new NsfHeader();
766 			NsfGetHeaderWrapper(out header);
767 			return header;
768 		}
769 
GetRomInfo(string filename = R)770 		public static RomInfo GetRomInfo(string filename = "")
771 		{
772 			InteropRomInfo romInfo = new InteropRomInfo();
773 			romInfo.Sha1 = new byte[40];
774 			InteropEmu.GetRomInfoWrapper(ref romInfo, filename);
775 			return new RomInfo(romInfo);
776 		}
777 
GetScreenSize(bool ignoreScale, ConsoleId consoleId = ConsoleId.Master)778 		public static ScreenSize GetScreenSize(bool ignoreScale, ConsoleId consoleId = ConsoleId.Master)
779 		{
780 			ScreenSize size;
781 			GetScreenSizeWrapper(consoleId, out size, ignoreScale);
782 			return size;
783 		}
784 
HistoryViewerGetSegments()785 		public static UInt32[] HistoryViewerGetSegments()
786 		{
787 			UInt32[] segmentBuffer = new UInt32[InteropEmu.HistoryViewerGetHistoryLength() / 30];
788 			UInt32 bufferSize = (UInt32)segmentBuffer.Length;
789 
790 			GCHandle hSegmentBuffer = GCHandle.Alloc(segmentBuffer, GCHandleType.Pinned);
791 			try {
792 				InteropEmu.HistoryViewerGetSegmentsWrapper(hSegmentBuffer.AddrOfPinnedObject(), ref bufferSize);
793 			} finally {
794 				hSegmentBuffer.Free();
795 			}
796 			Array.Resize(ref segmentBuffer, (int)bufferSize);
797 
798 			return segmentBuffer;
799 		}
800 
SetFlag(EmulationFlags flag, bool value)801 		public static void SetFlag(EmulationFlags flag, bool value)
802 		{
803 			if(value) {
804 				InteropEmu.SetFlags(flag);
805 			} else {
806 				InteropEmu.ClearFlags(flag);
807 			}
808 		}
809 
GetMesenVersion()810 		public static string GetMesenVersion()
811 		{
812 			UInt32 version = GetMesenVersionWrapper();
813 			UInt32 revision = version & 0xFF;
814 			UInt32 minor = (version >> 8) & 0xFF;
815 			UInt32 major = (version >> 16) & 0xFFFF;
816 			return string.Format("{0}.{1}.{2}", major.ToString(), minor.ToString(), revision.ToString());
817 		}
818 
GetRgbPalette()819 		public static Int32[] GetRgbPalette()
820 		{
821 			Int32[] paleteData = new Int32[512];
822 
823 			GCHandle hPaletteData = GCHandle.Alloc(paleteData, GCHandleType.Pinned);
824 			try {
825 				InteropEmu.GetRgbPaletteWrapper(hPaletteData.AddrOfPinnedObject());
826 			} finally {
827 				hPaletteData.Free();
828 			}
829 
830 			return paleteData;
831 		}
832 
GetLog()833 		public static string GetLog() { return PtrToStringUtf8(InteropEmu.GetLogWrapper()).Replace("\n", Environment.NewLine); }
GetKeyName(UInt32 key)834 		public static string GetKeyName(UInt32 key) { return PtrToStringUtf8(InteropEmu.GetKeyNameWrapper(key)); }
GetAudioDevices()835 		public static List<string> GetAudioDevices()
836 		{
837 			return new List<string>(PtrToStringUtf8(InteropEmu.GetAudioDevicesWrapper()).Split(new string[1] { "||" }, StringSplitOptions.RemoveEmptyEntries));
838 		}
839 
840 		public class ArchiveRomEntry
841 		{
842 			public string Filename;
843 			public bool IsUtf8;
844 
ToString()845 			public override string ToString()
846 			{
847 				return Filename;
848 			}
849 		}
850 
GetArchiveRomList(string filename)851 		public static List<ArchiveRomEntry> GetArchiveRomList(string filename)
852 		{
853 			//Split the array on the [!|!] delimiter
854 			byte[] buffer = PtrToByteArray(InteropEmu.GetArchiveRomListWrapper(filename));
855 			List<List<byte>> filenames = new List<List<byte>>();
856 			List<byte> filenameBytes = new List<byte>();
857 			for(int i = 0; i < buffer.Length - 5; i++) {
858 				if(buffer[i] == '[' && buffer[i+1] == '!' && buffer[i+2] == '|' && buffer[i+3] == '!' && buffer[i+4] == ']') {
859 					if(filenameBytes.Count > 0) {
860 						filenames.Add(filenameBytes);
861 					}
862 					filenameBytes = new List<byte>();
863 					i+=4;
864 				} else {
865 					filenameBytes.Add(buffer[i]);
866 				}
867 			}
868 			if(filenameBytes.Count > 0) {
869 				filenames.Add(filenameBytes);
870 			}
871 
872 			List<ArchiveRomEntry> entries = new List<ArchiveRomEntry>();
873 
874 			//Check whether or not each string is a valid utf8 filename, if not decode it using the system's default encoding.
875 			//This is necessary because zip files do not have any rules when it comes to encoding filenames
876 			for(int i = 0; i < filenames.Count; i++) {
877 				byte[] originalBytes = filenames[i].ToArray();
878 				string utf8Filename = Encoding.UTF8.GetString(originalBytes);
879 				byte[] convertedBytes = Encoding.UTF8.GetBytes(utf8Filename);
880 				bool equal = true;
881 				if(originalBytes.Length == convertedBytes.Length) {
882 					for(int j = 0; j < convertedBytes.Length; j++) {
883 						if(convertedBytes[j] != originalBytes[j]) {
884 							equal = false;
885 							break;
886 						}
887 					}
888 				} else {
889 					equal = false;
890 				}
891 
892 				if(!equal) {
893 					//String doesn't appear to be an utf8 string, use the system's default encoding
894 					entries.Add(new ArchiveRomEntry() { Filename = Encoding.Default.GetString(originalBytes), IsUtf8 = false });
895 				} else {
896 					entries.Add(new ArchiveRomEntry() { Filename = utf8Filename, IsUtf8 = true });
897 				}
898 			}
899 
900 			return entries;
901 		}
902 
903 		private static byte[] _codeByteArray = new byte[0];
PtrToStringUtf8(IntPtr ptr, UInt32 length = 0)904 		private static string PtrToStringUtf8(IntPtr ptr, UInt32 length = 0)
905 		{
906 			if(ptr == IntPtr.Zero) {
907 				return "";
908 			}
909 
910 			int len = 0;
911 			if(length == 0) {
912 				while(System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0) {
913 					len++;
914 				}
915 			} else {
916 				len = (int)length;
917 			}
918 
919 			if(len == 0) {
920 				return "";
921 			}
922 
923 			if(length == 0) {
924 				byte[] array = new byte[len];
925 				System.Runtime.InteropServices.Marshal.Copy(ptr, array, 0, len);
926 				return System.Text.Encoding.UTF8.GetString(array);
927 			} else {
928 				//For the code window, reuse the same buffer to reduce allocations
929 				if(_codeByteArray.Length < len) {
930 					Array.Resize(ref _codeByteArray, len);
931 				}
932 				System.Runtime.InteropServices.Marshal.Copy(ptr, _codeByteArray, 0, len);
933 				return System.Text.Encoding.UTF8.GetString(_codeByteArray, 0, len);
934 			}
935 		}
936 
PtrToByteArray(IntPtr ptr)937 		private static byte[] PtrToByteArray(IntPtr ptr)
938 		{
939 			if(ptr == IntPtr.Zero) {
940 				return new byte[0];
941 			}
942 
943 			int len = 0;
944 			while(System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0) {
945 				len++;
946 			}
947 
948 			byte[] array = new byte[len];
949 			System.Runtime.InteropServices.Marshal.Copy(ptr, array, 0, len);
950 
951 			return array;
952 		}
953 
954 		public enum ConsoleNotificationType
955 		{
956 			GameLoaded = 0,
957 			StateLoaded = 1,
958 			GameReset = 2,
959 			GamePaused = 3,
960 			GameResumed = 4,
961 			GameStopped = 5,
962 			CodeBreak = 6,
963 			CheatAdded = 7,
964 			CheatRemoved = 8,
965 			PpuFrameDone = 9,
966 			MovieEnded = 10,
967 			ResolutionChanged = 11,
968 			FdsBiosNotFound = 12,
969 			ConfigChanged = 13,
970 			DisconnectedFromServer = 14,
971 			PpuViewerDisplayFrame = 15,
972 			ExecuteShortcut = 16,
973 			EmulationStopped = 17,
974 			EventViewerDisplayFrame = 18,
975 			BeforeEmulationStop = 19,
976 			VsDualSystemStarted = 20,
977 			VsDualSystemStopped = 21,
978 		}
979 
980 		public enum ControllerType
981 		{
982 			None = 0,
983 			StandardController = 1,
984 			Zapper = 2,
985 			ArkanoidController = 3,
986 			SnesController = 4,
987 			PowerPad = 5,
988 			SnesMouse = 6,
989 			SuborMouse = 7,
990 		}
991 
992 		public enum ExpansionPortDevice
993 		{
994 			None = 0,
995 			Zapper = 1,
996 			FourPlayerAdapter = 2,
997 			ArkanoidController = 3,
998 			OekaKidsTablet = 4,
999 			FamilyTrainerMat = 5,
1000 			KonamiHyperShot = 6,
1001 			FamilyBasicKeyboard = 7,
1002 			PartyTap = 8,
1003 			Pachinko = 9,
1004 			ExcitingBoxing = 10,
1005 			JissenMahjong = 11,
1006 			SuborKeyboard = 12,
1007 			BarcodeBattler = 13,
1008 			HoriTrack = 14,
1009 			BandaiHyperShot = 15,
1010 			AsciiTurboFile = 16,
1011 			BattleBox = 17,
1012 		}
1013 
1014 		public enum MouseDevice
1015 		{
1016 			Unknown = 0,
1017 			SnesMouse,
1018 			SuborMouse,
1019 			ArkanoidController,
1020 			HoriTrack
1021 		}
1022 
1023 		public enum VsInputType
1024 		{
1025 			Default = 0,
1026 			SwapControllers = 1,
1027 			SwapAB = 2
1028 		}
1029 
1030 		public enum PpuModel
1031 		{
1032 			Ppu2C02 = 0,
1033 			Ppu2C03 = 1,
1034 			Ppu2C04A = 2,
1035 			Ppu2C04B = 3,
1036 			Ppu2C04C = 4,
1037 			Ppu2C04D = 5,
1038 			Ppu2C05A = 6,
1039 			Ppu2C05B = 7,
1040 			Ppu2C05C = 8,
1041 			Ppu2C05D = 9,
1042 			Ppu2C05E = 10,
1043 		}
1044 
1045 		public struct KeyMappingSet
1046 		{
1047 			public KeyMapping Mapping1;
1048 			public KeyMapping Mapping2;
1049 			public KeyMapping Mapping3;
1050 			public KeyMapping Mapping4;
1051 			public UInt32 TurboSpeed;
1052 
1053 			[MarshalAs(UnmanagedType.I1)]
1054 			public bool PowerpadUseSideA;
1055 		}
1056 
1057 		public struct KeyMapping
1058 		{
1059 			public UInt32 A;
1060 			public UInt32 B;
1061 			public UInt32 Up;
1062 			public UInt32 Down;
1063 			public UInt32 Left;
1064 			public UInt32 Right;
1065 			public UInt32 Start;
1066 			public UInt32 Select;
1067 			public UInt32 TurboA;
1068 			public UInt32 TurboB;
1069 			public UInt32 TurboStart;
1070 			public UInt32 TurboSelect;
1071 			public UInt32 Microphone;
1072 			public UInt32 LButton;
1073 			public UInt32 RButton;
1074 
1075 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
1076 			public UInt32[] PowerPadButtons;
1077 
1078 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 72)]
1079 			public UInt32[] FamilyBasicKeyboardButtons;
1080 
1081 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
1082 			public UInt32[] PartyTapButtons;
1083 
1084 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
1085 			public UInt32[] PachinkoButtons;
1086 
1087 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
1088 			public UInt32[] ExcitingBoxingButtons;
1089 
1090 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)]
1091 			public UInt32[] JissenMahjongButtons;
1092 
1093 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 99)]
1094 			public UInt32[] SuborKeyboardButtons;
1095 
1096 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
1097 			public UInt32[] BandaiMicrophoneButtons;
1098 		}
1099 
1100 		public enum StereoFilter
1101 		{
1102 			None = 0,
1103 			Delay = 1,
1104 			Panning = 2,
1105 			CombFilter = 3,
1106 		}
1107 
1108 		public struct AudioFilterSettings
1109 		{
1110 			public StereoFilter Filter;
1111 			public double Angle;
1112 			public Int32 Delay;
1113 			public Int32 Strength;
1114 
1115 			public double ReverbDelay;
1116 			public double ReverbStrength;
1117 
1118 			public Int32 CrossFeedRatio;
1119 		}
1120 
1121 		public struct ScreenSize
1122 		{
1123 			public Int32 Width;
1124 			public Int32 Height;
1125 			public double Scale;
1126 		}
1127 
1128 		public enum InputDisplayPosition
1129 		{
1130 			TopLeft = 0,
1131 			TopRight = 1,
1132 			BottomLeft = 2,
1133 			BottomRight = 3
1134 		}
1135 
1136 		public class NotificationEventArgs
1137 		{
1138 			public ConsoleNotificationType NotificationType;
1139 			public IntPtr Parameter;
1140 		}
1141 
1142 		public enum ConsoleId
1143 		{
1144 			Master = 0,
1145 			Slave = 1,
1146 			HistoryViewer = 2
1147 		}
1148 
1149 		public class NotificationListener : IDisposable
1150 		{
NotificationCallback(int type, IntPtr parameter)1151 			public delegate void NotificationCallback(int type, IntPtr parameter);
NotificationEventHandler(NotificationEventArgs e)1152 			public delegate void NotificationEventHandler(NotificationEventArgs e);
1153 			public event NotificationEventHandler OnNotification;
1154 
1155 			//Need to keep a reference to this callback, or it will get garbage collected (since the only reference to it is on the native side)
1156 			NotificationCallback _callback;
1157 			IntPtr _notificationListener;
1158 
NotificationListener(ConsoleId consoleId)1159 			public NotificationListener(ConsoleId consoleId)
1160 			{
1161 				_callback = (int type, IntPtr parameter) => {
1162 					this.ProcessNotification(type, parameter);
1163 				};
1164 				_notificationListener = InteropEmu.RegisterNotificationCallback(consoleId, _callback);
1165 			}
1166 
Dispose()1167 			public void Dispose()
1168 			{
1169 				InteropEmu.UnregisterNotificationCallback(_notificationListener);
1170 			}
1171 
ProcessNotification(int type, IntPtr parameter)1172 			public void ProcessNotification(int type, IntPtr parameter)
1173 			{
1174 				if(this.OnNotification != null) {
1175 					this.OnNotification(new NotificationEventArgs() {
1176 						NotificationType = (ConsoleNotificationType)type,
1177 						Parameter = parameter
1178 					});
1179 				}
1180 			}
1181 		}
1182 	}
1183 
1184 	public struct CdlRatios
1185 	{
1186 		public float CodeRatio;
1187 		public float DataRatio;
1188 		public float PrgRatio;
1189 
1190 		public float ChrRatio;
1191 		public float ChrReadRatio;
1192 		public float ChrDrawnRatio;
1193 	}
1194 
1195 	public enum CdlHighlightType
1196 	{
1197 		None = 0,
1198 		HighlightUsed = 1,
1199 		HighlightUnused = 2
1200 	}
1201 
1202 	public enum CdlStripFlag
1203 	{
1204 		StripNone = 0,
1205 		StripUnused = 1,
1206 		StripUsed = 2
1207 	}
1208 
1209 	public enum CdlPrgFlags
1210 	{
1211 		None = 0x00,
1212 		Code = 0x01,
1213 		Data = 0x02,
1214 
1215 		//Bit 0x10 is used for "indirectly accessed as code" in FCEUX
1216 		//Repurposed to mean the address is the target of a jump instruction
1217 		JumpTarget = 0x10,
1218 
1219 		IndirectData = 0x20,
1220 		PcmData = 0x40,
1221 
1222 		//Unused bit in original CDL spec
1223 		//Used to denote that the byte is the start of function (sub)
1224 		SubEntryPoint = 0x80
1225 	}
1226 
1227 	public enum DebugEventType : byte
1228 	{
1229 		None = 0,
1230 		PpuRegisterWrite,
1231 		PpuRegisterRead,
1232 		MapperRegisterWrite,
1233 		MapperRegisterRead,
1234 		Nmi,
1235 		Irq,
1236 		SpriteZeroHit,
1237 		Breakpoint
1238 	}
1239 
1240 	public struct DebugEventInfo
1241 	{
1242 		public UInt16 Cycle;
1243 		public Int16 Scanline;
1244 		public UInt16 ProgramCounter;
1245 		public UInt16 Address;
1246 		public Int16 BreakpointId;
1247 		public DebugEventType Type;
1248 		public byte Value;
1249 		public SByte PpuLatch;
1250 	}
1251 
1252 	public enum StackFrameFlags : byte
1253 	{
1254 		None = 0,
1255 		Nmi = 1,
1256 		Irq = 2
1257 	}
1258 
1259 	public enum PrgMemoryType
1260 	{
1261 		PrgRom,
1262 		SaveRam,
1263 		WorkRam,
1264 	}
1265 
1266 	public enum ChrMemoryType
1267 	{
1268 		Default,
1269 		ChrRom,
1270 		ChrRam,
1271 		NametableRam
1272 	}
1273 
1274 	public enum MemoryAccessType
1275 	{
1276 		Unspecified = -1,
1277 		NoAccess = 0x00,
1278 		Read = 0x01,
1279 		Write = 0x02,
1280 		ReadWrite = 0x03
1281 	}
1282 
1283 	public struct StackFrameInfo
1284 	{
1285 		public Int32 JumpSourceAbsolute;
1286 		public Int32 JumpTargetAbsolute;
1287 		public UInt16 JumpSource;
1288 		public UInt16 JumpTarget;
1289 		public StackFrameFlags Flags;
1290 	};
1291 
1292 	public struct InstructionProgress
1293 	{
1294 		public byte OpCode;
1295 		public UInt32 OpCycle;
1296 		public InteropMemoryOperationType OpMemoryOperationType;
1297 	}
1298 
1299 	public struct DebugState
1300 	{
1301 		public CPUState CPU;
1302 		public PPUDebugState PPU;
1303 		public CartridgeState Cartridge;
1304 		public ApuState APU;
1305 		public NesModel Model;
1306 		public UInt32 ClockRate;
1307 	}
1308 
1309 	public struct CartridgeState
1310 	{
1311 		public UInt32 PrgRomSize;
1312 		public UInt32 ChrRomSize;
1313 		public UInt32 ChrRamSize;
1314 
1315 		public UInt32 PrgPageCount;
1316 		public UInt32 PrgPageSize;
1317 
1318 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
1319 		public Int32[] PrgMemoryOffset;
1320 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
1321 		public PrgMemoryType[] PrgMemoryType;
1322 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
1323 		public MemoryAccessType[] PrgMemoryAccess;
1324 
1325 		public UInt32 ChrPageCount;
1326 		public UInt32 ChrPageSize;
1327 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x40)]
1328 		public Int32[] ChrMemoryOffset;
1329 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x40)]
1330 		public ChrMemoryType[] ChrMemoryType;
1331 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x40)]
1332 		public MemoryAccessType[] ChrMemoryAccess;
1333 
1334 		public UInt32 WorkRamPageSize;
1335 		public UInt32 SaveRamPageSize;
1336 
1337 		public MirroringType Mirroring;
1338 
1339 		[MarshalAs(UnmanagedType.I1)]
1340 		public bool HasBattery;
1341 	}
1342 
1343 	public enum MirroringType
1344 	{
1345 		Horizontal,
1346 		Vertical,
1347 		ScreenAOnly,
1348 		ScreenBOnly,
1349 		FourScreens
1350 	}
1351 
1352 	public struct PPUDebugState
1353 	{
1354 		public PPUControlFlags ControlFlags;
1355 		public PPUStatusFlags StatusFlags;
1356 		public PPUState State;
1357 		public Int32 Scanline;
1358 		public UInt32 Cycle;
1359 		public UInt32 FrameCount;
1360 		public UInt32 NmiScanline;
1361 		public UInt32 ScanlineCount;
1362 		public UInt32 SafeOamScanline;
1363 		public UInt16 BusAddress;
1364 		public byte MemoryReadBuffer;
1365 	}
1366 
1367 	public struct PPUState
1368 	{
1369 		public Byte Control;
1370 		public Byte Mask;
1371 		public Byte Status;
1372 		public UInt32 SpriteRamAddr;
1373 		public UInt16 VideoRamAddr;
1374 		public Byte XScroll;
1375 		public UInt16 TmpVideoRamAddr;
1376 
1377 		[MarshalAs(UnmanagedType.I1)]
1378 		public bool WriteToggle;
1379 
1380 		public UInt16 HighBitShift;
1381 		public UInt16 LowBitShift;
1382 	}
1383 
1384 	public struct PPUControlFlags
1385 	{
1386 		public Byte VerticalWrite;
1387 		public UInt16 SpritePatternAddr;
1388 		public UInt16 BackgroundPatternAddr;
1389 		public Byte LargeSprites;
1390 		public Byte VBlank;
1391 
1392 		public Byte Grayscale;
1393 		public Byte BackgroundMask;
1394 		public Byte SpriteMask;
1395 		public Byte BackgroundEnabled;
1396 		public Byte SpritesEnabled;
1397 		public Byte IntensifyRed;
1398 		public Byte IntensifyGreen;
1399 		public Byte IntensifyBlue;
1400 
GetMaskMesen.GUI.PPUControlFlags1401 		public Byte GetMask()
1402 		{
1403 			byte mask = 0;
1404 			if(Grayscale != 0) mask |= 0x01;
1405 			if(BackgroundMask != 0) mask |= 0x02;
1406 			if(SpriteMask != 0) mask |= 0x04;
1407 			if(BackgroundEnabled != 0) mask |= 0x08;
1408 			if(SpritesEnabled != 0) mask |= 0x10;
1409 			if(IntensifyBlue != 0) mask |= 0x80;
1410 			if(IntensifyRed != 0) mask |= 0x20;
1411 			if(IntensifyGreen != 0) mask |= 0x40;
1412 			return mask;
1413 		}
1414 
GetControlMesen.GUI.PPUControlFlags1415 		public Byte GetControl()
1416 		{
1417 			byte control = 0;
1418 			if(VerticalWrite != 0) control |= 0x04;
1419 			if(SpritePatternAddr == 0x1000) control |= 0x08;
1420 			if(BackgroundPatternAddr != 0x1000) control |= 0x10;
1421 			if(LargeSprites != 0) control |= 0x20;
1422 			if(VBlank != 0) control |= 0x80;
1423 			return control;
1424 		}
1425 	}
1426 
1427 	public struct PPUStatusFlags
1428 	{
1429 		public Byte SpriteOverflow;
1430 		public Byte Sprite0Hit;
1431 		public Byte VerticalBlank;
1432 
GetStatusMesen.GUI.PPUStatusFlags1433 		public Byte GetStatus()
1434 		{
1435 			byte status = 0;
1436 			if(SpriteOverflow != 0) status |= 0x20;
1437 			if(Sprite0Hit != 0) status |= 0x40;
1438 			if(VerticalBlank != 0) status |= 0x80;
1439 			return status;
1440 		}
1441 	}
1442 
1443 	public struct CPUState
1444 	{
1445 		public UInt16 PC;
1446 		public Byte SP;
1447 		public Byte A;
1448 		public Byte X;
1449 		public Byte Y;
1450 		public Byte PS;
1451 		public IRQSource IRQFlag;
1452 		public UInt64 CycleCount;
1453 
1454 		[MarshalAs(UnmanagedType.I1)]
1455 		public bool NMIFlag;
1456 
1457 		public UInt16 DebugPC;
1458 		public UInt16 PreviousDebugPC;
1459 	}
1460 
1461 	public struct ApuLengthCounterState
1462 	{
1463 		[MarshalAs(UnmanagedType.I1)]
1464 		public bool Halt;
1465 		public Byte Counter;
1466 		public Byte ReloadValue;
1467 	}
1468 
1469 	public struct ApuEnvelopeState
1470 	{
1471 		[MarshalAs(UnmanagedType.I1)]
1472 		public bool StartFlag;
1473 		[MarshalAs(UnmanagedType.I1)]
1474 		public bool Loop;
1475 		[MarshalAs(UnmanagedType.I1)]
1476 		public bool ConstantVolume;
1477 		public Byte Divider;
1478 		public Byte Counter;
1479 		public Byte Volume;
1480 	}
1481 
1482 	public struct ApuSquareState
1483 	{
1484 		public Byte Duty;
1485 		public Byte DutyPosition;
1486 		public UInt16 Period;
1487 		public UInt16 Timer;
1488 
1489 		[MarshalAs(UnmanagedType.I1)]
1490 		public bool SweepEnabled;
1491 		[MarshalAs(UnmanagedType.I1)]
1492 		public bool SweepNegate;
1493 		public Byte SweepPeriod;
1494 		public Byte SweepShift;
1495 
1496 		[MarshalAs(UnmanagedType.I1)]
1497 		public bool Enabled;
1498 		public Byte OutputVolume;
1499 		public double Frequency;
1500 
1501 		public ApuLengthCounterState LengthCounter;
1502 		public ApuEnvelopeState Envelope;
1503 	}
1504 
1505 	public struct ApuTriangleState
1506 	{
1507 		public UInt16 Period;
1508 		public UInt16 Timer;
1509 		public Byte SequencePosition;
1510 
1511 		[MarshalAs(UnmanagedType.I1)]
1512 		public bool Enabled;
1513 		public double Frequency;
1514 		public Byte OutputVolume;
1515 
1516 		public ApuLengthCounterState LengthCounter;
1517 	}
1518 
1519 	public struct ApuNoiseState
1520 	{
1521 		public UInt16 Period;
1522 		public UInt16 Timer;
1523 		public UInt16 ShiftRegister;
1524 		[MarshalAs(UnmanagedType.I1)]
1525 		public bool ModeFlag;
1526 
1527 		[MarshalAs(UnmanagedType.I1)]
1528 		public bool Enabled;
1529 		public double Frequency;
1530 		public Byte OutputVolume;
1531 
1532 		public ApuLengthCounterState LengthCounter;
1533 		public ApuEnvelopeState Envelope;
1534 	}
1535 
1536 	public struct ApuDmcState
1537 	{
1538 		public double SampleRate;
1539 		public UInt16 SampleAddr;
1540 		public UInt16 SampleLength;
1541 
1542 		[MarshalAs(UnmanagedType.I1)]
1543 		public bool Loop;
1544 		[MarshalAs(UnmanagedType.I1)]
1545 		public bool IrqEnabled;
1546 		public UInt16 Period;
1547 		public UInt16 Timer;
1548 		public UInt16 BytesRemaining;
1549 
1550 		public Byte OutputVolume;
1551 	}
1552 
1553 	public struct ApuFrameCounterState
1554 	{
1555 		[MarshalAs(UnmanagedType.I1)]
1556 		public bool FiveStepMode;
1557 		public Byte SequencePosition;
1558 		[MarshalAs(UnmanagedType.I1)]
1559 		public bool IrqEnabled;
1560 	}
1561 
1562 	public struct ApuState
1563 	{
1564 		public ApuSquareState Square1;
1565 		public ApuSquareState Square2;
1566 		public ApuTriangleState Triangle;
1567 		public ApuNoiseState Noise;
1568 		public ApuDmcState Dmc;
1569 		public ApuFrameCounterState FrameCounter;
1570 	}
1571 
1572 	[Serializable]
1573 	public struct InteropTraceLoggerOptions
1574 	{
1575 		[MarshalAs(UnmanagedType.I1)] public bool ShowExtraInfo;
1576 		[MarshalAs(UnmanagedType.I1)] public bool IndentCode;
1577 		[MarshalAs(UnmanagedType.I1)] public bool UseLabels;
1578 		[MarshalAs(UnmanagedType.I1)] public bool UseWindowsEol;
1579 		[MarshalAs(UnmanagedType.I1)] public bool ExtendZeroPage;
1580 
1581 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
1582 		public byte[] Condition;
1583 
1584 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
1585 		public byte[] Format;
1586 	}
1587 
1588 	public enum ProfilerDataType
1589 	{
1590 		FunctionExclusive = 0,
1591 		FunctionInclusive = 1,
1592 		Instructions = 2,
1593 		FunctionCallCount = 3,
1594 	}
1595 
1596 	[Flags]
1597 	public enum IRQSource : uint
1598 	{
1599 		External = 1,
1600 		FrameCounter = 2,
1601 		DMC = 4,
1602 	}
1603 
1604 	[Flags]
1605 	public enum PSFlags
1606 	{
1607 		Carry = 0x01,
1608 		Zero = 0x02,
1609 		Interrupt = 0x04,
1610 		Decimal = 0x08,
1611 		Break = 0x10,
1612 		Reserved = 0x20,
1613 		Overflow = 0x40,
1614 		Negative = 0x80
1615 	}
1616 
1617 	[Flags]
1618 	public enum EmulationFlags : UInt64
1619 	{
1620 		Paused = 0x01,
1621 		ShowFPS = 0x02,
1622 		VerticalSync = 0x04,
1623 		AllowInvalidInput = 0x08,
1624 		RemoveSpriteLimit = 0x10,
1625 		UseHdPacks = 0x20,
1626 		HasFourScore = 0x40,
1627 
1628 		DisableDynamicSampleRate = 0x80,
1629 
1630 		PauseOnMovieEnd = 0x0100,
1631 
1632 		DeveloperMode = 0x0200,
1633 
1634 		AllowBackgroundInput = 0x0400,
1635 		ReduceSoundInBackground = 0x0800,
1636 		MuteSoundInBackground = 0x1000,
1637 
1638 		FdsFastForwardOnLoad = 0x2000,
1639 		FdsAutoLoadDisk = 0x4000,
1640 		Mmc3IrqAltBehavior = 0x8000,
1641 
1642 		SwapDutyCycles = 0x10000,
1643 
1644 		AutoConfigureInput = 0x40000,
1645 
1646 		ShowLagCounter = 0x80000,
1647 
1648 		SilenceTriangleHighFreq = 0x100000,
1649 		ReduceDmcPopping = 0x200000,
1650 
1651 		DisableBackground = 0x400000,
1652 		DisableSprites = 0x800000,
1653 		ForceBackgroundFirstColumn = 0x1000000,
1654 		ForceSpritesFirstColumn = 0x2000000,
1655 		DisablePpu2004Reads = 0x4000000,
1656 		DisableNoiseModeFlag = 0x8000000,
1657 		DisablePaletteRead = 0x10000000,
1658 		DisableOamAddrBug = 0x20000000,
1659 		DisablePpuReset = 0x40000000,
1660 		EnableOamDecay = 0x80000000,
1661 
1662 		UseNes101Hvc101Behavior = 0x100000000,
1663 		ShowFrameCounter = 0x200000000,
1664 		ShowGameTimer = 0x400000000,
1665 
1666 		FdsAutoInsertDisk = 0x800000000,
1667 
1668 		Rewind = 0x1000000000,
1669 		Turbo = 0x2000000000,
1670 		InBackground = 0x4000000000,
1671 		NsfPlayerEnabled = 0x8000000000,
1672 
1673 		DisplayMovieIcons = 0x10000000000,
1674 		HidePauseOverlay = 0x20000000000,
1675 
1676 		UseCustomVsPalette = 0x40000000000,
1677 
1678 		AdaptiveSpriteLimit = 0x80000000000,
1679 
1680 		DisableGameSelectionScreen = 0x200000000000,
1681 
1682 		ConfirmExitResetPower = 0x400000000000,
1683 
1684 		NsfRepeat = 0x800000000000,
1685 		NsfShuffle = 0x1000000000000,
1686 
1687 		IntegerFpsMode = 0x2000000000000,
1688 
1689 		DebuggerWindowEnabled = 0x4000000000000,
1690 		BreakOnCrash = 0x8000000000000,
1691 
1692 		AllowMismatchingSaveStates = 0x10000000000000,
1693 
1694 		RandomizeMapperPowerOnState = 0x20000000000000,
1695 
1696 		UseHighResolutionTimer = 0x40000000000000,
1697 		DisplayDebugInfo = 0x80000000000000,
1698 
1699 		ReduceSoundInFastForward = 0x100000000000000,
1700 
1701 		VsDualMuteMaster = 0x200000000000000,
1702 		VsDualMuteSlave = 0x400000000000000,
1703 
1704 		ForceMaxSpeed = 0x4000000000000000,
1705 		ConsoleMode = 0x8000000000000000,
1706 	}
1707 
1708 	[Flags]
1709 	public enum DebuggerFlags
1710 	{
1711 		None = 0x00,
1712 
1713 		PpuPartialDraw = 0x01,
1714 		PpuShowPreviousFrame = 0x02,
1715 
1716 		ShowEffectiveAddresses = 0x04,
1717 		DisplayOpCodesInLowerCase = 0x08,
1718 		BreakOnBrk = 0x10,
1719 		BreakOnUnofficialOpCode = 0x20,
1720 		BreakOnUninitMemoryRead = 0x40,
1721 
1722 		DisassembleVerifiedData = 0x80,
1723 		DisassembleUnidentifiedData = 0x100,
1724 		ShowVerifiedData = 0x200,
1725 		ShowUnidentifiedData = 0x400,
1726 
1727 		IgnoreRedundantWrites = 0x800,
1728 
1729 		HidePauseIcon = 0x1000,
1730 
1731 		BreakOnDecayedOamRead = 0x2000,
1732 		BreakOnInit = 0x4000,
1733 		BreakOnPlay = 0x8000,
1734 
1735 		BreakOnFirstCycle = 0x10000,
1736 	}
1737 
1738 	public struct InteropRomInfo
1739 	{
1740 		public IntPtr RomNamePointer;
1741 		public UInt32 Crc32;
1742 		public UInt32 PrgCrc32;
1743 		public RomFormat Format;
1744 
1745 		[MarshalAs(UnmanagedType.I1)]
1746 		public bool IsChrRam;
1747 
1748 		public UInt16 MapperId;
1749 		public UInt32 FilePrgOffset;
1750 
1751 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
1752 		public byte[] Sha1;
1753 	}
1754 
1755 	public enum RomFormat
1756 	{
1757 		Unknown = 0,
1758 		iNes = 1,
1759 		Unif = 2,
1760 		Fds = 3,
1761 		Nsf = 4,
1762 	}
1763 
1764 	public class RomInfo
1765 	{
1766 		public ResourcePath RomFile;
1767 		public UInt32 Crc32;
1768 		public UInt32 PrgCrc32;
1769 		public RomFormat Format;
1770 		public bool IsChrRam;
1771 		public UInt16 MapperId;
1772 		public UInt32 FilePrgOffset;
1773 		public string Sha1;
1774 
RomInfo(InteropRomInfo romInfo)1775 		public RomInfo(InteropRomInfo romInfo)
1776 		{
1777 			this.RomFile = (ResourcePath)UTF8Marshaler.GetStringFromIntPtr(romInfo.RomNamePointer);
1778 			this.Crc32 = romInfo.Crc32;
1779 			this.PrgCrc32 = romInfo.PrgCrc32;
1780 			this.Format = romInfo.Format;
1781 			this.IsChrRam = romInfo.IsChrRam;
1782 			this.MapperId = romInfo.MapperId;
1783 			this.FilePrgOffset = romInfo.FilePrgOffset;
1784 			this.Sha1 = Encoding.UTF8.GetString(romInfo.Sha1);
1785 		}
1786 
GetRomName()1787 		public string GetRomName()
1788 		{
1789 			return Path.GetFileNameWithoutExtension(this.RomFile.FileName);
1790 		}
1791 
GetCrcString()1792 		public string GetCrcString()
1793 		{
1794 			return this.Crc32.ToString("X8");
1795 		}
1796 
GetPrgCrcString()1797 		public string GetPrgCrcString()
1798 		{
1799 			return this.PrgCrc32.ToString("X8");
1800 		}
1801 	};
1802 
1803 	public struct KeyCombination
1804 	{
1805 		public UInt32 Key1;
1806 		public UInt32 Key2;
1807 		public UInt32 Key3;
1808 
1809 		public bool IsEmpty { get { return Key1 == 0 && Key2 == 0 && Key3 == 0; } }
1810 
ToStringMesen.GUI.KeyCombination1811 		public override string ToString()
1812 		{
1813 			if(IsEmpty) {
1814 				return "";
1815 			} else {
1816 				return GetKeyNames();
1817 			}
1818 		}
1819 
KeyCombinationMesen.GUI.KeyCombination1820 		public KeyCombination(List<UInt32> scanCodes = null)
1821 		{
1822 			if(scanCodes != null) {
1823 				if(scanCodes.Any(code => code > 0xFFFF)) {
1824 					//If both keyboard & gamepad codes exist, only use the gamepad codes
1825 					//This fixes an issue with Steam where Steam can remap gamepad buttons to send keyboard keys
1826 					//See: Settings -> Controller Settings -> General Controller Settings -> Checking the Xbox/PS4/Generic/etc controller checkboxes will cause this
1827 					scanCodes = scanCodes.Where(code => code > 0xFFFF).ToList();
1828 				}
1829 
1830 				Key1 = scanCodes.Count > 0 ? scanCodes[0] : 0;
1831 				Key2 = scanCodes.Count > 1 ? scanCodes[1] : 0;
1832 				Key3 = scanCodes.Count > 2 ? scanCodes[2] : 0;
1833 			} else {
1834 				Key1 = 0;
1835 				Key2 = 0;
1836 				Key3 = 0;
1837 			}
1838 		}
1839 
GetKeyNamesMesen.GUI.KeyCombination1840 		private string GetKeyNames()
1841 		{
1842 			List<UInt32> scanCodes = new List<uint>() { Key1, Key2, Key3 };
1843 			List<string> keyNames = scanCodes.Select((UInt32 scanCode) => InteropEmu.GetKeyName(scanCode)).Where((keyName) => !string.IsNullOrWhiteSpace(keyName)).ToList();
1844 			keyNames.Sort((string a, string b) => {
1845 				if(a == b) {
1846 					return 0;
1847 				}
1848 
1849 				if(a == "Ctrl") {
1850 					return -1;
1851 				} else if(b == "Ctrl") {
1852 					return 1;
1853 				}
1854 
1855 				if(a == "Alt") {
1856 					return -1;
1857 				} else if(b == "Alt") {
1858 					return 1;
1859 				}
1860 
1861 				if(a == "Shift") {
1862 					return -1;
1863 				} else if(b == "Shift") {
1864 					return 1;
1865 				}
1866 
1867 				return a.CompareTo(b);
1868 			});
1869 
1870 			return string.Join("+", keyNames);
1871 		}
1872 	}
1873 
1874 	public enum EmulatorShortcut
1875 	{
1876 		FastForward,
1877 		Rewind,
1878 		RewindTenSecs,
1879 		RewindOneMin,
1880 
1881 		MoveToNextStateSlot,
1882 		MoveToPreviousStateSlot,
1883 		SaveState,
1884 		LoadState,
1885 
1886 		InsertNextDisk,
1887 		VsServiceButton,
1888 		VsServiceButton2,
1889 
1890 		ToggleCheats,
1891 		ToggleAudio,
1892 		ToggleFastForward,
1893 		ToggleRewind,
1894 		ToggleKeyboardMode,
1895 
1896 		RunSingleFrame,
1897 
1898 		// Everything below this is handled UI-side
1899 		SwitchDiskSide,
1900 		EjectDisk,
1901 
1902 		InsertCoin1,
1903 		InsertCoin2,
1904 		InsertCoin3,
1905 		InsertCoin4,
1906 
1907 		InputBarcode,
1908 
1909 		TakeScreenshot,
1910 
1911 		IncreaseSpeed,
1912 		DecreaseSpeed,
1913 		MaxSpeed,
1914 
1915 		Pause,
1916 		Reset,
1917 		PowerCycle,
1918 		PowerOff,
1919 		Exit,
1920 
1921 		SetScale1x,
1922 		SetScale2x,
1923 		SetScale3x,
1924 		SetScale4x,
1925 		SetScale5x,
1926 		SetScale6x,
1927 		ToggleFullscreen,
1928 		ToggleFps,
1929 		ToggleGameTimer,
1930 		ToggleFrameCounter,
1931 		ToggleLagCounter,
1932 		ToggleOsd,
1933 		ToggleAlwaysOnTop,
1934 		ToggleSprites,
1935 		ToggleBackground,
1936 		ToggleDebugInfo,
1937 
1938 		LoadRandomGame,
1939 		SaveStateSlot1,
1940 		SaveStateSlot2,
1941 		SaveStateSlot3,
1942 		SaveStateSlot4,
1943 		SaveStateSlot5,
1944 		SaveStateSlot6,
1945 		SaveStateSlot7,
1946 		SaveStateSlot8,
1947 		SaveStateSlot9,
1948 		SaveStateSlot10,
1949 		SaveStateToFile,
1950 
1951 		LoadStateSlot1,
1952 		LoadStateSlot2,
1953 		LoadStateSlot3,
1954 		LoadStateSlot4,
1955 		LoadStateSlot5,
1956 		LoadStateSlot6,
1957 		LoadStateSlot7,
1958 		LoadStateSlot8,
1959 		LoadStateSlot9,
1960 		LoadStateSlot10,
1961 		LoadStateSlotAuto,
1962 		LoadStateFromFile,
1963 
1964 		LoadLastSession,
1965 
1966 		OpenFile,
1967 
1968 
1969 		//Deprecated shortcuts
1970 		OpenDebugger = 0xFFFF,
1971 		OpenAssembler,
1972 		OpenPpuViewer,
1973 		OpenMemoryTools,
1974 		OpenScriptWindow,
1975 		OpenTraceLogger,
1976 		OpenApuViewer,
1977 		OpenEventViewer,
1978 	}
1979 
1980 	public struct InteropCheatInfo
1981 	{
1982 		public CheatType CheatType;
1983 		public UInt32 ProActionRockyCode;
1984 		public UInt32 Address;
1985 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
1986 		public byte[] GameGenieCode;
1987 		public byte Value;
1988 		public byte CompareValue;
1989 		[MarshalAs(UnmanagedType.I1)]
1990 		public bool UseCompareValue;
1991 		[MarshalAs(UnmanagedType.I1)]
1992 		public bool IsRelativeAddress;
1993 	}
1994 
1995 	public struct InteropBreakpoint
1996 	{
1997 		public Int32 Id;
1998 		public DebugMemoryType MemoryType;
1999 		public BreakpointTypeFlags Type;
2000 		public Int32 StartAddress;
2001 		public Int32 EndAddress;
2002 
2003 		[MarshalAs(UnmanagedType.I1)]
2004 		public bool Enabled;
2005 
2006 		[MarshalAs(UnmanagedType.I1)]
2007 		public bool MarkEvent;
2008 
2009 		[MarshalAs(UnmanagedType.I1)]
2010 		public bool ProcessDummyReadWrites;
2011 
2012 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
2013 		public byte[] Condition;
2014 	}
2015 
2016 	public struct NsfHeader
2017 	{
2018 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5)]
2019 		public Byte[] Header;
2020 
2021 		public Byte Version;
2022 		public Byte TotalSongs;
2023 		public Byte StartingSong;
2024 		public UInt16 LoadAddress;
2025 		public UInt16 InitAddress;
2026 		public UInt16 PlayAddress;
2027 
2028 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
2029 		public Byte[] SongName;
2030 
2031 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
2032 		public Byte[] ArtistName;
2033 
2034 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
2035 		public Byte[] CopyrightHolder;
2036 
2037 		public UInt16 PlaySpeedNtsc;
2038 
2039 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
2040 		public Byte[] BankSetup;
2041 
2042 		public UInt16 PlaySpeedPal;
2043 		public Byte Flags;
2044 		public Byte SoundChips;
2045 
2046 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
2047 		public Byte[] Padding;
2048 
2049 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
2050 		public Byte[] RipperName;
2051 
2052 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 20000)]
2053 		public Byte[] TrackName;
2054 
2055 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
2056 		public Int32[] TrackLength;
2057 
2058 		[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
2059 		public Int32[] TrackFade;
2060 
ConvertStringMesen.GUI.NsfHeader2061 		private string ConvertString(Byte[] input)
2062 		{
2063 			string output = Encoding.UTF8.GetString(input, 0, Array.IndexOf(input, (Byte)0));
2064 			if(output.Length == 0 || output == "<?>") {
2065 				return ResourceHelper.GetMessage("NsfUnknownField");
2066 			}
2067 
2068 			if(output[0] == 0xFFFD) {
2069 				//Patch to convert an invalid character at index 0 to a copyright sign
2070 				//This is usually the case for NSFe files (not sure what the encoding for NSF/NSFe is meant to be.  Is it properly defined?)
2071 				return "©" + output.Substring(1);
2072 			}
2073 
2074 			return output;
2075 		}
2076 
2077 		public bool HasSongName { get { return this.GetSongName() != ResourceHelper.GetMessage("NsfUnknownField"); } }
2078 
GetSongNameMesen.GUI.NsfHeader2079 		public string GetSongName()
2080 		{
2081 			return ConvertString(this.SongName);
2082 		}
2083 
GetArtistNameMesen.GUI.NsfHeader2084 		public string GetArtistName()
2085 		{
2086 			return ConvertString(this.ArtistName);
2087 		}
2088 
GetCopyrightHolderMesen.GUI.NsfHeader2089 		public string GetCopyrightHolder()
2090 		{
2091 			return ConvertString(this.CopyrightHolder);
2092 		}
2093 
GetRipperNameMesen.GUI.NsfHeader2094 		public string GetRipperName()
2095 		{
2096 			return ConvertString(this.RipperName);
2097 		}
2098 
GetTrackNamesMesen.GUI.NsfHeader2099 		public string[] GetTrackNames()
2100 		{
2101 			return Encoding.UTF8.GetString(this.TrackName, 0, Array.IndexOf(this.TrackName, (Byte)0)).Split(new string[] { "[!|!]" }, StringSplitOptions.None);
2102 		}
2103 	}
2104 
2105 	public enum RecordMovieFrom
2106 	{
2107 		StartWithoutSaveData,
2108 		StartWithSaveData,
2109 		CurrentState
2110 	}
2111 
2112 	public struct RecordMovieOptions
2113 	{
2114 		private const int AuthorMaxSize = 250;
2115 		private const int DescriptionMaxSize = 10000;
2116 		private const int FilenameMaxSize = 2000;
2117 
RecordMovieOptionsMesen.GUI.RecordMovieOptions2118 		public RecordMovieOptions(string filename, string author, string description, RecordMovieFrom recordFrom)
2119 		{
2120 			Author = Encoding.UTF8.GetBytes(author);
2121 			Array.Resize(ref Author, AuthorMaxSize);
2122 			Author[AuthorMaxSize-1] = 0;
2123 
2124 			Description = Encoding.UTF8.GetBytes(description.Replace("\r", ""));
2125 			Array.Resize(ref Description, DescriptionMaxSize);
2126 			Description[DescriptionMaxSize-1] = 0;
2127 
2128 			Filename = Encoding.UTF8.GetBytes(filename);
2129 			Array.Resize(ref Filename, FilenameMaxSize);
2130 			Filename[FilenameMaxSize-1] = 0;
2131 
2132 			RecordFrom = recordFrom;
2133 		}
2134 
2135 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = FilenameMaxSize)]
2136 		public byte[] Filename;
2137 
2138 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = AuthorMaxSize)]
2139 		public byte[] Author;
2140 
2141 		[MarshalAs(UnmanagedType.ByValArray, SizeConst = DescriptionMaxSize)]
2142 		public byte[] Description;
2143 
2144 		public RecordMovieFrom RecordFrom;
2145 	}
2146 
2147 	public enum BreakpointType
2148 	{
2149 		Global = 0,
2150 		Execute = 1,
2151 		ReadRam = 2,
2152 		WriteRam = 3,
2153 		ReadVram = 4,
2154 		WriteVram = 5,
2155 		DummyReadRam = 6,
2156 		DummyWriteRam = 7
2157 	}
2158 
2159 	[Flags]
2160 	public enum BreakpointTypeFlags
2161 	{
2162 		Global = 0,
2163 		Execute = 1,
2164 		Read = 2,
2165 		Write = 4,
2166 		ReadVram = 8,
2167 		WriteVram = 16
2168 	}
2169 
2170 	public enum EvalResultType
2171 	{
2172 		Numeric = 0,
2173 		Boolean = 1,
2174 		Invalid = 2,
2175 		DivideBy0 = 3,
2176 		OutOfScope = 4
2177 	}
2178 
2179 	public enum NesModel
2180 	{
2181 		Auto = 0,
2182 		NTSC = 1,
2183 		PAL = 2,
2184 		Dendy = 3,
2185 	}
2186 
2187 	public enum ConsoleType
2188 	{
2189 		Nes = 0,
2190 		Famicom = 1
2191 	}
2192 
2193 	public enum RamPowerOnState
2194 	{
2195 		AllZeros = 0,
2196 		AllOnes = 1,
2197 		Random = 2
2198 	}
2199 
2200 	public enum AudioChannel
2201 	{
2202 		Square1 = 0,
2203 		Square2 = 1,
2204 		Triangle = 2,
2205 		Noise = 3,
2206 		DMC = 4,
2207 		FDS = 5,
2208 		MMC5 = 6,
2209 		VRC6 = 7,
2210 		VRC7 = 8,
2211 		Namco163 = 9,
2212 		Sunsoft5B = 10
2213 	}
2214 
2215 	public enum EqualizerFilterType
2216 	{
2217 		None = 0,
2218 		Butterworth = 1,
2219 		Chebyshev1 = 2,
2220 		Chebyshev2 = 3
2221 	}
2222 
2223 	public enum VideoCodec
2224 	{
2225 		None = 0,
2226 		ZMBV = 1,
2227 		CSCD = 2,
2228 	}
2229 
2230 	public enum ScaleFilterType
2231 	{
2232 		xBRZ = 0,
2233 		HQX = 1,
2234 		Scale2x = 2,
2235 		_2xSai = 3,
2236 		Super2xSai = 4,
2237 		SuperEagle = 5,
2238 		Prescale = 6,
2239 	}
2240 
2241 	public enum VideoFilterType
2242 	{
2243 		None = 0,
2244 		NTSC = 1,
2245 		BisqwitNtscQuarterRes = 2,
2246 		BisqwitNtscHalfRes = 3,
2247 		BisqwitNtsc = 4,
2248 		xBRZ2x = 5,
2249 		xBRZ3x = 6,
2250 		xBRZ4x = 7,
2251 		xBRZ5x = 8,
2252 		xBRZ6x = 9,
2253 		HQ2x = 10,
2254 		HQ3x = 11,
2255 		HQ4x = 12,
2256 		Scale2x = 13,
2257 		Scale3x = 14,
2258 		Scale4x = 15,
2259 		_2xSai = 16,
2260 		Super2xSai = 17,
2261 		SuperEagle = 18,
2262 		Prescale2x = 19,
2263 		Prescale3x = 20,
2264 		Prescale4x = 21,
2265 		Prescale6x = 22,
2266 		Prescale8x = 23,
2267 		Prescale10x = 24,
2268 	}
2269 
2270 	public enum VideoResizeFilter
2271 	{
2272 		NearestNeighbor = 0,
2273 		Bilinear = 1
2274 	}
2275 
2276 	public enum VideoAspectRatio
2277 	{
2278 		NoStretching = 0,
2279 		Auto = 1,
2280 		NTSC = 2,
2281 		PAL = 3,
2282 		Standard = 4,
2283 		Widescreen = 5,
2284 		Custom = 6
2285 	}
2286 
2287 	public enum VideoRefreshRates
2288 	{
2289 		_50 = 50,
2290 		_60 = 60,
2291 		_100 = 100,
2292 		_120 = 120,
2293 		_200 = 200,
2294 		_240 = 240
2295 	}
2296 
2297 	[Flags]
2298 	public enum ConsoleFeatures
2299 	{
2300 		None = 0,
2301 		Fds = 1,
2302 		Nsf = 2,
2303 		VsSystem = 4,
2304 		BarcodeReader = 8,
2305 		TapeRecorder = 16,
2306 		BandaiMicrophone = 32,
2307 		DatachBarcodeReader = 64,
2308 	}
2309 
2310 	public enum ScreenRotation
2311 	{
2312 		None = 0,
2313 		_90Degrees = 90,
2314 		_180Degrees = 180,
2315 		_270Degrees = 270
2316 	}
2317 
2318 	public enum NametableDisplayMode
2319 	{
2320 		Normal = 0,
2321 		Grayscale = 1,
2322 		AttributeView = 2
2323 	}
2324 
2325 	public enum DebugMemoryType
2326 	{
2327 		CpuMemory = 0,
2328 		PpuMemory = 1,
2329 		PaletteMemory = 2,
2330 		SpriteMemory = 3,
2331 		SecondarySpriteMemory = 4,
2332 		PrgRom = 5,
2333 		ChrRom = 6,
2334 		ChrRam = 7,
2335 		WorkRam = 8,
2336 		SaveRam = 9,
2337 		InternalRam = 10,
2338 		NametableRam = 11
2339 	}
2340 
2341 	public enum BreakSource
2342 	{
2343 		Unspecified = -1,
2344 		Breakpoint = 0,
2345 		CpuStep = 1,
2346 		PpuStep = 2,
2347 		BreakOnBrk = 3,
2348 		BreakOnUnofficialOpCode = 4,
2349 		BreakOnReset = 5,
2350 		BreakOnFocus = 6,
2351 		BreakOnUninitMemoryRead = 7,
2352 		BreakOnDecayedOamRead = 8,
2353 		BreakOnCpuCrash = 9,
2354 		Pause = 10,
2355 		BreakAfterSuspend = 11,
2356 	}
2357 
2358 	public enum PpuAddressType
2359 	{
2360 		ChrRom = 0,
2361 		ChrRam = 1,
2362 		PaletteRam = 2,
2363 		NametableRam = 3
2364 	}
2365 
2366 	public enum AddressType
2367 	{
2368 		InternalRam = 0,
2369 		PrgRom = 1,
2370 		WorkRam = 2,
2371 		SaveRam = 3,
2372 		Register = 4
2373 	}
2374 
2375 	public static class AddressTypeExtensions
2376 	{
ToMemoryType(this AddressType type)2377 		public static DebugMemoryType ToMemoryType(this AddressType type)
2378 		{
2379 			switch(type) {
2380 				case AddressType.InternalRam: return DebugMemoryType.InternalRam;
2381 				case AddressType.Register: return DebugMemoryType.CpuMemory;
2382 				case AddressType.PrgRom: return DebugMemoryType.PrgRom;
2383 				case AddressType.WorkRam: return DebugMemoryType.WorkRam;
2384 				case AddressType.SaveRam: return DebugMemoryType.SaveRam;
2385 			}
2386 			return DebugMemoryType.CpuMemory;
2387 		}
2388 
ToMemoryType(this PpuAddressType type)2389 		public static DebugMemoryType ToMemoryType(this PpuAddressType type)
2390 		{
2391 			switch(type) {
2392 				case PpuAddressType.ChrRom: return DebugMemoryType.ChrRom;
2393 				case PpuAddressType.ChrRam: return DebugMemoryType.ChrRam;
2394 				case PpuAddressType.NametableRam: return DebugMemoryType.NametableRam;
2395 				case PpuAddressType.PaletteRam: return DebugMemoryType.PaletteMemory;
2396 			}
2397 			throw new Exception("Invalid memory type");
2398 		}
2399 
ToAddressType(this DebugMemoryType type)2400 		public static AddressType ToAddressType(this DebugMemoryType type)
2401 		{
2402 			switch(type) {
2403 				case DebugMemoryType.InternalRam: return AddressType.InternalRam;
2404 				case DebugMemoryType.CpuMemory: return AddressType.Register;
2405 				case DebugMemoryType.PrgRom: return AddressType.PrgRom;
2406 				case DebugMemoryType.WorkRam: return AddressType.WorkRam;
2407 				case DebugMemoryType.SaveRam: return AddressType.SaveRam;
2408 			}
2409 			return AddressType.Register;
2410 		}
2411 
ToPpuAddressType(this DebugMemoryType type)2412 		public static PpuAddressType ToPpuAddressType(this DebugMemoryType type)
2413 		{
2414 			switch(type) {
2415 				case DebugMemoryType.ChrRom: return PpuAddressType.ChrRom;
2416 				case DebugMemoryType.ChrRam: return PpuAddressType.ChrRam;
2417 				case DebugMemoryType.NametableRam: return PpuAddressType.NametableRam;
2418 				case DebugMemoryType.PaletteMemory: return PpuAddressType.PaletteRam;
2419 			}
2420 			throw new Exception("Invalid memory type");
2421 		}
2422 	}
2423 
2424 	public enum PerfTrackerMode
2425 	{
2426 		Disabled = 0,
2427 		Fullscreen = 1,
2428 		Compact = 2,
2429 		TextOnly = 3
2430 	}
2431 
2432 	public enum InteropMemoryOperationType
2433 	{
2434 		Read = 0,
2435 		Write = 1,
2436 		ExecOpCode = 2,
2437 		ExecOperand = 3,
2438 		PpuRenderingRead = 4,
2439 		DummyRead = 5,
2440 		DmcRead = 6,
2441 		DummyWrite = 7
2442 	}
2443 
2444 	public enum MemoryOperationType
2445 	{
2446 		//Note: Not identical to the C++ enum
2447 		Read = 0,
2448 		Write = 1,
2449 		Exec = 2,
2450 	}
2451 
2452 	[Flags]
2453 	public enum HdPackRecordFlags
2454 	{
2455 		None = 0,
2456 		UseLargeSprites = 1,
2457 		SortByUsageFrequency = 2,
2458 		GroupBlankTiles = 4,
2459 		IgnoreOverscan = 8,
2460 	}
2461 
2462 	[StructLayout(LayoutKind.Sequential)]
2463 	public class AddressTypeInfo
2464 	{
2465 		public Int32 Address;
2466 		public AddressType Type;
2467 	}
2468 
2469 	[StructLayout(LayoutKind.Sequential)]
2470 	public class PpuAddressTypeInfo
2471 	{
2472 		public Int32 Address;
2473 		public PpuAddressType Type;
2474 	}
2475 
2476 	public class MD5Helper
2477 	{
GetMD5Hash(string filename)2478 		public static string GetMD5Hash(string filename)
2479 		{
2480 			if(File.Exists(filename)) {
2481 				var md5 = System.Security.Cryptography.MD5.Create();
2482 				return BitConverter.ToString(md5.ComputeHash(File.ReadAllBytes(filename))).Replace("-", "");
2483 			}
2484 			return null;
2485 		}
2486 	}
2487 
2488 	public class UTF8Marshaler : ICustomMarshaler
2489 	{
2490 		static UTF8Marshaler _instance;
2491 
MarshalManagedToNative(object managedObj)2492 		public IntPtr MarshalManagedToNative(object managedObj)
2493 		{
2494 			if(managedObj == null) {
2495 				return IntPtr.Zero;
2496 			}
2497 			if(!(managedObj is string)) {
2498 				throw new MarshalDirectiveException("UTF8Marshaler must be used on a string.");
2499 			}
2500 
2501 			// not null terminated
2502 			byte[] strbuf = Encoding.UTF8.GetBytes((string)managedObj);
2503 			IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1);
2504 			Marshal.Copy(strbuf, 0, buffer, strbuf.Length);
2505 
2506 			// write the terminating null
2507 			Marshal.WriteByte(buffer + strbuf.Length, 0);
2508 			return buffer;
2509 		}
2510 
MarshalNativeToManaged(IntPtr pNativeData)2511 		public object MarshalNativeToManaged(IntPtr pNativeData)
2512 		{
2513 			return GetStringFromIntPtr(pNativeData);
2514 		}
2515 
CleanUpNativeData(IntPtr pNativeData)2516 		public void CleanUpNativeData(IntPtr pNativeData)
2517 		{
2518 			Marshal.FreeHGlobal(pNativeData);
2519 		}
2520 
CleanUpManagedData(object managedObj)2521 		public void CleanUpManagedData(object managedObj)
2522 		{
2523 		}
2524 
GetNativeDataSize()2525 		public int GetNativeDataSize()
2526 		{
2527 			return -1;
2528 		}
2529 
GetInstance(string cookie)2530 		public static ICustomMarshaler GetInstance(string cookie)
2531 		{
2532 			if(_instance == null) {
2533 				return _instance = new UTF8Marshaler();
2534 			}
2535 			return _instance;
2536 		}
2537 
GetStringFromIntPtr(IntPtr pNativeData)2538 		public static string GetStringFromIntPtr(IntPtr pNativeData)
2539 		{
2540 			int offset = 0;
2541 			byte b = 0;
2542 			do {
2543 				b = Marshal.ReadByte(pNativeData, offset);
2544 				offset++;
2545 			} while(b != 0);
2546 
2547 			int length = offset - 1;
2548 
2549 			// should not be null terminated
2550 			byte[] strbuf = new byte[length];
2551 			// skip the trailing null
2552 			Marshal.Copy((IntPtr)pNativeData, strbuf, 0, length);
2553 			string data = Encoding.UTF8.GetString(strbuf);
2554 			return data;
2555 		}
2556 	}
2557 }
2558