Skip to content

Commit

Permalink
Avoid extra framebuffer copies
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacMarovitz committed Apr 30, 2024
1 parent f218646 commit 0c8afc7
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 39 deletions.
7 changes: 5 additions & 2 deletions src/components/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::io::Read;
use std::process;
use crate::config::Config;
use crate::components::prelude::*;
use crate::Framebuffer;

pub struct CPU {
pub reg: Registers,
Expand All @@ -16,7 +17,9 @@ pub struct CPU {
unsafe impl Send for CPU {}

impl CPU {
pub fn new(rom: Vec<u8>, config: Config) -> Self {
pub fn new(rom: Vec<u8>,
config: Config,
framebuffer: Framebuffer) -> Self {
let mut boot_rom: [u8; 0x900] = [0; 0x900];
let booting: bool = match config.boot_rom {
Some(ref path) => {
Expand Down Expand Up @@ -45,7 +48,7 @@ impl CPU {

Self {
reg: Registers::new(config.clone().mode, booting),
mem: MMU::new(rom, config, booting, boot_rom),
mem: MMU::new(rom, config, booting, boot_rom, framebuffer),
halted: false,
ime: false,
ime_ask: false
Expand Down
15 changes: 9 additions & 6 deletions src/components/mmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::components::prelude::*;
use crate::config::Config;
use crate::mbc::prelude::*;
use crate::sound::apu::APU;
use crate::Framebuffer;
use bitflags::bitflags;
use num_traits::FromPrimitive;

Expand Down Expand Up @@ -34,7 +35,11 @@ bitflags! {
}

impl MMU {
pub fn new(rom: Vec<u8>, config: Config, booting: bool, boot_rom: [u8; 0x900]) -> Self {
pub fn new(rom: Vec<u8>,
config: Config,
booting: bool,
boot_rom: [u8; 0x900],
framebuffer: Framebuffer) -> Self {
let cart_type: CartTypes = FromPrimitive::from_u8(rom[0x0147]).expect("Failed to get Cart Type!");
let mbc_mode = match cart_type.get_mbc() {
MBCMode::Unsupported => panic!("Unsupported Cart Type! {:}", cart_type),
Expand All @@ -56,7 +61,7 @@ impl MMU {
Self {
mbc: mbc,
apu: APU::new(),
ppu: PPU::new(config.clone()),
ppu: PPU::new(config.clone(), framebuffer),
serial: Serial::new(config.print_serial),
joypad: Joypad::new(),
timer: Timer::new(),
Expand All @@ -71,24 +76,22 @@ impl MMU {
}
}

pub fn cycle(&mut self, cycles: u32) -> bool {
pub fn cycle(&mut self, cycles: u32) {
self.timer.cycle(cycles);
self.intf |= self.timer.interrupts;
self.timer.interrupts = Interrupts::empty();

self.intf |= self.joypad.interrupts;
self.joypad.interrupts = Interrupts::empty();

let did_draw = self.ppu.cycle(cycles);
self.ppu.cycle(cycles);
self.intf |= self.ppu.interrupts;
self.ppu.interrupts = Interrupts::empty();

self.apu.cycle(self.timer.div);

self.intf |= self.serial.interrupts;
self.serial.interrupts = Interrupts::empty();

did_draw
}

fn oamdma(&mut self, value: u8) {
Expand Down
32 changes: 14 additions & 18 deletions src/components/ppu.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::components::prelude::*;
use crate::config::{Color, Config, Palette};
use crate::Framebuffer;
use bitflags::bitflags;

pub const SCREEN_W: usize = 160;
Expand Down Expand Up @@ -33,7 +34,7 @@ pub struct PPU {
opri: bool,
bgprio: [Priority; SCREEN_W],
pub interrupts: Interrupts,
pub frame_buffer: Vec<u8>,
pub framebuffer: Framebuffer,
}

#[derive(PartialEq, Copy, Clone)]
Expand Down Expand Up @@ -130,7 +131,7 @@ impl BGPI {
}

impl PPU {
pub fn new(config: Config) -> Self {
pub fn new(config: Config, framebuffer: Framebuffer) -> Self {
Self {
mode: config.mode,
palette: config.palette,
Expand Down Expand Up @@ -159,13 +160,13 @@ impl PPU {
opri: true,
bgprio: [Priority::Normal; SCREEN_W],
interrupts: Interrupts::empty(),
frame_buffer: vec![0x00; 4 * SCREEN_W * SCREEN_H],
framebuffer,
}
}

pub fn cycle(&mut self, cycles: u32) -> bool {
pub fn cycle(&mut self, cycles: u32) {
if !self.lcdc.contains(LCDC::LCD_ENABLE) {
return false;
return
}

self.cycle_count += cycles;
Expand All @@ -178,7 +179,6 @@ impl PPU {
self.ppu_mode = PPUMode::Draw;
// println!("[PPU] Switching to Draw!");
}
false
}
PPUMode::Draw => {
// TODO: Allow variable length Mode 3
Expand All @@ -194,9 +194,6 @@ impl PPU {
self.draw_sprites();
}
// println!("[PPU] Switching to HBlank!");
false
} else {
false
}
}
PPUMode::HBlank => {
Expand All @@ -211,18 +208,15 @@ impl PPU {
if self.lcds.contains(LCDS::MODE_1_SELECT) {
self.interrupts |= Interrupts::LCD;
}
true
// println!("[PPU] Switching to VBlank!");
} else {
self.ppu_mode = PPUMode::OAMScan;
if self.lcds.contains(LCDS::MODE_2_SELECT) {
self.interrupts |= Interrupts::LCD;
}
false
// println!("[PPU] Switching to OAMScan!");
};
}
false
}
PPUMode::VBlank => {
if self.cycle_count >= 456 {
Expand All @@ -243,7 +237,6 @@ impl PPU {

self.check_lyc();
}
false
}
};
}
Expand Down Expand Up @@ -309,10 +302,11 @@ impl PPU {
let horizontal_offset = x * bytes_per_pixel;
let total_offset = vertical_offset + horizontal_offset;

self.frame_buffer[total_offset + 0] = r;
self.frame_buffer[total_offset + 1] = g;
self.frame_buffer[total_offset + 2] = b;
self.frame_buffer[total_offset + 3] = 0xFF;
let mut framebuffer = self.framebuffer.write().unwrap();
framebuffer[total_offset + 0] = r;
framebuffer[total_offset + 1] = g;
framebuffer[total_offset + 2] = b;
framebuffer[total_offset + 3] = 0xFF;
}

fn draw_bg(&mut self) {
Expand Down Expand Up @@ -615,7 +609,9 @@ impl Memory for PPU {
if !self.lcdc.contains(LCDC::LCD_ENABLE) {
self.reset_ly();
self.ppu_mode = PPUMode::HBlank;
self.frame_buffer = vec![0x00; 4 * SCREEN_W * SCREEN_H];

let mut framebuffer = self.framebuffer.write().unwrap();
*framebuffer = vec![0x00; 4 * SCREEN_W * SCREEN_H];
}
}
0xFF41 => {
Expand Down
22 changes: 9 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use winit::event_loop::EventLoop;
use winit::application::ApplicationHandler;
use winit::window::{Window, WindowId};

type Framebuffer = Arc<RwLock<Vec<u8>>>;

mod config;
mod context;
mod components;
Expand All @@ -44,7 +46,7 @@ struct App {
context: Option<Arc<Mutex<Context>>>,
config: Config,
input_tx: Sender<(JoypadButton, bool)>,
framebuffer: Arc<RwLock<Vec<u8>>>
framebuffer: Framebuffer
}

impl ApplicationHandler for App {
Expand Down Expand Up @@ -105,8 +107,8 @@ impl ApplicationHandler for App {
let context_arc = Arc::clone(&self.context.as_ref().unwrap());
let mut context = context_arc.lock().unwrap();

let framebuffer_arc = Arc::clone(&self.framebuffer);
context.update(&*framebuffer_arc.read().unwrap());
let framebuffer = Arc::clone(&self.framebuffer);
context.update(&*framebuffer.read().unwrap());

let _ = context.render();
}
Expand Down Expand Up @@ -160,19 +162,19 @@ fn main() {
event_loop.set_control_flow(ControlFlow::Poll);

let (input_tx, input_rx) = mpsc::channel::<(JoypadButton, bool)>();
let framebuffer_rw: Arc<RwLock<Vec<u8>>> = Arc::new(RwLock::new(vec![0; 4 * SCREEN_W * SCREEN_H]));
let framebuffer: Framebuffer = Arc::new(RwLock::new(vec![0; 4 * SCREEN_W * SCREEN_H]));

let mut app = App {
game_name: String::from(game_name),
context: None,
config: config.clone(),
input_tx,
framebuffer: framebuffer_rw.clone()
framebuffer: framebuffer.clone()
};

// Start CPU
thread::spawn(move || {
let mut cpu = CPU::new(buffer, config);
let mut cpu = CPU::new(buffer, config, framebuffer);
let mut step_cycles = 0;
let mut step_zero = Instant::now();

Expand Down Expand Up @@ -201,13 +203,7 @@ fn main() {

let cycles = cpu.cycle();
step_cycles += cycles;
let did_draw = cpu.mem.cycle(cycles);
if did_draw {
let framebuffer = cpu.mem.ppu.frame_buffer.clone();

let mut framebuffer_w = framebuffer_rw.write().unwrap();
*framebuffer_w = framebuffer;
}
cpu.mem.cycle(cycles);
}
});

Expand Down

0 comments on commit 0c8afc7

Please sign in to comment.