Compare commits

...

2 commits

Author SHA1 Message Date
de2cfc07ae make rfb handle disconnected pitch better
meh, it works. I really should probably do this in Frontend, but that would be another conversion step. idk
2024-08-05 01:04:21 -04:00
5944c5c1cb do init after load_game (mednafen boots now) 2024-08-05 00:37:29 -04:00
4 changed files with 47 additions and 13 deletions

View file

@ -24,7 +24,7 @@ pub(crate) static mut FRONTEND: *mut Frontend = std::ptr::null_mut();
/// Interface for the frontend to call to user code. /// Interface for the frontend to call to user code.
pub trait FrontendInterface { pub trait FrontendInterface {
/// Called when video is updated. /// Called when video is updated.
fn video_update(&mut self, slice: &[u32]); fn video_update(&mut self, slice: &[u32], pitch: u32);
/// Called when resize occurs. /// Called when resize occurs.
fn video_resize(&mut self, width: u32, height: u32); fn video_resize(&mut self, width: u32, height: u32);

View file

@ -202,7 +202,7 @@ pub(crate) unsafe extern "C" fn video_refresh_callback(
.resize((pitch * height as usize) as usize, 0); .resize((pitch * height as usize) as usize, 0);
// some cores are stupid // some cores are stupid
(*(*FRONTEND).interface).video_resize(pitch as u32, height); (*(*FRONTEND).interface).video_resize(width, height);
} }
// TODO: Make this convert from weird pitches to native resolution where possible. // TODO: Make this convert from weird pitches to native resolution where possible.
@ -217,7 +217,7 @@ pub(crate) unsafe extern "C" fn video_refresh_callback(
} }
} }
(*(*FRONTEND).interface).video_update(&(*FRONTEND).converted_pixel_buffer[..]); (*(*FRONTEND).interface).video_update(&(*FRONTEND).converted_pixel_buffer[..], pitch as u32);
} }
_ => { _ => {
let pixel_data_slice = std::slice::from_raw_parts( let pixel_data_slice = std::slice::from_raw_parts(
@ -225,7 +225,7 @@ pub(crate) unsafe extern "C" fn video_refresh_callback(
(pitch * height as usize) as usize, (pitch * height as usize) as usize,
); );
(*(*FRONTEND).interface).video_update(&pixel_data_slice); (*(*FRONTEND).interface).video_update(&pixel_data_slice, pitch as u32);
} }
} }
} }

View file

@ -104,10 +104,10 @@ impl FrontendInterface for App {
self.rfb_server.resize(width as u16, height as u16); self.rfb_server.resize(width as u16, height as u16);
} }
fn video_update(&mut self, slice: &[u32]) { fn video_update(&mut self, slice: &[u32], pitch: u32) {
let framebuffer_size = self.get_frontend().get_size(); //let framebuffer_size = self.get_frontend().get_size();
self.rfb_server self.rfb_server
.update_buffer(&slice, framebuffer_size.0 as u16, framebuffer_size.1 as u16); .update_buffer(&slice, pitch);
} }
fn audio_sample(&mut self, _slice: &[i16], _size: usize) {} fn audio_sample(&mut self, _slice: &[i16], _size: usize) {}
@ -170,12 +170,13 @@ fn main() -> Result<()> {
app.load_core(core_path)?; app.load_core(core_path)?;
// Initalize app
app.init();
if let Some(rom_path) = matches.get_one::<String>("rom") { if let Some(rom_path) = matches.get_one::<String>("rom") {
app.load_game(rom_path)? app.load_game(rom_path)?
} }
// Initalize app
app.init();
app.main_loop(); app.main_loop();
} }

View file

@ -18,6 +18,9 @@ pub struct RfbServer {
// This follows the same format as libretro joypad buttons. // This follows the same format as libretro joypad buttons.
buttons: [bool; 32], buttons: [bool; 32],
width: u16,
height: u16
} }
impl RfbServer { impl RfbServer {
@ -53,6 +56,8 @@ impl RfbServer {
ptr: NonNull::new_unchecked(screen), ptr: NonNull::new_unchecked(screen),
framebuffer: Vec::new(), framebuffer: Vec::new(),
buttons: [false; 32], buttons: [false; 32],
width: config.width,
height: config.height
}); });
// Disable the normal libvnc cursor (it's annoying) // Disable the normal libvnc cursor (it's annoying)
@ -76,6 +81,9 @@ impl RfbServer {
pub fn resize(&mut self, w: u16, h: u16) { pub fn resize(&mut self, w: u16, h: u16) {
let len = (w as usize) * (h as usize); let len = (w as usize) * (h as usize);
self.width = w;
self.height = h;
self.framebuffer.resize(len, 0); self.framebuffer.resize(len, 0);
unsafe { unsafe {
@ -91,16 +99,41 @@ impl RfbServer {
} }
} }
pub fn update_buffer(&mut self, slice: &[u32], width: u16, height: u16) { pub fn update_buffer(&mut self, slice: &[u32], pitch: u32) {
self.framebuffer.copy_from_slice(&slice);
//self.framebuffer.copy_from_slice(&slice);
let has_disconnected_pitch = pitch != self.width as u32;
#[cfg(debug)]
if has_disconnected_pitch {
info!("DEBUG: Pitch is not the same as width {}, {}", pitch, self.width);
}
// copy a line at a time (test)
for y in 0..self.height {
let src_line_off = (y as u32 * pitch) as usize;
let mut dest_line_off = src_line_off;
// copy only
if has_disconnected_pitch {
dest_line_off = (y * self.width) as usize;
}
// Create slices repressenting each part
let src_slice = &slice[src_line_off..src_line_off + self.width as usize];
let dest_slice = &mut self.framebuffer[dest_line_off..dest_line_off + self.width as usize];
dest_slice.copy_from_slice(src_slice);
}
unsafe { unsafe {
rfb::bindings::rfbMarkRectAsModified( rfb::bindings::rfbMarkRectAsModified(
self.ptr.as_ptr(), self.ptr.as_ptr(),
0, 0,
0, 0,
width as i32, self.width as i32,
height as i32, self.height as i32,
); );
} }
} }