From 1c99b69a12007802410cc15d0ee7ead4ec0233af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sat, 2 Jul 2022 09:35:42 +0100
Subject: [PATCH] feat: better MMu code structure

---
 examples/sdl/src/main.rs |  1 +
 src/gb.rs                | 12 ++++++++++-
 src/mmu.rs               | 28 +++++++++++++++-----------
 src/ppu.rs               | 43 ++++++++++++++++++++--------------------
 4 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/examples/sdl/src/main.rs b/examples/sdl/src/main.rs
index 98732d67..011e83f9 100644
--- a/examples/sdl/src/main.rs
+++ b/examples/sdl/src/main.rs
@@ -75,6 +75,7 @@ fn main() {
 
     let mut game_boy = GameBoy::new();
     game_boy.load_boot_default();
+    game_boy.load_rom("C:/Users/joamag/Desktop/tetris.gb");
 
     let mut counter = 0;
 
diff --git a/src/gb.rs b/src/gb.rs
index 3494c3f3..f1ae2ce1 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -1,4 +1,9 @@
-use crate::{cpu::Cpu, mmu::Mmu, ppu::{Ppu, FRAME_BUFFER_SIZE}, util::read_file};
+use crate::{
+    cpu::Cpu,
+    mmu::Mmu,
+    ppu::{Ppu, FRAME_BUFFER_SIZE},
+    util::read_file,
+};
 
 pub struct GameBoy {
     cpu: Cpu,
@@ -42,6 +47,11 @@ impl GameBoy {
         &(self.ppu().frame_buffer)
     }
 
+    pub fn load_rom(&mut self, path: &str) {
+        let data = read_file(path);
+        self.cpu.mmu().write_rom(0x0000, &data);
+    }
+
     pub fn load_boot(&mut self, path: &str) {
         let data = read_file(path);
         self.cpu.mmu().write_boot(0x0000, &data);
diff --git a/src/mmu.rs b/src/mmu.rs
index 3dcec160..beb8b3dd 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -32,7 +32,7 @@ impl Mmu {
 
     pub fn read(&mut self, addr: u16) -> u8 {
         match addr & 0xf000 {
-            // BIOS
+            // BOOT (256 B) + ROM0 (4 KB/16 KB)
             0x0000 => {
                 // in case the boot mode is active and the
                 // address is withing boot memory reads from it
@@ -47,21 +47,21 @@ impl Mmu {
                 }
                 self.rom[addr as usize]
             }
-            // ROM0
+            // ROM0 (12 KB/16 KB)
             0x1000 | 0x2000 | 0x3000 => self.rom[addr as usize],
-            // ROM1 (unbanked) (16k)
+            // ROM1 (unbanked) (16 KB)
             0x4000 | 0x5000 | 0x6000 | 0x7000 => self.rom[addr as usize],
-            // Graphics: VRAM (8k)
+            // Graphics: VRAM (8 KB)
             0x8000 | 0x9000 => {
                 println!("READING FROM VRAM");
                 self.ppu.vram[(addr & 0x1fff) as usize]
             }
-            // External RAM (8k)
+            // External RAM (8 KB)
             0xa000 | 0xb000 => {
                 println!("READING FROM ERAM");
                 self.eram[(addr & 0x1fff) as usize]
             }
-            // Working RAM (8k)
+            // Working RAM (8 KB)
             0xc000 | 0xd000 => self.ram[(addr & 0x1fff) as usize],
             // Working RAM shadow
             0xe000 => {
@@ -97,30 +97,30 @@ impl Mmu {
 
     pub fn write(&mut self, addr: u16, value: u8) {
         match addr & 0xf000 {
-            // BOOT
+            // BOOT (256 B) + ROM0 (4 KB/16 KB)
             0x0000 => {
                 println!("WRITING to BOOT")
             }
-            // ROM0
+            // ROM0 (12 KB/16 KB)
             0x1000 | 0x2000 | 0x3000 => {
                 println!("WRITING TO ROM 0");
             }
-            // ROM1 (unbanked) (16k)
+            // ROM1 (unbanked) (16 KB)
             0x4000 | 0x5000 | 0x6000 | 0x7000 => {
                 println!("WRITING TO ROM 1");
             }
-            // Graphics: VRAM (8k)
+            // Graphics: VRAM (8 KB)
             0x8000 | 0x9000 => {
                 self.ppu.vram[(addr & 0x1fff) as usize] = value;
                 if addr < 0x9800 {
                     self.ppu.update_tile(addr, value);
                 }
             }
-            // External RAM (8k)
+            // External RAM (8 KB)
             0xa000 | 0xb000 => {
                 println!("WRITING TO ERAM");
             }
-            // Working RAM (8k)
+            // Working RAM (8 KB)
             0xc000 | 0xd000 => {
                 println!("WRITING TO RAM");
                 self.ram[(addr & 0x1fff) as usize] = value;
@@ -166,4 +166,8 @@ impl Mmu {
     pub fn write_ram(&mut self, addr: u16, buffer: &[u8]) {
         self.ram[addr as usize..addr as usize + buffer.len()].clone_from_slice(buffer);
     }
+
+    pub fn write_rom(&mut self, addr: u16, buffer: &[u8]) {
+        self.rom[addr as usize..addr as usize + buffer.len()].clone_from_slice(buffer);
+    }
 }
diff --git a/src/ppu.rs b/src/ppu.rs
index c43f0546..250b1d5e 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -163,7 +163,7 @@ impl Ppu {
         match addr & 0x00ff {
             0x0040 => {
                 self.switch_bg = value & 0x01 == 0x01;
-                self.bg_map = value & 0x08 == 0x08;
+                self.bg_map = value & 0x08 == 0x08; // @todo o buf pode estar aqui
                 self.bg_tile = value & 0x10 == 0x10;
                 self.switch_lcd = value & 0x80 == 0x80;
             }
@@ -196,12 +196,8 @@ impl Ppu {
 
         for x in 0..8 {
             mask = 1 << (7 - x);
-            self.tiles[tile_index][y][x] =
-                if self.vram[addr] & mask > 0 {
-                    0x1
-                } else {
-                    0x0
-                } | if self.vram[addr + 1] & mask > 0 {
+            self.tiles[tile_index][y][x] = if self.vram[addr] & mask > 0 { 0x1 } else { 0x0 }
+                | if self.vram[addr + 1] & mask > 0 {
                     0x2
                 } else {
                     0x0
@@ -217,6 +213,7 @@ impl Ppu {
         // shifted by 3 meaning as the tiles are 8x8
         let mut line_offset: usize = (self.scx >> 3) as usize;
 
+        // calculates both the current Y and X positions within the tiles
         let y = ((self.scy + self.line) & 0x07) as usize;
         let mut x = (self.scx & 0x07) as usize;
 
@@ -233,6 +230,23 @@ impl Ppu {
         let mut frame_offset = self.line as usize * DISPLAY_WIDTH * RGB_SIZE;
 
         for _index in 0..DISPLAY_WIDTH {
+            // obtains the current pixel data from the tile and
+            // re-maps it according to the current palette
+            let pixel = self.tiles[tile_index][y][x];
+            let color = self.palette[pixel as usize];
+
+            // set the color pixel in the frame buffer
+            self.frame_buffer[frame_offset] = color[0];
+            self.frame_buffer[frame_offset + 1] = color[1];
+            self.frame_buffer[frame_offset + 2] = color[2];
+
+            // increments the offset of the frame buffer by the
+            // size of an RGB pixel (which is 3 bytes)
+            frame_offset += RGB_SIZE;
+
+            // increments the current tile X position in drawing
+            x += 1;
+
             // in case the end of tile width has been reached then
             // a new tile must be retrieved for plotting
             if x == 8 {
@@ -251,21 +265,6 @@ impl Ppu {
                     tile_index += 256;
                 }
             }
-
-            // obtains the current pixel data from the tile and
-            // re-maps it according to the current palette
-            let pixel = self.tiles[tile_index][y][x];
-            let color = self.palette[pixel as usize];
-
-            // set the color pixel in the frame buffer
-            self.frame_buffer[frame_offset] = color[0];
-            self.frame_buffer[frame_offset + 1] = color[1];
-            self.frame_buffer[frame_offset + 2] = color[2];
-
-            frame_offset += RGB_SIZE;
-
-            // increments the current tile X position in drawing
-            x += 1;
         }
     }
 }
-- 
GitLab