ReSharp3DS is an project that runs C# code on the Nintendo 3DS using nanoCLR / nanoFramework.
The project uses a C++ 3DS homebrew application to load C# assemblies compiled as .pe files, then executes them through nanoCLR.
Done (Click to expand)
- Initialize nanoCLR on Nintendo 3DS
- Load
mscorlib.peandapp.pefrom SD card - Execute C#
Program.Main() - Call native C++ functions from C# using
InternalCall - Basic Console API (
Clear,Write,WriteLine) - Input support (
Start,Select) - Full Button Mapping (A, B, X, Y, D-Pad, L, R)
- Runtime management (
Runtime.Yield(), static state preservation) - Validate on Citra & Real Hardware
- Fix screen flickering by avoiding full redraw every tick
- Graphics & Audio API
- Filesystem support
- Automatic native method binding instead of index-based mapping
- Runtime launcher with folder explorer
- Launch
.pefiles from folders - Automatic
mscorlib.perestore - Time API
- Random API
- Touch API
- CirclePad API
- Screen constants
- App API
- SystemInfo API
- Save API
-
Graphics.DrawBitmapBMP support -
Audio.SetSfxVolume -
Audio.SetMusicVolume -
Audio.IsPlaying -
Audio.IsMusicPlaying
To be implemented (Click to expand)
- Expanded Console API (bool, float, better formatting)
- Better error reporting for C# exceptions
- Better SystemInfo values on real hardware
Recommended SD card layout for current runtime versions:
SD:/
├── 3ds/
│ └── ReSharp3DS.3dsx
└── ReSharp3DS/
├── bin/
│ └── mscorlib.pe
├── app.pe
├── apps/
│ └── TestApp/
│ ├── manifest.json
│ ├── app.pe
│ └── assets/
│ ├── sprite.bmp
│ └── sound.wav
└── logs/
├── crash.txt
├── clr-panic.txt
└── <AppName>.logThe runtime dependency is expected at:
sdmc:/ReSharp3DS/bin/mscorlib.peThe launcher scans:
sdmc:/ReSharp3DS/and displays folders and .pe applications. mscorlib.pe is ignored by the launcher.
Current runtime versions include a file browser with folder, .pe, manifest, and touch support.
D-Pad Up / Down Move selection
A Open folder or launch selected .pe app
X Refresh current folder
START Exit launcher
Touch row Select/open folder or launch selected app
Touch right edge Quick scrollIf a .pe file is declared in manifest.json, the launcher can display the manifest name, author, and version instead of the raw .pe filename.
Current runtime versions no longer use the old runtime auto-update flow in this module.
The remaining network helper is focused on runtime file restore and downloads, especially restoring the nanoFramework core library when it is missing.
Available helper responsibilities:
FileExists
DirectoryExists
EnsureDirectory
DownloadFileThe runtime dependency can be restored from:
https://host.saysaa.fr/3ds/ReSharp3DS/dependencies/mscorlib.peThe expected local path is:
sdmc:/ReSharp3DS/bin/mscorlib.peIf automatic restore fails, copy mscorlib.pe manually to that path.
Current runtime and SDK versions include APIs for console output, input, touch, runtime control, timing, graphics, audio, files, directories, saves, app information, and system information.
Available APIs include:
Console API
Debug API
Input API
Runtime API
Time API
Random API
Touch API
CirclePad API
Screen constants
App API
SystemInfo API
Graphics API
Audio API
File API
Directory API
Save APINewer SDK helpers include:
Button
ScreenTarget
Vector2
Rect
Timer
GameApp
Input.IsHeld(Button)
Input.IsPressed(Button)
Input.CirclePad()
Touch.Position()
Runtime.ReturnToLauncher()
Graphics.SetTarget(ScreenTarget.Top/Bottom)
Graphics.DrawSpriteTransparent(...)
Save.Exists(...)
Save.Delete(...)
Save.SetBool(...)
Save.GetBool(...)int ms = Time.Milliseconds();
int seconds = Time.Seconds();Random.Seed(1234);
int value = Random.Next(0, 100);bool pressed = Touch.IsPressed();
int x = Touch.X();
int y = Touch.Y();int x = Input.CirclePadX();
int y = Input.CirclePadY();Screen.TopWidth
Screen.TopHeight
Screen.BottomWidth
Screen.BottomHeightstring path = App.GetPath();
string dir = App.GetDirectory();
string name = App.GetName();bool isNew3DS = SystemInfo.IsNew3DS();
int battery = SystemInfo.GetBatteryLevel();
int memory = SystemInfo.GetFreeMemory();Some values may return fallback values depending on hardware support.
Current fallback behavior:
GetBatteryLevel() returns -1 if unavailable
GetFreeMemory() returns 0 if unavailableAvailable methods include:
Graphics.Clear(int color);
Graphics.DrawPixel(int x, int y, int color);
Graphics.FillRect(int x, int y, int width, int height, int color);
Graphics.DrawRect(int x, int y, int width, int height, int color);
Graphics.DrawLine(int x1, int y1, int x2, int y2, int color);
Graphics.DrawCircle(int x, int y, int radius, int color);
Graphics.FillCircle(int x, int y, int radius, int color);
Graphics.DrawText(int x, int y, string text, int color);
Graphics.DrawBitmap(string path, int x, int y);
Graphics.DrawSprite(string path, int x, int y);
Graphics.DrawSprite(string path, int x, int y, int width, int height);
Graphics.DrawSpriteTransparent(string path, int x, int y, int transparentColor);
Graphics.SetTarget(ScreenTarget.Top);
Graphics.SetTarget(ScreenTarget.Bottom);
Graphics.Present();Graphics.DrawBitmap, Graphics.DrawSprite, and Graphics.DrawSpriteTransparent support simple BMP files.
Recommended format:
BMP
24-bit or 32-bit
uncompressedAvailable methods include:
Audio.Init();
Audio.Beep(int frequency, int durationMs);
Audio.Stop();
Audio.PlayWav(string path);
Audio.Loop(string path);
Audio.StopMusic();
Audio.SetVolume(int volume);
Audio.SetSfxVolume(int volume);
Audio.SetMusicVolume(int volume);
Audio.IsPlaying();
Audio.IsMusicPlaying();WAV files should be:
PCM WAV
16-bit
44100 Hz or 22050 Hz
mono or stereoFor real hardware, DSP audio must be available on the SD card.
Save.SetInt("score", 1200);
int score = Save.GetInt("score", 0);
Save.SetString("name", "Player");
string name = Save.GetString("name", "Default");
Save.SetBool("unlocked", true);
bool unlocked = Save.GetBool("unlocked", false);
bool exists = Save.Exists("score");
Save.Delete("score");File.Exists(string path);
File.WriteAllText(string path, string text);
File.ReadAllText(string path);
File.Delete(string path);
Directory.Exists(string path);
Directory.Create(string path);
Directory.Delete(string path);Paths can be relative to the running .pe application folder.
If a file is missing or incorrectly placed, the program will display an error:
[FATAL] app load failed
Make sure the ReSharp3DS folder is at the root of the SD card, not inside the /3ds/ folder.
Check that:
sdmc:/ReSharp3DS/bin/mscorlib.peexists and matches the nanoFramework version used by the SDK.
Check that your .pe files are inside:
sdmc:/ReSharp3DS/or inside a subfolder.
Check that the file is:
BMP
24-bit or 32-bit
uncompressedAlso check that the path is relative to the running .pe file.
Make sure DSP has been dumped correctly and is available on the SD card.
- Added
manifest.jsonsupport in the launcher. - Added manifest-based
.pedisplay names. - Added app metadata support through manifest fields:
nameauthorversionentrydescription
- Added selected app metadata display in the launcher:
Author: ...Version: ...
- Added touchscreen support in the launcher.
- Added improved launcher file browsing and app/folder sorting.
- Added
runtime_net.cppandruntime_net.hfor runtime network/file helpers. - Added helper functions for dependency restore:
FileExistsDirectoryExistsEnsureDirectoryDownloadFile
- Added basic crash log and crash screen infrastructure.
- Added runtime log paths:
sdmc:/ReSharp3DS/logs/crash.txtsdmc:/ReSharp3DS/logs/clr-panic.txtsdmc:/ReSharp3DS/logs/<AppName>.log
- Added centralized input snapshot logic for held buttons, pressed-once buttons, touch, and Circle Pad.
- Added graphics target support for top and bottom screen rendering.
- Added transparent sprite drawing support.
- The launcher now uses
manifest.jsonto rename the.peentry declared by the manifestentryfield. - Replaced the old updater-style code with a smaller runtime network helper.
- Runtime network code is now focused on dependency restore, especially
mscorlib.pe. - Input handling now avoids repeated
hidScanInput()calls from individual native functions.
- Removed the old
UpdateInfo/CheckForUpdatestyle update flow from the launcher side. - Removed runtime auto-update behavior from this part of the project.
- Fixed manifest display behavior so a
.pefile can be displayed with the manifest name. - Fixed author/version metadata rendering placement.
- Fixed generated C++ string literal issues caused by broken
\nescaping. - Fixed duplicate
copy_json_string_value(...)definition during manifest integration. - Fixed invalid
\0handling caused by embedded null characters in generated source.
- Added native binding for returning to the launcher:
RuntimeReturnToLauncher
- Added native debug log binding:
DebugLogFile
- Added native graphics target binding:
GraphicsSetTarget
- Added native transparent sprite binding:
GraphicsDrawSpriteTransparent
- Added native support for top/bottom screen drawing target selection.
- Added native debug file logging support.
- Added native system info improvements for battery level, free memory, and New 3DS detection.
- Native input calls now read from a cached input snapshot.
- Native graphics code can now target different screens.
- Native debug logging is prepared to write logs into the ReSharp3DS logs folder.
- Improved pressed-once input stability using frame-based state.
- Fixed native-side string literal issues generated during integration.
- Added C# helper enum:
Button
- Added C# screen target enum:
ScreenTarget
- Added C# helper structs:
Vector2Rect
- Added C# utility class:
Timer
- Added C# app base class:
GameApp
- Added input helpers:
Input.IsHeld(Button button)Input.IsPressed(Button button)Input.CirclePad()
- Added touch helper:
Touch.Position()
- Added runtime helper:
Runtime.ReturnToLauncher()
- Added debug helpers:
Debug.Log(...)Debug.Warn(...)Debug.Error(...)Debug.LogInt(...)
- Added graphics helpers:
Graphics.SetTarget(ScreenTarget.Top)Graphics.SetTarget(ScreenTarget.Bottom)Graphics.DrawSpriteTransparent(...)
- Added save helpers:
Save.Exists(...)Save.Delete(...)Save.SetBool(...)Save.GetBool(...)
- Improved SDK usability for C# app developers.
- Made input code cleaner with button enums.
- Made touch handling cleaner with a
Vector2helper. - Made save data easier to use with boolean helpers.
- Fixed
UI.DrawProgressBar(...)to avoid invalid or negative fill sizes. - Documented that apps must not compile two copies of
ReSharp3DS.cs.