From 056a38703d9ebb5e1492a700700b6b06234487df Mon Sep 17 00:00:00 2001
From: Gwilym Kuiper <gw@ilym.me>
Date: Sun, 13 Mar 2022 19:36:14 +0000
Subject: [PATCH 1/5] Use dma in objects

---
 agb/src/display/object.rs | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs
index ab9f7c4b..aa190675 100644
--- a/agb/src/display/object.rs
+++ b/agb/src/display/object.rs
@@ -16,6 +16,7 @@ use super::palette16::Palette16;
 use super::{Priority, DISPLAY_CONTROL};
 use crate::agb_alloc::block_allocator::BlockAllocator;
 use crate::agb_alloc::bump_allocator::StartEnd;
+use crate::dma;
 use crate::fixnum::Vector2D;
 
 use attributes::*;
@@ -577,8 +578,11 @@ impl SpriteController {
             };
 
             unsafe {
-                dest.as_ptr()
-                    .copy_from_nonoverlapping(sprite.data.as_ptr(), sprite.data.len())
+                dma::dma_copy(
+                    sprite.data.as_ptr().cast(),
+                    dest.as_ptr().cast(),
+                    sprite.data.len() / 2,
+                );
             }
 
             let storage = Storage::from_sprite_ptr(dest);
@@ -610,9 +614,11 @@ impl SpriteControllerInner {
             let dest = unsafe { PALETTE_ALLOCATOR.alloc(Palette16::layout())? };
 
             unsafe {
-                dest.as_ptr()
-                    .cast::<u16>()
-                    .copy_from_nonoverlapping(palette.colours.as_ptr(), palette.colours.len())
+                dma::dma_copy(
+                    palette.colours.as_ptr().cast(),
+                    dest.as_ptr().cast(),
+                    palette.colours.len(),
+                );
             }
 
             let storage = Storage::from_palette_ptr(dest);

From ea3d3d4936e1ffed99593419b86d4c38a66e5882 Mon Sep 17 00:00:00 2001
From: Gwilym Kuiper <gw@ilym.me>
Date: Sun, 13 Mar 2022 19:37:27 +0000
Subject: [PATCH 2/5] Rename dma_copy to dma_copy16

---
 agb/src/display/object.rs             | 4 ++--
 agb/src/display/tiled/map.rs          | 4 ++--
 agb/src/display/tiled/vram_manager.rs | 4 ++--
 agb/src/dma.rs                        | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs
index aa190675..5f5276c1 100644
--- a/agb/src/display/object.rs
+++ b/agb/src/display/object.rs
@@ -578,7 +578,7 @@ impl SpriteController {
             };
 
             unsafe {
-                dma::dma_copy(
+                dma::dma_copy16(
                     sprite.data.as_ptr().cast(),
                     dest.as_ptr().cast(),
                     sprite.data.len() / 2,
@@ -614,7 +614,7 @@ impl SpriteControllerInner {
             let dest = unsafe { PALETTE_ALLOCATOR.alloc(Palette16::layout())? };
 
             unsafe {
-                dma::dma_copy(
+                dma::dma_copy16(
                     palette.colours.as_ptr().cast(),
                     dest.as_ptr().cast(),
                     palette.colours.len(),
diff --git a/agb/src/display/tiled/map.rs b/agb/src/display/tiled/map.rs
index f86f8049..cfb9831a 100644
--- a/agb/src/display/tiled/map.rs
+++ b/agb/src/display/tiled/map.rs
@@ -3,7 +3,7 @@ use core::ops::{Deref, DerefMut};
 
 use crate::bitarray::Bitarray;
 use crate::display::{Priority, DISPLAY_CONTROL};
-use crate::dma::dma_copy;
+use crate::dma::dma_copy16;
 use crate::fixnum::Vector2D;
 use crate::memory_mapped::MemoryMapped;
 
@@ -106,7 +106,7 @@ impl RegularMap {
         let screenblock_memory = self.screenblock_memory();
 
         unsafe {
-            dma_copy(
+            dma_copy16(
                 self.tiles.as_ptr() as *const u16,
                 screenblock_memory,
                 32 * 32,
diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs
index 76be9999..7f375339 100644
--- a/agb/src/display/tiled/vram_manager.rs
+++ b/agb/src/display/tiled/vram_manager.rs
@@ -6,7 +6,7 @@ use alloc::vec::Vec;
 use crate::{
     agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd},
     display::palette16,
-    dma::dma_copy,
+    dma::dma_copy16,
     memory_mapped::MemoryMapped1DArray,
 };
 
@@ -213,7 +213,7 @@ impl<'a> VRamManager<'a> {
         let tile_size_in_half_words = TileFormat::FourBpp.tile_size() / 2;
 
         unsafe {
-            dma_copy(
+            dma_copy16(
                 tile_slice.as_ptr() as *const u16,
                 new_reference.as_ptr() as *mut u16,
                 tile_size_in_half_words,
diff --git a/agb/src/dma.rs b/agb/src/dma.rs
index a7c9c6d0..71651cfc 100644
--- a/agb/src/dma.rs
+++ b/agb/src/dma.rs
@@ -16,7 +16,7 @@ const DMA3_SOURCE_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(dma_sourc
 const DMA3_DEST_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(dma_dest_addr(3)) };
 const DMA3_CONTROL: MemoryMapped<u32> = unsafe { MemoryMapped::new(dma_control_addr(3)) };
 
-pub(crate) unsafe fn dma_copy(src: *const u16, dest: *mut u16, count: usize) {
+pub(crate) unsafe fn dma_copy16(src: *const u16, dest: *mut u16, count: usize) {
     assert!(count < u16::MAX as usize);
 
     DMA3_SOURCE_ADDR.set(src as u32);

From 989fcea1d01e25102474b8abbea77f7f78795151 Mon Sep 17 00:00:00 2001
From: Gwilym Kuiper <gw@ilym.me>
Date: Sun, 13 Mar 2022 19:43:03 +0000
Subject: [PATCH 3/5] Fix typo in exception

---
 agb/src/display/object.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs
index 5f5276c1..878c8c2b 100644
--- a/agb/src/display/object.rs
+++ b/agb/src/display/object.rs
@@ -364,7 +364,7 @@ impl ObjectController {
     }
 
     pub fn get_object<'a, 'b>(&'a self, sprite: SpriteBorrow<'b>) -> Object<'b, 'a> {
-        self.try_get_object(sprite).expect("No object avaliable")
+        self.try_get_object(sprite).expect("No object available")
     }
 
     pub fn try_get_object<'a, 'b>(&'a self, sprite: SpriteBorrow<'b>) -> Option<Object<'b, 'a>> {

From ef8b2edc6322b090184fa596da10d870073b514e Mon Sep 17 00:00:00 2001
From: Gwilym Kuiper <gw@ilym.me>
Date: Sun, 13 Mar 2022 19:53:07 +0000
Subject: [PATCH 4/5] Also dma the palette in backgrounds

---
 agb/src/display/tiled/vram_manager.rs | 8 ++++++--
 agb/src/memory_mapped.rs              | 4 ++++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs
index 7f375339..5c99f89f 100644
--- a/agb/src/display/tiled/vram_manager.rs
+++ b/agb/src/display/tiled/vram_manager.rs
@@ -266,8 +266,12 @@ impl<'a> VRamManager<'a> {
     }
 
     fn set_background_palette(&mut self, pal_index: u8, palette: &palette16::Palette16) {
-        for (colour_index, &colour) in palette.colours.iter().enumerate() {
-            PALETTE_BACKGROUND.set(pal_index as usize * 16 + colour_index, colour);
+        unsafe {
+            dma_copy16(
+                palette.colours.as_ptr(),
+                PALETTE_BACKGROUND.as_ptr().add(16 * pal_index as usize),
+                palette.colours.len(),
+            );
         }
     }
 
diff --git a/agb/src/memory_mapped.rs b/agb/src/memory_mapped.rs
index 940f3d77..57b5bb51 100644
--- a/agb/src/memory_mapped.rs
+++ b/agb/src/memory_mapped.rs
@@ -57,6 +57,10 @@ impl<T, const N: usize> MemoryMapped1DArray<T, N> {
     pub fn set(&self, n: usize, val: T) {
         unsafe { (&mut (*self.array)[n] as *mut T).write_volatile(val) }
     }
+
+    pub fn as_ptr(&self) -> *mut T {
+        self.array.cast()
+    }
 }
 
 pub struct MemoryMapped2DArray<T, const X: usize, const Y: usize> {

From 5bf78f6274bddda24ca8f4605eba87808f0b64c4 Mon Sep 17 00:00:00 2001
From: Gwilym Kuiper <gw@ilym.me>
Date: Sun, 13 Mar 2022 19:53:55 +0000
Subject: [PATCH 5/5] Also for raw copy

---
 agb/src/display/tiled/vram_manager.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs
index 5c99f89f..7a3c31c7 100644
--- a/agb/src/display/tiled/vram_manager.rs
+++ b/agb/src/display/tiled/vram_manager.rs
@@ -260,8 +260,8 @@ impl<'a> VRamManager<'a> {
 
     /// Copies raw palettes to the background palette without any checks.
     pub fn set_background_palette_raw(&mut self, palette: &[u16]) {
-        for (index, &colour) in palette.iter().enumerate() {
-            PALETTE_BACKGROUND.set(index, colour);
+        unsafe {
+            dma_copy16(palette.as_ptr(), PALETTE_BACKGROUND.as_ptr(), palette.len());
         }
     }