mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-27 12:41:30 +11:00
348 lines
21 KiB
HTML
348 lines
21 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="sidebar-visible no-js">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>Ch 0: Development Setup - Rust GBA Guide</title>
|
|
<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">
|
|
<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_prng.html"><strong aria-hidden="true">5.5.</strong> GBA PRNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
|
|
</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>
|
|
|
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
|
|
|
<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>
|
|
<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>
|
|
<a class="header" href="#per-system-setup" id="per-system-setup"><h2>Per System Setup</h2></a>
|
|
<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
|
|
file</a> 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 <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>
|
|
<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>
|
|
<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>
|
|
</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>
|
|
<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>
|
|
<ul>
|
|
<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>
|
|
<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>
|
|
<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>
|
|
</ul>
|
|
<a class="header" href="#compiling" id="compiling"><h2>Compiling</h2></a>
|
|
<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>
|
|
<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>
|
|
<p><code>cargo xbuild --target thumbv4-none-agb.json</code></p>
|
|
<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>,
|
|
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>
|
|
<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
|
|
build. Specifically, <a href="https://mgba.io/2018/09/24/mgba-0.7-beta1/">mgba 0.7 beta
|
|
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>
|
|
<p><code>arm-none-eabi-objcopy -O binary target/thumbv4-none-agb/MODE/BIN_NAME target/ROM_NAME.gba</code></p>
|
|
<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
|
|
directory named for that target, <code>thumbv4-none-agb/</code></li>
|
|
<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>
|
|
<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>
|
|
|
|
</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>
|
|
|
|
|
|
|
|
<a rel="next" href="../ch01/index.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<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>
|
|
|
|
|
|
|
|
<a href="../ch01/index.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<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>
|