From e2389ecf19875067c657d63ab9aa65151122b680 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sun, 13 Nov 2022 10:16:40 +0000
Subject: [PATCH] feat: WASM palette colors

---
 CHANGELOG.md          |  1 +
 examples/web/index.ts |  8 ++++++++
 src/gb.rs             | 27 +++++++++++++++++++++++++++
 src/ppu.rs            | 16 ++++++++++------
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b21ddc4..fc4e4e94 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 * Support for true fullscreen at a browser level
 * Support for more flexible palette colors
+* Support for setting palette colors using WASM
 
 ### Changed
 
diff --git a/examples/web/index.ts b/examples/web/index.ts
index 79836e4e..ebc456c9 100644
--- a/examples/web/index.ts
+++ b/examples/web/index.ts
@@ -286,6 +286,14 @@ class GameboyEmulator extends EmulatorBase implements Emulator {
                 break;
         }
 
+        // @todo replace this with somethign more flexible
+        this.gameBoy.set_palette_colors_ws([
+            "b6a571",
+            "8b7e56",
+            "554d35",
+            "201d13"
+        ]);
+
         // resets the Game Boy engine to restore it into
         // a valid state ready to be used
         this.gameBoy.reset();
diff --git a/src/gb.rs b/src/gb.rs
index 77691658..27623252 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -10,6 +10,8 @@ use crate::{
 };
 
 #[cfg(feature = "wasm")]
+use crate::ppu::Palette;
+use std::convert::TryInto;
 use wasm_bindgen::prelude::*;
 
 #[cfg(feature = "wasm")]
@@ -244,9 +246,34 @@ impl GameBoy {
             prev(info);
         }));
     }
+
     pub fn load_rom_ws(&mut self, data: &[u8]) -> Cartridge {
         self.load_rom(data).clone()
     }
+
+    pub fn set_palette_colors_ws(&mut self, value: Vec<JsValue>) {
+        let palette: Palette = value
+            .into_iter()
+            .map(|v| self.convert_value(&v))
+            .collect::<Vec<[u8; 3]>>()
+            .try_into()
+            .unwrap();
+        self.ppu().set_palette_colors(&palette);
+    }
+
+    fn convert_value(&self, value: &JsValue) -> [u8; 3] {
+        value
+            .as_string()
+            .unwrap()
+            .chars()
+            .collect::<Vec<char>>()
+            .chunks(2)
+            .map(|s| s.iter().collect::<String>())
+            .map(|s| u8::from_str_radix(&s, 16).unwrap())
+            .collect::<Vec<u8>>()
+            .try_into()
+            .unwrap()
+    }
 }
 
 #[cfg(feature = "wasm")]
diff --git a/src/ppu.rs b/src/ppu.rs
index f74fd1aa..c871a452 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -178,8 +178,8 @@ pub struct Ppu {
     /// The base colors that are going to be used in the registration
     /// of the concrete palettes, this value basically controls the
     /// colors that are going to be shown for each of the four base
-    /// values - 0x00, 0x01, 0x02, and 0x03
-    pallette_colors: Palette,
+    /// values - 0x00, 0x01, 0x02, and 0x03.
+    palette_colors: Palette,
 
     /// The palette of colors that is currently loaded in Game Boy
     /// and used for background (tiles).
@@ -308,7 +308,7 @@ impl Ppu {
                 priority: false,
                 index: 0,
             }; OBJ_COUNT],
-            pallette_colors: PALETTE_COLORS,
+            palette_colors: PALETTE_COLORS,
             palette: [[0u8; RGB_SIZE]; PALETTE_SIZE],
             palette_obj_0: [[0u8; RGB_SIZE]; PALETTE_SIZE],
             palette_obj_1: [[0u8; RGB_SIZE]; PALETTE_SIZE],
@@ -518,7 +518,7 @@ impl Ppu {
                 for index in 0..PALETTE_SIZE {
                     let color_index: usize = (value as usize >> (index * 2)) & 3;
                     match color_index {
-                        0..=3 => self.palette[index] = self.pallette_colors[color_index],
+                        0..=3 => self.palette[index] = self.palette_colors[color_index],
                         color_index => panic!("Invalid palette color index {:04x}", color_index),
                     }
                 }
@@ -528,7 +528,7 @@ impl Ppu {
                 for index in 0..PALETTE_SIZE {
                     let color_index: usize = (value as usize >> (index * 2)) & 3;
                     match color_index {
-                        0..=3 => self.palette_obj_0[index] = self.pallette_colors[color_index],
+                        0..=3 => self.palette_obj_0[index] = self.palette_colors[color_index],
                         color_index => panic!("Invalid palette color index {:04x}", color_index),
                     }
                 }
@@ -538,7 +538,7 @@ impl Ppu {
                 for index in 0..PALETTE_SIZE {
                     let color_index: usize = (value as usize >> (index * 2)) & 3;
                     match color_index {
-                        0..=3 => self.palette_obj_1[index] = self.pallette_colors[color_index],
+                        0..=3 => self.palette_obj_1[index] = self.palette_colors[color_index],
                         color_index => panic!("Invalid palette color index {:04x}", color_index),
                     }
                 }
@@ -565,6 +565,10 @@ impl Ppu {
         &self.tiles
     }
 
+    pub fn set_palette_colors(&mut self, value: &Palette) {
+        self.palette_colors = *value;
+    }
+
     pub fn palette(&self) -> Palette {
         self.palette
     }
-- 
GitLab