2019-06-30 20:31:16 +01:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io;
|
|
|
|
use std::io::prelude::*;
|
2019-12-04 23:15:49 +00:00
|
|
|
use std::path::Path;
|
|
|
|
use std::time;
|
2019-06-30 20:31:16 +01:00
|
|
|
|
2020-02-22 22:19:55 +00:00
|
|
|
use crate::core::GameBoyAdvance;
|
|
|
|
#[cfg(feature = "gdb")]
|
|
|
|
use gdbstub;
|
|
|
|
#[cfg(feature = "gdb")]
|
|
|
|
use gdbstub::GdbStub;
|
|
|
|
use std::fmt;
|
|
|
|
#[cfg(feature = "gdb")]
|
|
|
|
use std::net::TcpListener;
|
2020-02-23 21:05:09 +00:00
|
|
|
use std::net::ToSocketAddrs;
|
2020-02-22 22:19:55 +00:00
|
|
|
|
|
|
|
pub fn spawn_and_run_gdb_server<A: ToSocketAddrs + fmt::Display>(
|
|
|
|
target: &mut GameBoyAdvance,
|
|
|
|
addr: A,
|
|
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
#[cfg(feature = "gdb")]
|
|
|
|
{
|
|
|
|
info!("spawning gdbserver, listening on {}", addr);
|
|
|
|
|
|
|
|
let sock = TcpListener::bind(addr)?;
|
|
|
|
let (stream, addr) = sock.accept()?;
|
|
|
|
|
|
|
|
info!("got connection from {}", addr);
|
|
|
|
|
|
|
|
let mut gdb = GdbStub::new(stream);
|
|
|
|
let result = match gdb.run(target) {
|
|
|
|
Ok(state) => {
|
|
|
|
info!("Disconnected from GDB. Target state: {:?}", state);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
Err(gdbstub::Error::TargetError(e)) => Err(e),
|
|
|
|
Err(e) => return Err(e.into()),
|
|
|
|
};
|
|
|
|
|
|
|
|
info!("Debugger session ended, result={:?}", result);
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "gdb"))]
|
|
|
|
{
|
|
|
|
error!("failed. please compile me with 'gdb' feature")
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-12-04 23:15:49 +00:00
|
|
|
pub fn read_bin_file(filename: &Path) -> io::Result<Vec<u8>> {
|
2019-06-30 20:31:16 +01:00
|
|
|
let mut buf = Vec::new();
|
|
|
|
let mut file = File::open(filename)?;
|
|
|
|
file.read_to_end(&mut buf)?;
|
|
|
|
Ok(buf)
|
2019-07-01 15:45:29 +01:00
|
|
|
}
|
2019-07-30 22:52:46 +01:00
|
|
|
|
2020-01-16 17:49:43 +00:00
|
|
|
pub fn write_bin_file(filename: &Path, data: &Vec<u8>) -> io::Result<()> {
|
|
|
|
let mut f = File::create(filename)?;
|
|
|
|
f.write_all(data)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-12-04 23:15:49 +00:00
|
|
|
pub struct FpsCounter {
|
|
|
|
count: u32,
|
|
|
|
timer: time::Instant,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for FpsCounter {
|
|
|
|
fn default() -> FpsCounter {
|
|
|
|
FpsCounter {
|
|
|
|
count: 0,
|
|
|
|
timer: time::Instant::now(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FpsCounter {
|
|
|
|
pub fn tick(&mut self) -> Option<u32> {
|
|
|
|
self.count += 1;
|
|
|
|
if self.timer.elapsed() >= time::Duration::from_secs(1) {
|
|
|
|
let fps = self.count;
|
|
|
|
self.timer = time::Instant::now();
|
|
|
|
self.count = 0;
|
|
|
|
Some(fps)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-30 22:52:46 +01:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! index2d {
|
|
|
|
($x:expr, $y:expr, $w:expr) => {
|
|
|
|
$w * $y + $x
|
|
|
|
};
|
2019-08-13 19:57:45 +01:00
|
|
|
($t:ty, $x:expr, $y:expr, $w:expr) => {
|
|
|
|
(($w as $t) * ($y as $t) + ($x as $t)) as $t
|
|
|
|
};
|
2019-07-30 22:52:46 +01:00
|
|
|
}
|
2019-11-11 01:35:16 +00:00
|
|
|
|
2020-02-14 12:01:48 +00:00
|
|
|
#[allow(unused_macros)]
|
2019-11-11 01:35:16 +00:00
|
|
|
macro_rules! host_breakpoint {
|
|
|
|
() => {
|
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
unsafe {
|
|
|
|
::std::intrinsics::breakpoint()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|