From 6f93202c98004b7d8876b7a98131e2481fab40c8 Mon Sep 17 00:00:00 2001 From: Silvris <58583688+Silvris@users.noreply.github.com> Date: Sun, 15 Oct 2023 22:48:59 -0500 Subject: [PATCH 01/14] sni connector, with sanrio smash ball --- .gitignore | 4 +- HintMachine.SNIConnector/Devices.cs | 4 + .../HintMachine.SNIConnector.csproj | 100 +++++ .../Properties/AssemblyInfo.cs | 36 ++ HintMachine.SNIConnector/Protos/sni.proto | 425 ++++++++++++++++++ HintMachine.SNIConnector/app.config | 27 ++ HintMachine.SNIConnector/packages.config | 15 + HintMachine.SNIConnector/sni.proto | 425 ++++++++++++++++++ HintMachine.sln | 18 +- HintMachine/App.config | 28 +- HintMachine/ComboBoxPrompt.xaml | 19 + HintMachine/ComboBoxPrompt.xaml.cs | 35 ++ HintMachine/Games/SanrioConnector.cs | 97 ++++ .../GenericConnectors/ISNIConnector.cs | 123 +++++ HintMachine/Globals.cs | 1 + HintMachine/HintMachine.csproj | 34 +- HintMachine/packages.config | 14 +- 17 files changed, 1397 insertions(+), 8 deletions(-) create mode 100644 HintMachine.SNIConnector/Devices.cs create mode 100644 HintMachine.SNIConnector/HintMachine.SNIConnector.csproj create mode 100644 HintMachine.SNIConnector/Properties/AssemblyInfo.cs create mode 100644 HintMachine.SNIConnector/Protos/sni.proto create mode 100644 HintMachine.SNIConnector/app.config create mode 100644 HintMachine.SNIConnector/packages.config create mode 100644 HintMachine.SNIConnector/sni.proto create mode 100644 HintMachine/ComboBoxPrompt.xaml create mode 100644 HintMachine/ComboBoxPrompt.xaml.cs create mode 100644 HintMachine/Games/SanrioConnector.cs create mode 100644 HintMachine/GenericConnectors/ISNIConnector.cs diff --git a/.gitignore b/.gitignore index f7a499d..cd5d407 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -HintMachine/obj -HintMachine/bin +*/obj +*/bin .vs packages/ \ No newline at end of file diff --git a/HintMachine.SNIConnector/Devices.cs b/HintMachine.SNIConnector/Devices.cs new file mode 100644 index 0000000..bc9bb32 --- /dev/null +++ b/HintMachine.SNIConnector/Devices.cs @@ -0,0 +1,4 @@ +namespace HintMachine +{ + +} \ No newline at end of file diff --git a/HintMachine.SNIConnector/HintMachine.SNIConnector.csproj b/HintMachine.SNIConnector/HintMachine.SNIConnector.csproj new file mode 100644 index 0000000..71dc319 --- /dev/null +++ b/HintMachine.SNIConnector/HintMachine.SNIConnector.csproj @@ -0,0 +1,100 @@ + + + + + + Debug + AnyCPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2} + Library + Properties + HintMachine.SNIConnector + HintMachine.SNIConnector + v4.8 + 512 + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Google.Protobuf.3.24.4\lib\net45\Google.Protobuf.dll + + + ..\packages\Grpc.Core.Api.2.57.0\lib\net462\Grpc.Core.Api.dll + + + ..\packages\Grpc.Net.Client.2.56.0\lib\net462\Grpc.Net.Client.dll + + + ..\packages\Grpc.Net.Common.2.57.0\lib\netstandard2.0\Grpc.Net.Common.dll + + + ..\packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll + + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + ..\packages\System.Diagnostics.DiagnosticSource.6.0.1\lib\net461\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + ..\packages\System.Net.Http.WinHttpHandler.7.0.0\lib\net462\System.Net.Http.WinHttpHandler.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + \ No newline at end of file diff --git a/HintMachine.SNIConnector/Properties/AssemblyInfo.cs b/HintMachine.SNIConnector/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0a589a8 --- /dev/null +++ b/HintMachine.SNIConnector/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HintMachine.SNIConnector")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HintMachine.SNIConnector")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4ed98a39-76aa-45c8-9bef-ee24bc4bfbd2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HintMachine.SNIConnector/Protos/sni.proto b/HintMachine.SNIConnector/Protos/sni.proto new file mode 100644 index 0000000..e29de96 --- /dev/null +++ b/HintMachine.SNIConnector/Protos/sni.proto @@ -0,0 +1,425 @@ +syntax = "proto3"; + +option go_package = "github.com/alttpo/sni/protos/sni"; +option csharp_namespace = "SNI"; +option java_package = "com.github.alttpo.sni"; + +////////////////////////////////////////////////////////////////////////////////////////////////// +// services +////////////////////////////////////////////////////////////////////////////////////////////////// + +service Devices { + // detect and list devices currently connected to the system: + rpc ListDevices(DevicesRequest) returns (DevicesResponse) {} +} + +service DeviceControl { + // only available if DeviceCapability ResetSystem is present + rpc ResetSystem(ResetSystemRequest) returns (ResetSystemResponse) {} + + // only available if DeviceCapability ResetToMenu is present + rpc ResetToMenu(ResetToMenuRequest) returns (ResetToMenuResponse) {} + + // only available if DeviceCapability PauseUnpauseEmulation is present + rpc PauseUnpauseEmulation(PauseEmulationRequest) returns (PauseEmulationResponse) {} + + // only available if DeviceCapability PauseToggleEmulation is present + rpc PauseToggleEmulation(PauseToggleEmulationRequest) returns (PauseToggleEmulationResponse) {} +} + +service DeviceMemory { + // detect the current memory mapping for the given device by reading 00:FFB0 header: + rpc MappingDetect(DetectMemoryMappingRequest) returns (DetectMemoryMappingResponse) {} + + // read a single memory segment with a given size from the given device: + rpc SingleRead(SingleReadMemoryRequest) returns (SingleReadMemoryResponse) {} + // write a single memory segment with given data to the given device: + rpc SingleWrite(SingleWriteMemoryRequest) returns (SingleWriteMemoryResponse) {} + + // read multiple memory segments with given sizes from the given device: + rpc MultiRead(MultiReadMemoryRequest) returns (MultiReadMemoryResponse) {} + // write multiple memory segments with given data to the given device: + rpc MultiWrite(MultiWriteMemoryRequest) returns (MultiWriteMemoryResponse) {} + + // stream read multiple memory segments with given sizes from the given device: + rpc StreamRead(stream MultiReadMemoryRequest) returns (stream MultiReadMemoryResponse) {} + // stream write multiple memory segments with given data to the given device: + rpc StreamWrite(stream MultiWriteMemoryRequest) returns (stream MultiWriteMemoryResponse) {} +} + +service DeviceFilesystem { + rpc ReadDirectory(ReadDirectoryRequest) returns (ReadDirectoryResponse) {} + rpc MakeDirectory(MakeDirectoryRequest) returns (MakeDirectoryResponse) {} + rpc RemoveFile(RemoveFileRequest) returns (RemoveFileResponse) {} + rpc RenameFile(RenameFileRequest) returns (RenameFileResponse) {} + rpc PutFile(PutFileRequest) returns (PutFileResponse) {} + rpc GetFile(GetFileRequest) returns (GetFileResponse) {} + rpc BootFile(BootFileRequest) returns (BootFileResponse) {} +} + +service DeviceInfo { + rpc FetchFields(FieldsRequest) returns (FieldsResponse) {} +} + +service DeviceNWA { + rpc NWACommand(NWACommandRequest) returns (NWACommandResponse) {} +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// enums +////////////////////////////////////////////////////////////////////////////////////////////////// + +// address space used to interpret an address in: +enum AddressSpace { + // The default is the FX Pak Pro / SD2SNES's address space: + // $00_0000..$DF_FFFF = ROM contents, linearly mapped + // $E0_0000..$EF_FFFF = SRAM contents, linearly mapped + // $F5_0000..$F6_FFFF = WRAM contents, linearly mapped + // $F7_0000..$F7_FFFF = VRAM contents, linearly mapped + // $F8_0000..$F8_FFFF = APU contents, linearly mapped + // $F9_0000..$F9_01FF = CGRAM contents, linearly mapped + // $F9_0200..$F9_041F = OAM contents, linearly mapped + // $F9_0420..$F9_04FF = MISC contents, linearly mapped + // $F9_0500..$F9_06FF = PPUREG, linearly mapped + // $F9_0700..$F9_08FF = CPUREG, linearly mapped + // translated device address depends on device being talked to and its current MemoryMapping mode + FxPakPro = 0; // SNES + // The SNES's main A-bus; address depends on device's current MemoryMapping mode, e.g. LoROM, HiROM, ExHiROM, etc. + SnesABus = 1; + // Do not do any address translation; simply pass the raw address to the device as-is: + Raw = 2; +} + +// memory mapping mode of a SNES cart: +enum MemoryMapping { + Unknown = 0; + HiROM = 1; + LoROM = 2; + ExHiROM = 3; // (48-64Mbit) + SA1 = 4; + // TODO: BSX = 5; +} + +// capabilities of a device +enum DeviceCapability { + None = 0; + ReadMemory = 1; + WriteMemory = 2; + ExecuteASM = 3; + ResetSystem = 4; + PauseUnpauseEmulation = 5; + PauseToggleEmulation = 6; + ResetToMenu = 7; + FetchFields = 8; + + ReadDirectory = 10; + MakeDirectory = 11; + RemoveFile = 12; + RenameFile = 13; + PutFile = 14; + GetFile = 15; + BootFile = 16; + + NWACommand = 20; +} + +// fields to query from DeviceInfo.FetchFields +enum Field { + DeviceName = 0; + DeviceVersion = 1; + DeviceStatus = 2; + + CoreName = 20; + CoreVersion = 21; + CorePlatform = 22; + + RomFileName = 40; + RomHashType = 41; + RomHashValue = 42; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// devices messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message DevicesRequest { + // optional list of device kind filters + repeated string kinds = 1; + // TODO: repeated DeviceCapability capabilities; +} +message DevicesResponse { + message Device { + // URI that describes exactly how to connect to the device, e.g.: + // RetroArch: "ra://127.0.0.1:55355" + // FX Pak Pro: "fxpakpro://./dev/cu.usbmodemDEMO000000001" (MacOS) + // "fxpakpro://./COM4" (Windows) + // "fxpakpro://./dev/ttyACM0" (Linux) + // uri is used as the unique identifier of the device for clients to refer to + string uri = 1; + // friendly display name of the device + string displayName = 2; + // device kind, e.g. "fxpakpro", "retroarch", "lua" + string kind = 3; + // all device capabilities: + repeated DeviceCapability capabilities = 4; + // default address space for the device: + AddressSpace defaultAddressSpace = 5; + + // [DEPRECATED] console system supported, e.g. "snes", "n64" + // since devices can support multiple systems, it's better to fetch platform from DeviceInfo.FetchFields method + string system = 6 [deprecated = true]; + } + + repeated Device devices = 1; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// control messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message ResetSystemRequest { + string uri = 1; +} +message ResetSystemResponse { + string uri = 1; +} + +message ResetToMenuRequest { + string uri = 1; +} +message ResetToMenuResponse { + string uri = 1; +} + +message PauseEmulationRequest { + string uri = 1; + // true to pause emulation, false to unpause + bool paused = 2; +} +message PauseEmulationResponse { + string uri = 1; + bool paused = 2; +} + +message PauseToggleEmulationRequest { + string uri = 1; +} +message PauseToggleEmulationResponse { + string uri = 1; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// memory messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message DetectMemoryMappingRequest { + string uri = 1; + // optional fallback value to set in case detection fails for some reason + optional MemoryMapping fallbackMemoryMapping = 2; + // optional ROM header (from bus address $00:FFB0, at least $30 bytes long) to use for detection + // if not provided, the header will be read from the device + optional bytes romHeader00FFB0 = 3; +} +message DetectMemoryMappingResponse { + string uri = 1; + // the memory mapping mode detected + MemoryMapping memoryMapping = 2; + // true if confident we detected a mapping; false if using a fallback or default value + bool confidence = 3; + // the ROM header read from $00:FFB0, length is $50 bytes if server reads it, otherwise length of `romHeader00FFB0` from request + bytes romHeader00FFB0 = 4; +} + +message ReadMemoryRequest { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 4; + + uint32 size = 3; +} +message ReadMemoryResponse { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 6; + + // the address sent to the device and its space + uint32 deviceAddress = 3; + AddressSpace deviceAddressSpace = 4; + + bytes data = 5; +} +message WriteMemoryRequest { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 4; + + bytes data = 3; +} +message WriteMemoryResponse { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 6; + + uint32 deviceAddress = 3; + AddressSpace deviceAddressSpace = 4; + + uint32 size = 5; +} + +message SingleReadMemoryRequest { + string uri = 1; + ReadMemoryRequest request = 2; +} +message SingleReadMemoryResponse { + string uri = 1; + ReadMemoryResponse response = 2; +} + +message SingleWriteMemoryRequest { + string uri = 1; + WriteMemoryRequest request = 2; +} +message SingleWriteMemoryResponse { + string uri = 1; + WriteMemoryResponse response = 2; +} + +message MultiReadMemoryRequest { + string uri = 1; + repeated ReadMemoryRequest requests = 2; +} +message MultiReadMemoryResponse { + string uri = 1; + repeated ReadMemoryResponse responses = 2; +} + +message MultiWriteMemoryRequest { + string uri = 1; + repeated WriteMemoryRequest requests = 2; +} +message MultiWriteMemoryResponse { + string uri = 1; + repeated WriteMemoryResponse responses = 2; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// filesystem messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message ReadDirectoryRequest { + string uri = 1; + string path = 2; +} + +enum DirEntryType { + Directory = 0; + File = 1; +} + +message DirEntry { + string name = 1; + DirEntryType type = 2; +} + +message ReadDirectoryResponse { + string uri = 1; + string path = 2; + repeated DirEntry entries = 3; +} + +message MakeDirectoryRequest { + string uri = 1; + string path = 2; +} +message MakeDirectoryResponse { + string uri = 1; + string path = 2; +} + +message RemoveFileRequest { + string uri = 1; + string path = 2; +} +message RemoveFileResponse { + string uri = 1; + string path = 2; +} + +message RenameFileRequest { + string uri = 1; + string path = 2; + string newFilename = 3; +} +message RenameFileResponse { + string uri = 1; + string path = 2; + string newFilename = 3; +} + +message PutFileRequest { + string uri = 1; + string path = 2; + bytes data = 3; +} +message PutFileResponse { + string uri = 1; + string path = 2; + uint32 size = 3; +} + +message GetFileRequest { + string uri = 1; + string path = 2; +} +message GetFileResponse { + string uri = 1; + string path = 2; + uint32 size = 3; + bytes data = 4; +} + +message BootFileRequest { + string uri = 1; + string path = 2; +} +message BootFileResponse { + string uri = 1; + string path = 2; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// info messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message FieldsRequest { + string uri = 1; + repeated Field fields = 2; +} +message FieldsResponse { + string uri = 1; + repeated Field fields = 2; + repeated string values = 3; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// NWA messages (emu-nwaccess protocol pass through) +////////////////////////////////////////////////////////////////////////////////////////////////// + +message NWACommandRequest { + string uri = 1; + // emu-nwaccess command name: + string command = 2; + // command arguments: + string args = 3; + // an optional binary argument: + optional bytes binaryArg = 4; +} +message NWACommandResponse { + message NWAASCIIItem { + map item = 1; + } + + string uri = 1; + repeated NWAASCIIItem asciiReply = 2; + optional bytes binaryReplay = 3; +} diff --git a/HintMachine.SNIConnector/app.config b/HintMachine.SNIConnector/app.config new file mode 100644 index 0000000..cf8e6ad --- /dev/null +++ b/HintMachine.SNIConnector/app.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HintMachine.SNIConnector/packages.config b/HintMachine.SNIConnector/packages.config new file mode 100644 index 0000000..00843f3 --- /dev/null +++ b/HintMachine.SNIConnector/packages.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HintMachine.SNIConnector/sni.proto b/HintMachine.SNIConnector/sni.proto new file mode 100644 index 0000000..e29de96 --- /dev/null +++ b/HintMachine.SNIConnector/sni.proto @@ -0,0 +1,425 @@ +syntax = "proto3"; + +option go_package = "github.com/alttpo/sni/protos/sni"; +option csharp_namespace = "SNI"; +option java_package = "com.github.alttpo.sni"; + +////////////////////////////////////////////////////////////////////////////////////////////////// +// services +////////////////////////////////////////////////////////////////////////////////////////////////// + +service Devices { + // detect and list devices currently connected to the system: + rpc ListDevices(DevicesRequest) returns (DevicesResponse) {} +} + +service DeviceControl { + // only available if DeviceCapability ResetSystem is present + rpc ResetSystem(ResetSystemRequest) returns (ResetSystemResponse) {} + + // only available if DeviceCapability ResetToMenu is present + rpc ResetToMenu(ResetToMenuRequest) returns (ResetToMenuResponse) {} + + // only available if DeviceCapability PauseUnpauseEmulation is present + rpc PauseUnpauseEmulation(PauseEmulationRequest) returns (PauseEmulationResponse) {} + + // only available if DeviceCapability PauseToggleEmulation is present + rpc PauseToggleEmulation(PauseToggleEmulationRequest) returns (PauseToggleEmulationResponse) {} +} + +service DeviceMemory { + // detect the current memory mapping for the given device by reading 00:FFB0 header: + rpc MappingDetect(DetectMemoryMappingRequest) returns (DetectMemoryMappingResponse) {} + + // read a single memory segment with a given size from the given device: + rpc SingleRead(SingleReadMemoryRequest) returns (SingleReadMemoryResponse) {} + // write a single memory segment with given data to the given device: + rpc SingleWrite(SingleWriteMemoryRequest) returns (SingleWriteMemoryResponse) {} + + // read multiple memory segments with given sizes from the given device: + rpc MultiRead(MultiReadMemoryRequest) returns (MultiReadMemoryResponse) {} + // write multiple memory segments with given data to the given device: + rpc MultiWrite(MultiWriteMemoryRequest) returns (MultiWriteMemoryResponse) {} + + // stream read multiple memory segments with given sizes from the given device: + rpc StreamRead(stream MultiReadMemoryRequest) returns (stream MultiReadMemoryResponse) {} + // stream write multiple memory segments with given data to the given device: + rpc StreamWrite(stream MultiWriteMemoryRequest) returns (stream MultiWriteMemoryResponse) {} +} + +service DeviceFilesystem { + rpc ReadDirectory(ReadDirectoryRequest) returns (ReadDirectoryResponse) {} + rpc MakeDirectory(MakeDirectoryRequest) returns (MakeDirectoryResponse) {} + rpc RemoveFile(RemoveFileRequest) returns (RemoveFileResponse) {} + rpc RenameFile(RenameFileRequest) returns (RenameFileResponse) {} + rpc PutFile(PutFileRequest) returns (PutFileResponse) {} + rpc GetFile(GetFileRequest) returns (GetFileResponse) {} + rpc BootFile(BootFileRequest) returns (BootFileResponse) {} +} + +service DeviceInfo { + rpc FetchFields(FieldsRequest) returns (FieldsResponse) {} +} + +service DeviceNWA { + rpc NWACommand(NWACommandRequest) returns (NWACommandResponse) {} +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// enums +////////////////////////////////////////////////////////////////////////////////////////////////// + +// address space used to interpret an address in: +enum AddressSpace { + // The default is the FX Pak Pro / SD2SNES's address space: + // $00_0000..$DF_FFFF = ROM contents, linearly mapped + // $E0_0000..$EF_FFFF = SRAM contents, linearly mapped + // $F5_0000..$F6_FFFF = WRAM contents, linearly mapped + // $F7_0000..$F7_FFFF = VRAM contents, linearly mapped + // $F8_0000..$F8_FFFF = APU contents, linearly mapped + // $F9_0000..$F9_01FF = CGRAM contents, linearly mapped + // $F9_0200..$F9_041F = OAM contents, linearly mapped + // $F9_0420..$F9_04FF = MISC contents, linearly mapped + // $F9_0500..$F9_06FF = PPUREG, linearly mapped + // $F9_0700..$F9_08FF = CPUREG, linearly mapped + // translated device address depends on device being talked to and its current MemoryMapping mode + FxPakPro = 0; // SNES + // The SNES's main A-bus; address depends on device's current MemoryMapping mode, e.g. LoROM, HiROM, ExHiROM, etc. + SnesABus = 1; + // Do not do any address translation; simply pass the raw address to the device as-is: + Raw = 2; +} + +// memory mapping mode of a SNES cart: +enum MemoryMapping { + Unknown = 0; + HiROM = 1; + LoROM = 2; + ExHiROM = 3; // (48-64Mbit) + SA1 = 4; + // TODO: BSX = 5; +} + +// capabilities of a device +enum DeviceCapability { + None = 0; + ReadMemory = 1; + WriteMemory = 2; + ExecuteASM = 3; + ResetSystem = 4; + PauseUnpauseEmulation = 5; + PauseToggleEmulation = 6; + ResetToMenu = 7; + FetchFields = 8; + + ReadDirectory = 10; + MakeDirectory = 11; + RemoveFile = 12; + RenameFile = 13; + PutFile = 14; + GetFile = 15; + BootFile = 16; + + NWACommand = 20; +} + +// fields to query from DeviceInfo.FetchFields +enum Field { + DeviceName = 0; + DeviceVersion = 1; + DeviceStatus = 2; + + CoreName = 20; + CoreVersion = 21; + CorePlatform = 22; + + RomFileName = 40; + RomHashType = 41; + RomHashValue = 42; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// devices messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message DevicesRequest { + // optional list of device kind filters + repeated string kinds = 1; + // TODO: repeated DeviceCapability capabilities; +} +message DevicesResponse { + message Device { + // URI that describes exactly how to connect to the device, e.g.: + // RetroArch: "ra://127.0.0.1:55355" + // FX Pak Pro: "fxpakpro://./dev/cu.usbmodemDEMO000000001" (MacOS) + // "fxpakpro://./COM4" (Windows) + // "fxpakpro://./dev/ttyACM0" (Linux) + // uri is used as the unique identifier of the device for clients to refer to + string uri = 1; + // friendly display name of the device + string displayName = 2; + // device kind, e.g. "fxpakpro", "retroarch", "lua" + string kind = 3; + // all device capabilities: + repeated DeviceCapability capabilities = 4; + // default address space for the device: + AddressSpace defaultAddressSpace = 5; + + // [DEPRECATED] console system supported, e.g. "snes", "n64" + // since devices can support multiple systems, it's better to fetch platform from DeviceInfo.FetchFields method + string system = 6 [deprecated = true]; + } + + repeated Device devices = 1; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// control messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message ResetSystemRequest { + string uri = 1; +} +message ResetSystemResponse { + string uri = 1; +} + +message ResetToMenuRequest { + string uri = 1; +} +message ResetToMenuResponse { + string uri = 1; +} + +message PauseEmulationRequest { + string uri = 1; + // true to pause emulation, false to unpause + bool paused = 2; +} +message PauseEmulationResponse { + string uri = 1; + bool paused = 2; +} + +message PauseToggleEmulationRequest { + string uri = 1; +} +message PauseToggleEmulationResponse { + string uri = 1; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// memory messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message DetectMemoryMappingRequest { + string uri = 1; + // optional fallback value to set in case detection fails for some reason + optional MemoryMapping fallbackMemoryMapping = 2; + // optional ROM header (from bus address $00:FFB0, at least $30 bytes long) to use for detection + // if not provided, the header will be read from the device + optional bytes romHeader00FFB0 = 3; +} +message DetectMemoryMappingResponse { + string uri = 1; + // the memory mapping mode detected + MemoryMapping memoryMapping = 2; + // true if confident we detected a mapping; false if using a fallback or default value + bool confidence = 3; + // the ROM header read from $00:FFB0, length is $50 bytes if server reads it, otherwise length of `romHeader00FFB0` from request + bytes romHeader00FFB0 = 4; +} + +message ReadMemoryRequest { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 4; + + uint32 size = 3; +} +message ReadMemoryResponse { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 6; + + // the address sent to the device and its space + uint32 deviceAddress = 3; + AddressSpace deviceAddressSpace = 4; + + bytes data = 5; +} +message WriteMemoryRequest { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 4; + + bytes data = 3; +} +message WriteMemoryResponse { + uint32 requestAddress = 1; + AddressSpace requestAddressSpace = 2; + MemoryMapping requestMemoryMapping = 6; + + uint32 deviceAddress = 3; + AddressSpace deviceAddressSpace = 4; + + uint32 size = 5; +} + +message SingleReadMemoryRequest { + string uri = 1; + ReadMemoryRequest request = 2; +} +message SingleReadMemoryResponse { + string uri = 1; + ReadMemoryResponse response = 2; +} + +message SingleWriteMemoryRequest { + string uri = 1; + WriteMemoryRequest request = 2; +} +message SingleWriteMemoryResponse { + string uri = 1; + WriteMemoryResponse response = 2; +} + +message MultiReadMemoryRequest { + string uri = 1; + repeated ReadMemoryRequest requests = 2; +} +message MultiReadMemoryResponse { + string uri = 1; + repeated ReadMemoryResponse responses = 2; +} + +message MultiWriteMemoryRequest { + string uri = 1; + repeated WriteMemoryRequest requests = 2; +} +message MultiWriteMemoryResponse { + string uri = 1; + repeated WriteMemoryResponse responses = 2; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// filesystem messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message ReadDirectoryRequest { + string uri = 1; + string path = 2; +} + +enum DirEntryType { + Directory = 0; + File = 1; +} + +message DirEntry { + string name = 1; + DirEntryType type = 2; +} + +message ReadDirectoryResponse { + string uri = 1; + string path = 2; + repeated DirEntry entries = 3; +} + +message MakeDirectoryRequest { + string uri = 1; + string path = 2; +} +message MakeDirectoryResponse { + string uri = 1; + string path = 2; +} + +message RemoveFileRequest { + string uri = 1; + string path = 2; +} +message RemoveFileResponse { + string uri = 1; + string path = 2; +} + +message RenameFileRequest { + string uri = 1; + string path = 2; + string newFilename = 3; +} +message RenameFileResponse { + string uri = 1; + string path = 2; + string newFilename = 3; +} + +message PutFileRequest { + string uri = 1; + string path = 2; + bytes data = 3; +} +message PutFileResponse { + string uri = 1; + string path = 2; + uint32 size = 3; +} + +message GetFileRequest { + string uri = 1; + string path = 2; +} +message GetFileResponse { + string uri = 1; + string path = 2; + uint32 size = 3; + bytes data = 4; +} + +message BootFileRequest { + string uri = 1; + string path = 2; +} +message BootFileResponse { + string uri = 1; + string path = 2; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// info messages +////////////////////////////////////////////////////////////////////////////////////////////////// + +message FieldsRequest { + string uri = 1; + repeated Field fields = 2; +} +message FieldsResponse { + string uri = 1; + repeated Field fields = 2; + repeated string values = 3; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// NWA messages (emu-nwaccess protocol pass through) +////////////////////////////////////////////////////////////////////////////////////////////////// + +message NWACommandRequest { + string uri = 1; + // emu-nwaccess command name: + string command = 2; + // command arguments: + string args = 3; + // an optional binary argument: + optional bytes binaryArg = 4; +} +message NWACommandResponse { + message NWAASCIIItem { + map item = 1; + } + + string uri = 1; + repeated NWAASCIIItem asciiReply = 2; + optional bytes binaryReplay = 3; +} diff --git a/HintMachine.sln b/HintMachine.sln index 389e340..7d5a1a4 100644 --- a/HintMachine.sln +++ b/HintMachine.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2003 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34031.279 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HintMachine", "HintMachine\HintMachine.csproj", "{F07DABDF-B962-4696-B9DA-5E18E6E83D56}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HintMachine.SNIConnector", "HintMachine.SNIConnector\HintMachine.SNIConnector.csproj", "{4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,18 @@ Global {F07DABDF-B962-4696-B9DA-5E18E6E83D56}.Release|x64.Build.0 = Release|x64 {F07DABDF-B962-4696-B9DA-5E18E6E83D56}.Release|x86.ActiveCfg = Release|x86 {F07DABDF-B962-4696-B9DA-5E18E6E83D56}.Release|x86.Build.0 = Release|x86 + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Debug|x64.ActiveCfg = Debug|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Debug|x64.Build.0 = Debug|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Debug|x86.ActiveCfg = Debug|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Debug|x86.Build.0 = Debug|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Release|Any CPU.Build.0 = Release|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Release|x64.ActiveCfg = Release|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Release|x64.Build.0 = Release|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Release|x86.ActiveCfg = Release|Any CPU + {4ED98A39-76AA-45C8-9BEF-EE24BC4BFBD2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/HintMachine/App.config b/HintMachine/App.config index 4bfa005..dd47e84 100644 --- a/HintMachine/App.config +++ b/HintMachine/App.config @@ -1,6 +1,30 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HintMachine/ComboBoxPrompt.xaml b/HintMachine/ComboBoxPrompt.xaml new file mode 100644 index 0000000..494d675 --- /dev/null +++ b/HintMachine/ComboBoxPrompt.xaml @@ -0,0 +1,19 @@ + + + + + + + +