mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
Optimize framebuffer render
This commit is contained in:
parent
659f602b2a
commit
60fd55abca
@ -78,7 +78,7 @@ impl Bus {
|
|||||||
};
|
};
|
||||||
let mut data = [0x00; 0x10000];
|
let mut data = [0x00; 0x10000];
|
||||||
// Hardware registers after the bootrom
|
// Hardware registers after the bootrom
|
||||||
data[0xFF00] = 0b11001111;
|
data[0xFF00] = 0xCF;
|
||||||
data[0xFF01] = 0x00;
|
data[0xFF01] = 0x00;
|
||||||
data[0xFF02] = 0x7E;
|
data[0xFF02] = 0x7E;
|
||||||
data[0xFF04] = 0x18;
|
data[0xFF04] = 0x18;
|
||||||
@ -111,6 +111,9 @@ impl Bus {
|
|||||||
if BANK_ZERO.in_range(address) || BANK_SWITCHABLE.in_range(address) {
|
if BANK_ZERO.in_range(address) || BANK_SWITCHABLE.in_range(address) {
|
||||||
return self.game_rom.read(address);
|
return self.game_rom.read(address);
|
||||||
}
|
}
|
||||||
|
if address == JOYPAD_ADDRESS {
|
||||||
|
println!("{:08b}", self.data[address as usize]);
|
||||||
|
}
|
||||||
self.data[address as usize]
|
self.data[address as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +145,8 @@ impl Bus {
|
|||||||
} else if address == JOYPAD_ADDRESS {
|
} else if address == JOYPAD_ADDRESS {
|
||||||
let byte = self.data[JOYPAD_ADDRESS as usize];
|
let byte = self.data[JOYPAD_ADDRESS as usize];
|
||||||
self.data[JOYPAD_ADDRESS as usize] = (data & 0b11110000) | (byte & 0b00001111);
|
self.data[JOYPAD_ADDRESS as usize] = (data & 0b11110000) | (byte & 0b00001111);
|
||||||
|
} else if address == LCD_Y_ADDRESS {
|
||||||
|
println!("Write to LCD_Y not allowed");
|
||||||
} else {
|
} else {
|
||||||
self.data[address as usize] = data;
|
self.data[address as usize] = data;
|
||||||
}
|
}
|
||||||
|
@ -101,14 +101,7 @@ impl Emulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&mut self, frame: &mut [u8]) {
|
pub fn run(&mut self, cpu_cycles: Cycles, frame_buffer: &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) {
|
|
||||||
self.cpu.reset_cycles();
|
self.cpu.reset_cycles();
|
||||||
while self.cpu.get_cycles().0 <= cpu_cycles.0 {
|
while self.cpu.get_cycles().0 <= cpu_cycles.0 {
|
||||||
self.cpu.run(&mut self.bus);
|
self.cpu.run(&mut self.bus);
|
||||||
@ -116,7 +109,7 @@ impl Emulator {
|
|||||||
self.bus.reset_timer = false;
|
self.bus.reset_timer = false;
|
||||||
self.timer.reset(&mut self.bus);
|
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());
|
self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles());
|
||||||
|
|
||||||
// 1 CPU cycle = 238.42ns
|
// 1 CPU cycle = 238.42ns
|
||||||
@ -127,13 +120,14 @@ impl Emulator {
|
|||||||
|
|
||||||
pub fn cpu_loop(&mut self) {
|
pub fn cpu_loop(&mut self) {
|
||||||
let mut exit = false;
|
let mut exit = false;
|
||||||
|
let mut frame: [u8; 144 * 160] = [0; 144 * 160];
|
||||||
while !exit {
|
while !exit {
|
||||||
self.cpu.run(&mut self.bus);
|
self.cpu.run(&mut self.bus);
|
||||||
if self.bus.reset_timer {
|
if self.bus.reset_timer {
|
||||||
self.bus.reset_timer = false;
|
self.bus.reset_timer = false;
|
||||||
self.timer.reset(&mut self.bus);
|
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());
|
self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles());
|
||||||
|
|
||||||
// exit = self.cpu.get_exec_calls_count() >= 1258895; // log 1
|
// exit = self.cpu.get_exec_calls_count() >= 1258895; // log 1
|
||||||
|
30
src/ppu.rs
30
src/ppu.rs
@ -116,15 +116,15 @@ impl PPU {
|
|||||||
self.cycles.0 += cycles.0;
|
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;
|
let mut count = 0;
|
||||||
while count < cycles.0 {
|
while count < cycles.0 {
|
||||||
self.cycle(bus);
|
self.cycle(bus, frame_buffer);
|
||||||
count += 1;
|
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) {
|
if !PPU::get_lcd_control(bus, LCDControl::LCDEnable) {
|
||||||
self.increment_cycles(Cycles(1));
|
self.increment_cycles(Cycles(1));
|
||||||
return;
|
return;
|
||||||
@ -139,7 +139,7 @@ impl PPU {
|
|||||||
}
|
}
|
||||||
} else if self.cycles.0 == 80 + 1 {
|
} else if self.cycles.0 == 80 + 1 {
|
||||||
// Mode 3 drawing pixel line. This could also last 289 cycles
|
// 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);
|
PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::TransferringToLCD), true);
|
||||||
} else if self.cycles.0 == 80 + 172 + 1 {
|
} else if self.cycles.0 == 80 + 172 + 1 {
|
||||||
// Mode 0 Horizontal blank. This could last 87 or 204 cycles depending on the mode 3
|
// 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) {
|
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 {
|
fn get_scroll_x(bus: &Bus) -> u8 {
|
||||||
@ -300,7 +300,7 @@ impl PPU {
|
|||||||
Some(pixels[(x as usize).rem_euclid(8)])
|
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 palette = bus.read(BACKGROUND_PALETTE_ADDRESS);
|
||||||
let lcd_y = PPU::get_lcd_y(bus);
|
let lcd_y = PPU::get_lcd_y(bus);
|
||||||
if lcd_y as u32 >= LCD_HEIGHT {
|
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);
|
let bg_pixels = PPU::get_byte_pixels(tile_byte_1, tile_byte_2, palette);
|
||||||
|
|
||||||
for pixel in bg_pixels {
|
for pixel in bg_pixels {
|
||||||
let idx = lcd_x as usize + (lcd_y as usize * LCD_WIDTH as usize);
|
let idx = (lcd_x as usize + (lcd_y as usize * LCD_WIDTH as usize)) * 4;
|
||||||
self.rgba_frame[idx] = PPU::get_rgba(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];
|
||||||
if let Some(window_pixel) = PPU::get_window_pixel(lcd_x, bus) {
|
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;
|
lcd_x += 1;
|
||||||
@ -373,8 +381,4 @@ impl PPU {
|
|||||||
PPU::get_pixel(PPU::get_palette((byte1 & 0b01) | ((byte2 << 1) & 0b10), palette)),
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,8 @@ pub fn start_eventloop() {
|
|||||||
*control_flow = ControlFlow::Exit
|
*control_flow = ControlFlow::Exit
|
||||||
},
|
},
|
||||||
Event::MainEventsCleared => {
|
Event::MainEventsCleared => {
|
||||||
emulator.run(Cycles(70224));
|
emulator.run(Cycles(70224), pixels.get_frame());
|
||||||
emulator.draw(pixels.get_frame());
|
// emulator.draw(pixels.get_frame());
|
||||||
|
|
||||||
// thread::sleep(time::Duration::from_millis(14));
|
// thread::sleep(time::Duration::from_millis(14));
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
|
Loading…
Reference in New Issue
Block a user