Allow recolouring of the background using DMA

This commit is contained in:
Gwilym Inzani 2024-02-21 11:56:49 +00:00
parent edcd37c203
commit de0c4ca4f4
4 changed files with 63 additions and 7 deletions

View file

@ -8,7 +8,7 @@ use alloc::boxed::Box;
use agb::{
display::{
example_logo,
tiled::{RegularBackgroundSize, TileFormat},
tiled::{RegularBackgroundSize, TileFormat, TiledMap},
},
interrupt::VBlank,
};
@ -17,6 +17,8 @@ use agb::{
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut input = agb::input::ButtonController::new();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
@ -30,12 +32,36 @@ fn main(mut gba: agb::Gba) -> ! {
let vblank = VBlank::get();
let offsets: Box<[_]> = (0..160 * 2).collect();
let colours: Box<[_]> = (0..160).map(|i| ((i * 0xffff) / 160) as u16).collect();
let mut frame = 0;
loop {
let _transfer = unsafe { dma.hblank_transfer(&map.x_scroll_dma(), &offsets[frame..]) };
let mut effect = false;
loop {
input.update();
if input.is_just_pressed(agb::input::Button::A) {
effect = !effect;
}
let _x_scroll_transfer = if effect {
Some(unsafe { dma.hblank_transfer(&map.x_scroll_dma(), &offsets[frame..]) })
} else {
map.set_scroll_pos((0i16, 0i16));
None
};
let _background_color_transfer = if !effect {
Some(unsafe {
dma.hblank_transfer(&vram.background_palette_colour_dma(0, 2), &colours)
})
} else {
vram.set_background_palette_colour(0, 0, 0xffff);
None
};
map.commit(&mut vram);
vblank.wait_for_vblank();
frame += 1;
if frame > 160 {

View file

@ -258,8 +258,7 @@ impl<'a> InfiniteScrolledMap<'a> {
let offset = self.current_pos - (x_start * 8, y_start * 8).into();
self.map
.set_scroll_pos((offset.x as i16, offset.y as i16).into());
self.map.set_scroll_pos((offset.x as i16, offset.y as i16));
self.offset = (x_start, y_start).into();
let copy_from = self.copied_up_to;

View file

@ -291,8 +291,8 @@ impl RegularMap {
self.scroll
}
pub fn set_scroll_pos(&mut self, pos: Vector2D<i16>) {
self.scroll = pos;
pub fn set_scroll_pos(&mut self, pos: impl Into<Vector2D<i16>>) {
self.scroll = pos.into();
}
#[must_use]

View file

@ -5,6 +5,7 @@ use alloc::{slice, vec::Vec};
use crate::{
agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd},
display::palette16,
dma,
hash_map::{Entry, HashMap},
memory_mapped::MemoryMapped1DArray,
};
@ -424,6 +425,36 @@ impl VRamManager {
}
}
/// The DMA register for controlling a single colour in a single background. Good for drawing gradients
#[must_use]
pub fn background_palette_colour_dma(
&self,
pal_index: usize,
colour_index: usize,
) -> dma::DmaControllable<u16> {
assert!(pal_index < 16);
assert!(colour_index < 16);
dma::DmaControllable::new(unsafe {
PALETTE_BACKGROUND
.as_ptr()
.add(16 * pal_index + colour_index)
})
}
/// Sets a single colour for a given background palette. Takes effect immediately
pub fn set_background_palette_colour(
&mut self,
pal_index: usize,
colour_index: usize,
colour: u16,
) {
assert!(pal_index < 16);
assert!(colour_index < 16);
PALETTE_BACKGROUND.set(colour_index + 16 * pal_index, colour);
}
/// Copies palettes to the background palettes without any checks.
pub fn set_background_palettes(&mut self, palettes: &[palette16::Palette16]) {
for (palette_index, entry) in palettes.iter().enumerate() {