From d870fd4f07477a63d82cb4b63a1681c5ea27febd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Fri, 4 Aug 2023 01:14:01 +0100 Subject: [PATCH] chore: better endian handling in frame buffer --- frontends/libretro/src/lib.rs | 8 ++--- src/gb.rs | 12 ++++++++ src/ppu.rs | 55 +++++++++++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/frontends/libretro/src/lib.rs b/frontends/libretro/src/lib.rs index 11af42c0..3343e8e5 100644 --- a/frontends/libretro/src/lib.rs +++ b/frontends/libretro/src/lib.rs @@ -6,7 +6,7 @@ use boytacean::{ debugln, gb::{AudioProvider, GameBoy}, pad::PadKey, - ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_XRGB8888_SIZE, XRGB8888_SIZE}, + ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_SIZE, XRGB8888_SIZE}, rom::Cartridge, }; use consts::{ @@ -28,7 +28,7 @@ use std::{ static mut EMULATOR: Option<GameBoy> = None; static mut KEY_STATES: Option<HashMap<RetroJoypad, bool>> = None; -static mut FRAME_BUFFER: [u8; FRAME_BUFFER_XRGB8888_SIZE] = [0x00; FRAME_BUFFER_XRGB8888_SIZE]; +static mut FRAME_BUFFER: [u32; FRAME_BUFFER_SIZE] = [0x00; FRAME_BUFFER_SIZE]; static mut PENDING_CYCLES: u32 = 0_u32; @@ -249,11 +249,11 @@ pub extern "C" fn retro_run() { // in case a new frame is available in the emulator // then the frame must be pushed into display if emulator.ppu_frame() != last_frame { - let frame_buffer = emulator.frame_buffer_xrgb8888(); + let frame_buffer = emulator.frame_buffer_xrgb8888_u32(); unsafe { FRAME_BUFFER.copy_from_slice(&frame_buffer); video_refresh_cb( - FRAME_BUFFER.as_ptr(), + FRAME_BUFFER.as_ptr() as *const u8, DISPLAY_WIDTH as u32, DISPLAY_HEIGHT as u32, DISPLAY_WIDTH * XRGB8888_SIZE, diff --git a/src/gb.rs b/src/gb.rs index 16f06677..45ab76ed 100644 --- a/src/gb.rs +++ b/src/gb.rs @@ -966,14 +966,26 @@ impl GameBoy { self.ppu().frame_buffer_xrgb8888() } + pub fn frame_buffer_xrgb8888_u32(&mut self) -> [u32; FRAME_BUFFER_SIZE] { + self.ppu().frame_buffer_xrgb8888_u32() + } + pub fn frame_buffer_rgb1555(&mut self) -> [u8; FRAME_BUFFER_RGB1555_SIZE] { self.ppu().frame_buffer_rgb1555() } + pub fn frame_buffer_rgb1555_u16(&mut self) -> [u16; FRAME_BUFFER_SIZE] { + self.ppu().frame_buffer_rgb1555_u16() + } + pub fn frame_buffer_rgb565(&mut self) -> [u8; FRAME_BUFFER_RGB565_SIZE] { self.ppu().frame_buffer_rgb565() } + pub fn frame_buffer_rgb565_u16(&mut self) -> [u16; FRAME_BUFFER_SIZE] { + self.ppu().frame_buffer_rgb565_u16() + } + pub fn audio_buffer(&mut self) -> &VecDeque<u8> { self.apu().audio_buffer() } diff --git a/src/ppu.rs b/src/ppu.rs index b79e97f2..6abf7199 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -939,6 +939,19 @@ impl Ppu { buffer } + pub fn frame_buffer_xrgb8888_u32(&self) -> [u32; FRAME_BUFFER_SIZE] { + let mut buffer = [0u32; FRAME_BUFFER_SIZE]; + for index in 0..DISPLAY_SIZE { + let (r, g, b) = ( + self.frame_buffer[index * RGB_SIZE], + self.frame_buffer[index * RGB_SIZE + 1], + self.frame_buffer[index * RGB_SIZE + 2], + ); + buffer[index] = ((r as u32) << 16) | ((g as u32) << 8) | b as u32; + } + buffer + } + pub fn frame_buffer_rgb1555(&self) -> [u8; FRAME_BUFFER_RGB1555_SIZE] { let mut buffer = [0u8; FRAME_BUFFER_RGB1555_SIZE]; for index in 0..DISPLAY_SIZE { @@ -954,6 +967,19 @@ impl Ppu { buffer } + pub fn frame_buffer_rgb1555_u16(&self) -> [u16; FRAME_BUFFER_SIZE] { + let mut buffer = [0u16; FRAME_BUFFER_SIZE]; + for index in 0..DISPLAY_SIZE { + let (r, g, b) = ( + self.frame_buffer[index * RGB_SIZE], + self.frame_buffer[index * RGB_SIZE + 1], + self.frame_buffer[index * RGB_SIZE + 2], + ); + buffer[index] = Self::rgb888_to_rgb1555_u16(r, g, b); + } + buffer + } + pub fn frame_buffer_rgb565(&self) -> [u8; FRAME_BUFFER_RGB565_SIZE] { let mut buffer = [0u8; FRAME_BUFFER_RGB565_SIZE]; for index in 0..DISPLAY_SIZE { @@ -969,6 +995,19 @@ impl Ppu { buffer } + pub fn frame_buffer_rgb565_u16(&self) -> [u16; FRAME_BUFFER_SIZE] { + let mut buffer = [0u16; FRAME_BUFFER_SIZE]; + for index in 0..DISPLAY_SIZE { + let (r, g, b) = ( + self.frame_buffer[index * RGB_SIZE], + self.frame_buffer[index * RGB_SIZE + 1], + self.frame_buffer[index * RGB_SIZE + 2], + ); + buffer[index] = Self::rgb888_to_rgb565_u16(r, g, b); + } + buffer + } + pub fn vram(&self) -> &[u8; VRAM_SIZE] { &self.vram } @@ -1784,22 +1823,28 @@ impl Ppu { } fn rgb888_to_rgb1555(first: u8, second: u8, third: u8) -> PixelRgb1555 { + let pixel = Self::rgb888_to_rgb1555_u16(first, second, third); + [pixel as u8, (pixel >> 8) as u8] + } + + fn rgb888_to_rgb1555_u16(first: u8, second: u8, third: u8) -> u16 { let r = (first as u16 >> 3) & 0x1f; let g = (second as u16 >> 3) & 0x1f; let b = (third as u16 >> 3) & 0x1f; let a = 1; + (a << 15) | (r << 10) | (g << 5) | b + } - let pixel = (a << 15) | (r << 10) | (g << 5) | b; + fn rgb888_to_rgb565(first: u8, second: u8, third: u8) -> PixelRgb565 { + let pixel = Self::rgb888_to_rgb565_u16(first, second, third); [pixel as u8, (pixel >> 8) as u8] } - fn rgb888_to_rgb565(first: u8, second: u8, third: u8) -> PixelRgb565 { + fn rgb888_to_rgb565_u16(first: u8, second: u8, third: u8) -> u16 { let r = (first as u16 >> 3) & 0x1f; let g = (second as u16 >> 2) & 0x3f; let b = (third as u16 >> 3) & 0x1f; - - let pixel = (r << 11) | (g << 5) | b; - [pixel as u8, (pixel >> 8) as u8] + (r << 11) | (g << 5) | b } } -- GitLab