use std::mem::transmute; use crate::{verbose_println, Memory, State}; mod instructions; mod opcodes; #[derive(PartialEq)] pub(crate) enum FLAGS { Zero = 7, NSubtract = 6, HalfCarry = 5, Carry = 4, } pub(crate) enum Direction { Left, Right, } pub struct CPU { pub memory: Memory, pub state: State, pub last_instruction: u8, pub last_instruction_addr: u16, } impl CPU { pub fn exec_next(&mut self) { unsafe { self.last_instruction_addr = self.state.pc.as_u16 }; let opcode = self.next_opcode(); self.last_instruction = opcode; verbose_println!( "exec {:#4X} from pc: {:#X}", opcode, self.last_instruction_addr ); self.run_opcode(opcode); } fn next_opcode(&mut self) -> u8 { unsafe { let opcode = self.memory.get(self.state.pc.as_u16); self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(0x1); return opcode; }; } } fn as_signed(unsigned: u8) -> i8 { unsafe { return transmute(unsigned); } } fn get_bit(byte: u8, flag: u8) -> bool { let mask = 1 << flag; let got = byte & mask; return got > 0x0; } fn rotate(byte: u8, direction: &Direction) -> (u8, bool) { match direction { Direction::Left => { let carry = get_bit(byte, 7); let r = byte << 1; return (r, carry); } Direction::Right => { let carry = get_bit(byte, 0); let r = byte >> 1; return (r, carry); } } } fn get_rotation_carry(direction: &Direction) -> u8 { match direction { Direction::Left => 0b1, Direction::Right => 0b10000000, } } fn swap_nibbles(byte: u8) -> u8 { (byte & 0x0F) << 4 | (byte & 0xF0) >> 4 } fn res(byte: u8, bit: u8) -> u8 { byte & !(1 << bit) } fn set(byte: u8, bit: u8) -> u8 { byte | (1 << bit) }