feo3boy/
memdev.rs

1use std::convert::TryFrom;
2use std::ops::{Deref, DerefMut, Range};
3use std::{fmt, mem, slice};
4
5use log::trace;
6use thiserror::Error;
7
8pub use feo3boy_memdev_derive::MemDevice;
9
10use crate::apu::ApuRegs;
11use crate::input::ButtonRegister;
12use crate::interrupts::{InterruptContext, InterruptEnable, InterruptFlags, Interrupts};
13use crate::ppu::PpuRegs;
14use crate::serial::SerialRegs;
15use crate::timer::TimerRegs;
16
17pub use cartridge::{
18    Cartridge, Mbc1Rom, Mbc3Rom, ParseCartridgeError, RamBank, RomBank, RomOnly, SaveData,
19};
20
21mod cartridge;
22
23pub trait RangeOverlaps {
24    /// Returns true if this range fully encloses other.
25    fn encloses(&self, other: &Self) -> bool;
26}
27
28impl RangeOverlaps for Range<usize> {
29    fn encloses(&self, other: &Self) -> bool {
30        self.start <= other.start && self.end >= other.end
31    }
32}
33
34/// A memory address relative to a particular MemDevice. Tracks both the absolute address
35/// (for debugging purposes) and the relative address for indexing.
36#[derive(Copy, Clone, Debug)]
37pub struct RelativeAddr {
38    /// Raw address, originating from game code.
39    raw: u16,
40    /// Address relative to the start of a particular memory device.
41    relative: u16,
42}
43
44impl From<u16> for RelativeAddr {
45    /// Create a new address from a raw address. No offset is applied, so initially both the raw
46    /// and relative addresses are the same.
47    #[inline]
48    fn from(raw: u16) -> Self {
49        Self::new(raw)
50    }
51}
52
53impl RelativeAddr {
54    /// Creates a new address from the given raw value. The address is initially based at
55    /// the start of memory.
56    pub const fn new(raw: u16) -> Self {
57        RelativeAddr { raw, relative: raw }
58    }
59
60    /// Get a RelativeAddr for the first byte in the device starting at `addr`. This will
61    /// have `raw == addr` and `relative == 0`. It is equivalent to
62    /// `RelativeAddr::new(addr).offset_by(addr)`.
63    pub const fn device_start(addr: u16) -> Self {
64        RelativeAddr {
65            raw: addr,
66            relative: 0,
67        }
68    }
69
70    /// Gets the raw address that this Addr points at.
71    pub const fn raw(&self) -> u16 {
72        self.raw
73    }
74
75    /// Gets the address this Addr points at relative to the start of some unspecified device.
76    pub const fn relative(&self) -> u16 {
77        self.relative
78    }
79
80    /// Gets the address this Addr points at relative to the start of the (unspecified) device, as
81    /// a usize for convenient indexing.
82    pub const fn index(&self) -> usize {
83        self.relative as usize
84    }
85
86    /// Gets the current offset.
87    pub const fn offset(&self) -> u16 {
88        self.raw - self.relative
89    }
90
91    /// Get a range of the specified length that starts from this this address.
92    pub const fn range(&self, len: usize) -> Range<usize> {
93        self.index()..self.index() + len
94    }
95
96    /// Constructs a new address, offsetting the relative address by the specified amount.
97    /// Intended to be used to offset to the start of a child [`MemDevice`].
98    ///
99    /// Produces an address which is relative to `shift` in the current relative address
100    /// space. This is useful when passing an address to a child mem device: call
101    /// `offset_by` with the index of the start of the child relative to the parent to get
102    /// an address which indexes from the start of the child.
103    pub const fn offset_by(&self, shift: u16) -> Self {
104        assert!(
105            shift <= self.relative,
106            "Attempting to offset with overflow."
107        );
108        RelativeAddr {
109            raw: self.raw,
110            relative: self.relative - shift,
111        }
112    }
113
114    /// Skip over is the reverse of `offset_by`. It is intended to be used when you want
115    /// to bypass part of a child `MemDevice`. It produces an address which skips the
116    /// first `skipped` bytes of the current relative address space. Typical usage would
117    /// be `addr.offset_by(child_start).skip_over(num_bytes_to_skip)`.
118    pub const fn skip_over(&self, skipped: u16) -> Self {
119        RelativeAddr {
120            raw: self.raw,
121            relative: match self.relative.checked_add(skipped) {
122                Some(val) => val,
123                None => {
124                    panic!("Attempting to skip_over with overflow.")
125                }
126            },
127        }
128    }
129
130    /// Move the address forward by the specified number of bytes. This modifies both the
131    /// raw and relative addresses. Prevents wrapping in debug mode but not release.
132    pub const fn move_forward_by(&self, added: u16) -> Self {
133        RelativeAddr {
134            raw: self.raw + added,
135            relative: self.relative + added,
136        }
137    }
138
139    /// Move the address forward by the specified number of bytes. This modifies both the
140    /// raw and relative addresses.
141    pub const fn move_forward_by_wrapping(&self, added: u16) -> Self {
142        RelativeAddr {
143            raw: self.raw.wrapping_add(added),
144            relative: self.relative.wrapping_add(added),
145        }
146    }
147}
148
149impl fmt::Display for RelativeAddr {
150    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151        write!(f, "{:x}h({:x}h)", self.raw, self.relative)
152    }
153}
154
155/// Provides access to system memory.
156pub trait MemDevice {
157    /// Length of this MemDevice in bytes. Reads and writes must always be within the device.
158    const LEN: usize;
159
160    /// Read a typed value from this MemDevice. The value must be fully contained within
161    /// this device.
162    #[inline]
163    fn read_relative_into<V>(&self, addr: RelativeAddr, dest: &mut V)
164    where
165        V: MemValue,
166    {
167        struct Reader<'a, M: ?Sized> {
168            addr: RelativeAddr,
169            device: &'a M,
170        }
171        impl<'a, M: MemDevice + ?Sized> MemSource for Reader<'a, M> {
172            #[inline(always)]
173            fn get_byte(self) -> u8 {
174                self.device.read_byte_relative(self.addr)
175            }
176            #[inline(always)]
177            fn get_bytes(self, data: &mut [u8]) {
178                self.device.read_bytes_relative(self.addr, data)
179            }
180        }
181
182        dest.copy_from_mem(Reader { addr, device: self })
183    }
184
185    /// Read a typed value from this MemDevice. The value must be fully contained within
186    /// this device.
187    #[inline]
188    fn read_relative<V>(&self, addr: RelativeAddr) -> V
189    where
190        V: MemValue + Default,
191    {
192        let mut val = V::default();
193        self.read_relative_into(addr, &mut val);
194        val
195    }
196
197    /// Write a typed value into this MemDevice. The value must fit fully within the
198    /// device.
199    #[inline]
200    fn write_relative_from<V>(&mut self, addr: RelativeAddr, source: &V)
201    where
202        V: MemValue,
203    {
204        struct Writer<'a, M: ?Sized> {
205            addr: RelativeAddr,
206            device: &'a mut M,
207        }
208        impl<'a, M: MemDevice + ?Sized> MemDest for Writer<'a, M> {
209            #[inline(always)]
210            fn set_byte(self, val: u8) {
211                self.device.write_byte_relative(self.addr, val)
212            }
213            #[inline(always)]
214            fn set_bytes(self, data: &[u8]) {
215                self.device.write_bytes_relative(self.addr, data)
216            }
217        }
218
219        source.copy_to_mem(Writer { addr, device: self })
220    }
221
222    /// Write a typed value into this MemDevice. The value must fit fully within the
223    /// device.
224    #[inline]
225    fn write_relative<V>(&mut self, addr: RelativeAddr, val: V)
226    where
227        V: MemValue,
228    {
229        self.write_relative_from(addr, &val)
230    }
231
232    /// Read the byte at the specified address.
233    ///
234    /// The default implementation just calls `read_range_relative` with a single-byte
235    /// slice. A mem device may override this method if it can provide a more efficient
236    /// single-byte read.
237    #[inline]
238    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
239        let mut out = 0;
240        self.read_bytes_relative(addr, slice::from_mut(&mut out));
241        out
242    }
243
244    /// Read a range of bytes into a slice. The read bytes must not wrap past the end of
245    /// the device.
246    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]);
247
248    /// Write the byte at the sepcified address.
249    ///
250    /// The default implementation just calls `write_range_relative` with a single-byte
251    /// slice. A mem device may override this method if it can provide a more efficient
252    /// single-byte write.
253    #[inline]
254    fn write_byte_relative(&mut self, addr: RelativeAddr, data: u8) {
255        self.write_bytes_relative(addr, slice::from_ref(&data));
256    }
257
258    /// Write a range of bytes into memory from a slice. The slice must not exceed the
259    /// length of the MemDevice.
260    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]);
261}
262
263/// A [`MemDevice`] which exists at the root. Root MemDevices can read ranges that wrap
264/// around from the end of memory to the start.
265///
266/// A Root MemDevice can read data at any address. Because the device is at the root,
267/// addresses are `u16`.
268///
269/// The length of a RootMemDevice must always be 0x10000, however generic equality
270/// constraints currently prevent us from mandating that in the type signature. Once those
271/// are available, this should be changed to RootMemDevice: MemDevice<LEN = 0x10000>.
272pub trait RootMemDevice: MemDevice {
273    /// Read a typed value from this MemDevice. The value must be fully contained within
274    /// this device.
275    #[inline]
276    fn read_into<V>(&self, addr: u16, dest: &mut V)
277    where
278        V: MemValue,
279    {
280        struct Reader<'a, M: ?Sized> {
281            addr: u16,
282            device: &'a M,
283        }
284        impl<'a, M: RootMemDevice + ?Sized> MemSource for Reader<'a, M> {
285            #[inline(always)]
286            fn get_byte(self) -> u8 {
287                self.device.read_byte(self.addr)
288            }
289            #[inline(always)]
290            fn get_bytes(self, data: &mut [u8]) {
291                self.device.read_bytes(self.addr, data)
292            }
293        }
294
295        dest.copy_from_mem(Reader { addr, device: self })
296    }
297
298    /// Read a typed value from this MemDevice. The value must be fully contained within
299    /// this device.
300    #[inline]
301    fn read<V>(&self, addr: u16) -> V
302    where
303        V: MemValue + Default,
304    {
305        let mut val = V::default();
306        self.read_into(addr, &mut val);
307        val
308    }
309
310    /// Write a typed value into this MemDevice. The value must fit fully within the
311    /// device.
312    #[inline]
313    fn write_from<V>(&mut self, addr: u16, source: &V)
314    where
315        V: MemValue,
316    {
317        struct Writer<'a, M: ?Sized> {
318            addr: u16,
319            device: &'a mut M,
320        }
321        impl<'a, M: RootMemDevice + ?Sized> MemDest for Writer<'a, M> {
322            #[inline(always)]
323            fn set_byte(self, val: u8) {
324                self.device.write_byte(self.addr, val)
325            }
326            #[inline(always)]
327            fn set_bytes(self, data: &[u8]) {
328                self.device.write_bytes(self.addr, data)
329            }
330        }
331
332        source.copy_to_mem(Writer { addr, device: self })
333    }
334
335    /// Write a typed value into this MemDevice. The value must fit fully within the
336    /// device.
337    #[inline]
338    fn write<V>(&mut self, addr: u16, val: V)
339    where
340        V: MemValue,
341    {
342        self.write_from(addr, &val)
343    }
344
345    /// Read a single byte from memory.
346    #[inline]
347    fn read_byte(&self, addr: u16) -> u8 {
348        self.read_byte_relative(addr.into())
349    }
350
351    /// Read a range of bytes, wrapping at the ends of memory.
352    fn read_bytes(&self, mut addr: u16, mut data: &mut [u8]) {
353        const SIZE: usize = u16::MAX as usize + 1;
354        loop {
355            let len = SIZE - addr as usize;
356            if len < data.len() {
357                let (current, rest) = data.split_at_mut(len);
358                self.read_bytes_relative(addr.into(), current);
359                data = rest;
360                addr = 0;
361            } else {
362                self.read_bytes_relative(addr.into(), data);
363                break;
364            }
365        }
366    }
367
368    /// Write a single byte to memory.
369    #[inline]
370    fn write_byte(&mut self, addr: u16, val: u8) {
371        self.write_byte_relative(addr.into(), val);
372    }
373
374    /// Write a range of bytes, wrapping at the ends of memory.
375    fn write_bytes(&mut self, mut addr: u16, mut data: &[u8]) {
376        const SIZE: usize = u16::MAX as usize + 1;
377        loop {
378            let len = SIZE - addr as usize;
379            if len < data.len() {
380                let (current, rest) = data.split_at(len);
381                self.write_bytes_relative(addr.into(), current);
382                data = rest;
383                addr = 0;
384            } else {
385                self.write_bytes_relative(addr.into(), data);
386                break;
387            }
388        }
389    }
390}
391
392/// Helper trait for [`MemValue`] which allows it to work with both [`MemDevice`] and
393/// [`RootMemDevice`] and does not require it to know about addresses.
394///
395/// This trait represents memory in a particular MemDevice at a particular address which
396/// can be read from.
397pub trait MemSource {
398    /// Retrieve a single byte from the source address.
399    fn get_byte(self) -> u8;
400    /// Retrieve a slice of bytes from the source address.
401    fn get_bytes(self, data: &mut [u8]);
402}
403
404/// Helper trait for [`MemValue`] which allows it to work with both [`MemDevice`] and
405/// [`RootMemDevice`] and does not require it to know about addresses.
406///
407/// This trait represents memory in a particular MemDevice at a particular address which
408/// can be written to.
409pub trait MemDest {
410    /// Set a single byte at the destination address.
411    fn set_byte(self, val: u8);
412    /// Write a slice of bytes at the destination address.
413    fn set_bytes(self, data: &[u8]);
414}
415
416/// A value which can be stored in GameBoy memory.
417pub trait MemValue {
418    /// Convert this type into its in-memory representation.
419    fn copy_from_mem<S: MemSource>(&mut self, source: S);
420
421    fn copy_to_mem<D: MemDest>(&self, dest: D);
422}
423
424impl MemValue for u8 {
425    #[inline]
426    fn copy_from_mem<S: MemSource>(&mut self, source: S) {
427        *self = source.get_byte()
428    }
429
430    #[inline]
431    fn copy_to_mem<D: MemDest>(&self, dest: D) {
432        dest.set_byte(*self)
433    }
434}
435
436impl<const N: usize> MemValue for [u8; N] {
437    #[inline]
438    fn copy_from_mem<S: MemSource>(&mut self, source: S) {
439        source.get_bytes(self.as_mut())
440    }
441
442    #[inline]
443    fn copy_to_mem<D: MemDest>(&self, dest: D) {
444        dest.set_bytes(self.as_ref())
445    }
446}
447
448impl MemValue for i8 {
449    #[inline]
450    fn copy_from_mem<S: MemSource>(&mut self, source: S) {
451        *self = source.get_byte() as i8
452    }
453
454    #[inline]
455    fn copy_to_mem<D: MemDest>(&self, dest: D) {
456        dest.set_byte(*self as u8)
457    }
458}
459
460impl MemValue for u16 {
461    #[inline]
462    fn copy_from_mem<S: MemSource>(&mut self, source: S) {
463        let mut bytes = [0u8; 2];
464        source.get_bytes(bytes.as_mut());
465        *self = u16::from_le_bytes(bytes);
466    }
467
468    #[inline]
469    fn copy_to_mem<D: MemDest>(&self, dest: D) {
470        let bytes = self.to_le_bytes();
471        dest.set_bytes(bytes.as_ref());
472    }
473}
474
475/// Context trait for accessing memory.
476pub trait MemContext {
477    /// Type of MemDevice in this context.
478    type Mem: RootMemDevice;
479
480    /// Gets the memory.
481    fn mem(&self) -> &Self::Mem;
482
483    /// Get a mutable reference to the memory.
484    fn mem_mut(&mut self) -> &mut Self::Mem;
485}
486
487/// Makes a `MemDevice` into a `RootMemDevice` by treating all bytes past its end behave
488/// as a `NullRom`.
489#[derive(Debug, Clone, Eq, PartialEq)]
490#[repr(transparent)]
491pub struct RootExtend<M>(M);
492
493impl<M> RootExtend<M> {
494    /// Performs reference-to-reference conversion from any `MemDevice` to `RootExtend`.
495    #[inline]
496    pub fn wrap_ref<'a>(m: &'a M) -> &'a Self {
497        // RootExtend has the same memory representation (`repr(transparent)`) as `M` so
498        // it is safe to transmute the reference with the same lifetime while preserving
499        // mutability.
500        unsafe { mem::transmute(m) }
501    }
502
503    /// Performs reference-to-reference conversion from any `MemDevice` to `RootExtend`.
504    #[inline]
505    pub fn wrap_mut<'a>(m: &'a mut M) -> &'a mut Self {
506        // RootExtend has the same memory representation (`repr(transparent)`) as `M` so
507        // it is safe to transmute the reference with the same lifetime while preserving
508        // mutability.
509        unsafe { mem::transmute(m) }
510    }
511}
512
513impl<M: MemDevice> MemDevice for RootExtend<M> {
514    const LEN: usize = u16::MAX as usize + 1;
515
516    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
517        assert!(
518            addr.relative() == addr.raw(),
519            "Using RootExtend with offset address {}",
520            addr
521        );
522        if addr.index() < M::LEN {
523            self.0.read_byte_relative(addr)
524        } else {
525            check_addr!(RootExtend<M>, addr);
526            0xff
527        }
528    }
529
530    fn read_bytes_relative(&self, addr: RelativeAddr, mut data: &mut [u8]) {
531        assert!(
532            addr.relative() == addr.raw(),
533            "Using RootExtend with offset address {}",
534            addr
535        );
536        check_addr!(RootExtend<M>, addr, data.len());
537        if addr.index() < M::LEN {
538            let num_read = (M::LEN - addr.index()).min(data.len());
539            self.0.read_bytes_relative(addr, &mut data[..num_read]);
540            data = &mut data[num_read..];
541        }
542        // Fill any bytes not covered by the actuall data with 0xff. check_addr ensures
543        // all of data is in range, so we just fill it.
544        data.fill(0xff);
545    }
546
547    fn write_byte_relative(&mut self, addr: RelativeAddr, data: u8) {
548        assert!(
549            addr.relative() == addr.raw(),
550            "Using RootExtend with offset address {}",
551            addr
552        );
553        if addr.index() < M::LEN {
554            self.0.write_byte_relative(addr, data)
555        } else {
556            check_addr!(RootExtend<M>, addr);
557        }
558    }
559
560    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
561        assert!(
562            addr.relative() == addr.raw(),
563            "Using RootExtend with offset address {}",
564            addr
565        );
566        check_addr!(RootExtend<M>, addr, data.len());
567        if addr.index() < M::LEN {
568            let num_written = (M::LEN - addr.index()).min(data.len());
569            self.0.write_bytes_relative(addr, &data[..num_written]);
570        }
571    }
572}
573
574impl<M: MemDevice> RootMemDevice for RootExtend<M> {}
575
576/// Wraps a memory device to make it read-only.
577#[repr(transparent)]
578#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
579pub struct ReadOnly<M>(M);
580
581impl<M> Deref for ReadOnly<M> {
582    type Target = M;
583
584    fn deref(&self) -> &Self::Target {
585        &self.0
586    }
587}
588
589impl<M> ReadOnly<M> {
590    /// Constructs a ReadOnly memory device that wraps the given underlying memory.
591    pub fn new(mem: M) -> Self {
592        Self(mem)
593    }
594
595    /// Unwraps the inner memory device and returns it. This allows mutable access again.
596    pub fn into_inner(self) -> M {
597        self.0
598    }
599}
600
601impl<M: MemDevice> MemDevice for ReadOnly<M> {
602    const LEN: usize = M::LEN;
603
604    #[inline]
605    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]) {
606        self.0.read_bytes_relative(addr, data);
607    }
608
609    #[inline]
610    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
611        self.0.read_byte_relative(addr)
612    }
613
614    #[inline]
615    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
616        check_addr!(ReadOnly<M>, addr, data.len());
617    }
618
619    #[inline]
620    fn write_byte_relative(&mut self, addr: RelativeAddr, _data: u8) {
621        check_addr!(ReadOnly<M>, addr);
622    }
623}
624
625impl<M: RootMemDevice> RootMemDevice for ReadOnly<M> {
626    fn read_byte(&self, addr: u16) -> u8 {
627        self.0.read_byte(addr)
628    }
629
630    fn read_bytes(&self, addr: u16, data: &mut [u8]) {
631        self.0.read_bytes(addr, data)
632    }
633
634    fn write_byte(&mut self, _addr: u16, _val: u8) {}
635
636    fn write_bytes(&mut self, _addr: u16, _data: &[u8]) {}
637}
638
639/// A rom which does bounds checks, but contains no actual memory (always returns 0xff,
640/// ignores writes).
641pub struct NullRom<const N: usize>;
642
643impl<const N: usize> MemDevice for NullRom<N> {
644    const LEN: usize = N;
645
646    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]) {
647        check_addr!(NullRom<N>, addr, data.len());
648        data.fill(0xff);
649    }
650
651    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
652        check_addr!(NullRom<N>, addr, data.len());
653    }
654}
655
656const BIOS_LEN: usize = 0x100;
657
658/// Rom for the bios, which is swapped out once started.
659#[repr(transparent)]
660#[derive(Copy, Clone, Debug, Eq, PartialEq, MemDevice)]
661#[memdev(passthrough)]
662pub struct BiosRom(ReadOnly<[u8; BIOS_LEN]>);
663
664impl BiosRom {
665    /// Construct a `BiosRom` from an array of 256 bytes. Does not validate the contents.
666    pub fn new(data: [u8; BIOS_LEN]) -> Self {
667        Self(ReadOnly::new(data))
668    }
669
670    /// Constructs a `BiosRom` from a slice of contained bytes. The slice must be exactly 256
671    /// bytes. No other validation of the contents is performed.
672    // TryFrom/TryInto aren't standard imports, so provide a convenience method that doesn't
673    // require a TryFrom/TryInto import for the caller.
674    pub fn try_from_slice(data: &[u8]) -> Result<Self, BiosSizeError> {
675        Self::try_from(data)
676    }
677}
678
679impl Deref for BiosRom {
680    type Target = [u8];
681
682    fn deref(&self) -> &Self::Target {
683        self.0.as_ref()
684    }
685}
686
687impl Default for BiosRom {
688    fn default() -> Self {
689        Self(ReadOnly::new([0; BIOS_LEN]))
690    }
691}
692
693/// Error when converting a slice to a [`BiosRom`]. Contains the number of bytes of the given
694/// slice.
695#[derive(Copy, Clone, Debug, Error)]
696#[error("Expected exactly 256 bytes, got {0}")]
697pub struct BiosSizeError(pub usize);
698
699impl TryFrom<&[u8]> for BiosRom {
700    type Error = BiosSizeError;
701
702    fn try_from(data: &[u8]) -> Result<Self, BiosSizeError> {
703        if data.len() != BIOS_LEN {
704            Err(BiosSizeError(data.len()))
705        } else {
706            let mut arr = [0; BIOS_LEN];
707            arr.copy_from_slice(data);
708            Ok(Self(ReadOnly::new(arr)))
709        }
710    }
711}
712
713impl TryFrom<Vec<u8>> for BiosRom {
714    type Error = BiosSizeError;
715
716    fn try_from(data: Vec<u8>) -> Result<Self, BiosSizeError> {
717        Self::try_from(&*data)
718    }
719}
720
721/// Memory Device for the bios-enable bit.
722#[derive(Debug, Clone, Eq, PartialEq, MemDevice)]
723#[memdev(byte, read = Self::get_byte, write = Self::set_byte)]
724pub struct BiosEnable(bool);
725
726impl BiosEnable {
727    /// Return true if bios is enabled.
728    pub fn enabled(&self) -> bool {
729        self.0
730    }
731
732    fn get_byte(&self) -> u8 {
733        self.0 as u8
734    }
735
736    fn set_byte(&mut self, data: u8) {
737        // If value is false, stay false. If passed a non-zero value, become false.
738        self.0 = self.0 && data == 0;
739    }
740}
741
742impl Default for BiosEnable {
743    fn default() -> Self {
744        Self(true)
745    }
746}
747
748impl<const N: usize> MemDevice for [u8; N] {
749    const LEN: usize = N;
750
751    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
752        match self.get(addr.index()) {
753            Some(val) => *val,
754            None => panic!("Address {}  out of range for {} byte memory array", addr, N),
755        }
756    }
757
758    fn write_byte_relative(&mut self, addr: RelativeAddr, value: u8) {
759        match self.get_mut(addr.index()) {
760            Some(val) => *val = value,
761            None => panic!("Address {}  out of range for {} byte memory array", addr, N),
762        }
763    }
764
765    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]) {
766        match self.get(addr.range(data.len())) {
767            Some(vals) => data.copy_from_slice(vals),
768            None => panic!(
769                "Address {} + {} byte slice out of range for {} byte memory array",
770                addr,
771                data.len(),
772                N
773            ),
774        }
775    }
776
777    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
778        match self.get_mut(addr.range(data.len())) {
779            Some(vals) => vals.copy_from_slice(data),
780            None => panic!(
781                "Address {} + {} byte slice out of range for {} byte memory array",
782                addr,
783                data.len(),
784                N
785            ),
786        }
787    }
788}
789
790impl RootMemDevice for [u8; 0x10000] {
791    fn read_byte(&self, addr: u16) -> u8 {
792        self[addr as usize]
793    }
794
795    fn write_byte(&mut self, addr: u16, val: u8) {
796        self[addr as usize] = val;
797    }
798}
799
800/// Workaround for the implementation of Default for arrays being so janky
801/// Separated from main MemDevice interface in case arrays get const defaults later
802pub trait CustomDefault {
803    fn custom_default() -> Self;
804}
805
806impl<const N: usize> CustomDefault for [u8; N] {
807    fn custom_default() -> Self {
808        [0; N]
809    }
810}
811
812#[derive(Clone, Default, Debug, PartialEq, Eq)]
813pub struct MaskableMem<M> {
814    device: M,
815    masked: bool,
816}
817
818impl<M: CustomDefault> MaskableMem<M> {
819    pub fn new() -> Self {
820        MaskableMem::custom_default()
821    }
822}
823
824impl<M> MaskableMem<M> {
825    pub fn mask(&mut self) {
826        self.masked = true;
827    }
828
829    pub fn unmask(&mut self) {
830        self.masked = false;
831    }
832
833    /// Bypass masking to access the inner memory directly.
834    pub fn bypass(&self) -> &M {
835        &self.device
836    }
837
838    /// Bypass masking to access the inner memory directly.
839    pub fn bypass_mut(&mut self) -> &mut M {
840        &mut self.device
841    }
842}
843
844impl<M: CustomDefault> CustomDefault for MaskableMem<M> {
845    fn custom_default() -> Self {
846        MaskableMem {
847            device: M::custom_default(),
848            masked: false,
849        }
850    }
851}
852
853impl<M: MemDevice> MemDevice for MaskableMem<M> {
854    const LEN: usize = M::LEN;
855
856    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
857        if !self.masked {
858            self.device.read_byte_relative(addr)
859        } else {
860            check_addr!(MaskableMem<M>, addr);
861            0xff
862        }
863    }
864
865    fn write_byte_relative(&mut self, addr: RelativeAddr, value: u8) {
866        if !self.masked {
867            self.device.write_byte_relative(addr, value)
868        } else {
869            check_addr!(MaskableMem<M>, addr);
870        }
871    }
872
873    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]) {
874        if !self.masked {
875            self.device.read_bytes_relative(addr, data)
876        } else {
877            check_addr!(MaskableMem<M>, addr, data.len());
878            data.fill(0xff);
879        }
880    }
881
882    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
883        if !self.masked {
884            self.device.write_bytes_relative(addr, data)
885        } else {
886            check_addr!(MaskableMem<M>, addr, data.len());
887        }
888    }
889}
890
891impl<M: RootMemDevice> RootMemDevice for MaskableMem<M> {}
892
893impl<M> Deref for MaskableMem<M> {
894    type Target = M;
895    fn deref(&self) -> &Self::Target {
896        &self.device
897    }
898}
899
900impl<M> DerefMut for MaskableMem<M> {
901    fn deref_mut(&mut self) -> &mut Self::Target {
902        &mut self.device
903    }
904}
905
906/// A u8 acts as a single-byte memory device.
907impl MemDevice for u8 {
908    const LEN: usize = 1;
909
910    #[inline]
911    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
912        check_addr!(u8, addr);
913        *self
914    }
915
916    #[inline]
917    fn write_byte_relative(&mut self, addr: RelativeAddr, val: u8) {
918        check_addr!(u8, addr);
919        *self = val;
920    }
921
922    #[inline]
923    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]) {
924        check_addr!(u8, addr, data.len());
925        match data.first_mut() {
926            Some(out) => *out = *self,
927            None => {}
928        }
929    }
930
931    #[inline]
932    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
933        check_addr!(u8, addr, data.len());
934        match data.first() {
935            Some(val) => *self = *val,
936            None => {}
937        }
938    }
939}
940
941// This makes sure that Box<dyn MemDevice> implements MemDevice (as well as Box<Anything that
942// implements MemDevice>).
943impl<D: MemDevice> MemDevice for Box<D> {
944    const LEN: usize = D::LEN;
945
946    #[inline]
947    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
948        (**self).read_byte_relative(addr)
949    }
950
951    #[inline]
952    fn write_byte_relative(&mut self, addr: RelativeAddr, value: u8) {
953        (**self).write_byte_relative(addr, value)
954    }
955
956    #[inline]
957    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]) {
958        (**self).read_bytes_relative(addr, data)
959    }
960
961    #[inline]
962    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
963        (**self).write_bytes_relative(addr, data)
964    }
965}
966
967impl<D: RootMemDevice> RootMemDevice for Box<D> {
968    #[inline]
969    fn read_byte(&self, addr: u16) -> u8 {
970        (**self).read_byte(addr)
971    }
972
973    #[inline]
974    fn read_bytes(&self, addr: u16, data: &mut [u8]) {
975        (**self).read_bytes(addr, data)
976    }
977
978    #[inline]
979    fn write_byte(&mut self, addr: u16, data: u8) {
980        (**self).write_byte(addr, data)
981    }
982
983    #[inline]
984    fn write_bytes(&mut self, addr: u16, data: &[u8]) {
985        (**self).write_bytes(addr, data)
986    }
987}
988
989/// Memory device connecting memory mapped IO.
990#[derive(Clone, Default, Debug, PartialEq, Eq)]
991pub struct MemMappedIo {
992    pub buttons: ButtonRegister,
993    /// Registers used by the serial subsystem.
994    pub serial_regs: SerialRegs,
995    /// Registers used by the timer.
996    pub timer_regs: TimerRegs,
997    /// Set of active interrupts.
998    pub interrupt_flags: InterruptFlags,
999    /// apu status and settings
1000    pub apu_regs: ApuRegs,
1001    /// ppu status and settings
1002    pub ppu_regs: PpuRegs,
1003    pub bios_enable: BiosEnable,
1004}
1005
1006impl MemMappedIo {
1007    /// Construct new memory-mapped IO manager.
1008    pub fn new() -> Self {
1009        Default::default()
1010    }
1011}
1012
1013memdev_fields!(MemMappedIo, len: 0x80, {
1014    0x00 => buttons,
1015    0x01..=0x02 => serial_regs,
1016    0x03 => 0xff,
1017    0x04..=0x07 => timer_regs,
1018    0x08..=0x0e => 0xff,
1019    0x0f => interrupt_flags,
1020    0x10..=0x3f => apu_regs,
1021    0x40..=0x4b => ppu_regs,
1022    0x4c..=0x4f => 0xff,
1023    0x50 => bios_enable,
1024    0x51..=0x7f => 0xff,
1025});
1026
1027pub type Vram = MaskableMem<MaskableMem<[u8; 0x2000]>>;
1028pub type Oam = MaskableMem<MaskableMem<[u8; 160]>>;
1029
1030/// Simple memory device that consists of just 0x10000 bytes treated all as ram. This
1031/// MemDevice is primarily intended for use in tests. The only difference between this and
1032/// `Box<[u8; 0x10000]>` is that it provides convenient From implementations for
1033/// converting from slices and arrays of arbitrary numbers of bytes, which is convenient
1034/// for testing.
1035#[derive(Debug, MemDevice)]
1036#[memdev(passthrough)]
1037pub struct AllRam(Box<[u8; 0x10000]>);
1038
1039impl RootMemDevice for AllRam {
1040    #[inline]
1041    fn read_byte(&self, addr: u16) -> u8 {
1042        self.0.read_byte(addr)
1043    }
1044
1045    #[inline]
1046    fn read_bytes(&self, addr: u16, data: &mut [u8]) {
1047        self.0.read_bytes(addr, data)
1048    }
1049
1050    #[inline]
1051    fn write_byte(&mut self, addr: u16, val: u8) {
1052        self.0.write_byte(addr, val);
1053    }
1054
1055    #[inline]
1056    fn write_bytes(&mut self, addr: u16, data: &[u8]) {
1057        self.0.write_bytes(addr, data)
1058    }
1059}
1060
1061impl From<&[u8]> for AllRam {
1062    /// Creates an AllRam with initial data set by copying from a byte slice.
1063    fn from(bytes: &[u8]) -> Self {
1064        assert!(bytes.len() <= 0x10000);
1065        let mut ram = Box::new([0; 0x10000]);
1066        ram[..bytes.len()].copy_from_slice(bytes);
1067        Self(ram)
1068    }
1069}
1070
1071impl<const N: usize> From<&[u8; N]> for AllRam {
1072    /// Creates an AllRam with initial data set by copying from an array of any size less
1073    /// than 0x10000.
1074    fn from(bytes: &[u8; N]) -> Self {
1075        (&bytes[..]).into()
1076    }
1077}
1078
1079/// MemoryDevice which configures the standard memory mapping of the real GameBoy.
1080#[derive(Clone, Debug, Eq, PartialEq)]
1081pub struct GbMmu {
1082    /// The bios. Mapped to 0..0x100 while bios is enabled.
1083    pub bios: BiosRom,
1084    /// The inserted cartridge. Mapped to 0..0x8000 (rom) and 0xA000..0xC000 (ram).
1085    pub cart: Cartridge,
1086    /// Video Ram. Mapped to 0x8000..0xA000
1087    pub vram: Vram,
1088    /// Working Ram. Mapped to 0xC000..0xE000 and duplicately mapped at 0xE000..0xFE00.
1089    pub wram: [u8; 0x2000],
1090    /// Spirte info. Mapped to 0xFE00..0xFEA0.
1091    pub oam: Oam,
1092    /// Memory mapped IO. Mapped to 0xff00..FF80.
1093    // TODO: don't require this to be exposed directly (use traits like for interrupts).
1094    pub io: MemMappedIo,
1095    /// "Page Zero", memory primarily used for software-hardware interaction. Mapped to
1096    /// 0xFF80..0xffff
1097    pub zram: [u8; 127],
1098    /// Interrupt enable register. Mapped to 0xffff
1099    pub interrupt_enable: InterruptEnable,
1100}
1101
1102impl GbMmu {
1103    /// Construct a new MMU with the given bios and cartridge.
1104    /// Panics if the given bios data is not exactly 256 bytes.
1105    pub fn new(bios: BiosRom, cart: Cartridge) -> GbMmu {
1106        GbMmu {
1107            bios,
1108            cart,
1109            vram: Vram::new(),
1110            wram: [0; 0x2000],
1111            oam: Oam::new(),
1112            io: MemMappedIo::new(),
1113            zram: [0; 127],
1114            interrupt_enable: InterruptEnable(InterruptFlags::empty()),
1115        }
1116    }
1117}
1118
1119impl Default for GbMmu {
1120    fn default() -> Self {
1121        Self::new(Default::default(), Cartridge::None)
1122    }
1123}
1124
1125impl MemDevice for GbMmu {
1126    const LEN: usize = u16::MAX as usize + 1;
1127
1128    fn read_byte_relative(&self, addr: RelativeAddr) -> u8 {
1129        assert!(
1130            addr.relative() == addr.raw(),
1131            "Using Root MMU with offset address {}",
1132            addr
1133        );
1134        trace!("Read from MMU address {:#x}", addr.raw);
1135        dispatch_memdev_byte!(GbMmu, addr, |addr| {
1136            0x0..=0xff if self.io.bios_enable.enabled() => self.bios.read_byte_relative(addr),
1137            0x0..=0x7fff => self.cart.read_byte_relative(addr),
1138            0x8000..=0x9fff => self.vram.read_byte_relative(addr),
1139            // Cartridge ram uses the same device as cartridge rom, so skip over the
1140            // number of bytes in Cart ROM when reading from Cart RAM.
1141            0xa000..=0xbfff => self.cart.read_byte_relative(addr.skip_over(0x8000)),
1142            0xc000..=0xdfff => self.wram.read_byte_relative(addr),
1143            0xe000..=0xfdff => self.wram.read_byte_relative(addr),
1144            0xfe00..=0xfe9f => self.oam.read_byte_relative(addr),
1145            // Unmapped portion above sprite information, always returns 0xff.
1146            0xfea0..=0xfeff => 0xff,
1147            0xff00..=0xff7f => self.io.read_byte_relative(addr),
1148            0xff80..=0xfffe => self.zram.read_byte_relative(addr),
1149            0xffff => self.interrupt_enable.read_byte_relative(addr),
1150        })
1151    }
1152
1153    fn read_bytes_relative(&self, addr: RelativeAddr, data: &mut [u8]) {
1154        assert!(
1155            addr.relative() == addr.raw(),
1156            "Using Root MMU with offset address {}",
1157            addr
1158        );
1159        trace!("Read {} bytes from MMU address {:#x}", data.len(), addr.raw);
1160        dispatch_memdev_bytes!(GbMmu, addr, data, |addr, mut data| {
1161            0x0..=0xff if self.io.bios_enable.enabled() => self.bios.read_bytes_relative(addr, data),
1162            0x0..=0x7fff => self.cart.read_bytes_relative(addr, data),
1163            0x8000..=0x9fff => self.vram.read_bytes_relative(addr, data),
1164            // Cartridge ram uses the same device as cartridge rom, so skip over the
1165            // number of bytes in Cart ROM when reading from Cart RAM.
1166            0xa000..=0xbfff => self.cart.read_bytes_relative(addr.skip_over(0x8000), data),
1167            0xc000..=0xdfff => self.wram.read_bytes_relative(addr, data),
1168            0xe000..=0xfdff => self.wram.read_bytes_relative(addr, data),
1169            0xfe00..=0xfe9f => self.oam.read_bytes_relative(addr, data),
1170            // Unmapped portion above sprite information, always returns 0xff.
1171            0xfea0..=0xfeff => data.fill(0xff),
1172            0xff00..=0xff7f => self.io.read_bytes_relative(addr, data),
1173            0xff80..=0xfffe => self.zram.read_bytes_relative(addr, data),
1174            0xffff => self.interrupt_enable.read_bytes_relative(addr, data),
1175        });
1176    }
1177
1178    fn write_byte_relative(&mut self, addr: RelativeAddr, value: u8) {
1179        assert!(
1180            addr.relative() == addr.raw(),
1181            "Using Root MMU with offset address {}",
1182            addr
1183        );
1184        trace!("Write at MMU address {:#x}", addr.raw);
1185        // Address guaranteed to be in range since we cover the whole memory space.
1186        dispatch_memdev_byte!(GbMmu, addr, |addr| {
1187            0x0..=0xff if self.io.bios_enable.enabled() => self.bios.write_byte_relative(addr, value),
1188            0x0..=0x7fff => self.cart.write_byte_relative(addr, value),
1189            0x8000..=0x9fff => self.vram.write_byte_relative(addr, value),
1190            // Cartridge ram uses the same device as cartridge rom, so skip over the
1191            // number of bytes in Cart ROM when reading from Cart RAM.
1192            0xa000..=0xbfff => self.cart.write_byte_relative(addr.skip_over(0x8000), value),
1193            0xc000..=0xdfff => self.wram.write_byte_relative(addr, value),
1194            0xe000..=0xfdff => self.wram.write_byte_relative(addr, value),
1195            0xfe00..=0xfe9f => self.oam.write_byte_relative(addr, value),
1196            // Unmapped portion above sprite information.
1197            0xfea0..=0xfeff => (),
1198            0xff00..=0xff7f => self.io.write_byte_relative(addr, value),
1199            0xff80..=0xfffe => self.zram.write_byte_relative(addr, value),
1200            0xffff => self.interrupt_enable.write_byte_relative(addr, value),
1201        })
1202    }
1203
1204    fn write_bytes_relative(&mut self, addr: RelativeAddr, data: &[u8]) {
1205        assert!(
1206            addr.relative() == addr.raw(),
1207            "Using Root MMU with offset address {}",
1208            addr
1209        );
1210        trace!("Write {} bytes at MMU address {:#x}", data.len(), addr.raw);
1211        dispatch_memdev_bytes!(GbMmu, addr, data, |addr, ref data| {
1212            0x0..=0xff if self.io.bios_enable.enabled() => self.bios.write_bytes_relative(addr, data),
1213            0x0..=0x7fff => self.cart.write_bytes_relative(addr, data),
1214            0x8000..=0x9fff => self.vram.write_bytes_relative(addr, data),
1215            // Cartridge ram uses the same device as cartridge rom, so skip over the
1216            // number of bytes in Cart ROM when reading from Cart RAM.
1217            0xa000..=0xbfff => self.cart.write_bytes_relative(addr.skip_over(0x8000), data),
1218            0xc000..=0xdfff => self.wram.write_bytes_relative(addr, data),
1219            0xe000..=0xfdff => self.wram.write_bytes_relative(addr, data),
1220            0xfe00..=0xfe9f => self.oam.write_bytes_relative(addr, data),
1221            // Unmapped portion above sprite information, always returns 0.
1222            0xfea0..=0xfeff => {},
1223            0xff00..=0xff7f => self.io.write_bytes_relative(addr, data),
1224            0xff80..=0xfffe => self.zram.write_bytes_relative(addr, data),
1225            0xffff => self.interrupt_enable.write_bytes_relative(addr, data),
1226        });
1227    }
1228}
1229
1230impl RootMemDevice for GbMmu {}
1231
1232impl MemContext for GbMmu {
1233    type Mem = Self;
1234
1235    fn mem(&self) -> &Self::Mem {
1236        self
1237    }
1238
1239    fn mem_mut(&mut self) -> &mut Self::Mem {
1240        self
1241    }
1242}
1243
1244impl InterruptContext for GbMmu {
1245    type Interrupts = Self;
1246
1247    fn interrupts(&self) -> &Self::Interrupts {
1248        self
1249    }
1250
1251    fn interrupts_mut(&mut self) -> &mut Self::Interrupts {
1252        self
1253    }
1254}
1255
1256impl Interrupts for GbMmu {
1257    #[inline]
1258    fn queued(&self) -> InterruptFlags {
1259        self.io.interrupt_flags
1260    }
1261
1262    #[inline]
1263    fn set_queued(&mut self, flags: InterruptFlags) {
1264        self.io.interrupt_flags = flags;
1265    }
1266
1267    #[inline]
1268    fn enabled(&self) -> InterruptFlags {
1269        self.interrupt_enable.0
1270    }
1271
1272    #[inline]
1273    fn set_enabled(&mut self, flags: InterruptFlags) {
1274        self.interrupt_enable.0 = flags;
1275    }
1276}
1277
1278#[cfg(test)]
1279mod tests {
1280    use super::*;
1281
1282    use rand::distributions::Uniform;
1283    use rand::{Rng, SeedableRng};
1284    use rand_pcg::Pcg64Mcg;
1285
1286    fn init() {
1287        let _ = env_logger::builder().is_test(true).try_init();
1288    }
1289
1290    #[test]
1291    fn mmu_range_readwrite() {
1292        init();
1293
1294        let mut bios = BiosRom::new([0u8; 0x100]);
1295        for (i, byte) in bios.0 .0.iter_mut().enumerate() {
1296            *byte = i as u8;
1297        }
1298        let mut mmu_individual = GbMmu::new(bios, Cartridge::None);
1299        let mut mmu_slice = GbMmu::new(bios, Cartridge::None);
1300
1301        let mut input_buf = vec![];
1302        let mut output_buf_individual = vec![];
1303        let mut output_buf_slice = vec![];
1304        let mut rng =
1305            Pcg64Mcg::from_seed([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF]);
1306
1307        let len_dist = Uniform::new_inclusive(1, 0x400);
1308
1309        assert_eq!(mmu_individual, mmu_slice);
1310
1311        for _ in 0..0x80000 {
1312            let addr: u16 = rng.gen();
1313            let len = rng.sample(&len_dist);
1314            input_buf.resize(len, 0u8);
1315            rng.fill(&mut input_buf[..]);
1316
1317            for (i, &val) in input_buf.iter().enumerate() {
1318                mmu_individual.write_byte(addr.wrapping_add(i as u16), val);
1319            }
1320            mmu_slice.write_bytes(addr, &input_buf);
1321
1322            output_buf_individual.resize(len, 0u8);
1323            for (i, res) in output_buf_individual.iter_mut().enumerate() {
1324                *res = mmu_individual.read_byte(addr.wrapping_add(i as u16));
1325            }
1326            output_buf_slice.resize(len, 0u8);
1327            mmu_slice.read_bytes(addr, &mut output_buf_slice);
1328
1329            assert_eq!(output_buf_individual, output_buf_slice);
1330        }
1331
1332        // To reduce the test runtime, only compare the final result.
1333        assert_eq!(mmu_individual, mmu_slice);
1334    }
1335}