use std::fs::File; use std::io; use std::io::prelude::*; use std::path::Path; use std::time; #[cfg(not(target_arch = "wasm32"))] type Instant = time::Instant; #[cfg(not(target_arch = "wasm32"))] fn now() -> Instant { time::Instant::now() } #[cfg(target_arch = "wasm32")] use instant; #[cfg(target_arch = "wasm32")] type Instant = instant::Instant; #[cfg(target_arch = "wasm32")] fn now() -> Instant { instant::Instant::now() } use crate::GameBoyAdvance; #[cfg(feature = "gdb")] use gdbstub; #[cfg(feature = "gdb")] use gdbstub::GdbStub; use std::fmt; #[cfg(feature = "gdb")] use std::net::TcpListener; use std::net::ToSocketAddrs; pub fn spawn_and_run_gdb_server( #[allow(unused)] target: &mut GameBoyAdvance, #[allow(unused)] addr: A, ) -> Result<(), Box> { #[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(()) } pub fn read_bin_file(filename: &Path) -> io::Result> { let mut buf = Vec::new(); let mut file = File::open(filename)?; file.read_to_end(&mut buf)?; Ok(buf) } pub fn write_bin_file(filename: &Path, data: &Vec) -> io::Result<()> { let mut f = File::create(filename)?; f.write_all(data)?; Ok(()) } pub struct FpsCounter { count: u32, timer: Instant, } const SECOND: time::Duration = time::Duration::from_secs(1); impl Default for FpsCounter { fn default() -> FpsCounter { FpsCounter { count: 0, timer: now(), } } } impl FpsCounter { pub fn tick(&mut self) -> Option { self.count += 1; if self.timer.elapsed() >= SECOND { let fps = self.count; self.timer = now(); self.count = 0; Some(fps) } else { None } } } #[macro_export] macro_rules! index2d { ($x:expr, $y:expr, $w:expr) => { $w * $y + $x }; ($t:ty, $x:expr, $y:expr, $w:expr) => { (($w as $t) * ($y as $t) + ($x as $t)) as $t }; } #[allow(unused_macros)] macro_rules! host_breakpoint { () => { #[cfg(debug_assertions)] unsafe { ::std::intrinsics::breakpoint() } }; } pub mod audio { use ringbuf::{Consumer, Producer, RingBuffer}; pub struct AudioRingBuffer { pub prod: Producer, pub cons: Consumer, } impl AudioRingBuffer { pub fn new() -> AudioRingBuffer { let rb = RingBuffer::new(4096 * 2); let (prod, cons) = rb.split(); AudioRingBuffer { prod, cons } } pub fn producer(&mut self) -> &mut Producer { &mut self.prod } pub fn consumer(&mut self) -> &mut Consumer { &mut self.cons } } }