No debugging unless the game is running
This commit is contained in:
		
							parent
							
								
									f031bb17b2
								
							
						
					
					
						commit
						17d3811124
					
				| 
						 | 
					@ -305,6 +305,10 @@ impl Emulator {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn start_debugging(&mut self, sim_id: SimId, sender: DebugSender) {
 | 
					    fn start_debugging(&mut self, sim_id: SimId, sender: DebugSender) {
 | 
				
			||||||
 | 
					        if self.sim_state[sim_id.to_index()].load(Ordering::Acquire) != SimState::Ready {
 | 
				
			||||||
 | 
					            // Can't debug unless a game is connected
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        let debug = DebugInfo {
 | 
					        let debug = DebugInfo {
 | 
				
			||||||
            sender,
 | 
					            sender,
 | 
				
			||||||
            stop_reason: Some(DebugStopReason::Trapped),
 | 
					            stop_reason: Some(DebugStopReason::Trapped),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ use std::{
 | 
				
			||||||
use tokio::{
 | 
					use tokio::{
 | 
				
			||||||
    io::{AsyncWriteExt as _, BufReader},
 | 
					    io::{AsyncWriteExt as _, BufReader},
 | 
				
			||||||
    net::{TcpListener, TcpStream},
 | 
					    net::{TcpListener, TcpStream},
 | 
				
			||||||
    select,
 | 
					    pin, select,
 | 
				
			||||||
    sync::{mpsc, oneshot},
 | 
					    sync::{mpsc, oneshot},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use tracing::{debug, enabled, error, info, Level};
 | 
					use tracing::{debug, enabled, error, info, Level};
 | 
				
			||||||
| 
						 | 
					@ -57,8 +57,9 @@ impl GdbServer {
 | 
				
			||||||
                .unwrap()
 | 
					                .unwrap()
 | 
				
			||||||
                .block_on(async move {
 | 
					                .block_on(async move {
 | 
				
			||||||
                    select! {
 | 
					                    select! {
 | 
				
			||||||
                        _ = run_server(sim_id, client, port, &status) => {}
 | 
					                        _ = run_server(sim_id, client.clone(), port, &status) => {}
 | 
				
			||||||
                        _ = rx => {
 | 
					                        _ = rx => {
 | 
				
			||||||
 | 
					                            client.send_command(EmulatorCommand::StopDebugging(sim_id));
 | 
				
			||||||
                            *status.lock().unwrap() = GdbServerStatus::Stopped;
 | 
					                            *status.lock().unwrap() = GdbServerStatus::Stopped;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -73,19 +74,46 @@ impl GdbServer {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Drop for GdbServer {
 | 
				
			||||||
 | 
					    fn drop(&mut self) {
 | 
				
			||||||
 | 
					        self.stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn run_server(
 | 
					async fn run_server(
 | 
				
			||||||
    sim_id: SimId,
 | 
					    sim_id: SimId,
 | 
				
			||||||
    client: EmulatorClient,
 | 
					    client: EmulatorClient,
 | 
				
			||||||
    port: u16,
 | 
					    port: u16,
 | 
				
			||||||
    status: &Mutex<GdbServerStatus>,
 | 
					    status: &Mutex<GdbServerStatus>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
 | 
					    let (debug_sink, mut debug_source) = mpsc::unbounded_channel();
 | 
				
			||||||
 | 
					    client.send_command(EmulatorCommand::StartDebugging(sim_id, debug_sink));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info!("Connecting to debugger on port {port}...");
 | 
					    info!("Connecting to debugger on port {port}...");
 | 
				
			||||||
    let Some(stream) = try_connect(port, status).await else {
 | 
					    let connect_future = try_connect(port, status);
 | 
				
			||||||
 | 
					    pin!(connect_future);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let stream = loop {
 | 
				
			||||||
 | 
					        select! {
 | 
				
			||||||
 | 
					            stream = &mut connect_future => {
 | 
				
			||||||
 | 
					                if let Some(stream) = stream {
 | 
				
			||||||
 | 
					                    break stream;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            event = debug_source.recv() => {
 | 
				
			||||||
 | 
					                if event.is_none() {
 | 
				
			||||||
 | 
					                    // The sim has stopped (or was never started)
 | 
				
			||||||
 | 
					                    *status.lock().unwrap() = GdbServerStatus::Stopped;
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    info!("Connected!");
 | 
					    info!("Connected!");
 | 
				
			||||||
    let mut connection = GdbConnection::new(sim_id, client);
 | 
					    let mut connection = GdbConnection::new(sim_id, client);
 | 
				
			||||||
    match connection.run(stream).await {
 | 
					    match connection.run(stream, debug_source).await {
 | 
				
			||||||
        Ok(()) => {
 | 
					        Ok(()) => {
 | 
				
			||||||
            info!("Finished debugging.");
 | 
					            info!("Finished debugging.");
 | 
				
			||||||
            *status.lock().unwrap() = GdbServerStatus::Stopped;
 | 
					            *status.lock().unwrap() = GdbServerStatus::Stopped;
 | 
				
			||||||
| 
						 | 
					@ -154,12 +182,13 @@ impl GdbConnection {
 | 
				
			||||||
            memory_buf: None,
 | 
					            memory_buf: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    async fn run(&mut self, stream: TcpStream) -> Result<()> {
 | 
					    async fn run(
 | 
				
			||||||
        let (debug_sink, mut debug_source) = mpsc::unbounded_channel();
 | 
					        &mut self,
 | 
				
			||||||
 | 
					        stream: TcpStream,
 | 
				
			||||||
 | 
					        mut debug_source: mpsc::UnboundedReceiver<DebugEvent>,
 | 
				
			||||||
 | 
					    ) -> Result<()> {
 | 
				
			||||||
        let (rx, mut tx) = stream.into_split();
 | 
					        let (rx, mut tx) = stream.into_split();
 | 
				
			||||||
        let mut request_source = RequestSource::new(BufReader::new(rx));
 | 
					        let mut request_source = RequestSource::new(BufReader::new(rx));
 | 
				
			||||||
        self.client
 | 
					 | 
				
			||||||
            .send_command(EmulatorCommand::StartDebugging(self.sim_id, debug_sink));
 | 
					 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let response = select! {
 | 
					            let response = select! {
 | 
				
			||||||
                maybe_event = debug_source.recv() => {
 | 
					                maybe_event = debug_source.recv() => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::{path::PathBuf, process, time::SystemTime};
 | 
					use std::{path::PathBuf, process, time::SystemTime};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use anyhow::Result;
 | 
					use anyhow::{bail, Result};
 | 
				
			||||||
use app::Application;
 | 
					use app::Application;
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
use emulator::EmulatorBuilder;
 | 
					use emulator::EmulatorBuilder;
 | 
				
			||||||
| 
						 | 
					@ -95,10 +95,13 @@ fn main() -> Result<()> {
 | 
				
			||||||
    let args = Args::parse();
 | 
					    let args = Args::parse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (mut builder, client) = EmulatorBuilder::new();
 | 
					    let (mut builder, client) = EmulatorBuilder::new();
 | 
				
			||||||
    if let Some(path) = args.rom {
 | 
					    if let Some(path) = &args.rom {
 | 
				
			||||||
        builder = builder.with_rom(&path);
 | 
					        builder = builder.with_rom(path);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if args.debug_port.is_some() {
 | 
					    if args.debug_port.is_some() {
 | 
				
			||||||
 | 
					        if args.rom.is_none() {
 | 
				
			||||||
 | 
					            bail!("to start debugging, please select a game.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        builder = builder.start_paused(true);
 | 
					        builder = builder.start_paused(true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ use winit::event_loop::EventLoopProxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    app::UserEvent,
 | 
					    app::UserEvent,
 | 
				
			||||||
    emulator::{EmulatorClient, SimId},
 | 
					    emulator::{EmulatorClient, SimId, SimState},
 | 
				
			||||||
    gdbserver::{GdbServer, GdbServerStatus},
 | 
					    gdbserver::{GdbServer, GdbServerStatus},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@ use super::AppWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct GdbServerWindow {
 | 
					pub struct GdbServerWindow {
 | 
				
			||||||
    sim_id: SimId,
 | 
					    sim_id: SimId,
 | 
				
			||||||
 | 
					    client: EmulatorClient,
 | 
				
			||||||
    port_str: String,
 | 
					    port_str: String,
 | 
				
			||||||
    connected: bool,
 | 
					    connected: bool,
 | 
				
			||||||
    quit_on_disconnect: bool,
 | 
					    quit_on_disconnect: bool,
 | 
				
			||||||
| 
						 | 
					@ -22,6 +23,7 @@ impl GdbServerWindow {
 | 
				
			||||||
    pub fn new(sim_id: SimId, client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> Self {
 | 
					    pub fn new(sim_id: SimId, client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            sim_id,
 | 
					            sim_id,
 | 
				
			||||||
 | 
					            client: client.clone(),
 | 
				
			||||||
            port_str: (8080 + sim_id.to_index()).to_string(),
 | 
					            port_str: (8080 + sim_id.to_index()).to_string(),
 | 
				
			||||||
            connected: false,
 | 
					            connected: false,
 | 
				
			||||||
            quit_on_disconnect: false,
 | 
					            quit_on_disconnect: false,
 | 
				
			||||||
| 
						 | 
					@ -78,7 +80,9 @@ impl AppWindow for GdbServerWindow {
 | 
				
			||||||
                    self.connected = false;
 | 
					                    self.connected = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                let start_button = Button::new("Start");
 | 
					                let start_button = Button::new("Start");
 | 
				
			||||||
                if ui.add_enabled(port_num.is_some(), start_button).clicked() {
 | 
					                let can_start =
 | 
				
			||||||
 | 
					                    port_num.is_some() && self.client.sim_state(self.sim_id) == SimState::Ready;
 | 
				
			||||||
 | 
					                if ui.add_enabled(can_start, start_button).clicked() {
 | 
				
			||||||
                    let port = port_num.unwrap();
 | 
					                    let port = port_num.unwrap();
 | 
				
			||||||
                    self.server.start(port);
 | 
					                    self.server.start(port);
 | 
				
			||||||
                    self.connected = true;
 | 
					                    self.connected = true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue