From 1be6a7f0eebaf67d63b062427bbcc61e579fe827 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sun, 3 Mar 2024 19:39:39 +0000
Subject: [PATCH] chore: implementation of the `BusComponent`

More standard support for the `BusComponent` interface.
---
 src/apu.rs    | 12 +++++++++++-
 src/dma.rs    | 11 +++++++++++
 src/mmu.rs    | 15 +++++++++++++++
 src/pad.rs    | 12 +++++++++++-
 src/ppu.rs    | 11 +++++++++++
 src/rom.rs    | 13 ++++++++++++-
 src/serial.rs | 12 +++++++++++-
 src/timer.rs  | 11 +++++++++++
 8 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/src/apu.rs b/src/apu.rs
index 711e8115..030299b0 100644
--- a/src/apu.rs
+++ b/src/apu.rs
@@ -1,6 +1,6 @@
 use std::collections::VecDeque;
 
-use crate::{gb::GameBoy, warnln};
+use crate::{gb::GameBoy, mmu::BusComponent, warnln};
 
 const DUTY_TABLE: [[u8; 8]; 4] = [
     [0, 0, 0, 0, 0, 0, 0, 1],
@@ -1076,6 +1076,16 @@ impl Apu {
     }
 }
 
+impl BusComponent for Apu {
+    fn read(&mut self, addr: u16) -> u8 {
+        self.read(addr)
+    }
+
+    fn write(&mut self, addr: u16, value: u8) {
+        self.write(addr, value);
+    }
+}
+
 impl Default for Apu {
     fn default() -> Self {
         Self::new(44100, 2, 1.0, GameBoy::CPU_FREQ)
diff --git a/src/dma.rs b/src/dma.rs
index f3110d26..634cfa30 100644
--- a/src/dma.rs
+++ b/src/dma.rs
@@ -1,5 +1,6 @@
 use crate::{
     consts::{DMA_ADDR, HDMA1_ADDR, HDMA2_ADDR, HDMA3_ADDR, HDMA4_ADDR, HDMA5_ADDR},
+    mmu::BusComponent,
     warnln,
 };
 
@@ -173,6 +174,16 @@ impl Dma {
     }
 }
 
+impl BusComponent for Dma {
+    fn read(&mut self, addr: u16) -> u8 {
+        self.read(addr)
+    }
+
+    fn write(&mut self, addr: u16, value: u8) {
+        self.write(addr, value);
+    }
+}
+
 impl Default for Dma {
     fn default() -> Self {
         Self::new()
diff --git a/src/mmu.rs b/src/mmu.rs
index 3a7c5edf..350abcf7 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -21,6 +21,21 @@ pub const BOOT_SIZE_CGB: usize = 2304;
 pub const RAM_SIZE_DMG: usize = 8192;
 pub const RAM_SIZE_CGB: usize = 32768;
 
+pub trait BusComponent {
+    fn read(&mut self, addr: u16) -> u8;
+    fn write(&mut self, addr: u16, value: u8);
+    fn read_many(&mut self, addr: u16, count: usize) -> Vec<u8> {
+        (0..count)
+            .map(|offset| self.read(addr + offset as u16))
+            .collect()
+    }
+    fn write_many(&mut self, addr: u16, values: &[u8]) {
+        for (offset, &value) in values.iter().enumerate() {
+            self.write(addr + offset as u16, value);
+        }
+    }
+}
+
 pub struct Mmu {
     /// Register that controls the interrupts that are considered
     /// to be enabled and should be triggered.
diff --git a/src/pad.rs b/src/pad.rs
index be3a94b6..37cb34fc 100644
--- a/src/pad.rs
+++ b/src/pad.rs
@@ -1,6 +1,6 @@
 //! Gamepad related functions and structures.
 
-use crate::warnln;
+use crate::{mmu::BusComponent, warnln};
 
 #[cfg(feature = "wasm")]
 use wasm_bindgen::prelude::*;
@@ -167,6 +167,16 @@ impl Pad {
     }
 }
 
+impl BusComponent for Pad {
+    fn read(&mut self, addr: u16) -> u8 {
+        self.read(addr)
+    }
+
+    fn write(&mut self, addr: u16, value: u8) {
+        self.write(addr, value);
+    }
+}
+
 impl Default for Pad {
     fn default() -> Self {
         Self::new()
diff --git a/src/ppu.rs b/src/ppu.rs
index 196618bd..bd1d06b1 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -11,6 +11,7 @@ use std::{
 
 use crate::{
     gb::{GameBoyConfig, GameBoyMode},
+    mmu::BusComponent,
     util::SharedThread,
     warnln,
 };
@@ -2091,6 +2092,16 @@ impl Ppu {
     }
 }
 
+impl BusComponent for Ppu {
+    fn read(&mut self, addr: u16) -> u8 {
+        self.read(addr)
+    }
+
+    fn write(&mut self, addr: u16, value: u8) {
+        self.write(addr, value);
+    }
+}
+
 impl Default for Ppu {
     fn default() -> Self {
         Self::new(
diff --git a/src/rom.rs b/src/rom.rs
index c5fb6c86..541ef6a1 100644
--- a/src/rom.rs
+++ b/src/rom.rs
@@ -10,6 +10,7 @@ use crate::{
     debugln,
     error::Error,
     gb::GameBoyMode,
+    mmu::BusComponent,
     util::read_file,
     warnln,
 };
@@ -370,7 +371,7 @@ impl Cartridge {
         Self::from_data(&data)
     }
 
-    pub fn read(&self, addr: u16) -> u8 {
+    pub fn read(&mut self, addr: u16) -> u8 {
         match addr & 0xf000 {
             0x0000 | 0x1000 | 0x2000 | 0x3000 | 0x4000 | 0x5000 | 0x6000 | 0x7000 => {
                 (self.handler.read_rom)(self, addr)
@@ -823,6 +824,16 @@ impl Cartridge {
     }
 }
 
+impl BusComponent for Cartridge {
+    fn read(&mut self, addr: u16) -> u8 {
+        self.read(addr)
+    }
+
+    fn write(&mut self, addr: u16, value: u8) {
+        self.write(addr, value);
+    }
+}
+
 impl Default for Cartridge {
     fn default() -> Self {
         Self::new()
diff --git a/src/serial.rs b/src/serial.rs
index 4147e1b1..786e63ad 100644
--- a/src/serial.rs
+++ b/src/serial.rs
@@ -1,4 +1,4 @@
-use crate::warnln;
+use crate::{mmu::BusComponent, warnln};
 
 pub trait SerialDevice {
     /// Sends a byte (u8) to the attached serial connection.
@@ -202,6 +202,16 @@ impl Serial {
     }
 }
 
+impl BusComponent for Serial {
+    fn read(&mut self, addr: u16) -> u8 {
+        self.read(addr)
+    }
+
+    fn write(&mut self, addr: u16, value: u8) {
+        self.write(addr, value);
+    }
+}
+
 impl Default for Serial {
     fn default() -> Self {
         Self::new()
diff --git a/src/timer.rs b/src/timer.rs
index 057cdeb9..311c4370 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -1,5 +1,6 @@
 use crate::{
     consts::{DIV_ADDR, TAC_ADDR, TIMA_ADDR, TMA_ADDR},
+    mmu::BusComponent,
     warnln,
 };
 
@@ -147,6 +148,16 @@ impl Timer {
     }
 }
 
+impl BusComponent for Timer {
+    fn read(&mut self, addr: u16) -> u8 {
+        self.read(addr)
+    }
+
+    fn write(&mut self, addr: u16, value: u8) {
+        self.write(addr, value);
+    }
+}
+
 impl Default for Timer {
     fn default() -> Self {
         Self::new()
-- 
GitLab