Read actual register values
This commit is contained in:
		
							parent
							
								
									8707a5196b
								
							
						
					
					
						commit
						82c3104ab9
					
				| 
						 | 
					@ -15,8 +15,8 @@ use anyhow::Result;
 | 
				
			||||||
use egui_toast::{Toast, ToastKind, ToastOptions};
 | 
					use egui_toast::{Toast, ToastKind, ToastOptions};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{audio::Audio, graphics::TextureSink};
 | 
					use crate::{audio::Audio, graphics::TextureSink};
 | 
				
			||||||
pub use shrooms_vb_core::VBKey;
 | 
					 | 
				
			||||||
use shrooms_vb_core::{Sim, EXPECTED_FRAME_SIZE};
 | 
					use shrooms_vb_core::{Sim, EXPECTED_FRAME_SIZE};
 | 
				
			||||||
 | 
					pub use shrooms_vb_core::{VBKey, VBRegister};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod shrooms_vb_core;
 | 
					mod shrooms_vb_core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -390,6 +390,13 @@ impl Emulator {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            EmulatorCommand::ReadRegister(sim_id, register, done) => {
 | 
				
			||||||
 | 
					                let Some(sim) = self.sims.get_mut(sim_id.to_index()) else {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                let value = sim.read_register(register);
 | 
				
			||||||
 | 
					                let _ = done.send(value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            EmulatorCommand::SetAudioEnabled(p1, p2) => {
 | 
					            EmulatorCommand::SetAudioEnabled(p1, p2) => {
 | 
				
			||||||
                self.audio_on[SimId::Player1.to_index()].store(p1, Ordering::Release);
 | 
					                self.audio_on[SimId::Player1.to_index()].store(p1, Ordering::Release);
 | 
				
			||||||
                self.audio_on[SimId::Player2.to_index()].store(p2, Ordering::Release);
 | 
					                self.audio_on[SimId::Player2.to_index()].store(p2, Ordering::Release);
 | 
				
			||||||
| 
						 | 
					@ -447,6 +454,7 @@ pub enum EmulatorCommand {
 | 
				
			||||||
    StopSecondSim,
 | 
					    StopSecondSim,
 | 
				
			||||||
    Pause,
 | 
					    Pause,
 | 
				
			||||||
    Resume,
 | 
					    Resume,
 | 
				
			||||||
 | 
					    ReadRegister(SimId, VBRegister, oneshot::Sender<u32>),
 | 
				
			||||||
    SetAudioEnabled(bool, bool),
 | 
					    SetAudioEnabled(bool, bool),
 | 
				
			||||||
    Link,
 | 
					    Link,
 | 
				
			||||||
    Unlink,
 | 
					    Unlink,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,13 @@ bitflags! {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Copy, Debug)]
 | 
				
			||||||
 | 
					pub enum VBRegister {
 | 
				
			||||||
 | 
					    Program(u32),
 | 
				
			||||||
 | 
					    System(u32),
 | 
				
			||||||
 | 
					    PC,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type OnFrame = extern "C" fn(sim: *mut VB) -> c_int;
 | 
					type OnFrame = extern "C" fn(sim: *mut VB) -> c_int;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[link(name = "vb")]
 | 
					#[link(name = "vb")]
 | 
				
			||||||
| 
						 | 
					@ -77,6 +84,10 @@ extern "C" {
 | 
				
			||||||
        right_stride_x: c_int,
 | 
					        right_stride_x: c_int,
 | 
				
			||||||
        right_stride_y: c_int,
 | 
					        right_stride_y: c_int,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					    #[link_name = "vbGetProgramCounter"]
 | 
				
			||||||
 | 
					    fn vb_get_program_counter(sim: *mut VB) -> u32;
 | 
				
			||||||
 | 
					    #[link_name = "vbGetProgramRegister"]
 | 
				
			||||||
 | 
					    fn vb_get_program_register(sim: *mut VB, index: c_uint) -> i32;
 | 
				
			||||||
    #[link_name = "vbGetSamples"]
 | 
					    #[link_name = "vbGetSamples"]
 | 
				
			||||||
    fn vb_get_samples(
 | 
					    fn vb_get_samples(
 | 
				
			||||||
        sim: *mut VB,
 | 
					        sim: *mut VB,
 | 
				
			||||||
| 
						 | 
					@ -84,6 +95,8 @@ extern "C" {
 | 
				
			||||||
        capacity: *mut c_uint,
 | 
					        capacity: *mut c_uint,
 | 
				
			||||||
        position: *mut c_uint,
 | 
					        position: *mut c_uint,
 | 
				
			||||||
    ) -> *mut c_void;
 | 
					    ) -> *mut c_void;
 | 
				
			||||||
 | 
					    #[link_name = "vbGetSystemRegister"]
 | 
				
			||||||
 | 
					    fn vb_get_system_register(sim: *mut VB, index: c_uint) -> i32;
 | 
				
			||||||
    #[link_name = "vbGetUserData"]
 | 
					    #[link_name = "vbGetUserData"]
 | 
				
			||||||
    fn vb_get_user_data(sim: *mut VB) -> *mut c_void;
 | 
					    fn vb_get_user_data(sim: *mut VB) -> *mut c_void;
 | 
				
			||||||
    #[link_name = "vbInit"]
 | 
					    #[link_name = "vbInit"]
 | 
				
			||||||
| 
						 | 
					@ -291,6 +304,16 @@ impl Sim {
 | 
				
			||||||
    pub fn set_keys(&mut self, keys: VBKey) {
 | 
					    pub fn set_keys(&mut self, keys: VBKey) {
 | 
				
			||||||
        unsafe { vb_set_keys(self.sim, keys.bits()) };
 | 
					        unsafe { vb_set_keys(self.sim, keys.bits()) };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn read_register(&mut self, register: VBRegister) -> u32 {
 | 
				
			||||||
 | 
					        match register {
 | 
				
			||||||
 | 
					            VBRegister::Program(index) => unsafe {
 | 
				
			||||||
 | 
					                vb_get_program_register(self.sim, index) as u32
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            VBRegister::System(index) => unsafe { vb_get_system_register(self.sim, index) as u32 },
 | 
				
			||||||
 | 
					            VBRegister::PC => unsafe { vb_get_program_counter(self.sim) },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Drop for Sim {
 | 
					impl Drop for Sim {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -227,12 +227,23 @@ impl GdbConnection {
 | 
				
			||||||
                self.client.send_command(EmulatorCommand::Resume);
 | 
					                self.client.send_command(EmulatorCommand::Resume);
 | 
				
			||||||
                // Don't send a response until we hit a breakpoint or get interrupted
 | 
					                // Don't send a response until we hit a breakpoint or get interrupted
 | 
				
			||||||
            } else if req.match_str("p") {
 | 
					            } else if req.match_str("p") {
 | 
				
			||||||
                let Some(register) = req.match_hex::<u32>() else {
 | 
					                let mut read_register = || {
 | 
				
			||||||
 | 
					                    let register_index = req.match_hex::<usize>()?;
 | 
				
			||||||
 | 
					                    let register = REGISTERS.get(register_index)?.to_vb_register();
 | 
				
			||||||
 | 
					                    let (tx, rx) = ::oneshot::channel();
 | 
				
			||||||
 | 
					                    self.client.send_command(EmulatorCommand::ReadRegister(
 | 
				
			||||||
 | 
					                        self.sim_id,
 | 
				
			||||||
 | 
					                        register,
 | 
				
			||||||
 | 
					                        tx,
 | 
				
			||||||
 | 
					                    ));
 | 
				
			||||||
 | 
					                    rx.recv().ok()
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                let Some(value) = read_register() else {
 | 
				
			||||||
                    let res = self.response();
 | 
					                    let res = self.response();
 | 
				
			||||||
                    self.send(res).await?;
 | 
					                    self.send(res).await?;
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                let res = self.response().write_hex(register);
 | 
					                let res = self.response().write_hex(value);
 | 
				
			||||||
                self.send(res).await?;
 | 
					                self.send(res).await?;
 | 
				
			||||||
            } else if req.match_str("m") {
 | 
					            } else if req.match_str("m") {
 | 
				
			||||||
                let mut read_params = || {
 | 
					                let mut read_params = || {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
 | 
					use crate::emulator::VBRegister;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct RegisterInfo {
 | 
					pub struct RegisterInfo {
 | 
				
			||||||
    index: usize,
 | 
					    dwarf: u32,
 | 
				
			||||||
    name: &'static str,
 | 
					    name: &'static str,
 | 
				
			||||||
    set: &'static str,
 | 
					    set: &'static str,
 | 
				
			||||||
    alt_name: Option<&'static str>,
 | 
					    alt_name: Option<&'static str>,
 | 
				
			||||||
| 
						 | 
					@ -14,48 +16,59 @@ impl RegisterInfo {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        string.push_str(&format!(
 | 
					        string.push_str(&format!(
 | 
				
			||||||
            ";bitsize:32;offset:{};encoding:uint;format:hex;set:{};dwarf:{}",
 | 
					            ";bitsize:32;offset:{};encoding:uint;format:hex;set:{};dwarf:{}",
 | 
				
			||||||
            self.index * 4,
 | 
					            self.dwarf * 4,
 | 
				
			||||||
            self.set,
 | 
					            self.set,
 | 
				
			||||||
            self.index
 | 
					            self.dwarf
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
        if let Some(generic) = self.generic {
 | 
					        if let Some(generic) = self.generic {
 | 
				
			||||||
            string.push_str(&format!(";generic:{}", generic));
 | 
					            string.push_str(&format!(";generic:{}", generic));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        string
 | 
					        string
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn to_vb_register(&self) -> VBRegister {
 | 
				
			||||||
 | 
					        match self.dwarf {
 | 
				
			||||||
 | 
					            0..32 => VBRegister::Program(self.dwarf),
 | 
				
			||||||
 | 
					            32..40 => VBRegister::System(self.dwarf - 32),
 | 
				
			||||||
 | 
					            40..42 => VBRegister::System(self.dwarf - 16),
 | 
				
			||||||
 | 
					            42..45 => VBRegister::System(self.dwarf - 13),
 | 
				
			||||||
 | 
					            45 => VBRegister::PC,
 | 
				
			||||||
 | 
					            other => panic!("unexpected DWARF register {other}"),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro_rules! register {
 | 
					macro_rules! register {
 | 
				
			||||||
    ($set:expr, $index:expr, $name:expr) => {
 | 
					    ($set:expr, $dwarf:expr, $name:expr) => {
 | 
				
			||||||
        RegisterInfo {
 | 
					        RegisterInfo {
 | 
				
			||||||
            index: $index,
 | 
					            dwarf: $dwarf,
 | 
				
			||||||
            name: $name,
 | 
					            name: $name,
 | 
				
			||||||
            set: $set,
 | 
					            set: $set,
 | 
				
			||||||
            alt_name: None,
 | 
					            alt_name: None,
 | 
				
			||||||
            generic: None,
 | 
					            generic: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ($set:expr, $index:expr, $name:expr, alt: $alt:expr) => {
 | 
					    ($set:expr, $dwarf:expr, $name:expr, alt: $alt:expr) => {
 | 
				
			||||||
        RegisterInfo {
 | 
					        RegisterInfo {
 | 
				
			||||||
            index: $index,
 | 
					            dwarf: $dwarf,
 | 
				
			||||||
            name: $name,
 | 
					            name: $name,
 | 
				
			||||||
            set: $set,
 | 
					            set: $set,
 | 
				
			||||||
            alt_name: Some($alt),
 | 
					            alt_name: Some($alt),
 | 
				
			||||||
            generic: None,
 | 
					            generic: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ($set:expr, $index:expr, $name:expr, generic: $generic:expr) => {
 | 
					    ($set:expr, $dwarf:expr, $name:expr, generic: $generic:expr) => {
 | 
				
			||||||
        RegisterInfo {
 | 
					        RegisterInfo {
 | 
				
			||||||
            index: $index,
 | 
					            dwarf: $dwarf,
 | 
				
			||||||
            name: $name,
 | 
					            name: $name,
 | 
				
			||||||
            set: $set,
 | 
					            set: $set,
 | 
				
			||||||
            alt_name: None,
 | 
					            alt_name: None,
 | 
				
			||||||
            generic: Some($generic),
 | 
					            generic: Some($generic),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ($set:expr, $index:expr, $name:expr, alt: $alt:expr, generic: $generic:expr) => {
 | 
					    ($set:expr, $dwarf:expr, $name:expr, alt: $alt:expr, generic: $generic:expr) => {
 | 
				
			||||||
        RegisterInfo {
 | 
					        RegisterInfo {
 | 
				
			||||||
            index: $index,
 | 
					            dwarf: $dwarf,
 | 
				
			||||||
            name: $name,
 | 
					            name: $name,
 | 
				
			||||||
            set: $set,
 | 
					            set: $set,
 | 
				
			||||||
            alt_name: Some($alt),
 | 
					            alt_name: Some($alt),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue