use std::fmt::{Debug, Formatter};
use monsoon_core::emulation::palette_util::{RgbColor, RgbPalette};
use monsoon_core::emulation::ppu_util::{TOTAL_OUTPUT_HEIGHT, TOTAL_OUTPUT_WIDTH};
use monsoon_core::emulation::screen_renderer::ScreenRenderer;
use serde::{Deserialize, Serialize};
use serde_big_array::BigArray;
const PALETTE_COLORS: usize = 64;
const EMPHASIS_COMBINATIONS: usize = 8;
const FLAT_PALETTE_SIZE: usize = PALETTE_COLORS * EMPHASIS_COMBINATIONS;
const PALETTE_INDEX_MASK: usize = FLAT_PALETTE_SIZE - 1;
#[derive(Clone, Serialize, Deserialize)]
struct FlatPalette {
#[serde(with = "BigArray")]
palette: [RgbColor; FLAT_PALETTE_SIZE],
}
impl From<RgbPalette> for FlatPalette {
fn from(palette: RgbPalette) -> Self {
let mut flat = [RgbColor::default(); FLAT_PALETTE_SIZE];
for color in 0..PALETTE_COLORS {
for emph in 0..EMPHASIS_COMBINATIONS {
flat[color | (emph << 6)] = palette.colors[emph][color];
}
}
Self {
palette: flat,
}
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct LookupPaletteRenderer {
palette: FlatPalette,
image: Vec<RgbColor>,
}
impl Default for LookupPaletteRenderer {
fn default() -> Self { Self::new() }
}
impl LookupPaletteRenderer {
pub fn new() -> Self {
Self {
palette: RgbPalette::default().into(),
image: vec![],
}
}
}
impl Debug for LookupPaletteRenderer {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.get_display_name())
}
}
impl ScreenRenderer for LookupPaletteRenderer {
fn buffer_to_image(&mut self, buffer: &[u16]) -> &[RgbColor] {
if self.image.len() != buffer.len() {
self.image = Vec::with_capacity(buffer.len());
};
self.image.clear();
for x in buffer.iter() {
self.image
.push(self.palette.palette[(*x as usize) & PALETTE_INDEX_MASK])
}
&self.image
}
fn set_palette(&mut self, rgb_palette: RgbPalette) { self.palette = rgb_palette.into(); }
fn get_width(&self) -> usize { TOTAL_OUTPUT_WIDTH }
fn get_height(&self) -> usize { TOTAL_OUTPUT_HEIGHT }
fn get_id(&self) -> &'static str { "PaletteLookup" }
fn get_display_name(&self) -> &'static str { "Palette Lookup Renderer" }
}