mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Allow recolouring of the background using DMA
This commit is contained in:
parent
edcd37c203
commit
de0c4ca4f4
|
@ -8,7 +8,7 @@ use alloc::boxed::Box;
|
||||||
use agb::{
|
use agb::{
|
||||||
display::{
|
display::{
|
||||||
example_logo,
|
example_logo,
|
||||||
tiled::{RegularBackgroundSize, TileFormat},
|
tiled::{RegularBackgroundSize, TileFormat, TiledMap},
|
||||||
},
|
},
|
||||||
interrupt::VBlank,
|
interrupt::VBlank,
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,8 @@ use agb::{
|
||||||
fn main(mut gba: agb::Gba) -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let (gfx, mut vram) = gba.display.video.tiled0();
|
let (gfx, mut vram) = gba.display.video.tiled0();
|
||||||
|
|
||||||
|
let mut input = agb::input::ButtonController::new();
|
||||||
|
|
||||||
let mut map = gfx.background(
|
let mut map = gfx.background(
|
||||||
agb::display::Priority::P0,
|
agb::display::Priority::P0,
|
||||||
RegularBackgroundSize::Background32x32,
|
RegularBackgroundSize::Background32x32,
|
||||||
|
@ -30,12 +32,36 @@ fn main(mut gba: agb::Gba) -> ! {
|
||||||
let vblank = VBlank::get();
|
let vblank = VBlank::get();
|
||||||
|
|
||||||
let offsets: Box<[_]> = (0..160 * 2).collect();
|
let offsets: Box<[_]> = (0..160 * 2).collect();
|
||||||
|
let colours: Box<[_]> = (0..160).map(|i| ((i * 0xffff) / 160) as u16).collect();
|
||||||
|
|
||||||
let mut frame = 0;
|
let mut frame = 0;
|
||||||
|
|
||||||
loop {
|
let mut effect = false;
|
||||||
let _transfer = unsafe { dma.hblank_transfer(&map.x_scroll_dma(), &offsets[frame..]) };
|
|
||||||
|
|
||||||
|
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();
|
vblank.wait_for_vblank();
|
||||||
frame += 1;
|
frame += 1;
|
||||||
if frame > 160 {
|
if frame > 160 {
|
||||||
|
|
|
@ -258,8 +258,7 @@ impl<'a> InfiniteScrolledMap<'a> {
|
||||||
|
|
||||||
let offset = self.current_pos - (x_start * 8, y_start * 8).into();
|
let offset = self.current_pos - (x_start * 8, y_start * 8).into();
|
||||||
|
|
||||||
self.map
|
self.map.set_scroll_pos((offset.x as i16, offset.y as i16));
|
||||||
.set_scroll_pos((offset.x as i16, offset.y as i16).into());
|
|
||||||
self.offset = (x_start, y_start).into();
|
self.offset = (x_start, y_start).into();
|
||||||
|
|
||||||
let copy_from = self.copied_up_to;
|
let copy_from = self.copied_up_to;
|
||||||
|
|
|
@ -291,8 +291,8 @@ impl RegularMap {
|
||||||
self.scroll
|
self.scroll
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_scroll_pos(&mut self, pos: Vector2D<i16>) {
|
pub fn set_scroll_pos(&mut self, pos: impl Into<Vector2D<i16>>) {
|
||||||
self.scroll = pos;
|
self.scroll = pos.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
|
@ -5,6 +5,7 @@ use alloc::{slice, vec::Vec};
|
||||||
use crate::{
|
use crate::{
|
||||||
agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd},
|
agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd},
|
||||||
display::palette16,
|
display::palette16,
|
||||||
|
dma,
|
||||||
hash_map::{Entry, HashMap},
|
hash_map::{Entry, HashMap},
|
||||||
memory_mapped::MemoryMapped1DArray,
|
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.
|
/// Copies palettes to the background palettes without any checks.
|
||||||
pub fn set_background_palettes(&mut self, palettes: &[palette16::Palette16]) {
|
pub fn set_background_palettes(&mut self, palettes: &[palette16::Palette16]) {
|
||||||
for (palette_index, entry) in palettes.iter().enumerate() {
|
for (palette_index, entry) in palettes.iter().enumerate() {
|
||||||
|
|
Loading…
Reference in a new issue