diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..62eb617 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "gba" +version = "0.0.1" +authors = ["Lokathor ", "Ketsuban"] +edition = "2018" +license = "Apache2" + +[dependencies] + +[profile.release] +lto = true +panic = "abort" diff --git a/README.md b/README.md index ca17a2d..df33a49 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,57 @@ +[![License:Apache2](https://img.shields.io/badge/License-Apache2-green.svg)](https://www.apache.org/licenses/LICENSE-2.0) + # gba + A crate that helps you make GBA games + +# First Time Setup + +[ketsuban](https://github.com/ketsuban) is the wizard who explained to me how to +do this stuff. + +1) Install `devkitpro`. They have a graphical installer for Windows, or you can + use pacman or whatever for linux things I guess. The goal here, among other + things, is to have a `binutils` setup that's targeting `arm-none-eabi`. We'll + also use some of their tools that are specific to GBA development so if you + for some reason already have the appropriate `binutils` then you probably + still want devkitpro. + * On Windows you'll want something like `C:\devkitpro\devkitARM\bin` and + `C:\devkitpro\tools\bin` to be added to your PATH. I'm not sure on the + directories for other systems. If you know then file a PR with the info. + +2) Next we use `cargo install cargo-xbuild` to get that all setup. + +3) Create a binary project. We're going to want nightly rust for this, so if you + don't already have it set to default to nightly you should [set that + up](https://github.com/rust-lang-nursery/rustup.rs#the-toolchain-file) for + this project. + +4) Clone this repo. It has an appropriate `main.rs` that will draw three test + dots as well as other support files: + * crt0.s + * linker.ld + * thumbv4-none-eabi.json + * build.rs + +5) Run `arm-none-eabi-as crt0.s -o crt0.o` to build the `crt0.s` into a `crt0.o` + file. You could theoretically to it only when `crt0.s` changes, but in out + `build.bat` file it's set to simply run every single time because it's a + cheap enough operation. + +6) Build with `cargo xbuild --target thumbv4-none-eabi.json` + * The file extension is significant, and `cargo xbuild` takes it as a flag to + compile dependencies with the same sysroot, so you can include crates + normally. Well, crates that can run inside a GBA at least (Which means they + have to be `no_std`, and even `no_alloc`). + * This generates an ELF binary that some emulators can run directly (which is + helpful because it has debug symbols). + +7) Also you can patch up the output to be a "real" ROM file: + * `arm-none-eabi-objcopy -O binary target/thumbv4-none-eabi/debug/gbatest target/output.gba` + * `gbafix target/output.gba` + +8) Alternately, you can use the provided `build.bat` file (or write a similar + `build.sh` file of course), which does all four steps above. + +9) Time to read the [Tonc](https://www.coranac.com/tonc/text/toc.htm) tutorial + and convert all the C code you see into rust code. diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..554a6e1 --- /dev/null +++ b/build.bat @@ -0,0 +1,32 @@ +@echo off +REM It could work to only rebuild the `crt0.o` file when `crt0.s` actually +REM changes, but it's actually a super cheap operation so we'll just do it +REM every single time to avoid any mix ups. +@echo on + +arm-none-eabi-as crt0.s -o crt0.o + +@echo off +REM This builds our program for the GBA. Note that the extension here is +REM important, because it causes all crates that we might import to also +REM use the correct target. +@echo on + +cargo xbuild --target thumbv4-none-eabi.json + +@echo off +REM Some emulators can use cargo's output directly (which is cool, because then +REM you can keep debug symbols and stuff), but to make a "real" ROM we have to +REM also use the devkitpro tools to patch up the file a bit. +@echo on + +arm-none-eabi-objcopy -O binary target/thumbv4-none-eabi/debug/main target/output.gba +gbafix target/output.gba + +@echo off +REM Now all the same for release mode too! +@echo on + +cargo xbuild --target thumbv4-none-eabi.json --release +arm-none-eabi-objcopy -O binary target/thumbv4-none-eabi/release/main target/output-release.gba +gbafix target/output-release.gba diff --git a/crt0.s b/crt0.s new file mode 100644 index 0000000..9b06b47 --- /dev/null +++ b/crt0.s @@ -0,0 +1,34 @@ + .arm +__start: + b .Linit + + @ ROM header will be filled in by gbafix + .fill 188, 1, 0 + +.Linit: + @ set IRQ stack pointer + mov r0, #0x12 + msr CPSR_cf, r0 + ldr sp, =0x3007fa0 + + @ set user stack pointer + mov r0, #0x1f + msr CPSR_cf, r0 + ldr sp, =0x3007f00 + + @ copy .data section to IWRAM + ldr r0, =__data_lma @ source address + ldr r1, =__data_start @ destination address + ldr r3, =__data_end + sub r2, r3, r1 + beq .Lskip @ don't try to copy an empty .data section + add r2, #3 + mov r2, r2, asr #2 @ length (in words) + add r2, #0x04000000 @ copy by words + swi 0xb0000 + +.Lskip: + @ jump to user code + ldr r0, =main + bx r0 + .pool diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..5736a16 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,10 @@ +error_on_line_overflow = false +fn_args_density = "Compressed" +reorder_imported_names = true +reorder_imports = true +reorder_imports_in_group = true +use_try_shorthand = true +write_mode = "Overwrite" +tab_spaces = 2 +max_width = 150 +color = "Never" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0c9ac1a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +#![no_std] diff --git a/thumbv4-none-eabi.json b/thumbv4-none-eabi.json new file mode 100644 index 0000000..c6cdd94 --- /dev/null +++ b/thumbv4-none-eabi.json @@ -0,0 +1,34 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "win64", + "sysv64" + ], + "arch": "arm", + "atomic-cas": false, + "cpu": "arm7tdmi", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "emit-debug-gdb-scripts": false, + "env": "", + "executables": true, + "features": "+soft-float,+strict-align", + "linker": "arm-none-eabi-ld", + "linker-flavor": "ld", + "linker-is-gnu": true, + "llvm-target": "thumbv4-none-eabi", + "os": "none", + "panic-strategy": "abort", + "pre-link-args": { + "ld": [ + "-Tlinker.ld" + ] + }, + "relocation-model": "static", + "target-c-int-width": "32", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} \ No newline at end of file