2018-11-10 20:03:37 +11:00
<!DOCTYPE HTML>
< html lang = "en" class = "sidebar-visible no-js" >
< head >
<!-- Book generated using mdBook -->
< meta charset = "UTF-8" >
2018-11-18 11:14:42 +11:00
< title > Ch 0: Development Setup - Rust GBA Guide< / title >
2018-11-10 20:03:37 +11:00
< meta content = "text/html; charset=utf-8" http-equiv = "Content-Type" >
< meta name = "description" content = "" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< meta name = "theme-color" content = "#ffffff" / >
< link rel = "shortcut icon" href = "../favicon.png" >
< link rel = "stylesheet" href = "../css/variables.css" >
< link rel = "stylesheet" href = "../css/general.css" >
< link rel = "stylesheet" href = "../css/chrome.css" >
< link rel = "stylesheet" href = "../css/print.css" media = "print" >
<!-- Fonts -->
< link rel = "stylesheet" href = "../FontAwesome/css/font-awesome.css" >
< link href = "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel = "stylesheet" type = "text/css" >
< link href = "https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel = "stylesheet" type = "text/css" >
<!-- Highlight.js Stylesheets -->
< link rel = "stylesheet" href = "../highlight.css" >
< link rel = "stylesheet" href = "../tomorrow-night.css" >
< link rel = "stylesheet" href = "../ayu-highlight.css" >
<!-- Custom theme stylesheets -->
< / head >
< body class = "light" >
<!-- Provide site root to javascript -->
< script type = "text/javascript" > var path _to _root = "../" ; < / script >
<!-- Work around some values being stored in localStorage wrapped in quotes -->
< script type = "text/javascript" >
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') & & theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') & & sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
< / script >
<!-- Set the theme before any content is loaded, prevents flash -->
< script type = "text/javascript" >
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = 'light'; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
< / script >
<!-- Hide / unhide sidebar before it is displayed -->
< script type = "text/javascript" >
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
< / script >
< nav id = "sidebar" class = "sidebar" aria-label = "Table of contents" >
2018-11-22 17:00:59 +11:00
< ol class = "chapter" > < li > < a href = "../introduction.html" > < strong aria-hidden = "true" > 1.< / strong > Introduction< / a > < / li > < li > < a href = "../ch00/index.html" class = "active" > < strong aria-hidden = "true" > 2.< / strong > Ch 0: Development Setup< / a > < / li > < li > < a href = "../ch01/index.html" > < strong aria-hidden = "true" > 3.< / strong > Ch 1: Hello GBA< / a > < / li > < li > < ol class = "section" > < li > < a href = "../ch01/hello1.html" > < strong aria-hidden = "true" > 3.1.< / strong > hello1< / a > < / li > < li > < a href = "../ch01/volatile.html" > < strong aria-hidden = "true" > 3.2.< / strong > Volatile< / a > < / li > < li > < a href = "../ch01/io_registers.html" > < strong aria-hidden = "true" > 3.3.< / strong > IO Registers< / a > < / li > < li > < a href = "../ch01/the_display_control_register.html" > < strong aria-hidden = "true" > 3.4.< / strong > The Display Control Register< / a > < / li > < li > < a href = "../ch01/video_memory_intro.html" > < strong aria-hidden = "true" > 3.5.< / strong > Video Memory Intro< / a > < / li > < li > < a href = "../ch01/hello2.html" > < strong aria-hidden = "true" > 3.6.< / strong > hello2< / a > < / li > < / ol > < / li > < li > < a href = "../ch02/index.html" > < strong aria-hidden = "true" > 4.< / strong > Ch 2: User Input< / a > < / li > < li > < ol class = "section" > < li > < a href = "../ch02/the_key_input_register.html" > < strong aria-hidden = "true" > 4.1.< / strong > The Key Input Register< / a > < / li > < li > < a href = "../ch02/the_vcount_register.html" > < strong aria-hidden = "true" > 4.2.< / strong > The VCount Register< / a > < / li > < li > < a href = "../ch02/light_cycle.html" > < strong aria-hidden = "true" > 4.3.< / strong > light_cycle< / a > < / li > < / ol > < / li > < li > < a href = "../ch03/index.html" > < strong aria-hidden = "true" > 5.< / strong > Ch 3: Memory and Objects< / a > < / li > < li > < ol class = "section" > < li > < a href = "../ch03/gba_memory_mapping.html" > < strong aria-hidden = "true" > 5.1.< / strong > GBA Memory Mapping< / a > < / li > < li > < a href = "../ch03/tile_data.html" > < strong aria-hidden = "true" > 5.2.< / strong > Tile Data< / a > < / li > < li > < a href = "../ch03/regular_backgrounds.html" > < strong aria-hidden = "true" > 5.3.< / strong > Regular Backgrounds< / a > < / li > < li > < a href = "../ch03/regular_objects.html" > < strong aria-hidden = "true" > 5.4.< / strong > Regular Objects< / a > < / li > < li > < a href = "../ch03/gba_rng.html" > < strong aria-hidden = "true" > 5.5.< / strong > GBA RNG< / a > < / li > < li > < a href = "../ch03/memory_game.html" > < strong aria-hidden = "true" > 5.6.< / strong > memory_game< / a > < / li > < / ol > < / li > < / ol >
2018-11-10 20:03:37 +11:00
< / nav >
< div id = "page-wrapper" class = "page-wrapper" >
< div class = "page" >
< div id = "menu-bar" class = "menu-bar" >
< div id = "menu-bar-sticky-container" >
< div class = "left-buttons" >
< button id = "sidebar-toggle" class = "icon-button" type = "button" title = "Toggle Table of Contents" aria-label = "Toggle Table of Contents" aria-controls = "sidebar" >
< i class = "fa fa-bars" > < / i >
< / button >
< button id = "theme-toggle" class = "icon-button" type = "button" title = "Change theme" aria-label = "Change theme" aria-haspopup = "true" aria-expanded = "false" aria-controls = "theme-list" >
< i class = "fa fa-paint-brush" > < / i >
< / button >
< ul id = "theme-list" class = "theme-popup" aria-label = "Themes" role = "menu" >
< li role = "none" > < button role = "menuitem" class = "theme" id = "light" > Light < span class = "default" > (default)< / span > < / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "rust" > Rust< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "coal" > Coal< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "navy" > Navy< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "ayu" > Ayu< / button > < / li >
< / ul >
< button id = "search-toggle" class = "icon-button" type = "button" title = "Search. (Shortkey: s)" aria-label = "Toggle Searchbar" aria-expanded = "false" aria-keyshortcuts = "S" aria-controls = "searchbar" >
< i class = "fa fa-search" > < / i >
< / button >
< / div >
2018-11-18 11:14:42 +11:00
< h1 class = "menu-title" > Rust GBA Guide< / h1 >
2018-11-10 20:03:37 +11:00
< div class = "right-buttons" >
< a href = "../print.html" title = "Print this book" aria-label = "Print this book" >
< i id = "print-button" class = "fa fa-print" > < / i >
< / a >
< / div >
< / div >
< / div >
< div id = "search-wrapper" class = "hidden" >
< form id = "searchbar-outer" class = "searchbar-outer" >
< input type = "search" name = "search" id = "searchbar" name = "searchbar" placeholder = "Search this book ..." aria-controls = "searchresults-outer" aria-describedby = "searchresults-header" >
< / form >
< div id = "searchresults-outer" class = "searchresults-outer hidden" >
< div id = "searchresults-header" class = "searchresults-header" > < / div >
< ul id = "searchresults" >
< / ul >
< / div >
< / div >
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
< script type = "text/javascript" >
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
< / script >
< div id = "content" class = "content" >
< main >
< a class = "header" href = "#chapter-0-development-setup" id = "chapter-0-development-setup" > < h1 > Chapter 0: Development Setup< / h1 > < / a >
< p > 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.< / p >
2018-11-19 16:19:13 +11:00
< p > Once again, extra special thanks to < strong > Ketsuban< / strong > , who first dove into how to
make this all work with rust and then shared it with the world.< / p >
2018-11-10 20:03:37 +11:00
< a class = "header" href = "#per-system-setup" id = "per-system-setup" > < h2 > Per System Setup< / h2 > < / a >
2018-11-19 16:19:13 +11:00
< p > Obviously you need your computer to have a < a href = "https://rustup.rs/" > working rust
installation< / a > . 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 < code > rustup default nightly< / code > to set
nightly as the system wide default toolchain, or you can use a < a href = "https://github.com/rust-lang-nursery/rustup.rs#the-toolchain-file" > toolchain
2018-11-10 20:03:37 +11:00
file< / a > to use
2018-11-19 16:19:13 +11:00
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 < code > rust-src< / code > component so that
< code > cargo-xbuild< / code > will be able to compile the core crate for us in a bit, so run
< code > rustup component add rust-src< / code > .< / p >
< p > Next, you need < a href = "https://devkitpro.org/wiki/Getting_Started" > devkitpro< / a > . They've
got a graphical installer for Windows that runs nicely, and I guess < code > pacman< / code >
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 < code > arm-none-eabi< / code > target,
and we'll also be using some of their tools that are specific to GBA
development, so < em > even if< / em > you already have the right binutils for whatever
reason, you'll still want devkitpro for the < code > gbafix< / code > utility.< / p >
2018-11-10 20:03:37 +11:00
< ul >
< li > On Windows you'll want something like < code > C:\devkitpro\devkitARM\bin< / code > and
< code > C:\devkitpro\tools\bin< / code > to be < a href = "https://stackoverflow.com/q/44272416/455232" > added to your
PATH< / a > , depending on where you
installed it to and such.< / li >
2018-11-21 18:18:34 +11:00
< li > On Linux you can use pacman to get it, and the default install puts the stuff
in < code > /opt/devkitpro/devkitARM/bin< / code > and < code > /opt/devkitpro/tools/bin< / code > . If you need
help you can look in our repository's
< a href = "https://github.com/rust-console/gba/blob/master/.travis.yml" > .travis.yml< / a >
file to see exactly what our CI does.< / li >
2018-11-10 20:03:37 +11:00
< / ul >
< p > Finally, you'll need < code > cargo-xbuild< / code > . Just run < code > cargo install cargo-xbuild< / code > and
cargo will figure it all out for you.< / p >
< a class = "header" href = "#per-project-setup" id = "per-project-setup" > < h2 > Per Project Setup< / h2 > < / a >
2018-11-19 16:19:13 +11:00
< p > 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
< a href = "https://github.com/rust-console/gba" > rust-console/gba repo< / a > .< / p >
2018-11-10 20:03:37 +11:00
< ul >
2018-11-19 16:19:13 +11:00
< li > < code > thumbv4-none-agb.json< / code > describes the overall GBA to cargo-xbuild (and LLVM)
so it knows what to do. Technically the GBA is < code > thumbv4-none-eabi< / code > , but we
change the < code > eabi< / code > to < code > agb< / code > so that we can distinguish it from other < code > eabi< / code >
devices when using < code > cfg< / code > flags.< / li >
2018-11-10 20:03:37 +11:00
< li > < code > crt0.s< / code > 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
< code > crt0.o< / code > file before it can actually be used, but we'll cover that below.< / li >
2018-11-19 16:19:13 +11:00
< li > < code > linker.ld< / code > 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 < code > crt0.o< / code > file with our compiled rust code.< / li >
2018-11-10 20:03:37 +11:00
< / ul >
< a class = "header" href = "#compiling" id = "compiling" > < h2 > Compiling< / h2 > < / a >
2018-11-14 04:56:57 +11:00
< p > The next steps only work once you've got some source code to build. If you need
a quick test, copy the < code > hello1.rs< / code > file from our examples directory in the
repository.< / p >
2018-11-10 20:03:37 +11:00
< p > Once you've got something to build, you perform the following steps:< / p >
< ul >
< li >
< p > < code > arm-none-eabi-as crt0.s -o crt0.o< / code > < / p >
< ul >
< li > This builds your text format < code > crt0.s< / code > file into object format < code > crt0.o< / code > . You
don't need to perform it every time, only when < code > crt0.s< / code > changes, but you
might as well do it every time so that you never forget to because it's a
practically instant operation.< / li >
< / ul >
< / li >
< li >
2018-11-11 17:39:26 +11:00
< p > < code > cargo xbuild --target thumbv4-none-agb.json< / code > < / p >
2018-11-10 20:03:37 +11:00
< ul >
< li > This builds your Rust source. It accepts < em > most of< / em > the normal options, such
as < code > --release< / code > , and options, such as < code > --bin foo< / code > or < code > --examples< / code > , that you'd
expect < code > cargo< / code > to accept.< / li >
< li > You < strong > can not< / strong > build and run tests this way, because they require < code > std< / code > ,
2018-11-19 16:19:13 +11:00
which the GBA doesn't have. If you want you can still run some of your
project's tests with < code > cargo test --lib< / code > 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 < code > examples/< / code > directory and then run the demo in an emulator
and see if it does what you expect.< / li >
2018-11-10 20:03:37 +11:00
< li > The file extension is important. < code > cargo xbuild< / code > 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.< / li >
< / ul >
< / li >
< / ul >
< p > 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
2018-11-11 18:25:26 +11:00
build. Specifically, < a href = "https://mgba.io/2018/09/24/mgba-0.7-beta1/" > mgba 0.7 beta
2018-11-10 20:03:37 +11:00
1< / a > can do it, and perhaps other
emulators can also do it.< / p >
< p > 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.< / p >
< ul >
< li >
2018-11-11 17:39:26 +11:00
< p > < code > arm-none-eabi-objcopy -O binary target/thumbv4-none-agb/MODE/BIN_NAME target/ROM_NAME.gba< / code > < / p >
2018-11-10 20:03:37 +11:00
< ul >
< li > This will perform an < a href = "https://linux.die.net/man/1/objcopy" > objcopy< / a > on our
program. Here I've named the program < code > arm-none-eabi-objcopy< / code > , which is what
devkitpro calls their version of < code > objcopy< / code > 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.< / li >
< li > As you can see from reading the man page, the < code > -O binary< / code > option takes our
lovely ELF file with symbols and all that and strips it down to basically a
bare memory dump of the program.< / li >
< li > The next argument is the input file. You might not be familiar with how
< code > cargo< / code > arranges stuff in the < code > target/< / code > directory, and between RLS and
< code > cargo doc< / code > and stuff it gets kinda crowded, so it goes like this:
< ul >
< li > Since our program was built for a non-local target, first we've got a
2018-11-11 17:39:26 +11:00
directory named for that target, < code > thumbv4-none-agb/< / code > < / li >
2018-11-10 20:03:37 +11:00
< li > Next, the " MODE" is either < code > debug/< / code > or < code > release/< / code > , depending on if we had
the < code > --release< / code > flag included. You'll probably only be packing release
mode programs all the way into GBA roms, but it works with either mode.< / li >
< li > Finally, the name of the program. If your program is something out of the
project's < code > src/bin/< / code > then it'll be that file's name, or whatever name you
configured for the bin in the < code > Cargo.toml< / code > file. If your program is
something out of the project's < code > examples/< / code > directory there will be a
similar < code > examples/< / code > sub-directory first, and then the example's name.< / li >
< / ul >
< / li >
< li > The final argument is the output of the < code > objcopy< / code > , which I suggest putting
at just the top level of the < code > target/< / code > directory. Really it could go
anywhere, but if you're using git then it's likely that your < code > .gitignore< / code >
file is already setup to exclude everything in < code > target/< / code > , so this makes sure
that your intermediate game builds don't get checked into your git.< / li >
< / ul >
< / li >
< li >
< p > < code > gbafix target/ROM_NAME.gba< / code > < / p >
< ul >
< li > The < code > gbafix< / code > tool also comes from devkitpro. The GBA is very picky about a
ROM's format, and < code > gbafix< / code > patches the ROM's header and such so that it'll
work right. Unlike < code > objcopy< / code > , 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.< / li >
< / ul >
< / li >
< / ul >
< p > And you're finally done!< / p >
2018-11-18 11:14:42 +11:00
< p > 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 < code > Makefile.toml< / code > which runs
using the < a href = "https://github.com/sagiegurari/cargo-make" > cargo-make< / a > plugin. It's
not really the best plugin, but it's what's available.< / p >
2018-11-10 20:03:37 +11:00
< / main >
< nav class = "nav-wrapper" aria-label = "Page navigation" >
<!-- Mobile navigation buttons -->
< a rel = "prev" href = "../introduction.html" class = "mobile-nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
< i class = "fa fa-angle-left" > < / i >
< / a >
2018-11-15 13:53:21 +11:00
< a rel = "next" href = "../ch01/index.html" class = "mobile-nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
2018-11-10 20:03:37 +11:00
< i class = "fa fa-angle-right" > < / i >
< / a >
< div style = "clear: both" > < / div >
< / nav >
< / div >
< / div >
< nav class = "nav-wide-wrapper" aria-label = "Page navigation" >
< a href = "../introduction.html" class = "nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
< i class = "fa fa-angle-left" > < / i >
< / a >
2018-11-15 13:53:21 +11:00
< a href = "../ch01/index.html" class = "nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
2018-11-10 20:03:37 +11:00
< i class = "fa fa-angle-right" > < / i >
< / a >
< / nav >
< / div >
< script src = "../elasticlunr.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../mark.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../searcher.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../clipboard.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../highlight.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../book.js" type = "text/javascript" charset = "utf-8" > < / script >
<!-- Custom JS scripts -->
< / body >
< / html >