mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-26 04:01:31 +11:00
143 lines
7.9 KiB
Markdown
143 lines
7.9 KiB
Markdown
# Chapter 0: Development Setup
|
|
|
|
Before you can build a GBA game you'll have to follow some special steps to
|
|
setup the development environment. Perhaps unfortunately, there's enough detail
|
|
here to warrant a mini-chapter all on its own.
|
|
|
|
Once again, extra special thanks to **Ketsuban**, who first dove into how to
|
|
make this all work with rust and then shared it with the world.
|
|
|
|
## Per System Setup
|
|
|
|
Obviously you need your computer to have a [working rust
|
|
installation](https://rustup.rs/). However, you'll also need to ensure that
|
|
you're using a nightly toolchain (we will need it for inline assembly, among
|
|
other potential useful features). You can run `rustup default nightly` to set
|
|
nightly as the system wide default toolchain, or you can use a [toolchain
|
|
file](https://github.com/rust-lang-nursery/rustup.rs#the-toolchain-file) to use
|
|
nightly just on a specific project, but either way we'll be assuming the use of
|
|
nightly from now on. You'll also need the `rust-src` component so that
|
|
`cargo-xbuild` will be able to compile the core crate for us in a bit, so run
|
|
`rustup component add rust-src`.
|
|
|
|
Next, you need [devkitpro](https://devkitpro.org/wiki/Getting_Started). They've
|
|
got a graphical installer for Windows that runs nicely, and I guess `pacman`
|
|
support on Linux (I'm on Windows so I haven't tried the Linux install myself).
|
|
We'll be using a few of their general binutils for the `arm-none-eabi` target,
|
|
and we'll also be using some of their tools that are specific to GBA
|
|
development, so _even if_ you already have the right binutils for whatever
|
|
reason, you'll still want devkitpro for the `gbafix` utility.
|
|
|
|
* On Windows you'll want something like `C:\devkitpro\devkitARM\bin` and
|
|
`C:\devkitpro\tools\bin` to be [added to your
|
|
PATH](https://stackoverflow.com/q/44272416/455232), depending on where you
|
|
installed it to and such.
|
|
* On Linux you can use pacman to get it, and the default install puts the stuff
|
|
in `/opt/devkitpro/devkitARM/bin` and `/opt/devkitpro/tools/bin`. If you need
|
|
help you can look in our repository's
|
|
[.travis.yml](https://github.com/rust-console/gba/blob/master/.travis.yml)
|
|
file to see exactly what our CI does.
|
|
|
|
Finally, you'll need `cargo-xbuild`. Just run `cargo install cargo-xbuild` and
|
|
cargo will figure it all out for you.
|
|
|
|
## Per Project Setup
|
|
|
|
Once the system wide tools are ready, you'll need some particular files each
|
|
time you want to start a new project. You can find them in the root of the
|
|
[rust-console/gba repo](https://github.com/rust-console/gba).
|
|
|
|
* `thumbv4-none-agb.json` describes the overall GBA to cargo-xbuild (and LLVM)
|
|
so it knows what to do. Technically the GBA is `thumbv4-none-eabi`, but we
|
|
change the `eabi` to `agb` so that we can distinguish it from other `eabi`
|
|
devices when using `cfg` flags.
|
|
* `crt0.s` describes some ASM startup stuff. If you have more ASM to place here
|
|
later on this is where you can put it. You also need to build it into a
|
|
`crt0.o` file before it can actually be used, but we'll cover that below.
|
|
* `linker.ld` tells the linker all the critical info about the layout
|
|
expectations that the GBA has about our program, and that it should also
|
|
include the `crt0.o` file with our compiled rust code.
|
|
|
|
## Compiling
|
|
|
|
The next steps only work once you've got some source code to build. If you need
|
|
a quick test, copy the `hello1.rs` file from our examples directory in the
|
|
repository.
|
|
|
|
Once you've got something to build, you perform the following steps:
|
|
|
|
* `arm-none-eabi-as crt0.s -o crt0.o`
|
|
* This builds your text format `crt0.s` file into object format `crt0.o`. You
|
|
don't need to perform it every time, only when `crt0.s` changes, but you
|
|
might as well do it every time so that you never forget to because it's a
|
|
practically instant operation.
|
|
|
|
* `cargo xbuild --target thumbv4-none-agb.json`
|
|
* This builds your Rust source. It accepts _most of_ the normal options, such
|
|
as `--release`, and options, such as `--bin foo` or `--examples`, that you'd
|
|
expect `cargo` to accept.
|
|
* You **can not** build and run tests this way, because they require `std`,
|
|
which the GBA doesn't have. If you want you can still run some of your
|
|
project's tests with `cargo test --lib` or similar, but that builds for your
|
|
local machine, so anything specific to the GBA (such as reading and writing
|
|
registers) won't be testable that way. If you want to isolate and try out
|
|
some piece code running on the GBA you'll unfortunately have to make a demo
|
|
for it in your `examples/` directory and then run the demo in an emulator
|
|
and see if it does what you expect.
|
|
* The file extension is important. `cargo xbuild` takes it as a flag to
|
|
compile dependencies with the same sysroot, so you can include crates
|
|
normally. Well, creates that work in the GBA's limited environment, but you
|
|
get the idea.
|
|
|
|
At this point you have an ELF binary that some emulators can execute directly.
|
|
This is helpful because it'll have debug symbols and all that, assuming a debug
|
|
build. Specifically, [mgba 0.7 beta
|
|
1](https://mgba.io/2018/09/24/mgba-0.7-beta1/) can do it, and perhaps other
|
|
emulators can also do it.
|
|
|
|
However, if you want a "real" ROM that works in all emulators and that you could
|
|
transfer to a flash cart there's a little more to do.
|
|
|
|
* `arm-none-eabi-objcopy -O binary target/thumbv4-none-agb/MODE/BIN_NAME target/ROM_NAME.gba`
|
|
* This will perform an [objcopy](https://linux.die.net/man/1/objcopy) on our
|
|
program. Here I've named the program `arm-none-eabi-objcopy`, which is what
|
|
devkitpro calls their version of `objcopy` that's specific to the GBA in the
|
|
Windows install. If the program isn't found under that name, have a look in
|
|
your installation directory to see if it's under a slightly different name
|
|
or something.
|
|
* As you can see from reading the man page, the `-O binary` option takes our
|
|
lovely ELF file with symbols and all that and strips it down to basically a
|
|
bare memory dump of the program.
|
|
* The next argument is the input file. You might not be familiar with how
|
|
`cargo` arranges stuff in the `target/` directory, and between RLS and
|
|
`cargo doc` and stuff it gets kinda crowded, so it goes like this:
|
|
* Since our program was built for a non-local target, first we've got a
|
|
directory named for that target, `thumbv4-none-agb/`
|
|
* Next, the "MODE" is either `debug/` or `release/`, depending on if we had
|
|
the `--release` flag included. You'll probably only be packing release
|
|
mode programs all the way into GBA roms, but it works with either mode.
|
|
* Finally, the name of the program. If your program is something out of the
|
|
project's `src/bin/` then it'll be that file's name, or whatever name you
|
|
configured for the bin in the `Cargo.toml` file. If your program is
|
|
something out of the project's `examples/` directory there will be a
|
|
similar `examples/` sub-directory first, and then the example's name.
|
|
* The final argument is the output of the `objcopy`, which I suggest putting
|
|
at just the top level of the `target/` directory. Really it could go
|
|
anywhere, but if you're using git then it's likely that your `.gitignore`
|
|
file is already setup to exclude everything in `target/`, so this makes sure
|
|
that your intermediate game builds don't get checked into your git.
|
|
|
|
* `gbafix target/ROM_NAME.gba`
|
|
* The `gbafix` tool also comes from devkitpro. The GBA is very picky about a
|
|
ROM's format, and `gbafix` patches the ROM's header and such so that it'll
|
|
work right. Unlike `objcopy`, this tool is custom built for GBA development,
|
|
so it works just perfectly without any arguments beyond the file name. The
|
|
ROM is patched in place, so we don't even need to specify a new destination.
|
|
|
|
And you're finally done!
|
|
|
|
Of course, you probably want to make a script for all that, but it's up to you.
|
|
On our own project we have it mostly set up within a `Makefile.toml` which runs
|
|
using the [cargo-make](https://github.com/sagiegurari/cargo-make) plugin. It's
|
|
not really the best plugin, but it's what's available.
|