diff --git a/Cargo.lock b/Cargo.lock index 046f41c..cd37711 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -992,6 +992,7 @@ dependencies = [ "bytemuck", "futures", "itertools", + "num-traits", "once_cell", "rand", "serde", diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 29d72ce..38c330c 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -16,3 +16,4 @@ itertools = "0.10.5" serde = { version = "1.0", features = ["derive"] } serde_with = "2.3.1" bytemuck = "1.13" +num-traits = "0.2" diff --git a/lib/src/processor/memory/mmio/gpu/types.rs b/lib/src/processor/memory/mmio/gpu/types.rs index 237ab11..559826c 100644 --- a/lib/src/processor/memory/mmio/gpu/types.rs +++ b/lib/src/processor/memory/mmio/gpu/types.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::{ processor::memory::addresses::{OamAddress, VramAddress}, - util::{as_signed, get_bit}, + util::{as_signed, get_bit, SaturatingCast}, }; use super::cgb::CgbPalette; @@ -117,10 +117,24 @@ impl From for [u8; 4] { } 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) + let b = (bytes & (0b11111 << 10)) >> 10; + let g = (bytes & (0b11111 << 5)) >> 5; + let r = bytes & 0b11111; + // direct colour emulation: + // let blue = (raw_blue << 3) | (raw_blue >> 2); + // let green = (raw_green << 3) | (raw_green >> 2); + // let red = (raw_red << 3) | (raw_red >> 2); + + // colour emulation from + // https://web.archive.org/web/20200322151952/https://byuu.net/video/color-emulation + let blue = (r * 6 + g * 4 + b * 22).min(960) >> 2; + let green = (g * 24 + b * 8).min(960) >> 2; + let red = (r * 26 + g * 4 + b * 2).min(960) >> 2; + Colour( + red.saturating_cast(), + green.saturating_cast(), + blue.saturating_cast(), + ) } impl ColourInner { diff --git a/lib/src/util.rs b/lib/src/util.rs index 0503ac2..e466f20 100644 --- a/lib/src/util.rs +++ b/lib/src/util.rs @@ -1,3 +1,5 @@ +use num_traits::{PrimInt, Unsigned}; + use crate::processor::{memory::mmio::gpu::Colour, Direction}; use std::{io, mem::transmute}; @@ -82,6 +84,23 @@ impl Nibbles for u8 { } } +pub trait SaturatingCast +where + T: PrimInt + Unsigned, +{ + fn saturating_cast(&self) -> T; +} + +impl SaturatingCast for F +where + T: PrimInt + Unsigned + TryFrom, + F: PrimInt + Unsigned, +{ + fn saturating_cast(&self) -> T { + (*self).try_into().unwrap_or(T::max_value()) + } +} + pub fn scale_buffer + Copy>( buffer: &[T], width: usize,