mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
PPU optimization
This commit is contained in:
parent
d94b912ff6
commit
f7ca3fcc25
@ -57,7 +57,7 @@ pub struct Bus {
|
|||||||
|
|
||||||
impl Bus {
|
impl Bus {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let game_rom = match ROM::load_file("ignore/dr-mario.gb".to_string()) {
|
let game_rom = match ROM::load_file("ignore/tetris.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("ignore/mooneye/emulator-only/mbc1/bits_bank1.gb".to_string()) {
|
// let game_rom = match ROM::load_file("ignore/mooneye/emulator-only/mbc1/bits_bank1.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs.gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/01-special.gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/01-special.gb".to_string()) {
|
||||||
|
@ -831,8 +831,8 @@ pub enum Opcode {
|
|||||||
pub struct Cycles(pub usize);
|
pub struct Cycles(pub usize);
|
||||||
|
|
||||||
impl Cycles {
|
impl Cycles {
|
||||||
pub fn to_t(&self) -> usize {
|
pub fn to_t(&self) -> Self {
|
||||||
self.0 * 4
|
Self(self.0 * 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,13 +99,13 @@ impl Emulator {
|
|||||||
|
|
||||||
pub fn run(&mut self, cpu_cycles: Cycles, frame_buffer: &mut [u8]) {
|
pub fn run(&mut self, cpu_cycles: Cycles, frame_buffer: &mut [u8]) {
|
||||||
self.cpu.reset_cycles();
|
self.cpu.reset_cycles();
|
||||||
while self.cpu.get_cycles().to_t() <= cpu_cycles.0 {
|
while self.cpu.get_cycles().to_t().0 <= cpu_cycles.0 {
|
||||||
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(), frame_buffer);
|
self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t(), 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
|
||||||
@ -123,7 +123,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(), &mut frame);
|
self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t(), &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
|
||||||
|
20
src/ppu.rs
20
src/ppu.rs
@ -186,42 +186,34 @@ impl PPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles, frame_buffer: &mut [u8]) {
|
pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles, frame_buffer: &mut [u8]) {
|
||||||
let mut count = 0;
|
|
||||||
while count < cycles.to_t() {
|
|
||||||
self.cycle(bus, frame_buffer);
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if PPU::get_lcd_y(bus) < 144 {
|
if PPU::get_lcd_y(bus) < 144 {
|
||||||
if self.cycles.0 == 0 {
|
if self.cycles.0 <= 80 && !PPU::get_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::SearchingOAM)) {
|
||||||
// Mode 2 OAM scan
|
// Mode 2 OAM scan
|
||||||
PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::SearchingOAM), true);
|
PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::SearchingOAM), true);
|
||||||
self.stat_interrupt(bus);
|
self.stat_interrupt(bus);
|
||||||
self.oam_search(bus);
|
self.oam_search(bus);
|
||||||
} else if self.cycles.0 == 80 + 1 {
|
} else if self.cycles.0 > 80 && self.cycles.0 <= 80 + 172 && !PPU::get_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::TransferringToLCD)) {
|
||||||
// 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, frame_buffer);
|
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 && self.cycles.0 <= 80 + 172 + 204 && !PPU::get_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::HBlank)) {
|
||||||
// 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
|
||||||
PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::HBlank), true);
|
PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::HBlank), true);
|
||||||
self.stat_interrupt(bus);
|
self.stat_interrupt(bus);
|
||||||
}
|
}
|
||||||
} else if PPU::get_lcd_y(bus) == 144 && self.cycles.0 == 0 {
|
} else if PPU::get_lcd_y(bus) >= 144 && !PPU::get_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::VBlank)) {
|
||||||
// Mode 1 Vertical blank
|
// Mode 1 Vertical blank
|
||||||
bus.set_interrupt_flag(Interrupt::VBlank, true);
|
bus.set_interrupt_flag(Interrupt::VBlank, true);
|
||||||
PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::VBlank), true);
|
PPU::set_lcd_status(bus, LCDStatus::ModeFlag(LCDStatusModeFlag::VBlank), true);
|
||||||
self.stat_interrupt(bus);
|
self.stat_interrupt(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.increment_cycles(Cycles(1));
|
self.increment_cycles(cycles);
|
||||||
|
|
||||||
// Horizontal scan completed
|
// Horizontal scan completed
|
||||||
if self.cycles.0 > 456 {
|
if self.cycles.0 > 456 {
|
||||||
|
@ -18,6 +18,7 @@ enum Region {
|
|||||||
NonJapanese,
|
NonJapanese,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
enum MBC {
|
enum MBC {
|
||||||
NoMBC,
|
NoMBC,
|
||||||
MBC1,
|
MBC1,
|
||||||
@ -159,6 +160,7 @@ impl ROM {
|
|||||||
|
|
||||||
let info = ROMInfo::from_bytes(&data);
|
let info = ROMInfo::from_bytes(&data);
|
||||||
println!("has ram {}", info.has_ram);
|
println!("has ram {}", info.has_ram);
|
||||||
|
println!("mbc {:?}", info.mbc);
|
||||||
let ram = Vec::with_capacity(info.ram_size() as usize);
|
let ram = Vec::with_capacity(info.ram_size() as usize);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -31,7 +31,7 @@ impl Timer {
|
|||||||
|
|
||||||
pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles) {
|
pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles) {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while count < cycles.to_t() {
|
while count < cycles.to_t().0 {
|
||||||
self.cycle(bus);
|
self.cycle(bus);
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user