object attribute stuff

This commit is contained in:
Lokathor 2018-11-23 14:41:07 -07:00
parent 423a2f584b
commit 6b631474fa
31 changed files with 2213 additions and 258 deletions

View file

@ -32,3 +32,21 @@ without trading away too much in terms of quality.
To top it all off, we'll make a simple "memory game" sort of thing. There's some To top it all off, we'll make a simple "memory game" sort of thing. There's some
face down cards in a grid, you pick one to check, then you pick the other to face down cards in a grid, you pick one to check, then you pick the other to
check, and then if they match the pair disappears. check, and then if they match the pair disappears.
## Drawing Priority
Both backgrounds and objects can have "priority" values associated with them.
TONC and GBATEK have _opposite_ ideas of what it means to have the "highest"
priority. TONC goes by highest numerical value, and GBATEK goes by what's on the
z-layer closest to the user. Let's list out the rules as clearly as we can:
* Priority is always two bits, so 0 through 3.
* Priority conceptually proceeds in drawing passes that count _down_, so any
priority 3 things can get covered up by priority 2 things. In truth there's
probably depth testing and buffering stuff going on so it's all one single
pass, but conceptually we will imagine it happening as all of the 3 elements,
then all of 2, and so on.
* Objects always draw over top of backgrounds of equal priority.
* Within things of the same type and priority, the lower numbered element "wins"
and gets its pixel drawn (bg0 is favored over bg1, obj0 is favored over obj1,
etc).

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View file

@ -122,10 +122,10 @@ GBA's CPU _can't do any of that_. On the GBA, there's a genuine speed difference
between looping over indexes and then indexing each loop (slow) compared to between looping over indexes and then indexing each loop (slow) compared to
using an iterator that just stores an internal pointer and does +1 offset per using an iterator that just stores an internal pointer and does +1 offset per
loop until it reaches the end (fast). The repeated indexing itself can by itself loop until it reaches the end (fast). The repeated indexing itself can by itself
be an expensive step. If you've got a slice of data to process, be sure to go be an expensive step. If it's like a 3 element array it's no big deal, but if
over it with `.iter()` and `.iter_mut()` if you can, instead of looping by you've got a big slice of data to process, be sure to go over it with `.iter()`
index. This is Rust and all, so probably you were gonna do that anyway, but just and `.iter_mut()` if you can, instead of looping by index. This is Rust and all,
a heads up. so probably you were gonna do that anyway, but just a heads up.
## Get your Tilemap ready ## Get your Tilemap ready
@ -241,9 +241,7 @@ separate groups of related registers.
Each of these are a read/write `u16` location. This is where we get to all of Each of these are a read/write `u16` location. This is where we get to all of
the important details that we've been putting off. the important details that we've been putting off.
* 2 bits for the priority of each background (0 being highest). If two * 2 bits for the priority.
backgrounds are set to the same priority the the lower numbered background
layer takes prescience.
* 2 bits for "character base block", the charblock that all of the tile indexes * 2 bits for "character base block", the charblock that all of the tile indexes
for this background are offset from. for this background are offset from.
* 1 bit for mosaic effect being enabled (we'll get to that below). * 1 bit for mosaic effect being enabled (we'll get to that below).

View file

@ -4,12 +4,387 @@ As with backgrounds, objects can be used in both an affine and non-affine way.
For this section we'll focus on the non-affine elements, and then we'll do all For this section we'll focus on the non-affine elements, and then we'll do all
the affine stuff in a later chapter. the affine stuff in a later chapter.
TODO: tio afero ke mi diris
## Objects vs Sprites ## Objects vs Sprites
As [TONC](https://www.coranac.com/tonc/text/regobj.htm) helpfully reminds us
(and then proceeds to not follow its own advice), we should always try to think
in terms of _objects_, not _sprites_. A sprite is a logical / software concern,
perhaps a player concern, whereas an object is a hardware concern.
What's more, a given sprite that the player sees might need more than one object
to display. Objects must be either square or rectangular (so sprite bits that
stick out probably call for a second object), and can only be from 8x8 to 64x64
(so anything bigger has to be two objects lined up to appear as one).
## General Object Info
Unlike with backgrounds, you can enable the object layer in any video mode.
There's space for 128 object definitions in OAM.
The display gets a number of cycles per scanline to process objects: 1210 by
default, but only 954 if you enable the "HBlank interval free" setting in the
display control register. The [cycle cost per
object](http://problemkaputt.de/gbatek.htm#lcdobjoverview) depends on the
object's size and if it's using affine or regular mode, so enabling the HBlank
interval free setting doesn't cut the number of objects displayable by an exact
number of objects. The objects are processed in order of their definitions and
if you run out of cycles then the rest just don't get shown. If there's a
concern that you might run out of cycles you can place important objects (such
as the player) at the start of the list and then less important animation
objects later on.
## Ready the Palette ## Ready the Palette
Objects use the palette the same as the background does. The only difference is
that the palette data for objects starts at `0x500_0200`.
```rust
pub const PALRAM_OBJECT_BASE: VolatilePtr<u16> = VolatilePtr(0x500_0200 as *mut u16);
pub fn object_palette(slot: usize) -> u16 {
assert!(slot < 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).read() }
}
pub fn set_object_palette(slot: usize, color: u16) {
assert!(slot < 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).write(color) }
}
```
## Ready the Tiles ## Ready the Tiles
Objects, as with backgrounds, are composed of 8x8 tiles, and if you want
something bigger than 8x8 you have to use more than one tile put together.
Object tiles go into the final two charblocks of VRAM (indexes 4 and 5). Because
there's only two of them, they are sometimes called the lower block
(`0x601_0000`) and the higher/upper block (`0x601_4000`).
Tile indexes for sprites always offset from the base of the lower block, and
they always go 32 bytes at a time, regardless of if the object is set for 4bpp
or 8bpp. From this we can determine that there's 512 tile slots in each of the
two object charblocks. However, in video modes 3, 4, and 5 the space for the
background cuts into the lower charblock, so you can only safely use the upper
charblock.
With backgrounds you picked every single tile individually with a bunch of
screen entry values. Objects don't do that at all. Instead you pick a base tile,
size, and shape, then it figures out the rest from there. However, you may
recall back with the display control register something about an "object memory
1d" bit. This is where that comes into play.
* If object memory is set to be 2d (the default) then each charblock is treated
as 32 tiles by 32 tiles square. Each object has a base tile and dimensions,
and that just extracts directly from the charblock picture as if you were
selecting an area. This mode probably makes for the easiest image editing.
* If object memory is set to be 1d then the tiles are loaded sequentially from
the starting point, enough to fill in the object's dimensions. This most
probably makes it the easiest to program with about things, since programming
languages are pretty good at 1d things.
I'm not sure I explained that well, here's a picture:
![2d1d-diagram](obj_memory_2d1d.jpg)
In 2d mode, a new row of tiles starts every 32 tile indexes.
Of course, the mode that you actually end up using is not particularly
important, since it should be the job of your image conversion routine to get
everything all lined up and into place anyway.
## Set the Object Attributes ## Set the Object Attributes
The final step is to assign the correct attributes to an object. Each object has
three `u16` values that make up its overall attributes.
Before we go into the details, I want to remind you that the hardware will
attempt to process every single object every single frame, and also that all of
the GBA's memory is cleared to 0 at startup. Why do these two things matter
right now? As you'll see in a second an "all zero" set of object attributes
causes an 8x8 object to appear at 0,0 using object tile index 0. This is usually
_not_ what you want your unused objects to do. When your game first starts you
should take a moment to mark any objects you won't be using as objects to not
render.
### ObjectAttributes.attr0
* 8 bits for row coordinate (marks the top of the sprite)
* 2 bits for object rendering: 0 = Normal, 1 = Affine, 2 = Disabled, 3 = Affine with double rendering area
* 2 bits for object mode: 0 = Normal, 1 = Alpha Blending, 2 = Object Window, 3 = Forbidden
* 1 bit for mosaic enabled
* 1 bit 8bpp color enabled
* 2 bits for shape: 0 = Square, 1 = Horizontal, 2 = Vertical, 3 = Forbidden
If an object is 128 pixels big at Y > 128 you'll get a strange looking result
where it acts like Y > -128 and then displays partly off screen to the top.
### ObjectAttributes.attr1
* 9 bit for column coordinate (marks the left of the sprite)
* Either:
* 3 empty bits, 1 bit for horizontal flip, 1 bit for vertical flip (non-affine)
* 5 bits for affine index (affine)
* 2 bits for size.
| Size | Square | Horizontal | Vertical|
|:----:|:------:|:----------:|:-------:|
| 0 | 8x8 | 16x8 | 8x16 |
| 1 | 16x16 | 32x8 | 8x32 |
| 2 | 32x32 | 32x16 | 16x32 |
| 3 | 64x64 | 64x32 | 32x64 |
### ObjectAttributes.attr2
* 10 bits for the base tile index
* 2 bits for priority
* 4 bits for the palbank index (4bpp mode only, ignored in 8bpp)
### ObjectAttributes summary
So I said in the GBA memory mapping section that C people would tell you that
the object attributes should look like this:
```rust
#[repr(C)]
pub struct ObjectAttributes {
attr0: u16,
attr1: u16,
attr2: u16,
filler: i16,
}
```
Except that:
1) It's wasteful when we store object attributes on their own outside of OAM
(which we definitely might want to do).
2) In Rust we can't access just one field through a volatile pointer (our
pointers aren't actually volatile to begin with, just the ops we do with them
are). We have to read or write the whole pointer's value at a time.
Similarly, we can't do things like `|=` and `&=` with volatile in Rust. So in
rust we can't have a volatile pointer to an ObjectAttributes and then write
to just the three "real" values and not touch the filler field. Having the
filler value in there just means we have to dance around it more, not less.
3) We want to newtype this whole thing to prevent accidental invalid states from
being written into memory.
So we will not be using that representation. At the same time we want to have no
overhead, so we will stick to three `u16` values. We could newtype each
individual field to be its own type (`ObjectAttributesAttr0` or something silly
like that), since there aren't actual dependencies between two different fields
such that a change in one can throw another into a forbidden state. The worst
that can happen is if we disable or enable affine mode (`attr0`) it can change
the meaning of `attr1`. The changed meaning isn't actually in invalid state
though, so we _could_ make each field its own type if we wanted.
However, when you think about it, I can't imagine a common situation where we do
something like make an `attr0` value that we then want to save on its own and
apply to several different `ObjectAttributes` that we make during a game. That
just doesn't sound likely to me. So, we'll go the route where `ObjectAttributes`
is just a big black box to the outside world and we don't need to think about
the three fields internally as being separate.
First we make it so that we can get and set object attributes from memory:
```rust
pub const OAM: usize = 0x700_0000;
pub fn object_attributes(slot: usize) -> ObjectAttributes {
assert!(slot < 128);
let ptr = VolatilePtr((OAM + slot * (size_of::<u16>() * 4)) as *mut u16);
unsafe {
ObjectAttributes {
attr0: ptr.read(),
attr1: ptr.offset(1).read(),
attr2: ptr.offset(2).read(),
}
}
}
pub fn set_object_attributes(slot: usize, obj: ObjectAttributes) {
assert!(slot < 128);
let ptr = VolatilePtr((OAM + slot * (size_of::<u16>() * 4)) as *mut u16);
unsafe {
ptr.write(obj.attr0);
ptr.offset(1).write(obj.attr1);
ptr.offset(2).write(obj.attr2);
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ObjectAttributes {
attr0: u16,
attr1: u16,
attr2: u16,
}
```
Then we add a billion methods to the `ObjectAttributes` type so that we can
actually set all the different values that we want to set.
This code block is the last thing on this page so if you don't wanna scroll past
the whole thing you can just go to the next page.
```rust
#[derive(Debug, Clone, Copy)]
pub enum ObjectRenderMode {
Normal,
Affine,
Disabled,
DoubleAreaAffine,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectMode {
Normal,
AlphaBlending,
ObjectWindow,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectShape {
Square,
Horizontal,
Vertical,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectOrientation {
Normal,
HFlip,
VFlip,
BothFlip,
Affine(u8),
}
impl ObjectAttributes {
pub fn row(&self) -> u16 {
self.attr0 & 0b1111_1111
}
pub fn column(&self) -> u16 {
self.attr1 & 0b1_1111_1111
}
pub fn rendering(&self) -> ObjectRenderMode {
match (self.attr0 >> 8) & 0b11 {
0 => ObjectRenderMode::Normal,
1 => ObjectRenderMode::Affine,
2 => ObjectRenderMode::Disabled,
3 => ObjectRenderMode::DoubleAreaAffine,
_ => unimplemented!(),
}
}
pub fn mode(&self) -> ObjectMode {
match (self.attr0 >> 0xA) & 0b11 {
0 => ObjectMode::Normal,
1 => ObjectMode::AlphaBlending,
2 => ObjectMode::ObjectWindow,
_ => unimplemented!(),
}
}
pub fn mosaic(&self) -> bool {
((self.attr0 << 3) as i16) < 0
}
pub fn two_fifty_six_colors(&self) -> bool {
((self.attr0 << 2) as i16) < 0
}
pub fn shape(&self) -> ObjectShape {
match (self.attr0 >> 0xE) & 0b11 {
0 => ObjectShape::Square,
1 => ObjectShape::Horizontal,
2 => ObjectShape::Vertical,
_ => unimplemented!(),
}
}
pub fn orientation(&self) -> ObjectOrientation {
if (self.attr0 >> 8) & 1 > 0 {
ObjectOrientation::Affine((self.attr1 >> 9) as u8 & 0b1_1111)
} else {
match (self.attr1 >> 0xC) & 0b11 {
0 => ObjectOrientation::Normal,
1 => ObjectOrientation::HFlip,
2 => ObjectOrientation::VFlip,
3 => ObjectOrientation::BothFlip,
}
}
}
pub fn size(&self) -> u16 {
self.attr1 >> 0xE
}
pub fn tile_index(&self) -> u16 {
self.attr2 & 0b11_1111_1111
}
pub fn priority(&self) -> u16 {
self.attr2 >> 0xA
}
pub fn palbank(&self) -> u16 {
self.attr2 >> 0xC
}
//
pub fn set_row(&mut self, row: u16) {
self.attr0 &= !0b1111_1111;
self.attr0 |= row & 0b1111_1111;
}
pub fn set_column(&mut self, col: u16) {
self.attr1 &= !0b1_1111_1111;
self.attr2 |= col & 0b1_1111_1111;
}
pub fn set_rendering(&mut self, rendering: ObjectRenderMode) {
const RENDERING_MASK: u16 = 0b11 << 8;
self.attr0 &= !RENDERING_MASK;
self.attr0 |= (rendering as u16) << 8;
}
pub fn set_mode(&mut self, mode: ObjectMode) {
const MODE_MASK: u16 = 0b11 << 0xA;
self.attr0 &= MODE_MASK;
self.attr0 |= (mode as u16) << 0xA;
}
pub fn set_mosaic(&mut self, bit: bool) {
const MOSAIC_BIT: u16 = 1 << 0xC;
if bit {
self.attr0 |= MOSAIC_BIT
} else {
self.attr0 &= !MOSAIC_BIT
}
}
pub fn set_two_fifty_six_colors(&mut self, bit: bool) {
const COLOR_MODE_BIT: u16 = 1 << 0xD;
if bit {
self.attr0 |= COLOR_MODE_BIT
} else {
self.attr0 &= !COLOR_MODE_BIT
}
}
pub fn set_shape(&mut self, shape: ObjectShape) {
self.attr0 &= 0b0011_1111_1111_1111;
self.attr0 |= (shape as u16) << 0xE;
}
pub fn set_orientation(&mut self, orientation: ObjectOrientation) {
const AFFINE_INDEX_MASK: u16 = 0b1_1111 << 9;
self.attr1 &= !AFFINE_INDEX_MASK;
let bits = match orientation {
ObjectOrientation::Affine(index) => (index as u16) << 9,
ObjectOrientation::Normal => 0,
ObjectOrientation::HFlip => 1 << 0xC,
ObjectOrientation::VFlip => 1 << 0xD,
ObjectOrientation::BothFlip => 0b11 << 0xC,
};
self.attr1 |= bits;
}
pub fn set_size(&mut self, size: u16) {
self.attr1 &= 0b0011_1111_1111_1111;
self.attr1 |= size << 14;
}
pub fn set_tile_index(&mut self, index: u16) {
self.attr2 &= !0b11_1111_1111;
self.attr2 |= 0b11_1111_1111 & index;
}
pub fn set_priority(&mut self, priority: u16) {
self.attr2 &= !0b0000_1100_0000_0000;
self.attr2 |= (priority & 0b11) << 0xA;
}
pub fn set_palbank(&mut self, palbank: u16) {
self.attr2 &= !0b1111_0000_0000_0000;
self.attr2 |= (palbank & 0b1111) << 0xC;
}
}
```

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch00/index.html" class="active"><strong aria-hidden="true">2.</strong> Ch 0: Development Setup</a></li><li><a href="../ch01/index.html"><strong aria-hidden="true">3.</strong> Ch 1: Hello GBA</a></li><li><ol class="section"><li><a href="../ch01/hello1.html"><strong aria-hidden="true">3.1.</strong> hello1</a></li><li><a href="../ch01/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html" class="active"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html" class="active"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@ -225,6 +225,20 @@ and then a <em>separate</em> setting outside of the graphical data determines wh
palbank is to be used for that background or object (the screen entry data for palbank is to be used for that background or object (the screen entry data for
backgrounds, and the object attributes for objects).</li> backgrounds, and the object attributes for objects).</li>
</ul> </ul>
<a class="header" href="#transparency" id="transparency"><h3>Transparency</h3></a>
<p>When a pixel within a background or object specifies index 0 as its palette
entry it is treated as a transparent pixel. This means that in 8bpp mode there's
only 255 actual color options (0 being transparent), and in 4bpp mode there's
only 15 actual color options available within each palbank (the 0th entry of
<em>each</em> palbank is transparent).</p>
<p>Individual backgrounds, and individual objects, each determine if they're 4bpp
or 8bpp separately, so a given overall palette slot might map to a used color in
8bpp and an unused/transparent color in 4bpp. If you're a palette wizard.</p>
<p>Palette slot 0 of the overall background palette is used to determine the
&quot;backdrop&quot; color. That's the color you see if no background or object ends up
being rendered within a given pixel.</p>
<p>Since display mode 3 and display mode 5 don't use the palette, they cannot
benefit from transparency.</p>
<a class="header" href="#video-ram--vram" id="video-ram--vram"><h2>Video RAM / VRAM</h2></a> <a class="header" href="#video-ram--vram" id="video-ram--vram"><h2>Video RAM / VRAM</h2></a>
<ul> <ul>
<li><code>0x6000000</code> to <code>0x6017FFF</code> (96k)</li> <li><code>0x6000000</code> to <code>0x6017FFF</code> (96k)</li>

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html" class="active"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html" class="active"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@ -144,7 +144,7 @@
<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="../ch03/object_basics.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <a rel="prev" href="../ch03/regular_objects.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>
@ -162,7 +162,7 @@
<nav class="nav-wide-wrapper" aria-label="Page navigation"> <nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="../ch03/object_basics.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <a href="../ch03/regular_objects.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>

View file

@ -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/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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@ -165,6 +165,23 @@ without trading away too much in terms of quality.</p>
<p>To top it all off, we'll make a simple &quot;memory game&quot; sort of thing. There's some <p>To top it all off, we'll make a simple &quot;memory game&quot; sort of thing. There's some
face down cards in a grid, you pick one to check, then you pick the other to face down cards in a grid, you pick one to check, then you pick the other to
check, and then if they match the pair disappears.</p> check, and then if they match the pair disappears.</p>
<a class="header" href="#drawing-priority" id="drawing-priority"><h2>Drawing Priority</h2></a>
<p>Both backgrounds and objects can have &quot;priority&quot; values associated with them.
TONC and GBATEK have <em>opposite</em> ideas of what it means to have the &quot;highest&quot;
priority. TONC goes by highest numerical value, and GBATEK goes by what's on the
z-layer closest to the user. Let's list out the rules as clearly as we can:</p>
<ul>
<li>Priority is always two bits, so 0 through 3.</li>
<li>Priority conceptually proceeds in drawing passes that count <em>down</em>, so any
priority 3 things can get covered up by priority 2 things. In truth there's
probably depth testing and buffering stuff going on so it's all one single
pass, but conceptually we will imagine it happening as all of the 3 elements,
then all of 2, and so on.</li>
<li>Objects always draw over top of backgrounds of equal priority.</li>
<li>Within things of the same type and priority, the lower numbered element &quot;wins&quot;
and gets its pixel drawn (bg0 is favored over bg1, obj0 is favored over obj1,
etc).</li>
</ul>
</main> </main>

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html" class="active"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html" class="active"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View file

@ -1,201 +0,0 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Object Basics - 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"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html" class="active"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</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="#object-basics" id="object-basics"><h1>Object Basics</h1></a>
<p>TODO</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../ch03/regular_backgrounds.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="../ch03/gba_rng.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="../ch03/regular_backgrounds.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="../ch03/gba_rng.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>

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html" class="active"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html" class="active"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@ -136,8 +136,291 @@
<div id="content" class="content"> <div id="content" class="content">
<main> <main>
<a class="header" href="#tiled-backgrounds" id="tiled-backgrounds"><h1>Tiled Backgrounds</h1></a> <a class="header" href="#regular-backgrounds" id="regular-backgrounds"><h1>Regular Backgrounds</h1></a>
<p>TODO</p> <p>So, backgrounds, they're cool. Why do we call the ones here &quot;regular&quot;
backgrounds? Because there's also &quot;affine&quot; backgrounds. However, affine math
stuff adds a complication, so for now we'll just work with regular backgrounds.
The non-affine backgrounds are sometimes called &quot;text mode&quot; backgrounds by other
guides.</p>
<p>To get your background image working you generally need to perform all of the
following steps, though I suppose the exact ordering is up to you.</p>
<a class="header" href="#tiled-video-modes" id="tiled-video-modes"><h2>Tiled Video Modes</h2></a>
<p>When you want regular tiled display, you must use video mode 0 or 1.</p>
<ul>
<li>Mode 0 allows for using all four BG layers (0 through 3) as regular
backgrounds.</li>
<li>Mode 1 allows for using BG0 and BG1 as regular backgrounds, BG2 as an affine
background, and BG3 not at all.</li>
<li>Mode 2 allows for BG2 and BG3 to be used as affine backgrounds, while BG0 and
BG1 cannot be used at all.</li>
</ul>
<p>We will not cover affine backgrounds in this chapter, so we will naturally be
using video mode 0.</p>
<p>Also, note that you have to enable each background layer that you want to use
within the display control register.</p>
<a class="header" href="#get-your-palette-ready" id="get-your-palette-ready"><h2>Get Your Palette Ready</h2></a>
<p>Background palette starts at <code>0x5000000</code> and is 256 <code>u16</code> values long. It'd
potentially be possible declare a static array starting at a fixed address and
use a linker script to make sure that it ends up at the right spot in the final
program, but since we have to use volatile reads and writes with PALRAM anyway,
we'll just reuse our <code>VolatilePtr</code> type. Something like this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub const PALRAM_BG_BASE: VolatilePtr&lt;u16&gt; = VolatilePtr(0x500_0000 as *mut u16);
pub fn bg_palette(slot: usize) -&gt; u16 {
assert!(slot &lt; 256);
unsafe { PALRAM_BG_BASE.offset(slot as isize).read() }
}
pub fn set_bg_palette(slot: usize, color: u16) {
assert!(slot &lt; 256);
unsafe { PALRAM_BG_BASE.offset(slot as isize).write(color) }
}
#}</code></pre></pre>
<p>As we discussed with the tile color depths, the palette can be utilized as a
single block of palette values (<code>[u16; 256]</code>) or as 16 palbanks of 16 palette
values each (<code>[[u16;16]; 16]</code>). This setting is assigned per background layer
via IO register.</p>
<a class="header" href="#get-your-tiles-ready" id="get-your-tiles-ready"><h2>Get Your Tiles Ready</h2></a>
<p>Tile data is placed into charblocks. A charblock is always 16kb, so depending on
color depth it will have either 256 or 512 tiles within that charblock.
Charblocks 0, 1, 2, and 3 are all for background tiles. That's a maximum of 2048
tiles for backgrounds, but as you'll see in a moment a particular tilemap entry
can't even index that high. Instead, each background layer is assigned a
&quot;character base block&quot;, and then tilemap entries index relative to the character
base block of that background layer.</p>
<p>Now, if you want to move in a lot of tile data you'll probably want to use a DMA
routine, or at least write a function like memcopy32 for fast <code>u32</code> copying from
ROM into VRAM. However, for now, and because we're being very explicit since
this is our first time doing it, we'll write it as functions for individual tile
reads and writes.</p>
<p>The math works like indexing a pointer, except that we have two sizes we need to
go by. First you take the base address for VRAM (<code>0x600_0000</code>), then add the
size of a charblock (16kb) times the charblock you want to place the tile
within, and then you add the index of the tile slot you're placing it into times
the size of that type of tile. Like this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub fn bg_tile_4pp(base_block: usize, tile_index: usize) -&gt; Tile4bpp {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 512);
let address = VRAM + size_of::&lt;Charblock4bpp&gt;() * base_block + size_of::&lt;Tile4bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile4bpp).read() }
}
pub fn set_bg_tile_4pp(base_block: usize, tile_index: usize, tile: Tile4bpp) {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 512);
let address = VRAM + size_of::&lt;Charblock4bpp&gt;() * base_block + size_of::&lt;Tile4bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile4bpp).write(tile) }
}
pub fn bg_tile_8pp(base_block: usize, tile_index: usize) -&gt; Tile8bpp {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 256);
let address = VRAM + size_of::&lt;Charblock8bpp&gt;() * base_block + size_of::&lt;Tile8bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile8bpp).read() }
}
pub fn set_bg_tile_8pp(base_block: usize, tile_index: usize, tile: Tile8bpp) {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 256);
let address = VRAM + size_of::&lt;Charblock8bpp&gt;() * base_block + size_of::&lt;Tile8bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile8bpp).write(tile) }
}
#}</code></pre></pre>
<p>For bulk operations, you'd do the exact same math to get your base destination
pointer, and then you'd get the base source pointer for the tile you're copying
out of ROM, and then you'd do the bulk copy for the correct number of <code>u32</code>
values that you're trying to move (8 per tile moved for 4bpp, or 16 per tile
moved for 8bpp).</p>
<p><strong>GBA Limitation Note:</strong> on a modern PC (eg: <code>x86</code> or <code>x86_64</code>) you're probably
used to index based loops and iterator based loops being the same speed. The CPU
has the ability to do a &quot;fused multiply add&quot;, so the base address of the array
plus desired index * size per element is a single CPU operation to compute. It's
slightly more complicated if there's arrays within arrays like there are here,
but with normal arrays it's basically the same speed to index per loop cycle as
it is to take a base address and then add +1 offset per loop cycle. However, the
GBA's CPU <em>can't do any of that</em>. On the GBA, there's a genuine speed difference
between looping over indexes and then indexing each loop (slow) compared to
using an iterator that just stores an internal pointer and does +1 offset per
loop until it reaches the end (fast). The repeated indexing itself can by itself
be an expensive step. If it's like a 3 element array it's no big deal, but if
you've got a big slice of data to process, be sure to go over it with <code>.iter()</code>
and <code>.iter_mut()</code> if you can, instead of looping by index. This is Rust and all,
so probably you were gonna do that anyway, but just a heads up.</p>
<a class="header" href="#get-your-tilemap-ready" id="get-your-tilemap-ready"><h2>Get your Tilemap ready</h2></a>
<p>I believe that at one point I alluded to a tilemap existing. Well, just as the
tiles are arranged into charblocks, the data describing what tile to show in
what location is arranged into a thing called a <strong>screenblock</strong>.</p>
<p>A screenblock is placed into VRAM the same as the tile data charblocks. Starting
at the base of VRAM (<code>0x600_0000</code>) there are 32 slots for the screenblock array.
Each screenblock is 2048 bytes (<code>0x800</code>). Naturally, if our tiles are using up
charblock space within VRAM and our tilemaps are using up screenblock space
within the same VRAM... well it would just be a <em>disaster</em> if they ran in to
each other. Once again, it's up to you as the programmer to determine how much
space you want to devote to each thing. Each complete charblock uses up 8
screenblocks worth of space, but you don't have to fill a complete charblock
with tiles, so you can be very fiddly with how you split the memory.</p>
<p>Each screenblock is composed of a series of <em>screenblock entry</em> values, which
describe what tile index to use and if the tile should be flipped and what
palbank it should use (if any). Because both regular backgrounds and affine
backgrounds are composed of screenblocks with entries, and because the affine
background has a smaller format for screenblock entries, we'll name
appropriately.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct RegularScreenblock {
data: [RegularScreenblockEntry; 32 * 32],
}
#[derive(Debug, Clone, Copy, Default)]
#[repr(transparent)]
pub struct RegularScreenblockEntry(u16);
#}</code></pre></pre>
<p>So, with one entry per tile, a single screenblock allows for 32x32 tiles worth of
background.</p>
<p>The format of a regular screenblock entry is quite simple compared to some of
the IO register stuff:</p>
<ul>
<li>10 bits for tile index (base off of the character base block of the background)</li>
<li>1 bit for horizontal flip</li>
<li>1 bit for vertical flip</li>
<li>4 bits for picking which palbank to use (if 4bpp, otherwise it's ignored)</li>
</ul>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
impl RegularScreenblockEntry {
pub fn tile_id(self) -&gt; u16 {
self.0 &amp; 0b11_1111_1111
}
pub fn set_tile_id(&amp;mut self, id: u16) {
self.0 &amp;= !0b11_1111_1111;
self.0 |= id;
}
pub fn horizontal_flip(self) -&gt; bool {
(self.0 &amp; (1 &lt;&lt; 0xA)) &gt; 0
}
pub fn set_horizontal_flip(&amp;mut self, bit: bool) {
if bit {
self.0 |= 1 &lt;&lt; 0xA;
} else {
self.0 &amp;= !(1 &lt;&lt; 0xA);
}
}
pub fn vertical_flip(self) -&gt; bool {
(self.0 &amp; (1 &lt;&lt; 0xB)) &gt; 0
}
pub fn set_vertical_flip(&amp;mut self, bit: bool) {
if bit {
self.0 |= 1 &lt;&lt; 0xB;
} else {
self.0 &amp;= !(1 &lt;&lt; 0xB);
}
}
pub fn palbank_index(self) -&gt; u16 {
self.0 &gt;&gt; 12
}
pub fn set_palbank_index(&amp;mut self, palbank_index: u16) {
self.0 &amp;= 0b1111_1111_1111;
self.0 |= palbank_index;
}
}
#}</code></pre></pre>
<p>Now, at either 256 or 512 tiles per charblock, you might be thinking that with a
10 bit index you can index past the end of one charblock and into the next.
You'd be right, mostly.</p>
<p>As long as you stay within the background memory region for charblocks (that is,
0 through 3), then it all works out. However, if you try to get the background
rendering to reach outside of the background charblocks you'll get an
implementation defined result. It's not the dreaded &quot;undefined behavior&quot; we're
often worried about in programming, but the results <em>are</em> determined by what
you're running the game on. With GBA hardware you get a bizarre result
(basically another way to put garbage on the screen). With a DS it acts as if
the tiles were all 0s. If you use an emulator it might or might not allow for
you to do this, it's up to the emulator writers.</p>
<a class="header" href="#set-your-io-registers" id="set-your-io-registers"><h2>Set Your IO Registers</h2></a>
<p>Instead of being just a single IO register to learn about this time, there's two
separate groups of related registers.</p>
<a class="header" href="#background-control" id="background-control"><h3>Background Control</h3></a>
<ul>
<li>BG0CNT (<code>0x400_0008</code>): BG0 Control</li>
<li>BG1CNT (<code>0x400_000A</code>): BG1 Control</li>
<li>BG2CNT (<code>0x400_000C</code>): BG2 Control</li>
<li>BG3CNT (<code>0x400_000E</code>): BG3 Control</li>
</ul>
<p>Each of these are a read/write <code>u16</code> location. This is where we get to all of
the important details that we've been putting off.</p>
<ul>
<li>2 bits for the priority.</li>
<li>2 bits for &quot;character base block&quot;, the charblock that all of the tile indexes
for this background are offset from.</li>
<li>1 bit for mosaic effect being enabled (we'll get to that below).</li>
<li>1 bit to enable 8bpp, otherwise 4bpp is used.</li>
<li>5 bits to pick the &quot;screen base block&quot;, the screen block that serves as the
<em>base</em> value for this background.</li>
<li>1 bit that is <em>not</em> used in regular mode, but in affine mode it can be enabled
to cause the affine background to wrap around at the edges.</li>
<li>2 bits for the background size.</li>
</ul>
<p>The size works a little funny. When size is 0 only the base screen block is
used. If size is 1 or 2 then the base screenblock and the following screenblock
are placed next to each other (horizontally for 1, vertically for 2). If the
size is 3 then the base screenblock and the following three screenblocks are
arranged into a 2x2 grid of screenblocks.</p>
<a class="header" href="#background-offset" id="background-offset"><h3>Background Offset</h3></a>
<ul>
<li>BG0HOFS (<code>0x400_0010</code>): BG0 X-Offset</li>
<li>BG0VOFS (<code>0x400_0012</code>): BG0 Y-Offset</li>
<li>BG1HOFS (<code>0x400_0014</code>): BG1 X-Offset</li>
<li>BG1VOFS (<code>0x400_0016</code>): BG1 Y-Offset</li>
<li>BG2HOFS (<code>0x400_0018</code>): BG2 X-Offset</li>
<li>BG2VOFS (<code>0x400_001A</code>): BG2 Y-Offset</li>
<li>BG3HOFS (<code>0x400_001C</code>): BG3 X-Offset</li>
<li>BG3VOFS (<code>0x400_001E</code>): BG3 Y-Offset</li>
</ul>
<p>Each of these are a <em>write only</em> <code>u16</code> location. Bits 0 through 8 are used, so
the offsets can be 0 through 511. They also only apply in regular backgrounds.
If a background is in an affine state then you'll use different IO registers to
control it (discussed in a later chapter).</p>
<p>The offset that you assign determines the pixel offset of the display area
relative to the start of the background scene, as if the screen was a camera
looking at the scene. In other words, as a BG X offset value increases, you can
think of it as the camera moving to the right, or as that background moving to
the left. Like when mario walks toward the goal. Similarly, when a BG Y offset
increases the camera is moving down, or the background is moving up, like when
mario falls down from a high platform.</p>
<p>Depending on how much the background is scrolled and the size of the background,
it will loop.</p>
<a class="header" href="#mosaic" id="mosaic"><h2>Mosaic</h2></a>
<p>As a special effect, you can apply mosaic to backgrounds and objects. It's just
a single flag for each background, so all backgrounds will use the same mosaic
settings when they have it enabled. What it actually does is split the normal
image into &quot;blocks&quot; and then each block gets the color of the top left pixel of
that block. This is the effect you see when link hits an electric foe with his
sword and the whole screen &quot;buzzes&quot; at you.</p>
<p>The mosaic control is a <em>write only</em> <code>u16</code> IO register at <code>0x400_004C</code>.</p>
<p>There's 4 bits each for:</p>
<ul>
<li>Horizontal BG stretch</li>
<li>Vertical BG stretch</li>
<li>Horizontal object stretch</li>
<li>Vertical object stretch</li>
</ul>
<p>The inputs should be 1 <em>less</em> than the desired block size. So if you set a
stretch value of 5 then pixels 0-5 would be part of the first block (6 pixels),
then 6-11 is the next block (another 6 pixels) and so on.</p>
<p>If you need to make a pixel other than the top left part of each block the one
that determines the mosaic color you can carefully offset the background or
image by a tiny bit, but of course that makes every mosaic block change its
target pixel. You can't change the target pixel on a block by block basis.</p>
</main> </main>
@ -150,7 +433,7 @@
<a rel="next" href="../ch03/object_basics.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <a rel="next" href="../ch03/regular_objects.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>
@ -168,7 +451,7 @@
<a href="../ch03/object_basics.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <a href="../ch03/regular_objects.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>

View file

@ -0,0 +1,568 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Regular Objects - 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"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html" class="active"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</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="#regular-objects" id="regular-objects"><h1>Regular Objects</h1></a>
<p>As with backgrounds, objects can be used in both an affine and non-affine way.
For this section we'll focus on the non-affine elements, and then we'll do all
the affine stuff in a later chapter.</p>
<a class="header" href="#objects-vs-sprites" id="objects-vs-sprites"><h2>Objects vs Sprites</h2></a>
<p>As <a href="https://www.coranac.com/tonc/text/regobj.htm">TONC</a> helpfully reminds us
(and then proceeds to not follow its own advice), we should always try to think
in terms of <em>objects</em>, not <em>sprites</em>. A sprite is a logical / software concern,
perhaps a player concern, whereas an object is a hardware concern.</p>
<p>What's more, a given sprite that the player sees might need more than one object
to display. Objects must be either square or rectangular (so sprite bits that
stick out probably call for a second object), and can only be from 8x8 to 64x64
(so anything bigger has to be two objects lined up to appear as one).</p>
<a class="header" href="#general-object-info" id="general-object-info"><h2>General Object Info</h2></a>
<p>Unlike with backgrounds, you can enable the object layer in any video mode.
There's space for 128 object definitions in OAM.</p>
<p>The display gets a number of cycles per scanline to process objects: 1210 by
default, but only 954 if you enable the &quot;HBlank interval free&quot; setting in the
display control register. The <a href="http://problemkaputt.de/gbatek.htm#lcdobjoverview">cycle cost per
object</a> depends on the
object's size and if it's using affine or regular mode, so enabling the HBlank
interval free setting doesn't cut the number of objects displayable by an exact
number of objects. The objects are processed in order of their definitions and
if you run out of cycles then the rest just don't get shown. If there's a
concern that you might run out of cycles you can place important objects (such
as the player) at the start of the list and then less important animation
objects later on.</p>
<a class="header" href="#ready-the-palette" id="ready-the-palette"><h2>Ready the Palette</h2></a>
<p>Objects use the palette the same as the background does. The only difference is
that the palette data for objects starts at <code>0x500_0200</code>.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub const PALRAM_OBJECT_BASE: VolatilePtr&lt;u16&gt; = VolatilePtr(0x500_0200 as *mut u16);
pub fn object_palette(slot: usize) -&gt; u16 {
assert!(slot &lt; 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).read() }
}
pub fn set_object_palette(slot: usize, color: u16) {
assert!(slot &lt; 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).write(color) }
}
#}</code></pre></pre>
<a class="header" href="#ready-the-tiles" id="ready-the-tiles"><h2>Ready the Tiles</h2></a>
<p>Objects, as with backgrounds, are composed of 8x8 tiles, and if you want
something bigger than 8x8 you have to use more than one tile put together.
Object tiles go into the final two charblocks of VRAM (indexes 4 and 5). Because
there's only two of them, they are sometimes called the lower block
(<code>0x601_0000</code>) and the higher/upper block (<code>0x601_4000</code>).</p>
<p>Tile indexes for sprites always offset from the base of the lower block, and
they always go 32 bytes at a time, regardless of if the object is set for 4bpp
or 8bpp. From this we can determine that there's 512 tile slots in each of the
two object charblocks. However, in video modes 3, 4, and 5 the space for the
background cuts into the lower charblock, so you can only safely use the upper
charblock.</p>
<p>With backgrounds you picked every single tile individually with a bunch of
screen entry values. Objects don't do that at all. Instead you pick a base tile,
size, and shape, then it figures out the rest from there. However, you may
recall back with the display control register something about an &quot;object memory
1d&quot; bit. This is where that comes into play.</p>
<ul>
<li>If object memory is set to be 2d (the default) then each charblock is treated
as 32 tiles by 32 tiles square. Each object has a base tile and dimensions,
and that just extracts directly from the charblock picture as if you were
selecting an area. This mode probably makes for the easiest image editing.</li>
<li>If object memory is set to be 1d then the tiles are loaded sequentially from
the starting point, enough to fill in the object's dimensions. This most
probably makes it the easiest to program with about things, since programming
languages are pretty good at 1d things.</li>
</ul>
<p>I'm not sure I explained that well, here's a picture:</p>
<p><img src="obj_memory_2d1d.jpg" alt="2d1d-diagram" /></p>
<p>In 2d mode, a new row of tiles starts every 32 tile indexes.</p>
<p>Of course, the mode that you actually end up using is not particularly
important, since it should be the job of your image conversion routine to get
everything all lined up and into place anyway.</p>
<a class="header" href="#set-the-object-attributes" id="set-the-object-attributes"><h2>Set the Object Attributes</h2></a>
<p>The final step is to assign the correct attributes to an object. Each object has
three <code>u16</code> values that make up its overall attributes.</p>
<p>Before we go into the details, I want to remind you that the hardware will
attempt to process every single object every single frame, and also that all of
the GBA's memory is cleared to 0 at startup. Why do these two things matter
right now? As you'll see in a second an &quot;all zero&quot; set of object attributes
causes an 8x8 object to appear at 0,0 using object tile index 0. This is usually
<em>not</em> what you want your unused objects to do. When your game first starts you
should take a moment to mark any objects you won't be using as objects to not
render.</p>
<a class="header" href="#objectattributesattr0" id="objectattributesattr0"><h3>ObjectAttributes.attr0</h3></a>
<ul>
<li>8 bits for row coordinate (marks the top of the sprite)</li>
<li>2 bits for object rendering: 0 = Normal, 1 = Affine, 2 = Disabled, 3 = Affine with double rendering area</li>
<li>2 bits for object mode: 0 = Normal, 1 = Alpha Blending, 2 = Object Window, 3 = Forbidden</li>
<li>1 bit for mosaic enabled</li>
<li>1 bit 8bpp color enabled</li>
<li>2 bits for shape: 0 = Square, 1 = Horizontal, 2 = Vertical, 3 = Forbidden</li>
</ul>
<p>If an object is 128 pixels big at Y &gt; 128 you'll get a strange looking result
where it acts like Y &gt; -128 and then displays partly off screen to the top.</p>
<a class="header" href="#objectattributesattr1" id="objectattributesattr1"><h3>ObjectAttributes.attr1</h3></a>
<ul>
<li>9 bit for column coordinate (marks the left of the sprite)</li>
<li>Either:
<ul>
<li>3 empty bits, 1 bit for horizontal flip, 1 bit for vertical flip (non-affine)</li>
<li>5 bits for affine index (affine)</li>
</ul>
</li>
<li>2 bits for size.</li>
</ul>
<table><thead><tr><th align="center"> Size </th><th align="center"> Square </th><th align="center"> Horizontal </th><th align="center"> Vertical</th></tr></thead><tbody>
<tr><td align="center"> 0 </td><td align="center"> 8x8 </td><td align="center"> 16x8 </td><td align="center"> 8x16 </td></tr>
<tr><td align="center"> 1 </td><td align="center"> 16x16 </td><td align="center"> 32x8 </td><td align="center"> 8x32 </td></tr>
<tr><td align="center"> 2 </td><td align="center"> 32x32 </td><td align="center"> 32x16 </td><td align="center"> 16x32 </td></tr>
<tr><td align="center"> 3 </td><td align="center"> 64x64 </td><td align="center"> 64x32 </td><td align="center"> 32x64 </td></tr>
</tbody></table>
<a class="header" href="#objectattributesattr2" id="objectattributesattr2"><h3>ObjectAttributes.attr2</h3></a>
<ul>
<li>10 bits for the base tile index</li>
<li>2 bits for priority</li>
<li>4 bits for the palbank index (4bpp mode only, ignored in 8bpp)</li>
</ul>
<a class="header" href="#objectattributes-summary" id="objectattributes-summary"><h3>ObjectAttributes summary</h3></a>
<p>So I said in the GBA memory mapping section that C people would tell you that
the object attributes should look like this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[repr(C)]
pub struct ObjectAttributes {
attr0: u16,
attr1: u16,
attr2: u16,
filler: i16,
}
#}</code></pre></pre>
<p>Except that:</p>
<ol>
<li>It's wasteful when we store object attributes on their own outside of OAM
(which we definitely might want to do).</li>
<li>In Rust we can't access just one field through a volatile pointer (our
pointers aren't actually volatile to begin with, just the ops we do with them
are). We have to read or write the whole pointer's value at a time.
Similarly, we can't do things like <code>|=</code> and <code>&amp;=</code> with volatile in Rust. So in
rust we can't have a volatile pointer to an ObjectAttributes and then write
to just the three &quot;real&quot; values and not touch the filler field. Having the
filler value in there just means we have to dance around it more, not less.</li>
<li>We want to newtype this whole thing to prevent accidental invalid states from
being written into memory.</li>
</ol>
<p>So we will not be using that representation. At the same time we want to have no
overhead, so we will stick to three <code>u16</code> values. We could newtype each
individual field to be its own type (<code>ObjectAttributesAttr0</code> or something silly
like that), since there aren't actual dependencies between two different fields
such that a change in one can throw another into a forbidden state. The worst
that can happen is if we disable or enable affine mode (<code>attr0</code>) it can change
the meaning of <code>attr1</code>. The changed meaning isn't actually in invalid state
though, so we <em>could</em> make each field its own type if we wanted.</p>
<p>However, when you think about it, I can't imagine a common situation where we do
something like make an <code>attr0</code> value that we then want to save on its own and
apply to several different <code>ObjectAttributes</code> that we make during a game. That
just doesn't sound likely to me. So, we'll go the route where <code>ObjectAttributes</code>
is just a big black box to the outside world and we don't need to think about
the three fields internally as being separate.</p>
<p>First we make it so that we can get and set object attributes from memory:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub const OAM: usize = 0x700_0000;
pub fn object_attributes(slot: usize) -&gt; ObjectAttributes {
assert!(slot &lt; 128);
let ptr = VolatilePtr((OAM + slot * (size_of::&lt;u16&gt;() * 4)) as *mut u16);
unsafe {
ObjectAttributes {
attr0: ptr.read(),
attr1: ptr.offset(1).read(),
attr2: ptr.offset(2).read(),
}
}
}
pub fn set_object_attributes(slot: usize, obj: ObjectAttributes) {
assert!(slot &lt; 128);
let ptr = VolatilePtr((OAM + slot * (size_of::&lt;u16&gt;() * 4)) as *mut u16);
unsafe {
ptr.write(obj.attr0);
ptr.offset(1).write(obj.attr1);
ptr.offset(2).write(obj.attr2);
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ObjectAttributes {
attr0: u16,
attr1: u16,
attr2: u16,
}
#}</code></pre></pre>
<p>Then we add a billion methods to the <code>ObjectAttributes</code> type so that we can
actually set all the different values that we want to set.</p>
<p>This code block is the last thing on this page so if you don't wanna scroll past
the whole thing you can just go to the next page.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[derive(Debug, Clone, Copy)]
pub enum ObjectRenderMode {
Normal,
Affine,
Disabled,
DoubleAreaAffine,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectMode {
Normal,
AlphaBlending,
ObjectWindow,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectShape {
Square,
Horizontal,
Vertical,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectOrientation {
Normal,
HFlip,
VFlip,
BothFlip,
Affine(u8),
}
impl ObjectAttributes {
pub fn row(&amp;self) -&gt; u16 {
self.attr0 &amp; 0b1111_1111
}
pub fn column(&amp;self) -&gt; u16 {
self.attr1 &amp; 0b1_1111_1111
}
pub fn rendering(&amp;self) -&gt; ObjectRenderMode {
match (self.attr0 &gt;&gt; 8) &amp; 0b11 {
0 =&gt; ObjectRenderMode::Normal,
1 =&gt; ObjectRenderMode::Affine,
2 =&gt; ObjectRenderMode::Disabled,
3 =&gt; ObjectRenderMode::DoubleAreaAffine,
_ =&gt; unimplemented!(),
}
}
pub fn mode(&amp;self) -&gt; ObjectMode {
match (self.attr0 &gt;&gt; 0xA) &amp; 0b11 {
0 =&gt; ObjectMode::Normal,
1 =&gt; ObjectMode::AlphaBlending,
2 =&gt; ObjectMode::ObjectWindow,
_ =&gt; unimplemented!(),
}
}
pub fn mosaic(&amp;self) -&gt; bool {
((self.attr0 &lt;&lt; 3) as i16) &lt; 0
}
pub fn two_fifty_six_colors(&amp;self) -&gt; bool {
((self.attr0 &lt;&lt; 2) as i16) &lt; 0
}
pub fn shape(&amp;self) -&gt; ObjectShape {
match (self.attr0 &gt;&gt; 0xE) &amp; 0b11 {
0 =&gt; ObjectShape::Square,
1 =&gt; ObjectShape::Horizontal,
2 =&gt; ObjectShape::Vertical,
_ =&gt; unimplemented!(),
}
}
pub fn orientation(&amp;self) -&gt; ObjectOrientation {
if (self.attr0 &gt;&gt; 8) &amp; 1 &gt; 0 {
ObjectOrientation::Affine((self.attr1 &gt;&gt; 9) as u8 &amp; 0b1_1111)
} else {
match (self.attr1 &gt;&gt; 0xC) &amp; 0b11 {
0 =&gt; ObjectOrientation::Normal,
1 =&gt; ObjectOrientation::HFlip,
2 =&gt; ObjectOrientation::VFlip,
3 =&gt; ObjectOrientation::BothFlip,
}
}
}
pub fn size(&amp;self) -&gt; u16 {
self.attr1 &gt;&gt; 0xE
}
pub fn tile_index(&amp;self) -&gt; u16 {
self.attr2 &amp; 0b11_1111_1111
}
pub fn priority(&amp;self) -&gt; u16 {
self.attr2 &gt;&gt; 0xA
}
pub fn palbank(&amp;self) -&gt; u16 {
self.attr2 &gt;&gt; 0xC
}
//
pub fn set_row(&amp;mut self, row: u16) {
self.attr0 &amp;= !0b1111_1111;
self.attr0 |= row &amp; 0b1111_1111;
}
pub fn set_column(&amp;mut self, col: u16) {
self.attr1 &amp;= !0b1_1111_1111;
self.attr2 |= col &amp; 0b1_1111_1111;
}
pub fn set_rendering(&amp;mut self, rendering: ObjectRenderMode) {
const RENDERING_MASK: u16 = 0b11 &lt;&lt; 8;
self.attr0 &amp;= !RENDERING_MASK;
self.attr0 |= (rendering as u16) &lt;&lt; 8;
}
pub fn set_mode(&amp;mut self, mode: ObjectMode) {
const MODE_MASK: u16 = 0b11 &lt;&lt; 0xA;
self.attr0 &amp;= MODE_MASK;
self.attr0 |= (mode as u16) &lt;&lt; 0xA;
}
pub fn set_mosaic(&amp;mut self, bit: bool) {
const MOSAIC_BIT: u16 = 1 &lt;&lt; 0xC;
if bit {
self.attr0 |= MOSAIC_BIT
} else {
self.attr0 &amp;= !MOSAIC_BIT
}
}
pub fn set_two_fifty_six_colors(&amp;mut self, bit: bool) {
const COLOR_MODE_BIT: u16 = 1 &lt;&lt; 0xD;
if bit {
self.attr0 |= COLOR_MODE_BIT
} else {
self.attr0 &amp;= !COLOR_MODE_BIT
}
}
pub fn set_shape(&amp;mut self, shape: ObjectShape) {
self.attr0 &amp;= 0b0011_1111_1111_1111;
self.attr0 |= (shape as u16) &lt;&lt; 0xE;
}
pub fn set_orientation(&amp;mut self, orientation: ObjectOrientation) {
const AFFINE_INDEX_MASK: u16 = 0b1_1111 &lt;&lt; 9;
self.attr1 &amp;= !AFFINE_INDEX_MASK;
let bits = match orientation {
ObjectOrientation::Affine(index) =&gt; (index as u16) &lt;&lt; 9,
ObjectOrientation::Normal =&gt; 0,
ObjectOrientation::HFlip =&gt; 1 &lt;&lt; 0xC,
ObjectOrientation::VFlip =&gt; 1 &lt;&lt; 0xD,
ObjectOrientation::BothFlip =&gt; 0b11 &lt;&lt; 0xC,
};
self.attr1 |= bits;
}
pub fn set_size(&amp;mut self, size: u16) {
self.attr1 &amp;= 0b0011_1111_1111_1111;
self.attr1 |= size &lt;&lt; 14;
}
pub fn set_tile_index(&amp;mut self, index: u16) {
self.attr2 &amp;= !0b11_1111_1111;
self.attr2 |= 0b11_1111_1111 &amp; index;
}
pub fn set_priority(&amp;mut self, priority: u16) {
self.attr2 &amp;= !0b0000_1100_0000_0000;
self.attr2 |= (priority &amp; 0b11) &lt;&lt; 0xA;
}
pub fn set_palbank(&amp;mut self, palbank: u16) {
self.attr2 &amp;= !0b1111_0000_0000_0000;
self.attr2 |= (palbank &amp; 0b1111) &lt;&lt; 0xC;
}
}
#}</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../ch03/regular_backgrounds.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="../ch03/gba_rng.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="../ch03/regular_backgrounds.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="../ch03/gba_rng.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>

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="../ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="../ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="../ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="../ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="../ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="../ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="../ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="../ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="../ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html" class="active"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="../ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="../ch03/tile_data.html" class="active"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="../ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="../ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="../ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="../ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@ -157,7 +157,9 @@ directory</a> of the repo
if you want to get them that way.</p> if you want to get them that way.</p>
<a class="header" href="#expected-knowledge" id="expected-knowledge"><h2>Expected Knowledge</h2></a> <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 <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> to have already read <a href="https://doc.rust-lang.org/book/">The Rust Book</a>. Having
also read through the <a href="https://doc.rust-lang.org/nomicon/">Rustonomicon</a> is
appreciated but not required.</p>
<p>It's very difficult to know when you've said something that someone else won't <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 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 clear please <a href="https://github.com/rust-console/gba/issues">file an issue</a> and
@ -176,14 +178,11 @@ folks in the server as well (there's a few hundred folks).</p>
<p>If you want to read more about developing on the GBA there are some other good <p>If you want to read more about developing on the GBA there are some other good
resources as well:</p> 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>
<li><a href="http://problemkaputt.de/gbatek.htm">GBATEK</a>, a homebrew tech manual for <li><a href="http://problemkaputt.de/gbatek.htm">GBATEK</a>, a homebrew tech manual for
GBA/NDS/DSi. We will regularly link to parts of it when talking about various GBA/NDS/DSi. We will regularly link to parts of it when talking about various
bits of the GBA.</li> bits of the GBA.</li>
<li><a href="https://www.cs.rit.edu/%7Etjh8300/CowBite/CowBiteSpec.htm">CowBite</a> is another
tech specification that's more GBA specific. It's sometimes got more ASCII
art diagrams and example C struct layouts than GBATEK does.</li>
</ul> </ul>
</main> </main>

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@ -157,7 +157,9 @@ directory</a> of the repo
if you want to get them that way.</p> if you want to get them that way.</p>
<a class="header" href="#expected-knowledge" id="expected-knowledge"><h2>Expected Knowledge</h2></a> <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 <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> to have already read <a href="https://doc.rust-lang.org/book/">The Rust Book</a>. Having
also read through the <a href="https://doc.rust-lang.org/nomicon/">Rustonomicon</a> is
appreciated but not required.</p>
<p>It's very difficult to know when you've said something that someone else won't <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 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 clear please <a href="https://github.com/rust-console/gba/issues">file an issue</a> and
@ -176,14 +178,11 @@ folks in the server as well (there's a few hundred folks).</p>
<p>If you want to read more about developing on the GBA there are some other good <p>If you want to read more about developing on the GBA there are some other good
resources as well:</p> 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>
<li><a href="http://problemkaputt.de/gbatek.htm">GBATEK</a>, a homebrew tech manual for <li><a href="http://problemkaputt.de/gbatek.htm">GBATEK</a>, a homebrew tech manual for
GBA/NDS/DSi. We will regularly link to parts of it when talking about various GBA/NDS/DSi. We will regularly link to parts of it when talking about various
bits of the GBA.</li> bits of the GBA.</li>
<li><a href="https://www.cs.rit.edu/%7Etjh8300/CowBite/CowBiteSpec.htm">CowBite</a> is another
tech specification that's more GBA specific. It's sometimes got more ASCII
art diagrams and example C struct layouts than GBATEK does.</li>
</ul> </ul>
</main> </main>

View file

@ -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/volatile.html"><strong aria-hidden="true">3.2.</strong> Volatile</a></li><li><a href="ch01/io_registers.html"><strong aria-hidden="true">3.3.</strong> IO Registers</a></li><li><a href="ch01/the_display_control_register.html"><strong aria-hidden="true">3.4.</strong> The Display Control Register</a></li><li><a href="ch01/video_memory_intro.html"><strong aria-hidden="true">3.5.</strong> Video Memory Intro</a></li><li><a href="ch01/hello2.html"><strong aria-hidden="true">3.6.</strong> hello2</a></li></ol></li><li><a href="ch02/index.html"><strong aria-hidden="true">4.</strong> Ch 2: User Input</a></li><li><ol class="section"><li><a href="ch02/the_key_input_register.html"><strong aria-hidden="true">4.1.</strong> The Key Input Register</a></li><li><a href="ch02/the_vcount_register.html"><strong aria-hidden="true">4.2.</strong> The VCount Register</a></li><li><a href="ch02/light_cycle.html"><strong aria-hidden="true">4.3.</strong> light_cycle</a></li></ol></li><li><a href="ch03/index.html"><strong aria-hidden="true">5.</strong> Ch 3: Memory and Objects</a></li><li><ol class="section"><li><a href="ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="ch03/object_basics.html"><strong aria-hidden="true">5.4.</strong> Object Basics</a></li><li><a href="ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol> <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><li><ol class="section"><li><a href="ch03/gba_memory_mapping.html"><strong aria-hidden="true">5.1.</strong> GBA Memory Mapping</a></li><li><a href="ch03/tile_data.html"><strong aria-hidden="true">5.2.</strong> Tile Data</a></li><li><a href="ch03/regular_backgrounds.html"><strong aria-hidden="true">5.3.</strong> Regular Backgrounds</a></li><li><a href="ch03/regular_objects.html"><strong aria-hidden="true">5.4.</strong> Regular Objects</a></li><li><a href="ch03/gba_rng.html"><strong aria-hidden="true">5.5.</strong> GBA RNG</a></li><li><a href="ch03/memory_game.html"><strong aria-hidden="true">5.6.</strong> memory_game</a></li></ol></li></ol>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@ -157,7 +157,9 @@ directory</a> of the repo
if you want to get them that way.</p> if you want to get them that way.</p>
<a class="header" href="#expected-knowledge" id="expected-knowledge"><h2>Expected Knowledge</h2></a> <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 <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> to have already read <a href="https://doc.rust-lang.org/book/">The Rust Book</a>. Having
also read through the <a href="https://doc.rust-lang.org/nomicon/">Rustonomicon</a> is
appreciated but not required.</p>
<p>It's very difficult to know when you've said something that someone else won't <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 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 clear please <a href="https://github.com/rust-console/gba/issues">file an issue</a> and
@ -176,14 +178,11 @@ folks in the server as well (there's a few hundred folks).</p>
<p>If you want to read more about developing on the GBA there are some other good <p>If you want to read more about developing on the GBA there are some other good
resources as well:</p> 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>
<li><a href="http://problemkaputt.de/gbatek.htm">GBATEK</a>, a homebrew tech manual for <li><a href="http://problemkaputt.de/gbatek.htm">GBATEK</a>, a homebrew tech manual for
GBA/NDS/DSi. We will regularly link to parts of it when talking about various GBA/NDS/DSi. We will regularly link to parts of it when talking about various
bits of the GBA.</li> bits of the GBA.</li>
<li><a href="https://www.cs.rit.edu/%7Etjh8300/CowBite/CowBiteSpec.htm">CowBite</a> is another
tech specification that's more GBA specific. It's sometimes got more ASCII
art diagrams and example C struct layouts than GBATEK does.</li>
</ul> </ul>
<a class="header" href="#chapter-0-development-setup" id="chapter-0-development-setup"><h1>Chapter 0: Development Setup</h1></a> <a class="header" href="#chapter-0-development-setup" id="chapter-0-development-setup"><h1>Chapter 0: Development Setup</h1></a>
<p>Before you can build a GBA game you'll have to follow some special steps to <p>Before you can build a GBA game you'll have to follow some special steps to
@ -1302,6 +1301,23 @@ without trading away too much in terms of quality.</p>
<p>To top it all off, we'll make a simple &quot;memory game&quot; sort of thing. There's some <p>To top it all off, we'll make a simple &quot;memory game&quot; sort of thing. There's some
face down cards in a grid, you pick one to check, then you pick the other to face down cards in a grid, you pick one to check, then you pick the other to
check, and then if they match the pair disappears.</p> check, and then if they match the pair disappears.</p>
<a class="header" href="#drawing-priority" id="drawing-priority"><h2>Drawing Priority</h2></a>
<p>Both backgrounds and objects can have &quot;priority&quot; values associated with them.
TONC and GBATEK have <em>opposite</em> ideas of what it means to have the &quot;highest&quot;
priority. TONC goes by highest numerical value, and GBATEK goes by what's on the
z-layer closest to the user. Let's list out the rules as clearly as we can:</p>
<ul>
<li>Priority is always two bits, so 0 through 3.</li>
<li>Priority conceptually proceeds in drawing passes that count <em>down</em>, so any
priority 3 things can get covered up by priority 2 things. In truth there's
probably depth testing and buffering stuff going on so it's all one single
pass, but conceptually we will imagine it happening as all of the 3 elements,
then all of 2, and so on.</li>
<li>Objects always draw over top of backgrounds of equal priority.</li>
<li>Within things of the same type and priority, the lower numbered element &quot;wins&quot;
and gets its pixel drawn (bg0 is favored over bg1, obj0 is favored over obj1,
etc).</li>
</ul>
<a class="header" href="#gba-memory-mapping" id="gba-memory-mapping"><h1>GBA Memory Mapping</h1></a> <a class="header" href="#gba-memory-mapping" id="gba-memory-mapping"><h1>GBA Memory Mapping</h1></a>
<p>The <a href="http://problemkaputt.de/gbatek.htm#gbamemorymap">GBA Memory Map</a> has <p>The <a href="http://problemkaputt.de/gbatek.htm#gbamemorymap">GBA Memory Map</a> has
several memory portions to it, each with their own little differences. Most of several memory portions to it, each with their own little differences. Most of
@ -1391,6 +1407,20 @@ and then a <em>separate</em> setting outside of the graphical data determines wh
palbank is to be used for that background or object (the screen entry data for palbank is to be used for that background or object (the screen entry data for
backgrounds, and the object attributes for objects).</li> backgrounds, and the object attributes for objects).</li>
</ul> </ul>
<a class="header" href="#transparency" id="transparency"><h3>Transparency</h3></a>
<p>When a pixel within a background or object specifies index 0 as its palette
entry it is treated as a transparent pixel. This means that in 8bpp mode there's
only 255 actual color options (0 being transparent), and in 4bpp mode there's
only 15 actual color options available within each palbank (the 0th entry of
<em>each</em> palbank is transparent).</p>
<p>Individual backgrounds, and individual objects, each determine if they're 4bpp
or 8bpp separately, so a given overall palette slot might map to a used color in
8bpp and an unused/transparent color in 4bpp. If you're a palette wizard.</p>
<p>Palette slot 0 of the overall background palette is used to determine the
&quot;backdrop&quot; color. That's the color you see if no background or object ends up
being rendered within a given pixel.</p>
<p>Since display mode 3 and display mode 5 don't use the palette, they cannot
benefit from transparency.</p>
<a class="header" href="#video-ram--vram" id="video-ram--vram"><h2>Video RAM / VRAM</h2></a> <a class="header" href="#video-ram--vram" id="video-ram--vram"><h2>Video RAM / VRAM</h2></a>
<ul> <ul>
<li><code>0x6000000</code> to <code>0x6017FFF</code> (96k)</li> <li><code>0x6000000</code> to <code>0x6017FFF</code> (96k)</li>
@ -1630,10 +1660,660 @@ example</a></li>
macro to have the formatted resource be available as a const value you can macro to have the formatted resource be available as a const value you can
load at runtime.</li> load at runtime.</li>
</ol> </ol>
<a class="header" href="#tiled-backgrounds" id="tiled-backgrounds"><h1>Tiled Backgrounds</h1></a> <a class="header" href="#regular-backgrounds" id="regular-backgrounds"><h1>Regular Backgrounds</h1></a>
<p>TODO</p> <p>So, backgrounds, they're cool. Why do we call the ones here &quot;regular&quot;
<a class="header" href="#object-basics" id="object-basics"><h1>Object Basics</h1></a> backgrounds? Because there's also &quot;affine&quot; backgrounds. However, affine math
<p>TODO</p> stuff adds a complication, so for now we'll just work with regular backgrounds.
The non-affine backgrounds are sometimes called &quot;text mode&quot; backgrounds by other
guides.</p>
<p>To get your background image working you generally need to perform all of the
following steps, though I suppose the exact ordering is up to you.</p>
<a class="header" href="#tiled-video-modes" id="tiled-video-modes"><h2>Tiled Video Modes</h2></a>
<p>When you want regular tiled display, you must use video mode 0 or 1.</p>
<ul>
<li>Mode 0 allows for using all four BG layers (0 through 3) as regular
backgrounds.</li>
<li>Mode 1 allows for using BG0 and BG1 as regular backgrounds, BG2 as an affine
background, and BG3 not at all.</li>
<li>Mode 2 allows for BG2 and BG3 to be used as affine backgrounds, while BG0 and
BG1 cannot be used at all.</li>
</ul>
<p>We will not cover affine backgrounds in this chapter, so we will naturally be
using video mode 0.</p>
<p>Also, note that you have to enable each background layer that you want to use
within the display control register.</p>
<a class="header" href="#get-your-palette-ready" id="get-your-palette-ready"><h2>Get Your Palette Ready</h2></a>
<p>Background palette starts at <code>0x5000000</code> and is 256 <code>u16</code> values long. It'd
potentially be possible declare a static array starting at a fixed address and
use a linker script to make sure that it ends up at the right spot in the final
program, but since we have to use volatile reads and writes with PALRAM anyway,
we'll just reuse our <code>VolatilePtr</code> type. Something like this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub const PALRAM_BG_BASE: VolatilePtr&lt;u16&gt; = VolatilePtr(0x500_0000 as *mut u16);
pub fn bg_palette(slot: usize) -&gt; u16 {
assert!(slot &lt; 256);
unsafe { PALRAM_BG_BASE.offset(slot as isize).read() }
}
pub fn set_bg_palette(slot: usize, color: u16) {
assert!(slot &lt; 256);
unsafe { PALRAM_BG_BASE.offset(slot as isize).write(color) }
}
#}</code></pre></pre>
<p>As we discussed with the tile color depths, the palette can be utilized as a
single block of palette values (<code>[u16; 256]</code>) or as 16 palbanks of 16 palette
values each (<code>[[u16;16]; 16]</code>). This setting is assigned per background layer
via IO register.</p>
<a class="header" href="#get-your-tiles-ready" id="get-your-tiles-ready"><h2>Get Your Tiles Ready</h2></a>
<p>Tile data is placed into charblocks. A charblock is always 16kb, so depending on
color depth it will have either 256 or 512 tiles within that charblock.
Charblocks 0, 1, 2, and 3 are all for background tiles. That's a maximum of 2048
tiles for backgrounds, but as you'll see in a moment a particular tilemap entry
can't even index that high. Instead, each background layer is assigned a
&quot;character base block&quot;, and then tilemap entries index relative to the character
base block of that background layer.</p>
<p>Now, if you want to move in a lot of tile data you'll probably want to use a DMA
routine, or at least write a function like memcopy32 for fast <code>u32</code> copying from
ROM into VRAM. However, for now, and because we're being very explicit since
this is our first time doing it, we'll write it as functions for individual tile
reads and writes.</p>
<p>The math works like indexing a pointer, except that we have two sizes we need to
go by. First you take the base address for VRAM (<code>0x600_0000</code>), then add the
size of a charblock (16kb) times the charblock you want to place the tile
within, and then you add the index of the tile slot you're placing it into times
the size of that type of tile. Like this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub fn bg_tile_4pp(base_block: usize, tile_index: usize) -&gt; Tile4bpp {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 512);
let address = VRAM + size_of::&lt;Charblock4bpp&gt;() * base_block + size_of::&lt;Tile4bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile4bpp).read() }
}
pub fn set_bg_tile_4pp(base_block: usize, tile_index: usize, tile: Tile4bpp) {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 512);
let address = VRAM + size_of::&lt;Charblock4bpp&gt;() * base_block + size_of::&lt;Tile4bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile4bpp).write(tile) }
}
pub fn bg_tile_8pp(base_block: usize, tile_index: usize) -&gt; Tile8bpp {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 256);
let address = VRAM + size_of::&lt;Charblock8bpp&gt;() * base_block + size_of::&lt;Tile8bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile8bpp).read() }
}
pub fn set_bg_tile_8pp(base_block: usize, tile_index: usize, tile: Tile8bpp) {
assert!(base_block &lt; 4);
assert!(tile_index &lt; 256);
let address = VRAM + size_of::&lt;Charblock8bpp&gt;() * base_block + size_of::&lt;Tile8bpp&gt;() * tile_index;
unsafe { VolatilePtr(address as *mut Tile8bpp).write(tile) }
}
#}</code></pre></pre>
<p>For bulk operations, you'd do the exact same math to get your base destination
pointer, and then you'd get the base source pointer for the tile you're copying
out of ROM, and then you'd do the bulk copy for the correct number of <code>u32</code>
values that you're trying to move (8 per tile moved for 4bpp, or 16 per tile
moved for 8bpp).</p>
<p><strong>GBA Limitation Note:</strong> on a modern PC (eg: <code>x86</code> or <code>x86_64</code>) you're probably
used to index based loops and iterator based loops being the same speed. The CPU
has the ability to do a &quot;fused multiply add&quot;, so the base address of the array
plus desired index * size per element is a single CPU operation to compute. It's
slightly more complicated if there's arrays within arrays like there are here,
but with normal arrays it's basically the same speed to index per loop cycle as
it is to take a base address and then add +1 offset per loop cycle. However, the
GBA's CPU <em>can't do any of that</em>. On the GBA, there's a genuine speed difference
between looping over indexes and then indexing each loop (slow) compared to
using an iterator that just stores an internal pointer and does +1 offset per
loop until it reaches the end (fast). The repeated indexing itself can by itself
be an expensive step. If it's like a 3 element array it's no big deal, but if
you've got a big slice of data to process, be sure to go over it with <code>.iter()</code>
and <code>.iter_mut()</code> if you can, instead of looping by index. This is Rust and all,
so probably you were gonna do that anyway, but just a heads up.</p>
<a class="header" href="#get-your-tilemap-ready" id="get-your-tilemap-ready"><h2>Get your Tilemap ready</h2></a>
<p>I believe that at one point I alluded to a tilemap existing. Well, just as the
tiles are arranged into charblocks, the data describing what tile to show in
what location is arranged into a thing called a <strong>screenblock</strong>.</p>
<p>A screenblock is placed into VRAM the same as the tile data charblocks. Starting
at the base of VRAM (<code>0x600_0000</code>) there are 32 slots for the screenblock array.
Each screenblock is 2048 bytes (<code>0x800</code>). Naturally, if our tiles are using up
charblock space within VRAM and our tilemaps are using up screenblock space
within the same VRAM... well it would just be a <em>disaster</em> if they ran in to
each other. Once again, it's up to you as the programmer to determine how much
space you want to devote to each thing. Each complete charblock uses up 8
screenblocks worth of space, but you don't have to fill a complete charblock
with tiles, so you can be very fiddly with how you split the memory.</p>
<p>Each screenblock is composed of a series of <em>screenblock entry</em> values, which
describe what tile index to use and if the tile should be flipped and what
palbank it should use (if any). Because both regular backgrounds and affine
backgrounds are composed of screenblocks with entries, and because the affine
background has a smaller format for screenblock entries, we'll name
appropriately.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct RegularScreenblock {
data: [RegularScreenblockEntry; 32 * 32],
}
#[derive(Debug, Clone, Copy, Default)]
#[repr(transparent)]
pub struct RegularScreenblockEntry(u16);
#}</code></pre></pre>
<p>So, with one entry per tile, a single screenblock allows for 32x32 tiles worth of
background.</p>
<p>The format of a regular screenblock entry is quite simple compared to some of
the IO register stuff:</p>
<ul>
<li>10 bits for tile index (base off of the character base block of the background)</li>
<li>1 bit for horizontal flip</li>
<li>1 bit for vertical flip</li>
<li>4 bits for picking which palbank to use (if 4bpp, otherwise it's ignored)</li>
</ul>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
impl RegularScreenblockEntry {
pub fn tile_id(self) -&gt; u16 {
self.0 &amp; 0b11_1111_1111
}
pub fn set_tile_id(&amp;mut self, id: u16) {
self.0 &amp;= !0b11_1111_1111;
self.0 |= id;
}
pub fn horizontal_flip(self) -&gt; bool {
(self.0 &amp; (1 &lt;&lt; 0xA)) &gt; 0
}
pub fn set_horizontal_flip(&amp;mut self, bit: bool) {
if bit {
self.0 |= 1 &lt;&lt; 0xA;
} else {
self.0 &amp;= !(1 &lt;&lt; 0xA);
}
}
pub fn vertical_flip(self) -&gt; bool {
(self.0 &amp; (1 &lt;&lt; 0xB)) &gt; 0
}
pub fn set_vertical_flip(&amp;mut self, bit: bool) {
if bit {
self.0 |= 1 &lt;&lt; 0xB;
} else {
self.0 &amp;= !(1 &lt;&lt; 0xB);
}
}
pub fn palbank_index(self) -&gt; u16 {
self.0 &gt;&gt; 12
}
pub fn set_palbank_index(&amp;mut self, palbank_index: u16) {
self.0 &amp;= 0b1111_1111_1111;
self.0 |= palbank_index;
}
}
#}</code></pre></pre>
<p>Now, at either 256 or 512 tiles per charblock, you might be thinking that with a
10 bit index you can index past the end of one charblock and into the next.
You'd be right, mostly.</p>
<p>As long as you stay within the background memory region for charblocks (that is,
0 through 3), then it all works out. However, if you try to get the background
rendering to reach outside of the background charblocks you'll get an
implementation defined result. It's not the dreaded &quot;undefined behavior&quot; we're
often worried about in programming, but the results <em>are</em> determined by what
you're running the game on. With GBA hardware you get a bizarre result
(basically another way to put garbage on the screen). With a DS it acts as if
the tiles were all 0s. If you use an emulator it might or might not allow for
you to do this, it's up to the emulator writers.</p>
<a class="header" href="#set-your-io-registers" id="set-your-io-registers"><h2>Set Your IO Registers</h2></a>
<p>Instead of being just a single IO register to learn about this time, there's two
separate groups of related registers.</p>
<a class="header" href="#background-control" id="background-control"><h3>Background Control</h3></a>
<ul>
<li>BG0CNT (<code>0x400_0008</code>): BG0 Control</li>
<li>BG1CNT (<code>0x400_000A</code>): BG1 Control</li>
<li>BG2CNT (<code>0x400_000C</code>): BG2 Control</li>
<li>BG3CNT (<code>0x400_000E</code>): BG3 Control</li>
</ul>
<p>Each of these are a read/write <code>u16</code> location. This is where we get to all of
the important details that we've been putting off.</p>
<ul>
<li>2 bits for the priority.</li>
<li>2 bits for &quot;character base block&quot;, the charblock that all of the tile indexes
for this background are offset from.</li>
<li>1 bit for mosaic effect being enabled (we'll get to that below).</li>
<li>1 bit to enable 8bpp, otherwise 4bpp is used.</li>
<li>5 bits to pick the &quot;screen base block&quot;, the screen block that serves as the
<em>base</em> value for this background.</li>
<li>1 bit that is <em>not</em> used in regular mode, but in affine mode it can be enabled
to cause the affine background to wrap around at the edges.</li>
<li>2 bits for the background size.</li>
</ul>
<p>The size works a little funny. When size is 0 only the base screen block is
used. If size is 1 or 2 then the base screenblock and the following screenblock
are placed next to each other (horizontally for 1, vertically for 2). If the
size is 3 then the base screenblock and the following three screenblocks are
arranged into a 2x2 grid of screenblocks.</p>
<a class="header" href="#background-offset" id="background-offset"><h3>Background Offset</h3></a>
<ul>
<li>BG0HOFS (<code>0x400_0010</code>): BG0 X-Offset</li>
<li>BG0VOFS (<code>0x400_0012</code>): BG0 Y-Offset</li>
<li>BG1HOFS (<code>0x400_0014</code>): BG1 X-Offset</li>
<li>BG1VOFS (<code>0x400_0016</code>): BG1 Y-Offset</li>
<li>BG2HOFS (<code>0x400_0018</code>): BG2 X-Offset</li>
<li>BG2VOFS (<code>0x400_001A</code>): BG2 Y-Offset</li>
<li>BG3HOFS (<code>0x400_001C</code>): BG3 X-Offset</li>
<li>BG3VOFS (<code>0x400_001E</code>): BG3 Y-Offset</li>
</ul>
<p>Each of these are a <em>write only</em> <code>u16</code> location. Bits 0 through 8 are used, so
the offsets can be 0 through 511. They also only apply in regular backgrounds.
If a background is in an affine state then you'll use different IO registers to
control it (discussed in a later chapter).</p>
<p>The offset that you assign determines the pixel offset of the display area
relative to the start of the background scene, as if the screen was a camera
looking at the scene. In other words, as a BG X offset value increases, you can
think of it as the camera moving to the right, or as that background moving to
the left. Like when mario walks toward the goal. Similarly, when a BG Y offset
increases the camera is moving down, or the background is moving up, like when
mario falls down from a high platform.</p>
<p>Depending on how much the background is scrolled and the size of the background,
it will loop.</p>
<a class="header" href="#mosaic" id="mosaic"><h2>Mosaic</h2></a>
<p>As a special effect, you can apply mosaic to backgrounds and objects. It's just
a single flag for each background, so all backgrounds will use the same mosaic
settings when they have it enabled. What it actually does is split the normal
image into &quot;blocks&quot; and then each block gets the color of the top left pixel of
that block. This is the effect you see when link hits an electric foe with his
sword and the whole screen &quot;buzzes&quot; at you.</p>
<p>The mosaic control is a <em>write only</em> <code>u16</code> IO register at <code>0x400_004C</code>.</p>
<p>There's 4 bits each for:</p>
<ul>
<li>Horizontal BG stretch</li>
<li>Vertical BG stretch</li>
<li>Horizontal object stretch</li>
<li>Vertical object stretch</li>
</ul>
<p>The inputs should be 1 <em>less</em> than the desired block size. So if you set a
stretch value of 5 then pixels 0-5 would be part of the first block (6 pixels),
then 6-11 is the next block (another 6 pixels) and so on.</p>
<p>If you need to make a pixel other than the top left part of each block the one
that determines the mosaic color you can carefully offset the background or
image by a tiny bit, but of course that makes every mosaic block change its
target pixel. You can't change the target pixel on a block by block basis.</p>
<a class="header" href="#regular-objects" id="regular-objects"><h1>Regular Objects</h1></a>
<p>As with backgrounds, objects can be used in both an affine and non-affine way.
For this section we'll focus on the non-affine elements, and then we'll do all
the affine stuff in a later chapter.</p>
<a class="header" href="#objects-vs-sprites" id="objects-vs-sprites"><h2>Objects vs Sprites</h2></a>
<p>As <a href="https://www.coranac.com/tonc/text/regobj.htm">TONC</a> helpfully reminds us
(and then proceeds to not follow its own advice), we should always try to think
in terms of <em>objects</em>, not <em>sprites</em>. A sprite is a logical / software concern,
perhaps a player concern, whereas an object is a hardware concern.</p>
<p>What's more, a given sprite that the player sees might need more than one object
to display. Objects must be either square or rectangular (so sprite bits that
stick out probably call for a second object), and can only be from 8x8 to 64x64
(so anything bigger has to be two objects lined up to appear as one).</p>
<a class="header" href="#general-object-info" id="general-object-info"><h2>General Object Info</h2></a>
<p>Unlike with backgrounds, you can enable the object layer in any video mode.
There's space for 128 object definitions in OAM.</p>
<p>The display gets a number of cycles per scanline to process objects: 1210 by
default, but only 954 if you enable the &quot;HBlank interval free&quot; setting in the
display control register. The <a href="http://problemkaputt.de/gbatek.htm#lcdobjoverview">cycle cost per
object</a> depends on the
object's size and if it's using affine or regular mode, so enabling the HBlank
interval free setting doesn't cut the number of objects displayable by an exact
number of objects. The objects are processed in order of their definitions and
if you run out of cycles then the rest just don't get shown. If there's a
concern that you might run out of cycles you can place important objects (such
as the player) at the start of the list and then less important animation
objects later on.</p>
<a class="header" href="#ready-the-palette" id="ready-the-palette"><h2>Ready the Palette</h2></a>
<p>Objects use the palette the same as the background does. The only difference is
that the palette data for objects starts at <code>0x500_0200</code>.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub const PALRAM_OBJECT_BASE: VolatilePtr&lt;u16&gt; = VolatilePtr(0x500_0200 as *mut u16);
pub fn object_palette(slot: usize) -&gt; u16 {
assert!(slot &lt; 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).read() }
}
pub fn set_object_palette(slot: usize, color: u16) {
assert!(slot &lt; 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).write(color) }
}
#}</code></pre></pre>
<a class="header" href="#ready-the-tiles" id="ready-the-tiles"><h2>Ready the Tiles</h2></a>
<p>Objects, as with backgrounds, are composed of 8x8 tiles, and if you want
something bigger than 8x8 you have to use more than one tile put together.
Object tiles go into the final two charblocks of VRAM (indexes 4 and 5). Because
there's only two of them, they are sometimes called the lower block
(<code>0x601_0000</code>) and the higher/upper block (<code>0x601_4000</code>).</p>
<p>Tile indexes for sprites always offset from the base of the lower block, and
they always go 32 bytes at a time, regardless of if the object is set for 4bpp
or 8bpp. From this we can determine that there's 512 tile slots in each of the
two object charblocks. However, in video modes 3, 4, and 5 the space for the
background cuts into the lower charblock, so you can only safely use the upper
charblock.</p>
<p>With backgrounds you picked every single tile individually with a bunch of
screen entry values. Objects don't do that at all. Instead you pick a base tile,
size, and shape, then it figures out the rest from there. However, you may
recall back with the display control register something about an &quot;object memory
1d&quot; bit. This is where that comes into play.</p>
<ul>
<li>If object memory is set to be 2d (the default) then each charblock is treated
as 32 tiles by 32 tiles square. Each object has a base tile and dimensions,
and that just extracts directly from the charblock picture as if you were
selecting an area. This mode probably makes for the easiest image editing.</li>
<li>If object memory is set to be 1d then the tiles are loaded sequentially from
the starting point, enough to fill in the object's dimensions. This most
probably makes it the easiest to program with about things, since programming
languages are pretty good at 1d things.</li>
</ul>
<p>I'm not sure I explained that well, here's a picture:</p>
<p><img src="obj_memory_2d1d.jpg" alt="2d1d-diagram" /></p>
<p>In 2d mode, a new row of tiles starts every 32 tile indexes.</p>
<p>Of course, the mode that you actually end up using is not particularly
important, since it should be the job of your image conversion routine to get
everything all lined up and into place anyway.</p>
<a class="header" href="#set-the-object-attributes" id="set-the-object-attributes"><h2>Set the Object Attributes</h2></a>
<p>The final step is to assign the correct attributes to an object. Each object has
three <code>u16</code> values that make up its overall attributes.</p>
<p>Before we go into the details, I want to remind you that the hardware will
attempt to process every single object every single frame, and also that all of
the GBA's memory is cleared to 0 at startup. Why do these two things matter
right now? As you'll see in a second an &quot;all zero&quot; set of object attributes
causes an 8x8 object to appear at 0,0 using object tile index 0. This is usually
<em>not</em> what you want your unused objects to do. When your game first starts you
should take a moment to mark any objects you won't be using as objects to not
render.</p>
<a class="header" href="#objectattributesattr0" id="objectattributesattr0"><h3>ObjectAttributes.attr0</h3></a>
<ul>
<li>8 bits for row coordinate (marks the top of the sprite)</li>
<li>2 bits for object rendering: 0 = Normal, 1 = Affine, 2 = Disabled, 3 = Affine with double rendering area</li>
<li>2 bits for object mode: 0 = Normal, 1 = Alpha Blending, 2 = Object Window, 3 = Forbidden</li>
<li>1 bit for mosaic enabled</li>
<li>1 bit 8bpp color enabled</li>
<li>2 bits for shape: 0 = Square, 1 = Horizontal, 2 = Vertical, 3 = Forbidden</li>
</ul>
<p>If an object is 128 pixels big at Y &gt; 128 you'll get a strange looking result
where it acts like Y &gt; -128 and then displays partly off screen to the top.</p>
<a class="header" href="#objectattributesattr1" id="objectattributesattr1"><h3>ObjectAttributes.attr1</h3></a>
<ul>
<li>9 bit for column coordinate (marks the left of the sprite)</li>
<li>Either:
<ul>
<li>3 empty bits, 1 bit for horizontal flip, 1 bit for vertical flip (non-affine)</li>
<li>5 bits for affine index (affine)</li>
</ul>
</li>
<li>2 bits for size.</li>
</ul>
<table><thead><tr><th align="center"> Size </th><th align="center"> Square </th><th align="center"> Horizontal </th><th align="center"> Vertical</th></tr></thead><tbody>
<tr><td align="center"> 0 </td><td align="center"> 8x8 </td><td align="center"> 16x8 </td><td align="center"> 8x16 </td></tr>
<tr><td align="center"> 1 </td><td align="center"> 16x16 </td><td align="center"> 32x8 </td><td align="center"> 8x32 </td></tr>
<tr><td align="center"> 2 </td><td align="center"> 32x32 </td><td align="center"> 32x16 </td><td align="center"> 16x32 </td></tr>
<tr><td align="center"> 3 </td><td align="center"> 64x64 </td><td align="center"> 64x32 </td><td align="center"> 32x64 </td></tr>
</tbody></table>
<a class="header" href="#objectattributesattr2" id="objectattributesattr2"><h3>ObjectAttributes.attr2</h3></a>
<ul>
<li>10 bits for the base tile index</li>
<li>2 bits for priority</li>
<li>4 bits for the palbank index (4bpp mode only, ignored in 8bpp)</li>
</ul>
<a class="header" href="#objectattributes-summary" id="objectattributes-summary"><h3>ObjectAttributes summary</h3></a>
<p>So I said in the GBA memory mapping section that C people would tell you that
the object attributes should look like this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[repr(C)]
pub struct ObjectAttributes {
attr0: u16,
attr1: u16,
attr2: u16,
filler: i16,
}
#}</code></pre></pre>
<p>Except that:</p>
<ol>
<li>It's wasteful when we store object attributes on their own outside of OAM
(which we definitely might want to do).</li>
<li>In Rust we can't access just one field through a volatile pointer (our
pointers aren't actually volatile to begin with, just the ops we do with them
are). We have to read or write the whole pointer's value at a time.
Similarly, we can't do things like <code>|=</code> and <code>&amp;=</code> with volatile in Rust. So in
rust we can't have a volatile pointer to an ObjectAttributes and then write
to just the three &quot;real&quot; values and not touch the filler field. Having the
filler value in there just means we have to dance around it more, not less.</li>
<li>We want to newtype this whole thing to prevent accidental invalid states from
being written into memory.</li>
</ol>
<p>So we will not be using that representation. At the same time we want to have no
overhead, so we will stick to three <code>u16</code> values. We could newtype each
individual field to be its own type (<code>ObjectAttributesAttr0</code> or something silly
like that), since there aren't actual dependencies between two different fields
such that a change in one can throw another into a forbidden state. The worst
that can happen is if we disable or enable affine mode (<code>attr0</code>) it can change
the meaning of <code>attr1</code>. The changed meaning isn't actually in invalid state
though, so we <em>could</em> make each field its own type if we wanted.</p>
<p>However, when you think about it, I can't imagine a common situation where we do
something like make an <code>attr0</code> value that we then want to save on its own and
apply to several different <code>ObjectAttributes</code> that we make during a game. That
just doesn't sound likely to me. So, we'll go the route where <code>ObjectAttributes</code>
is just a big black box to the outside world and we don't need to think about
the three fields internally as being separate.</p>
<p>First we make it so that we can get and set object attributes from memory:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub const OAM: usize = 0x700_0000;
pub fn object_attributes(slot: usize) -&gt; ObjectAttributes {
assert!(slot &lt; 128);
let ptr = VolatilePtr((OAM + slot * (size_of::&lt;u16&gt;() * 4)) as *mut u16);
unsafe {
ObjectAttributes {
attr0: ptr.read(),
attr1: ptr.offset(1).read(),
attr2: ptr.offset(2).read(),
}
}
}
pub fn set_object_attributes(slot: usize, obj: ObjectAttributes) {
assert!(slot &lt; 128);
let ptr = VolatilePtr((OAM + slot * (size_of::&lt;u16&gt;() * 4)) as *mut u16);
unsafe {
ptr.write(obj.attr0);
ptr.offset(1).write(obj.attr1);
ptr.offset(2).write(obj.attr2);
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ObjectAttributes {
attr0: u16,
attr1: u16,
attr2: u16,
}
#}</code></pre></pre>
<p>Then we add a billion methods to the <code>ObjectAttributes</code> type so that we can
actually set all the different values that we want to set.</p>
<p>This code block is the last thing on this page so if you don't wanna scroll past
the whole thing you can just go to the next page.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[derive(Debug, Clone, Copy)]
pub enum ObjectRenderMode {
Normal,
Affine,
Disabled,
DoubleAreaAffine,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectMode {
Normal,
AlphaBlending,
ObjectWindow,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectShape {
Square,
Horizontal,
Vertical,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectOrientation {
Normal,
HFlip,
VFlip,
BothFlip,
Affine(u8),
}
impl ObjectAttributes {
pub fn row(&amp;self) -&gt; u16 {
self.attr0 &amp; 0b1111_1111
}
pub fn column(&amp;self) -&gt; u16 {
self.attr1 &amp; 0b1_1111_1111
}
pub fn rendering(&amp;self) -&gt; ObjectRenderMode {
match (self.attr0 &gt;&gt; 8) &amp; 0b11 {
0 =&gt; ObjectRenderMode::Normal,
1 =&gt; ObjectRenderMode::Affine,
2 =&gt; ObjectRenderMode::Disabled,
3 =&gt; ObjectRenderMode::DoubleAreaAffine,
_ =&gt; unimplemented!(),
}
}
pub fn mode(&amp;self) -&gt; ObjectMode {
match (self.attr0 &gt;&gt; 0xA) &amp; 0b11 {
0 =&gt; ObjectMode::Normal,
1 =&gt; ObjectMode::AlphaBlending,
2 =&gt; ObjectMode::ObjectWindow,
_ =&gt; unimplemented!(),
}
}
pub fn mosaic(&amp;self) -&gt; bool {
((self.attr0 &lt;&lt; 3) as i16) &lt; 0
}
pub fn two_fifty_six_colors(&amp;self) -&gt; bool {
((self.attr0 &lt;&lt; 2) as i16) &lt; 0
}
pub fn shape(&amp;self) -&gt; ObjectShape {
match (self.attr0 &gt;&gt; 0xE) &amp; 0b11 {
0 =&gt; ObjectShape::Square,
1 =&gt; ObjectShape::Horizontal,
2 =&gt; ObjectShape::Vertical,
_ =&gt; unimplemented!(),
}
}
pub fn orientation(&amp;self) -&gt; ObjectOrientation {
if (self.attr0 &gt;&gt; 8) &amp; 1 &gt; 0 {
ObjectOrientation::Affine((self.attr1 &gt;&gt; 9) as u8 &amp; 0b1_1111)
} else {
match (self.attr1 &gt;&gt; 0xC) &amp; 0b11 {
0 =&gt; ObjectOrientation::Normal,
1 =&gt; ObjectOrientation::HFlip,
2 =&gt; ObjectOrientation::VFlip,
3 =&gt; ObjectOrientation::BothFlip,
}
}
}
pub fn size(&amp;self) -&gt; u16 {
self.attr1 &gt;&gt; 0xE
}
pub fn tile_index(&amp;self) -&gt; u16 {
self.attr2 &amp; 0b11_1111_1111
}
pub fn priority(&amp;self) -&gt; u16 {
self.attr2 &gt;&gt; 0xA
}
pub fn palbank(&amp;self) -&gt; u16 {
self.attr2 &gt;&gt; 0xC
}
//
pub fn set_row(&amp;mut self, row: u16) {
self.attr0 &amp;= !0b1111_1111;
self.attr0 |= row &amp; 0b1111_1111;
}
pub fn set_column(&amp;mut self, col: u16) {
self.attr1 &amp;= !0b1_1111_1111;
self.attr2 |= col &amp; 0b1_1111_1111;
}
pub fn set_rendering(&amp;mut self, rendering: ObjectRenderMode) {
const RENDERING_MASK: u16 = 0b11 &lt;&lt; 8;
self.attr0 &amp;= !RENDERING_MASK;
self.attr0 |= (rendering as u16) &lt;&lt; 8;
}
pub fn set_mode(&amp;mut self, mode: ObjectMode) {
const MODE_MASK: u16 = 0b11 &lt;&lt; 0xA;
self.attr0 &amp;= MODE_MASK;
self.attr0 |= (mode as u16) &lt;&lt; 0xA;
}
pub fn set_mosaic(&amp;mut self, bit: bool) {
const MOSAIC_BIT: u16 = 1 &lt;&lt; 0xC;
if bit {
self.attr0 |= MOSAIC_BIT
} else {
self.attr0 &amp;= !MOSAIC_BIT
}
}
pub fn set_two_fifty_six_colors(&amp;mut self, bit: bool) {
const COLOR_MODE_BIT: u16 = 1 &lt;&lt; 0xD;
if bit {
self.attr0 |= COLOR_MODE_BIT
} else {
self.attr0 &amp;= !COLOR_MODE_BIT
}
}
pub fn set_shape(&amp;mut self, shape: ObjectShape) {
self.attr0 &amp;= 0b0011_1111_1111_1111;
self.attr0 |= (shape as u16) &lt;&lt; 0xE;
}
pub fn set_orientation(&amp;mut self, orientation: ObjectOrientation) {
const AFFINE_INDEX_MASK: u16 = 0b1_1111 &lt;&lt; 9;
self.attr1 &amp;= !AFFINE_INDEX_MASK;
let bits = match orientation {
ObjectOrientation::Affine(index) =&gt; (index as u16) &lt;&lt; 9,
ObjectOrientation::Normal =&gt; 0,
ObjectOrientation::HFlip =&gt; 1 &lt;&lt; 0xC,
ObjectOrientation::VFlip =&gt; 1 &lt;&lt; 0xD,
ObjectOrientation::BothFlip =&gt; 0b11 &lt;&lt; 0xC,
};
self.attr1 |= bits;
}
pub fn set_size(&amp;mut self, size: u16) {
self.attr1 &amp;= 0b0011_1111_1111_1111;
self.attr1 |= size &lt;&lt; 14;
}
pub fn set_tile_index(&amp;mut self, index: u16) {
self.attr2 &amp;= !0b11_1111_1111;
self.attr2 |= 0b11_1111_1111 &amp; index;
}
pub fn set_priority(&amp;mut self, priority: u16) {
self.attr2 &amp;= !0b0000_1100_0000_0000;
self.attr2 |= (priority &amp; 0b11) &lt;&lt; 0xA;
}
pub fn set_palbank(&amp;mut self, palbank: u16) {
self.attr2 &amp;= !0b1111_0000_0000_0000;
self.attr2 |= (palbank &amp; 0b1111) &lt;&lt; 0xC;
}
}
#}</code></pre></pre>
<a class="header" href="#gba-rng" id="gba-rng"><h1>GBA RNG</h1></a> <a class="header" href="#gba-rng" id="gba-rng"><h1>GBA RNG</h1></a>
<p>TODO</p> <p>TODO</p>
<a class="header" href="#memory_game" id="memory_game"><h1>memory_game</h1></a> <a class="header" href="#memory_game" id="memory_game"><h1>memory_game</h1></a>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -286,3 +286,208 @@ impl RegularScreenblockEntry {
self.0 |= palbank_index; self.0 |= palbank_index;
} }
} }
pub const PALRAM_OBJECT_BASE: VolatilePtr<u16> = VolatilePtr(0x500_0200 as *mut u16);
pub fn object_palette(slot: usize) -> u16 {
assert!(slot < 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).read() }
}
pub fn set_object_palette(slot: usize, color: u16) {
assert!(slot < 256);
unsafe { PALRAM_OBJECT_BASE.offset(slot as isize).write(color) }
}
pub const OAM: usize = 0x700_0000;
pub fn object_attributes(slot: usize) -> ObjectAttributes {
assert!(slot < 128);
let ptr = VolatilePtr((OAM + slot * (size_of::<u16>() * 4)) as *mut u16);
unsafe {
ObjectAttributes {
attr0: ptr.read(),
attr1: ptr.offset(1).read(),
attr2: ptr.offset(2).read(),
}
}
}
pub fn set_object_attributes(slot: usize, obj: ObjectAttributes) {
assert!(slot < 128);
let ptr = VolatilePtr((OAM + slot * (size_of::<u16>() * 4)) as *mut u16);
unsafe {
ptr.write(obj.attr0);
ptr.offset(1).write(obj.attr1);
ptr.offset(2).write(obj.attr2);
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ObjectAttributes {
attr0: u16,
attr1: u16,
attr2: u16,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectRenderMode {
Normal,
Affine,
Disabled,
DoubleAreaAffine,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectMode {
Normal,
AlphaBlending,
ObjectWindow,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectShape {
Square,
Horizontal,
Vertical,
}
#[derive(Debug, Clone, Copy)]
pub enum ObjectOrientation {
Normal,
HFlip,
VFlip,
BothFlip,
Affine(u8),
}
impl ObjectAttributes {
pub fn row(&self) -> u16 {
self.attr0 & 0b1111_1111
}
pub fn column(&self) -> u16 {
self.attr1 & 0b1_1111_1111
}
pub fn rendering(&self) -> ObjectRenderMode {
match (self.attr0 >> 8) & 0b11 {
0 => ObjectRenderMode::Normal,
1 => ObjectRenderMode::Affine,
2 => ObjectRenderMode::Disabled,
3 => ObjectRenderMode::DoubleAreaAffine,
_ => unimplemented!(),
}
}
pub fn mode(&self) -> ObjectMode {
match (self.attr0 >> 0xA) & 0b11 {
0 => ObjectMode::Normal,
1 => ObjectMode::AlphaBlending,
2 => ObjectMode::ObjectWindow,
_ => unimplemented!(),
}
}
pub fn mosaic(&self) -> bool {
((self.attr0 << 3) as i16) < 0
}
pub fn two_fifty_six_colors(&self) -> bool {
((self.attr0 << 2) as i16) < 0
}
pub fn shape(&self) -> ObjectShape {
match (self.attr0 >> 0xE) & 0b11 {
0 => ObjectShape::Square,
1 => ObjectShape::Horizontal,
2 => ObjectShape::Vertical,
_ => unimplemented!(),
}
}
pub fn orientation(&self) -> ObjectOrientation {
if (self.attr0 >> 8) & 1 > 0 {
ObjectOrientation::Affine((self.attr1 >> 9) as u8 & 0b1_1111)
} else {
match (self.attr1 >> 0xC) & 0b11 {
0 => ObjectOrientation::Normal,
1 => ObjectOrientation::HFlip,
2 => ObjectOrientation::VFlip,
3 => ObjectOrientation::BothFlip,
}
}
}
pub fn size(&self) -> u16 {
self.attr1 >> 0xE
}
pub fn tile_index(&self) -> u16 {
self.attr2 & 0b11_1111_1111
}
pub fn priority(&self) -> u16 {
self.attr2 >> 0xA
}
pub fn palbank(&self) -> u16 {
self.attr2 >> 0xC
}
//
pub fn set_row(&mut self, row: u16) {
self.attr0 &= !0b1111_1111;
self.attr0 |= row & 0b1111_1111;
}
pub fn set_column(&mut self, col: u16) {
self.attr1 &= !0b1_1111_1111;
self.attr2 |= col & 0b1_1111_1111;
}
pub fn set_rendering(&mut self, rendering: ObjectRenderMode) {
const RENDERING_MASK: u16 = 0b11 << 8;
self.attr0 &= !RENDERING_MASK;
self.attr0 |= (rendering as u16) << 8;
}
pub fn set_mode(&mut self, mode: ObjectMode) {
const MODE_MASK: u16 = 0b11 << 0xA;
self.attr0 &= MODE_MASK;
self.attr0 |= (mode as u16) << 0xA;
}
pub fn set_mosaic(&mut self, bit: bool) {
const MOSAIC_BIT: u16 = 1 << 0xC;
if bit {
self.attr0 |= MOSAIC_BIT
} else {
self.attr0 &= !MOSAIC_BIT
}
}
pub fn set_two_fifty_six_colors(&mut self, bit: bool) {
const COLOR_MODE_BIT: u16 = 1 << 0xD;
if bit {
self.attr0 |= COLOR_MODE_BIT
} else {
self.attr0 &= !COLOR_MODE_BIT
}
}
pub fn set_shape(&mut self, shape: ObjectShape) {
self.attr0 &= 0b0011_1111_1111_1111;
self.attr0 |= (shape as u16) << 0xE;
}
pub fn set_orientation(&mut self, orientation: ObjectOrientation) {
const AFFINE_INDEX_MASK: u16 = 0b1_1111 << 9;
self.attr1 &= !AFFINE_INDEX_MASK;
let bits = match orientation {
ObjectOrientation::Affine(index) => (index as u16) << 9,
ObjectOrientation::Normal => 0,
ObjectOrientation::HFlip => 1 << 0xC,
ObjectOrientation::VFlip => 1 << 0xD,
ObjectOrientation::BothFlip => 0b11 << 0xC,
};
self.attr1 |= bits;
}
pub fn set_size(&mut self, size: u16) {
self.attr1 &= 0b0011_1111_1111_1111;
self.attr1 |= size << 14;
}
pub fn set_tile_index(&mut self, index: u16) {
self.attr2 &= !0b11_1111_1111;
self.attr2 |= 0b11_1111_1111 & index;
}
pub fn set_priority(&mut self, priority: u16) {
self.attr2 &= !0b0000_1100_0000_0000;
self.attr2 |= (priority & 0b11) << 0xA;
}
pub fn set_palbank(&mut self, palbank: u16) {
self.attr2 &= !0b1111_0000_0000_0000;
self.attr2 |= (palbank & 0b1111) << 0xC;
}
}