0xC0 - 0xFF
This commit is contained in:
parent
f07c6a41a3
commit
e4ba687968
|
@ -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],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue