2021-11-05 15:08:17 +00:00
|
|
|
// use std::{thread, time};
|
2021-11-01 02:02:09 +00:00
|
|
|
use winit_input_helper::WinitInputHelper;
|
|
|
|
use winit::event::{VirtualKeyCode};
|
2021-10-14 01:50:48 +00:00
|
|
|
|
2021-11-01 02:02:09 +00:00
|
|
|
use crate::cpu::{CPU, Cycles, Interrupt};
|
2021-10-14 00:38:37 +00:00
|
|
|
use crate::bus::Bus;
|
2021-11-15 21:38:52 +00:00
|
|
|
use crate::joypad::{Button};
|
2021-11-19 22:11:27 +00:00
|
|
|
#[cfg(not(test))]
|
|
|
|
use crate::rom::{save_file};
|
2021-10-14 00:38:37 +00:00
|
|
|
|
2021-10-26 22:34:59 +00:00
|
|
|
pub struct Emulator {
|
2021-10-14 00:38:37 +00:00
|
|
|
bus: Bus,
|
2021-11-15 16:25:30 +00:00
|
|
|
cpu: CPU,
|
2021-10-14 00:38:37 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 22:34:59 +00:00
|
|
|
impl Emulator {
|
2021-10-14 00:38:37 +00:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
2021-11-15 21:38:52 +00:00
|
|
|
bus: Bus::new(),
|
2021-10-14 00:38:37 +00:00
|
|
|
cpu: CPU::new(),
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-19 22:11:27 +00:00
|
|
|
pub fn close(&self) {
|
|
|
|
println!("closing emulator");
|
|
|
|
|
|
|
|
#[cfg(not(test))]
|
|
|
|
match save_file(self.bus.rom.ram(), self.bus.rom.info()) {
|
|
|
|
Err(err) => eprintln!("Could not save file: {}", err),
|
|
|
|
_ => {},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-11-01 02:02:09 +00:00
|
|
|
pub fn handle_input(&mut self, input: &WinitInputHelper) {
|
|
|
|
let mut change = false;
|
|
|
|
if input.key_pressed(VirtualKeyCode::K) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::A);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_pressed(VirtualKeyCode::J) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::B);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_pressed(VirtualKeyCode::W) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::Up);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_pressed(VirtualKeyCode::S) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::Down);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_pressed(VirtualKeyCode::A) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::Left);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_pressed(VirtualKeyCode::D) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::Right);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_pressed(VirtualKeyCode::N) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::Start);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_pressed(VirtualKeyCode::B) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.press(Button::Select);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.key_released(VirtualKeyCode::K) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::A);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_released(VirtualKeyCode::J) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::B);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_released(VirtualKeyCode::W) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::Up);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_released(VirtualKeyCode::S) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::Down);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_released(VirtualKeyCode::A) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::Left);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_released(VirtualKeyCode::D) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::Right);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_released(VirtualKeyCode::N) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::Start);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if input.key_released(VirtualKeyCode::B) {
|
|
|
|
change = true;
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.joypad.release(Button::Select);
|
2021-11-01 02:02:09 +00:00
|
|
|
}
|
|
|
|
if change {
|
|
|
|
self.bus.set_interrupt_flag(Interrupt::Joypad, true);
|
2021-10-14 00:38:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-03 16:59:48 +00:00
|
|
|
pub fn run(&mut self, cpu_cycles: Cycles, frame_buffer: &mut [u8]) {
|
2021-10-26 22:34:59 +00:00
|
|
|
self.cpu.reset_cycles();
|
2021-11-07 02:36:16 +00:00
|
|
|
while self.cpu.get_cycles().to_t().0 <= cpu_cycles.0 {
|
2021-10-26 22:34:59 +00:00
|
|
|
self.cpu.run(&mut self.bus);
|
2021-11-15 16:25:30 +00:00
|
|
|
let cycles = self.cpu.get_last_op_cycles().to_t();
|
2021-11-15 21:38:52 +00:00
|
|
|
self.bus.ppu.do_cycles(cycles, frame_buffer);
|
|
|
|
if self.bus.ppu.get_interrupt(Interrupt::VBlank) {
|
|
|
|
self.bus.set_interrupt_flag(Interrupt::VBlank, true);
|
|
|
|
self.bus.ppu.set_interrupt(Interrupt::VBlank, false);
|
|
|
|
}
|
|
|
|
if self.bus.ppu.get_interrupt(Interrupt::LCDSTAT) {
|
|
|
|
self.bus.set_interrupt_flag(Interrupt::LCDSTAT, true);
|
|
|
|
self.bus.ppu.set_interrupt(Interrupt::LCDSTAT, false);
|
|
|
|
}
|
|
|
|
self.bus.timer.do_cycles(cycles);
|
|
|
|
if self.bus.timer.get_interrupt() {
|
|
|
|
self.bus.set_interrupt_flag(Interrupt::Timer, true);
|
|
|
|
self.bus.timer.set_interrupt(false);
|
|
|
|
}
|
2021-11-03 13:36:30 +00:00
|
|
|
|
|
|
|
// 1 CPU cycle = 238.42ns
|
|
|
|
// thread::sleep(time::Duration::from_nanos((self.cpu.get_last_op_cycles().0 * 238).try_into().unwrap()));
|
|
|
|
|
2021-10-26 22:34:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn cpu_loop(&mut self) {
|
2021-10-14 01:50:48 +00:00
|
|
|
let mut exit = false;
|
2021-11-11 01:57:58 +00:00
|
|
|
let mut frame: [u8; 144 * 160 * 4] = [0; 144 * 160 * 4];
|
2021-10-14 01:50:48 +00:00
|
|
|
while !exit {
|
|
|
|
self.cpu.run(&mut self.bus);
|
2021-11-15 21:38:52 +00:00
|
|
|
let cycles = self.cpu.get_last_op_cycles().to_t();
|
|
|
|
self.bus.ppu.do_cycles(cycles, &mut frame);
|
|
|
|
if self.bus.ppu.get_interrupt(Interrupt::VBlank) {
|
|
|
|
self.bus.set_interrupt_flag(Interrupt::VBlank, true);
|
|
|
|
self.bus.ppu.set_interrupt(Interrupt::VBlank, false);
|
|
|
|
}
|
|
|
|
if self.bus.ppu.get_interrupt(Interrupt::LCDSTAT) {
|
|
|
|
self.bus.set_interrupt_flag(Interrupt::LCDSTAT, true);
|
|
|
|
self.bus.ppu.set_interrupt(Interrupt::LCDSTAT, false);
|
|
|
|
}
|
|
|
|
self.bus.timer.do_cycles(cycles);
|
|
|
|
if self.bus.timer.get_interrupt() {
|
|
|
|
self.bus.set_interrupt_flag(Interrupt::Timer, true);
|
|
|
|
self.bus.timer.set_interrupt(false);
|
|
|
|
}
|
2021-10-14 01:50:48 +00:00
|
|
|
|
2021-10-20 02:55:35 +00:00
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 1258895; // log 1
|
2021-11-03 13:36:30 +00:00
|
|
|
exit = self.cpu.get_exec_calls_count() >= 161502; // log 2
|
2021-10-20 02:55:35 +00:00
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 1068422; // log 3
|
2021-10-20 03:36:10 +00:00
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 1262766; // log 4
|
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 1763388; // log 5
|
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 1763388; // log 5
|
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 243272; // log 6
|
2021-10-20 17:29:55 +00:00
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 287416; // log 7
|
2021-10-20 18:39:39 +00:00
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 223892; // log 8
|
2021-10-20 18:47:59 +00:00
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 4420382; // log 9
|
2021-10-20 19:33:11 +00:00
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 6714723; // log 10
|
|
|
|
// exit = self.cpu.get_exec_calls_count() >= 7429762; // log 11
|
2021-10-14 01:50:48 +00:00
|
|
|
}
|
2021-10-14 00:38:37 +00:00
|
|
|
}
|
|
|
|
}
|