use crate::types::{GameInput, KeyState};
mod cpu;
mod graphics;
mod joypad;
mod mem;
mod sound;
pub struct Emulator {
screen: graphics::Screen,
cpu: cpu::CPU,
joypad: joypad::Joypad,
paused: bool,
}
impl Default for Emulator {
fn default() -> Self {
Self::new()
}
}
impl Emulator {
const MAXCYCLES: u32 = 69905;
pub fn new() -> Self {
let mut cpu = cpu::CPU::new();
cpu.memory_mut().ram_startup();
Emulator { screen: graphics::Screen::new(), cpu, joypad: joypad::Joypad::new(), paused: true }
}
pub fn update(&mut self) {
if self.paused {
return;
}
let mut num_cycles: u32 = 0;
while num_cycles < Self::MAXCYCLES {
let cycles = self.cpu.execute_next_opcode(false);
num_cycles += cycles as u32;
self.cpu.update_timers(cycles as i32);
self.screen.update_screen(self.cpu.memory_mut(), cycles as i32);
self.cpu.handle_interrupts();
}
}
pub fn toggle_pause(&mut self) {
self.paused = !self.paused;
}
pub fn is_paused(&self) -> bool {
self.paused
}
pub fn load_rom_data(&mut self, data: &[u8]) {
let mem = self.cpu.memory_mut();
mem.load_rom_data(data);
mem.ram_startup();
self.cpu.reset();
self.paused = false;
}
#[cfg(feature = "std")]
pub fn load_rom(&mut self, path: &str) -> Result<(), std::string::String> {
let data = std::fs::read(path).map_err(|e| e.to_string())?;
self.load_rom_data(&data);
Ok(())
}
pub fn get_display_buffer(&self) -> &[u8] {
&self.screen.buffer
}
pub fn dump_lcd_mem(&self) {
#[cfg(feature = "std")]
{
let mem = self.cpu.memory();
println!("IDK: {:X}", mem.read_byte_forced(0xFF26));
println!(
"LCD Control: {:X}",
mem.read_byte_forced(crate::types::LCD_CONTROL)
);
println!("Scroll Y: {:X}", mem.read_byte_forced(0xFF42));
println!("Scroll X: {:X}", mem.read_byte_forced(0xFF43));
println!("BG Palette: {:X}", mem.read_byte_forced(0xFF47));
println!("OBJ palette: {:X}", mem.read_byte_forced(0xFF48));
println!(
"Current Scanline: {:X}",
mem.read_byte_forced(crate::types::CURRENT_SCANLINE)
);
println!(
"Joystick Register: 0x{:X}",
mem.read_byte_forced(crate::types::INPUT_REGISTER)
);
}
}
pub fn game_input(&mut self, input: GameInput, val: KeyState) {
self.joypad.log_input(self.cpu.memory_mut(), input, val)
}
}