chore: remove Cycle struct and begin scheduler design
This commit is contained in:
parent
10ac579c40
commit
6087e3b20b
14
src/cpu.rs
14
src/cpu.rs
|
@ -1,10 +1,10 @@
|
|||
use crate::apu::Apu;
|
||||
use crate::bus::{Bus, BusIo};
|
||||
use crate::instruction::cycle::Cycle;
|
||||
use crate::instruction::Instruction;
|
||||
use crate::interrupt::{InterruptEnable, InterruptFlag};
|
||||
use crate::joypad::Joypad;
|
||||
use crate::ppu::Ppu;
|
||||
use crate::Cycle;
|
||||
use bitfield::bitfield;
|
||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||
|
||||
|
@ -133,7 +133,7 @@ impl Cpu {
|
|||
self.bus.clock();
|
||||
|
||||
let elapsed = match kind {
|
||||
ImeEnabled | NonePending => Cycle::new(4),
|
||||
ImeEnabled | NonePending => 4,
|
||||
SomePending => todo!("Implement HALT bug"),
|
||||
};
|
||||
|
||||
|
@ -146,11 +146,11 @@ impl Cpu {
|
|||
self.handle_ei();
|
||||
|
||||
// For use in Blargg's Test ROMs
|
||||
// if self.read_byte(0xFF02) == 0x81 {
|
||||
// let c = self.read_byte(0xFF01) as char;
|
||||
// self.write_byte(0xFF02, 0x00);
|
||||
// eprint!("{}", c);
|
||||
// }
|
||||
if self.read_byte(0xFF02) == 0x81 {
|
||||
let c = self.read_byte(0xFF01) as char;
|
||||
self.write_byte(0xFF02, 0x00);
|
||||
eprint!("{}", c);
|
||||
}
|
||||
|
||||
elapsed
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::cpu::Cpu as SM83;
|
||||
use crate::instruction::cycle::Cycle;
|
||||
use crate::joypad;
|
||||
use crate::ppu::Ppu;
|
||||
use crate::Cycle;
|
||||
use anyhow::Result;
|
||||
use gilrs::Gilrs;
|
||||
use std::time::Duration;
|
||||
use winit_input_helper::WinitInputHelper;
|
||||
|
||||
pub const SM83_CYCLE_TIME: Duration = Duration::from_nanos(1_000_000_000 / SM83_CLOCK_SPEED);
|
||||
pub const CYCLES_IN_FRAME: Cycle = Cycle::new(456 * 154); // 456 Cycles times 154 scanlines
|
||||
pub const CYCLES_IN_FRAME: Cycle = 456 * 154; // 456 Cycles times 154 scanlines
|
||||
pub(crate) const SM83_CLOCK_SPEED: u64 = 0x40_0000; // Hz which is 4.194304Mhz
|
||||
const DEFAULT_TITLE: &str = "DMG-01 Emulator";
|
||||
|
||||
|
@ -34,7 +34,7 @@ pub fn run(
|
|||
input: &WinitInputHelper,
|
||||
target: Cycle,
|
||||
) -> Cycle {
|
||||
let mut elapsed = Cycle::new(0);
|
||||
let mut elapsed = 0;
|
||||
|
||||
if let Some(event) = gamepad.next_event() {
|
||||
joypad::handle_gamepad_input(game_boy.joypad_mut(), event);
|
||||
|
@ -49,7 +49,7 @@ pub fn run(
|
|||
}
|
||||
|
||||
pub fn run_frame(game_boy: &mut SM83, gamepad: &mut Gilrs, input: &WinitInputHelper) -> Cycle {
|
||||
let mut elapsed = Cycle::new(0);
|
||||
let mut elapsed = 0;
|
||||
|
||||
if let Some(event) = gamepad.next_event() {
|
||||
joypad::handle_gamepad_input(game_boy.joypad_mut(), event);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
pub use apu::gen::AudioSPSC;
|
||||
pub use instruction::cycle::Cycle;
|
||||
pub type Cycle = u64;
|
||||
|
||||
pub const GB_WIDTH: usize = 160;
|
||||
pub const GB_HEIGHT: usize = 144;
|
||||
|
|
|
@ -11,7 +11,7 @@ use winit::window::{Window, WindowBuilder};
|
|||
use winit_input_helper::WinitInputHelper;
|
||||
|
||||
const WINDOW_SCALE: usize = 3;
|
||||
const AUDIO_ENABLED: bool = true;
|
||||
const AUDIO_ENABLED: bool = false;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let app = App::new(crate_name!())
|
||||
|
|
14
src/ppu.rs
14
src/ppu.rs
|
@ -1,5 +1,5 @@
|
|||
use crate::bus::BusIo;
|
||||
use crate::instruction::cycle::Cycle;
|
||||
use crate::Cycle;
|
||||
use crate::GB_HEIGHT;
|
||||
use crate::GB_WIDTH;
|
||||
use dma::DirectMemoryAccess;
|
||||
|
@ -79,7 +79,7 @@ impl Ppu {
|
|||
|
||||
match self.stat.mode() {
|
||||
PpuMode::OamScan => {
|
||||
if self.cycle >= 80.into() {
|
||||
if self.cycle >= 80 {
|
||||
self.stat.set_mode(PpuMode::Drawing);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ impl Ppu {
|
|||
PpuMode::Drawing => {
|
||||
if self.ctrl.lcd_enabled() {
|
||||
// Only Draw when the LCD Is Enabled
|
||||
self.draw(self.cycle.into());
|
||||
self.draw(self.cycle);
|
||||
} else {
|
||||
self.reset();
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ impl Ppu {
|
|||
PpuMode::HBlank => {
|
||||
// This mode will always end at 456 cycles
|
||||
|
||||
if self.cycle >= 456.into() {
|
||||
if self.cycle >= 456 {
|
||||
self.cycle %= 456;
|
||||
self.pos.line_y += 1;
|
||||
|
||||
|
@ -167,7 +167,7 @@ impl Ppu {
|
|||
}
|
||||
}
|
||||
PpuMode::VBlank => {
|
||||
if self.cycle > 456.into() {
|
||||
if self.cycle > 456 {
|
||||
self.cycle %= 456;
|
||||
self.pos.line_y += 1;
|
||||
|
||||
|
@ -228,7 +228,7 @@ impl Ppu {
|
|||
self.scan_state.next();
|
||||
}
|
||||
|
||||
fn draw(&mut self, _cycle: u32) {
|
||||
fn draw(&mut self, _cycle: Cycle) {
|
||||
use FetcherState::*;
|
||||
|
||||
let mut iter = self.obj_buffer.iter_mut();
|
||||
|
@ -470,7 +470,7 @@ impl Default for Ppu {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
vram: Box::new([0u8; VRAM_SIZE]),
|
||||
cycle: Cycle::new(0),
|
||||
cycle: Default::default(),
|
||||
frame_buf: Box::new([0; GB_WIDTH * GB_HEIGHT * 4]),
|
||||
int: Default::default(),
|
||||
ctrl: Default::default(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::instruction::cycle::Cycle;
|
||||
use crate::Cycle;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct DirectMemoryAccess {
|
||||
|
@ -56,7 +56,7 @@ impl DirectMemoryAccess {
|
|||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.cycle = Cycle::new(0);
|
||||
self.cycle = 0;
|
||||
self.state = DmaState::Disabled;
|
||||
self.start.0 = None;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
use crate::Cycle;
|
||||
use std::collections::BinaryHeap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Scheduler {
|
||||
timestamp: Cycle,
|
||||
queue: BinaryHeap<Event>,
|
||||
}
|
||||
|
||||
impl Scheduler {
|
||||
pub(crate) fn init() -> Self {
|
||||
let mut scheduler = Self {
|
||||
timestamp: Default::default(),
|
||||
queue: Default::default(),
|
||||
};
|
||||
|
||||
scheduler.push(Event {
|
||||
kind: EventKind::TimestampOverflow,
|
||||
timestamp: Cycle::MAX,
|
||||
cb: |_delay| panic!("Reached Cycle::MAX"),
|
||||
});
|
||||
|
||||
scheduler
|
||||
}
|
||||
|
||||
pub(crate) fn push(&mut self, event: Event) {
|
||||
self.queue.push(event);
|
||||
}
|
||||
|
||||
pub(crate) fn step(&mut self, cycles: Cycle) {
|
||||
self.timestamp += cycles;
|
||||
|
||||
loop {
|
||||
let should_pop = match self.queue.peek() {
|
||||
Some(event) => self.timestamp >= event.timestamp,
|
||||
None => false,
|
||||
};
|
||||
|
||||
if !should_pop {
|
||||
break;
|
||||
}
|
||||
|
||||
let event = self.queue.pop().expect("Pop Event from Scheduler Queue");
|
||||
|
||||
(event.cb)(self.timestamp - event.timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Event {
|
||||
kind: EventKind,
|
||||
cb: fn(Cycle),
|
||||
pub(crate) timestamp: Cycle,
|
||||
}
|
||||
|
||||
impl Eq for Event {}
|
||||
impl PartialEq for Event {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.kind == other.kind && self.timestamp == other.timestamp
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Event {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Event {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.timestamp.cmp(&other.timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum EventKind {
|
||||
TimestampOverflow,
|
||||
}
|
Loading…
Reference in New Issue