mirror of
https://github.com/italicsjenga/gba.git
synced 2025-01-11 11:31:31 +11:00
476 lines
26 KiB
HTML
476 lines
26 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="sidebar-visible no-js">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>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="development-setup.html"><strong aria-hidden="true">1.</strong> Development Setup</a></li><li><a href="gba-asm.html"><strong aria-hidden="true">2.</strong> GBA Assembly</a></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="#development-setup" id="development-setup"><h1>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.</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>Once all the tools are in place, there's particular steps that you need to
|
|
compile the project. For these to work you'll need some source code to compile.
|
|
Unlike with other things, an empty main file and/or an empty lib file will cause
|
|
a total build failure, because we'll need a
|
|
<a href="https://rust-embedded.github.io/book/intro/no-std.html">no_std</a> build, and rust
|
|
defaults to builds that use the standard library. The next section has a minimal
|
|
example file you can use (along with explanation), but we'll describe the build
|
|
steps here.</p>
|
|
<ul>
|
|
<li>
|
|
<p><code>arm-none-eabi-as crt0.s -o target/crt0.o</code></p>
|
|
<ul>
|
|
<li>This builds your text format <code>crt0.s</code> file into object format <code>crt0.o</code>
|
|
that's placed in the <code>target/</code> directory. Note that if the <code>target/</code>
|
|
directory doesn't exist yet it will fail, so you have to make the directory
|
|
if it's not there. You don't need to rebuild <code>crt0.s</code> every single time,
|
|
only when it changes, but you might as well throw a line to do it every time
|
|
into your build script so that you never forget because it's a practically
|
|
instant operation anyway.</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! It will work if you forget it, but <code>cargo xbuild</code> takes the inclusion of the extension as a flag to also compile
|
|
dependencies with the same sysroot, so you can include other crates in your
|
|
build. Well, crates 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
|
|
(more on that later). However, if you want a "real" ROM that works in all
|
|
emulators and that you could transfer to a flash cart to play on real hardware
|
|
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 <em>finally</em> 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.</p>
|
|
<a class="header" href="#checking-your-setup" id="checking-your-setup"><h2>Checking Your Setup</h2></a>
|
|
<p>As I said, you need some source code to compile just to check that your
|
|
compilation pipeline is working. Here's a sample file that just puts three dots
|
|
on the screen without depending on any crates or anything at all.</p>
|
|
<p><code>hello_magic.rs</code>:</p>
|
|
<pre><pre class="playpen"><code class="language-rust">#![no_std]
|
|
#![feature(start)]
|
|
|
|
#[panic_handler]
|
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
|
loop {}
|
|
}
|
|
|
|
#[start]
|
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
|
unsafe {
|
|
(0x400_0000 as *mut u16).write_volatile(0x0403);
|
|
(0x600_0000 as *mut u16).offset(120 + 80 * 240).write_volatile(0x001F);
|
|
(0x600_0000 as *mut u16).offset(136 + 80 * 240).write_volatile(0x03E0);
|
|
(0x600_0000 as *mut u16).offset(120 + 96 * 240).write_volatile(0x7C00);
|
|
loop {}
|
|
}
|
|
}
|
|
</code></pre></pre>
|
|
<p>Throw that into your project skeleton, build the program, and give it a run. You
|
|
should see a red, green, and blue dot close-ish to the middle of the screen. If
|
|
you don't, something <em>already</em> went wrong. Double check things, phone a friend,
|
|
write your senators, try asking <code>Lokathor</code> or <code>Ketsuban</code> on the <a href="https://discordapp.com/invite/aVESxV8">Rust Community
|
|
Discord</a>, until you're eventually able to
|
|
get your three dots going.</p>
|
|
<p>Of course, I'm sure you want to know why those numbers are the numbers to use.
|
|
Well that's what the whole rest of the book is about!</p>
|
|
<a class="header" href="#gba-assembly" id="gba-assembly"><h1>GBA Assembly</h1></a>
|
|
<p>On the GBA sometimes you just end up using assembly. Not a whole lot, but
|
|
sometimes. Accordingly, you should know how assembly works on the GBA.</p>
|
|
<ul>
|
|
<li>
|
|
<p>The <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0210c/index.html">ARM Infocenter:
|
|
ARM7TDMI</a>
|
|
is the basic authority for reference information. The GBA has a CPU with the
|
|
<code>ARMv4</code> ISA, the <code>ARMv4T</code> variant, and specifically the <code>ARM7TDMI</code>
|
|
microarchitecture. Someone at ARM decided that having both <code>ARM#</code> and <code>ARMv#</code>
|
|
was a good way to <a href="https://en.wikichip.org/wiki/arm/versions">version things</a>,
|
|
even when the numbers don't match, and the rest of us have been sad ever
|
|
since. The link there will take you to the correct book within the big pile of
|
|
ARM books available within the ARM Infocenter. Note that there is also a <a href="http://infocenter.arm.com/help/topic/com.arm.doc.ddi0210c/DDI0210B.pdf">PDF
|
|
Version</a>
|
|
of the documentation available, if you'd like that.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <a href="https://problemkaputt.de/gbatek.htm#armcpuoverview">GBATek: ARM CPU
|
|
Overview</a> also has quite a
|
|
bit of info. Most of it is somewhat a duplication of what you'd find in the
|
|
ARM Infocenter reference manual, but it's also somewhat specialized towards
|
|
the GBA's specifics. It's in the usual, uh, "sparse" style that GBATEK is
|
|
written in, so I wouldn't suggest that read it first.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <a href="https://rust.godbolt.org/z/ndCnk3">Compiler Explorer</a> can be used to
|
|
quickly look at assembly output of your Rust code. That link there will load
|
|
up an essentially blank <code>no_std</code> file with <code>opt-level=3</code> set and targeting
|
|
<code>thumbv6m-none-eabi</code>. That's <em>not</em> the same as the GBA (it's two ISA revisions
|
|
later, ARMv6 instead of ARMv4), but it's the closest CPU target that ships
|
|
with rustc, so it's the closest you can get with the compiler explorer
|
|
website. If you're very dedicated I suppose you could setup a <a href="https://github.com/mattgodbolt/compiler-explorer#running-a-local-instance">local
|
|
instance</a>
|
|
of compiler explorer and then add the extra target definition and so on, but
|
|
that's <em>probably</em> overkill.</p>
|
|
</li>
|
|
</ul>
|
|
<a class="header" href="#arm-and-thumb" id="arm-and-thumb"><h2>ARM and THUMB</h2></a>
|
|
<p>The "T" part in <code>ARMv4T</code> and <code>ARM7TDMI</code> means "Thumb". An ARM chip that supports
|
|
Thumb mode has two different instruction sets instead of just one. The chip can
|
|
run in ARM mode with 32-bit instructions, or it can run in THUMB mode with
|
|
16-bit instructions. Apparently these modes are sometimes called <code>a32</code> and <code>t32</code>
|
|
in a more modern context, but I will stick with ARM and THUMB because that's
|
|
what other GBA references use (particularly GBATEK), and it's probably best to
|
|
be more in agreement with them than with stuff for Raspberry Pi programming or
|
|
whatever other modern ARM thing.</p>
|
|
<p>On the GBA, the memory bus that physically transfers data from the game pak into
|
|
the device is a 16-bit memory bus. This means that if you need to transfer more
|
|
than 16 bits at a time you have to do more than one transfer. Since we'd like
|
|
our instructions to get to the CPU as fast as possible, we compile the majority
|
|
of our program with the THUMB instruction set. The ARM reference says that with
|
|
THUMB instructions on a 16-bit memory bus system you get about 160% performance
|
|
compared to using ARM instructions. That's absolutely something we want to take
|
|
advantage of. Also, your THUMB compiled code is about 65% of the same code
|
|
compiled with ARM. Since a game ROM can only be 32MB total, and we're trying to
|
|
fit in images and sound too, we want to get space savings where we can.</p>
|
|
<p>You may wonder, why is the THUMB code 65% as large if the instructions
|
|
themselves are 50% as large, and why have ARM mode at all if there's such a
|
|
benefit to be had with THUMB? Well, THUMB mode doesn't support as many different
|
|
instructions as ARM mode does. Some lines of source code that can compile to a
|
|
single ARM instruction might need to compile into more than one THUMB
|
|
instruction. THUMB still has most of the really good instructions available, so
|
|
it all averages out to about 65%.</p>
|
|
<p>That said, some parts of a GBA program <em>must</em> be written in ARM mode. Also, ARM
|
|
mode does allow that increased instruction flexibility. So we <em>need</em> to use ARM
|
|
some of the time, and we might just <em>want</em> to use ARM even when we don't need
|
|
to. It is possible to switch modes on the fly, there's extremely minimal
|
|
overhead, even less than doing some function calls. The only problem is the
|
|
16-bit memory bus of the game pak giving us a needless speed penalty with our
|
|
ARM code. The CPU <em>executes</em> the ARM instructions at full speed, but then it has
|
|
to wait while more instructions get sent in. What do we do? Well, code is
|
|
ultimately just a different kind of data. We can copy parts of our code off the
|
|
game pak ROM and place it into a part of the RAM that has a 32-bit memory bus.
|
|
Then the CPU can execute the code from there, going at full speed. Of course,
|
|
there's only a very small amount of RAM compared to the size of a game pak, so
|
|
we'll only do this with a few select functions. Exactly which functions will
|
|
probably depend on your game.</p>
|
|
<p>One problem with this process is that Rust doesn't currently offer a way to mark
|
|
individual functions for being ARM or THUMB. The whole program is compiled in a
|
|
single mode. That's not an automatic killer, since we can use the <code>asm!</code> macro
|
|
to write some inline assembly, then within our inline assembly we switch from
|
|
THUMB to ARM, do some ARM stuff, and switch back to THUMB mode before the inline
|
|
assembly is over. Rust is none the wiser to what happened. Yeah, it's clunky,
|
|
that's why <a href="https://github.com/rust-embedded/wg/issues/256#issuecomment-439677804">it's on the 2019
|
|
wishlist</a>
|
|
to fix it (then LLVM can manage it automatically for you).</p>
|
|
<p>The bigger problem is that when we do that all of our functions still start off
|
|
in THUMB mode, even if they temporarily use ARM mode. For the few bits of code
|
|
that must start <em>already in</em> ARM mode, we're stuck. Those parts have to be
|
|
written in external assembly files and then included with the linker. We were
|
|
already going to write some assembly, and we already use more than one file in
|
|
our project all the time, those parts aren't a big problem. The big problem is
|
|
that using custom linker scripts isn't transitive between crates.</p>
|
|
<p>What I mean is that once we have a file full of custom assembly that we're
|
|
linking in by hand, that's not "part of" the crate any more. At least not as
|
|
<code>cargo</code> see it. So we can't just upload it to <code>crates.io</code> and then depend on it
|
|
in other projects and have <code>cargo</code> download the right version and and include it
|
|
all automatically. We're back to fully manually copying files from the old
|
|
project into the new one, adding more lines to the linker script each time we
|
|
split up a new assembly file, all that stuff. Like the stone age. Sometimes ya
|
|
gotta suffer for your art.</p>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
|
|
|
|
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
|
|
|
|
|
|
</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 -->
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
window.addEventListener('load', function() {
|
|
window.setTimeout(window.print, 100);
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|