use crate::rom::block::Block;
use crate::rom::palette_cycle::PaletteCycle;
#[derive(Debug)]
pub struct RomGraphics {
bits_per_pixel: u8,
gfx_rom_graphics: Vec<i16>,
tiles: Vec<[[i16; 8]; 8]>,
}
impl RomGraphics {
pub fn new(bits_per_pixel: u8) -> Self {
RomGraphics {
bits_per_pixel,
gfx_rom_graphics: vec![],
tiles: vec![],
}
}
fn build_tiles(&mut self) {
let n = self.gfx_rom_graphics.len() / (8 * usize::from(self.bits_per_pixel));
self.tiles = vec![];
for i in 0..n {
self.tiles.push([[0; 8]; 8]);
let o = i * 8 * usize::from(self.bits_per_pixel);
for x in 0..8 {
self.tiles[i][x] = [0; 8];
for y in 0..8 {
let mut c = 0;
for bp in 0..usize::from(self.bits_per_pixel) {
let half_bp = bp / 2;
let gfx = self.gfx_rom_graphics[o + y * 2 + (half_bp * 16 + (bp & 1))];
c += ((gfx & (1 << 7 - x)) >> 7 - x) << bp;
}
self.tiles[i][x][y] = c;
}
}
}
}
pub fn draw(&mut self, bmp: &mut [i16], palette: &PaletteCycle, array_rom_graphics: &[i16]) {
let data = bmp;
let mut block;
let mut tile;
let mut sub_palette;
let mut n;
let mut b1;
let mut b2;
let mut vertical_flip;
let mut horizontal_flip;
let stride = 1024;
for i in 0..32 {
for j in 0..32 {
n = j * 32 + i;
b1 = array_rom_graphics[n * 2];
b2 = array_rom_graphics[n * 2 + 1] << 8;
block = i64::from(b1 + b2);
tile = block & 0x3FF;
vertical_flip = (block & 0x8000) != 0;
horizontal_flip = (block & 0x4000) != 0;
sub_palette = (block >> 10) & 7;
self.draw_tile(
data,
stride,
i * 8,
j * 8,
palette,
tile as usize,
sub_palette as usize,
vertical_flip,
horizontal_flip,
);
}
}
}
fn draw_tile(
&mut self,
pixels: &mut [i16],
stride: usize,
x: usize,
y: usize,
palette: &PaletteCycle,
tile: usize,
sub_palette: usize,
vertical_flip: bool,
horizontal_flip: bool,
) {
let x = x as isize;
let y = y as isize;
let sub_palette_array = palette.get_colors(sub_palette);
let mut px;
let mut py;
let mut pos;
for i in 0usize..8 {
if horizontal_flip {
px = x + 7 - i as isize;
} else {
px = x + i as isize;
}
for j in 0usize..8 {
let rgb_array = sub_palette_array[self.tiles[tile][i][j] as usize];
if vertical_flip {
py = y + 7 - j as isize;
} else {
py = y + j as isize;
}
pos = 4 * px + (stride as isize) * py;
pixels[(pos + 0) as usize] = ((rgb_array >> 16) & 0xFF) as i16;
pixels[(pos + 1) as usize] = ((rgb_array >> 8) & 0xFF) as i16;
pixels[(pos + 2) as usize] = ((rgb_array) & 0xFF) as i16;
}
}
}
pub fn load_graphics(&mut self, mut block: Block) {
self.gfx_rom_graphics = block.decompress();
self.build_tiles();
}
}