use arg::Args;
use librsmsx::libs::graphics::GraphicsType;
use librsmsx::libs::msx::MSX;
use librsmsx::libs::ports::Ports;
use librsmsx::libs::ppi::PPI;
use librsmsx::libs::psg::PSG;
use librsmsx::libs::sound::SoundType;
use librsmsx::libs::vdp::Vdp;
use librsmsx::libs::{memory::Memory, z80::z80_base::Z80};
use log::{Level, LevelFilter, Metadata, Record};
use macroquad::prelude::*;
const SYSTEM_ROM_FILE: &str = "cbios_main_msx1.rom";
#[derive(Args, Debug)]
struct MyArgs {
#[arg(long)]
cart: String,
#[arg(long = "sys")]
system_rom: String,
#[arg(long, default_value = "true")]
quality: bool,
#[arg(long = "fint", default_value = "16")]
frame_interval: u32,
#[arg(long)]
mtype: String,
}
static MY_LOGGER: MyLogger = MyLogger;
struct MyLogger;
impl log::Log for MyLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Debug
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
println!("{} - {}", record.level(), record.args());
}
if record.metadata().level() == Level::Error {
panic!();
}
}
fn flush(&self) {}
}
use std::{cell::RefCell, ops::ControlFlow, rc::Rc};
use librsmsx::libs::z80::{hook::FuncHook, z80_base::Z80Data, z80_tables::Z80Tables};
pub struct SampleHook {
calls: u64,
}
impl Default for SampleHook {
fn default() -> Self {
Self::new()
}
}
impl SampleHook {
pub(crate) fn new() -> Self {
Self { calls: 0 }
}
}
impl FuncHook for SampleHook {
fn handle_jp_hl_hook(
&mut self,
_data: &mut Z80Data,
_memory: &mut Memory,
_tables: &Z80Tables,
_jmp_tgt: u16,
) -> ControlFlow<()> {
ControlFlow::Continue(())
}
fn handle_call_hook(
&mut self,
_data: &mut Z80Data,
_memory: &mut Memory,
_tables: &Z80Tables,
new_pc: u16,
_old_pc: u16,
) -> ControlFlow<()> {
self.calls += 1;
println!("new call hook #:{} 0x{:04x}", self.calls, new_pc);
ControlFlow::Continue(())
}
}
#[macroquad::main("rsmsx")]
async fn main() {
log::set_logger(&MY_LOGGER).unwrap();
log::set_max_level(LevelFilter::Debug);
let args: std::vec::Vec<_> = std::env::args().skip(1).collect();
match MyArgs::from_args(args.iter().map(|x| x.as_str())) {
Ok(mut args) => {
if args.system_rom.is_empty() {
args.system_rom = SYSTEM_ROM_FILE.to_string();
}
let ppi = Rc::new(RefCell::new(PPI::new()));
let mut memory = Memory::new(ppi.clone());
memory.load_bios_basic(&args.system_rom);
if !args.cart.is_empty() {
memory.load_rom(&args.cart, 1, &args.mtype);
}
let psg = PSG::new(SoundType::Normal);
let vdp = Rc::new(RefCell::new(Vdp::new(GraphicsType::Normal, args.quality)));
vdp.borrow_mut().init_graphics();
let ports = Ports::new(vdp.clone(), ppi.clone(), psg);
let mut cpu_z80 = Z80::new(memory, ports);
cpu_z80.set_hook(Rc::new(RefCell::new(SampleHook::new())));
cpu_z80.reboot();
let mut msx = MSX::new(
cpu_z80,
vdp.clone(),
);
let avg_fps = msx.main_loop(args.frame_interval as isize).await;
log::info!("Avg FPS: {:.2}", avg_fps);
}
Err(err) => println!("err={:?}", err),
}
}