automatic palettes work
This commit is contained in:
parent
7fba9cca89
commit
27e0374181
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -989,6 +989,7 @@ name = "gb-emu-lib"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-ringbuf",
|
||||
"bytemuck",
|
||||
"futures",
|
||||
"itertools",
|
||||
"once_cell",
|
||||
|
|
|
@ -15,3 +15,4 @@ once_cell = "1.17.1"
|
|||
itertools = "0.10.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_with = "2.3.1"
|
||||
bytemuck = "1.13"
|
||||
|
|
|
@ -5,8 +5,8 @@ use self::{
|
|||
cgb::CgbData,
|
||||
tile_window::TileWindow,
|
||||
types::{
|
||||
GpuInterrupts, Lcdc, Oam, ObjPalette, ObjSize, Object, ObjectFlags, Palette, Stat,
|
||||
TiledataArea, TilemapArea, Vram,
|
||||
ColourInner, GpuInterrupts, Lcdc, Oam, ObjPalette, ObjSize, Object, ObjectFlags, Palette,
|
||||
Stat, TiledataArea, TilemapArea, Vram,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
|
@ -132,7 +132,7 @@ where
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let buffer = vec![Colour::Error.into(); WIDTH * HEIGHT];
|
||||
let buffer = vec![ColourInner::Error.rgb_bytes(None).into(); WIDTH * HEIGHT];
|
||||
|
||||
Self {
|
||||
buffer,
|
||||
|
@ -315,7 +315,8 @@ where
|
|||
*e = true;
|
||||
}
|
||||
for x in 0..WIDTH {
|
||||
self.buffer[(scanline as usize * WIDTH) + x] = Colour::Error.into();
|
||||
self.buffer[(scanline as usize * WIDTH) + x] =
|
||||
ColourInner::Error.rgb_bytes(None).into();
|
||||
}
|
||||
if self.lcdc.bg_window_enable {
|
||||
self.render_scanline_bg(scanline);
|
||||
|
@ -328,7 +329,8 @@ where
|
|||
}
|
||||
} else {
|
||||
for x in 0..WIDTH {
|
||||
self.buffer[(scanline as usize * WIDTH) + x] = Colour::Error.into();
|
||||
self.buffer[(scanline as usize * WIDTH) + x] =
|
||||
ColourInner::Error.rgb_bytes(None).into();
|
||||
}
|
||||
}
|
||||
if self.lcdc.obj_enable {
|
||||
|
@ -449,7 +451,9 @@ where
|
|||
if x_coord < WIDTH {
|
||||
let buffer_index = (scanline as usize * WIDTH) + x_coord;
|
||||
if !object.flags.behind_bg_and_window || self.is_bg_zero[x_coord] {
|
||||
self.buffer[buffer_index] = colour.into();
|
||||
let cgb_data = self.cgb_data.as_ref().map(|v| (v.palettes.obj, 0));
|
||||
|
||||
self.buffer[buffer_index] = colour.rgb_bytes(cgb_data).into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +499,9 @@ where
|
|||
let (colour, is_zero) = self.bg_palette.map_bits(lsb, msb);
|
||||
self.is_bg_zero[x] = is_zero;
|
||||
|
||||
self.buffer[(scanline as usize * WIDTH) + x] = colour.into();
|
||||
let cgb_data = self.cgb_data.as_ref().map(|v| (v.palettes.bg, 0));
|
||||
|
||||
self.buffer[(scanline as usize * WIDTH) + x] = colour.rgb_bytes(cgb_data).into();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ use super::{Colour, Gpu};
|
|||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
pub(super) struct CgbData {
|
||||
palettes: CgbPaletteRegisters,
|
||||
object_priority_mode: ObjectPriorityMode,
|
||||
pub(super) palettes: CgbPaletteRegisters,
|
||||
pub(super) object_priority_mode: ObjectPriorityMode,
|
||||
}
|
||||
|
||||
impl Default for CgbData {
|
||||
|
@ -24,24 +24,24 @@ impl Default for CgbData {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
enum ObjectPriorityMode {
|
||||
pub(super) enum ObjectPriorityMode {
|
||||
OamLocation = 0,
|
||||
Coordinate = 1,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Default)]
|
||||
struct CgbPaletteRegisters {
|
||||
bg: CgbPalette,
|
||||
obj: CgbPalette,
|
||||
pub(super) struct CgbPaletteRegisters {
|
||||
pub(super) bg: CgbPalette,
|
||||
pub(super) obj: CgbPalette,
|
||||
}
|
||||
|
||||
#[serde_with::serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
struct CgbPalette {
|
||||
pub(super) struct CgbPalette {
|
||||
auto_increment: bool,
|
||||
index: u8,
|
||||
#[serde_as(as = "[_; 0x40]")]
|
||||
data: [u8; 0x40],
|
||||
pub(super) data: [u8; 0x40],
|
||||
}
|
||||
|
||||
impl Default for CgbPalette {
|
||||
|
|
|
@ -4,7 +4,10 @@ use crate::{
|
|||
util::get_bit,
|
||||
};
|
||||
|
||||
use super::{types::Vram, Colour};
|
||||
use super::{
|
||||
types::{ColourInner, Vram},
|
||||
Colour,
|
||||
};
|
||||
|
||||
pub(super) struct TileWindow<ColourFormat, R>
|
||||
where
|
||||
|
@ -22,7 +25,10 @@ where
|
|||
{
|
||||
pub(super) fn new(window: R) -> Self {
|
||||
Self {
|
||||
sprite_buffer: vec![Colour::Error.into(); TILE_WINDOW_WIDTH * TILE_WINDOW_HEIGHT],
|
||||
sprite_buffer: vec![
|
||||
ColourInner::Error.rgb_bytes(None).into();
|
||||
TILE_WINDOW_WIDTH * TILE_WINDOW_HEIGHT
|
||||
],
|
||||
sprite_renderer: window,
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +78,7 @@ where
|
|||
let colour = palette.map_bits(lsb, msb);
|
||||
|
||||
self.sprite_buffer[real_px_x + (real_px_y * TILE_WINDOW_WIDTH)] =
|
||||
colour.0.into();
|
||||
colour.0.rgb_bytes(None).into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use bytemuck::from_bytes;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
|
@ -5,6 +6,8 @@ use crate::{
|
|||
util::{as_signed, get_bit},
|
||||
};
|
||||
|
||||
use super::cgb::CgbPalette;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
|
||||
pub(crate) enum DrawMode {
|
||||
HBlank,
|
||||
|
@ -89,75 +92,92 @@ impl Default for Lcdc {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Colour {
|
||||
White,
|
||||
LightGray,
|
||||
DarkGray,
|
||||
Black,
|
||||
Error,
|
||||
pub enum ColourInner {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
Two = 2,
|
||||
Three = 3,
|
||||
Error = 255,
|
||||
}
|
||||
|
||||
pub struct Colour(u8, u8, u8);
|
||||
|
||||
impl From<Colour> for u32 {
|
||||
fn from(value: Colour) -> Self {
|
||||
let rgb = value.rgb_bytes();
|
||||
let (r, g, b) = (rgb.0 as u32, rgb.1 as u32, rgb.2 as u32);
|
||||
let (r, g, b) = (value.0 as u32, value.1 as u32, value.2 as u32);
|
||||
(r << 16) | (g << 8) | b
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Colour> for [u8; 4] {
|
||||
fn from(value: Colour) -> Self {
|
||||
let (r, g, b) = value.rgb_bytes();
|
||||
let Colour(r, g, b) = value;
|
||||
[r, g, b, 0xFF]
|
||||
}
|
||||
}
|
||||
|
||||
impl Colour {
|
||||
fn rgb_bytes(&self) -> (u8, u8, u8) {
|
||||
fn rgb_from_bytes(bytes: u16) -> Colour {
|
||||
let blue = (((bytes & (0b11111 << 10)) >> 10) << 3) as u8;
|
||||
let green = (((bytes & (0b11111 << 5)) >> 5) << 3) as u8;
|
||||
let red = ((bytes & 0b11111) << 3) as u8;
|
||||
Colour(red, green, blue)
|
||||
}
|
||||
|
||||
impl ColourInner {
|
||||
pub(super) fn rgb_bytes(&self, cgb_data: Option<(CgbPalette, u8)>) -> Colour {
|
||||
if let Some((cgb_palette, pallete_num)) = cgb_data {
|
||||
if *self == ColourInner::Error {
|
||||
return Colour(0xFF, 0, 0);
|
||||
}
|
||||
let offset: usize = (pallete_num as usize * 2 * 4) + (*self as usize * 2);
|
||||
|
||||
rgb_from_bytes(*from_bytes(&cgb_palette.data[offset..=offset + 1]))
|
||||
} else {
|
||||
match self {
|
||||
Colour::White => (0xFF, 0xFF, 0xFF),
|
||||
Colour::LightGray => (0xAA, 0xAA, 0xAA),
|
||||
Colour::DarkGray => (0x55, 0x55, 0x55),
|
||||
Colour::Black => (0x00, 0x00, 0x00),
|
||||
Colour::Error => (0xFF, 0x00, 0x00),
|
||||
ColourInner::Zero => Colour(0xFF, 0xFF, 0xFF),
|
||||
ColourInner::One => Colour(0xAA, 0xAA, 0xAA),
|
||||
ColourInner::Two => Colour(0x55, 0x55, 0x55),
|
||||
ColourInner::Three => Colour(0x00, 0x00, 0x00),
|
||||
ColourInner::Error => Colour(0xFF, 0x00, 0x00),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn from_bits(first: bool, second: bool) -> Colour {
|
||||
pub(super) fn from_bits(first: bool, second: bool) -> ColourInner {
|
||||
match (first, second) {
|
||||
(true, true) => Colour::Black,
|
||||
(true, false) => Colour::LightGray,
|
||||
(false, true) => Colour::DarkGray,
|
||||
(false, false) => Colour::White,
|
||||
(true, true) => ColourInner::Three,
|
||||
(true, false) => ColourInner::One,
|
||||
(false, true) => ColourInner::Two,
|
||||
(false, false) => ColourInner::Zero,
|
||||
}
|
||||
}
|
||||
|
||||
fn as_bits(&self) -> u8 {
|
||||
match self {
|
||||
Colour::White => 0b00,
|
||||
Colour::LightGray => 0b01,
|
||||
Colour::DarkGray => 0b10,
|
||||
Colour::Black => 0b11,
|
||||
Colour::Error => 0b00,
|
||||
ColourInner::Zero => 0b00,
|
||||
ColourInner::One => 0b01,
|
||||
ColourInner::Two => 0b10,
|
||||
ColourInner::Three => 0b11,
|
||||
ColourInner::Error => 0b00,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub(super) struct Palette {
|
||||
pub(super) zero: Colour,
|
||||
pub(super) one: Colour,
|
||||
pub(super) two: Colour,
|
||||
pub(super) three: Colour,
|
||||
pub(super) zero: ColourInner,
|
||||
pub(super) one: ColourInner,
|
||||
pub(super) two: ColourInner,
|
||||
pub(super) three: ColourInner,
|
||||
}
|
||||
|
||||
impl Palette {
|
||||
pub(super) fn from_byte(byte: u8) -> Palette {
|
||||
Palette {
|
||||
zero: Colour::from_bits(get_bit(byte, 0), get_bit(byte, 1)),
|
||||
one: Colour::from_bits(get_bit(byte, 2), get_bit(byte, 3)),
|
||||
two: Colour::from_bits(get_bit(byte, 4), get_bit(byte, 5)),
|
||||
three: Colour::from_bits(get_bit(byte, 6), get_bit(byte, 7)),
|
||||
zero: ColourInner::from_bits(get_bit(byte, 0), get_bit(byte, 1)),
|
||||
one: ColourInner::from_bits(get_bit(byte, 2), get_bit(byte, 3)),
|
||||
two: ColourInner::from_bits(get_bit(byte, 4), get_bit(byte, 5)),
|
||||
three: ColourInner::from_bits(get_bit(byte, 6), get_bit(byte, 7)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +188,7 @@ impl Palette {
|
|||
| (self.three.as_bits() << 6)
|
||||
}
|
||||
|
||||
pub(super) fn map_bits(&self, lsb: bool, msb: bool) -> (Colour, bool) {
|
||||
pub(super) fn map_bits(&self, lsb: bool, msb: bool) -> (ColourInner, bool) {
|
||||
match (lsb, msb) {
|
||||
(true, true) => (self.three, false),
|
||||
(true, false) => (self.one, false),
|
||||
|
|
Loading…
Reference in a new issue