From 8bf59e0f2094d5f2d2deafeb5fdac6fa50cc4df9 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 18:31:28 +0100 Subject: [PATCH 01/18] add bitarray implementation --- agb/src/bitarray.rs | 24 ++++++++++++++++++++++++ agb/src/lib.rs | 1 + 2 files changed, 25 insertions(+) create mode 100644 agb/src/bitarray.rs diff --git a/agb/src/bitarray.rs b/agb/src/bitarray.rs new file mode 100644 index 00000000..a5388733 --- /dev/null +++ b/agb/src/bitarray.rs @@ -0,0 +1,24 @@ +pub struct Bitarray { + a: [u32; N], +} + +impl Bitarray { + pub fn new() -> Self { + Bitarray { a: [0; N] } + } + + pub fn get(&self, index: usize) -> Option { + if index < N * 32 { + Some((self.a[index / N] >> (N % 32) & 1) != 0) + } else { + None + } + } + + pub fn set(&mut self, index: usize, value: bool) { + let value = value as u32; + let mask = 1 << (N % 32); + let value_mask = value << (N % 32); + self.a[index / N] = self.a[index / N] & !mask | value_mask + } +} diff --git a/agb/src/lib.rs b/agb/src/lib.rs index 413aba5a..45a25f81 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -20,6 +20,7 @@ pub mod input; /// Implements sound output. pub mod sound; +mod bitarray; mod interrupt; mod memory_mapped; /// Implements logging to the mgba emulator. From c208b6528ae1f2d77a2bc41943115e9e3cafff33 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 18:35:49 +0100 Subject: [PATCH 02/18] add tests --- agb/src/bitarray.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/agb/src/bitarray.rs b/agb/src/bitarray.rs index a5388733..381cf5a1 100644 --- a/agb/src/bitarray.rs +++ b/agb/src/bitarray.rs @@ -22,3 +22,12 @@ impl Bitarray { self.a[index / N] = self.a[index / N] & !mask | value_mask } } + +#[test_case] +fn write_and_read(_gba: &mut crate::Gba) { + let mut a: Bitarray<2> = Bitarray::new(); + assert_eq!(a.get(55).unwrap(), false, "expect unset values to be false"); + a.set(62, true); + assert_eq!(a.get(62).unwrap(), true, "expect set value to be true"); + assert_eq!(a.get(120), None, "expect out of range to give None"); +} From 9fad597844c3b7a9da3aab9f3a0f18c2eebad056 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 18:36:08 +0100 Subject: [PATCH 03/18] fix faulty implementation --- agb/src/bitarray.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agb/src/bitarray.rs b/agb/src/bitarray.rs index 381cf5a1..d6ec5563 100644 --- a/agb/src/bitarray.rs +++ b/agb/src/bitarray.rs @@ -9,7 +9,7 @@ impl Bitarray { pub fn get(&self, index: usize) -> Option { if index < N * 32 { - Some((self.a[index / N] >> (N % 32) & 1) != 0) + Some((self.a[index / 32] >> (N % 32) & 1) != 0) } else { None } @@ -19,7 +19,7 @@ impl Bitarray { let value = value as u32; let mask = 1 << (N % 32); let value_mask = value << (N % 32); - self.a[index / N] = self.a[index / N] & !mask | value_mask + self.a[index / 32] = self.a[index / 32] & !mask | value_mask } } From a7cb7ea7b43c8e1ff77770a6a6f5ff1717cc046a Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 18:36:23 +0100 Subject: [PATCH 04/18] keep track of which objects have been assigned --- agb/src/display/object.rs | 41 ++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 3055cd5c..6f08bd6c 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -1,4 +1,5 @@ use super::DISPLAY_CONTROL; +use crate::bitarray::Bitarray; use crate::memory_mapped::MemoryMapped1DArray; const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray = @@ -6,8 +7,8 @@ const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray = /// Handles distributing objects and matricies along with operations that effect all objects. pub struct ObjectControl { - object_count: u8, - affine_count: u8, + objects: Bitarray<4>, + affines: Bitarray<1>, } /// The standard object, without rotation. @@ -227,8 +228,8 @@ impl ObjectControl { unsafe { o.commit(index) }; } ObjectControl { - object_count: 0, - affine_count: 0, + objects: Bitarray::new(), + affines: Bitarray::new(), } } @@ -246,14 +247,32 @@ impl ObjectControl { DISPLAY_CONTROL.set(disp); } + fn get_unused_object_index(&mut self) -> u8 { + for index in 0..128 { + if self.objects.get(index).unwrap() == false { + self.objects.set(index, true); + return index as u8; + } + } + panic!("object id must be less than 128"); + } + + fn get_unused_affine_index(&mut self) -> u8 { + for index in 0..32 { + if self.affines.get(index).unwrap() == false { + self.affines.set(index, true); + return index as u8; + } + } + panic!("affine id must be less than 32"); + } + /// Get an unused standard object. Currently dropping an unused object will /// not free this. You should either keep around all objects you need /// forever or drop and reobtain ObjectControl. Panics if more than 128 /// objects are obtained. pub fn get_object_standard(&mut self) -> ObjectStandard { - let id = self.object_count; - self.object_count += 1; - assert!(id < 128, "object id must be less than 128"); + let id = self.get_unused_object_index(); ObjectStandard { attributes: ObjectAttribute::new(), id, @@ -265,9 +284,7 @@ impl ObjectControl { /// forever or drop and reobtain ObjectControl. Panics if more than 128 /// objects are obtained. pub fn get_object_affine(&mut self) -> ObjectAffine { - let id = self.object_count; - self.object_count += 1; - assert!(id < 128, "object id must be less than 128"); + let id = self.get_unused_object_index(); ObjectAffine { attributes: ObjectAttribute::new(), id, @@ -280,9 +297,7 @@ impl ObjectControl { /// need forever or drop and reobtain ObjectControl. Panics if more than 32 /// affine matricies are obtained. pub fn get_affine(&mut self) -> AffineMatrix { - let id = self.affine_count; - self.affine_count += 1; - assert!(id < 32, "affine id must be less than 32"); + let id = self.get_unused_affine_index(); AffineMatrix { attributes: AffineMatrixAttributes { p_a: 0, From 1d9d6e4ac25a8dc5d1b414860c72e78585f2cd30 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:15:16 +0100 Subject: [PATCH 05/18] fix regex --- mgba-test-runner/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mgba-test-runner/src/main.rs b/mgba-test-runner/src/main.rs index 12b916b9..40b5ccd9 100644 --- a/mgba-test-runner/src/main.rs +++ b/mgba-test-runner/src/main.rs @@ -18,7 +18,7 @@ enum Status { fn test_file(file_to_run: &str) -> Status { let mut finished = Status::Running; - let debug_reader_mutex = Regex::new(r"^\[(.*)\] GBA Debug: (.*)$").unwrap(); + let debug_reader_mutex = Regex::new(r"(?s)^\[(.*)\] GBA Debug: (.*)$").unwrap(); let mut mgba = runner::MGBA::new(file_to_run); let video_buffer = mgba.get_video_buffer(); From a17b37c2b73c37ca6e6244617ccb0de2b8abcd8d Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:15:25 +0100 Subject: [PATCH 06/18] add new test --- agb/src/bitarray.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/agb/src/bitarray.rs b/agb/src/bitarray.rs index d6ec5563..63adc0d0 100644 --- a/agb/src/bitarray.rs +++ b/agb/src/bitarray.rs @@ -31,3 +31,24 @@ fn write_and_read(_gba: &mut crate::Gba) { assert_eq!(a.get(62).unwrap(), true, "expect set value to be true"); assert_eq!(a.get(120), None, "expect out of range to give None"); } + +#[test_case] +fn test_everything(_gba: &mut crate::Gba) { + for i in 0..64 { + let mut a: Bitarray<2> = Bitarray::new(); + a.set(i, true); + for j in 0..64 { + let expected = if i == j { true } else { false }; + assert_eq!( + a.get(j).unwrap(), + expected, + "set index {} and read {}, expected {} but got {}. u32 of this is {:#b}", + i, + j, + expected, + a.get(j).unwrap(), + a.a[j / 32], + ); + } + } +} From 3cdb966dd9d788b041166979ab86d7935b6ecc56 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:15:58 +0100 Subject: [PATCH 07/18] fix implementation --- agb/src/bitarray.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agb/src/bitarray.rs b/agb/src/bitarray.rs index 63adc0d0..6f7c08ea 100644 --- a/agb/src/bitarray.rs +++ b/agb/src/bitarray.rs @@ -9,7 +9,7 @@ impl Bitarray { pub fn get(&self, index: usize) -> Option { if index < N * 32 { - Some((self.a[index / 32] >> (N % 32) & 1) != 0) + Some((self.a[index / 32] >> (index % 32) & 1) != 0) } else { None } @@ -17,8 +17,8 @@ impl Bitarray { pub fn set(&mut self, index: usize, value: bool) { let value = value as u32; - let mask = 1 << (N % 32); - let value_mask = value << (N % 32); + let mask = 1 << (index % 32); + let value_mask = value << (index % 32); self.a[index / 32] = self.a[index / 32] & !mask | value_mask } } From cd602d69a4e8e6d273741714ec9f990e907fca6b Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:28:43 +0100 Subject: [PATCH 08/18] add allocation for objects and matricies --- agb/src/display/object.rs | 87 ++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 6f08bd6c..615fde54 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -1,3 +1,5 @@ +use core::cell::RefCell; + use super::DISPLAY_CONTROL; use crate::bitarray::Bitarray; use crate::memory_mapped::MemoryMapped1DArray; @@ -7,29 +9,39 @@ const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray = /// Handles distributing objects and matricies along with operations that effect all objects. pub struct ObjectControl { - objects: Bitarray<4>, - affines: Bitarray<1>, + objects: RefCell>, + affines: RefCell>, +} + +struct ObjectLoan<'a> { + index: u8, + objects: &'a RefCell>, +} + +struct AffineLoan<'a> { + index: u8, + affines: &'a RefCell>, } /// The standard object, without rotation. -pub struct ObjectStandard { +pub struct ObjectStandard<'a> { attributes: ObjectAttribute, - id: u8, + loan: ObjectLoan<'a>, } /// The affine object, with potential for using a transformation matrix to alter /// how the sprite is rendered to screen. -pub struct ObjectAffine { +pub struct ObjectAffine<'a> { attributes: ObjectAttribute, - id: u8, + loan: ObjectLoan<'a>, aff_id: Option, } /// Refers to an affine matrix in the OAM. Includes both an index and the /// components of the affine matrix. -pub struct AffineMatrix { +pub struct AffineMatrix<'a> { pub attributes: AffineMatrixAttributes, - id: u8, + loan: AffineLoan<'a>, } /// The components of the affine matrix. The components are fixed point 8:8. @@ -67,11 +79,11 @@ pub enum Size { S32x64 = 0b10_11, } -impl ObjectStandard { +impl ObjectStandard<'_> { /// Commits the object to OAM such that the updated version is displayed on /// screen. Recommend to do this during VBlank. pub fn commit(&self) { - unsafe { self.attributes.commit(self.id) } + unsafe { self.attributes.commit(self.loan.index) } } /// Sets the x coordinate of the sprite on screen. @@ -104,11 +116,11 @@ impl ObjectStandard { } } -impl ObjectAffine { +impl ObjectAffine<'_> { /// Commits the object to OAM such that the updated version is displayed on /// screen. Recommend to do this during VBlank. pub fn commit(&self) { - unsafe { self.attributes.commit(self.id) } + unsafe { self.attributes.commit(self.loan.index) } } /// Sets the x coordinate of the sprite on screen. @@ -142,8 +154,8 @@ impl ObjectAffine { /// Sets the affine matrix to use. Changing the affine matrix will change /// how the sprite is rendered. pub fn set_affine_mat(&mut self, aff: &AffineMatrix) { - self.attributes.set_affine(aff.id); - self.aff_id = Some(aff.id); + self.attributes.set_affine(aff.loan.index); + self.aff_id = Some(aff.loan.index); } } @@ -152,6 +164,20 @@ fn set_bits(current: u16, value: u16, length: u16, shift: u16) -> u16 { (current & !(mask << shift)) | ((value & mask) << shift) } +impl Drop for ObjectLoan<'_> { + fn drop(&mut self) { + let mut objs = self.objects.borrow_mut(); + objs.set(self.index as usize, false); + } +} + +impl Drop for AffineLoan<'_> { + fn drop(&mut self) { + let mut affs = self.affines.borrow_mut(); + affs.set(self.index as usize, false); + } +} + struct ObjectAttribute { a0: u16, a1: u16, @@ -198,11 +224,11 @@ impl ObjectAttribute { } } -impl AffineMatrix { +impl AffineMatrix<'_> { #[allow(clippy::identity_op)] /// Commits matrix to OAM, will cause any objects using this matrix to be updated. pub fn commit(&self) { - let id = self.id as usize; + let id = self.loan.index as usize; OBJECT_ATTRIBUTE_MEMORY.set((id + 0) * 4 + 3, self.attributes.p_a as u16); OBJECT_ATTRIBUTE_MEMORY.set((id + 1) * 4 + 3, self.attributes.p_b as u16); OBJECT_ATTRIBUTE_MEMORY.set((id + 2) * 4 + 3, self.attributes.p_c as u16); @@ -228,8 +254,8 @@ impl ObjectControl { unsafe { o.commit(index) }; } ObjectControl { - objects: Bitarray::new(), - affines: Bitarray::new(), + objects: RefCell::new(Bitarray::new()), + affines: RefCell::new(Bitarray::new()), } } @@ -248,9 +274,10 @@ impl ObjectControl { } fn get_unused_object_index(&mut self) -> u8 { + let mut objects = self.objects.borrow_mut(); for index in 0..128 { - if self.objects.get(index).unwrap() == false { - self.objects.set(index, true); + if objects.get(index).unwrap() == false { + objects.set(index, true); return index as u8; } } @@ -258,9 +285,10 @@ impl ObjectControl { } fn get_unused_affine_index(&mut self) -> u8 { + let mut affines = self.affines.borrow_mut(); for index in 0..32 { - if self.affines.get(index).unwrap() == false { - self.affines.set(index, true); + if affines.get(index).unwrap() == false { + affines.set(index, true); return index as u8; } } @@ -275,7 +303,10 @@ impl ObjectControl { let id = self.get_unused_object_index(); ObjectStandard { attributes: ObjectAttribute::new(), - id, + loan: ObjectLoan { + objects: &self.objects, + index: id, + }, } } @@ -287,7 +318,10 @@ impl ObjectControl { let id = self.get_unused_object_index(); ObjectAffine { attributes: ObjectAttribute::new(), - id, + loan: ObjectLoan { + objects: &self.objects, + index: id, + }, aff_id: None, } } @@ -305,7 +339,10 @@ impl ObjectControl { p_c: 0, p_d: 0, }, - id, + loan: AffineLoan { + affines: &self.affines, + index: id, + }, } } } From 72662cff5a3815383f9c72d80794a314bdb5535c Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:29:21 +0100 Subject: [PATCH 09/18] update documentation --- agb/src/display/object.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 615fde54..355ac643 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -295,10 +295,8 @@ impl ObjectControl { panic!("affine id must be less than 32"); } - /// Get an unused standard object. Currently dropping an unused object will - /// not free this. You should either keep around all objects you need - /// forever or drop and reobtain ObjectControl. Panics if more than 128 - /// objects are obtained. + /// Get an unused standard object. Panics if more than 128 objects are + /// obtained. pub fn get_object_standard(&mut self) -> ObjectStandard { let id = self.get_unused_object_index(); ObjectStandard { @@ -310,10 +308,8 @@ impl ObjectControl { } } - /// Get an unused affine object. Currently dropping an unused object will - /// not free this. You should either keep around all objects you need - /// forever or drop and reobtain ObjectControl. Panics if more than 128 - /// objects are obtained. + /// Get an unused affine object. Panics if more than 128 objects are + /// obtained. pub fn get_object_affine(&mut self) -> ObjectAffine { let id = self.get_unused_object_index(); ObjectAffine { @@ -326,10 +322,8 @@ impl ObjectControl { } } - /// Get an unused affine matrix. Currently dropping an unused object will - /// not free this. You should either keep around all affine matricies you - /// need forever or drop and reobtain ObjectControl. Panics if more than 32 - /// affine matricies are obtained. + /// Get an unused affine matrix. Panics if more than 32 affine matricies are + /// obtained. pub fn get_affine(&mut self) -> AffineMatrix { let id = self.get_unused_affine_index(); AffineMatrix { From 95407e11f6b73b9070075ade474f11b3026a9fe8 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:37:41 +0100 Subject: [PATCH 10/18] add test and fix implementation --- agb/src/display/object.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 355ac643..aaaee39b 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -273,7 +273,7 @@ impl ObjectControl { DISPLAY_CONTROL.set(disp); } - fn get_unused_object_index(&mut self) -> u8 { + fn get_unused_object_index(&self) -> u8 { let mut objects = self.objects.borrow_mut(); for index in 0..128 { if objects.get(index).unwrap() == false { @@ -284,7 +284,7 @@ impl ObjectControl { panic!("object id must be less than 128"); } - fn get_unused_affine_index(&mut self) -> u8 { + fn get_unused_affine_index(&self) -> u8 { let mut affines = self.affines.borrow_mut(); for index in 0..32 { if affines.get(index).unwrap() == false { @@ -297,7 +297,7 @@ impl ObjectControl { /// Get an unused standard object. Panics if more than 128 objects are /// obtained. - pub fn get_object_standard(&mut self) -> ObjectStandard { + pub fn get_object_standard(&self) -> ObjectStandard { let id = self.get_unused_object_index(); ObjectStandard { attributes: ObjectAttribute::new(), @@ -310,7 +310,7 @@ impl ObjectControl { /// Get an unused affine object. Panics if more than 128 objects are /// obtained. - pub fn get_object_affine(&mut self) -> ObjectAffine { + pub fn get_object_affine(&self) -> ObjectAffine { let id = self.get_unused_object_index(); ObjectAffine { attributes: ObjectAttribute::new(), @@ -324,7 +324,7 @@ impl ObjectControl { /// Get an unused affine matrix. Panics if more than 32 affine matricies are /// obtained. - pub fn get_affine(&mut self) -> AffineMatrix { + pub fn get_affine(&self) -> AffineMatrix { let id = self.get_unused_affine_index(); AffineMatrix { attributes: AffineMatrixAttributes { @@ -340,3 +340,22 @@ impl ObjectControl { } } } + +#[cfg(test)] +mod tests { + #[test_case] + fn get_and_release(gba: &mut crate::Gba) { + let gfx = gba.display.video.tiled0(); + let objs = gfx.object; + + { + let o0 = objs.get_object_standard(); + let o1 = objs.get_object_standard(); + assert_eq!(o0.loan.index, 0); + assert_eq!(o1.loan.index, 1); + } + + let o0 = objs.get_object_standard(); + assert_eq!(o0.loan.index, 0); + } +} From 1c779e3c31267332d31d548f0cdc279417f0a8c8 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:37:45 +0100 Subject: [PATCH 11/18] fix example --- agb/examples/chicken.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agb/examples/chicken.rs b/agb/examples/chicken.rs index 8fb68d55..c10a348b 100644 --- a/agb/examples/chicken.rs +++ b/agb/examples/chicken.rs @@ -15,8 +15,8 @@ enum State { Flapping, } -struct Character { - object: ObjectStandard, +struct Character<'a> { + object: ObjectStandard<'a>, position: Vector2D, velocity: Vector2D, } From 8867c5c9f1da050aa125a74b264dfd0f34e11901 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 19:43:09 +0100 Subject: [PATCH 12/18] satisfy linter --- agb/src/display/object.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index aaaee39b..da43f3c0 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -276,7 +276,7 @@ impl ObjectControl { fn get_unused_object_index(&self) -> u8 { let mut objects = self.objects.borrow_mut(); for index in 0..128 { - if objects.get(index).unwrap() == false { + if !objects.get(index).unwrap() { objects.set(index, true); return index as u8; } @@ -287,7 +287,7 @@ impl ObjectControl { fn get_unused_affine_index(&self) -> u8 { let mut affines = self.affines.borrow_mut(); for index in 0..32 { - if affines.get(index).unwrap() == false { + if !affines.get(index).unwrap() { affines.set(index, true); return index as u8; } From 33738c0f9347ac13be2ef0c87ef3009c2fc814d7 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 22:29:27 +0100 Subject: [PATCH 13/18] add test for affine matrix getting --- agb/src/display/object.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index da43f3c0..fd9fe0ac 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -344,18 +344,40 @@ impl ObjectControl { #[cfg(test)] mod tests { #[test_case] - fn get_and_release(gba: &mut crate::Gba) { + fn get_and_release_object(gba: &mut crate::Gba) { let gfx = gba.display.video.tiled0(); let objs = gfx.object; - { + let _o1 = { let o0 = objs.get_object_standard(); let o1 = objs.get_object_standard(); assert_eq!(o0.loan.index, 0); assert_eq!(o1.loan.index, 1); - } + o1 + }; let o0 = objs.get_object_standard(); assert_eq!(o0.loan.index, 0); + let o2 = objs.get_object_affine(); + assert_eq!(o2.loan.index, 2); + } + + #[test_case] + fn get_and_release_affine(gba: &mut crate::Gba) { + let gfx = gba.display.video.tiled0(); + let objs = gfx.object; + + let _a1 = { + let a0 = objs.get_affine(); + let a1 = objs.get_affine(); + assert_eq!(a0.loan.index, 0); + assert_eq!(a1.loan.index, 1); + a1 + }; + + let a0 = objs.get_affine(); + assert_eq!(a0.loan.index, 0); + let a2 = objs.get_affine(); + assert_eq!(a2.loan.index, 2); } } From b1ff3526237bae0c9ffcde058158a33446fe4a6c Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Fri, 4 Jun 2021 22:39:10 +0100 Subject: [PATCH 14/18] use lifetimes to prevent affine matrix dropping --- agb/src/display/object.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index fd9fe0ac..4aaef8d1 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -116,7 +116,7 @@ impl ObjectStandard<'_> { } } -impl ObjectAffine<'_> { +impl<'a> ObjectAffine<'a> { /// Commits the object to OAM such that the updated version is displayed on /// screen. Recommend to do this during VBlank. pub fn commit(&self) { @@ -153,7 +153,7 @@ impl ObjectAffine<'_> { } /// Sets the affine matrix to use. Changing the affine matrix will change /// how the sprite is rendered. - pub fn set_affine_mat(&mut self, aff: &AffineMatrix) { + pub fn set_affine_mat(&mut self, aff: &'a AffineMatrix) { self.attributes.set_affine(aff.loan.index); self.aff_id = Some(aff.loan.index); } From 1d8ac652f1db26929f5294339a5c0805bd2d2e71 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Sat, 5 Jun 2021 00:16:31 +0100 Subject: [PATCH 15/18] fix sprite size ordering --- agb/src/display/object.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 4aaef8d1..243237ad 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -196,11 +196,11 @@ impl ObjectAttribute { } fn set_size(&mut self, size: Size) { - let lower = size as u16 & 0b11; - let upper = (size as u16 >> 2) & 0b11; + let a1 = size as u16 & 0b11; + let a0 = (size as u16 >> 2) & 0b11; - self.a0 = set_bits(self.a0, lower, 2, 0xE); - self.a1 = set_bits(self.a1, upper, 2, 0xE); + self.a0 = set_bits(self.a0, a0, 2, 0xE); + self.a1 = set_bits(self.a1, a1, 2, 0xE); } fn set_x(&mut self, x: u8) { From 225d0aca9f4f2bcab1e2a9410c319300693ffc79 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Sat, 5 Jun 2021 00:16:44 +0100 Subject: [PATCH 16/18] set 1d mapping --- agb/src/display/tiled0.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agb/src/display/tiled0.rs b/agb/src/display/tiled0.rs index a31d662e..46247be5 100644 --- a/agb/src/display/tiled0.rs +++ b/agb/src/display/tiled0.rs @@ -253,7 +253,7 @@ pub struct Tiled0 { impl Tiled0 { pub(crate) unsafe fn new() -> Self { - set_graphics_settings(GraphicsSettings::empty()); + set_graphics_settings(GraphicsSettings::empty() | GraphicsSettings::SPRITE1_D); set_graphics_mode(DisplayMode::Tiled0); Tiled0 { used_blocks: 0, From 3b9231ef6e2ab3f7892299982246958cf5118402 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Sat, 5 Jun 2021 00:26:10 +0100 Subject: [PATCH 17/18] fix coordinates --- agb/src/display/object.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 243237ad..a68abb72 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -87,11 +87,11 @@ impl ObjectStandard<'_> { } /// Sets the x coordinate of the sprite on screen. - pub fn set_x(&mut self, x: u8) { + pub fn set_x(&mut self, x: u16) { self.attributes.set_x(x) } /// Sets the y coordinate of the sprite on screen. - pub fn set_y(&mut self, y: u8) { + pub fn set_y(&mut self, y: u16) { self.attributes.set_y(y) } /// Sets the index of the tile to use as the sprite. Potentially a temporary function. @@ -124,11 +124,11 @@ impl<'a> ObjectAffine<'a> { } /// Sets the x coordinate of the sprite on screen. - pub fn set_x(&mut self, x: u8) { + pub fn set_x(&mut self, x: u16) { self.attributes.set_x(x) } /// Sets the y coordinate of the sprite on screen. - pub fn set_y(&mut self, y: u8) { + pub fn set_y(&mut self, y: u16) { self.attributes.set_y(y) } /// Sets the index of the tile to use as the sprite. Potentially a temporary function. @@ -203,12 +203,12 @@ impl ObjectAttribute { self.a1 = set_bits(self.a1, a1, 2, 0xE); } - fn set_x(&mut self, x: u8) { - self.a1 = set_bits(self.a1, x as u16, 8, 0); + fn set_x(&mut self, x: u16) { + self.a1 = set_bits(self.a1, x, 9, 0); } - fn set_y(&mut self, y: u8) { - self.a0 = set_bits(self.a0, y as u16, 8, 0) + fn set_y(&mut self, y: u16) { + self.a0 = set_bits(self.a0, y, 8, 0) } fn set_tile_id(&mut self, id: u16) { From eea0e6d3b3f9651d745d0c68b5d6ec6604b24a6a Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Sat, 5 Jun 2021 00:27:13 +0100 Subject: [PATCH 18/18] fix chicken example --- agb/examples/chicken.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agb/examples/chicken.rs b/agb/examples/chicken.rs index c10a348b..38b08100 100644 --- a/agb/examples/chicken.rs +++ b/agb/examples/chicken.rs @@ -151,8 +151,8 @@ fn update_chicken_object(chicken: &mut Character, state: State, frame_count: u32 } } - let x: u8 = (chicken.position.x >> 8).try_into().unwrap(); - let y: u8 = (chicken.position.y >> 8).try_into().unwrap(); + let x: u16 = (chicken.position.x >> 8).try_into().unwrap(); + let y: u16 = (chicken.position.y >> 8).try_into().unwrap(); chicken.object.set_x(x - 4); chicken.object.set_y(y - 4);