diff options
author | Astatin <[email protected]> | 2024-09-14 23:49:32 +0900 |
---|---|---|
committer | Astatin <astatin@redacted> | 2024-09-14 23:49:32 +0900 |
commit | 7101d14f3bcc0af29b8d51b1f5d58689fee1a571 (patch) | |
tree | f0d24574e6ec3153a3f4a5969233946be43719a6 /src/opcodes.rs | |
parent | 249921a2094d172e94543446e2af11dcba5075e8 (diff) |
Add keyboard support & start supporting serial communication (but tetris doesn't work in 2p)
Diffstat (limited to 'src/opcodes.rs')
-rw-r--r-- | src/opcodes.rs | 1276 |
1 files changed, 651 insertions, 625 deletions
diff --git a/src/opcodes.rs b/src/opcodes.rs index f238239..2502782 100644 --- a/src/opcodes.rs +++ b/src/opcodes.rs @@ -1,825 +1,851 @@ +use crate::serial::Serial; use crate::state::{flag, reg, GBState, MemError}; // The opcodes functions are returning the number of cycles used. -pub fn r_16b_from_pc(state: &mut GBState) -> Result<u16, MemError> { - let p: u16 = state.mem.r(state.cpu.pc)? as u16 | ((state.mem.r(state.cpu.pc + 1)? as u16) << 8); - state.cpu.pc += 2; +impl GBState { + fn r_16b_from_pc(&mut self) -> Result<u16, MemError> { + let p: u16 = self.mem.r(self.cpu.pc)? as u16 | ((self.mem.r(self.cpu.pc + 1)? as u16) << 8); + self.cpu.pc += 2; - Ok(p) -} + Ok(p) + } -pub fn r_8b_from_pc(state: &mut GBState) -> Result<u8, MemError> { - let p = state.mem.r(state.cpu.pc)?; - state.cpu.pc += 1; + fn r_8b_from_pc(&mut self) -> Result<u8, MemError> { + let p = self.mem.r(self.cpu.pc)?; + self.cpu.pc += 1; - Ok(p) -} + Ok(p) + } -pub fn ldrr(state: &mut GBState, n1: u8, n2: u8) -> Result<(), MemError> { - // Load a register into another register - // LD r, r - state.w_reg(n1, state.r_reg(n2)?) -} + fn ldrr(&mut self, n1: u8, n2: u8) -> Result<(), MemError> { + // Load a register into another register + // LD r, r + self.w_reg(n1, self.r_reg(n2)?) + } -pub fn ldr8(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - // Load an raw 8b value into a register - let p = r_8b_from_pc(state)?; + fn ldr8(&mut self, n1: u8) -> Result<u64, MemError> { + // Load an raw 8b value into a register + let p = self.r_8b_from_pc()?; - state.w_reg(n1, p)?; - Ok(8) -} + self.w_reg(n1, p)?; + Ok(8) + } -pub fn ldrr16(state: &mut GBState, rr: u8, x: u16) { - // Load a raw 16b value into a register - state.cpu.w16(rr, x); -} + fn ldrr16(&mut self, rr: u8, x: u16) { + // Load a raw 16b value into a register + self.cpu.w16(rr, x); + } -pub fn ldnnsp(state: &mut GBState) -> Result<u64, MemError> { - // Load SP into an arbitrary position in memory - let p = r_16b_from_pc(state)?; + fn ldnnsp(&mut self) -> Result<u64, MemError> { + // Load SP into an arbitrary position in memory + let p = self.r_16b_from_pc()?; - state.mem.w(p, (state.cpu.sp & 0xff) as u8)?; - state.mem.w(p + 1, (state.cpu.sp >> 8) as u8)?; - Ok(20) -} + self.mem.w(p, (self.cpu.sp & 0xff) as u8)?; + self.mem.w(p + 1, (self.cpu.sp >> 8) as u8)?; + Ok(20) + } -pub fn ldsphl(state: &mut GBState) -> u64 { - state.cpu.sp = state.cpu.r16(reg::HL); - 8 -} + fn ldsphl(&mut self) -> u64 { + self.cpu.sp = self.cpu.r16(reg::HL); + 8 + } -pub fn ldnna(state: &mut GBState, nn: u16) -> Result<(), MemError> { - // Load A into an arbitrary position in memory - state.mem.w(nn, state.cpu.r[reg::A as usize])?; - Ok(()) -} + fn ldnna(&mut self, nn: u16) -> Result<(), MemError> { + // Load A into an arbitrary position in memory + self.mem.w(nn, self.cpu.r[reg::A as usize])?; + Ok(()) + } -pub fn ldann(state: &mut GBState, nn: u16) -> Result<(), MemError> { - // Load A from an arbitrary position in memory - state.cpu.r[reg::A as usize] = state.mem.r(nn)?; - Ok(()) -} + fn ldann(&mut self, nn: u16) -> Result<(), MemError> { + // Load A from an arbitrary position in memory + self.cpu.r[reg::A as usize] = self.mem.r(nn)?; + Ok(()) + } -pub fn push(state: &mut GBState, x: u16) -> Result<(), MemError> { - state.cpu.sp -= 2; + pub fn push(&mut self, x: u16) -> Result<(), MemError> { + self.cpu.sp -= 2; - state.mem.w(state.cpu.sp, (x & 0xff) as u8)?; + self.mem.w(self.cpu.sp, (x & 0xff) as u8)?; - state.mem.w(state.cpu.sp + 1, (x >> 8) as u8)?; + self.mem.w(self.cpu.sp + 1, (x >> 8) as u8)?; - Ok(()) -} + Ok(()) + } -pub fn pop(state: &mut GBState) -> Result<u16, MemError> { - let res = state.mem.r(state.cpu.sp)? as u16 | ((state.mem.r(state.cpu.sp + 1)? as u16) << 8); + fn pop(&mut self) -> Result<u16, MemError> { + let res = self.mem.r(self.cpu.sp)? as u16 | ((self.mem.r(self.cpu.sp + 1)? as u16) << 8); - state.cpu.sp += 2; + self.cpu.sp += 2; - Ok(res) -} + Ok(res) + } -pub fn jr8(state: &mut GBState) -> Result<u64, MemError> { - // Unconditional relative jump - let p = r_8b_from_pc(state)?; + fn jr8(&mut self) -> Result<u64, MemError> { + // Unconditional relative jump + let p = self.r_8b_from_pc()?; - state.cpu.pc = (state.cpu.pc as i16 + p as i8 as i16) as u16; + self.cpu.pc = (self.cpu.pc as i16 + p as i8 as i16) as u16; - Ok(12) -} + Ok(12) + } + + fn jrcc8(&mut self, n1: u8) -> Result<u64, MemError> { + // Conditional relative jump + let p = self.r_8b_from_pc()?; + let mut cycles = 8; -pub fn jrcc8(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - // Conditional relative jump - let p = r_8b_from_pc(state)?; - let mut cycles = 8; + if self.cpu.check_flag(n1 & 0b11) { + cycles += 4; + self.cpu.pc = (self.cpu.pc as i16 + p as i8 as i16) as u16; + } - if state.cpu.check_flag(n1 & 0b11) { - cycles += 4; - state.cpu.pc = (state.cpu.pc as i16 + p as i8 as i16) as u16; + Ok(cycles) } - Ok(cycles) -} + fn jp16(&mut self) -> Result<u64, MemError> { + // Unconditional absolute jump + let p = self.r_16b_from_pc()?; -pub fn jp16(state: &mut GBState) -> Result<u64, MemError> { - // Unconditional absolute jump - let p = r_16b_from_pc(state)?; + self.cpu.pc = p; - state.cpu.pc = p; + Ok(16) + } - Ok(16) -} + fn jphl(&mut self) -> u64 { + // Unconditional absolute jump to HL + self.cpu.pc = self.cpu.r16(reg::HL); -pub fn jphl(state: &mut GBState) -> u64 { - // Unconditional absolute jump to HL - state.cpu.pc = state.cpu.r16(reg::HL); + 4 + } - 4 -} + fn jpcc16(&mut self, n1: u8) -> Result<u64, MemError> { + // Conditional absolute jump + let p = self.r_16b_from_pc()?; + let mut cycles = 8; -pub fn jpcc16(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - // Conditional absolute jump - let p = r_16b_from_pc(state)?; - let mut cycles = 8; + if self.cpu.check_flag(n1 & 0b11) { + cycles += 4; + self.cpu.pc = p; + } - if state.cpu.check_flag(n1 & 0b11) { - cycles += 4; - state.cpu.pc = p; + Ok(cycles) } - Ok(cycles) -} + fn call(&mut self) -> Result<u64, MemError> { + // Unconditional function call + let p = self.r_16b_from_pc()?; -pub fn call(state: &mut GBState) -> Result<u64, MemError> { - // Unconditional function call - let p = r_16b_from_pc(state)?; + self.push(self.cpu.pc)?; + self.cpu.pc = p; - push(state, state.cpu.pc)?; - state.cpu.pc = p; + Ok(24) + } - Ok(24) -} + fn callcc(&mut self, n1: u8) -> Result<u64, MemError> { + // Conditional function call + let p = self.r_16b_from_pc()?; + let mut cycles = 12; -pub fn callcc(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - // Conditional function call - let p = r_16b_from_pc(state)?; - let mut cycles = 12; + if self.cpu.check_flag(n1 & 0b11) { + cycles += 12; + self.push(self.cpu.pc)?; + self.cpu.pc = p; + } - if state.cpu.check_flag(n1 & 0b11) { - cycles += 12; - push(state, state.cpu.pc)?; - state.cpu.pc = p; + Ok(cycles) } - Ok(cycles) -} + fn ret(&mut self) -> Result<u64, MemError> { + let res = self.pop()?; + + if res == 0 { + println!("DEBUG: {:?}", self.cpu); + panic!("RET to start"); + } -pub fn ret(state: &mut GBState) -> Result<u64, MemError> { - let res = pop(state)?; + self.cpu.pc = res; - if res == 0 { - println!("DEBUG: {:?}", state.cpu); - panic!("RET to start"); + Ok(16) } - state.cpu.pc = res; - - Ok(16) -} + fn retcc(&mut self, n1: u8) -> Result<u64, MemError> { + let mut cycles = 8; + if self.cpu.check_flag(n1 & 0b11) { + cycles += 12; + self.cpu.pc = self.pop()?; + } -pub fn retcc(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - let mut cycles = 8; - if state.cpu.check_flag(n1 & 0b11) { - cycles += 12; - state.cpu.pc = pop(state)?; + Ok(cycles) } - Ok(cycles) -} + fn ld00a(&mut self, n1: u8) -> Result<u64, MemError> { + // Load register A into or from memory pointed by rr (BC, DE or HL(+/-)) + // LD (rr), A + // LD A, (rr) + let ptr_reg = match n1 & 0b110 { + 0b000 => reg::B, + 0b010 => reg::C, + _ => reg::HL, + }; -pub fn ld00a(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - // Load register A into or from memory pointed by rr (BC, DE or HL(+/-)) - // LD (rr), A - // LD A, (rr) - let ptr_reg = match n1 & 0b110 { - 0b000 => reg::B, - 0b010 => reg::C, - _ => reg::HL, - }; + if n1 & 0b001 == 1 { + self.cpu.r[reg::A as usize] = self.mem.r(self.cpu.r16(ptr_reg))?; + } else { + self.mem + .w(self.cpu.r16(ptr_reg), self.cpu.r[reg::A as usize])?; + } - if n1 & 0b001 == 1 { - state.cpu.r[reg::A as usize] = state.mem.r(state.cpu.r16(ptr_reg))?; - } else { - state - .mem - .w(state.cpu.r16(ptr_reg), state.cpu.r[reg::A as usize])?; - } + if n1 & 0b110 == 0b100 { + self.cpu.w16(reg::HL, self.cpu.r16(reg::HL) + 1); // (HL+) + } - if n1 & 0b110 == 0b100 { - state.cpu.w16(reg::HL, state.cpu.r16(reg::HL) + 1); // (HL+) - } + if n1 & 0b110 == 0b110 { + self.cpu.w16(reg::HL, self.cpu.r16(reg::HL) - 1); // (HL-) + } - if n1 & 0b110 == 0b110 { - state.cpu.w16(reg::HL, state.cpu.r16(reg::HL) - 1); // (HL-) + Ok(8) } - Ok(8) -} + fn inc8(&mut self, n1: u8) -> Result<u64, MemError> { + // Increment 8 bit register + self.w_reg(n1, self.r_reg(n1)? + 1)?; + self.cpu.r[reg::F as usize] &= !(flag::N | flag::ZF | flag::H); + if self.r_reg(n1)? == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } -pub fn inc8(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - // Increment 8 bit register - state.w_reg(n1, state.r_reg(n1)? + 1)?; - state.cpu.r[reg::F as usize] &= !(flag::N | flag::ZF | flag::H); - if state.r_reg(n1)? == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; - } + if self.r_reg(n1)? & 0xf == 0x0 { + self.cpu.r[reg::F as usize] |= flag::H; + } - if state.r_reg(n1)? & 0xf == 0x0 { - state.cpu.r[reg::F as usize] |= flag::H; + Ok(4) } - Ok(4) -} + fn dec8(&mut self, n1: u8) -> Result<u64, MemError> { + // Decrement 8 bit register + self.w_reg(n1, self.r_reg(n1)? - 1)?; + self.cpu.r[reg::F as usize] |= flag::N; + + self.cpu.r[reg::F as usize] &= !(flag::ZF | flag::H); + if self.r_reg(n1)? == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } -pub fn dec8(state: &mut GBState, n1: u8) -> Result<u64, MemError> { - // Decrement 8 bit register - state.w_reg(n1, state.r_reg(n1)? - 1)?; - state.cpu.r[reg::F as usize] |= flag::N; + if self.r_reg(n1)? & 0xf == 0xf { + self.cpu.r[reg::F as usize] |= flag::H; + } - state.cpu.r[reg::F as usize] &= !(flag::ZF | flag::H); - if state.r_reg(n1)? == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + Ok(4) } - if state.r_reg(n1)? & 0xf == 0xf { - state.cpu.r[reg::F as usize] |= flag::H; + fn inc16(&mut self, rr: u8) -> u64 { + // Increment 16 bit register + self.cpu.w16(rr, self.cpu.r16(rr) + 1); + 8 } - Ok(4) -} + fn dec16(&mut self, rr: u8) -> u64 { + // Decrement 16 bit register + self.cpu.w16(rr, self.cpu.r16(rr) - 1); + 8 + } -pub fn inc16(state: &mut GBState, rr: u8) -> u64 { - // Increment 16 bit register - state.cpu.w16(rr, state.cpu.r16(rr) + 1); - 8 -} + fn ccf(&mut self) { + // Flip carry flag + self.cpu.r[reg::F as usize] = (self.cpu.r[reg::F as usize] & 0b10011111) ^ 0b00010000 + } -pub fn dec16(state: &mut GBState, rr: u8) -> u64 { - // Decrement 16 bit register - state.cpu.w16(rr, state.cpu.r16(rr) - 1); - 8 -} + fn scf(&mut self) { + // Set carry flag + self.cpu.r[reg::F as usize] = (self.cpu.r[reg::F as usize] & 0b10011111) | 0b00010000 + } -pub fn ccf(state: &mut GBState) { - // Flip carry flag - state.cpu.r[reg::F as usize] = (state.cpu.r[reg::F as usize] & 0b10011111) ^ 0b00010000 -} + fn daa(&mut self) { + // Decimal Adjust Accumulator + // Adjust the A register after a addition or substraction to keep valid BCD representation + let nibble_low = self.cpu.r[reg::A as usize] & 0b1111; + let sub_flag = (self.cpu.r[reg::F as usize] & flag::N) != 0; + let half_carry_flag = (self.cpu.r[reg::F as usize] & flag::H) != 0; -pub fn scf(state: &mut GBState) { - // Set carry flag - state.cpu.r[reg::F as usize] = (state.cpu.r[reg::F as usize] & 0b10011111) | 0b00010000 -} + if (half_carry_flag || nibble_low > 9) && !sub_flag { + self.cpu.r[reg::A as usize] += 0x06; + } + if (half_carry_flag || nibble_low > 9) && sub_flag { + self.cpu.r[reg::A as usize] -= 0x06; + } -pub fn daa(state: &mut GBState) { - // Decimal Adjust Accumulator - // Adjust the A register after a addition or substraction to keep valid BCD representation - let nibble_low = state.cpu.r[reg::A as usize] & 0b1111; - let sub_flag = (state.cpu.r[reg::F as usize] & flag::N) != 0; - let half_carry_flag = (state.cpu.r[reg::F as usize] & flag::H) != 0; + let nibble_high = self.cpu.r[reg::A as usize] >> 4; - if (half_carry_flag || nibble_low > 9) && !sub_flag { - state.cpu.r[reg::A as usize] += 0x06; - } - if (half_carry_flag || nibble_low > 9) && sub_flag { - state.cpu.r[reg::A as usize] -= 0x06; - } + self.cpu.r[reg::F as usize] &= !(flag::CY | flag::ZF); - let nibble_high = state.cpu.r[reg::A as usize] >> 4; + if nibble_high > 9 && !sub_flag { + self.cpu.r[reg::A as usize] += 0x60; + self.cpu.r[reg::F as usize] |= flag::CY; + } + if nibble_high > 9 && sub_flag { + self.cpu.r[reg::A as usize] -= 0x60; + self.cpu.r[reg::F as usize] |= flag::CY; + } - state.cpu.r[reg::F as usize] &= !(flag::CY | flag::ZF); + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } - if nibble_high > 9 && !sub_flag { - state.cpu.r[reg::A as usize] += 0x60; - state.cpu.r[reg::F as usize] |= flag::CY; - } - if nibble_high > 9 && sub_flag { - state.cpu.r[reg::A as usize] -= 0x60; - state.cpu.r[reg::F as usize] |= flag::CY; + self.cpu.r[reg::F as usize] &= !flag::H; } - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + fn cpl(&mut self) { + // Flip all bits in register A + self.cpu.r[reg::F as usize] = self.cpu.r[reg::F as usize] | flag::N | flag::H; + self.cpu.r[reg::A as usize] ^= 0xff; } - state.cpu.r[reg::F as usize] &= !flag::H; -} + fn addsp8(&mut self) -> Result<u64, MemError> { + let n = self.r_8b_from_pc()? as i8; -pub fn cpl(state: &mut GBState) { - // Flip all bits in register A - state.cpu.r[reg::F as usize] = state.cpu.r[reg::F as usize] | flag::N | flag::H; - state.cpu.r[reg::A as usize] ^= 0xff; -} - -pub fn addsp8(state: &mut GBState) -> Result<u64, MemError> { - let n = r_8b_from_pc(state)? as i8; + self.cpu.sp = (self.cpu.sp as i32 + n as i32) as u16; - state.cpu.sp = (state.cpu.sp as i32 + n as i32) as u16; + self.cpu.r[reg::F as usize] &= !(flag::N | flag::H | flag::CY); - state.cpu.r[reg::F as usize] &= !(flag::N | flag::H | flag::CY); + if (self.cpu.sp & 0xff) as i32 + n as i32 & !0xff != 0 { + self.cpu.r[reg::F as usize] |= flag::H; + } - if (state.cpu.sp & 0xff) as i32 + n as i32 & !0xff != 0 { - state.cpu.r[reg::F as usize] |= flag::H; + if (self.cpu.sp as i32 + n as i32) & !0xffff != 0 { + self.cpu.r[reg::F as usize] |= flag::CY; + } + Ok(16) } - if (state.cpu.sp as i32 + n as i32) & !0xffff != 0 { - state.cpu.r[reg::F as usize] |= flag::CY; - } - Ok(16) -} + fn add(&mut self, x: u8) { + // ADD a number to A and store the result in A + let res = x as u16 + self.cpu.r[reg::A as usize] as u16; -pub fn add(state: &mut GBState, x: u8) { - // ADD a number to A and store the result in A - let res = x as u16 + state.cpu.r[reg::A as usize] as u16; + self.cpu.r[reg::F as usize] = 0; - state.cpu.r[reg::F as usize] = 0; + if (x & 0xf) + (self.cpu.r[reg::A as usize] & 0xf) > 0xf { + self.cpu.r[reg::F as usize] |= flag::H; + } - if (x & 0xf) + (state.cpu.r[reg::A as usize] & 0xf) > 0xf { - state.cpu.r[reg::F as usize] |= flag::H; - } + if res > 0xff { + self.cpu.r[reg::F as usize] |= flag::CY; + } - if res > 0xff { - state.cpu.r[reg::F as usize] |= flag::CY; + self.cpu.r[reg::A as usize] = res as u8; + + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } - state.cpu.r[reg::A as usize] = res as u8; + fn addhlrr(&mut self, rr: u8) -> u64 { + let n = self.cpu.r16(rr); + let hl = self.cpu.r16(reg::HL); - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; - } -} + self.cpu.w16(reg::HL, (hl as i32 + n as i32) as u16); -pub fn addhlrr(state: &mut GBState, rr: u8) -> u64 { - let n = state.cpu.r16(rr); - let hl = state.cpu.r16(reg::HL); + self.cpu.r[reg::F as usize] &= !(flag::N | flag::H | flag::CY); - state.cpu.w16(reg::HL, (hl as i32 + n as i32) as u16); + if (hl & 0xff) as i32 + n as i32 & !0xff != 0 { + self.cpu.r[reg::F as usize] |= flag::H; + } - state.cpu.r[reg::F as usize] &= !(flag::N | flag::H | flag::CY); + if (hl as i32 + n as i32) & !0xffff != 0 { + self.cpu.r[reg::F as usize] |= flag::CY; + } - if (hl & 0xff) as i32 + n as i32 & !0xff != 0 { - state.cpu.r[reg::F as usize] |= flag::H; + 8 } - if (hl as i32 + n as i32) & !0xffff != 0 { - state.cpu.r[reg::F as usize] |= flag::CY; - } + fn adc(&mut self, x: u8) { + // ADD a number and the carry flag to A and store the result in A + let carry = (self.cpu.r[reg::F as usize] & flag::CY) >> 4; + let res = x as u16 + self.cpu.r[reg::A as usize] as u16 + carry as u16; - 8 -} + self.cpu.r[reg::F as usize] = 0; -pub fn adc(state: &mut GBState, x: u8) { - // ADD a number and the carry flag to A and store the result in A - let carry = (state.cpu.r[reg::F as usize] & flag::CY) >> 4; - let res = x as u16 + state.cpu.r[reg::A as usize] as u16 + carry as u16; + if (x & 0xf) + ((self.cpu.r[reg::A as usize] & 0xf) + carry) > 0xf { + self.cpu.r[reg::F as usize] |= flag::H; + } - state.cpu.r[reg::F as usize] = 0; + if res > 0xff { + self.cpu.r[reg::F as usize] |= flag::CY; + } - if (x & 0xf) + ((state.cpu.r[reg::A as usize] & 0xf) + carry) > 0xf { - state.cpu.r[reg::F as usize] |= flag::H; - } + self.cpu.r[reg::A as usize] = res as u8; - if res > 0xff { - state.cpu.r[reg::F as usize] |= flag::CY; + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } - state.cpu.r[reg::A as usize] = res as u8; + fn sub(&mut self, x: u8) { + // SUB a number to A and store the result in A + self.cpu.r[reg::F as usize] = flag::N; - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; - } -} + if (x & 0xf) > (self.cpu.r[reg::A as usize] & 0xf) { + self.cpu.r[reg::F as usize] |= flag::H; + } + + if x > self.cpu.r[reg::A as usize] { + self.cpu.r[reg::F as usize] |= flag::CY; + } -pub fn sub(state: &mut GBState, x: u8) { - // SUB a number to A and store the result in A - state.cpu.r[reg::F as usize] = flag::N; + self.cpu.r[reg::A as usize] = self.cpu.r[reg::A as usize] - x; - if (x & 0xf) > (state.cpu.r[reg::A as usize] & 0xf) { - state.cpu.r[reg::F as usize] |= flag::H; + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } - if x > state.cpu.r[reg::A as usize] { - state.cpu.r[reg::F as usize] |= flag::CY; - } + fn sbc(&mut self, x: u8) { + // SUB a number and the carry flag to A and store the result in A + let carry = (self.cpu.r[reg::F as usize] & flag::CY) >> 4; + self.cpu.r[reg::F as usize] = flag::N; - state.cpu.r[reg::A as usize] = state.cpu.r[reg::A as usize] - x; + if (x & 0xf) > (self.cpu.r[reg::A as usize] & 0xf) - carry { + self.cpu.r[reg::F as usize] |= flag::H; + } - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; - } -} + if x as i32 > self.cpu.r[reg::A as usize] as i32 - carry as i32 { + self.cpu.r[reg::F as usize] |= flag::CY; + } -pub fn sbc(state: &mut GBState, x: u8) { - // SUB a number and the carry flag to A and store the result in A - let carry = (state.cpu.r[reg::F as usize] & flag::CY) >> 4; - state.cpu.r[reg::F as usize] = flag::N; + self.cpu.r[reg::A as usize] = self.cpu.r[reg::A as usize] - x - carry; - if (x & 0xf) > (state.cpu.r[reg::A as usize] & 0xf) - carry { - state.cpu.r[reg::F as usize] |= flag::H; + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } - if x as i32 > state.cpu.r[reg::A as usize] as i32 - carry as i32 { - state.cpu.r[reg::F as usize] |= flag::CY; - } + fn and(&mut self, x: u8) { + // AND a number to A and store the result in A + self.cpu.r[reg::A as usize] &= x; - state.cpu.r[reg::A as usize] = state.cpu.r[reg::A as usize] - x - carry; + self.cpu.r[reg::F as usize] = flag::H; - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } -} -pub fn and(state: &mut GBState, x: u8) { - // AND a number to A and store the result in A - state.cpu.r[reg::A as usize] &= x; + fn xor(&mut self, x: u8) { + // XOR a number to A and store the result in A + self.cpu.r[reg::A as usize] ^= x; - state.cpu.r[reg::F as usize] = flag::H; + self.cpu.r[reg::F as usize] = 0; - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } -} -pub fn xor(state: &mut GBState, x: u8) { - // XOR a number to A and store the result in A - state.cpu.r[reg::A as usize] ^= x; + fn or(&mut self, x: u8) { + // OR a number to A and store the result in A + self.cpu.r[reg::A as usize] |= x; - state.cpu.r[reg::F as usize] = 0; + self.cpu.r[reg::F as usize] = 0; - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + if self.cpu.r[reg::A as usize] == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } -} -pub fn or(state: &mut GBState, x: u8) { - // OR a number to A and store the result in A - state.cpu.r[reg::A as usize] |= x; + fn cp(&mut self, x: u8) { + // SUB a number to A and update the flags accordingly without updating A + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] = 0; + self.cpu.r[reg::F as usize] |= flag::N; - if state.cpu.r[reg::A as usize] == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; - } -} + if x & 0xf > self.cpu.r[reg::A as usize] & 0xf { + self.cpu.r[reg::F as usize] |= flag::H; + } -pub fn cp(state: &mut GBState, x: u8) { - // SUB a number to A and update the flags accordingly without updating A - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + if x > self.cpu.r[reg::A as usize] { + self.cpu.r[reg::F as usize] |= flag::CY; + } - state.cpu.r[reg::F as usize] |= flag::N; + let res = self.cpu.r[reg::A as usize] - x; - if x & 0xf > state.cpu.r[reg::A as usize] & 0xf { - state.cpu.r[reg::F as usize] |= flag::H; + if res == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } } - if x > state.cpu.r[reg::A as usize] { - state.cpu.r[reg::F as usize] |= flag::CY; + fn rlc(&mut self, r_i: u8) -> Result<(), MemError> { + // ROTATE LEFT the input register + let mut n = self.r_reg(r_i)?; + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + self.cpu.r[reg::F as usize] |= (n >> 7) << 4; + n <<= 1; + n |= (self.cpu.r[reg::F as usize] & flag::CY) >> 4; + self.w_reg(r_i, n) } - let res = state.cpu.r[reg::A as usize] - x; - - if res == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + fn rrc(&mut self, r_i: u8) -> Result<(), MemError> { + // ROTATE RIGHT the input register + let mut n = self.r_reg(r_i)?; + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + self.cpu.r[reg::F as usize] |= (n & 1) << 4; + n >>= 1; + n |= ((self.cpu.r[reg::F as usize] & flag::CY) >> 4) << 7; + self.w_reg(r_i, n) } -} -pub fn rlc(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // ROTATE LEFT the input register - let mut n = state.r_reg(r_i)?; - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] |= (n >> 7) << 4; - n <<= 1; - n |= (state.cpu.r[reg::F as usize] & flag::CY) >> 4; - state.w_reg(r_i, n) -} + fn rl(&mut self, r_i: u8) -> Result<(), MemError> { + // ROTATE LEFT THROUGH CARRY the input register + // (RLC IS ROTATE AND RL IS ROTATE THROUGH CARRY ! IT DOESN'T MAKE ANY SENSE !!) + let mut n = self.r_reg(r_i)?; + let carry = (self.cpu.r[reg::F as usize] & flag::CY) >> 4; -pub fn rrc(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // ROTATE RIGHT the input register - let mut n = state.r_reg(r_i)?; - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] |= (n & 1) << 4; - n >>= 1; - n |= ((state.cpu.r[reg::F as usize] & flag::CY) >> 4) << 7; - state.w_reg(r_i, n) -} + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + self.cpu.r[reg::F as usize] |= (n >> 7) << 4; + n <<= 1; + n |= carry; + self.w_reg(r_i, n) + } -pub fn rl(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // ROTATE LEFT THROUGH CARRY the input register - // (RLC IS ROTATE AND RL IS ROTATE THROUGH CARRY ! IT DOESN'T MAKE ANY SENSE !!) - let mut n = state.r_reg(r_i)?; - let carry = (state.cpu.r[reg::F as usize] & flag::CY) >> 4; - - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] |= (n >> 7) << 4; - n <<= 1; - n |= carry; - state.w_reg(r_i, n) -} + fn rr(&mut self, r_i: u8) -> Result<(), MemError> { + // ROTATE RIGHT THROUGH CARRY the input register + let mut n = self.r_reg(r_i)?; + let carry = (self.cpu.r[reg::F as usize] & flag::CY) >> 4; -pub fn rr(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // ROTATE RIGHT THROUGH CARRY the input register - let mut n = state.r_reg(r_i)?; - let carry = (state.cpu.r[reg::F as usize] & flag::CY) >> 4; + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + self.cpu.r[reg::F as usize] |= (n & 1) << 4; + n >>= 1; + n |= carry << 7; + self.w_reg(r_i, n) + } - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] |= (n & 1) << 4; - n >>= 1; - n |= carry << 7; - state.w_reg(r_i, n) -} + fn sla(&mut self, r_i: u8) -> Result<(), MemError> { + // Shift left Arithmetic (b0=0) the input register + let mut n = self.r_reg(r_i)?; -pub fn sla(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // Shift left Arithmetic (b0=0) the input register - let mut n = state.r_reg(r_i)?; + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + self.cpu.r[reg::F as usize] |= (n >> 7) << 4; + n <<= 1; - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] |= (n >> 7) << 4; - n <<= 1; + if n == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } - if n == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + self.w_reg(r_i, n) } - state.w_reg(r_i, n) -} + fn sra(&mut self, r_i: u8) -> Result<(), MemError> { + // Shift right Arithmetic (b7=b7) the input register + let mut n = self.r_reg(r_i)?; -pub fn sra(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // Shift right Arithmetic (b7=b7) the input register - let mut n = state.r_reg(r_i)?; + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + self.cpu.r[reg::F as usize] |= (n & 0b1) << 4; + let b7 = n & 0b10000000; + n >>= 1; + n |= b7; - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] |= (n & 0b1) << 4; - let b7 = n & 0b10000000; - n >>= 1; - n |= b7; + if n == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } - if n == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + self.w_reg(r_i, n) } - state.w_reg(r_i, n) -} + fn swap(&mut self, r_i: u8) -> Result<(), MemError> { + // Swap the high nibble and low nibble + let mut n = self.r_reg(r_i)?; -pub fn swap(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // Swap the high nibble and low nibble - let mut n = state.r_reg(r_i)?; + let nibble_low = n & 0b1111; + let nibble_high = n >> 4; - let nibble_low = n & 0b1111; - let nibble_high = n >> 4; + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + n = nibble_high | (nibble_low << 4); - n = nibble_high | (nibble_low << 4); + if n == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } - if n == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + self.w_reg(r_i, n) } - state.w_reg(r_i, n) -} + fn srl(&mut self, r_i: u8) -> Result<(), MemError> { + // Shift right Logical (b7=0) the input register + let mut n = self.r_reg(r_i)?; -pub fn srl(state: &mut GBState, r_i: u8) -> Result<(), MemError> { - // Shift right Logical (b7=0) the input register - let mut n = state.r_reg(r_i)?; + self.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); + self.cpu.r[reg::F as usize] |= (n & 0b1) << 4; + n >>= 1; - state.cpu.r[reg::F as usize] &= !(flag::H | flag::N | flag::ZF | flag::CY); - state.cpu.r[reg::F as usize] |= (n & 0b1) << 4; - n >>= 1; + if n == 0 { + self.cpu.r[reg::F as usize] |= flag::ZF; + } - if n == 0 { - state.cpu.r[reg::F as usize] |= flag::ZF; + self.w_reg(r_i, n) } - state.w_reg(r_i, n) -} + fn bit(&mut self, n1: u8, n2: u8) -> Result<(), MemError> { + let z = (((self.r_reg(n2)? >> n1) & 1) ^ 1) << 7; -pub fn bit(state: &mut GBState, n1: u8, n2: u8) -> Result<(), MemError> { - let z = (((state.r_reg(n2)? >> n1) & 1) ^ 1) << 7; + self.cpu.r[reg::F as usize] &= !(flag::N | flag::ZF); + self.cpu.r[reg::F as usize] |= flag::H | z; + Ok(()) + } - state.cpu.r[reg::F as usize] &= !(flag::N | flag::ZF); - state.cpu.r[reg::F as usize] |= flag::H | z; - Ok(()) -} + fn set(&mut self, n1: u8, n2: u8) -> Result<(), MemError> { + self.w_reg(n2, self.r_reg(n2)? | (1 << n1)) + } -pub fn set(state: &mut GBState, n1: u8, n2: u8) -> Result<(), MemError> { - state.w_reg(n2, state.r_reg(n2)? | (1 << n1)) -} + fn res(&mut self, n1: u8, n2: u8) -> Result<(), MemError> { + self.w_reg(n2, self.r_reg(n2)? & !(1 << n1)) + } -pub fn res(state: &mut GBState, n1: u8, n2: u8) -> Result<(), MemError> { - state.w_reg(n2, state.r_reg(n2)? & !(1 << n1)) -} + // I don't remember why I separated op00, op01, op10 and op11 AND I'M NOT GOING TO CHANGE IT + // BECAUSE I LOVE CHAOS -// I don't remember why I separated op00, op01, op10 and op11 AND I'M NOT GOING TO CHANGE IT -// BECAUSE I LOVE CHAOS - -pub fn op00(state: &mut GBState, n1: u8, n2: u8) -> Result<u64, MemError> { - // Dispatcher for the instructions starting with 0b00 based on their 3 LSB - match n2 { - 0b000 => match n1 { - 0b000 => Ok(4), - 0b001 => ldnnsp(state), - 0b010 => todo!("STOP"), - 0b011 => jr8(state), - _ => jrcc8(state, n1), - }, - 0b001 => match n1 { - 0b001 | 0b011 | 0b101 | 0b111 => Ok(addhlrr(state, n1 >> 1)), - 0b000 | 0b010 | 0b100 | 0b110 => { - let p = r_16b_from_pc(state)?; - ldrr16(state, n1 >> 1, p); - Ok(12) + fn op00(&mut self, n1: u8, n2: u8) -> Result<u64, MemError> { + // Dispatcher for the instructions starting with 0b00 based on their 3 LSB + match n2 { + 0b000 => match n1 { + 0b000 => Ok(4), + 0b001 => self.ldnnsp(), + 0b010 => todo!("STOP"), + 0b011 => self.jr8(), + _ => self.jrcc8(n1), + }, + 0b001 => match n1 { + 0b001 | 0b011 | 0b101 | 0b111 => Ok(self.addhlrr(n1 >> 1)), + 0b000 | 0b010 | 0b100 | 0b110 => { + let p = self.r_16b_from_pc()?; + self.ldrr16(n1 >> 1, p); + Ok(12) + } + _ => panic!(), + }, + 0b010 => self.ld00a(n1), + 0b011 => match n1 { + 0b001 | 0b011 | 0b101 | 0b111 => Ok(self.dec16(n1 >> 1)), + 0b000 | 0b010 | 0b100 | 0b110 => Ok(self.inc16(n1 >> 1)), + _ => panic!(), + }, + 0b100 => self.inc8(n1), + 0b101 => self.dec8(n1), + 0b110 => self.ldr8(n1), + 0b111 => { + match n1 { + 0b000 => self.rlc(7)?, + 0b001 => self.rrc(7)?, + 0b010 => self.rl(7)?, + 0b011 => self.rr(7)?, + 0b100 => self.daa(), + 0b101 => self.cpl(), + 0b110 => self.scf(), + 0b111 => self.ccf(), + _ => panic!(), + }; + Ok(4) } _ => panic!(), - }, - 0b010 => ld00a(state, n1), - 0b011 => match n1 { - 0b001 | 0b011 | 0b101 | 0b111 => Ok(dec16(state, n1 >> 1)), - 0b000 | 0b010 | 0b100 | 0b110 => Ok(inc16(state, n1 >> 1)), - _ => panic!(), - }, - 0b100 => inc8(state, n1), - 0b101 => dec8(state, n1), - 0b110 => ldr8(state, n1), - 0b111 => { - match n1 { - 0b000 => rlc(state, 7)?, - 0b001 => rrc(state, 7)?, - 0b010 => rl(state, 7)?, - 0b011 => rr(state, 7)?, - 0b100 => daa(state), - 0b101 => cpl(state), - 0b110 => scf(state), - 0b111 => ccf(state), - _ => panic!(), - }; + } + } + + fn op01(&mut self, n1: u8, n2: u8) -> Result<u64, MemError> { + // Dispatcher for the instructions starting with 0b01 (LD r,r and HALT) + if n1 == 0b110 && n2 == 0b110 { + self.mem.halt = true; Ok(4) + } else { + self.ldrr(n1, n2)?; + + if n1 == 0b110 || n2 == 0b110 { + Ok(8) + } else { + Ok(4) + } } - _ => panic!(), } -} -pub fn op01(state: &mut GBState, n1: u8, n2: u8) -> Result<u64, MemError> { - // Dispatcher for the instructions starting with 0b01 (LD r,r and HALT) - if n1 == 0b110 && n2 == 0b110 { - state.mem.halt = true; - Ok(4) - } else { - ldrr(state, n1, n2)?; + fn op10(&mut self, n1: u8, n2: u8) -> Result<u64, MemError> { + // Dispatcher for the instructions starting with 0b10 (Arithmetic) + match n1 { + 0b000 => self.add(self.r_reg(n2)?), + 0b001 => self.adc(self.r_reg(n2)?), + 0b010 => self.sub(self.r_reg(n2)?), + 0b011 => self.sbc(self.r_reg(n2)?), + 0b100 => self.and(self.r_reg(n2)?), + 0b101 => self.xor(self.r_reg(n2)?), + 0b110 => self.or(self.r_reg(n2)?), + 0b111 => self.cp(self.r_reg(n2)?), + _ => panic!(), + } - if n1 == 0b110 || n2 == 0b110 { + if n2 == 0b110 { Ok(8) } else { Ok(4) } } -} -pub fn op10(state: &mut GBState, n1: u8, n2: u8) -> Result<u64, MemError> { - // Dispatcher for the instructions starting with 0b10 (Arithmetic) - match n1 { - 0b000 => add(state, state.r_reg(n2)?), - 0b001 => adc(state, state.r_reg(n2)?), - 0b010 => sub(state, state.r_reg(n2)?), - 0b011 => sbc(state, state.r_reg(n2)?), - 0b100 => and(state, state.r_reg(n2)?), - 0b101 => xor(state, state.r_reg(n2)?), - 0b110 => or(state, state.r_reg(n2)?), - 0b111 => cp(state, state.r_reg(n2)?), - _ => panic!(), - } - - if n2 == 0b110 { - Ok(8) - } else { - Ok(4) - } -} - -pub fn op11(state: &mut GBState, n1: u8, n2: u8) -> Result<u64, MemError> { - match n2 { - 0b000 => match n1 { - 0b100 => { - let n = r_8b_from_pc(state)?; - ldnna(state, n as u16 | 0xff00)?; - Ok(12) - } - 0b101 => addsp8(state), - 0b110 => { - let n = r_8b_from_pc(state)?; - ldann(state, n as u16 | 0xff00)?; - Ok(12) - } - 0b111 => { - let n = r_8b_from_pc(state)?; - ldrr16(state, reg::HL, n as u16 + state.cpu.sp); - Ok(12) - } - _ => retcc(state, n1 & 0b11), - }, - 0b001 => match n1 { - 0b001 => ret(state), - 0b011 => { - state.mem.ime = true; - - ret(state) - } - 0b101 => Ok(jphl(state)), - 0b111 => Ok(ldsphl(state)), - _ => { - let p = pop(state)?; - state.cpu.r[(n1 >> 1) as usize * 2 + 1] = (p & 0xff) as u8; - state.cpu.r[(n1 >> 1) as usize * 2] = (p >> 8) as u8; - Ok(12) - } - }, - 0b010 => match n1 { - 0b100 => { - ldnna(state, state.cpu.r[reg::C as usize] as u16 | 0xff00)?; - Ok(8) - } - 0b101 => { - let nn = r_16b_from_pc(state)?; - ldnna(state, nn)?; - Ok(16) - } + fn op11(&mut self, n1: u8, n2: u8) -> Result<u64, MemError> { + match n2 { + 0b000 => match n1 { + 0b100 => { + let n = self.r_8b_from_pc()?; + self.ldnna(n as u16 | 0xff00)?; + Ok(12) + } + 0b101 => self.addsp8(), + 0b110 => { + let n = self.r_8b_from_pc()?; + self.ldann(n as u16 | 0xff00)?; + Ok(12) + } + 0b111 => { + let n = self.r_8b_from_pc()?; + self.ldrr16(reg::HL, n as u16 + self.cpu.sp); + Ok(12) + } + _ => self.retcc(n1 & 0b11), + }, + 0b001 => match n1 { + 0b001 => self.ret(), + 0b011 => { + self.mem.ime = true; + + self.ret() + } + 0b101 => Ok(self.jphl()), + 0b111 => Ok(self.ldsphl()), + _ => { + let p = self.pop()?; + self.cpu.r[(n1 >> 1) as usize * 2 + 1] = (p & 0xff) as u8; + self.cpu.r[(n1 >> 1) as usize * 2] = (p >> 8) as u8; + Ok(12) + } + }, + 0b010 => match n1 { + 0b100 => { + self.ldnna(self.cpu.r[reg::C as usize] as u16 | 0xff00)?; + Ok(8) + } + 0b101 => { + let nn = self.r_16b_from_pc()?; + self.ldnna(nn)?; + Ok(16) + } + 0b110 => { + self.ldann(self.cpu.r[reg::C as usize] as u16 | 0xff00)?; + Ok(8) + } + 0b111 => { + let nn = self.r_16b_from_pc()?; + self.ldann(nn)?; + Ok(16) + } + _ => self.jpcc16(n1 & 0b11), + }, + 0b011 => match n1 { + 0b000 => self.jp16(), + 0b001 => self.op_bitwise(), // Bitwise operations + 0b010 | 0b011 | 0b100 | 0b101 => unimplemented!(), + 0b110 => { + self.mem.ime = false; + Ok(4) + } + 0b111 => { + self.mem.ime = true; + Ok(4) + } + _ => panic!(), + }, + 0b100 => self.callcc(n1 & 0b11), + 0b101 => match n1 { + 0b001 => self.call(), + 0b011 | 0b101 | 0b111 => unimplemented!(), + _ => { + let value = self.cpu.r[(n1 >> 1) as usize * 2 + 1] as u16 + | ((self.cpu.r[(n1 >> 1) as usize * 2] as u16) << 8); + self.push(value)?; + Ok(16) + } + }, 0b110 => { - ldann(state, state.cpu.r[reg::C as usize] as u16 | 0xff00)?; + let p = self.r_8b_from_pc()?; + + match n1 { + 0b000 => self.add(p), + 0b001 => self.adc(p), + 0b010 => self.sub(p), + 0b011 => self.sbc(p), + 0b100 => self.and(p), + 0b101 => self.xor(p), + 0b110 => self.or(p), + 0b111 => self.cp(p), + _ => panic!(), + } Ok(8) } 0b111 => { - let nn = r_16b_from_pc(state)?; - ldann(state, nn)?; + let p = n1 << 3; + + self.push(self.cpu.pc)?; + self.cpu.pc = p as u16; Ok(16) - } - _ => jpcc16(state, n1 & 0b11), - }, - 0b011 => match n1 { - 0b000 => jp16(state), - 0b001 => op_bitwise(state), // Bitwise operations - 0b010 | 0b011 | 0b100 | 0b101 => unimplemented!(), - 0b110 => { - state.mem.ime = false; - Ok(4) - } - 0b111 => { - state.mem.ime = true; - Ok(4) - } + } // RST _ => panic!(), - }, - 0b100 => callcc(state, n1 & 0b11), - 0b101 => match n1 { - 0b001 => call(state), - 0b011 | 0b101 | 0b111 => unimplemented!(), - _ => { - let value = state.cpu.r[(n1 >> 1) as usize * 2 + 1] as u16 - | ((state.cpu.r[(n1 >> 1) as usize * 2] as u16) << 8); - push(state, value)?; - Ok(16) - } - }, - 0b110 => { - let p = r_8b_from_pc(state)?; - - match n1 { - 0b000 => add(state, p), - 0b001 => adc(state, p), - 0b010 => sub(state, p), - 0b011 => sbc(state, p), - 0b100 => and(state, p), - 0b101 => xor(state, p), - 0b110 => or(state, p), - 0b111 => cp(state, p), - _ => panic!(), - } - Ok(8) } - 0b111 => { - let p = n1 << 3; + } - push(state, state.cpu.pc)?; - state.cpu.pc = p as u16; + fn op_bitwise(&mut self) -> Result<u64, MemError> { + let p = self.r_8b_from_pc()?; + let opcode = p >> 6; + let n1 = p >> 3 & 0b111; + let n2 = p & 0b111; + + match opcode { + 0b00 => match n1 { + 0b000 => self.rlc(n2), + 0b001 => self.rrc(n2), + 0b010 => self.rl(n2), + 0b011 => self.rr(n2), + 0b100 => self.sla(n2), + 0b101 => self.sra(n2), + 0b110 => self.swap(n2), + 0b111 => self.srl(n2), + _ => panic!(), + }, + 0b01 => self.bit(n1, n2), + 0b10 => self.res(n1, n2), + 0b11 => self.set(n1, n2), + _ => panic!(), + }?; + if n2 == 0b110 { Ok(16) - } // RST - _ => panic!(), + } else { + Ok(8) + } } -} -pub fn op_bitwise(state: &mut GBState) -> Result<u64, MemError> { - let p = r_8b_from_pc(state)?; - let opcode = p >> 6; - let n1 = p >> 3 & 0b111; - let n2 = p & 0b111; - - match opcode { - 0b00 => match n1 { - 0b000 => rlc(state, n2), - 0b001 => rrc(state, n2), - 0b010 => rl(state, n2), - 0b011 => rr(state, n2), - 0b100 => sla(state, n2), - 0b101 => sra(state, n2), - 0b110 => swap(state, n2), - 0b111 => srl(state, n2), + pub fn exec_opcode(&mut self) -> Result<u64, MemError> { + let opcode = self.mem.r(self.cpu.pc)?; + + if self.is_debug { + println!( + "{:02x}:{:04x} = {:02x} (IME: {})", + self.mem.rom_bank, self.cpu.pc, opcode, self.mem.ime + ); + } + + self.cpu.pc += 1; + + let n1 = (opcode >> 3) & 0b111; + let n2 = opcode & 0b111; + + match opcode >> 6 { + 0b00 => self.op00(n1, n2), + 0b01 => self.op01(n1, n2), + 0b10 => self.op10(n1, n2), + 0b11 => self.op11(n1, n2), _ => panic!(), - }, - 0b01 => bit(state, n1, n2), - 0b10 => res(state, n1, n2), - 0b11 => set(state, n1, n2), - _ => panic!(), - }?; - if n2 == 0b110 { - Ok(16) - } else { - Ok(8) + } } } |