diff --git a/src/bus.rs b/src/bus.rs index cc2d21c..4a8d536 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -78,7 +78,7 @@ impl Bus { }; let mut data = [0x00; 0x10000]; // Hardware registers after the bootrom - data[0xFF00] = 0b11001111; + data[0xFF00] = 0xCF; data[0xFF01] = 0x00; data[0xFF02] = 0x7E; data[0xFF04] = 0x18; @@ -111,6 +111,9 @@ impl Bus { if BANK_ZERO.in_range(address) || BANK_SWITCHABLE.in_range(address) { return self.game_rom.read(address); } + if address == JOYPAD_ADDRESS { + println!("{:08b}", self.data[address as usize]); + } self.data[address as usize] } @@ -142,6 +145,8 @@ impl Bus { } else if address == JOYPAD_ADDRESS { let byte = self.data[JOYPAD_ADDRESS as usize]; self.data[JOYPAD_ADDRESS as usize] = (data & 0b11110000) | (byte & 0b00001111); + } else if address == LCD_Y_ADDRESS { + println!("Write to LCD_Y not allowed"); } else { self.data[address as usize] = data; } diff --git a/src/emulator.rs b/src/emulator.rs index 747f97b..7cbcd1b 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -101,14 +101,7 @@ impl Emulator { } } - pub fn draw(&mut self, frame: &mut [u8]) { - let ppu_frame = self.ppu.get_rgba_frame(); - for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { - pixel.copy_from_slice(&ppu_frame[i]); - } - } - - pub fn run(&mut self, cpu_cycles: Cycles) { + pub fn run(&mut self, cpu_cycles: Cycles, frame_buffer: &mut [u8]) { self.cpu.reset_cycles(); while self.cpu.get_cycles().0 <= cpu_cycles.0 { self.cpu.run(&mut self.bus); @@ -116,7 +109,7 @@ impl Emulator { self.bus.reset_timer = false; self.timer.reset(&mut self.bus); } - self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); + self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles(), frame_buffer); self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); // 1 CPU cycle = 238.42ns @@ -127,13 +120,14 @@ impl Emulator { pub fn cpu_loop(&mut self) { let mut exit = false; + let mut frame: [u8; 144 * 160] = [0; 144 * 160]; while !exit { self.cpu.run(&mut self.bus); if self.bus.reset_timer { self.bus.reset_timer = false; self.timer.reset(&mut self.bus); } - self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); + self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles(), &mut frame); self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); // exit = self.cpu.get_exec_calls_count() >= 1258895; // log 1 diff --git a/src/ppu.rs b/src/ppu.rs index c179680..915cc4b 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -116,15 +116,15 @@ impl PPU { self.cycles.0 += cycles.0; } - pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles) { + pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles, frame_buffer: &mut [u8]) { let mut count = 0; while count < cycles.0 { - self.cycle(bus); + self.cycle(bus, frame_buffer); count += 1; } } - pub fn cycle(&mut self, bus: &mut Bus) { + pub fn cycle(&mut self, bus: &mut Bus, frame_buffer: &mut [u8]) { if !PPU::get_lcd_control(bus, LCDControl::LCDEnable) { self.increment_cycles(Cycles(1)); return; @@ -139,7 +139,7 @@ impl PPU { } } else if self.cycles.0 == 80 + 1 { // Mode 3 drawing pixel line. This could also last 289 cycles - self.draw_line(bus); + self.draw_line(bus, frame_buffer); PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::TransferringToLCD), true); } else if self.cycles.0 == 80 + 172 + 1 { // Mode 0 Horizontal blank. This could last 87 or 204 cycles depending on the mode 3 @@ -190,7 +190,7 @@ impl PPU { } fn set_lcd_y(bus: &mut Bus, val: u8) { - bus.write(LCD_Y_ADDRESS, val); + bus.force_write(LCD_Y_ADDRESS, val); } fn get_scroll_x(bus: &Bus) -> u8 { @@ -300,7 +300,7 @@ impl PPU { Some(pixels[(x as usize).rem_euclid(8)]) } - fn draw_line(&mut self, bus: &Bus) { + fn draw_line(&mut self, bus: &Bus, frame_buffer: &mut [u8]) { let palette = bus.read(BACKGROUND_PALETTE_ADDRESS); let lcd_y = PPU::get_lcd_y(bus); if lcd_y as u32 >= LCD_HEIGHT { @@ -321,10 +321,18 @@ impl PPU { let bg_pixels = PPU::get_byte_pixels(tile_byte_1, tile_byte_2, palette); for pixel in bg_pixels { - let idx = lcd_x as usize + (lcd_y as usize * LCD_WIDTH as usize); - self.rgba_frame[idx] = PPU::get_rgba(pixel); + let idx = (lcd_x as usize + (lcd_y as usize * LCD_WIDTH as usize)) * 4; + let rgba = PPU::get_rgba(pixel); + frame_buffer[idx] = rgba[0]; + frame_buffer[idx + 1] = rgba[1]; + frame_buffer[idx + 2] = rgba[2]; + frame_buffer[idx + 3] = rgba[3]; if let Some(window_pixel) = PPU::get_window_pixel(lcd_x, bus) { - self.rgba_frame[idx] = PPU::get_rgba(window_pixel); + let rgba = PPU::get_rgba(pixel); + frame_buffer[idx] = rgba[0]; + frame_buffer[idx + 1] = rgba[1]; + frame_buffer[idx + 2] = rgba[2]; + frame_buffer[idx + 3] = rgba[3]; } lcd_x += 1; @@ -373,8 +381,4 @@ impl PPU { PPU::get_pixel(PPU::get_palette((byte1 & 0b01) | ((byte2 << 1) & 0b10), palette)), ] } - - pub fn get_rgba_frame(&self) -> &[[u8; 4]; FRAME_BUFFER_LENGTH as usize] { - &self.rgba_frame - } } diff --git a/src/render.rs b/src/render.rs index 65f97cc..217aad7 100644 --- a/src/render.rs +++ b/src/render.rs @@ -64,8 +64,8 @@ pub fn start_eventloop() { *control_flow = ControlFlow::Exit }, Event::MainEventsCleared => { - emulator.run(Cycles(70224)); - emulator.draw(pixels.get_frame()); + emulator.run(Cycles(70224), pixels.get_frame()); + // emulator.draw(pixels.get_frame()); // thread::sleep(time::Duration::from_millis(14)); window.request_redraw();