mirror of
https://github.com/italicsjenga/gba.git
synced 2025-01-11 19:41:30 +11:00
edits, cleanups, and a goal for ch3
This commit is contained in:
parent
3a355db578
commit
241fb1746c
|
@ -14,7 +14,7 @@ before_script:
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cargo check && cargo check --release
|
- cargo check && cargo check --release
|
||||||
# exclude the examples from the test build, just the lib
|
# Only run a test build for the library itself
|
||||||
- cargo test --lib && cargo test --lib --release
|
- cargo test --lib && cargo test --lib --release
|
||||||
- cd book && mdbook build
|
- cd book && mdbook build
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,12 @@ dependencies = ["create-target-dir"]
|
||||||
command = "arm-none-eabi-as"
|
command = "arm-none-eabi-as"
|
||||||
args = ["crt0.s", "-o", "target/crt0.o"]
|
args = ["crt0.s", "-o", "target/crt0.o"]
|
||||||
|
|
||||||
[tasks.build-debug]
|
[tasks.build-examples-debug]
|
||||||
dependencies = ["assemble"]
|
dependencies = ["assemble"]
|
||||||
command = "cargo"
|
command = "cargo"
|
||||||
args = ["xbuild", "--examples", "--target", "thumbv4-none-agb.json"]
|
args = ["xbuild", "--examples", "--target", "thumbv4-none-agb.json"]
|
||||||
|
|
||||||
[tasks.build-release]
|
[tasks.build-examples-release]
|
||||||
dependencies = ["assemble"]
|
dependencies = ["assemble"]
|
||||||
command = "cargo"
|
command = "cargo"
|
||||||
args = ["xbuild", "--examples", "--target", "thumbv4-none-agb.json", "--release"]
|
args = ["xbuild", "--examples", "--target", "thumbv4-none-agb.json", "--release"]
|
||||||
|
@ -56,4 +56,8 @@ fn main() -> std::io::Result<()> {
|
||||||
]
|
]
|
||||||
|
|
||||||
[tasks.build]
|
[tasks.build]
|
||||||
dependencies = ["build-debug", "build-release", "pack-roms"]
|
dependencies = ["build-examples-debug", "build-examples-release", "pack-roms"]
|
||||||
|
|
||||||
|
[tasks.test]
|
||||||
|
command = "cargo"
|
||||||
|
args = ["test", "--lib"]
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
[book]
|
[book]
|
||||||
title = "Rust GBA Tutorials"
|
title = "Rust GBA Guide"
|
||||||
authors = ["Lokathor"]
|
authors = ["Lokathor"]
|
||||||
#description = "Rust GBA Tutorials."
|
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
build-dir = "../docs"
|
build-dir = "../docs"
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* [Ch 0: Development Setup](ch00/index.md)
|
* [Ch 0: Development Setup](ch00/index.md)
|
||||||
* [Ch 1: Hello GBA](ch01/index.md)
|
* [Ch 1: Hello GBA](ch01/index.md)
|
||||||
* [hello1](ch01/hello1.md)
|
* [hello1](ch01/hello1.md)
|
||||||
|
* [Volatile](ch01/volatile.md)
|
||||||
* [IO Registers](ch01/io_registers.md)
|
* [IO Registers](ch01/io_registers.md)
|
||||||
* [The Display Control Register](ch01/the_display_control_register.md)
|
* [The Display Control Register](ch01/the_display_control_register.md)
|
||||||
* [Video Memory Intro](ch01/video_memory_intro.md)
|
* [Video Memory Intro](ch01/video_memory_intro.md)
|
||||||
|
|
|
@ -4,26 +4,25 @@ 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
|
setup the development environment. Perhaps unfortunately, there's enough detail
|
||||||
here to warrant a mini-chapter all on its own.
|
here to warrant a mini-chapter all on its own.
|
||||||
|
|
||||||
Before we begin I'd like to give a special thanks to **Ketsuban**, who is the
|
Once again, extra special thanks to **Ketsuban**, who first dove into how to
|
||||||
wizard that arranged for all of this to be able to happen and laid out the
|
make this all work with rust and then shared it with the world.
|
||||||
details of the plan to the rest of the world.
|
|
||||||
|
|
||||||
## Per System Setup
|
## Per System Setup
|
||||||
|
|
||||||
Obviously you need your computer to have a working rust installation. However,
|
Obviously you need your computer to have a [working rust
|
||||||
you'll also need to ensure that you're using a nightly toolchain. You can run
|
installation](https://rustup.rs/). However, you'll also need to ensure that
|
||||||
`rustup default nightly` to set nightly as the system wide default toolchain, or
|
you're using a nightly toolchain. You can run `rustup default nightly` to set
|
||||||
you can use a [toolchain
|
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
|
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 nightly
|
nightly just on a specific project, but either way we'll be assuming the use of
|
||||||
from now on.
|
nightly from now on.
|
||||||
|
|
||||||
Next you need [devkitpro](https://devkitpro.org/wiki/Getting_Started). They've
|
Next, you need [devkitpro](https://devkitpro.org/wiki/Getting_Started). They've
|
||||||
got a graphical installer for Windows, and `pacman` support on Linux. We'll be
|
got a graphical installer for Windows, and `pacman` support on Linux. We'll be
|
||||||
using a few of their binutils for the `arm-none-eabi` target, and we'll also be
|
using a few of general their binutils for the `arm-none-eabi` target, and we'll
|
||||||
using some of their tools that are specific to GBA development, so _even if_ you
|
also be using some of their tools that are specific to GBA development, so _even
|
||||||
already have the right binutils for whatever reason, you'll still want devkitpro
|
if_ you already have the right binutils for whatever reason, you'll still want
|
||||||
for the `gbafix` utility.
|
devkitpro for the `gbafix` utility.
|
||||||
|
|
||||||
* On Windows you'll want something like `C:\devkitpro\devkitARM\bin` and
|
* On Windows you'll want something like `C:\devkitpro\devkitARM\bin` and
|
||||||
`C:\devkitpro\tools\bin` to be [added to your
|
`C:\devkitpro\tools\bin` to be [added to your
|
||||||
|
@ -37,21 +36,20 @@ cargo will figure it all out for you.
|
||||||
|
|
||||||
## Per Project Setup
|
## Per Project Setup
|
||||||
|
|
||||||
Now you'll need some particular files each time you want to start a new project.
|
Once the system wide tools are ready, you'll need some particular files each
|
||||||
You can find them in the root of the [rust-console/gba
|
time you want to start a new project. You can find them in the root of the
|
||||||
repo](https://github.com/rust-console/gba).
|
[rust-console/gba repo](https://github.com/rust-console/gba).
|
||||||
|
|
||||||
* `thumbv4-none-agb.json` describes the overall GBA to cargo-xbuild so it knows
|
* `thumbv4-none-agb.json` describes the overall GBA to cargo-xbuild (and LLVM)
|
||||||
what to do. This is actually a somewhat made up target name since there's no
|
so it knows what to do. Technically the GBA is `thumbv4-none-eabi`, but we
|
||||||
official target name. The GBA is essentially the same as a normal
|
change the `eabi` to `agb` so that we can distinguish it from other `eabi`
|
||||||
`thumbv4-none-eabi` device, but we give it the "agb" signifier so that later
|
devices when using `cfg` flags.
|
||||||
on we'll be able to use rust's `cfg` ability to allow our code to know if it's
|
|
||||||
specifically targeting a GBA or some other similar device (like an NDS).
|
|
||||||
* `crt0.s` describes some ASM startup stuff. If you have more ASM to place here
|
* `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
|
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.
|
`crt0.o` file before it can actually be used, but we'll cover that below.
|
||||||
* `linker.ld` tells the linker more critical info about the layout expectations
|
* `linker.ld` tells the linker all the critical info about the layout
|
||||||
that the GBA has about our program.
|
expectations that the GBA has about our program, and that it should also
|
||||||
|
include the `crt0.o` file with our compiled rust code.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
|
|
||||||
|
@ -72,13 +70,13 @@ Once you've got something to build, you perform the following steps:
|
||||||
as `--release`, and options, such as `--bin foo` or `--examples`, that you'd
|
as `--release`, and options, such as `--bin foo` or `--examples`, that you'd
|
||||||
expect `cargo` to accept.
|
expect `cargo` to accept.
|
||||||
* You **can not** build and run tests this way, because they require `std`,
|
* You **can not** build and run tests this way, because they require `std`,
|
||||||
which the GBA doesn't have. You can still run some of your project's tests
|
which the GBA doesn't have. If you want you can still run some of your
|
||||||
with `cargo test`, but that builds for your local machine, so anything
|
project's tests with `cargo test --lib` or similar, but that builds for your
|
||||||
specific to the GBA (such as reading and writing registers) won't be
|
local machine, so anything specific to the GBA (such as reading and writing
|
||||||
testable that way. If you want to isolate and try out some piece code
|
registers) won't be testable that way. If you want to isolate and try out
|
||||||
running on the GBA you'll unfortunately have to make a demo for it in your
|
some piece code running on the GBA you'll unfortunately have to make a demo
|
||||||
`examples/` directory and then run the demo in an emulator and see if it
|
for it in your `examples/` directory and then run the demo in an emulator
|
||||||
does what you expect.
|
and see if it does what you expect.
|
||||||
* The file extension is important. `cargo xbuild` takes it as a flag to
|
* The file extension is important. `cargo xbuild` takes it as a flag to
|
||||||
compile dependencies with the same sysroot, so you can include crates
|
compile dependencies with the same sysroot, so you can include crates
|
||||||
normally. Well, creates that work in the GBA's limited environment, but you
|
normally. Well, creates that work in the GBA's limited environment, but you
|
||||||
|
@ -132,3 +130,6 @@ transfer to a flash cart there's a little more to do.
|
||||||
And you're finally done!
|
And you're finally done!
|
||||||
|
|
||||||
Of course, you probably want to make a script for all that, but it's up to you.
|
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.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# hello1
|
# hello1
|
||||||
|
|
||||||
|
Our first example will be a totally minimal, full magic number crazy town.
|
||||||
Ready? Here goes:
|
Ready? Here goes:
|
||||||
|
|
||||||
`hello1.rs`
|
`hello1.rs`
|
||||||
|
@ -8,7 +9,6 @@ Ready? Here goes:
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -26,17 +26,18 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Throw that into your project, build the program (as described back in Chapter
|
Throw that into your project skeleton, build the program (as described back in
|
||||||
0), and give it a run. You should see a red, green, and blue dot close-ish to
|
Chapter 0), and give it a run in your emulator. You should see a red, green, and
|
||||||
the middle of the screen. If you don't, something already went wrong. Double
|
blue dot close-ish to the middle of the screen. If you don't, something already
|
||||||
check things, phone a friend, write your senators, try asking Ketsuban on the
|
went wrong. Double check things, phone a friend, write your senators, try asking
|
||||||
[Rust Community Discord](https://discordapp.com/invite/aVESxV8), until you're
|
Ketsuban on the [Rust Community Discord](https://discordapp.com/invite/aVESxV8),
|
||||||
able to get your three dots going.
|
until you're able to get your three dots going.
|
||||||
|
|
||||||
## Explaining hello1
|
## A basic hello1 explanation
|
||||||
|
|
||||||
So, what just happened? Even if you're used to Rust that might look pretty
|
So, what just happened? Even if you're used to Rust that might look pretty
|
||||||
strange. We'll go over each part extra carefully.
|
strange. We'll go over most of the little parts right here, and then bigger
|
||||||
|
parts will get their own sections.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
|
@ -60,7 +61,6 @@ There's no standard library available on the GBA, so we'll have to live a core
|
||||||
only life.
|
only life.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -74,10 +74,6 @@ However, right now we don't know how to get any sort of message out to the user
|
||||||
so... we do nothing at all. We _can't even return_ from here, so we just sit in
|
so... we do nothing at all. We _can't even return_ from here, so we just sit in
|
||||||
an infinite loop. The player will have to reset the universe from the outside.
|
an infinite loop. The player will have to reset the universe from the outside.
|
||||||
|
|
||||||
The `#[cfg(not(test))]` part makes this item only exist in the program when
|
|
||||||
we're _not_ in a test build. This is so that `cargo test` and such work right as
|
|
||||||
much as possible.
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
|
@ -148,46 +144,5 @@ magic numbers mean or do.
|
||||||
* `0x06000000` is the start of Video RAM.
|
* `0x06000000` is the start of Video RAM.
|
||||||
|
|
||||||
So we write some magic to the display control register once, then we write some
|
So we write some magic to the display control register once, then we write some
|
||||||
other magic to three locations of magic to the Video RAM. We get three dots,
|
other magic to three magic locations in the Video RAM. Somehow that shows three
|
||||||
each in their own location... so that second part makes sense at least.
|
dots. Gotta read on to find out why!
|
||||||
|
|
||||||
We'll get into the magic number details in the other sections of this chapter.
|
|
||||||
|
|
||||||
## Sidebar: Volatile
|
|
||||||
|
|
||||||
We'll get into what all that is in a moment, but first let's ask ourselves: Why
|
|
||||||
are we doing _volatile_ writes? You've probably never used it before at all.
|
|
||||||
What is volatile anyway?
|
|
||||||
|
|
||||||
Well, the optimizer is pretty aggressive some of the time, and so it'll skip
|
|
||||||
reads and writes when it thinks can. Like if you write to a pointer once, and
|
|
||||||
then again a moment later, and it didn't see any other reads in between, it'll
|
|
||||||
think that it can just skip doing that first write since it'll get overwritten
|
|
||||||
anyway. Sometimes that's right, but sometimes it's wrong.
|
|
||||||
|
|
||||||
Marking a read or write as _volatile_ tells the compiler that it really must do
|
|
||||||
that action, and in the exact order that we wrote it out. It says that there
|
|
||||||
might even be special hardware side effects going on that the compiler isn't
|
|
||||||
aware of. In this case, the write to the display control register sets a video
|
|
||||||
mode, and the writes to the Video RAM set pixels that will show up on the
|
|
||||||
screen.
|
|
||||||
|
|
||||||
Similar to "atomic" operations you might have heard about, all volatile
|
|
||||||
operations are enforced to happen in the exact order that you specify them, but
|
|
||||||
only relative to other volatile operations. So something like
|
|
||||||
|
|
||||||
```rust
|
|
||||||
c.volatile_write(5);
|
|
||||||
a += b;
|
|
||||||
d.volatile_write(7);
|
|
||||||
```
|
|
||||||
|
|
||||||
might end up changing `a` either before or after the change to `c` (since the
|
|
||||||
value of `a` doesn't affect the write to `c`), but the write to `d` will
|
|
||||||
_always_ happen after the write to `c` even though the compiler doesn't see any
|
|
||||||
direct data dependency there.
|
|
||||||
|
|
||||||
If you ever use volatile stuff on other platforms it's important to note that
|
|
||||||
volatile doesn't make things thread-safe, you still need atomic for that.
|
|
||||||
However, the GBA doesn't have threads, so we don't have to worry about thread
|
|
||||||
safety concerns.
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ Okay so let's have a look again:
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -28,10 +27,11 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
|
|
||||||
Now let's clean this up so that it's clearer what's going on.
|
Now let's clean this up so that it's clearer what's going on.
|
||||||
|
|
||||||
First we'll label that display control stuff:
|
First we'll label that display control stuff, including using the `VolatilePtr`
|
||||||
|
type from the volatile explanation:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub const DISPCNT: *mut u16 = 0x04000000 as *mut u16;
|
pub const DISPCNT: VolatilePtr<u16> = VolatilePtr(0x04000000 as *mut u16);
|
||||||
pub const MODE3: u16 = 3;
|
pub const MODE3: u16 = 3;
|
||||||
pub const BG2: u16 = 0b100_0000_0000;
|
pub const BG2: u16 = 0b100_0000_0000;
|
||||||
```
|
```
|
||||||
|
@ -43,9 +43,12 @@ pub const VRAM: usize = 0x06000000;
|
||||||
pub const SCREEN_WIDTH: isize = 240;
|
pub const SCREEN_WIDTH: isize = 240;
|
||||||
```
|
```
|
||||||
|
|
||||||
And then we want a small helper function for putting together a color value.
|
Note that VRAM has to be interpreted in different ways depending on mode, so we
|
||||||
|
just leave it as `usize` and we'll cast it into the right form closer to the
|
||||||
|
actual use.
|
||||||
|
|
||||||
Happily, this one can even be declared as a const function. At the time of
|
Next we want a small helper function for putting together a color value.
|
||||||
|
Happily, this one can even be declared as a `const` function. At the time of
|
||||||
writing, we've got the "minimal const fn" support in nightly. It really is quite
|
writing, we've got the "minimal const fn" support in nightly. It really is quite
|
||||||
limited, but I'm happy to let rustc and LLVM pre-compute as much as they can
|
limited, but I'm happy to let rustc and LLVM pre-compute as much as they can
|
||||||
when it comes to the GBA's tiny CPU.
|
when it comes to the GBA's tiny CPU.
|
||||||
|
@ -62,7 +65,7 @@ usually helps you think about it a lot better.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
||||||
(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write_volatile(color);
|
VolatilePtr(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write(color);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -74,7 +77,6 @@ So now we've got this:
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -83,7 +85,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
unsafe {
|
unsafe {
|
||||||
DISPCNT.write_volatile(MODE3 | BG2);
|
DISPCNT.write(MODE3 | BG2);
|
||||||
mode3_pixel(120, 80, rgb16(31, 0, 0));
|
mode3_pixel(120, 80, rgb16(31, 0, 0));
|
||||||
mode3_pixel(136, 80, rgb16(0, 31, 0));
|
mode3_pixel(136, 80, rgb16(0, 31, 0));
|
||||||
mode3_pixel(120, 96, rgb16(0, 0, 31));
|
mode3_pixel(120, 96, rgb16(0, 0, 31));
|
||||||
|
@ -91,7 +93,22 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DISPCNT: *mut u16 = 0x04000000 as *mut u16;
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct VolatilePtr<T>(pub *mut T);
|
||||||
|
impl<T> VolatilePtr<T> {
|
||||||
|
pub unsafe fn read(&self) -> T {
|
||||||
|
core::ptr::read_volatile(self.0)
|
||||||
|
}
|
||||||
|
pub unsafe fn write(&self, data: T) {
|
||||||
|
core::ptr::write_volatile(self.0, data);
|
||||||
|
}
|
||||||
|
pub unsafe fn offset(self, count: isize) -> Self {
|
||||||
|
VolatilePtr(self.0.wrapping_offset(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DISPCNT: VolatilePtr<u16> = VolatilePtr(0x04000000 as *mut u16);
|
||||||
pub const MODE3: u16 = 3;
|
pub const MODE3: u16 = 3;
|
||||||
pub const BG2: u16 = 0b100_0000_0000;
|
pub const BG2: u16 = 0b100_0000_0000;
|
||||||
|
|
||||||
|
@ -103,7 +120,7 @@ pub const fn rgb16(red: u16, green: u16, blue: u16) -> u16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
||||||
(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write_volatile(color);
|
VolatilePtr(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write(color);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,3 @@ First let's [convert that to
|
||||||
binary](https://www.wolframalpha.com/input/?i=0x0403), and we get
|
binary](https://www.wolframalpha.com/input/?i=0x0403), and we get
|
||||||
`0b100_0000_0011`. So, that's setting Mode 3 with background 2 enabled and
|
`0b100_0000_0011`. So, that's setting Mode 3 with background 2 enabled and
|
||||||
nothing else special.
|
nothing else special.
|
||||||
|
|
||||||
However, I think we can do better than that. This is a prime target for more
|
|
||||||
newtyping as we attempt a `hello2` program.
|
|
||||||
|
|
|
@ -106,8 +106,8 @@ So at pixels `(120,80)`, `(136,80)`, and `(120,96)` we write three values. Once
|
||||||
again we probably need to [convert them](https://www.wolframalpha.com/) into
|
again we probably need to [convert them](https://www.wolframalpha.com/) into
|
||||||
binary to make sense of it.
|
binary to make sense of it.
|
||||||
|
|
||||||
* 0x001F: 0b11111
|
* 0x001F: 0b0_00000_00000_11111
|
||||||
* 0x03E0: 0b11111_00000
|
* 0x03E0: 0b0_00000_11111_00000
|
||||||
* 0x7C00: 0b11111_00000_00000
|
* 0x7C00: 0b0_11111_00000_00000
|
||||||
|
|
||||||
Ah, of course, a red pixel, a green pixel, and a blue pixel.
|
Ah, of course, a red pixel, a green pixel, and a blue pixel.
|
||||||
|
|
70
book/src/ch01/volatile.md
Normal file
70
book/src/ch01/volatile.md
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
# Volatile
|
||||||
|
|
||||||
|
Before we focus on what the numbers mean, first let's ask ourselves: Why are we
|
||||||
|
doing _volatile_ writes? You've probably never used that keywords before at all.
|
||||||
|
What _is_ volatile anyway?
|
||||||
|
|
||||||
|
Well, the optimizer is pretty aggressive, and so it'll skip reads and writes
|
||||||
|
when it thinks can. Like if you write to a pointer once, and then again a moment
|
||||||
|
later, and it didn't see any other reads in between, it'll think that it can
|
||||||
|
just skip doing that first write since it'll get overwritten anyway. Sometimes
|
||||||
|
that's correct, but sometimes it's not.
|
||||||
|
|
||||||
|
Marking a read or write as _volatile_ tells the compiler that it really must do
|
||||||
|
that action, and in the exact order that we wrote it out. It says that there
|
||||||
|
might even be special hardware side effects going on that the compiler isn't
|
||||||
|
aware of. In this case, the write to the display control register sets a video
|
||||||
|
mode, and the writes to the Video RAM set pixels that will show up on the
|
||||||
|
screen.
|
||||||
|
|
||||||
|
Similar to "atomic" operations you might have heard about, all volatile
|
||||||
|
operations are enforced to happen in the exact order that you specify them, but
|
||||||
|
only relative to other volatile operations. So something like
|
||||||
|
|
||||||
|
```rust
|
||||||
|
c.volatile_write(5);
|
||||||
|
a += b;
|
||||||
|
d.volatile_write(7);
|
||||||
|
```
|
||||||
|
|
||||||
|
might end up changing `a` either before or after the change to `c` (since the
|
||||||
|
value of `a` doesn't affect the write to `c`), but the write to `d` will
|
||||||
|
_always_ happen after the write to `c`, even though the compiler doesn't see any
|
||||||
|
direct data dependency there.
|
||||||
|
|
||||||
|
If you ever go on to use volatile stuff on other platforms it's important to
|
||||||
|
note that volatile doesn't make things thread-safe, you still need atomic for
|
||||||
|
that. However, the GBA doesn't have threads, so we don't have to worry about
|
||||||
|
those sorts of thread safety concerns (there's interrupts, but that's another
|
||||||
|
matter).
|
||||||
|
|
||||||
|
## Volatile by default
|
||||||
|
|
||||||
|
Of course, writing out `volatile_write` every time is more than we wanna do.
|
||||||
|
There's clarity and then there's excessive. This is a chance to write our first
|
||||||
|
[newtype](https://doc.rust-lang.org/1.0.0/style/features/types/newtype.html).
|
||||||
|
Basically a type that's got the exact same binary representation as some other
|
||||||
|
type, but new methods and trait implementations.
|
||||||
|
|
||||||
|
We want a `*mut T` that's volatile by default, and also when we offset it...
|
||||||
|
well the verdict is slightly unclear on how `offset` vs `wrapping_offset` work
|
||||||
|
when you're using pointers that you made up out of nowhere. I've asked the
|
||||||
|
experts and they genuinely weren't sure, so we'll make an `offset` method that
|
||||||
|
does a `wrapping_offset` just to be careful.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct VolatilePtr<T>(pub *mut T);
|
||||||
|
impl<T> VolatilePtr<T> {
|
||||||
|
pub unsafe fn read(&self) -> T {
|
||||||
|
core::ptr::read_volatile(self.0)
|
||||||
|
}
|
||||||
|
pub unsafe fn write(&self, data: T) {
|
||||||
|
core::ptr::write_volatile(self.0, data);
|
||||||
|
}
|
||||||
|
pub unsafe fn offset(self, count: isize) -> Self {
|
||||||
|
VolatilePtr(self.0.wrapping_offset(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -16,21 +16,21 @@ We need some better drawing operations this time around.
|
||||||
pub unsafe fn mode3_clear_screen(color: u16) {
|
pub unsafe fn mode3_clear_screen(color: u16) {
|
||||||
let color = color as u32;
|
let color = color as u32;
|
||||||
let bulk_color = color << 16 | color;
|
let bulk_color = color << 16 | color;
|
||||||
let mut ptr = VRAM as *mut u32;
|
let mut ptr = VolatilePtr(VRAM as *mut u32);
|
||||||
for _ in 0..SCREEN_HEIGHT {
|
for _ in 0..SCREEN_HEIGHT {
|
||||||
for _ in 0..(SCREEN_WIDTH / 2) {
|
for _ in 0..(SCREEN_WIDTH / 2) {
|
||||||
ptr.write_volatile(bulk_color);
|
ptr.write(bulk_color);
|
||||||
ptr = ptr.offset(1);
|
ptr = ptr.offset(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mode3_draw_pixel(col: isize, row: isize, color: u16) {
|
pub unsafe fn mode3_draw_pixel(col: isize, row: isize, color: u16) {
|
||||||
(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write_volatile(color);
|
VolatilePtr(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mode3_read_pixel(col: isize, row: isize) -> u16 {
|
pub unsafe fn mode3_read_pixel(col: isize, row: isize) -> u16 {
|
||||||
(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).read_volatile()
|
VolatilePtr(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).read()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ Now we just have to fill in the main function:
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
unsafe {
|
unsafe {
|
||||||
DISPCNT.write_volatile(MODE3 | BG2);
|
DISPCNT.write(MODE3 | BG2);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut px = SCREEN_WIDTH / 2;
|
let mut px = SCREEN_WIDTH / 2;
|
||||||
|
@ -55,7 +55,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// read the input for this frame
|
// read the input for this frame
|
||||||
let this_frame_keys = read_key_input();
|
let this_frame_keys = key_input();
|
||||||
|
|
||||||
// adjust game state and wait for vblank
|
// adjust game state and wait for vblank
|
||||||
px += 2 * this_frame_keys.column_direction() as isize;
|
px += 2 * this_frame_keys.column_direction() as isize;
|
||||||
|
|
|
@ -56,15 +56,15 @@ a `u16` and then wrap that in our newtype which will implement methods for
|
||||||
reading and writing the key bits.
|
reading and writing the key bits.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub const KEYINPUT: *mut u16 = 0x400_0130 as *mut u16;
|
pub const KEYINPUT: VolatilePtr<u16> = VolatilePtr(0x400_0130 as *mut u16);
|
||||||
|
|
||||||
/// A newtype over the key input state of the GBA.
|
/// A newtype over the key input state of the GBA.
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct KeyInputSetting(u16);
|
pub struct KeyInputSetting(u16);
|
||||||
|
|
||||||
pub fn read_key_input() -> KeyInputSetting {
|
pub fn key_input() -> KeyInputSetting {
|
||||||
unsafe { KeyInputSetting(KEYINPUT.read_volatile()) }
|
unsafe { KeyInputSetting(KEYINPUT.read()) }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ a mask for only the 10 used bits we can flip the "low when pressed" values so
|
||||||
that the entire result has active bits in all positions where a key is pressed.
|
that the entire result has active bits in all positions where a key is pressed.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub fn read_key_input() -> KeyInputSetting {
|
pub fn key_input() -> KeyInputSetting {
|
||||||
unsafe { KeyInputSetting(KEYINPUT.read_volatile() ^ 0b0000_0011_1111_1111) }
|
unsafe { KeyInputSetting(KEYINPUT.read_volatile() ^ 0b0000_0011_1111_1111) }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -46,10 +46,10 @@ quickly during the blank period.
|
||||||
So first we want a way to check the vcount value at all:
|
So first we want a way to check the vcount value at all:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub const VCOUNT: *mut u16 = 0x0400_0006 as *mut u16;
|
pub const VCOUNT: VolatilePtr<u16> = VolatilePtr(0x0400_0006 as *mut u16);
|
||||||
|
|
||||||
pub fn read_vcount() -> u16 {
|
pub fn vcount() -> u16 {
|
||||||
unsafe { VCOUNT.read_volatile() }
|
unsafe { VCOUNT.read() }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -59,11 +59,11 @@ Then we want two little helper functions to wait until VBlank and vdraw.
|
||||||
pub const SCREEN_HEIGHT: isize = 160;
|
pub const SCREEN_HEIGHT: isize = 160;
|
||||||
|
|
||||||
pub fn wait_until_vblank() {
|
pub fn wait_until_vblank() {
|
||||||
while read_vcount() < SCREEN_HEIGHT as u16 {}
|
while vcount() < SCREEN_HEIGHT as u16 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_until_vdraw() {
|
pub fn wait_until_vdraw() {
|
||||||
while read_vcount() >= SCREEN_HEIGHT as u16 {}
|
while vcount() >= SCREEN_HEIGHT as u16 {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1 +1,17 @@
|
||||||
# Ch 3: Memory and Objects
|
# Ch 3: Memory and Objects
|
||||||
|
|
||||||
|
Alright so we can do some basic "movement", but we left a big trail in the video
|
||||||
|
memory of where we went. Most of the time that's not what we want at all. If we
|
||||||
|
want to draw something over top of our background without trashing the
|
||||||
|
background memory that's an "object" (but not in the "Object Oriented" sense).
|
||||||
|
You might recall that objects have their own layer that you can enable in the
|
||||||
|
display control register.
|
||||||
|
|
||||||
|
Of course, once we're drawing these objects we'll want some scratch space to
|
||||||
|
work with them a bit, so we'll finally go over the GBA's full memory layout.
|
||||||
|
|
||||||
|
And since most games are pretty boring without an RNG, we'll cover the kinds of
|
||||||
|
RNG that you might want to include in a GBA game.
|
||||||
|
|
||||||
|
Then we'll do something or other that includes moving things and and RNG...
|
||||||
|
which is pretty much any game at all.
|
||||||
|
|
|
@ -1,8 +1,38 @@
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
Here's a book that'll help you program in Rust on the GBA.
|
Here's a book that'll help you program in Rust on the Game Boy Advance (GBA).
|
||||||
|
|
||||||
It's very "work in progress". At the moment there's only one demo program.
|
It's a work in progress of course, but so is most of everything in Rust.
|
||||||
|
|
||||||
|
## Style and Purpose
|
||||||
|
|
||||||
|
I'm out to teach you how to program in Rust on the GBA, obviously. However,
|
||||||
|
while there _is_ a [gba](https://github.com/rust-console/gba) crate, and while I
|
||||||
|
genuinely believe it to be a good and useful crate for GBA programming, we _will
|
||||||
|
not_ be using the `gba` crate within this book. In fact we won't be using any
|
||||||
|
crates at all. We can call it the [Handmade Hero](https://handmadehero.org/)
|
||||||
|
approach, if you like.
|
||||||
|
|
||||||
|
I don't want to just teach you how to use the `gba` crate, I want to teach you
|
||||||
|
what you'd need to know to write the crate from scratch if it wasn't there.
|
||||||
|
|
||||||
|
Each chapter of the book will focus on a few things you'll need to know about
|
||||||
|
GBA programming and then present a fully self-contained example that puts those
|
||||||
|
ideas into action. Just one file per example, no dependencies, no external
|
||||||
|
assets, no fuss. The examples will be in the text of the book within code
|
||||||
|
blocks, but also you can find them in the [examples
|
||||||
|
directory](https://github.com/rust-console/gba/tree/master/examples) of the repo
|
||||||
|
if you want to get them that way.
|
||||||
|
|
||||||
|
## Expected Knowledge
|
||||||
|
|
||||||
|
I will try not to ask too much of the reader ahead of time, but you are expected
|
||||||
|
to have already read [The Rust Book](https://doc.rust-lang.org/book/).
|
||||||
|
|
||||||
|
It's very difficult to know when you've said something that someone else won't
|
||||||
|
already know about, or if you're presenting ideas out of order. If things aren't
|
||||||
|
clear please [file an issue](https://github.com/rust-console/gba/issues) and
|
||||||
|
we'll try to address it.
|
||||||
|
|
||||||
## Getting Help
|
## Getting Help
|
||||||
|
|
||||||
|
@ -14,11 +44,12 @@ channel.
|
||||||
* `Lokathor` is the fool who decided to write a crate and book for it.
|
* `Lokathor` is the fool who decided to write a crate and book for it.
|
||||||
|
|
||||||
If it's _not_ a GBA specific question then you can probably ask any of the other
|
If it's _not_ a GBA specific question then you can probably ask any of the other
|
||||||
folks in the server as well.
|
folks in the server as well (there's a few hundred folks).
|
||||||
|
|
||||||
## Other Works
|
## Further Reading
|
||||||
|
|
||||||
If you want to read more about developing on the GBA there are some other good resources as well:
|
If you want to read more about developing on the GBA there are some other good
|
||||||
|
resources as well:
|
||||||
|
|
||||||
* [Tonc](https://www.coranac.com/tonc/text/toc.htm), a tutorial series written
|
* [Tonc](https://www.coranac.com/tonc/text/toc.htm), a tutorial series written
|
||||||
for C, but it's what I based the ordering of this book's sections on.
|
for C, but it's what I based the ordering of this book's sections on.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Ch 0: Development Setup - Rust GBA Tutorials</title>
|
<title>Ch 0: Development Setup - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
@ -275,7 +275,10 @@ ROM is patched in place, so we don't even need to specify a new destination.</li
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>And you're finally done!</p>
|
<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.</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>
|
</main>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>hello1 - Rust GBA Tutorials</title>
|
<title>hello1 - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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" class="active"><strong aria-hidden="true">3.1.</strong> hello1</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
@ -137,12 +137,12 @@
|
||||||
<div id="content" class="content">
|
<div id="content" class="content">
|
||||||
<main>
|
<main>
|
||||||
<a class="header" href="#hello1" id="hello1"><h1>hello1</h1></a>
|
<a class="header" href="#hello1" id="hello1"><h1>hello1</h1></a>
|
||||||
<p>Ready? Here goes:</p>
|
<p>Our first example will be a totally minimal, full magic number crazy town.
|
||||||
|
Ready? Here goes:</p>
|
||||||
<p><code>hello1.rs</code></p>
|
<p><code>hello1.rs</code></p>
|
||||||
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -159,12 +159,12 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<p>Throw that into your project, build the program (as described back in Chapter
|
<p>Throw that into your project skeleton, build the program (as described back in
|
||||||
0), and give it a run. You should see a red, green, and blue dot close-ish to
|
Chapter 0), and give it a run in your emulator. You should see a red, green, and
|
||||||
the middle of the screen. If you don't, something already went wrong. Double
|
blue dot close-ish to the middle of the screen. If you don't, something already
|
||||||
check things, phone a friend, write your senators, try asking Ketsuban on the
|
went wrong. Double check things, phone a friend, write your senators, try asking
|
||||||
<a href="https://discordapp.com/invite/aVESxV8">Rust Community Discord</a>, until you're
|
Ketsuban on the <a href="https://discordapp.com/invite/aVESxV8">Rust Community Discord</a>,
|
||||||
able to get your three dots going.</p>
|
until you're able to get your three dots going.</p>
|
||||||
<a class="header" href="#explaining-hello1" id="explaining-hello1"><h2>Explaining hello1</h2></a>
|
<a class="header" href="#explaining-hello1" id="explaining-hello1"><h2>Explaining hello1</h2></a>
|
||||||
<p>So, what just happened? Even if you're used to Rust that might look pretty
|
<p>So, what just happened? Even if you're used to Rust that might look pretty
|
||||||
strange. We'll go over each part extra carefully.</p>
|
strange. We'll go over each part extra carefully.</p>
|
||||||
|
@ -191,7 +191,6 @@ only life.</p>
|
||||||
<pre><pre class="playpen"><code class="language-rust">
|
<pre><pre class="playpen"><code class="language-rust">
|
||||||
# #![allow(unused_variables)]
|
# #![allow(unused_variables)]
|
||||||
#fn main() {
|
#fn main() {
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -203,9 +202,6 @@ Basically, if we somehow trigger a panic, this is where the program goes.
|
||||||
However, right now we don't know how to get any sort of message out to the user
|
However, right now we don't know how to get any sort of message out to the user
|
||||||
so... we do nothing at all. We <em>can't even return</em> from here, so we just sit in
|
so... we do nothing at all. We <em>can't even return</em> from here, so we just sit in
|
||||||
an infinite loop. The player will have to reset the universe from the outside.</p>
|
an infinite loop. The player will have to reset the universe from the outside.</p>
|
||||||
<p>The <code>#[cfg(not(test))]</code> part makes this item only exist in the program when
|
|
||||||
we're <em>not</em> in a test build. This is so that <code>cargo test</code> and such work right as
|
|
||||||
much as possible.</p>
|
|
||||||
<pre><pre class="playpen"><code class="language-rust">#[start]
|
<pre><pre class="playpen"><code class="language-rust">#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
|
@ -271,40 +267,8 @@ magic numbers mean or do.</p>
|
||||||
<p>So we write some magic to the display control register once, then we write some
|
<p>So we write some magic to the display control register once, then we write some
|
||||||
other magic to three locations of magic to the Video RAM. We get three dots,
|
other magic to three locations of magic to the Video RAM. We get three dots,
|
||||||
each in their own location... so that second part makes sense at least.</p>
|
each in their own location... so that second part makes sense at least.</p>
|
||||||
<p>We'll get into the magic number details in the other sections of this chapter.</p>
|
<p>But what <em>exactly</em> is going on? Well that's what the whole rest of this chapter
|
||||||
<a class="header" href="#sidebar-volatile" id="sidebar-volatile"><h2>Sidebar: Volatile</h2></a>
|
(and this book) is about.</p>
|
||||||
<p>We'll get into what all that is in a moment, but first let's ask ourselves: Why
|
|
||||||
are we doing <em>volatile</em> writes? You've probably never used it before at all.
|
|
||||||
What is volatile anyway?</p>
|
|
||||||
<p>Well, the optimizer is pretty aggressive some of the time, and so it'll skip
|
|
||||||
reads and writes when it thinks can. Like if you write to a pointer once, and
|
|
||||||
then again a moment later, and it didn't see any other reads in between, it'll
|
|
||||||
think that it can just skip doing that first write since it'll get overwritten
|
|
||||||
anyway. Sometimes that's right, but sometimes it's wrong.</p>
|
|
||||||
<p>Marking a read or write as <em>volatile</em> tells the compiler that it really must do
|
|
||||||
that action, and in the exact order that we wrote it out. It says that there
|
|
||||||
might even be special hardware side effects going on that the compiler isn't
|
|
||||||
aware of. In this case, the write to the display control register sets a video
|
|
||||||
mode, and the writes to the Video RAM set pixels that will show up on the
|
|
||||||
screen.</p>
|
|
||||||
<p>Similar to "atomic" operations you might have heard about, all volatile
|
|
||||||
operations are enforced to happen in the exact order that you specify them, but
|
|
||||||
only relative to other volatile operations. So something like</p>
|
|
||||||
<pre><pre class="playpen"><code class="language-rust">
|
|
||||||
# #![allow(unused_variables)]
|
|
||||||
#fn main() {
|
|
||||||
c.volatile_write(5);
|
|
||||||
a += b;
|
|
||||||
d.volatile_write(7);
|
|
||||||
#}</code></pre></pre>
|
|
||||||
<p>might end up changing <code>a</code> either before or after the change to <code>c</code> (since the
|
|
||||||
value of <code>a</code> doesn't affect the write to <code>c</code>), but the write to <code>d</code> will
|
|
||||||
<em>always</em> happen after the write to <code>c</code> even though the compiler doesn't see any
|
|
||||||
direct data dependency there.</p>
|
|
||||||
<p>If you ever use volatile stuff on other platforms it's important to note that
|
|
||||||
volatile doesn't make things thread-safe, you still need atomic for that.
|
|
||||||
However, the GBA doesn't have threads, so we don't have to worry about thread
|
|
||||||
safety concerns.</p>
|
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
@ -317,7 +281,7 @@ safety concerns.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="../ch01/io_registers.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="../ch01/volatile.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -335,7 +299,7 @@ safety concerns.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="../ch01/io_registers.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="../ch01/volatile.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>hello2 - Rust GBA Tutorials</title>
|
<title>hello2 - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html" class="active"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
@ -142,7 +142,6 @@
|
||||||
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -202,7 +201,6 @@ pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
||||||
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Ch 1: Hello GBA - Rust GBA Tutorials</title>
|
<title>Ch 1: Hello GBA - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><strong aria-hidden="true">2.</strong> Ch 0: Development Setup</a></li><li><a href="../ch01/index.html" class="active"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><strong aria-hidden="true">2.</strong> Ch 0: Development Setup</a></li><li><a href="../ch01/index.html" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>IO Registers - Rust GBA Tutorials</title>
|
<title>IO Registers - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html" class="active"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
@ -176,7 +176,7 @@ array index is.</p>
|
||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="../ch01/hello1.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="../ch01/volatile.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ array index is.</p>
|
||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="../ch01/hello1.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="../ch01/volatile.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>The Display Control Register - Rust GBA Tutorials</title>
|
<title>The Display Control Register - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html" class="active"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Video Memory Intro - Rust GBA Tutorials</title>
|
<title>Video Memory Intro - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html" class="active"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
233
docs/ch01/volatile.html
Normal file
233
docs/ch01/volatile.html
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang="en" class="sidebar-visible no-js">
|
||||||
|
<head>
|
||||||
|
<!-- Book generated using mdBook -->
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Volatile - 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"><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" class="active"><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></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="#volatile" id="volatile"><h1>Volatile</h1></a>
|
||||||
|
<p>Before we focus on what the numbers mean, first let's ask ourselves: Why are we
|
||||||
|
doing <em>volatile</em> writes? You've probably never used that keywords before at all.
|
||||||
|
What <em>is</em> volatile anyway?</p>
|
||||||
|
<p>Well, the optimizer is pretty aggressive, and so it'll skip reads and writes
|
||||||
|
when it thinks can. Like if you write to a pointer once, and then again a moment
|
||||||
|
later, and it didn't see any other reads in between, it'll think that it can
|
||||||
|
just skip doing that first write since it'll get overwritten anyway. Sometimes
|
||||||
|
that's correct, but sometimes it's not.</p>
|
||||||
|
<p>Marking a read or write as <em>volatile</em> tells the compiler that it really must do
|
||||||
|
that action, and in the exact order that we wrote it out. It says that there
|
||||||
|
might even be special hardware side effects going on that the compiler isn't
|
||||||
|
aware of. In this case, the write to the display control register sets a video
|
||||||
|
mode, and the writes to the Video RAM set pixels that will show up on the
|
||||||
|
screen.</p>
|
||||||
|
<p>Similar to "atomic" operations you might have heard about, all volatile
|
||||||
|
operations are enforced to happen in the exact order that you specify them, but
|
||||||
|
only relative to other volatile operations. So something like</p>
|
||||||
|
<pre><pre class="playpen"><code class="language-rust">
|
||||||
|
# #![allow(unused_variables)]
|
||||||
|
#fn main() {
|
||||||
|
c.volatile_write(5);
|
||||||
|
a += b;
|
||||||
|
d.volatile_write(7);
|
||||||
|
#}</code></pre></pre>
|
||||||
|
<p>might end up changing <code>a</code> either before or after the change to <code>c</code> (since the
|
||||||
|
value of <code>a</code> doesn't affect the write to <code>c</code>), but the write to <code>d</code> will
|
||||||
|
<em>always</em> happen after the write to <code>c</code>, even though the compiler doesn't see any
|
||||||
|
direct data dependency there.</p>
|
||||||
|
<p>If you ever go on to use volatile stuff on other platforms it's important to
|
||||||
|
note that volatile doesn't make things thread-safe, you still need atomic for
|
||||||
|
that. However, the GBA doesn't have threads, so we don't have to worry about
|
||||||
|
those sorts of thread safety concerns (there's interrupts, but that's another
|
||||||
|
matter).</p>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
|
<a rel="prev" href="../ch01/hello1.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/io_registers.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="../ch01/hello1.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/io_registers.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>
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Ch 2: User Input - Rust GBA Tutorials</title>
|
<title>Ch 2: User Input - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html" class="active"><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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>light_cycle - Rust GBA Tutorials</title>
|
<title>light_cycle - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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" class="active"><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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>The Key Input Register - Rust GBA Tutorials</title>
|
<title>The Key Input Register - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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" class="active"><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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>The VCount Register - Rust GBA Tutorials</title>
|
<title>The VCount Register - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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" class="active"><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></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Ch 3: Memory and Objects - Rust GBA Tutorials</title>
|
<title>Ch 3: Memory and Objects - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.5.</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" class="active"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li></ol>
|
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html"><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" class="active"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Introduction - Rust GBA Tutorials</title>
|
<title>Introduction - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="ch00/index.html"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="print.html" title="Print this book" aria-label="Print this book">
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
@ -137,8 +137,31 @@
|
||||||
<div id="content" class="content">
|
<div id="content" class="content">
|
||||||
<main>
|
<main>
|
||||||
<a class="header" href="#introduction" id="introduction"><h1>Introduction</h1></a>
|
<a class="header" href="#introduction" id="introduction"><h1>Introduction</h1></a>
|
||||||
<p>Here's a book that'll help you program in Rust on the GBA.</p>
|
<p>Here's a book that'll help you program in Rust on the Game Boy Advance (GBA).</p>
|
||||||
<p>It's very "work in progress". At the moment there's only one demo program.</p>
|
<p>It's a work in progress of course, but so is most of everything in Rust.</p>
|
||||||
|
<a class="header" href="#style-and-purpose" id="style-and-purpose"><h2>Style and Purpose</h2></a>
|
||||||
|
<p>I'm out to teach you how to program in Rust on the GBA, obviously. However,
|
||||||
|
while there <em>is</em> a <a href="https://github.com/rust-console/gba">gba</a> crate, and while I
|
||||||
|
genuinely believe it to be a good and useful crate for GBA programming, we <em>will
|
||||||
|
not</em> be using the <code>gba</code> crate within this book. In fact we won't be using any
|
||||||
|
crates at all. We can call it the <a href="https://handmadehero.org/">Handmade Hero</a>
|
||||||
|
approach, if you like.</p>
|
||||||
|
<p>I don't want to just teach you how to use the <code>gba</code> crate, I want to teach you
|
||||||
|
what you'd need to know to write the crate from scratch if it wasn't there.</p>
|
||||||
|
<p>Each chapter of the book will focus on a few things you'll need to know about
|
||||||
|
GBA programming and then present a fully self-contained example that puts those
|
||||||
|
ideas into action. Just one file per example, no dependencies, no external
|
||||||
|
assets, no fuss. The examples will be in the text of the book within code
|
||||||
|
blocks, but also you can find them in the <a href="https://github.com/rust-console/gba/tree/master/examples">examples
|
||||||
|
directory</a> of the repo
|
||||||
|
if you want to get them that way.</p>
|
||||||
|
<a class="header" href="#expected-knowledge" id="expected-knowledge"><h2>Expected Knowledge</h2></a>
|
||||||
|
<p>I will try not to ask too much of the reader ahead of time, but you are expected
|
||||||
|
to have already read <a href="https://doc.rust-lang.org/book/">The Rust Book</a>.</p>
|
||||||
|
<p>It's very difficult to know when you've said something that someone else won't
|
||||||
|
already know about. Or if you're presenting ideas out of order. If things aren't
|
||||||
|
clear please <a href="https://github.com/rust-console/gba/issues">file an issue</a> and
|
||||||
|
we'll try to address it.</p>
|
||||||
<a class="header" href="#getting-help" id="getting-help"><h2>Getting Help</h2></a>
|
<a class="header" href="#getting-help" id="getting-help"><h2>Getting Help</h2></a>
|
||||||
<p>If you want to contact us you should join the <a href="https://discordapp.com/invite/aVESxV8">Rust Community
|
<p>If you want to contact us you should join the <a href="https://discordapp.com/invite/aVESxV8">Rust Community
|
||||||
Discord</a> and ask in the <code>#gamedev</code>
|
Discord</a> and ask in the <code>#gamedev</code>
|
||||||
|
@ -148,9 +171,10 @@ channel.</p>
|
||||||
<li><code>Lokathor</code> is the fool who decided to write a crate and book for it.</li>
|
<li><code>Lokathor</code> is the fool who decided to write a crate and book for it.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>If it's <em>not</em> a GBA specific question then you can probably ask any of the other
|
<p>If it's <em>not</em> a GBA specific question then you can probably ask any of the other
|
||||||
folks in the server as well.</p>
|
folks in the server as well (there's a few hundred folks).</p>
|
||||||
<a class="header" href="#other-works" id="other-works"><h2>Other Works</h2></a>
|
<a class="header" href="#further-reading" id="further-reading"><h2>Further Reading</h2></a>
|
||||||
<p>If you want to read more about developing on the GBA there are some other good resources as well:</p>
|
<p>If you want to read more about developing on the GBA there are some other good
|
||||||
|
resources as well:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://www.coranac.com/tonc/text/toc.htm">Tonc</a>, a tutorial series written
|
<li><a href="https://www.coranac.com/tonc/text/toc.htm">Tonc</a>, a tutorial series written
|
||||||
for C, but it's what I based the ordering of this book's sections on.</li>
|
for C, but it's what I based the ordering of this book's sections on.</li>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Introduction - Rust GBA Tutorials</title>
|
<title>Introduction - Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<ol class="chapter"><li><a href="introduction.html" class="active"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="ch00/index.html"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="introduction.html" class="active"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="ch00/index.html"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="print.html" title="Print this book" aria-label="Print this book">
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
@ -137,8 +137,31 @@
|
||||||
<div id="content" class="content">
|
<div id="content" class="content">
|
||||||
<main>
|
<main>
|
||||||
<a class="header" href="#introduction" id="introduction"><h1>Introduction</h1></a>
|
<a class="header" href="#introduction" id="introduction"><h1>Introduction</h1></a>
|
||||||
<p>Here's a book that'll help you program in Rust on the GBA.</p>
|
<p>Here's a book that'll help you program in Rust on the Game Boy Advance (GBA).</p>
|
||||||
<p>It's very "work in progress". At the moment there's only one demo program.</p>
|
<p>It's a work in progress of course, but so is most of everything in Rust.</p>
|
||||||
|
<a class="header" href="#style-and-purpose" id="style-and-purpose"><h2>Style and Purpose</h2></a>
|
||||||
|
<p>I'm out to teach you how to program in Rust on the GBA, obviously. However,
|
||||||
|
while there <em>is</em> a <a href="https://github.com/rust-console/gba">gba</a> crate, and while I
|
||||||
|
genuinely believe it to be a good and useful crate for GBA programming, we <em>will
|
||||||
|
not</em> be using the <code>gba</code> crate within this book. In fact we won't be using any
|
||||||
|
crates at all. We can call it the <a href="https://handmadehero.org/">Handmade Hero</a>
|
||||||
|
approach, if you like.</p>
|
||||||
|
<p>I don't want to just teach you how to use the <code>gba</code> crate, I want to teach you
|
||||||
|
what you'd need to know to write the crate from scratch if it wasn't there.</p>
|
||||||
|
<p>Each chapter of the book will focus on a few things you'll need to know about
|
||||||
|
GBA programming and then present a fully self-contained example that puts those
|
||||||
|
ideas into action. Just one file per example, no dependencies, no external
|
||||||
|
assets, no fuss. The examples will be in the text of the book within code
|
||||||
|
blocks, but also you can find them in the <a href="https://github.com/rust-console/gba/tree/master/examples">examples
|
||||||
|
directory</a> of the repo
|
||||||
|
if you want to get them that way.</p>
|
||||||
|
<a class="header" href="#expected-knowledge" id="expected-knowledge"><h2>Expected Knowledge</h2></a>
|
||||||
|
<p>I will try not to ask too much of the reader ahead of time, but you are expected
|
||||||
|
to have already read <a href="https://doc.rust-lang.org/book/">The Rust Book</a>.</p>
|
||||||
|
<p>It's very difficult to know when you've said something that someone else won't
|
||||||
|
already know about. Or if you're presenting ideas out of order. If things aren't
|
||||||
|
clear please <a href="https://github.com/rust-console/gba/issues">file an issue</a> and
|
||||||
|
we'll try to address it.</p>
|
||||||
<a class="header" href="#getting-help" id="getting-help"><h2>Getting Help</h2></a>
|
<a class="header" href="#getting-help" id="getting-help"><h2>Getting Help</h2></a>
|
||||||
<p>If you want to contact us you should join the <a href="https://discordapp.com/invite/aVESxV8">Rust Community
|
<p>If you want to contact us you should join the <a href="https://discordapp.com/invite/aVESxV8">Rust Community
|
||||||
Discord</a> and ask in the <code>#gamedev</code>
|
Discord</a> and ask in the <code>#gamedev</code>
|
||||||
|
@ -148,9 +171,10 @@ channel.</p>
|
||||||
<li><code>Lokathor</code> is the fool who decided to write a crate and book for it.</li>
|
<li><code>Lokathor</code> is the fool who decided to write a crate and book for it.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>If it's <em>not</em> a GBA specific question then you can probably ask any of the other
|
<p>If it's <em>not</em> a GBA specific question then you can probably ask any of the other
|
||||||
folks in the server as well.</p>
|
folks in the server as well (there's a few hundred folks).</p>
|
||||||
<a class="header" href="#other-works" id="other-works"><h2>Other Works</h2></a>
|
<a class="header" href="#further-reading" id="further-reading"><h2>Further Reading</h2></a>
|
||||||
<p>If you want to read more about developing on the GBA there are some other good resources as well:</p>
|
<p>If you want to read more about developing on the GBA there are some other good
|
||||||
|
resources as well:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://www.coranac.com/tonc/text/toc.htm">Tonc</a>, a tutorial series written
|
<li><a href="https://www.coranac.com/tonc/text/toc.htm">Tonc</a>, a tutorial series written
|
||||||
for C, but it's what I based the ordering of this book's sections on.</li>
|
for C, but it's what I based the ordering of this book's sections on.</li>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Rust GBA Tutorials</title>
|
<title>Rust GBA Guide</title>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<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"><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/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="ch01/the_display_control_register.html"><strong aria-hidden="true">3.3.</strong> The Display Control Register</a></li><li><a href="ch01/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="ch01/hello2.html"><strong aria-hidden="true">3.5.</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></ol>
|
<ol class="chapter"><li><a href="introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="ch00/index.html"><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></ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="page-wrapper" class="page-wrapper">
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">Rust GBA Tutorials</h1>
|
<h1 class="menu-title">Rust GBA Guide</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="print.html" title="Print this book" aria-label="Print this book">
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
@ -137,8 +137,31 @@
|
||||||
<div id="content" class="content">
|
<div id="content" class="content">
|
||||||
<main>
|
<main>
|
||||||
<a class="header" href="#introduction" id="introduction"><h1>Introduction</h1></a>
|
<a class="header" href="#introduction" id="introduction"><h1>Introduction</h1></a>
|
||||||
<p>Here's a book that'll help you program in Rust on the GBA.</p>
|
<p>Here's a book that'll help you program in Rust on the Game Boy Advance (GBA).</p>
|
||||||
<p>It's very "work in progress". At the moment there's only one demo program.</p>
|
<p>It's a work in progress of course, but so is most of everything in Rust.</p>
|
||||||
|
<a class="header" href="#style-and-purpose" id="style-and-purpose"><h2>Style and Purpose</h2></a>
|
||||||
|
<p>I'm out to teach you how to program in Rust on the GBA, obviously. However,
|
||||||
|
while there <em>is</em> a <a href="https://github.com/rust-console/gba">gba</a> crate, and while I
|
||||||
|
genuinely believe it to be a good and useful crate for GBA programming, we <em>will
|
||||||
|
not</em> be using the <code>gba</code> crate within this book. In fact we won't be using any
|
||||||
|
crates at all. We can call it the <a href="https://handmadehero.org/">Handmade Hero</a>
|
||||||
|
approach, if you like.</p>
|
||||||
|
<p>I don't want to just teach you how to use the <code>gba</code> crate, I want to teach you
|
||||||
|
what you'd need to know to write the crate from scratch if it wasn't there.</p>
|
||||||
|
<p>Each chapter of the book will focus on a few things you'll need to know about
|
||||||
|
GBA programming and then present a fully self-contained example that puts those
|
||||||
|
ideas into action. Just one file per example, no dependencies, no external
|
||||||
|
assets, no fuss. The examples will be in the text of the book within code
|
||||||
|
blocks, but also you can find them in the <a href="https://github.com/rust-console/gba/tree/master/examples">examples
|
||||||
|
directory</a> of the repo
|
||||||
|
if you want to get them that way.</p>
|
||||||
|
<a class="header" href="#expected-knowledge" id="expected-knowledge"><h2>Expected Knowledge</h2></a>
|
||||||
|
<p>I will try not to ask too much of the reader ahead of time, but you are expected
|
||||||
|
to have already read <a href="https://doc.rust-lang.org/book/">The Rust Book</a>.</p>
|
||||||
|
<p>It's very difficult to know when you've said something that someone else won't
|
||||||
|
already know about. Or if you're presenting ideas out of order. If things aren't
|
||||||
|
clear please <a href="https://github.com/rust-console/gba/issues">file an issue</a> and
|
||||||
|
we'll try to address it.</p>
|
||||||
<a class="header" href="#getting-help" id="getting-help"><h2>Getting Help</h2></a>
|
<a class="header" href="#getting-help" id="getting-help"><h2>Getting Help</h2></a>
|
||||||
<p>If you want to contact us you should join the <a href="https://discordapp.com/invite/aVESxV8">Rust Community
|
<p>If you want to contact us you should join the <a href="https://discordapp.com/invite/aVESxV8">Rust Community
|
||||||
Discord</a> and ask in the <code>#gamedev</code>
|
Discord</a> and ask in the <code>#gamedev</code>
|
||||||
|
@ -148,9 +171,10 @@ channel.</p>
|
||||||
<li><code>Lokathor</code> is the fool who decided to write a crate and book for it.</li>
|
<li><code>Lokathor</code> is the fool who decided to write a crate and book for it.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>If it's <em>not</em> a GBA specific question then you can probably ask any of the other
|
<p>If it's <em>not</em> a GBA specific question then you can probably ask any of the other
|
||||||
folks in the server as well.</p>
|
folks in the server as well (there's a few hundred folks).</p>
|
||||||
<a class="header" href="#other-works" id="other-works"><h2>Other Works</h2></a>
|
<a class="header" href="#further-reading" id="further-reading"><h2>Further Reading</h2></a>
|
||||||
<p>If you want to read more about developing on the GBA there are some other good resources as well:</p>
|
<p>If you want to read more about developing on the GBA there are some other good
|
||||||
|
resources as well:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://www.coranac.com/tonc/text/toc.htm">Tonc</a>, a tutorial series written
|
<li><a href="https://www.coranac.com/tonc/text/toc.htm">Tonc</a>, a tutorial series written
|
||||||
for C, but it's what I based the ordering of this book's sections on.</li>
|
for C, but it's what I based the ordering of this book's sections on.</li>
|
||||||
|
@ -300,7 +324,10 @@ ROM is patched in place, so we don't even need to specify a new destination.</li
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>And you're finally done!</p>
|
<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.</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>
|
||||||
<a class="header" href="#ch-1-hello-gba" id="ch-1-hello-gba"><h1>Ch 1: Hello GBA</h1></a>
|
<a class="header" href="#ch-1-hello-gba" id="ch-1-hello-gba"><h1>Ch 1: Hello GBA</h1></a>
|
||||||
<p>Traditionally a person writes a "hello, world" program so that they can test
|
<p>Traditionally a person writes a "hello, world" program so that they can test
|
||||||
that their development environment is setup properly and to just get a feel for
|
that their development environment is setup properly and to just get a feel for
|
||||||
|
@ -310,12 +337,12 @@ will look like. All that stuff.</p>
|
||||||
GBA has no terminal, but it does have a screen, so instead we're going to draw
|
GBA has no terminal, but it does have a screen, so instead we're going to draw
|
||||||
three dots to the screen.</p>
|
three dots to the screen.</p>
|
||||||
<a class="header" href="#hello1" id="hello1"><h1>hello1</h1></a>
|
<a class="header" href="#hello1" id="hello1"><h1>hello1</h1></a>
|
||||||
<p>Ready? Here goes:</p>
|
<p>Our first example will be a totally minimal, full magic number crazy town.
|
||||||
|
Ready? Here goes:</p>
|
||||||
<p><code>hello1.rs</code></p>
|
<p><code>hello1.rs</code></p>
|
||||||
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -332,12 +359,12 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<p>Throw that into your project, build the program (as described back in Chapter
|
<p>Throw that into your project skeleton, build the program (as described back in
|
||||||
0), and give it a run. You should see a red, green, and blue dot close-ish to
|
Chapter 0), and give it a run in your emulator. You should see a red, green, and
|
||||||
the middle of the screen. If you don't, something already went wrong. Double
|
blue dot close-ish to the middle of the screen. If you don't, something already
|
||||||
check things, phone a friend, write your senators, try asking Ketsuban on the
|
went wrong. Double check things, phone a friend, write your senators, try asking
|
||||||
<a href="https://discordapp.com/invite/aVESxV8">Rust Community Discord</a>, until you're
|
Ketsuban on the <a href="https://discordapp.com/invite/aVESxV8">Rust Community Discord</a>,
|
||||||
able to get your three dots going.</p>
|
until you're able to get your three dots going.</p>
|
||||||
<a class="header" href="#explaining-hello1" id="explaining-hello1"><h2>Explaining hello1</h2></a>
|
<a class="header" href="#explaining-hello1" id="explaining-hello1"><h2>Explaining hello1</h2></a>
|
||||||
<p>So, what just happened? Even if you're used to Rust that might look pretty
|
<p>So, what just happened? Even if you're used to Rust that might look pretty
|
||||||
strange. We'll go over each part extra carefully.</p>
|
strange. We'll go over each part extra carefully.</p>
|
||||||
|
@ -364,7 +391,6 @@ only life.</p>
|
||||||
<pre><pre class="playpen"><code class="language-rust">
|
<pre><pre class="playpen"><code class="language-rust">
|
||||||
# #![allow(unused_variables)]
|
# #![allow(unused_variables)]
|
||||||
#fn main() {
|
#fn main() {
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -376,9 +402,6 @@ Basically, if we somehow trigger a panic, this is where the program goes.
|
||||||
However, right now we don't know how to get any sort of message out to the user
|
However, right now we don't know how to get any sort of message out to the user
|
||||||
so... we do nothing at all. We <em>can't even return</em> from here, so we just sit in
|
so... we do nothing at all. We <em>can't even return</em> from here, so we just sit in
|
||||||
an infinite loop. The player will have to reset the universe from the outside.</p>
|
an infinite loop. The player will have to reset the universe from the outside.</p>
|
||||||
<p>The <code>#[cfg(not(test))]</code> part makes this item only exist in the program when
|
|
||||||
we're <em>not</em> in a test build. This is so that <code>cargo test</code> and such work right as
|
|
||||||
much as possible.</p>
|
|
||||||
<pre><pre class="playpen"><code class="language-rust">#[start]
|
<pre><pre class="playpen"><code class="language-rust">#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
|
@ -444,16 +467,17 @@ magic numbers mean or do.</p>
|
||||||
<p>So we write some magic to the display control register once, then we write some
|
<p>So we write some magic to the display control register once, then we write some
|
||||||
other magic to three locations of magic to the Video RAM. We get three dots,
|
other magic to three locations of magic to the Video RAM. We get three dots,
|
||||||
each in their own location... so that second part makes sense at least.</p>
|
each in their own location... so that second part makes sense at least.</p>
|
||||||
<p>We'll get into the magic number details in the other sections of this chapter.</p>
|
<p>But what <em>exactly</em> is going on? Well that's what the whole rest of this chapter
|
||||||
<a class="header" href="#sidebar-volatile" id="sidebar-volatile"><h2>Sidebar: Volatile</h2></a>
|
(and this book) is about.</p>
|
||||||
<p>We'll get into what all that is in a moment, but first let's ask ourselves: Why
|
<a class="header" href="#volatile" id="volatile"><h1>Volatile</h1></a>
|
||||||
are we doing <em>volatile</em> writes? You've probably never used it before at all.
|
<p>Before we focus on what the numbers mean, first let's ask ourselves: Why are we
|
||||||
What is volatile anyway?</p>
|
doing <em>volatile</em> writes? You've probably never used that keywords before at all.
|
||||||
<p>Well, the optimizer is pretty aggressive some of the time, and so it'll skip
|
What <em>is</em> volatile anyway?</p>
|
||||||
reads and writes when it thinks can. Like if you write to a pointer once, and
|
<p>Well, the optimizer is pretty aggressive, and so it'll skip reads and writes
|
||||||
then again a moment later, and it didn't see any other reads in between, it'll
|
when it thinks can. Like if you write to a pointer once, and then again a moment
|
||||||
think that it can just skip doing that first write since it'll get overwritten
|
later, and it didn't see any other reads in between, it'll think that it can
|
||||||
anyway. Sometimes that's right, but sometimes it's wrong.</p>
|
just skip doing that first write since it'll get overwritten anyway. Sometimes
|
||||||
|
that's correct, but sometimes it's not.</p>
|
||||||
<p>Marking a read or write as <em>volatile</em> tells the compiler that it really must do
|
<p>Marking a read or write as <em>volatile</em> tells the compiler that it really must do
|
||||||
that action, and in the exact order that we wrote it out. It says that there
|
that action, and in the exact order that we wrote it out. It says that there
|
||||||
might even be special hardware side effects going on that the compiler isn't
|
might even be special hardware side effects going on that the compiler isn't
|
||||||
|
@ -472,12 +496,13 @@ d.volatile_write(7);
|
||||||
#}</code></pre></pre>
|
#}</code></pre></pre>
|
||||||
<p>might end up changing <code>a</code> either before or after the change to <code>c</code> (since the
|
<p>might end up changing <code>a</code> either before or after the change to <code>c</code> (since the
|
||||||
value of <code>a</code> doesn't affect the write to <code>c</code>), but the write to <code>d</code> will
|
value of <code>a</code> doesn't affect the write to <code>c</code>), but the write to <code>d</code> will
|
||||||
<em>always</em> happen after the write to <code>c</code> even though the compiler doesn't see any
|
<em>always</em> happen after the write to <code>c</code>, even though the compiler doesn't see any
|
||||||
direct data dependency there.</p>
|
direct data dependency there.</p>
|
||||||
<p>If you ever use volatile stuff on other platforms it's important to note that
|
<p>If you ever go on to use volatile stuff on other platforms it's important to
|
||||||
volatile doesn't make things thread-safe, you still need atomic for that.
|
note that volatile doesn't make things thread-safe, you still need atomic for
|
||||||
However, the GBA doesn't have threads, so we don't have to worry about thread
|
that. However, the GBA doesn't have threads, so we don't have to worry about
|
||||||
safety concerns.</p>
|
those sorts of thread safety concerns (there's interrupts, but that's another
|
||||||
|
matter).</p>
|
||||||
<a class="header" href="#io-registers" id="io-registers"><h1>IO Registers</h1></a>
|
<a class="header" href="#io-registers" id="io-registers"><h1>IO Registers</h1></a>
|
||||||
<p>The GBA has a large number of <strong>IO Registers</strong> (not to be confused with CPU
|
<p>The GBA has a large number of <strong>IO Registers</strong> (not to be confused with CPU
|
||||||
registers). These are special memory locations from <code>0x04000000</code> to
|
registers). These are special memory locations from <code>0x04000000</code> to
|
||||||
|
@ -702,7 +727,6 @@ binary to make sense of it.</p>
|
||||||
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -762,7 +786,6 @@ pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
||||||
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
<pre><pre class="playpen"><code class="language-rust">#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,6 @@
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -10,7 +9,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
unsafe {
|
unsafe {
|
||||||
DISPCNT.write_volatile(MODE3 | BG2);
|
DISPCNT.write(MODE3 | BG2);
|
||||||
mode3_pixel(120, 80, rgb16(31, 0, 0));
|
mode3_pixel(120, 80, rgb16(31, 0, 0));
|
||||||
mode3_pixel(136, 80, rgb16(0, 31, 0));
|
mode3_pixel(136, 80, rgb16(0, 31, 0));
|
||||||
mode3_pixel(120, 96, rgb16(0, 0, 31));
|
mode3_pixel(120, 96, rgb16(0, 0, 31));
|
||||||
|
@ -18,7 +17,22 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DISPCNT: *mut u16 = 0x04000000 as *mut u16;
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct VolatilePtr<T>(pub *mut T);
|
||||||
|
impl<T> VolatilePtr<T> {
|
||||||
|
pub unsafe fn read(&self) -> T {
|
||||||
|
core::ptr::read_volatile(self.0)
|
||||||
|
}
|
||||||
|
pub unsafe fn write(&self, data: T) {
|
||||||
|
core::ptr::write_volatile(self.0, data);
|
||||||
|
}
|
||||||
|
pub unsafe fn offset(self, count: isize) -> Self {
|
||||||
|
VolatilePtr(self.0.wrapping_offset(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DISPCNT: VolatilePtr<u16> = VolatilePtr(0x04000000 as *mut u16);
|
||||||
pub const MODE3: u16 = 3;
|
pub const MODE3: u16 = 3;
|
||||||
pub const BG2: u16 = 0b100_0000_0000;
|
pub const BG2: u16 = 0b100_0000_0000;
|
||||||
|
|
||||||
|
@ -30,5 +44,5 @@ pub const fn rgb16(red: u16, green: u16, blue: u16) -> u16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) {
|
||||||
(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write_volatile(color);
|
VolatilePtr(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write(color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
#![feature(start)]
|
|
||||||
#![no_std]
|
|
||||||
|
|
||||||
extern crate gba;
|
|
||||||
use gba::{io_registers::*, video_ram::*};
|
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[start]
|
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
|
||||||
let mode3bg2 = {
|
|
||||||
let mut setting = DisplayControlSetting::default();
|
|
||||||
setting.set_display_bg2(true);
|
|
||||||
setting.set_mode(DisplayControlMode::Bitmap3);
|
|
||||||
setting
|
|
||||||
};
|
|
||||||
set_display_control(mode3bg2);
|
|
||||||
|
|
||||||
let red = rgb16(31, 0, 0);
|
|
||||||
let green = rgb16(0, 31, 0);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let this_frame_keys = key_input();
|
|
||||||
|
|
||||||
let this_frame_key_raw: u16 = unsafe { core::mem::transmute(this_frame_keys) };
|
|
||||||
|
|
||||||
wait_until_vblank();
|
|
||||||
|
|
||||||
for i in 0..16 {
|
|
||||||
let key = ((this_frame_key_raw >> i) & 1) > 0;
|
|
||||||
mode3_draw_pixel(15 - i, 0, if key { green } else { red });
|
|
||||||
mode3_draw_pixel(15 - i, 1, if key { green } else { red });
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_until_vdraw();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
@ -10,7 +9,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
unsafe {
|
unsafe {
|
||||||
DISPCNT.write_volatile(MODE3 | BG2);
|
DISPCNT.write(MODE3 | BG2);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut px = SCREEN_WIDTH / 2;
|
let mut px = SCREEN_WIDTH / 2;
|
||||||
|
@ -19,7 +18,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// read the input for this frame
|
// read the input for this frame
|
||||||
let this_frame_keys = read_key_input();
|
let this_frame_keys = key_input();
|
||||||
|
|
||||||
// adjust game state and wait for vblank
|
// adjust game state and wait for vblank
|
||||||
px += 2 * this_frame_keys.column_direction() as isize;
|
px += 2 * this_frame_keys.column_direction() as isize;
|
||||||
|
@ -53,7 +52,22 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DISPCNT: *mut u16 = 0x04000000 as *mut u16;
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct VolatilePtr<T>(pub *mut T);
|
||||||
|
impl<T> VolatilePtr<T> {
|
||||||
|
pub unsafe fn read(&self) -> T {
|
||||||
|
core::ptr::read_volatile(self.0)
|
||||||
|
}
|
||||||
|
pub unsafe fn write(&self, data: T) {
|
||||||
|
core::ptr::write_volatile(self.0, data);
|
||||||
|
}
|
||||||
|
pub unsafe fn offset(self, count: isize) -> Self {
|
||||||
|
VolatilePtr(self.0.wrapping_offset(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DISPCNT: VolatilePtr<u16> = VolatilePtr(0x04000000 as *mut u16);
|
||||||
pub const MODE3: u16 = 3;
|
pub const MODE3: u16 = 3;
|
||||||
pub const BG2: u16 = 0b100_0000_0000;
|
pub const BG2: u16 = 0b100_0000_0000;
|
||||||
|
|
||||||
|
@ -68,24 +82,24 @@ pub const fn rgb16(red: u16, green: u16, blue: u16) -> u16 {
|
||||||
pub unsafe fn mode3_clear_screen(color: u16) {
|
pub unsafe fn mode3_clear_screen(color: u16) {
|
||||||
let color = color as u32;
|
let color = color as u32;
|
||||||
let bulk_color = color << 16 | color;
|
let bulk_color = color << 16 | color;
|
||||||
let mut ptr = VRAM as *mut u32;
|
let mut ptr = VolatilePtr(VRAM as *mut u32);
|
||||||
for _ in 0..SCREEN_HEIGHT {
|
for _ in 0..SCREEN_HEIGHT {
|
||||||
for _ in 0..(SCREEN_WIDTH / 2) {
|
for _ in 0..(SCREEN_WIDTH / 2) {
|
||||||
ptr.write_volatile(bulk_color);
|
ptr.write(bulk_color);
|
||||||
ptr = ptr.offset(1);
|
ptr = ptr.offset(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mode3_draw_pixel(col: isize, row: isize, color: u16) {
|
pub unsafe fn mode3_draw_pixel(col: isize, row: isize, color: u16) {
|
||||||
(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write_volatile(color);
|
VolatilePtr(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mode3_read_pixel(col: isize, row: isize) -> u16 {
|
pub unsafe fn mode3_read_pixel(col: isize, row: isize) -> u16 {
|
||||||
(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).read_volatile()
|
VolatilePtr(VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).read()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const KEYINPUT: *mut u16 = 0x400_0130 as *mut u16;
|
pub const KEYINPUT: VolatilePtr<u16> = VolatilePtr(0x400_0130 as *mut u16);
|
||||||
|
|
||||||
/// A newtype over the key input state of the GBA.
|
/// A newtype over the key input state of the GBA.
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||||
|
@ -101,8 +115,8 @@ pub enum TriBool {
|
||||||
Plus = 1,
|
Plus = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_key_input() -> KeyInputSetting {
|
pub fn key_input() -> KeyInputSetting {
|
||||||
unsafe { KeyInputSetting(KEYINPUT.read_volatile() ^ 0b0000_0011_1111_1111) }
|
unsafe { KeyInputSetting(KEYINPUT.read() ^ 0b0000_0011_1111_1111) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const KEY_A: u16 = 1 << 0;
|
pub const KEY_A: u16 = 1 << 0;
|
||||||
|
@ -146,16 +160,16 @@ impl KeyInputSetting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const VCOUNT: *mut u16 = 0x0400_0006 as *mut u16;
|
pub const VCOUNT: VolatilePtr<u16> = VolatilePtr(0x0400_0006 as *mut u16);
|
||||||
|
|
||||||
pub fn read_vcount() -> u16 {
|
pub fn vcount() -> u16 {
|
||||||
unsafe { VCOUNT.read_volatile() }
|
unsafe { VCOUNT.read() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_until_vblank() {
|
pub fn wait_until_vblank() {
|
||||||
while read_vcount() < SCREEN_HEIGHT as u16 {}
|
while vcount() < SCREEN_HEIGHT as u16 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_until_vdraw() {
|
pub fn wait_until_vdraw() {
|
||||||
while read_vcount() >= SCREEN_HEIGHT as u16 {}
|
while vcount() >= SCREEN_HEIGHT as u16 {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![cfg_attr(not(test), no_std)]
|
#![cfg_attr(not(test), no_std)]
|
||||||
#![feature(asm)]
|
#![cfg_attr(not(test), feature(asm))]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
//! This crate helps you write GBA ROMs.
|
//! This crate helps you write GBA ROMs.
|
||||||
|
@ -70,6 +70,8 @@ pub fn modulus(numerator: i32, denominator: i32) -> i32 {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn div_modulus(numerator: i32, denominator: i32) -> (i32, i32) {
|
pub fn div_modulus(numerator: i32, denominator: i32) -> (i32, i32) {
|
||||||
assert!(denominator != 0);
|
assert!(denominator != 0);
|
||||||
|
#[cfg(not(test))]
|
||||||
|
{
|
||||||
let div_out: i32;
|
let div_out: i32;
|
||||||
let mod_out: i32;
|
let mod_out: i32;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -81,4 +83,9 @@ pub fn div_modulus(numerator: i32, denominator: i32) -> (i32, i32) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(div_out, mod_out)
|
(div_out, mod_out)
|
||||||
|
}
|
||||||
|
#[cfg(test)]
|
||||||
|
{
|
||||||
|
(numerator / denominator, numerator % denominator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue