FrameRunner

Struct FrameRunner 

Source
pub struct FrameRunner<const EXT_CLOCK_HZ: u32, const TIME_FRAME_HZ: u32> { /* private fields */ }
Expand description

A helper for running emulated frames.

FRAME_PERIOD = 1 / TIME_FRAME_HZ

|<-        FRAME_PERIOD         ->|
t1          t2                   t3
<- emulate -><====== sleep =======>

The FrameRunner keeps track of and manages the emulated time. It holds the instance of TClock and a current frame limit.

The implementation methods running the emulation expect an instance of a Z80 emulator implementing the Cpu trait and the system bus emulator implementing Memory, Io and BusDevice traits.

  • EXT_CLOCK_HZ: an external clock frequency in hertz (NOT THE CPU CLOCK).
  • TIME_FRAME_HZ: how many frames per second the emulation will run.

Implementations§

Source§

impl<const EXT_HZ: u32, const FRAME_HZ: u32> FrameRunner<EXT_HZ, FRAME_HZ>

Source

pub fn debug_preview<C: Cpu, M>(&self, cpu: &C, bus: &M) -> CpuDebug
where M: Memory<Timestamp = Ts>,

Return a CpuDebug as a preview of the instruction to execute next.

The instruction shown will not necessarily be the one that will execute next in cases such as:

  • An IRQ can be requested before CPU fetches the instructions.
  • The memory page 0x2000 - 0x3FFF might contain the RAM page and will change the contents to the ROM page when the CPU fetches an instruction.
  • A more than one of 0xFD/0xDD prefixes in a row resides in memory at PC.
Source

pub fn debug_step<C: Cpu, M>( &mut self, cpu: &mut C, bus: &mut M, ) -> (Option<CpuDebug>, Ts)
where M: Memory<Timestamp = Ts> + Io<Timestamp = Ts> + BusDevice<Timestamp = Ts>,

Run emulation step and return a pair of an optional CpuDebug of an executed instruction and a step duration in T-states.

Returns (None, Ts) if Cpu was already halted.

Source

pub fn debug_runto_int<C: Cpu, M>( &mut self, cpu: &mut C, bus: &mut M, ) -> (Option<CpuDebug>, Ts)
where M: Memory<Timestamp = Ts> + Io<Timestamp = Ts> + BusDevice<Timestamp = Ts>,

Run emulation and stop on an IRQ request. Return a pair of an optional CpuDebug of the last instruction and a total duration in T-states.

Returns (None, Ts) if CPU was already halted and no interrupt occured or a frame has passed.

Source

pub fn debug_runto_ret<C: Cpu, M>( &mut self, cpu: &mut C, bus: &mut M, ) -> (Option<CpuDebug>, Ts)
where M: Memory<Timestamp = Ts> + Io<Timestamp = Ts> + BusDevice<Timestamp = Ts>,

Run emulation until a RET/RET cc/RETI/RETN is successfully executed. Return a pair of an optional CpuDebug of the last instruction and a total duration in T-states.

Returns (None, Ts) if a frame has passed before any RET instruction.

Source

pub fn run_until_brkpt<C: Cpu, M>( &mut self, cpu: &mut C, bus: &mut M, brkpts: &[u16], ) -> (Option<usize>, Ts)
where M: Memory<Timestamp = Ts> + Io<Timestamp = Ts> + BusDevice<Timestamp = Ts>,

Run emulation until PC equals to one of the brkpoints. Return a pair of an optional brkpoint index and a total duration in T-states.

Returns ((None, Ts)) if no brkpoints were hit and a frame has passed.

NOTE: brkpts MUST be sorted!

Source§

impl<const EXT_HZ: u32, const FRAME_HZ: u32> FrameRunner<EXT_HZ, FRAME_HZ>

Source

pub const EXT_CLOCK_HZ: u32 = EXT_HZ

The external clock frequency used by peripherals.

Source

pub const TIME_FRAME_HZ: u32 = FRAME_HZ

Emulation frames frequency.

Source

pub const FRAME_DURATION: Duration

A real-time duration of a single frame.

Source

pub const fn clock_is_valid(clock_hz: Ts) -> bool

Return whether the clock_hz is a valid CPU clock for this runner.

Source

pub fn external_clock_tstates(&self) -> u32

Return the external clock period in the number of T-states.

The external clock drives some peripherals.

Source

pub fn new(clock_hz: Ts) -> Self

Create a new runner.

clock_hz: a CPU clock in T-states per second. It must be divisible by Self::EXT_CLOCK_HZ * 2.

Panics if the clock is invalid.

Source

pub fn frame_duration() -> Duration

A real-time duration of a single running frame.

Source

pub fn start<C: Cpu, M>(&mut self, cpu: &mut C, bus: &mut M)
where M: BusDevice<Timestamp = Ts>,

Reset everything including clock and the frame limit counter.

This function should be called before very first step.

Source

pub fn step<C: Cpu, M>(&mut self, cpu: &mut C, bus: &mut M) -> Ts
where M: Memory<Timestamp = Ts> + Io<Timestamp = Ts> + BusDevice<Timestamp = Ts>,

Run the emulation for a period of a single frame and return the frame duration in emulated T-states.

Source

pub fn reset<C: Cpu, M>(&mut self, cpu: &mut C, bus: &mut M)
where M: BusDevice<Timestamp = Ts>,

Reset the cpu and bus devices.

Source

pub fn nmi<C: Cpu, M>(&mut self, cpu: &mut C, bus: &mut M) -> Option<Ts>
where M: Memory<Timestamp = Ts> + Io<Timestamp = Ts>,

Trigger a non-maskable interrupt and return a number of T-states that it took on success.

Auto Trait Implementations§

§

impl<const EXT_CLOCK_HZ: u32, const TIME_FRAME_HZ: u32> Freeze for FrameRunner<EXT_CLOCK_HZ, TIME_FRAME_HZ>

§

impl<const EXT_CLOCK_HZ: u32, const TIME_FRAME_HZ: u32> RefUnwindSafe for FrameRunner<EXT_CLOCK_HZ, TIME_FRAME_HZ>

§

impl<const EXT_CLOCK_HZ: u32, const TIME_FRAME_HZ: u32> Send for FrameRunner<EXT_CLOCK_HZ, TIME_FRAME_HZ>

§

impl<const EXT_CLOCK_HZ: u32, const TIME_FRAME_HZ: u32> Sync for FrameRunner<EXT_CLOCK_HZ, TIME_FRAME_HZ>

§

impl<const EXT_CLOCK_HZ: u32, const TIME_FRAME_HZ: u32> Unpin for FrameRunner<EXT_CLOCK_HZ, TIME_FRAME_HZ>

§

impl<const EXT_CLOCK_HZ: u32, const TIME_FRAME_HZ: u32> UnwindSafe for FrameRunner<EXT_CLOCK_HZ, TIME_FRAME_HZ>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.