Started work on palette support
This commit is contained in:
parent
509a76924a
commit
458fec99dd
118
src/display.rs
118
src/display.rs
@ -51,6 +51,12 @@ const SPRITE_X_FLIP: u8 = 1 << 5;
|
||||
const SPRITE_PALETTE_NO: u8 = 1 << 4; // NonCGB only
|
||||
const SPRITE_TILE_VRAM_BANK: u8 = 1 << 3; // CGB only
|
||||
|
||||
const MONOCHROME_PALETTE: &'static [[f64; 3]; 4] = &[
|
||||
[0.605, 0.734, 0.059],
|
||||
[0.543, 0.672, 0.059],
|
||||
[0.188, 0.383, 0.188],
|
||||
[0.059, 0.219, 0.059],
|
||||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
enum DisplayMode {
|
||||
@ -89,6 +95,14 @@ impl Sprite {
|
||||
fn is_y_flipped(&self) -> bool {
|
||||
self.flags & SPRITE_Y_FLIP == SPRITE_Y_FLIP
|
||||
}
|
||||
|
||||
fn palette(&self) -> u8 {
|
||||
if self.flags & SPRITE_PALETTE_NO == 0 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Display {
|
||||
@ -156,7 +170,8 @@ impl Display {
|
||||
#[inline]
|
||||
fn set_pixel(&mut self, x: u8, y: u8, color: sdl2::pixels::Color) {
|
||||
self.renderer.set_draw_color(color);
|
||||
self.renderer.fill_rect(sdl2::rect::Rect::new((x as i32) * SCALE as i32, (y as i32) * SCALE as i32, SCALE as u32, SCALE as u32));
|
||||
self.renderer.fill_rect(sdl2::rect::Rect::new((x as i32) * SCALE as i32, (y as i32) * SCALE as i32, SCALE as u32, SCALE as u32))
|
||||
.expect("Draw failed");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -198,11 +213,26 @@ impl Display {
|
||||
0xFF43 => self.scrollx = val,
|
||||
0xFF44 => self.curline = 0,
|
||||
0xFF45 => self.lyc = val,
|
||||
0xFF47 => self.background_palette = val,
|
||||
0xFF48 => self.object_palette_0 = val,
|
||||
0xFF49 => self.object_palette_1 = val,
|
||||
0xFF4A => self.windowy = val,
|
||||
0xFF4B => self.windowx = val,
|
||||
0xFF47 => {
|
||||
println!("BG PALETTE = {:02X}", val);
|
||||
self.background_palette = val;
|
||||
}
|
||||
0xFF48 => {
|
||||
println!("OBJ0 PALETTE = {:02X}", val);
|
||||
self.object_palette_0 = val;
|
||||
}
|
||||
0xFF49 => {
|
||||
println!("OBJ1 PALETTE = {:02X}", val);
|
||||
self.object_palette_1 = val;
|
||||
}
|
||||
0xFF4A => {
|
||||
println!("WY set to {:02X}", val);
|
||||
self.windowy = val;
|
||||
}
|
||||
0xFF4B => {
|
||||
println!("WX set to {:02X}", val);
|
||||
self.windowx = val;
|
||||
}
|
||||
_ => panic!("Display: Write {:02X} to {:04X} unsupported", val, addr),
|
||||
}
|
||||
}
|
||||
@ -321,16 +351,19 @@ impl Display {
|
||||
for i in 0 .. 39 {
|
||||
let sprite = &sprites[i];
|
||||
|
||||
// Skip hidden sprites
|
||||
if sprite.is_hidden() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Should we draw this sprite this iteration
|
||||
if foreground && !sprite.is_foreground() {
|
||||
continue;
|
||||
} else if !foreground && sprite.is_foreground() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate correct coords
|
||||
let x: u8 = sprite.x.wrapping_sub(8);
|
||||
let y: u8 = sprite.y.wrapping_sub(16);
|
||||
|
||||
@ -338,12 +371,13 @@ impl Display {
|
||||
|
||||
// Is this sprite on the current line?
|
||||
if y.wrapping_add(8) >= render_y && y <= render_y {
|
||||
// Flip sprite, TODO: Validate
|
||||
let y_o: u8 = match sprite.is_y_flipped() {
|
||||
true => y ^ 7,
|
||||
false => y
|
||||
};
|
||||
let tile_offset_y: usize = render_y as usize - y_o as usize;
|
||||
let tile_base_addr: usize = sprite.tile as usize * 16;
|
||||
let tile_base_addr: usize = sprite.tile as usize * 16; // Should this be twice as wide in wide mode?
|
||||
|
||||
let tile_line_1 = self.vram[tile_base_addr + tile_offset_y * 2 + 1];
|
||||
let tile_line_2 = self.vram[tile_base_addr + tile_offset_y * 2 + 1];
|
||||
@ -352,6 +386,9 @@ impl Display {
|
||||
|
||||
// We need to draw this.
|
||||
let wide_mode = self.control & CTRL_BG_SPRITE_SIZE > 0;
|
||||
if wide_mode {
|
||||
panic!("TODO");
|
||||
}
|
||||
let limit = match wide_mode {
|
||||
true => 16,
|
||||
false => 8
|
||||
@ -374,23 +411,36 @@ impl Display {
|
||||
b2 = (tile_line_2 & 1 << (7 - x_o2)) > 0;
|
||||
}
|
||||
|
||||
if b1 {
|
||||
factor += 64;
|
||||
}
|
||||
if b2 {
|
||||
factor += 128;
|
||||
}
|
||||
// -> self.background_palette.
|
||||
//0xFF47 => self.background_palette = val,
|
||||
//0xFF48 => self.object_palette_0 = val,
|
||||
//0xFF49 => self.object_palette_1 = val,
|
||||
|
||||
// Transparent.
|
||||
// Sprites may be transparent.
|
||||
if !b1 && !b2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
factor = 255 - factor;
|
||||
let c = (b1 as u8) * 2 + b2 as u8;
|
||||
let lookup: [u8; 4] = match sprite.palette() {
|
||||
0 => [
|
||||
self.object_palette_0 & 3,
|
||||
(self.object_palette_0 >> 2) & 3,
|
||||
(self.object_palette_0 >> 4) & 3,
|
||||
(self.object_palette_0 >> 6) & 3,
|
||||
],
|
||||
1 => [
|
||||
self.object_palette_1 & 3,
|
||||
(self.object_palette_1 >> 2) & 3,
|
||||
(self.object_palette_1 >> 4) & 3,
|
||||
(self.object_palette_1 >> 6) & 3,
|
||||
],
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let entry = MONOCHROME_PALETTE[lookup[c as usize] as usize];
|
||||
|
||||
// Draw stuff. We're currently only in monochrome mode
|
||||
self.set_pixel(x.wrapping_add(x_o), render_y, sdl2::pixels::Color::RGB(factor, factor, factor));
|
||||
|
||||
self.set_pixel(x.wrapping_add(x_o), render_y, sdl2::pixels::Color::RGB((entry[0]*255.0) as u8, (entry[1]*255.0) as u8, (entry[2]*255.0) as u8));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -449,12 +499,12 @@ impl Display {
|
||||
for t_x in 0 .. 160/8 {
|
||||
self.renderer.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 10, 0xFF));
|
||||
|
||||
let RX: i32 = (t_x as i32)*8 + map_offset_x as i32;
|
||||
let RY: i32 = ((render_y as u32) & 0xFFFFFFF8) as i32 - map_offset_y as i32;
|
||||
let TS: u32 = 8u32 * (SCALE as u32);
|
||||
let rx: i32 = (t_x as i32)*8 + map_offset_x as i32;
|
||||
let ry: i32 = ((render_y as u32) & 0xFFFFFFF8) as i32 - map_offset_y as i32;
|
||||
let ts: u32 = 8u32 * (SCALE as u32);
|
||||
self.renderer.draw_rect(
|
||||
sdl2::rect::Rect::new(RX * SCALE as i32, RY * SCALE as i32, TS, TS)
|
||||
);
|
||||
sdl2::rect::Rect::new(rx * SCALE as i32, ry * SCALE as i32, ts, ts)
|
||||
).expect("Draw failed");
|
||||
}
|
||||
}
|
||||
// Render pixels (20 tiles)
|
||||
@ -494,23 +544,18 @@ impl Display {
|
||||
// Get the correct bit
|
||||
let b1: bool = (tile_line_1 & 1 << (7 - tile_offset_x)) > 0;
|
||||
let b2: bool = (tile_line_2 & 1 << (7 - tile_offset_x)) > 0;
|
||||
if !b1 && !b2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut factor = 0;
|
||||
if b1 {
|
||||
factor += 64;
|
||||
}
|
||||
if b2 {
|
||||
factor += 128;
|
||||
}
|
||||
|
||||
factor = 255 - factor;
|
||||
let c = (b1 as u8) * 2 + b2 as u8;
|
||||
let lookup: [u8; 4] = [
|
||||
self.background_palette & 3,
|
||||
(self.background_palette >> 2) & 3,
|
||||
(self.background_palette >> 4) & 3,
|
||||
(self.background_palette >> 6) & 3,
|
||||
];
|
||||
let entry = MONOCHROME_PALETTE[lookup[c as usize] as usize];
|
||||
|
||||
// Draw stuff. We're currently only in monochrome mode
|
||||
self.set_pixel(render_x, render_y, sdl2::pixels::Color::RGB(factor, factor, factor));
|
||||
|
||||
self.set_pixel(render_x, render_y, sdl2::pixels::Color::RGB((entry[0]*255.0) as u8, (entry[1]*255.0) as u8, (entry[2]*255.0) as u8));
|
||||
}
|
||||
|
||||
if self.control & CTRL_BG_SPRITE_ENABLE > 0 {
|
||||
@ -518,5 +563,4 @@ impl Display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user