diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 2a24fe1..676aac9 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -18,6 +18,6 @@ * [GBA Memory Mapping](ch03/gba_memory_mapping.md) * [Tile Data](ch03/tile_data.md) * [Regular Backgrounds](ch03/regular_backgrounds.md) - * [Object Basics](ch03/object_basics.md) + * [Regular Objects](ch03/regular_objects.md) * [GBA RNG](ch03/gba_rng.md) * [memory_game](ch03/memory_game.md) diff --git a/book/src/ch03/object_basics.md b/book/src/ch03/object_basics.md deleted file mode 100644 index 18b751e..0000000 --- a/book/src/ch03/object_basics.md +++ /dev/null @@ -1,2 +0,0 @@ -# Object Basics -TODO diff --git a/book/src/ch03/regular_backgrounds.md b/book/src/ch03/regular_backgrounds.md index c49738a..c7872cc 100644 --- a/book/src/ch03/regular_backgrounds.md +++ b/book/src/ch03/regular_backgrounds.md @@ -23,6 +23,9 @@ When you want regular tiled display, you must use video mode 0 or 1. We will not cover affine backgrounds in this chapter, so we will naturally be using video mode 0. +Also, note that you have to enable each background layer that you want to use +within the display control register. + ## Get Your Palette Ready Background palette starts at `0x5000000` and is 256 `u16` values long. It'd @@ -36,12 +39,12 @@ pub const PALRAM_BG_BASE: VolatilePtr = VolatilePtr(0x500_0000 as *mut u16) pub fn bg_palette(slot: usize) -> u16 { assert!(slot < 256); - PALRAM_BG_BASE.offset(slot as isize).read() + unsafe { PALRAM_BG_BASE.offset(slot as isize).read() } } pub fn set_bg_palette(slot: usize, color: u16) { assert!(slot < 256); - PALRAM_BG_BASE.offset(slot as isize).write(color) + unsafe { PALRAM_BG_BASE.offset(slot as isize).write(color) } } ``` @@ -77,28 +80,28 @@ pub fn bg_tile_4pp(base_block: usize, tile_index: usize) -> Tile4bpp { assert!(base_block < 4); assert!(tile_index < 512); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile4bpp).read() + unsafe { VolatilePtr(address as *mut Tile4bpp).read() } } pub fn set_bg_tile_4pp(base_block: usize, tile_index: usize, tile: Tile4bpp) { assert!(base_block < 4); assert!(tile_index < 512); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile4bpp).write(tile) + unsafe { VolatilePtr(address as *mut Tile4bpp).write(tile) } } pub fn bg_tile_8pp(base_block: usize, tile_index: usize) -> Tile8bpp { assert!(base_block < 4); assert!(tile_index < 256); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile8bpp).read() + unsafe { VolatilePtr(address as *mut Tile8bpp).read() } } pub fn set_bg_tile_8pp(base_block: usize, tile_index: usize, tile: Tile8bpp) { assert!(base_block < 4); assert!(tile_index < 256); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile8bpp).write(tile) + unsafe { VolatilePtr(address as *mut Tile8bpp).write(tile) } } ``` @@ -218,9 +221,10 @@ As long as you stay within the background memory region for charblocks (that is, rendering to reach outside of the background charblocks you'll get an implementation defined result. It's not the dreaded "undefined behavior" we're often worried about in programming, but the results _are_ determined by what -you're running the game on. With real hardware, you get a bizarre result -(basically another way to put garbage on the screen). If you use an emulator it -might or might not allow for you to do this, it's up to the emulator writers. +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. ## Set Your IO Registers @@ -287,9 +291,12 @@ it will loop. 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. +settings when they have it enabled. What it actually does is split the normal +image into "blocks" 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 "buzzes" at you. -The mosaic control is a read/write `u16` IO register at `0x400_004C`. +The mosaic control is a _write only_ `u16` IO register at `0x400_004C`. There's 4 bits each for: @@ -298,4 +305,11 @@ There's 4 bits each for: * Horizontal object stretch * Vertical object stretch -The \ No newline at end of file +The inputs should be 1 _less_ 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. + +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. diff --git a/book/src/ch03/regular_objects.md b/book/src/ch03/regular_objects.md new file mode 100644 index 0000000..89c14a6 --- /dev/null +++ b/book/src/ch03/regular_objects.md @@ -0,0 +1,15 @@ +# Regular Objects + +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. + +TODO: tio afero ke mi diris + +## Objects vs Sprites + +## Ready the Palette + +## Ready the Tiles + +## Set the Object Attributes diff --git a/book/src/introduction.md b/book/src/introduction.md index 27a0d80..328d265 100644 --- a/book/src/introduction.md +++ b/book/src/introduction.md @@ -27,7 +27,9 @@ if you want to get them that way. ## Expected Knowledge I will try not to ask too much of the reader ahead of time, but you are expected -to have already read [The Rust Book](https://doc.rust-lang.org/book/). +to have already read [The Rust Book](https://doc.rust-lang.org/book/). Having +also read through the [Rustonomicon](https://doc.rust-lang.org/nomicon/) is +appreciated but not required. 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 @@ -56,6 +58,3 @@ resources as well: * [GBATEK](http://problemkaputt.de/gbatek.htm), a homebrew tech manual for GBA/NDS/DSi. We will regularly link to parts of it when talking about various bits of the GBA. -* [CowBite](https://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm) 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. diff --git a/examples/memory_game.rs b/examples/memory_game.rs index 923d55f..3a2ccfa 100644 --- a/examples/memory_game.rs +++ b/examples/memory_game.rs @@ -204,40 +204,40 @@ pub const PALRAM_BG_BASE: VolatilePtr = VolatilePtr(0x500_0000 as *mut u16) pub fn bg_palette(slot: usize) -> u16 { assert!(slot < 256); - PALRAM_BG_BASE.offset(slot as isize).read() + unsafe { PALRAM_BG_BASE.offset(slot as isize).read() } } pub fn set_bg_palette(slot: usize, color: u16) { assert!(slot < 256); - PALRAM_BG_BASE.offset(slot as isize).write(color) + unsafe { PALRAM_BG_BASE.offset(slot as isize).write(color) } } pub fn bg_tile_4pp(base_block: usize, tile_index: usize) -> Tile4bpp { assert!(base_block < 4); assert!(tile_index < 512); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile4bpp).read() + unsafe { VolatilePtr(address as *mut Tile4bpp).read() } } pub fn set_bg_tile_4pp(base_block: usize, tile_index: usize, tile: Tile4bpp) { assert!(base_block < 4); assert!(tile_index < 512); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile4bpp).write(tile) + unsafe { VolatilePtr(address as *mut Tile4bpp).write(tile) } } pub fn bg_tile_8pp(base_block: usize, tile_index: usize) -> Tile8bpp { assert!(base_block < 4); assert!(tile_index < 256); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile8bpp).read() + unsafe { VolatilePtr(address as *mut Tile8bpp).read() } } pub fn set_bg_tile_8pp(base_block: usize, tile_index: usize, tile: Tile8bpp) { assert!(base_block < 4); assert!(tile_index < 256); let address = VRAM + size_of::() * base_block + size_of::() * tile_index; - VolatilePtr(address as *mut Tile8bpp).write(tile) + unsafe { VolatilePtr(address as *mut Tile8bpp).write(tile) } } #[derive(Clone, Copy)]