![]() |
VOOZH | about |
dotnet add package MattEqualsCoder.SnesConnectorLibrary --version 1.0.4
NuGet\Install-Package MattEqualsCoder.SnesConnectorLibrary -Version 1.0.4
<PackageReference Include="MattEqualsCoder.SnesConnectorLibrary" Version="1.0.4" />
<PackageVersion Include="MattEqualsCoder.SnesConnectorLibrary" Version="1.0.4" />Directory.Packages.props
<PackageReference Include="MattEqualsCoder.SnesConnectorLibrary" />Project file
paket add MattEqualsCoder.SnesConnectorLibrary --version 1.0.4
#r "nuget: MattEqualsCoder.SnesConnectorLibrary, 1.0.4"
#:package MattEqualsCoder.SnesConnectorLibrary@1.0.4
#addin nuget:?package=MattEqualsCoder.SnesConnectorLibrary&version=1.0.4Install as a Cake Addin
#tool nuget:?package=MattEqualsCoder.SnesConnectorLibrary&version=1.0.4Install as a Cake Tool
The SNES Connector Library is a C# based nuget package intended to facilitate communicating with the various types of methods of retrieving and updating data in SNES emulators and hardware.
The following was tested as part of the creation of this library:
Add the MattEqualsCoder.SNESConnectorLibrary nuget package to your project: https://www.nuget.org/packages/MattEqualsCoder.SnesConnectorLibrary/0.1.0
You can instantiate the ISnesConnectorLibrary in two ways:
When building your services, you can use the following code to add all of the SNES Connector Library services. This is recommended if you use the Microsoft Extensions Logging so that it'll print info and exception statements when connecting and disconnecting.
var serviceCollection = new ServiceCollection()
.AddSnesConnectorServices();
var services = serviceCollection.BuildServiceProvider();
var snesConnectorService = services.GetRequiredService<ISnesConnectorService>();
You can also call the following function, but it will not include any logging:
var snesConnectorService = ISnesConnectorService.CreateService();
Connecting is as simple as calling the SNES Connector Service's Connect method. You can either pass it just the SnesConnectorType desired, or pass in an SnesConnectorSettings object. By using the SnesConnectorSettings object, you can allow people to change the IP addresses used by the connectors. This can be useful for users who may have it changed for whatever reason (like me!)
The types of connectors are as follows. Only one connector can be used as a single time, but any or all of them can be used as options for your users. Note that there are multiple types of Lua connectors because each one works slightly differently and uses different ports. If a user is using multiple Lua scripts simultaneously (say for a tracker and crowd control), then it's imperitive that they use different ports. Because of this, there are multiple Lua script connectors available.
The SNES Connector Library includes Lua scripts to be used for the connector type SnesConnectorType.Lua. You will need to make those Lua scripts available and direct the user to them to use for snes9x-rr and BizHawk. You can create the Lua scripts using the Snes Connector Service CreateLuaScriptsFolder method, like the following:
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SnesLua")
_snesConnectorService.CreateLuaScriptsFolder(path);
There are two functions for making memory requests, depending on the need. All requests are asynchronous and added to a queue for processing at certain intervals. This is done due to the limitations of some connectors of not working well with multiple requests being sent simultaneously, requiring only request to be pending at a time.
You can make a single memory retrieval or update request using the SNES Connector Service MakeMemoryRequest method.
// Makes a single request to retrieve 2 bytes from the WRAM location 0x7E09C4
_snesConnectorService.MakeMemoryRequest(new SnesSingleMemoryRequest()
{
MemoryRequestType = SnesMemoryRequestType.RetrieveMemory,
SnesMemoryDomain = SnesMemoryDomain.ConsoleRAM,
AddressFormat = AddressFormat.Snes9x,
SniMemoryMapping = MemoryMapping.ExHiRom,
Address = 0x7E09C4,
Length = 2,
OnResponse = (data, prevData) =>
{
Console.WriteLine("Data Received");
}
});
// Makes a single request to update the WRAM location 0x7E09C2
_snesConnectorService.MakeMemoryRequest(new SnesSingleMemoryRequest()
{
MemoryRequestType = SnesMemoryRequestType.UpdateMemory,
SnesMemoryDomain = SnesMemoryDomain.ConsoleRAM,
AddressFormat = AddressFormat.Snes9x,
SniMemoryMapping = MemoryMapping.ExHiRom,
Address = 0x7E09C2,
Data = new byte[] { 0xFF, 0xA0 }
});
The fields are as follows:
You can make recurring requests that will retrieve data at certain intervals using the SNES Connector Service AddRecurringRequest method. Recurring requests cannot update data.
// Retrieve whether the player is currently in Super Metroid or A Link to the Past from SRAM
var request = _snesConnectorService.AddRecurringMemoryRequest(new SnesRecurringMemoryRequest()
{
MemoryRequestType = SnesMemoryRequestType.RetrieveMemory,
SnesMemoryDomain = SnesMemoryDomain.CartridgeSave,
AddressFormat = AddressFormat.Snes9x,
SniMemoryMapping = MemoryMapping.ExHiRom,
Address = 0xA173FE,
Length = 2,
FrequencySeconds = 0.5,
RespondOnChangeOnly = true,
OnResponse = (data, prevData) =>
{
Model.CurrentGame = data.ReadUInt8(0) == 0xFF ? "Super Metroid" : "A Link to the Past";
},
});
The fields are the same as SnesSingleMemoryRequest, only without the RequestType and with the following fields added:
If requests ever need to be removed and not called anymore, you can call the SNES Connector Service RemoveRecurringRequest method, passing in the request object passed into (or returned by) the AddRecurringRequest method.
Note that if you make multiple recurring requests for the same memory address, to prevent duplicate calls out to the connector, the calls are combined into a single request to the connector. For the frequency, it'll use the time of the fastest request and it'll grab the bytes needed for the largest request. However, the callbacks are still only called when they are applicable.
There are three different address formats that can be used which are outlined below. When creating requests, you can specify any of these as long as the address locations match the expected ranges. The SNES Connector Service will automatically adjust it to match what is required for the particular connector.
| Memory Type | Addresses |
|---|---|
| ConsoleRAM (WRAM) | 0x7E0000 - 0x7FFFFF |
| CartridgeSave (SRAM) | 0xA06000, 0xA07000, 0xA16000, 0xA17000 ... 0x11F7FFF |
| Rom | 0x000000 - 0xDFFFFF |
| Memory Type | Addresses |
|---|---|
| ConsoleRAM (WRAM) | 0x000000 - 0x01FFFF |
| CartridgeSave (SRAM) | 0x000000 - 0x0FFFFF |
| Rom | 0x000000 - 0xDFFFFF |
| Memory Type | Addresses |
|---|---|
| ConsoleRAM (WRAM) | 0xF50000 - 0xF6FFFF |
| CartridgeSave (SRAM) | 0xE00000 - 0xEFFFFF |
| Rom | 0x000000 - 0xDFFFFF |
The SnesData object is a wrapper around the bytes returned from a retrieval request. It's got multiple functions which can be called to retrieve and check the data that was received.
// Scan for roms
snesConnectorService.GetFileList(new SnesFileListRequest()
{
Path = "",
Recursive = true,
Filter = file => file.Name.EndsWith(".sfc", StringComparison.OrdinalIgnoreCase) || file.Name.EndsWith(".smc", StringComparison.OrdinalIgnoreCase),
OnResponse = (files) =>
{
Model.Roms = files.Select(x => x.FullPath).ToList();
Model.SelectedRom = Model.Roms.First();
Model.Status = $"{Model.Roms.Count} roms found";
}
});
// Boot rom file
snesConnectorService.BootRom(new SnesBootRomRequest()
{
Path = "/roms/MyRom.smc",
OnComplete = () =>
{
Console.WriteLine("Booted rom!")
}
});
// Uploads MyRom.smc to the root of the SNES
snesConnectorService.UploadFile(new SnesUploadFileRequest()
{
LocalFilePath = "C:\MyRom.smc",
TargetFilePath = "/roms/MyRom.smc"
OnComplete = () =>
{
Console.WriteLine("Upload of MyRom complete");
}
});
// Deletes MyRom.smc from the root of the SNES
snesConnectorService.DeleteFile(new SnesDeleteFileRequest()
{
Path = "/roms/MyRom.smc",
OnComplete = () =>
{
Console.WriteLine("MyRom deleted");
}
});
The SNES Connector App is a very simple cross platform UI app that can be used as an example of how to request and update different types of memory. This was made with the SMZ3 Cas' fork in mind, but I believe it should work with mainline SMZ3 as well. It'll display the rom game title, determine whether you're in Metroid or Zelda, and get either Link's or Samus's X, Y coordinates depending on the current game. There are a couple buttons that can be used to either refill your hearts/energy or give you 20 rupee items.
As of this moment, there are a few known limitations for some connectors due to downstream services.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 1 NuGet packages that depend on MattEqualsCoder.SnesConnectorLibrary:
| Package | Downloads |
|---|---|
|
MattEqualsCoder.MSURandomizer.Library
Library for detecting, selecting, and randomizing MSUs for various games and randomizers. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.4 | 580 | 1/17/2026 |
| 1.0.3 | 144 | 1/16/2026 |
| 1.0.2 | 134 | 1/13/2026 |
| 1.0.1 | 881 | 3/11/2025 |
| 1.0.0 | 172 | 1/8/2025 |
| 1.0.0-beta.3 | 105 | 1/6/2025 |
| 1.0.0-beta.2 | 110 | 1/3/2025 |
| 0.9.9 | 769 | 12/21/2024 |
| 0.9.8 | 847 | 6/22/2024 |
| 0.9.8-rc.1 | 435 | 4/30/2024 |
| 0.9.7 | 261 | 4/24/2024 |
| 0.9.6 | 256 | 4/4/2024 |
| 0.9.5 | 214 | 4/3/2024 |
| 0.9.4 | 198 | 3/23/2024 |
| 0.9.3 | 216 | 3/13/2024 |
| 0.9.2 | 283 | 3/11/2024 |
| 0.9.1 | 211 | 3/11/2024 |
| 0.9.0 | 194 | 3/7/2024 |
| 0.1.7 | 193 | 4/2/2024 |
| 0.1.6 | 204 | 2/19/2024 |