From ebc4e15f3d9da4d944922eb6b67b6992f1930ca4 Mon Sep 17 00:00:00 2001 From: Corwin <corwin@kuiper.dev> Date: Fri, 15 Jul 2022 21:59:36 +0100 Subject: [PATCH 1/9] constify sprite function --- agb/src/display/object.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 0b88c3e1..8f18f34b 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -249,8 +249,11 @@ impl Tag { } #[must_use] - pub fn sprite(&self, idx: usize) -> &'static Sprite { - &self.sprites()[idx] + pub const fn sprite(&self, idx: usize) -> &'static Sprite { + if idx >= self.len { + panic!("out of bounds access to sprite"); + } + unsafe { &*self.sprites.add(idx) } } #[inline] From 8a55fc7f0e7cca350fa2568b77d0ca95e92bf420 Mon Sep 17 00:00:00 2001 From: Corwin <corwin@kuiper.dev> Date: Sat, 16 Jul 2022 09:08:35 +0100 Subject: [PATCH 2/9] support larger sprites --- agb-image-converter/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 6077dc1c..baa3a92c 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -115,7 +115,7 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream { for frame in frames { let width = frame.width(); - assert!(width == frame.height() && width.is_power_of_two() && width <= 32); + assert!(width == frame.height() && width.is_power_of_two() && width <= 64); let image = Image::load_from_dyn_image(frame); add_to_optimiser( From 2026e49569627e889dbd0d606e09abc1c9a6d242 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper <gw@ilym.me> Date: Fri, 15 Jul 2022 23:55:19 +0100 Subject: [PATCH 3/9] Start the tile ram one tile in to prevent overwriting the transparent tile --- agb/src/display/tiled/vram_manager.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index a2a2ce15..6caa8956 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -17,7 +17,7 @@ const PALETTE_BACKGROUND: MemoryMapped1DArray<u16, 256> = static TILE_ALLOCATOR: BlockAllocator = unsafe { BlockAllocator::new(StartEnd { - start: || TILE_RAM_START, + start: || TILE_RAM_START + 8 * 8, end: || TILE_RAM_START + 0x8000, }) }; From 1be10ba45031b921322bb7a0e76f754bd18d2c83 Mon Sep 17 00:00:00 2001 From: Corwin <corwin@kuiper.dev> Date: Sat, 16 Jul 2022 13:36:33 +0100 Subject: [PATCH 4/9] align sprite data to 2 byte boundaries --- agb-image-converter/src/lib.rs | 2 +- agb/src/display/object.rs | 33 ++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index baa3a92c..c9c58898 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -154,7 +154,7 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream { quote! { Sprite::new( &PALETTES[#assignment], - #data, + align_bytes!(u16, #data), Size::from_width_height(#width, #height) ) } diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 8f18f34b..b5a3287b 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -135,11 +135,32 @@ pub enum Size { S32x64 = 0b10_11, } +#[repr(C)] // guarantee 'bytes' comes after '_align' +pub struct AlignedAs<Align, Bytes: ?Sized> { + pub _align: [Align; 0], + pub bytes: Bytes, +} + +#[macro_export] +macro_rules! align_bytes { + ($align_ty:ty, $data:literal) => {{ + use $crate::display::object::AlignedAs; + + const ALIGNED: &AlignedAs<$align_ty, [u8]> = &AlignedAs { + _align: [], + bytes: *$data, + }; + + &ALIGNED.bytes + }}; +} + #[macro_export] macro_rules! include_aseprite { ($($aseprite_path: expr),*) => {{ use $crate::display::object::{Size, Sprite, Tag, TagMap, Graphics}; use $crate::display::palette16::Palette16; + use $crate::align_bytes; $crate::include_aseprite_inner!($($aseprite_path),*); @@ -778,11 +799,13 @@ impl SpriteControllerInner { }; unsafe { - dma::dma_copy16( - sprite.data.as_ptr().cast(), - dest.as_ptr().cast(), - sprite.data.len() / 2, - ); + dest.as_ptr() + .copy_from_nonoverlapping(sprite.data.as_ptr(), sprite.data.len()); + // dma::dma_copy16( + // sprite.data.as_ptr().cast(), + // dest.as_ptr().cast(), + // sprite.data.len() / 2, + // ); } let storage = Storage::from_sprite_ptr(dest); From 3d579390c8b652f1175cf14b553dac09c11064c4 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper <gw@ilym.me> Date: Sat, 16 Jul 2022 18:02:55 +0100 Subject: [PATCH 5/9] Make the num macro work if you don't depend on agb_macros yourself --- agb-fixnum/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/agb-fixnum/src/lib.rs b/agb-fixnum/src/lib.rs index efa6586e..ebbe2179 100644 --- a/agb-fixnum/src/lib.rs +++ b/agb-fixnum/src/lib.rs @@ -9,10 +9,13 @@ use core::{ }, }; +#[doc(hidden)] +pub use agb_macros::num as num_inner; + #[macro_export] macro_rules! num { ($value:literal) => {{ - $crate::Num::new_from_parts(agb_macros::num!($value)) + $crate::Num::new_from_parts($crate::num_inner!($value)) }}; } From a5e0e145d2a41d8cdca9a26f56250631adecc590 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper <gw@ilym.me> Date: Sat, 16 Jul 2022 18:47:39 +0100 Subject: [PATCH 6/9] Attempt to support changing the volume of stereo sound --- agb/src/sound/mixer/mixer.s | 8 +++++--- agb/src/sound/mixer/sw_mixer.rs | 7 ++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/agb/src/sound/mixer/mixer.s b/agb/src/sound/mixer/mixer.s index 33f59172..4af591e1 100644 --- a/agb/src/sound/mixer/mixer.s +++ b/agb/src/sound/mixer/mixer.s @@ -95,10 +95,12 @@ agb_arm_func agb_rs__mixer_add_stereo @ Arguments @ r0 - pointer to the data to be copied (u8 array) @ r1 - pointer to the sound buffer (i16 array which will alternate left and right channels, 32-bit aligned) + @ r2 - volume to play the sound at @ @ The sound buffer must be SOUND_BUFFER_SIZE * 2 in size = 176 * 2 - push {r4-r8} + push {r4-r9} + mov r9, r2 ldr r5, =0x00000FFF ldr r8, =agb_rs__buffer_size @@ -128,7 +130,7 @@ agb_arm_func agb_rs__mixer_add_stereo lsl r6, r6, #24 @ r6 = | R | 0 | 0 | 0 | drop everything except the right sample orr r6, r7, r6, asr #8 @ r6 = | 1 | R | 1 | L | now we have it perfectly set up - add r4, r4, r6, lsl #4 @ r4 += r6 << 4 (calculating both the left and right samples together) + mla r4, r6, r9, r4 @ r4 += r6 * r9 (calculating both the left and right samples together) str r4, [r1], #4 @ store the new value, and increment the pointer .endr @@ -136,7 +138,7 @@ agb_arm_func agb_rs__mixer_add_stereo subs r8, r8, #4 @ loop counter bne 1b @ jump back if we're done with the loop - pop {r4-r8} + pop {r4-r9} bx lr agb_arm_end agb_rs__mixer_add_stereo diff --git a/agb/src/sound/mixer/sw_mixer.rs b/agb/src/sound/mixer/sw_mixer.rs index 676c0ed8..80b5b139 100644 --- a/agb/src/sound/mixer/sw_mixer.rs +++ b/agb/src/sound/mixer/sw_mixer.rs @@ -25,7 +25,11 @@ extern "C" { right_amount: Num<i16, 4>, ); - fn agb_rs__mixer_add_stereo(sound_data: *const u8, sound_buffer: *mut Num<i16, 4>); + fn agb_rs__mixer_add_stereo( + sound_data: *const u8, + sound_buffer: *mut Num<i16, 4>, + volume: Num<i16, 4>, + ); fn agb_rs__mixer_collapse(sound_buffer: *mut i8, input_buffer: *const Num<i16, 4>); } @@ -447,6 +451,7 @@ impl MixerBuffer { agb_rs__mixer_add_stereo( channel.data.as_ptr().add(channel.pos.floor()), buffer.as_mut_ptr(), + channel.volume, ); } } else { From 3de22df7a2591141434e9e3d1173b3e3e5544e0b Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper <gw@ilym.me> Date: Sun, 17 Jul 2022 10:32:01 +0100 Subject: [PATCH 7/9] Add get and set position on sound channels --- agb/src/sound/mixer/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/agb/src/sound/mixer/mod.rs b/agb/src/sound/mixer/mod.rs index 9b72e599..dda398e1 100644 --- a/agb/src/sound/mixer/mod.rs +++ b/agb/src/sound/mixer/mod.rs @@ -375,4 +375,17 @@ impl SoundChannel { pub fn stop(&mut self) { self.is_done = true; } + + /// Gets how far along the sound has played. + #[inline] + pub fn pos(&self) -> Num<usize, 8> { + self.pos + } + + /// Sets the playback position + #[inline] + pub fn set_pos(&mut self, pos: impl Into<Num<usize, 8>>) -> &mut Self { + self.pos = pos.into(); + self + } } From c2a4845a2e6ad87ad8961ec489c7b5762ea66c73 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper <gw@ilym.me> Date: Thu, 21 Jul 2022 20:34:26 +0100 Subject: [PATCH 8/9] Add a must_use to pos --- agb/src/sound/mixer/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/agb/src/sound/mixer/mod.rs b/agb/src/sound/mixer/mod.rs index dda398e1..ac01dba7 100644 --- a/agb/src/sound/mixer/mod.rs +++ b/agb/src/sound/mixer/mod.rs @@ -378,6 +378,7 @@ impl SoundChannel { /// Gets how far along the sound has played. #[inline] + #[must_use] pub fn pos(&self) -> Num<usize, 8> { self.pos } From 8df9f4b5c461d25ba2e899b1eabf953d45a6a391 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper <gw@ilym.me> Date: Thu, 21 Jul 2022 20:52:07 +0100 Subject: [PATCH 9/9] Go back to using DMA for sprites --- agb/src/display/object.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index b5a3287b..04a33587 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -799,13 +799,11 @@ impl SpriteControllerInner { }; unsafe { - dest.as_ptr() - .copy_from_nonoverlapping(sprite.data.as_ptr(), sprite.data.len()); - // dma::dma_copy16( - // sprite.data.as_ptr().cast(), - // dest.as_ptr().cast(), - // sprite.data.len() / 2, - // ); + dma::dma_copy16( + sprite.data.as_ptr().cast(), + dest.as_ptr().cast(), + sprite.data.len() / 2, + ); } let storage = Storage::from_sprite_ptr(dest);