Module z80emu::macros

source ·
Expand description

Helper macros when implementing Io, Memory and Clock for wrapper types.

use z80emu::{*, host::TsCounter};

struct Ticks<T: Copy>(TsCounter<T>);

struct BusWrap<B>(B);

impl Clock for Ticks<i32> {
    forward_host_clock_types!{ @ => TsCounter<i32> }
    forward_host_clock_methods!{ @ => |c| c.0 }
}

impl<B: Io> Io for BusWrap<B> {
    forward_host_io_types!{ @ => B }
    forward_host_io_methods!{ @ => |b| b.0 }
}

impl<B: Memory> Memory for BusWrap<B> {
    forward_host_memory_types!{ @ => B }
    forward_host_memory_methods!{ @ => |b| b.0 }
}

One practical scenario is that the wrapper requires only a few methods with custom behaviour while forwarding the rest.

use core::num::NonZeroU16;
use z80emu::*;

struct DebugBus<'a, B> {
    bus: &'a mut B,
    irq_data: Option<u8>
}

// To illustrate an example with accessors:
impl<'a, B> DebugBus<'a, B> {
    fn bus_mut(&mut self) -> &mut B {
        &mut *self.bus
    }
    fn bus_ref(&self) -> &B {
        &*self.bus
    }
}

impl<B: Io> Io for DebugBus<'_, B> {
    // while we should use just this:
    // forward_host_io_types!{ @ => B }

    // here we illustrate how to forward only selected types:
    type Timestamp = <B as Io>::Timestamp;
    forward_host_io_types! { (WrIoBreak RetiBreak) => B }

    /// Capture data from an interrupting device.
    fn irq_data(&mut self, pc: u16, ts: Self::Timestamp) -> (u8, Option<NonZeroU16>) {
        let (data, delay) = self.bus.irq_data(pc, ts);
        self.irq_data = Some(data);
        (data, delay)
    }

    // forward remaining methods
    forward_host_io_methods! {
        (write_io, read_io, is_irq, reti) => |me| me.bus_mut() }

    // be carefull if you don't forward a method, a default implementation
    // will be used for that method instead
}

impl<B: Memory> Memory for DebugBus<'_, B> {
    forward_host_memory_types!{ @ => B }
    // here we can split implementations between methods that access &self:
    forward_host_memory_methods!{ @ref => |me| me.bus_ref() }
    // from methods accessing &mut self
    forward_host_memory_methods!{ @mut => |me| me.bus_mut() }
}