diff --git a/src/main.rs b/src/main.rs index abab379..642f9c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ // hide console in release mode #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use std::{path::PathBuf, process}; +use std::{path::PathBuf, process, time::SystemTime}; use anyhow::Result; use app::Application; @@ -24,6 +24,43 @@ struct Args { rom: Option, } +fn set_panic_handler() { + std::panic::set_hook(Box::new(|info| { + let mut message = String::new(); + if let Some(msg) = info.payload().downcast_ref::<&str>() { + message += &format!("{}\n", msg); + } else if let Some(msg) = info.payload().downcast_ref::() { + message += &format!("{}\n", msg); + } + if let Some(location) = info.location() { + message += &format!( + " in file '{}' at line {}\n", + location.file(), + location.line() + ); + } + let backtrace = std::backtrace::Backtrace::force_capture(); + message += &format!("stack trace:\n{:#}\n", backtrace); + + eprint!("{}", message); + + let Some(project_dirs) = directories::ProjectDirs::from("com", "virtual-boy", "Lemur") + else { + return; + }; + let data_dir = project_dirs.data_dir(); + if std::fs::create_dir_all(data_dir).is_err() { + return; + } + let timestamp = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_millis(); + let logfile_name = format!("crash-{}.txt", timestamp); + let _ = std::fs::write(data_dir.join(logfile_name), message); + })); +} + #[cfg(windows)] fn set_process_priority_to_high() -> Result<()> { use windows::Win32::{Foundation, System::Threading}; @@ -34,6 +71,8 @@ fn set_process_priority_to_high() -> Result<()> { } fn main() -> Result<()> { + set_panic_handler(); + #[cfg(windows)] set_process_priority_to_high()?;