From eebb5b61f489261739d7da55ca64c28bdf193034 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Sun, 10 Dec 2023 14:52:14 -0500 Subject: [PATCH] More GPU boilerplate --- src/cpu.rs | 4 ++-- src/gpu.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++--- src/main.rs | 22 ++++++++++++---------- src/mmu.rs | 7 ++++--- src/mode.rs | 1 + 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index c98fc06..5ca2887 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -4,7 +4,7 @@ use crate::registers::{Registers, Flags}; pub struct CPU { reg: Registers, - mem: MMU, + pub mem: MMU, halted: bool, // Enabled Interrupts ei: bool @@ -14,7 +14,7 @@ impl CPU { pub fn new(mode: GBMode, rom: Vec) -> Self { Self { reg: Registers::new(mode), - mem: MMU::new(rom), + mem: MMU::new(mode, rom), halted: false, ei: true } diff --git a/src/gpu.rs b/src/gpu.rs index 79285ae..1d92f45 100644 --- a/src/gpu.rs +++ b/src/gpu.rs @@ -1,9 +1,11 @@ use bitflags::{bitflags, Flags}; +use crate::mode::GBMode; pub const SCREEN_W: usize = 160; pub const SCREEN_H: usize = 144; pub struct GPU { + mode: GBMode, sy: u8, sx: u8, ly: u8, @@ -12,7 +14,8 @@ pub struct GPU { wx: u8, lcdc: LCDC, lcds: LCDS, - ram: [u8; 0x4000] + ram: [u8; 0x4000], + frame_buffer: [[[u8; 3]; SCREEN_W]; SCREEN_H] } bitflags! { @@ -52,8 +55,9 @@ bitflags! { } } impl GPU { - pub fn new() -> Self { + pub fn new(mode: GBMode) -> Self { Self { + mode, sy: 0, sx: 0, ly: 0, @@ -62,10 +66,47 @@ impl GPU { wx: 0, lcdc: LCDC::empty(), lcds: LCDS::empty(), - ram: [0; 0x4000] + ram: [0; 0x4000], + frame_buffer: [[[0; 3]; SCREEN_W]; SCREEN_H] } } + pub fn cycle(&mut self) { + self.draw_bg(); + } + + fn grey_to_l(v: u8, i: usize) -> u8 { + match v >> (2 * i) & 0x03 { + 0x00 => 0xFF, + 0x01 => 0xFC, + 0x02 => 0x60, + _ => 0x00 + } + } + + fn set_rgb(&mut self, x: usize, r: u8, g: u8, b: u8) { + // TODO: Color mapping from CGB -> sRGB + self.frame_buffer[self.ly as usize][x] = [r, g, b]; + } + + fn draw_bg(&mut self) { + for x in 0..SCREEN_W { + if self.mode == GBMode::Color { + let r = 0; + let g = 0; + let b = 0; + self.set_rgb(x, r, g, b); + } else { + let lightness = Self::grey_to_l(0, 0); + self.set_rgb(x, lightness, lightness, lightness); + } + } + } + + fn draw_sprites(&mut self) { + + } + pub fn read(&self, a: u16) -> u8 { match a { 0xFF40 => self.lcdc.bits(), diff --git a/src/main.rs b/src/main.rs index 0c965e8..3ba5581 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,16 @@ async fn main() -> Result<(), impl std::error::Error> { let game_name = std::str::from_utf8(&name_data[0..index]).expect("Failed to get game name!"); println!("Starting \"{game_name}\"..."); + let event_loop = EventLoop::new().unwrap(); + + let window = WindowBuilder::new() + .with_title(format!("gb-rs - {:}", game_name)) + .with_inner_size(winit::dpi::LogicalSize::new(160, 144)) + .build(&event_loop) + .unwrap(); + + let mut context = Context::new(window).await; + let buffer_copy = buffer.clone(); // Start CPU tokio::spawn(async move { @@ -51,20 +61,12 @@ async fn main() -> Result<(), impl std::error::Error> { while true { let cycles = cpu.cycle(); + cpu.mem.gpu.cycle(); + sleep(Duration::from_millis((1000_f64 / 4_194_304_f64 * cycles as f64) as u64)).await; } }); - let event_loop = EventLoop::new().unwrap(); - - let window = WindowBuilder::new() - .with_title(format!("gb-rs - {:}", game_name)) - .with_inner_size(winit::dpi::LogicalSize::new(160, 144)) - .build(&event_loop) - .unwrap(); - - let mut context = Context::new(window).await; - let mut modifiers = ModifiersState::default(); event_loop.run(move |event, elwt| { diff --git a/src/mmu.rs b/src/mmu.rs index a1e1645..6768224 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,8 +1,9 @@ use crate::gpu::GPU; +use crate::mode::GBMode; pub struct MMU { rom: Vec, - gpu: GPU, + pub gpu: GPU, wram: [u8; 0x8000], hram: [u8; 0x7F], interrupt: u8, @@ -10,10 +11,10 @@ pub struct MMU { } impl MMU { - pub fn new(rom: Vec) -> Self { + pub fn new(mode: GBMode, rom: Vec) -> Self { Self { rom, - gpu: GPU::new(), + gpu: GPU::new(mode), wram: [0; 0x8000], hram: [0; 0x7f], interrupt: 0, diff --git a/src/mode.rs b/src/mode.rs index 00de0a3..478db7a 100644 --- a/src/mode.rs +++ b/src/mode.rs @@ -1,3 +1,4 @@ +#[derive(Clone, Copy, PartialEq)] pub enum GBMode { Classic, Color,