diff --git a/CHANGELOG.md b/CHANGELOG.md index 0378cbfb..095a6e51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `find_colour_index_16` and `find_colour_index_256` to the `VRamManager` to find where a colour is in a palette. -### Changed - -- `dma.hblank_transfer` is no longer `unsafe`. - ## [0.20.2] - 2024/05/25 ### Fixed diff --git a/agb/examples/dma_effect_background_colour.rs b/agb/examples/dma_effect_background_colour.rs index 7d1cfed1..f7386c59 100644 --- a/agb/examples/dma_effect_background_colour.rs +++ b/agb/examples/dma_effect_background_colour.rs @@ -37,10 +37,12 @@ fn main(mut gba: agb::Gba) -> ! { .expect("Should contain colour 0x732b"); loop { - let _background_color_transfer = dma.hblank_transfer( - &vram.background_palette_colour_dma(0, background_colour_index), - &colours, - ); + let _background_color_transfer = unsafe { + dma.hblank_transfer( + &vram.background_palette_colour_dma(0, background_colour_index), + &colours, + ) + }; vblank.wait_for_vblank(); } diff --git a/agb/examples/dma_effect_background_scroll.rs b/agb/examples/dma_effect_background_scroll.rs index a74243ce..eb5cdfaa 100644 --- a/agb/examples/dma_effect_background_scroll.rs +++ b/agb/examples/dma_effect_background_scroll.rs @@ -34,7 +34,8 @@ fn main(mut gba: agb::Gba) -> ! { let mut frame = 0; loop { - let _x_scroll_transfer = dma.hblank_transfer(&map.x_scroll_dma(), &offsets[frame..]); + let _x_scroll_transfer = + unsafe { dma.hblank_transfer(&map.x_scroll_dma(), &offsets[frame..]) }; vblank.wait_for_vblank(); frame += 1; diff --git a/agb/examples/dma_effect_circular_window.rs b/agb/examples/dma_effect_circular_window.rs index cbdf8285..d98e6f60 100644 --- a/agb/examples/dma_effect_circular_window.rs +++ b/agb/examples/dma_effect_circular_window.rs @@ -90,7 +90,7 @@ fn main(mut gba: agb::Gba) -> ! { window.commit(); let dma_controllable = window.win_in(WinIn::Win0).horizontal_position_dma(); - let _transfer = dmas.dma0.hblank_transfer(&dma_controllable, &circle_poses); + let _transfer = unsafe { dmas.dma0.hblank_transfer(&dma_controllable, &circle_poses) }; vblank.wait_for_vblank(); } diff --git a/agb/src/dma.rs b/agb/src/dma.rs index 48e870db..a16fc021 100644 --- a/agb/src/dma.rs +++ b/agb/src/dma.rs @@ -70,14 +70,18 @@ impl Dma { /// drop the DmaTransferHandler return value until the next vblank interrupt to ensure that you /// a continuous effect. /// + /// # Safety + /// + /// While DmaTransferHandle is not dropped, the slice at `values` must not move in memory. + /// /// # Examples /// /// See the `dma_effect_*` examples in the repository to see some ways to use this. - pub fn hblank_transfer( - &self, + pub unsafe fn hblank_transfer<'a, T>( + &'a self, location: &DmaControllable, - values: &[T], - ) -> DmaTransferHandle + values: &'a [T], + ) -> DmaTransferHandle<'a, T> where T: Copy, { @@ -89,13 +93,10 @@ impl Dma { let n_transfers = (size_of::() / 2) as u32; - self.source_addr.set(handle.data[1..].as_ptr() as u32); + self.source_addr.set(handle.data.as_ptr().add(1) as u32); self.dest_addr.set(location.memory_location as u32); - // SAFETY: by construction it is safe to write to location.memory_location - unsafe { - location.memory_location.write_volatile(values[0]); - } + location.memory_location.write_volatile(values[0]); self.ctrl_addr.set( (0b10 << 0x15) | // keep destination address fixed @@ -126,15 +127,17 @@ impl DmaControllable { } } -pub struct DmaTransferHandle +pub struct DmaTransferHandle<'a, T> where T: Copy, { number: usize, data: Pin>, + + phantom: PhantomData<&'a ()>, } -impl DmaTransferHandle +impl<'a, T> DmaTransferHandle<'a, T> where T: Copy, { @@ -142,11 +145,12 @@ where Self { number, data: Box::into_pin(data.into()), + phantom: PhantomData, } } } -impl Drop for DmaTransferHandle +impl<'a, T> Drop for DmaTransferHandle<'a, T> where T: Copy, {