mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
EI instruction delay and fix palette bug
This commit is contained in:
parent
aed56708fd
commit
98be8f29dd
@ -58,7 +58,7 @@ pub struct Bus {
|
|||||||
|
|
||||||
impl Bus {
|
impl Bus {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let game_rom = match ROM::load_file("ignore/tetris.gb".to_string()) {
|
let game_rom = match ROM::load_file("ignore/dmg-acid2.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()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/02-interrupts.gb".to_string()) {
|
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/02-interrupts.gb".to_string()) {
|
||||||
@ -76,6 +76,7 @@ impl Bus {
|
|||||||
_ => panic!("Could not read ROM"),
|
_ => panic!("Could not read ROM"),
|
||||||
};
|
};
|
||||||
let mut data = [0x00; 0x10000];
|
let mut data = [0x00; 0x10000];
|
||||||
|
data[0xFF00] = 0b11001111;
|
||||||
data[0xFF01] = 0x00;
|
data[0xFF01] = 0x00;
|
||||||
data[0xFF02] = 0x7E;
|
data[0xFF02] = 0x7E;
|
||||||
data[0xFF04] = 0x18;
|
data[0xFF04] = 0x18;
|
||||||
@ -95,6 +96,7 @@ impl Bus {
|
|||||||
|
|
||||||
data[0xFF4A] = 0x00;
|
data[0xFF4A] = 0x00;
|
||||||
data[0xFF4B] = 0x00;
|
data[0xFF4B] = 0x00;
|
||||||
|
data[0xFFFF] = 0x00;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
data,
|
data,
|
||||||
|
23
src/cpu.rs
23
src/cpu.rs
@ -843,6 +843,7 @@ pub struct CPU {
|
|||||||
exec_calls_count: usize,
|
exec_calls_count: usize,
|
||||||
is_halted: bool,
|
is_halted: bool,
|
||||||
ime: bool, // Interrupt Master Enable
|
ime: bool, // Interrupt Master Enable
|
||||||
|
ei_delay: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CPU {
|
impl CPU {
|
||||||
@ -853,6 +854,7 @@ impl CPU {
|
|||||||
last_op_cycles: Cycles(0),
|
last_op_cycles: Cycles(0),
|
||||||
exec_calls_count: 0,
|
exec_calls_count: 0,
|
||||||
is_halted: false,
|
is_halted: false,
|
||||||
|
ei_delay: false,
|
||||||
ime: true,
|
ime: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -913,7 +915,6 @@ impl CPU {
|
|||||||
bus.set_interrupt_flag(interrupt, false);
|
bus.set_interrupt_flag(interrupt, false);
|
||||||
let vector = interrupt.get_vector();
|
let vector = interrupt.get_vector();
|
||||||
self.exec(Opcode::CALL(OpcodeParameter::U16(vector)), bus);
|
self.exec(Opcode::CALL(OpcodeParameter::U16(vector)), bus);
|
||||||
println!("Interrupt: {:?}", interrupt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_interrupts(&mut self, bus: &mut Bus) -> Option<Interrupt> {
|
pub fn check_interrupts(&mut self, bus: &mut Bus) -> Option<Interrupt> {
|
||||||
@ -952,6 +953,12 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
self.increment_cycles(cycles);
|
self.increment_cycles(cycles);
|
||||||
self.exec(opcode, bus);
|
self.exec(opcode, bus);
|
||||||
|
if self.ei_delay && !self.ime {
|
||||||
|
println!("EI delay");
|
||||||
|
self.ei_delay = false;
|
||||||
|
self.run(bus);
|
||||||
|
self.ime = true;
|
||||||
|
}
|
||||||
} else if self.is_halted {
|
} else if self.is_halted {
|
||||||
self.increment_cycles(Cycles(1));
|
self.increment_cycles(Cycles(1));
|
||||||
}
|
}
|
||||||
@ -1781,25 +1788,20 @@ impl CPU {
|
|||||||
Opcode::EI => {
|
Opcode::EI => {
|
||||||
println!("EI");
|
println!("EI");
|
||||||
self.registers.increment(Register::PC, 1);
|
self.registers.increment(Register::PC, 1);
|
||||||
self.ime = true;
|
self.ei_delay = true;
|
||||||
},
|
},
|
||||||
// Disable interrupts
|
// Disable interrupts
|
||||||
Opcode::DI => {
|
Opcode::DI => {
|
||||||
println!("DI");
|
|
||||||
self.registers.increment(Register::PC, 1);
|
self.registers.increment(Register::PC, 1);
|
||||||
self.ime = false;
|
self.ime = false;
|
||||||
},
|
},
|
||||||
// Same as enabling interrupts and then executing RET
|
// Same as enabling interrupts and then executing RET
|
||||||
Opcode::RETI => {
|
Opcode::RETI => {
|
||||||
println!("RETI");
|
|
||||||
let prev_pc = self.registers.get(Register::PC);
|
|
||||||
self.exec(Opcode::EI, bus);
|
|
||||||
self.exec(Opcode::RET(OpcodeParameter::NoParam), bus);
|
self.exec(Opcode::RET(OpcodeParameter::NoParam), bus);
|
||||||
self.registers.set(Register::PC, prev_pc.wrapping_add(1));
|
self.ime = true;
|
||||||
},
|
},
|
||||||
// Don't execute instructions until an interrupt is requested
|
// Don't execute instructions until an interrupt is requested
|
||||||
Opcode::HALT => {
|
Opcode::HALT => {
|
||||||
println!("HALT");
|
|
||||||
self.registers.increment(Register::PC, 1);
|
self.registers.increment(Register::PC, 1);
|
||||||
self.is_halted = true;
|
self.is_halted = true;
|
||||||
},
|
},
|
||||||
@ -1807,8 +1809,9 @@ impl CPU {
|
|||||||
self.registers.increment(Register::PC, 2);
|
self.registers.increment(Register::PC, 2);
|
||||||
},
|
},
|
||||||
Opcode::NOP => self.registers.increment(Register::PC, 1),
|
Opcode::NOP => self.registers.increment(Register::PC, 1),
|
||||||
Opcode::IllegalInstruction => {panic!("Illegal instruction");},
|
/* Opcode::IllegalInstruction => {panic!("Illegal instruction");},
|
||||||
_ => {panic!("Illegal instruction");},
|
_ => {panic!("Illegal instruction");}, */
|
||||||
|
_ => self.registers.increment(Register::PC, 1),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
src/ppu.rs
28
src/ppu.rs
@ -163,16 +163,20 @@ impl PPU {
|
|||||||
self.reset_cycles();
|
self.reset_cycles();
|
||||||
|
|
||||||
PPU::set_lcd_y(bus, PPU::get_lcd_y(bus).wrapping_add(1));
|
PPU::set_lcd_y(bus, PPU::get_lcd_y(bus).wrapping_add(1));
|
||||||
|
|
||||||
let lyc_compare = PPU::get_lcd_y(bus) == bus.read(LCD_Y_COMPARE_ADDRESS);
|
|
||||||
PPU::set_lcd_status(bus, LCDStatus::LYCFlag, lyc_compare);
|
|
||||||
if PPU::get_lcd_status(bus, LCDStatus::LYCInterrupt) && lyc_compare {
|
|
||||||
PPU::request_interrupt(bus, Interrupt::LCDSTAT);
|
|
||||||
}
|
|
||||||
// Frame completed
|
// Frame completed
|
||||||
if PPU::get_lcd_y(bus) > 153 {
|
if PPU::get_lcd_y(bus) > 153 {
|
||||||
PPU::set_lcd_y(bus, 0);
|
PPU::set_lcd_y(bus, 0);
|
||||||
}
|
}
|
||||||
|
PPU::check_lyc(bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_lyc(bus: &mut Bus) {
|
||||||
|
let lyc_compare = PPU::get_lcd_y(bus) == bus.read(LCD_Y_COMPARE_ADDRESS);
|
||||||
|
if PPU::get_lcd_status(bus, LCDStatus::LYCInterrupt) && lyc_compare {
|
||||||
|
println!("lyc");
|
||||||
|
PPU::set_lcd_status(bus, LCDStatus::LYCFlag, lyc_compare);
|
||||||
|
PPU::request_interrupt(bus, Interrupt::LCDSTAT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,6 +334,7 @@ impl PPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_palette(index: u8, palette_byte: u8) -> u8 {
|
fn get_palette(index: u8, palette_byte: u8) -> u8 {
|
||||||
|
let index = index & 0b11;
|
||||||
match index {
|
match index {
|
||||||
0b00 => palette_byte & 0b11,
|
0b00 => palette_byte & 0b11,
|
||||||
0b01 => (palette_byte >> 2) & 0b11,
|
0b01 => (palette_byte >> 2) & 0b11,
|
||||||
@ -340,12 +345,13 @@ impl PPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_pixel(two_bit_pixel: u8) -> Pixel {
|
fn get_pixel(two_bit_pixel: u8) -> Pixel {
|
||||||
|
let two_bit_pixel = two_bit_pixel & 0b11;
|
||||||
match two_bit_pixel {
|
match two_bit_pixel {
|
||||||
0x00 => Pixel::White,
|
0b00 => Pixel::White,
|
||||||
0x01 => Pixel::Light,
|
0b01 => Pixel::Light,
|
||||||
0x10 => Pixel::Dark,
|
0b10 => Pixel::Dark,
|
||||||
0x11 => Pixel::Black,
|
0b11 => Pixel::Black,
|
||||||
_ => Pixel::Black,
|
_ => Pixel::White,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ impl Timer {
|
|||||||
if self.cycles.0 >= tima_rate {
|
if self.cycles.0 >= tima_rate {
|
||||||
if tima.checked_add(1) == None {
|
if tima.checked_add(1) == None {
|
||||||
bus.write(TIMER_COUNTER_ADDRESS, bus.read(TIMER_MODULO_ADDRESS));
|
bus.write(TIMER_COUNTER_ADDRESS, bus.read(TIMER_MODULO_ADDRESS));
|
||||||
bus.set_interrupt_flag(Interrupt::Timer, false);
|
bus.set_interrupt_flag(Interrupt::Timer, true);
|
||||||
} else {
|
} else {
|
||||||
bus.write(TIMER_COUNTER_ADDRESS, tima.wrapping_add(1));
|
bus.write(TIMER_COUNTER_ADDRESS, tima.wrapping_add(1));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user