use crate::{ Background, Gsa, Rgb, BACKGROUND_MAX_SIZE, EMPTY_TILE, HALF_TILE_SIZE, MAX_BACKGROUNDS, SCREEN_HEIGHT, SCREEN_WIDTH, TILESET_SIZE, TILE_SIZE, TRANSPARENT, }; use glam::IVec2; use softbuffer::Buffer; fn draw_tile(target: &mut [u8], pos: IVec2, tile: u16, tileset: &[u8], half: bool) { let tilesize = if half { HALF_TILE_SIZE } else { TILE_SIZE }; let tx = tile as usize % 0x100 * tilesize; let ty = tile as usize / 0x100 * tilesize; let startx = pos.x.max(0).min(SCREEN_WIDTH as i32); let starty = pos.y.max(0).min(SCREEN_HEIGHT as i32); let endx = (pos.x + tilesize as i32).max(0).min(SCREEN_WIDTH as i32); let endy = (pos.y + tilesize as i32).max(0).min(SCREEN_HEIGHT as i32); for y in (starty - pos.y)..(endy - pos.y) { for x in (startx - pos.x)..(endx - pos.x) { let p = tileset[(x as usize + tx) + (y as usize + ty) * (TILESET_SIZE * TILE_SIZE)]; if p != TRANSPARENT { target[(x as usize + pos.x as usize) + (y as usize + pos.y as usize) * SCREEN_WIDTH] = p; } } } } fn render_map(target: &mut [u8], map: &Background, tileset: &[u8]) { let tcmult = if map.half_tile { 2 } else { 1 }; let tilesize = if map.half_tile { HALF_TILE_SIZE } else { TILE_SIZE } as i32; let mut startx = map.scroll.x / tilesize; let mut starty = map.scroll.y / tilesize; let endx = (BACKGROUND_MAX_SIZE as i32).min(startx + 20 * tcmult); let endy = (BACKGROUND_MAX_SIZE as i32).min(starty + 12 * tcmult); startx = 0.max(startx); starty = 0.max(starty); for x in startx..endx { for y in starty..endy { let tile = map.tiles[x as usize][y as usize]; if tile > EMPTY_TILE { draw_tile( target, IVec2 { x: x * tilesize - map.scroll.x, y: y * tilesize - map.scroll.y, }, tile, tileset, map.half_tile, ); } } } } pub(crate) fn render_to_screen(target: &mut [u8], gsa: &Gsa, tileset: &[u8]) { for i in 0..MAX_BACKGROUNDS { render_map(target, &gsa.bgs[i], tileset); for sprite in &gsa.sprites { if sprite.tile > 0 && sprite.priority == i as u8 { draw_tile(target, sprite.pos, sprite.tile, tileset, false); } } } } pub(crate) fn render_to_window( target: &mut Buffer, src: &mut [u8], palette: &[Rgb; 256], window_size: IVec2, scale: usize, off_x: usize, off_y: usize, ) { let start = window_size.x as usize * off_y; let end = start + window_size.x as usize * SCREEN_HEIGHT * scale; for (y, row) in target[start..end] .chunks_exact_mut(window_size.x as usize * scale) .enumerate() { let y = y as i32; for x in 0..SCREEN_WIDTH { let p = src[x + y as usize * SCREEN_WIDTH]; for scaley in 0..scale { for scalex in 0..scale { let sx = x * scale + scalex; row[sx + off_x + scaley * window_size.x as usize] = palette[p as usize].to_u32(); } } //unrolled is faster benchmarked... <_< /* let ww = window_size.x as usize; match scale { 1 => { row[x + off_x] = palette[p as usize].to_u32(); } 2 => { row[x * 2 + off_x] = palette[p as usize].to_u32(); row[x * 2 + off_x + 1] = palette[p as usize].to_u32(); row[x * 2 + off_x + ww] = palette[p as usize].to_u32(); row[x * 2 + off_x + ww + 1] = palette[p as usize].to_u32(); } 6 => { row[x * 6 + off_x + ww * 0] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 0 + 1] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 0 + 2] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 0 + 3] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 0 + 4] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 0 + 5] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 1] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 1 + 1] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 1 + 2] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 1 + 3] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 1 + 4] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 1 + 5] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 2] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 2 + 1] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 2 + 2] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 2 + 3] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 2 + 4] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 2 + 5] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 3] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 3 + 1] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 3 + 2] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 3 + 3] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 3 + 4] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 3 + 5] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 4] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 4 + 1] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 4 + 2] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 4 + 3] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 4 + 4] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 4 + 5] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 5] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 5 + 1] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 5 + 2] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 5 + 3] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 5 + 4] = palette[p as usize].to_u32(); row[x * 6 + off_x + ww * 5 + 5] = palette[p as usize].to_u32(); } _ => {} } */ } } }