diff --git a/HintMachine.SNI/Default.cs b/HintMachine.SNI/Default.cs
new file mode 100644
index 0000000..b9ba69d
--- /dev/null
+++ b/HintMachine.SNI/Default.cs
@@ -0,0 +1,7 @@
+namespace HintMachine.SNIConnection
+{
+ public class Default
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/HintMachine.SNI/HintMachine.SNIConnection.csproj b/HintMachine.SNI/HintMachine.SNIConnection.csproj
new file mode 100644
index 0000000..2efb9ae
--- /dev/null
+++ b/HintMachine.SNI/HintMachine.SNIConnection.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
diff --git a/HintMachine.SNI/Protos/sni.proto b/HintMachine.SNI/Protos/sni.proto
new file mode 100644
index 0000000..e29de96
--- /dev/null
+++ b/HintMachine.SNI/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.sln b/HintMachine.sln
index 409125d..13c4023 100644
--- a/HintMachine.sln
+++ b/HintMachine.sln
@@ -4,6 +4,8 @@ VisualStudioVersion = 17.7.34003.232
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HintMachine", "HintMachine\HintMachine.csproj", "{F07DABDF-B962-4696-B9DA-5E18E6E83D56}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HintMachine.SNIConnection", "HintMachine.SNI\HintMachine.SNIConnection.csproj", "{62A06E61-0F83-458F-B7E4-1A6A60B1EA89}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -14,6 +16,10 @@ Global
{F07DABDF-B962-4696-B9DA-5E18E6E83D56}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F07DABDF-B962-4696-B9DA-5E18E6E83D56}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F07DABDF-B962-4696-B9DA-5E18E6E83D56}.Release|Any CPU.Build.0 = Release|Any CPU
+ {62A06E61-0F83-458F-B7E4-1A6A60B1EA89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {62A06E61-0F83-458F-B7E4-1A6A60B1EA89}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {62A06E61-0F83-458F-B7E4-1A6A60B1EA89}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {62A06E61-0F83-458F-B7E4-1A6A60B1EA89}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/HintMachine/App.config b/HintMachine/App.config
index 3e895f9..2b8342b 100644
--- a/HintMachine/App.config
+++ b/HintMachine/App.config
@@ -6,10 +6,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HintMachine/Assets/covers/sanrio_world_smash_ball.png b/HintMachine/Assets/covers/sanrio_world_smash_ball.png
new file mode 100644
index 0000000..47b2d8b
Binary files /dev/null and b/HintMachine/Assets/covers/sanrio_world_smash_ball.png differ
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HintMachine/ComboBoxPrompt.xaml.cs b/HintMachine/ComboBoxPrompt.xaml.cs
new file mode 100644
index 0000000..4b5deb3
--- /dev/null
+++ b/HintMachine/ComboBoxPrompt.xaml.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace HintMachine
+{
+ ///
+ /// Interaction logic for ComboBoxPrompt.xaml
+ ///
+ public partial class ComboBoxPrompt : Window
+ {
+ public ComboBoxPrompt(string prompt, List comboOptions)
+ {
+ InitializeComponent();
+ Prompt.Content = prompt;
+ ComboMain.ItemsSource = comboOptions;
+ }
+
+ private void Confirmed(object sender, RoutedEventArgs e)
+ {
+ DialogResult = true;
+ Close();
+ }
+ }
+}
diff --git a/HintMachine/HintMachine.csproj b/HintMachine/HintMachine.csproj
index 6e72184..c3e6ca9 100644
--- a/HintMachine/HintMachine.csproj
+++ b/HintMachine/HintMachine.csproj
@@ -215,6 +215,9 @@
PreserveNewest
+
+ PreserveNewest
+
@@ -225,6 +228,9 @@
+
+
+