├── .cargo └── config ├── .gitignore ├── 3ds.json ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── README.md ├── Xargo.toml └── src └── main.rs /.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "3ds" 3 | 4 | [target.3ds] 5 | linker = "arm-none-eabi-gcc" 6 | rustflags = [ 7 | "-Clink-arg=-specs=3dsx.specs", 8 | "-Clink-arg=-mfloat-abi=hard", 9 | "-Clink-arg=-march=armv6k", 10 | "-Clink-arg=-mtune=mpcore", 11 | "-Clink-arg=-mfpu=vfp", 12 | "-Clink-arg=-mtp=soft", 13 | "-Clink-arg=-z", 14 | "-Clink-arg=muldefs", 15 | "-Clink-arg=-lgcc", 16 | "-Clink-arg=-lsysbase", 17 | "-Clink-arg=-lc" 18 | ] 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | dist/ 3 | 4 | *.rlib 5 | 6 | *.o 7 | *.ll 8 | *.elf 9 | *.3dsx 10 | *.smdh 11 | -------------------------------------------------------------------------------- /3ds.json: -------------------------------------------------------------------------------- 1 | { 2 | "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", 3 | "llvm-target": "arm-none-eabihf", 4 | "linker": "arm-none-eabi-gcc", 5 | "ar": "arm-none-eabi-ar", 6 | "target-endian": "little", 7 | "target-pointer-width": "32", 8 | "target-c-int-width": "32", 9 | "target-family": "unix", 10 | "arch": "arm", 11 | "os": "horizon", 12 | "env": "newlib", 13 | "cpu": "mpcore", 14 | "features": "+vfp2", 15 | "relocation-model": "static", 16 | "executables": true, 17 | "exe-suffix": ".elf", 18 | "linker-flavor": "gcc" 19 | } 20 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "bitflags" 3 | version = "1.0.3" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "ctru-rs" 8 | version = "0.7.0" 9 | source = "git+https://github.com/rust3ds/ctru-rs#15cb3c1e91842a68a8e50e1e1a42aefab13cc25e" 10 | dependencies = [ 11 | "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 12 | "ctru-sys 0.4.0 (git+https://github.com/rust3ds/ctru-rs)", 13 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 14 | "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 15 | ] 16 | 17 | [[package]] 18 | name = "ctru-sys" 19 | version = "0.4.0" 20 | source = "git+https://github.com/rust3ds/ctru-rs#15cb3c1e91842a68a8e50e1e1a42aefab13cc25e" 21 | dependencies = [ 22 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 23 | ] 24 | 25 | [[package]] 26 | name = "libc" 27 | version = "0.2.43" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | 30 | [[package]] 31 | name = "rust3ds-template" 32 | version = "0.1.0" 33 | dependencies = [ 34 | "ctru-rs 0.7.0 (git+https://github.com/rust3ds/ctru-rs)", 35 | ] 36 | 37 | [[package]] 38 | name = "widestring" 39 | version = "0.2.2" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | 42 | [metadata] 43 | "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" 44 | "checksum ctru-rs 0.7.0 (git+https://github.com/rust3ds/ctru-rs)" = "" 45 | "checksum ctru-sys 0.4.0 (git+https://github.com/rust3ds/ctru-rs)" = "" 46 | "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" 47 | "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" 48 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "Nintendo 3DS project template" 3 | name = "rust3ds-template" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | ctru-rs = { git = "https://github.com/rust3ds/ctru-rs" } 8 | 9 | [profile.dev] 10 | lto = true 11 | 12 | [profile.release] 13 | lto = true 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Project info 2 | CRATE_NAME := rust3ds-template 3 | PROG_NAME := Rust 3DS Template 4 | PROG_DESC := Rust, a modern, safe systems language. 5 | PROG_AUTHOR := You 6 | PROG_ICON := $(DEVKITPRO)/libctru/default_icon.png 7 | 8 | 3DSXTOOL := $(DEVKITPRO)/tools/bin/3dsxtool 9 | SMDHTOOL := $(DEVKITPRO)/tools/bin/smdhtool 10 | 11 | export CC_3ds := $(DEVKITARM)/bin/arm-none-eabi-gcc 12 | export TARGET_CFLAGS := -specs=3dsx.specs -mfloat-abi=hard -march=armv6k -mtune=mpcore \ 13 | -mfpu=vfp -mtp=soft 14 | 15 | .PHONY: all clean $(CRATE_NAME) dist test send target/3ds/release/$(CRATE_NAME).elf 16 | 17 | all: $(CRATE_NAME) 18 | 19 | target/3ds/release/$(CRATE_NAME).elf: 20 | RUST_TARGET_PATH=$(shell pwd) xargo build --release 21 | 22 | target/3ds/release/$(CRATE_NAME).smdh: 23 | $(SMDHTOOL) --create "${PROG_NAME}" "${PROG_DESC}" "${PROG_AUTHOR}" "${PROG_ICON}" target/3ds/release/$(CRATE_NAME).smdh 24 | 25 | target/3ds/release/$(CRATE_NAME).3dsx: target/3ds/release/$(CRATE_NAME).elf target/3ds/release/$(CRATE_NAME).smdh 26 | $(3DSXTOOL) target/3ds/release/$(CRATE_NAME).elf target/3ds/release/$(CRATE_NAME).3dsx --smdh=target/3ds/release/$(CRATE_NAME).smdh 27 | 28 | $(CRATE_NAME): target/3ds/release/$(CRATE_NAME).3dsx 29 | 30 | dist: $(CRATE_NAME) 31 | mkdir -p dist/$(CRATE_NAME) 32 | cp target/3ds/release/$(CRATE_NAME).elf dist/$(CRATE_NAME) 33 | cp target/3ds/release/$(CRATE_NAME).3dsx dist/$(CRATE_NAME) 34 | cp $(PROG_ICON) dist/$(CRATE_NAME)/$(CRATE_NAME).png 35 | 36 | test: $(CRATE_NAME) 37 | citra target/3ds/release/$(CRATE_NAME).elf 38 | 39 | send: $(CRATE_NAME) 40 | 3dslink target/3ds/release/$(CRATE_NAME).3dsx 41 | 42 | clean: 43 | rm -rf target 44 | rm -rf dist 45 | 46 | nuke: clean 47 | rm -rf ~/.xargo 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | This repository has been deprecated in favour of the new example projects present within the new ctru-rs version of the Rust3DS toolchain. Also, the build instructions here documented aren't valid for our new projects. For more information about the new tools and libraries, check [ctru-rs](https://github.com/rust3ds/ctru-rs). 3 | 4 | # Rust 3DS Template 5 | 6 | An example project demonstrating how to compile and run Rust programs on the Nintendo 3DS using [ctru-rs](https://github.com/rust3ds/ctru-rs). 7 | 8 | ## Requirements 9 | 10 | A nightly version of Rust is required to use this project. If you don't have Rust installed or don't have a nightly compiler, check out [rustup.rs](https://rustup.rs). 11 | 12 | Next, you will need [Xargo](https://github.com/japaric/xargo) to facilitate cross-compilation to the 3DS. 13 | 14 | Finally, you will need the most recent version of [devkitARM](http://sourceforge.net/projects/devkitpro/files/devkitARM/). 15 | 16 | ### Preparation of the requirements 17 | 18 | #### Installing Rust 19 | 20 | If you don't have Rust installed (macOS & Linux): 21 | 22 | `$ curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly` 23 | 24 | If you have already installed rustup: 25 | 26 | `$ rustup default nightly` 27 | 28 | #### Installing Xargo 29 | 30 | `$ rustup component add rust-src` 31 | `$ cargo install xargo` 32 | 33 | #### Installing devkitARM 34 | 35 | As of this writing, the current version of devkitARM is r48 and the current version of libctru is 1.5.0. 36 | 37 | A detailed tutorial on how to set up devkitARM can be found on the [3dbrew wiki](http://3dbrew.org/wiki/Setting_up_Development_Environment). 38 | 39 | On macOS & Linux, devkitARM requires two environment variables to be set: 40 | 41 | * `$DEVKITPRO` = `/path/to/devkitPro/` (usually `/opt/devkitpro/`) 42 | * `$DEVKITARM` = `$DEVKITPRO/devkitARM` 43 | 44 | ## Usage 45 | 46 | Use the included `Makefile` to build your program. Under the hood, `make` calls `xargo` to create a custom sysroot containing cross-compiled versions of the Rust core libraries, as well as a limited version of the Rust standard library. `xargo` caches the sysroot after it has been built for the first time. Once the sysroot is in place, a Homebrew Launcher-compatible `3dsx` version of your program will be generated. 47 | 48 | Running `make` will build your program in release mode. Running `make test` will open your program in the `Citra` emulator if you have it installed. Running `make send` will send your program to your 3DS via `3dslink` (press Y in the Homebrew Launcher to receive the program). 49 | 50 | ## Troubleshooting 51 | 52 | >I get an error saying that the `3ds` target can't be found when I run `xargo build` 53 | 54 | Recent versions of Rust require you to set the `$RUST_TARGET_PATH` env variable to the directory where your target spec is located. The Makefile does this automatically when you invoke it, or you can manually set the variable yourself. 55 | 56 | >`std` or `` is failing to build 57 | 58 | Nightly Rust moves fast and things tend to break a lot. If you want to use a known-working nightly, try the one listed in the [travis config file](https://github.com/rust3ds/ctru-rs/blob/master/.travis.yml#L3-L4) for `ctru-rs`. And feel free to file an issue detailing the error at the repo too! 59 | 60 | >I'm running my homebrew in Citra and I don't see any error message if my program panics 61 | 62 | You need to enable Debug SVC output in Citra's logger. There are two configuration files in `~/.config/citra-emu`: `sdl2-config.ini` and `qt-config.ini`. The first is for the normal `citra` executable and the second for `citra-qt`. Add `Debug.Emulated:Debug` to the `log_filter` variable for whichever version you intend to use. The Makefile calls the sdl2 version by default when running `make test`. 63 | 64 | >I got `hello world` working, but now what? Is there documentation for how to do anything else? 65 | 66 | Not quite yet, but we're working on that. Feel free to browse the list of [example programs](https://github.com/rust3ds/ctru-rs/tree/master/examples/src/bin) in the meantime. 67 | 68 | You should also become familiar with [libctru's documentation](http://smealum.github.io/ctrulib/) if you aren't already. It will help you understand what the current `ctru-rs` APIs are doing, plus you can use raw `libctru` functions directly via the `ctru-sys` crate if you want access to anything not yet exposed in `ctru-rs`. 69 | -------------------------------------------------------------------------------- /Xargo.toml: -------------------------------------------------------------------------------- 1 | [dependencies.alloc] 2 | [dependencies.panic_abort] 3 | [dependencies.panic_unwind] 4 | 5 | [dependencies.std] 6 | git = "https://github.com/rust3ds/ctru-rs" 7 | stage = 1 8 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate ctru; 2 | 3 | use ctru::gfx::Gfx; 4 | use ctru::console::Console; 5 | use ctru::services::apt::Apt; 6 | use ctru::services::hid::{Hid, KeyPad}; 7 | 8 | fn main() { 9 | let apt = Apt::init().unwrap(); 10 | let hid = Hid::init().unwrap(); 11 | let gfx = Gfx::default(); 12 | let _console = Console::default(); 13 | 14 | println!("Hello, world!"); 15 | 16 | println!("\x1b[29;16HPress Start to exit"); 17 | 18 | while apt.main_loop() { 19 | gfx.flush_buffers(); 20 | gfx.swap_buffers(); 21 | gfx.wait_for_vblank(); 22 | 23 | hid.scan_input(); 24 | if hid.keys_down().contains(KeyPad::KEY_START) { 25 | break; 26 | } 27 | } 28 | } 29 | --------------------------------------------------------------------------------