Fix tests and more PPU optimizations

This commit is contained in:
Franco Colmenarez 2021-11-17 10:12:11 -05:00
parent dc7d06cefc
commit 5493eb5690
3 changed files with 23 additions and 20 deletions

View File

@ -37,11 +37,12 @@ pub struct Bus {
impl Bus { impl Bus {
pub fn new() -> Self { pub fn new() -> Self {
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
#[cfg(not(test))]
if args.len() < 2 { if args.len() < 2 {
println!("Please, specify a ROM file"); println!("Please, specify a ROM file");
std::process::exit(1); std::process::exit(1);
} }
let game_rom = match load_rom(&args[1]) { let game_rom = match load_rom(&args.get(1).unwrap_or(&"".to_string())) {
Ok(rom) => rom, Ok(rom) => rom,
Err(err) => { Err(err) => {
println!("Could not read ROM: {}", err); println!("Could not read ROM: {}", err);

View File

@ -909,7 +909,7 @@ impl CPU {
} }
pub fn handle_interrupt(&mut self, bus: &mut Bus, interrupt: Interrupt) { pub fn handle_interrupt(&mut self, bus: &mut Bus, interrupt: Interrupt) {
println!("Interrupt: {:?}", interrupt); // println!("Interrupt: {:?}", interrupt);
bus.set_interrupt_flag(interrupt, false); bus.set_interrupt_flag(interrupt, false);
self.ime = false; self.ime = false;
self.registers.decrement(Register::PC, 3); self.registers.decrement(Register::PC, 3);

View File

@ -207,12 +207,15 @@ pub struct PPU {
state: bool, state: bool,
vblank_request: bool, vblank_request: bool,
lcdstat_request: bool, lcdstat_request: bool,
background_priority: bool,
window_enable: bool,
lcd_enable: bool,
cycles: Cycles, cycles: Cycles,
sprite_buffer: Vec<Sprite>, sprite_buffer: Vec<Sprite>,
window_y_counter: u8, window_y_counter: u8,
last_bg_index: u8, last_bg_index: u8,
bg_palette: u8, bg_palette: u8,
lcd_control_cache: Option<u8>, lcd_control: u8,
current_background_pixels: Option<[u8; 8]>, current_background_pixels: Option<[u8; 8]>,
current_window_pixels: Option<[u8; 8]>, current_window_pixels: Option<[u8; 8]>,
lcd_y: u8, lcd_y: u8,
@ -231,12 +234,15 @@ impl PPU {
state: false, state: false,
vblank_request: false, vblank_request: false,
lcdstat_request: false, lcdstat_request: false,
background_priority: false,
window_enable: false,
lcd_enable: false,
cycles: Cycles(0), cycles: Cycles(0),
sprite_buffer: Vec::new(), sprite_buffer: Vec::new(),
window_y_counter: 0, window_y_counter: 0,
last_bg_index: 0, last_bg_index: 0,
bg_palette: 0, bg_palette: 0,
lcd_control_cache: None, lcd_control: 0,
current_background_pixels: None, current_background_pixels: None,
current_window_pixels: None, current_window_pixels: None,
lcd_y: 0, lcd_y: 0,
@ -287,6 +293,9 @@ impl PPU {
} }
pub fn get_register(&self, address: u16) -> u8 { pub fn get_register(&self, address: u16) -> u8 {
if address == LCD_CONTROL_ADDRESS {
return self.lcd_control;
}
self.io_registers[(address - 0xFF40) as usize] self.io_registers[(address - 0xFF40) as usize]
} }
@ -294,10 +303,10 @@ impl PPU {
if address == LCD_Y_ADDRESS { if address == LCD_Y_ADDRESS {
return; return;
} else if address == LCD_CONTROL_ADDRESS { } else if address == LCD_CONTROL_ADDRESS {
let address = address - 0xFF40; self.lcd_control = data;
self.io_registers[address as usize] = data;
// Check if LCD is being turned on or off // Check if LCD is being turned on or off
if (get_bit(data, BitIndex::I7) && !get_bit(self.io_registers[address as usize], BitIndex::I7)) || self.lcd_enable = get_bit(data, BitIndex::I7);
if (get_bit(data, BitIndex::I7) && !get_bit(self.lcd_control, BitIndex::I7)) ||
!get_bit(data, BitIndex::I7) !get_bit(data, BitIndex::I7)
{ {
self.io_registers[LCD_Y_ADDRESS as usize - 0xFF40] = 0x00; self.io_registers[LCD_Y_ADDRESS as usize - 0xFF40] = 0x00;
@ -328,8 +337,7 @@ impl PPU {
} }
pub fn do_cycles(&mut self, cycles: Cycles, frame_buffer: &mut [u8]) { pub fn do_cycles(&mut self, cycles: Cycles, frame_buffer: &mut [u8]) {
self.lcd_control_cache = None; if !self.lcd_enable {
if !self.get_lcd_control(LCDControl::LCDEnable) {
self.increment_cycles(cycles); self.increment_cycles(cycles);
return; return;
} }
@ -347,6 +355,8 @@ impl PPU {
self.scroll_y = self.get_register(SCROLL_Y_ADDRESS); self.scroll_y = self.get_register(SCROLL_Y_ADDRESS);
self.window_x = self.get_register(WINDOW_X_ADDRESS); self.window_x = self.get_register(WINDOW_X_ADDRESS);
self.window_y = self.get_register(WINDOW_Y_ADDRESS); self.window_y = self.get_register(WINDOW_Y_ADDRESS);
self.window_enable = self.get_lcd_control(LCDControl::WindowEnable);
self.background_priority = self.get_lcd_control(LCDControl::BackgroundPriority);
self.set_lcd_status(LCDStatus::ModeFlag(LCDStatusModeFlag::TransferringToLCD), true); self.set_lcd_status(LCDStatus::ModeFlag(LCDStatusModeFlag::TransferringToLCD), true);
self.draw_line(frame_buffer); self.draw_line(frame_buffer);
} else if self.cycles.0 > 80 + 172 && self.cycles.0 <= 80 + 172 + 204 && !self.get_lcd_status(LCDStatus::ModeFlag(LCDStatusModeFlag::HBlank)) { } else if self.cycles.0 > 80 + 172 && self.cycles.0 <= 80 + 172 + 204 && !self.get_lcd_status(LCDStatus::ModeFlag(LCDStatusModeFlag::HBlank)) {
@ -477,15 +487,7 @@ impl PPU {
} }
pub fn get_lcd_control(&mut self, control: LCDControl) -> bool { pub fn get_lcd_control(&mut self, control: LCDControl) -> bool {
let byte = match self.lcd_control_cache { control.get(self.lcd_control)
Some(byte) => byte,
None => {
let byte = self.get_register(LCD_CONTROL_ADDRESS);
self.lcd_control_cache = Some(byte);
byte
},
};
control.get(byte)
} }
pub fn get_lcd_status(&self, status: LCDStatus) -> bool { pub fn get_lcd_status(&self, status: LCDStatus) -> bool {
@ -542,7 +544,7 @@ impl PPU {
} }
fn get_window_pixel(&mut self, lcd_x: u8) -> Option<Pixel> { fn get_window_pixel(&mut self, lcd_x: u8) -> Option<Pixel> {
if !self.get_lcd_control(LCDControl::WindowEnable) { if !self.window_enable {
return None; return None;
} }
@ -591,7 +593,7 @@ impl PPU {
} }
fn get_background_pixel(&mut self, lcd_x: u8) -> Option<Pixel> { fn get_background_pixel(&mut self, lcd_x: u8) -> Option<Pixel> {
if !self.get_lcd_control(LCDControl::BackgroundPriority) { if !self.background_priority {
return None; return None;
} }
let lcd_y = self.lcd_y; let lcd_y = self.lcd_y;