Gdb fixes
Former-commit-id: 2940580fc6b3760d77b5598b0faf72a773183304 Former-commit-id: cf3f361178c75d4e39832774bdd052ef8aab6be8
This commit is contained in:
parent
3bb480c120
commit
c8c1cdd57b
|
@ -1,11 +1,18 @@
|
|||
use std::fmt;
|
||||
|
||||
use log::debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use bit::BitIndex;
|
||||
use num::FromPrimitive;
|
||||
use ansi_term::{Colour, Style};
|
||||
|
||||
use rustboyadvance_utils::{Shared, WeakPointer};
|
||||
|
||||
pub use super::exception::Exception;
|
||||
use super::reg_string;
|
||||
|
||||
use super::{arm::ArmCond, psr::RegPSR, Addr, CpuMode, CpuState};
|
||||
|
||||
use rustboyadvance_utils::{Shared, WeakPointer};
|
||||
|
||||
use super::memory::{MemoryAccess, MemoryInterface};
|
||||
use MemoryAccess::*;
|
||||
|
@ -37,18 +44,12 @@ cfg_if! {
|
|||
use super::DecodedInstruction;
|
||||
use super::arm::ArmInstruction;
|
||||
use super::thumb::ThumbInstruction;
|
||||
use super::reg_string;
|
||||
use std::fmt;
|
||||
|
||||
use ansi_term::{Colour, Style};
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
use bit::BitIndex;
|
||||
use num::FromPrimitive;
|
||||
|
||||
pub enum CpuAction {
|
||||
AdvancePC(MemoryAccess),
|
||||
PipelineFlushed,
|
||||
|
@ -104,7 +105,7 @@ impl Default for DebuggerState {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct Arm7tdmiCore<I: MemoryInterface> {
|
||||
pub pc: u32,
|
||||
pub bus: Shared<I>,
|
||||
|
@ -506,6 +507,29 @@ impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: MemoryInterface> fmt::Debug for Arm7tdmiCore<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "ARM7TDMI Core Status:")?;
|
||||
writeln!(f, "\tCPSR: {}", self.cpsr)?;
|
||||
writeln!(f, "\tGeneral Purpose Registers:")?;
|
||||
let reg_normal_style = Style::new().bold();
|
||||
let gpr = self.copy_registers();
|
||||
for i in 0..15 {
|
||||
let mut reg_name = reg_string(i).to_string();
|
||||
reg_name.make_ascii_uppercase();
|
||||
let entry = format!("\t{:-3} = 0x{:08x}", reg_name, gpr[i]);
|
||||
write!(
|
||||
f,
|
||||
"{}{}",
|
||||
reg_normal_style.paint(entry),
|
||||
if (i + 1) % 4 == 0 { "\n" } else { "" }
|
||||
)?;
|
||||
}
|
||||
let pc = format!("\tPC = 0x{:08x}", self.get_next_pc());
|
||||
writeln!(f, "{}", reg_normal_style.paint(pc))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "debugger")]
|
||||
impl<I: MemoryInterface> fmt::Display for Core<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
|
@ -41,7 +41,7 @@ impl<I: MemoryGdbInterface> SingleThreadBase for Arm7tdmiCore<I> {
|
|||
&mut self,
|
||||
regs: &mut gdbstub_arch::arm::reg::ArmCoreRegs,
|
||||
) -> TargetResult<(), Self> {
|
||||
regs.pc = self.get_next_pc();
|
||||
regs.pc = self.pc;
|
||||
regs.lr = self.get_reg(REG_LR);
|
||||
regs.sp = self.get_reg(REG_SP);
|
||||
regs.r[..].copy_from_slice(&self.gpr[..13]);
|
||||
|
@ -56,7 +56,7 @@ impl<I: MemoryGdbInterface> SingleThreadBase for Arm7tdmiCore<I> {
|
|||
self.set_reg(REG_PC, regs.pc);
|
||||
self.set_reg(REG_LR, regs.lr);
|
||||
self.set_reg(REG_SP, regs.sp);
|
||||
self.gpr.copy_from_slice(®s.r);
|
||||
self.gpr[..13].copy_from_slice(®s.r);
|
||||
self.cpsr.set(regs.cpsr);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use arm7tdmi::gdbstub::stub::SingleThreadStopReason;
|
|||
use bincode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::gdb_support::{gdb_thread::start_gdb_server_thread, DebuggerState};
|
||||
use crate::gdb_support::{gdb_thread::start_gdb_server_thread, DebuggerRequestHandler};
|
||||
|
||||
use super::cartridge::Cartridge;
|
||||
use super::dma::DmaController;
|
||||
|
@ -24,13 +24,13 @@ use arm7tdmi::{self, Arm7tdmiCore};
|
|||
use rustboyadvance_utils::Shared;
|
||||
|
||||
pub struct GameBoyAdvance {
|
||||
pub(crate) cpu: Box<Arm7tdmiCore<SysBus>>,
|
||||
pub cpu: Box<Arm7tdmiCore<SysBus>>,
|
||||
pub(crate) sysbus: Shared<SysBus>,
|
||||
pub(crate) io_devs: Shared<IoDevices>,
|
||||
pub(crate) scheduler: SharedScheduler,
|
||||
interrupt_flags: SharedInterruptFlags,
|
||||
audio_interface: DynAudioInterface,
|
||||
pub(crate) debugger: Option<DebuggerState>,
|
||||
pub(crate) debugger: Option<DebuggerRequestHandler>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -251,17 +251,12 @@ impl GameBoyAdvance {
|
|||
|
||||
/// Recv & handle messages from the debugger, and return if we are stopped or not
|
||||
pub fn debugger_run(&mut self) {
|
||||
let mut should_stop = false;
|
||||
let mut should_interrupt_frame = false;
|
||||
let debugger = self.debugger.take().expect("debugger should be None here");
|
||||
let debugger = debugger
|
||||
.handle_message(self, &mut should_stop)
|
||||
.map_err(|_| "Failed to handle message")
|
||||
.unwrap();
|
||||
|
||||
self.debugger = debugger;
|
||||
self.debugger = debugger.handle_incoming_requests(self, &mut should_interrupt_frame);
|
||||
|
||||
if let Some(debugger) = &mut self.debugger {
|
||||
if should_stop {
|
||||
if should_interrupt_frame {
|
||||
debugger.notify_stop_reason(SingleThreadStopReason::DoneStep);
|
||||
} else {
|
||||
self.frame_interruptible();
|
||||
|
@ -277,7 +272,7 @@ impl GameBoyAdvance {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cpu_step(&mut self) {
|
||||
pub(crate) fn cpu_step(&mut self) {
|
||||
if self.io_devs.intc.irq_pending() {
|
||||
self.cpu.irq();
|
||||
self.io_devs.haltcnt = HaltState::Running;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use std::result;
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
type SendSync<T> = Arc<Mutex<T>>;
|
||||
|
||||
use arm7tdmi::gdbstub::common::Signal;
|
||||
use arm7tdmi::gdbstub::stub::{DisconnectReason, SingleThreadStopReason};
|
||||
use arm7tdmi::gdbstub::target::TargetError;
|
||||
use arm7tdmi::gdbstub::target::{ext::base::singlethread::SingleThreadBase, Target};
|
||||
|
@ -20,7 +20,7 @@ mod target;
|
|||
use crate::GameBoyAdvance;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum DebuggerMessage {
|
||||
pub(crate) enum DebuggerRequest {
|
||||
ReadRegs(SendSync<ArmCoreRegs>),
|
||||
WriteRegs(ArmCoreRegs),
|
||||
ReadAddrs(Addr, SendSync<Box<[u8]>>),
|
||||
|
@ -28,15 +28,15 @@ pub(crate) enum DebuggerMessage {
|
|||
WriteAddrs(Addr, Box<[u8]>),
|
||||
AddSwBreakpoint(Addr),
|
||||
DelSwBreakpoint(Addr),
|
||||
Stop,
|
||||
Interrupt,
|
||||
Resume,
|
||||
SingleStep,
|
||||
Disconnected(DisconnectReason),
|
||||
}
|
||||
|
||||
pub struct DebuggerTarget {
|
||||
tx: Sender<DebuggerMessage>,
|
||||
operation_signal: Arc<(Mutex<bool>, Condvar)>,
|
||||
tx: Sender<DebuggerRequest>,
|
||||
request_complete_signal: Arc<(Mutex<bool>, Condvar)>,
|
||||
stop_signal: Arc<(Mutex<SingleThreadStopReason<u32>>, Condvar)>,
|
||||
memory_map: String,
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ pub struct DebuggerTarget {
|
|||
impl DebuggerTarget {
|
||||
#[inline]
|
||||
pub fn wait_for_operation(&mut self) {
|
||||
let (lock, cvar) = &*self.operation_signal;
|
||||
let (lock, cvar) = &*self.request_complete_signal;
|
||||
let mut finished = lock.lock().unwrap();
|
||||
while !*finished {
|
||||
finished = cvar.wait(finished).unwrap();
|
||||
|
@ -53,39 +53,39 @@ impl DebuggerTarget {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct DebuggerState {
|
||||
rx: Receiver<DebuggerMessage>,
|
||||
operation_signal: Arc<(Mutex<bool>, Condvar)>,
|
||||
pub(crate) struct DebuggerRequestHandler {
|
||||
rx: Receiver<DebuggerRequest>,
|
||||
request_complete_signal: Arc<(Mutex<bool>, Condvar)>,
|
||||
stop_signal: Arc<(Mutex<SingleThreadStopReason<u32>>, Condvar)>,
|
||||
thread: JoinHandle<()>,
|
||||
stopped: bool,
|
||||
}
|
||||
|
||||
impl DebuggerState {
|
||||
pub fn handle_message(
|
||||
mut self,
|
||||
gba: &mut GameBoyAdvance,
|
||||
should_stop: &mut bool,
|
||||
) -> Result<Option<DebuggerState>, TargetError<<DebuggerTarget as Target>::Error>> {
|
||||
if self.thread.is_finished() {
|
||||
warn!("gdb server thread unexpectdly died");
|
||||
*should_stop = true;
|
||||
self.thread.join().unwrap();
|
||||
return Ok(None);
|
||||
enum DebuggerStatus {
|
||||
RequestComplete,
|
||||
ResumeRequested,
|
||||
StopRequested,
|
||||
Disconnected(DisconnectReason),
|
||||
}
|
||||
if let Ok(msg) = self.rx.try_recv() {
|
||||
use DebuggerMessage::*;
|
||||
let mut result = match msg {
|
||||
|
||||
impl DebuggerRequestHandler {
|
||||
fn handle_request(
|
||||
&mut self,
|
||||
gba: &mut GameBoyAdvance,
|
||||
req: &mut DebuggerRequest,
|
||||
) -> Result<DebuggerStatus, TargetError<<DebuggerTarget as Target>::Error>> {
|
||||
use DebuggerRequest::*;
|
||||
match req {
|
||||
ReadRegs(regs) => {
|
||||
let mut regs = regs.lock().unwrap();
|
||||
gba.cpu.read_registers(&mut regs)?;
|
||||
debug!("Debugger requested to read regs: {:?}", regs);
|
||||
Ok(Some(self))
|
||||
Ok(DebuggerStatus::RequestComplete)
|
||||
}
|
||||
WriteRegs(regs) => {
|
||||
debug!("Debugger requested to write regs: {:?}", regs);
|
||||
gba.cpu.write_registers(®s)?;
|
||||
Ok(Some(self))
|
||||
gba.cpu.write_registers(regs)?;
|
||||
Ok(DebuggerStatus::RequestComplete)
|
||||
}
|
||||
ReadAddrs(addr, data) => {
|
||||
let mut data = data.lock().unwrap();
|
||||
|
@ -94,8 +94,8 @@ impl DebuggerState {
|
|||
data.len(),
|
||||
addr
|
||||
);
|
||||
gba.cpu.read_addrs(addr, &mut data)?;
|
||||
Ok(Some(self))
|
||||
gba.cpu.read_addrs(*addr, &mut data)?;
|
||||
Ok(DebuggerStatus::RequestComplete)
|
||||
}
|
||||
WriteAddrs(addr, data) => {
|
||||
debug!(
|
||||
|
@ -103,55 +103,89 @@ impl DebuggerState {
|
|||
data.len(),
|
||||
addr
|
||||
);
|
||||
gba.cpu.write_addrs(addr, &data)?;
|
||||
Ok(Some(self))
|
||||
gba.cpu.write_addrs(*addr, &data)?;
|
||||
Ok(DebuggerStatus::RequestComplete)
|
||||
}
|
||||
Stop => {
|
||||
Interrupt => {
|
||||
debug!("Debugger requested stopped");
|
||||
self.stopped = true;
|
||||
Ok(Some(self))
|
||||
self.notify_stop_reason(SingleThreadStopReason::Signal(Signal::SIGINT));
|
||||
Ok(DebuggerStatus::StopRequested)
|
||||
}
|
||||
Resume => {
|
||||
debug!("Debugger requested resume");
|
||||
self.stopped = false;
|
||||
Ok(Some(self))
|
||||
Ok(DebuggerStatus::ResumeRequested)
|
||||
}
|
||||
SingleStep => {
|
||||
debug!("Debugger requested single step");
|
||||
gba.run::<true>(1);
|
||||
self.notify_stop_reason(SingleThreadStopReason::DoneStep);
|
||||
self.stopped = true;
|
||||
Ok(Some(self))
|
||||
gba.cpu_step();
|
||||
let stop_reason = SingleThreadStopReason::DoneStep;
|
||||
self.notify_stop_reason(stop_reason);
|
||||
Ok(DebuggerStatus::StopRequested)
|
||||
}
|
||||
AddSwBreakpoint(addr) => {
|
||||
gba.cpu.add_breakpoint(addr);
|
||||
Ok(Some(self))
|
||||
gba.cpu.add_breakpoint(*addr);
|
||||
Ok(DebuggerStatus::RequestComplete)
|
||||
}
|
||||
DelSwBreakpoint(addr) => {
|
||||
gba.cpu.del_breakpoint(addr);
|
||||
Ok(Some(self))
|
||||
gba.cpu.del_breakpoint(*addr);
|
||||
Ok(DebuggerStatus::RequestComplete)
|
||||
}
|
||||
Disconnected(reason) => {
|
||||
Disconnected(reason) => Ok(DebuggerStatus::Disconnected(*reason)),
|
||||
}
|
||||
}
|
||||
|
||||
fn terminate(mut self, should_interrupt_frame: &mut bool) -> Option<DebuggerRequestHandler> {
|
||||
self.notify_stop_reason(SingleThreadStopReason::Exited(1));
|
||||
self.thread.join().unwrap();
|
||||
self.stopped = true;
|
||||
*should_interrupt_frame = true;
|
||||
None
|
||||
}
|
||||
|
||||
pub fn handle_incoming_requests(
|
||||
mut self,
|
||||
gba: &mut GameBoyAdvance,
|
||||
should_interrupt_frame: &mut bool,
|
||||
) -> Option<DebuggerRequestHandler> {
|
||||
if self.thread.is_finished() {
|
||||
warn!("gdb server thread unexpectdly died");
|
||||
return self.terminate(should_interrupt_frame);
|
||||
}
|
||||
while let Ok(mut req) = self.rx.try_recv() {
|
||||
match self.handle_request(gba, &mut req) {
|
||||
Ok(DebuggerStatus::RequestComplete) => {
|
||||
self.notify_request_complete();
|
||||
}
|
||||
Ok(DebuggerStatus::StopRequested) => {
|
||||
self.stopped = true;
|
||||
self.notify_request_complete();
|
||||
}
|
||||
Ok(DebuggerStatus::ResumeRequested) => {
|
||||
self.stopped = false;
|
||||
self.notify_request_complete();
|
||||
}
|
||||
Ok(DebuggerStatus::Disconnected(reason)) => {
|
||||
debug!("Debugger disconnected due to {:?}", reason);
|
||||
debug!("closing gdbserver thread");
|
||||
self.thread.join().unwrap();
|
||||
Ok(None)
|
||||
return self.terminate(should_interrupt_frame);
|
||||
}
|
||||
};
|
||||
if let Ok(Some(result)) = &mut result {
|
||||
let (lock, cvar) = &*result.operation_signal;
|
||||
|
||||
Err(_) => {
|
||||
error!("An error occured while handling debug request {:?}", req);
|
||||
return self.terminate(should_interrupt_frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
*should_interrupt_frame = self.stopped;
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn notify_request_complete(&mut self) {
|
||||
let (lock, cvar) = &*self.request_complete_signal;
|
||||
let mut finished = lock.lock().unwrap();
|
||||
*finished = true;
|
||||
cvar.notify_one();
|
||||
*should_stop = result.stopped;
|
||||
} else {
|
||||
*should_stop = true;
|
||||
}
|
||||
result
|
||||
} else {
|
||||
*should_stop = self.stopped;
|
||||
Ok(Some(self))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notify_stop_reason(&mut self, reason: SingleThreadStopReason<u32>) {
|
||||
|
|
|
@ -6,7 +6,7 @@ use arm7tdmi::gdb::gdbstub::{
|
|||
target::Target,
|
||||
};
|
||||
|
||||
use super::{DebuggerMessage, DebuggerTarget};
|
||||
use super::{DebuggerRequest, DebuggerTarget};
|
||||
|
||||
pub struct DebuggerEventLoop {}
|
||||
|
||||
|
@ -54,7 +54,7 @@ impl run_blocking::BlockingEventLoop for DebuggerEventLoop {
|
|||
target: &mut DebuggerTarget,
|
||||
) -> Result<Option<SingleThreadStopReason<u32>>, <DebuggerTarget as Target>::Error> {
|
||||
info!("on_interrupt: sending stop message");
|
||||
target.tx.send(DebuggerMessage::Stop).unwrap();
|
||||
target.tx.send(DebuggerRequest::Interrupt).unwrap();
|
||||
target.wait_for_operation();
|
||||
info!("Waiting for target to stop <blocking>");
|
||||
let (lock, cvar) = &*target.stop_signal;
|
||||
|
|
|
@ -11,21 +11,23 @@ use arm7tdmi::{
|
|||
|
||||
use crate::{GBAError, GameBoyAdvance};
|
||||
|
||||
use super::{event_loop::DebuggerEventLoop, DebuggerMessage, DebuggerState, DebuggerTarget};
|
||||
use super::{
|
||||
event_loop::DebuggerEventLoop, DebuggerRequest, DebuggerRequestHandler, DebuggerTarget,
|
||||
};
|
||||
|
||||
/// Starts a gdbserver thread
|
||||
pub(crate) fn start_gdb_server_thread(
|
||||
gba: &mut GameBoyAdvance,
|
||||
port: u16,
|
||||
) -> Result<DebuggerState, GBAError> {
|
||||
) -> Result<DebuggerRequestHandler, GBAError> {
|
||||
let (tx, rx) = crossbeam::channel::unbounded();
|
||||
let operation_signal = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let request_complete_signal = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let stop_signal = Arc::new((
|
||||
Mutex::new(SingleThreadStopReason::Signal(Signal::SIGINT)),
|
||||
Condvar::new(),
|
||||
));
|
||||
let stop_signal_2 = stop_signal.clone();
|
||||
let operation_signal_2 = operation_signal.clone();
|
||||
let request_complete_signal_2 = request_complete_signal.clone();
|
||||
let memory_map = gba.sysbus.generate_memory_map_xml().unwrap();
|
||||
|
||||
let conn = wait_for_connection(port)?;
|
||||
|
@ -35,7 +37,7 @@ pub(crate) fn start_gdb_server_thread(
|
|||
|
||||
let mut target = DebuggerTarget {
|
||||
tx,
|
||||
operation_signal: operation_signal_2,
|
||||
request_complete_signal: request_complete_signal_2,
|
||||
stop_signal: stop_signal_2,
|
||||
memory_map,
|
||||
};
|
||||
|
@ -46,13 +48,13 @@ pub(crate) fn start_gdb_server_thread(
|
|||
.unwrap();
|
||||
target
|
||||
.tx
|
||||
.send(DebuggerMessage::Disconnected(disconnect_reason))
|
||||
.send(DebuggerRequest::Disconnected(disconnect_reason))
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
let mut debugger = DebuggerState {
|
||||
let mut debugger = DebuggerRequestHandler {
|
||||
rx,
|
||||
operation_signal,
|
||||
request_complete_signal,
|
||||
stop_signal,
|
||||
thread,
|
||||
stopped: true,
|
||||
|
|
|
@ -12,7 +12,7 @@ use gdbstub::target::ext::breakpoints::BreakpointsOps;
|
|||
use gdbstub::target::{self, Target, TargetError, TargetResult};
|
||||
use gdbstub_arch::arm::reg::ArmCoreRegs;
|
||||
|
||||
use super::{DebuggerMessage, DebuggerTarget};
|
||||
use super::{DebuggerRequest, DebuggerTarget};
|
||||
|
||||
impl Target for DebuggerTarget {
|
||||
type Error = ();
|
||||
|
@ -38,7 +38,7 @@ impl SingleThreadBase for DebuggerTarget {
|
|||
fn read_registers(&mut self, regs: &mut ArmCoreRegs) -> TargetResult<(), Self> {
|
||||
let regs_copy = Arc::new(Mutex::new(ArmCoreRegs::default()));
|
||||
self.tx
|
||||
.send(DebuggerMessage::ReadRegs(regs_copy.clone()))
|
||||
.send(DebuggerRequest::ReadRegs(regs_copy.clone()))
|
||||
.unwrap();
|
||||
self.wait_for_operation();
|
||||
regs_copy.lock().unwrap().clone_into(regs);
|
||||
|
@ -47,7 +47,7 @@ impl SingleThreadBase for DebuggerTarget {
|
|||
|
||||
fn write_registers(&mut self, regs: &ArmCoreRegs) -> TargetResult<(), Self> {
|
||||
self.tx
|
||||
.send(DebuggerMessage::WriteRegs(regs.clone()))
|
||||
.send(DebuggerRequest::WriteRegs(regs.clone()))
|
||||
.unwrap();
|
||||
self.wait_for_operation();
|
||||
Ok(())
|
||||
|
@ -56,7 +56,7 @@ impl SingleThreadBase for DebuggerTarget {
|
|||
fn read_addrs(&mut self, start_addr: u32, data: &mut [u8]) -> TargetResult<(), Self> {
|
||||
let buffer = Arc::new(Mutex::new(vec![0; data.len()].into_boxed_slice()));
|
||||
self.tx
|
||||
.send(DebuggerMessage::ReadAddrs(start_addr, buffer.clone()))
|
||||
.send(DebuggerRequest::ReadAddrs(start_addr, buffer.clone()))
|
||||
.unwrap();
|
||||
self.wait_for_operation();
|
||||
data.copy_from_slice(&buffer.lock().unwrap());
|
||||
|
@ -78,7 +78,7 @@ impl SingleThreadBase for DebuggerTarget {
|
|||
|
||||
impl SingleThreadResume for DebuggerTarget {
|
||||
fn resume(&mut self, _signal: Option<Signal>) -> Result<(), Self::Error> {
|
||||
self.tx.send(DebuggerMessage::Resume).unwrap();
|
||||
self.tx.send(DebuggerRequest::Resume).unwrap();
|
||||
self.wait_for_operation();
|
||||
Ok(())
|
||||
}
|
||||
|
@ -94,9 +94,7 @@ impl SingleThreadResume for DebuggerTarget {
|
|||
|
||||
impl SingleThreadSingleStep for DebuggerTarget {
|
||||
fn step(&mut self, _signal: Option<Signal>) -> Result<(), Self::Error> {
|
||||
self.tx.send(DebuggerMessage::SingleStep).unwrap();
|
||||
self.wait_for_operation();
|
||||
self.tx.send(DebuggerMessage::Stop).unwrap();
|
||||
self.tx.send(DebuggerRequest::SingleStep).unwrap();
|
||||
self.wait_for_operation();
|
||||
Ok(())
|
||||
}
|
||||
|
@ -135,7 +133,7 @@ impl target::ext::breakpoints::SwBreakpoint for DebuggerTarget {
|
|||
_kind: gdbstub_arch::arm::ArmBreakpointKind,
|
||||
) -> TargetResult<bool, Self> {
|
||||
self.tx
|
||||
.send(DebuggerMessage::AddSwBreakpoint(addr))
|
||||
.send(DebuggerRequest::AddSwBreakpoint(addr))
|
||||
.unwrap();
|
||||
self.wait_for_operation();
|
||||
Ok(true)
|
||||
|
@ -147,7 +145,7 @@ impl target::ext::breakpoints::SwBreakpoint for DebuggerTarget {
|
|||
_kind: gdbstub_arch::arm::ArmBreakpointKind,
|
||||
) -> TargetResult<bool, Self> {
|
||||
self.tx
|
||||
.send(DebuggerMessage::DelSwBreakpoint(addr))
|
||||
.send(DebuggerRequest::DelSwBreakpoint(addr))
|
||||
.unwrap();
|
||||
self.wait_for_operation();
|
||||
Ok(true)
|
||||
|
|
|
@ -95,12 +95,26 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
audio_interface,
|
||||
));
|
||||
|
||||
// let gba_raw_ptr = Box::into_raw(gba) as usize;
|
||||
// static mut gba_raw: usize = 0;
|
||||
// unsafe { gba_raw = gba_raw_ptr };
|
||||
// let mut gba = unsafe {Box::from_raw(gba_raw_ptr as *mut GameBoyAdvance) };
|
||||
|
||||
// std::panic::set_hook(Box::new(|panic_info| {
|
||||
// let gba = unsafe {Box::from_raw(gba_raw as *mut GameBoyAdvance) };
|
||||
// println!("System crashed Oh No!!! {:?}", gba.cpu);
|
||||
// let normal_panic = std::panic::take_hook();
|
||||
// normal_panic(panic_info);
|
||||
// }));
|
||||
|
||||
|
||||
if opts.skip_bios {
|
||||
println!("Skipping bios animation..");
|
||||
gba.skip_bios();
|
||||
}
|
||||
|
||||
if opts.gdbserver {
|
||||
todo!("gdb")
|
||||
gba.start_gdbserver(DEFAULT_GDB_SERVER_PORT);
|
||||
}
|
||||
|
||||
let mut vsync = true;
|
||||
|
@ -146,7 +160,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
if opts.savestate_path().is_file() {
|
||||
let save = read_bin_file(&opts.savestate_path())?;
|
||||
info!("Restoring state from {:?}...", opts.savestate_path());
|
||||
gba.restore_state(&save)?;
|
||||
let (audio_interface, _sdl_audio_device_new) = audio::create_audio_player(&sdl_context)?;
|
||||
_sdl_audio_device = _sdl_audio_device_new;
|
||||
let rom = opts.read_rom()?.into_boxed_slice();
|
||||
gba = Box::new(GameBoyAdvance::from_saved_state(&save, bios_bin.clone(), rom, audio_interface)?);
|
||||
info!("Restored!");
|
||||
} else {
|
||||
info!("Savestate not created, please create one by pressing F5");
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use std::path::PathBuf;
|
||||
use std::{path::PathBuf, io};
|
||||
|
||||
use rustboyadvance_core::{
|
||||
cartridge::{BackupType, GamepakBuilder},
|
||||
prelude::Cartridge,
|
||||
};
|
||||
use rustboyadvance_utils::read_bin_file;
|
||||
use structopt::StructOpt;
|
||||
|
||||
const SAVE_TYPE_POSSIBLE_VALUES: &[&str] =
|
||||
|
@ -61,4 +62,8 @@ impl Options {
|
|||
pub fn rom_name(&self) -> &str {
|
||||
self.rom.file_name().unwrap().to_str().unwrap()
|
||||
}
|
||||
|
||||
pub fn read_rom(&self) -> Result<Vec<u8>, std::io::Error> {
|
||||
read_bin_file(&self.rom)
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue