From 66a5c94d5b9cf05fb7f553bba70a51df9bf20f11 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 28 Nov 2023 15:03:33 +0100 Subject: [PATCH] Color math: properly clip colors --- src/snes/ppu/color.rs | 14 ++++++++++++-- src/snes/ppu/render.rs | 4 +++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/snes/ppu/color.rs b/src/snes/ppu/color.rs index c98d7d8..44c8982 100644 --- a/src/snes/ppu/color.rs +++ b/src/snes/ppu/color.rs @@ -1,3 +1,5 @@ +use std::cmp::min; + use num_traits::int::PrimInt; use num_traits::AsPrimitive; @@ -18,6 +20,14 @@ impl SnesColor { Self((r as u16 & 0x1F) | (g as u16 & 0x1F) << 5 | (b as u16 & 0x1F) << 10) } + pub fn from_rgb5_clip(r: u8, g: u8, b: u8) -> SnesColor { + Self( + (min(r, 0x1F) as u16 & 0x1F) + | (min(g, 0x1F) as u16 & 0x1F) << 5 + | (min(b, 0x1F) as u16 & 0x1F) << 10, + ) + } + /// Convert to a (host)-native color (RGB888) pub fn to_native(&self) -> Color { // TODO better put this in the frontend? I'm not sure.. @@ -77,7 +87,7 @@ impl SnesColor { /// Color math add pub fn cm_add(&self, other: &SnesColor, div2: bool) -> SnesColor { let div = if div2 { 2 } else { 1 }; - Self::from_rgb5( + Self::from_rgb5_clip( (self.r() + other.r()) / div, (self.g() + other.g()) / div, (self.b() + other.b()) / div, @@ -87,7 +97,7 @@ impl SnesColor { /// Color math subtract pub fn cm_sub(&self, other: &SnesColor, div2: bool) -> SnesColor { let div = if div2 { 2 } else { 1 }; - Self::from_rgb5( + Self::from_rgb5_clip( (self.r().saturating_sub(other.r())) / div, (self.g().saturating_sub(other.g())) / div, (self.b().saturating_sub(other.b())) / div, diff --git a/src/snes/ppu/render.rs b/src/snes/ppu/render.rs index fbf7f4c..3703bb9 100644 --- a/src/snes/ppu/render.rs +++ b/src/snes/ppu/render.rs @@ -370,7 +370,9 @@ where return pixel; } - let div2 = self.cgadsub & (1 << 6) != 0 && sublayer != LAYER_BACKDROP; + let div2 = self.cgadsub & (1 << 6) != 0 + && sublayer != LAYER_BACKDROP + && mainlayer != LAYER_BACKDROP; if self.cgadsub & (1 << 7) == 0 { // Add mode pixel = pixel.cm_add(&subclr, div2);