0xC0 - 0xFF

This commit is contained in:
Alex Janka 2023-02-02 10:54:16 +11:00
parent f07c6a41a3
commit e4ba687968
4 changed files with 222 additions and 3 deletions

View file

@ -76,6 +76,7 @@ pub struct Memory {
oam: [u8; 160], oam: [u8; 160],
interrupts: u8, interrupts: u8,
ime: bool, ime: bool,
ime_scheduled: u8,
io: [u8; 76], io: [u8; 76],
} }
@ -93,6 +94,7 @@ impl Memory {
oam: [0x0; 160], oam: [0x0; 160],
interrupts: 0x0, interrupts: 0x0,
ime: false, ime: false,
ime_scheduled: 0x0,
io: [0xFF; 76], io: [0xFF; 76],
} }
} }

View file

@ -110,6 +110,10 @@ impl CPU {
self.reg.pc.set_low(address); self.reg.pc.set_low(address);
} }
pub(crate) fn ret(&mut self) {
self.reg.pc = self.pop_word();
}
pub(crate) fn jr(&mut self, jump: i8) { pub(crate) fn jr(&mut self, jump: i8) {
self.reg.pc = self.reg.pc.wrapping_add_signed(jump.into()); self.reg.pc = self.reg.pc.wrapping_add_signed(jump.into());
} }

View file

@ -120,6 +120,20 @@ impl CPU {
} }
} }
pub(crate) fn sp_add(&mut self, first: u16, second: i8) -> u16 {
let (result, carry) = first.overflowing_add_signed(second.into());
self.clear_flag(Flags::NSubtract);
self.clear_flag(Flags::Zero);
self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(
Flags::HalfCarry,
(((first & 0xFFF).wrapping_add_signed(<i8 as Into<i16>>::into(second) & 0xFFF))
& 0x1000)
== 0x1000,
);
return result;
}
pub(crate) fn add_u8s(&mut self, first: u8, second: u8) -> u8 { pub(crate) fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_add(second); let (result, carry) = first.overflowing_add(second);
self.clear_flag(Flags::NSubtract); self.clear_flag(Flags::NSubtract);

View file

@ -6,6 +6,13 @@ use super::{as_signed, res, set, swap_nibbles, Flags, Reg8, SplitRegister, CPU};
impl CPU { impl CPU {
#[allow(dead_code)] #[allow(dead_code)]
pub fn run_opcode(&mut self, opcode: u8) { pub fn run_opcode(&mut self, opcode: u8) {
if self.memory.ime_scheduled > 0 {
self.memory.ime_scheduled = self.memory.ime_scheduled.saturating_sub(1);
if self.memory.ime_scheduled == 0 {
self.memory.ime = true;
}
}
match opcode { match opcode {
0x00 => { 0x00 => {
// noop // noop
@ -491,9 +498,201 @@ impl CPU {
0xBD => self.cp(self.reg.get_8(Reg8::A), self.reg.get_8(Reg8::L)), 0xBD => self.cp(self.reg.get_8(Reg8::A), self.reg.get_8(Reg8::L)),
0xBE => self.cp(self.reg.get_8(Reg8::A), self.memory.get(self.reg.hl)), 0xBE => self.cp(self.reg.get_8(Reg8::A), self.memory.get(self.reg.hl)),
0xBF => self.cp(self.reg.get_8(Reg8::A), self.reg.get_8(Reg8::A)), 0xBF => self.cp(self.reg.get_8(Reg8::A), self.reg.get_8(Reg8::A)),
0xC0 => {
_ => { if !self.is_flag(Flags::Zero) {
undefined(opcode); self.ret();
}
}
0xC1 => self.reg.bc = self.pop_word(),
0xC2 => {
let jump = self.ld_immediate_word();
if !self.is_flag(Flags::Zero) {
self.reg.pc = jump;
}
}
0xC3 => {
let jump = self.ld_immediate_word();
self.reg.pc = jump;
}
0xC4 => {
let pc = self.ld_immediate_word();
if !self.is_flag(Flags::Zero) {
self.push(self.reg.pc);
self.reg.pc = pc;
}
}
0xC5 => self.push(self.reg.bc),
0xC6 => {
let byte = self.ld_immediate_byte();
let val = self.add_u8s(self.reg.get_8(Reg8::A), byte);
self.reg.set_8(Reg8::A, val);
}
0xC7 => self.rst(0x0),
0xC8 => {
if self.is_flag(Flags::Zero) {
self.ret();
}
}
0xC9 => self.ret(),
0xCA => {
let jump = self.ld_immediate_word();
if self.is_flag(Flags::Zero) {
self.reg.pc = jump;
}
}
0xCB => panic!("haven't implemented 0xCB opcodes yet!!"),
0xCC => {
let pc = self.ld_immediate_word();
if self.is_flag(Flags::Zero) {
self.push(self.reg.pc);
self.reg.pc = pc;
}
}
0xCD => {
let pc = self.ld_immediate_word();
self.push(self.reg.pc);
self.reg.pc = pc;
}
0xCE => {
let byte = self.ld_immediate_byte();
let val = self.adc(self.reg.get_8(Reg8::A), byte);
self.reg.set_8(Reg8::A, val);
}
0xCF => self.rst(0x08),
0xD0 => {
if !self.is_flag(Flags::Carry) {
self.ret();
}
}
0xD1 => self.reg.de = self.pop_word(),
0xD2 => {
let jump = self.ld_immediate_word();
if !self.is_flag(Flags::Carry) {
self.reg.pc = jump;
}
}
0xD4 => {
let pc = self.ld_immediate_word();
if !self.is_flag(Flags::Carry) {
self.push(self.reg.pc);
self.reg.pc = pc;
}
}
0xD5 => self.push(self.reg.de),
0xD6 => {
let byte = self.ld_immediate_byte();
let val = self.sub_u8s(self.reg.get_8(Reg8::A), byte);
self.reg.set_8(Reg8::A, val);
}
0xD7 => self.rst(0x10),
0xD8 => {
if self.is_flag(Flags::Carry) {
self.ret();
}
}
0xD9 => {
self.ret();
self.memory.ime = true;
}
0xDA => {
let jump = self.ld_immediate_word();
if self.is_flag(Flags::Carry) {
self.reg.pc = jump;
}
}
0xDC => {
let pc = self.ld_immediate_word();
if self.is_flag(Flags::Carry) {
self.push(self.reg.pc);
self.reg.pc = pc;
}
}
0xDE => {
let byte = self.ld_immediate_byte();
let val = self.sbc(self.reg.get_8(Reg8::A), byte);
self.reg.set_8(Reg8::A, val);
}
0xDF => self.rst(0x18),
0xE0 => {
let mut addr: u16 = 0x0;
addr.set_high(0xFF);
addr.set_low(self.ld_immediate_byte());
self.memory.set(addr, self.reg.get_8(Reg8::A));
}
0xE1 => self.reg.hl = self.pop_word(),
0xE2 => {
let mut addr: u16 = 0x0;
addr.set_high(0xFF);
addr.set_low(self.reg.get_8(Reg8::C));
self.memory.set(addr, self.reg.get_8(Reg8::A));
}
0xE5 => self.push(self.reg.hl),
0xE6 => {
let byte = self.ld_immediate_byte();
let val = self.and(self.reg.get_8(Reg8::A), byte);
self.reg.set_8(Reg8::A, val);
}
0xE7 => self.rst(0x20),
0xE8 => {
let v = as_signed(self.ld_immediate_byte());
self.reg.sp = self.sp_add(self.reg.sp, v);
}
0xE9 => {
self.reg.pc = self.reg.hl;
}
0xEA => {
let addr = self.ld_immediate_word();
self.memory.set(addr, self.reg.get_8(Reg8::A));
}
0xEE => {
let byte = self.ld_immediate_byte();
let val = self.xor(self.reg.get_8(Reg8::A), byte);
self.reg.set_8(Reg8::A, val);
}
0xEF => self.rst(0x28),
0xF0 => {
let mut addr: u16 = 0x0;
addr.set_high(0xFF);
addr.set_low(self.ld_immediate_byte());
self.reg.set_8(Reg8::A, self.memory.get(addr));
}
0xF1 => self.reg.af = self.pop_word(),
0xF2 => {
let mut addr: u16 = 0x0;
addr.set_high(0xFF);
addr.set_low(self.reg.get_8(Reg8::C));
self.reg.set_8(Reg8::A, self.memory.get(addr));
}
0xF3 => {
self.memory.ime = false;
self.memory.ime_scheduled = 0;
}
0xF5 => self.push(self.reg.af),
0xF6 => {
let byte = self.ld_immediate_byte();
let val = self.or(self.reg.get_8(Reg8::A), byte);
self.reg.set_8(Reg8::A, val);
}
0xF7 => self.rst(0x30),
0xF8 => {
let v = as_signed(self.ld_immediate_byte());
self.reg.hl = self.sp_add(self.reg.sp, v);
}
0xF9 => {
self.reg.sp = self.reg.hl;
}
0xFA => {
let addr = self.ld_immediate_word();
self.reg.set_8(Reg8::A, self.memory.get(addr));
}
0xFB => self.memory.ime_scheduled = 2,
0xFE => {
let byte = self.ld_immediate_byte();
self.cp(self.reg.get_8(Reg8::A), byte);
}
0xFF => self.rst(0x38),
0xD3 | 0xDB | 0xDD | 0xE3 | 0xE4 | 0xEB | 0xEC | 0xED | 0xF4 | 0xFC | 0xFD => {
undefined(opcode)
} }
} }
} }