reznez 0.0.0

The high accuracy NES Emulator
Documentation
use std::fmt;

use crate::ppu::pixel_index::PixelRow;

pub const MAX_SCANLINE: u16 = 261;
pub const MAX_CYCLE: u16 = 340;

#[derive(Clone, Copy, Debug)]
pub struct Clock {
    frame: i64,
    scanline: u16,
    cycle: u16,

    total_cycles: u64,
}

impl Clock {
    pub fn mesen_compatible() -> Clock {
        Clock { frame: 0, scanline: 0, cycle: 6, total_cycles: 0 }
    }

    pub fn starting_at(frame: i64, scanline: u16, cycle: u16) -> Clock {
        Clock { frame, scanline, cycle, total_cycles: 0 }
    }

    pub fn frame(&self) -> i64 {
        self.frame
    }

    pub fn scanline(&self) -> u16 {
        self.scanline
    }

    pub fn cycle(&self) -> u16 {
        self.cycle
    }

    pub fn total_cycles(&self) -> u64 {
        self.total_cycles
    }

    pub fn scanline_pixel_row(&self) -> Option<PixelRow> {
        PixelRow::try_from_u16(self.scanline)
    }

    pub fn tick(&mut self, skip_odd_frame_cycle: bool) -> bool {
        self.total_cycles += 1;

        let max_cycle = if skip_odd_frame_cycle && self.frame % 2 == 1 {
            MAX_CYCLE - 1
        } else {
            MAX_CYCLE
        };
        let is_last_cycle_of_frame = self.scanline == MAX_SCANLINE && self.cycle >= max_cycle;
        if is_last_cycle_of_frame {
            self.frame += 1;
            self.scanline = 0;
            self.cycle = 0;
        } else if self.cycle == MAX_CYCLE {
            self.scanline += 1;
            self.cycle = 0;
        } else {
            self.cycle += 1;
        }

        is_last_cycle_of_frame
    }
}

impl fmt::Display for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "F:{},S:{:03},C:{:03}", self.frame, self.scanline, self.cycle)
    }
}