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