allocate palettes too

This commit is contained in:
Corwin 2022-02-12 14:40:31 +00:00
parent 6a2c9d8826
commit d764ff9900
2 changed files with 85 additions and 13 deletions

View file

@ -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.
}
_ => {}
}
} }
} }

View file

@ -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],