Skip to content
Snippets Groups Projects
Verified Commit cb0b2456 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

chore: rgb565 support for libretro

parent ee1e04f6
No related branches found
No related tags found
No related merge requests found
Pipeline #3170 passed
......@@ -6,16 +6,17 @@ use boytacean::{
debugln,
gb::{AudioProvider, GameBoy},
pad::PadKey,
ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_RGB155_SIZE, RGB1555_SIZE},
ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_RGB565_SIZE, RGB565_SIZE},
rom::Cartridge,
};
use consts::{
RETRO_DEVICE_ID_JOYPAD_A, RETRO_DEVICE_ID_JOYPAD_B, RETRO_DEVICE_ID_JOYPAD_DOWN,
RETRO_DEVICE_ID_JOYPAD_L, RETRO_DEVICE_ID_JOYPAD_L2, RETRO_DEVICE_ID_JOYPAD_L3,
RETRO_DEVICE_ID_JOYPAD_LEFT, RETRO_DEVICE_ID_JOYPAD_R, RETRO_DEVICE_ID_JOYPAD_R2,
RETRO_DEVICE_ID_JOYPAD_R3, RETRO_DEVICE_ID_JOYPAD_RIGHT, RETRO_DEVICE_ID_JOYPAD_SELECT,
RETRO_DEVICE_ID_JOYPAD_START, RETRO_DEVICE_ID_JOYPAD_UP, RETRO_DEVICE_ID_JOYPAD_X,
RETRO_DEVICE_ID_JOYPAD_Y, RETRO_DEVICE_JOYPAD,
REGION_NTSC, RETRO_API_VERSION, RETRO_DEVICE_ID_JOYPAD_A, RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_DOWN, RETRO_DEVICE_ID_JOYPAD_L, RETRO_DEVICE_ID_JOYPAD_L2,
RETRO_DEVICE_ID_JOYPAD_L3, RETRO_DEVICE_ID_JOYPAD_LEFT, RETRO_DEVICE_ID_JOYPAD_R,
RETRO_DEVICE_ID_JOYPAD_R2, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_DEVICE_ID_JOYPAD_RIGHT,
RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_START, RETRO_DEVICE_ID_JOYPAD_UP,
RETRO_DEVICE_ID_JOYPAD_X, RETRO_DEVICE_ID_JOYPAD_Y, RETRO_DEVICE_JOYPAD,
RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, RETRO_PIXEL_FORMAT_RGB565,
};
use std::{
collections::HashMap,
......@@ -25,11 +26,9 @@ use std::{
slice::from_raw_parts,
};
use crate::consts::{REGION_NTSC, RETRO_API_VERSION};
static mut EMULATOR: Option<GameBoy> = None;
static mut KEY_STATES: Option<HashMap<RetroJoypad, bool>> = None;
static mut FRAME_BUFFER: [u8; FRAME_BUFFER_RGB155_SIZE] = [0x00; FRAME_BUFFER_RGB155_SIZE];
static mut FRAME_BUFFER: [u8; FRAME_BUFFER_RGB565_SIZE] = [0x00; FRAME_BUFFER_RGB565_SIZE];
static mut AUDIO_BUFFER: Option<Vec<i16>> = None;
static mut PENDING_CYCLES: u32 = 0_u32;
......@@ -198,6 +197,12 @@ pub unsafe extern "C" fn retro_get_system_av_info(info: *mut RetroSystemAvInfo)
(*info).geometry.aspect_ratio = DISPLAY_WIDTH as f32 / DISPLAY_HEIGHT as f32;
(*info).timing.fps = GameBoy::VISUAL_FREQ as f64;
(*info).timing.sample_rate = EMULATOR.as_ref().unwrap().audio_sampling_rate() as f64;
let environment_cb = unsafe { ENVIRONMENT_CALLBACK.as_ref().unwrap() };
environment_cb(
RETRO_ENVIRONMENT_SET_PIXEL_FORMAT,
&RETRO_PIXEL_FORMAT_RGB565 as *const _ as *const c_void,
);
}
#[no_mangle]
......@@ -249,14 +254,14 @@ 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_rgb1555();
let frame_buffer = emulator.frame_buffer_rgb565();
unsafe {
FRAME_BUFFER.copy_from_slice(&frame_buffer);
video_refresh_cb(
FRAME_BUFFER.as_ptr(),
DISPLAY_WIDTH as u32,
DISPLAY_HEIGHT as u32,
DISPLAY_WIDTH * RGB1555_SIZE,
DISPLAY_WIDTH * RGB565_SIZE,
);
}
......
......@@ -16,8 +16,8 @@ use crate::{
mmu::Mmu,
pad::{Pad, PadKey},
ppu::{
Ppu, PpuMode, Tile, DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_RGB155_SIZE,
FRAME_BUFFER_SIZE,
Ppu, PpuMode, Tile, DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_RGB1555_SIZE,
FRAME_BUFFER_RGB565_SIZE, FRAME_BUFFER_SIZE,
},
rom::{Cartridge, RamSize},
serial::{NullDevice, Serial, SerialDevice},
......@@ -962,10 +962,14 @@ impl GameBoy {
&(self.ppu().frame_buffer)
}
pub fn frame_buffer_rgb1555(&mut self) -> [u8; FRAME_BUFFER_RGB155_SIZE] {
pub fn frame_buffer_rgb1555(&mut self) -> [u8; FRAME_BUFFER_RGB1555_SIZE] {
self.ppu().frame_buffer_rgb1555()
}
pub fn frame_buffer_rgb565(&mut self) -> [u8; FRAME_BUFFER_RGB565_SIZE] {
self.ppu().frame_buffer_rgb565()
}
pub fn audio_buffer(&mut self) -> &VecDeque<u8> {
self.apu().audio_buffer()
}
......
......@@ -24,6 +24,7 @@ pub const PALETTE_SIZE: usize = 4;
pub const RGB_SIZE: usize = 3;
pub const RGBA_SIZE: usize = 4;
pub const RGB1555_SIZE: usize = 2;
pub const RGB565_SIZE: usize = 2;
pub const TILE_WIDTH: usize = 8;
pub const TILE_HEIGHT: usize = 8;
pub const TILE_WIDTH_I: usize = 7;
......@@ -59,7 +60,10 @@ pub const COLOR_BUFFER_SIZE: usize = DISPLAY_SIZE;
pub const FRAME_BUFFER_SIZE: usize = DISPLAY_SIZE * RGB_SIZE;
/// The size of the RGB1555 frame buffer in bytes.
pub const FRAME_BUFFER_RGB155_SIZE: usize = DISPLAY_SIZE * RGB1555_SIZE;
pub const FRAME_BUFFER_RGB1555_SIZE: usize = DISPLAY_SIZE * RGB1555_SIZE;
/// The size of the RGB565 frame buffer in bytes.
pub const FRAME_BUFFER_RGB565_SIZE: usize = DISPLAY_SIZE * RGB565_SIZE;
/// The base colors to be used to populate the
/// custom palettes of the Game Boy.
......@@ -85,6 +89,10 @@ pub type PixelAlpha = [u8; RGBA_SIZE];
/// bit at the beginning.
pub type PixelRgb1555 = [u8; RGB1555_SIZE];
/// Defines a pixel with 5 bits per channel except for the
/// green channel which uses 6 bits.
pub type PixelRgb565 = [u8; RGB565_SIZE];
/// Defines a type that represents a color palette
/// within the Game Boy context.
pub type Palette = [Pixel; PALETTE_SIZE];
......@@ -907,8 +915,8 @@ impl Ppu {
}
}
pub fn frame_buffer_rgb1555(&self) -> [u8; FRAME_BUFFER_RGB155_SIZE] {
let mut buffer = [0u8; FRAME_BUFFER_RGB155_SIZE];
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 {
let (r, g, b) = (
self.frame_buffer[index * 3],
......@@ -922,6 +930,21 @@ impl Ppu {
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 {
let (r, g, b) = (
self.frame_buffer[index * 3],
self.frame_buffer[index * 3 + 1],
self.frame_buffer[index * 3 + 2],
);
let rgb565 = Self::rgb888_to_rgb565(r, g, b);
buffer[index * 2] = rgb565[0];
buffer[index * 2 + 1] = rgb565[1];
}
buffer
}
pub fn vram(&self) -> &[u8; VRAM_SIZE] {
&self.vram
}
......@@ -1745,6 +1768,15 @@ impl Ppu {
let pixel = (a << 15) | (r << 10) | (g << 5) | b;
[pixel as u8, (pixel >> 8) as u8]
}
fn rgb888_to_rgb565(first: u8, second: u8, third: u8) -> PixelRgb565 {
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]
}
}
impl Default for Ppu {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment