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_PALETTE_NO: u8 = 1 << 4; // NonCGB only
|
||||||
const SPRITE_TILE_VRAM_BANK: u8 = 1 << 3; // CGB 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)]
|
#[derive(Debug)]
|
||||||
enum DisplayMode {
|
enum DisplayMode {
|
||||||
@ -89,6 +95,14 @@ impl Sprite {
|
|||||||
fn is_y_flipped(&self) -> bool {
|
fn is_y_flipped(&self) -> bool {
|
||||||
self.flags & SPRITE_Y_FLIP == SPRITE_Y_FLIP
|
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 {
|
pub struct Display {
|
||||||
@ -156,7 +170,8 @@ impl Display {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn set_pixel(&mut self, x: u8, y: u8, color: sdl2::pixels::Color) {
|
fn set_pixel(&mut self, x: u8, y: u8, color: sdl2::pixels::Color) {
|
||||||
self.renderer.set_draw_color(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]
|
#[inline]
|
||||||
@ -198,11 +213,26 @@ impl Display {
|
|||||||
0xFF43 => self.scrollx = val,
|
0xFF43 => self.scrollx = val,
|
||||||
0xFF44 => self.curline = 0,
|
0xFF44 => self.curline = 0,
|
||||||
0xFF45 => self.lyc = val,
|
0xFF45 => self.lyc = val,
|
||||||
0xFF47 => self.background_palette = val,
|
0xFF47 => {
|
||||||
0xFF48 => self.object_palette_0 = val,
|
println!("BG PALETTE = {:02X}", val);
|
||||||
0xFF49 => self.object_palette_1 = val,
|
self.background_palette = val;
|
||||||
0xFF4A => self.windowy = val,
|
}
|
||||||
0xFF4B => self.windowx = 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),
|
_ => panic!("Display: Write {:02X} to {:04X} unsupported", val, addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,16 +351,19 @@ impl Display {
|
|||||||
for i in 0 .. 39 {
|
for i in 0 .. 39 {
|
||||||
let sprite = &sprites[i];
|
let sprite = &sprites[i];
|
||||||
|
|
||||||
|
// Skip hidden sprites
|
||||||
if sprite.is_hidden() {
|
if sprite.is_hidden() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should we draw this sprite this iteration
|
||||||
if foreground && !sprite.is_foreground() {
|
if foreground && !sprite.is_foreground() {
|
||||||
continue;
|
continue;
|
||||||
} else if !foreground && sprite.is_foreground() {
|
} else if !foreground && sprite.is_foreground() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate correct coords
|
||||||
let x: u8 = sprite.x.wrapping_sub(8);
|
let x: u8 = sprite.x.wrapping_sub(8);
|
||||||
let y: u8 = sprite.y.wrapping_sub(16);
|
let y: u8 = sprite.y.wrapping_sub(16);
|
||||||
|
|
||||||
@ -338,12 +371,13 @@ impl Display {
|
|||||||
|
|
||||||
// Is this sprite on the current line?
|
// Is this sprite on the current line?
|
||||||
if y.wrapping_add(8) >= render_y && y <= render_y {
|
if y.wrapping_add(8) >= render_y && y <= render_y {
|
||||||
|
// Flip sprite, TODO: Validate
|
||||||
let y_o: u8 = match sprite.is_y_flipped() {
|
let y_o: u8 = match sprite.is_y_flipped() {
|
||||||
true => y ^ 7,
|
true => y ^ 7,
|
||||||
false => y
|
false => y
|
||||||
};
|
};
|
||||||
let tile_offset_y: usize = render_y as usize - y_o as usize;
|
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_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];
|
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.
|
// We need to draw this.
|
||||||
let wide_mode = self.control & CTRL_BG_SPRITE_SIZE > 0;
|
let wide_mode = self.control & CTRL_BG_SPRITE_SIZE > 0;
|
||||||
|
if wide_mode {
|
||||||
|
panic!("TODO");
|
||||||
|
}
|
||||||
let limit = match wide_mode {
|
let limit = match wide_mode {
|
||||||
true => 16,
|
true => 16,
|
||||||
false => 8
|
false => 8
|
||||||
@ -374,23 +411,36 @@ impl Display {
|
|||||||
b2 = (tile_line_2 & 1 << (7 - x_o2)) > 0;
|
b2 = (tile_line_2 & 1 << (7 - x_o2)) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if b1 {
|
// -> self.background_palette.
|
||||||
factor += 64;
|
//0xFF47 => self.background_palette = val,
|
||||||
}
|
//0xFF48 => self.object_palette_0 = val,
|
||||||
if b2 {
|
//0xFF49 => self.object_palette_1 = val,
|
||||||
factor += 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transparent.
|
// Sprites may be transparent.
|
||||||
if !b1 && !b2 {
|
if !b1 && !b2 {
|
||||||
continue;
|
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
|
// 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 {
|
for t_x in 0 .. 160/8 {
|
||||||
self.renderer.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 10, 0xFF));
|
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 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 ry: i32 = ((render_y as u32) & 0xFFFFFFF8) as i32 - map_offset_y as i32;
|
||||||
let TS: u32 = 8u32 * (SCALE as u32);
|
let ts: u32 = 8u32 * (SCALE as u32);
|
||||||
self.renderer.draw_rect(
|
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)
|
// Render pixels (20 tiles)
|
||||||
@ -494,23 +544,18 @@ impl Display {
|
|||||||
// Get the correct bit
|
// Get the correct bit
|
||||||
let b1: bool = (tile_line_1 & 1 << (7 - tile_offset_x)) > 0;
|
let b1: bool = (tile_line_1 & 1 << (7 - tile_offset_x)) > 0;
|
||||||
let b2: bool = (tile_line_2 & 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;
|
let c = (b1 as u8) * 2 + b2 as u8;
|
||||||
if b1 {
|
let lookup: [u8; 4] = [
|
||||||
factor += 64;
|
self.background_palette & 3,
|
||||||
}
|
(self.background_palette >> 2) & 3,
|
||||||
if b2 {
|
(self.background_palette >> 4) & 3,
|
||||||
factor += 128;
|
(self.background_palette >> 6) & 3,
|
||||||
}
|
];
|
||||||
|
let entry = MONOCHROME_PALETTE[lookup[c as usize] as usize];
|
||||||
factor = 255 - factor;
|
|
||||||
|
|
||||||
// Draw stuff. We're currently only in monochrome mode
|
// 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 {
|
if self.control & CTRL_BG_SPRITE_ENABLE > 0 {
|
||||||
@ -518,5 +563,4 @@ impl Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user