mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 16:51:33 +11:00
allocate palettes too
This commit is contained in:
parent
6a2c9d8826
commit
d764ff9900
|
@ -21,6 +21,13 @@ static SPRITE_ALLOCATOR: BlockAllocator = unsafe {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PALETTE_ALLOCATOR: BlockAllocator = unsafe {
|
||||||
|
BlockAllocator::new(StartEnd {
|
||||||
|
start: || 0x0500_0200,
|
||||||
|
end: || 0x0500_0400,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray<u16, 512> =
|
const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray<u16, 512> =
|
||||||
unsafe { MemoryMapped1DArray::new(0x0700_0000) };
|
unsafe { MemoryMapped1DArray::new(0x0700_0000) };
|
||||||
const PALETTE_SPRITE: MemoryMapped1DArray<u16, 256> =
|
const PALETTE_SPRITE: MemoryMapped1DArray<u16, 256> =
|
||||||
|
@ -74,6 +81,8 @@ impl Size {
|
||||||
|
|
||||||
struct SpriteBorrow<'a> {
|
struct SpriteBorrow<'a> {
|
||||||
id: SpriteId,
|
id: SpriteId,
|
||||||
|
sprite_location: u16,
|
||||||
|
palette_location: u16,
|
||||||
controller: &'a RefCell<SpriteControllerInner>,
|
controller: &'a RefCell<SpriteControllerInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +92,21 @@ struct Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Storage {
|
impl Storage {
|
||||||
fn from_ptr(d: NonNull<u8>) -> Self {
|
fn from_sprite_ptr(d: NonNull<u8>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
location: (((d.as_ptr() as usize) - 0x06010000) / BYTES_PER_TILE_4BPP) as u16,
|
location: (((d.as_ptr() as usize) - 0x06010000) / BYTES_PER_TILE_4BPP) as u16,
|
||||||
count: 1,
|
count: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn from_palette_ptr(d: NonNull<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
location: ((d.as_ptr() as usize - 0x0500_0200) / Palette16::layout().size()) as u16,
|
||||||
|
count: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn to_palette_ptr(&self) -> *mut u8 {
|
||||||
|
(self.location as usize * Palette16::layout().size() + 0x0500_0200) as *mut u8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Object<'a> {
|
pub struct Object<'a> {
|
||||||
|
@ -125,6 +143,21 @@ impl SpriteId {
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
struct PaletteId(usize);
|
struct PaletteId(usize);
|
||||||
|
|
||||||
|
impl PaletteId {
|
||||||
|
fn get_palette(self) -> &'static Palette16 {
|
||||||
|
unsafe { (self.0 as *const Palette16).as_ref().unwrap_unchecked() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Palette16 {
|
||||||
|
fn get_id(&'static self) -> PaletteId {
|
||||||
|
PaletteId(self as *const _ as usize)
|
||||||
|
}
|
||||||
|
const fn layout() -> Layout {
|
||||||
|
Layout::new::<Self>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Sprite {
|
impl Sprite {
|
||||||
fn get_id(&'static self) -> SpriteId {
|
fn get_id(&'static self) -> SpriteId {
|
||||||
SpriteId(self as *const _ as usize)
|
SpriteId(self as *const _ as usize)
|
||||||
|
@ -140,49 +173,87 @@ impl SpriteController {
|
||||||
let id = sprite.get_id();
|
let id = sprite.get_id();
|
||||||
if let Some(storage) = inner.sprite.get_mut(&id) {
|
if let Some(storage) = inner.sprite.get_mut(&id) {
|
||||||
storage.count += 1;
|
storage.count += 1;
|
||||||
|
let palette_location = inner.get_palette(sprite.palette).unwrap();
|
||||||
Some(SpriteBorrow {
|
Some(SpriteBorrow {
|
||||||
id,
|
id,
|
||||||
|
palette_location,
|
||||||
|
sprite_location: storage.location,
|
||||||
controller: &self.inner,
|
controller: &self.inner,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// layout is non zero sized, so this is safe to call
|
// layout is non zero sized, so this is safe to call
|
||||||
|
|
||||||
let dest = unsafe { SPRITE_ALLOCATOR.alloc(sprite.layout())? };
|
let dest = unsafe { SPRITE_ALLOCATOR.alloc(sprite.layout())? };
|
||||||
inner.sprite.insert(id, Storage::from_ptr(dest));
|
let palette_location = inner.get_palette(sprite.palette);
|
||||||
|
let palette_location = match palette_location {
|
||||||
|
Some(a) => a,
|
||||||
|
None => {
|
||||||
|
unsafe { SPRITE_ALLOCATOR.dealloc(dest.as_ptr(), sprite.layout()) }
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// need to consider palette
|
let storage = Storage::from_sprite_ptr(dest);
|
||||||
todo!();
|
inner.sprite.insert(id, storage);
|
||||||
|
|
||||||
Some(SpriteBorrow {
|
Some(SpriteBorrow {
|
||||||
id,
|
id,
|
||||||
controller: &self.inner,
|
controller: &self.inner,
|
||||||
|
palette_location,
|
||||||
|
sprite_location: storage.location,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SpriteControllerInner {
|
||||||
|
fn get_palette(&mut self, palette: &'static Palette16) -> Option<u16> {
|
||||||
|
let id = palette.get_id();
|
||||||
|
if let Some(storage) = self.palette.get_mut(&id) {
|
||||||
|
storage.count += 1;
|
||||||
|
Some(storage.location)
|
||||||
|
} else {
|
||||||
|
let dest = unsafe { PALETTE_ALLOCATOR.alloc(Palette16::layout())? };
|
||||||
|
let storage = Storage::from_palette_ptr(dest);
|
||||||
|
self.palette.insert(id, storage);
|
||||||
|
|
||||||
|
Some(storage.location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_palette(&mut self, palette: &'static Palette16) {
|
||||||
|
let id = palette.get_id();
|
||||||
|
self.palette
|
||||||
|
.entry(id)
|
||||||
|
.and_replace_entry_with(|_, mut storage| {
|
||||||
|
storage.count -= 1;
|
||||||
|
if storage.count == 0 {
|
||||||
|
unsafe {
|
||||||
|
PALETTE_ALLOCATOR.dealloc(storage.to_palette_ptr(), Palette16::layout());
|
||||||
|
}
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(storage)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Drop for SpriteBorrow<'a> {
|
impl<'a> Drop for SpriteBorrow<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let inner = self.controller.borrow_mut();
|
let inner = self.controller.borrow_mut();
|
||||||
let entry = inner
|
inner
|
||||||
.sprite
|
.sprite
|
||||||
.entry(self.id)
|
.entry(self.id)
|
||||||
.and_replace_entry_with(|_, mut storage| {
|
.and_replace_entry_with(|_, mut storage| {
|
||||||
storage.count -= 1;
|
storage.count -= 1;
|
||||||
if storage.count == 0 {
|
if storage.count == 0 {
|
||||||
|
inner.return_palette(self.id.get_sprite().palette);
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(storage)
|
Some(storage)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
match entry {
|
|
||||||
Entry::Vacant(_) => {
|
|
||||||
// free the underlying resource.
|
|
||||||
// palette might be unused too.
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Palette16 {
|
pub struct Palette16 {
|
||||||
pub(crate) colours: [u16; 16],
|
pub(crate) colours: [u16; 16],
|
||||||
|
|
Loading…
Reference in a new issue