diff --git a/src/bus.rs b/src/bus.rs new file mode 100644 index 0000000..adbd46e --- /dev/null +++ b/src/bus.rs @@ -0,0 +1,14 @@ +#[derive(Debug, Copy, Clone)] +pub struct MemoryBus { + +} + +impl MemoryBus { + pub fn read_byte(&self, _address: u16) { + unimplemented!() + } + + pub fn write_byte(&self, _address: u16) { + unimplemented!() + } +} \ No newline at end of file diff --git a/src/cpu.rs b/src/cpu.rs index b19fb09..673b0c8 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1,365 +1,91 @@ -// use super::instructions::Instruction; +use super::bus::MemoryBus; +use std::ops::{Index, IndexMut}; +use std::convert::From; -// Gameboy CPU +#[derive(Debug, Copy, Clone)] pub struct LR35902 { - _sp: u16, - _pc: u16, - _reg: Registers, + bus: MemoryBus, + registers: Registers, + sp: u16, // Stack Pointer + pc: u16, // Program Counter + flag: Flag, // Flag Register + ime: bool, // Interrupt Master Enable Flag } -impl LR35902 { - pub fn cycle(&mut self) { - let opcode = Self::fetch(); - self.decode(opcode); - Self::execute(); - } +#[derive(Debug, Copy, Clone)] +pub struct Flag { + z: bool, // Zero Flag + n: bool, // Subtract Flag + h: bool, // Half-Carry Flag + c: bool, // Carry Flag +} - fn fetch() -> u8 { - unimplemented!() - } - - fn decode(&mut self, opcode: u8) { - // Source: https://gb-archive.github.io/salvage/decoding_gbz80_opcodes/Decoding%20Gamboy%20Z80%20Opcodes.html - // x = the opcode's 1st octal digit (i.e. bits 7-6) - // y = the opcode's 2nd octal digit (i.e. bits 5-3) - // z = the opcode's 3rd octal digit (i.e. bits 2-0) - // p = y right-shifted one position (i.e. bits 5-4) - // q = y modulo 2 (i.e. bit 3) - - let x = opcode >> 6; - let y = (opcode & 0b00111000) >> 3; // 0b00111000 = 0x38 - let z = opcode & 0b00000111; // 0b00000111 = 0x07 - let p = y >> 1; - let q = y & 0b00000001; // 0b001 = 0x1; - - let _d: i8 = 0; // Displacement Byte - let _n: u8 = 0; // 8-bit Immediate Operand - let _nn: u16 = 0; // 16-bit Immediate Operand - - match (x, z, q, y, p) { - (0, 0, _, 0, _) => {} - _ => panic!("Unexpected Opcode!"), +impl From for Flag { + fn from(num: u8) -> Self { + Flag { + z: (num >> 7) == 1, + n: ((num >> 6) & 0x01) == 1, + h: ((num >> 5) & 0x01) == 1, + c: ((num >> 4) & 0x01) == 1, } } - fn execute() { - unimplemented!() +} + +impl From for u8 { + fn from(flag: Flag) -> Self { + (flag.z as u8) << 7 | (flag.n as u8) << 6 | (flag.h as u8) << 5 | (flag.c as u8) << 4 } } -#[derive(Debug, Copy, Clone, Default)] +#[derive(Debug, Copy, Clone)] pub struct Registers { - a: u8, // Accumulator Register + a: u8, b: u8, c: u8, d: u8, e: u8, h: u8, l: u8, - f: Flag, } -impl Registers { - pub fn set_af(&mut self, value: u16) { - let (high, low) = Self::split_u16(value); - - self.a = high; - self.f = low.into(); - } - - pub fn get_af(&self) -> u16 { - Self::merge_u8s(self.a, self.f.into()) - } - - pub fn set_bc(&mut self, value: u16) { - let (high, low) = Self::split_u16(value); - - self.b = high; - self.c = low; - } - - pub fn get_bc(&self) -> u16 { - Self::merge_u8s(self.b, self.c) - } - - pub fn set_de(&mut self, value: u16) { - let (high, low) = Self::split_u16(value); - - self.d = high; - self.e = low; - } - - pub fn get_de(&self) -> u16 { - Self::merge_u8s(self.d, self.e) - } - - pub fn set_hl(&mut self, value: u16) { - let (high, low) = Self::split_u16(value); - - self.h = high; - self.l = low; - } - - pub fn get_hl(&self) -> u16 { - Self::merge_u8s(self.h, self.l) - } - - pub fn set_a(&mut self, a: u8) { - self.a = a; - } - - pub fn get_a(&self) -> u8 { - self.a - } - - pub fn set_b(&mut self, b: u8) { - self.b = b; - } - - pub fn get_b(&self) -> u8 { - self.b - } - - pub fn set_c(&mut self, c: u8) { - self.c = c; - } - - pub fn get_c(&self) -> u8 { - self.c - } - - pub fn set_d(&mut self, d: u8) { - self.d = d; - } - - pub fn get_d(&self) -> u8 { - self.d - } - - pub fn set_e(&mut self, e: u8) { - self.e = e; - } - - pub fn get_e(&self) -> u8 { - self.e - } - - pub fn set_h(&mut self, h: u8) { - self.h = h; - } - - pub fn get_h(&self) -> u8 { - self.h - } - - pub fn set_l(&mut self, l: u8) { - self.l = l; - } - - pub fn get_l(&self) -> u8 { - self.l - } - - pub fn set_f>(&mut self, flag: F) { - self.f = flag.into(); - } - - pub fn get_f(&self) -> Flag { - self.f - } - - pub fn get_u8_f(&self) -> u8 { - self.f.into() - } - - fn split_u16(value: u16) -> (u8, u8) { - ((value >> 8) as u8, value as u8) - } - - fn merge_u8s(left: u8, right: u8) -> u16 { - (left as u16) << 8 | right as u16 +impl Index for Registers { + type Output = u8; + + fn index(&self, index: Register) -> &Self::Output { + match index { + Register::A => &self.a, + Register::B => &self.b, + Register::C => &self.c, + Register::D => &self.d, + Register::E => &self.e, + Register::H => &self.h, + Register::L => &self.l, + } } } -#[derive(Debug, Copy, Clone, Default)] -pub struct Flag(u8); - -impl Flag { - pub fn get_zf(&self) -> bool { - (self.0 >> 7) == 1 - } - - pub fn set_zf(&mut self, enabled: bool) { - if enabled { - self.0 |= 0b10000000; // Set - } else { - self.0 &= 0b01111111; // Clear - } - } - - pub fn get_n(&self) -> bool { - ((self.0 >> 6) & 0x01) == 1 - } - - pub fn set_n(&mut self, enabled: bool) { - if enabled { - self.0 |= 0b01000000; // Set - } else { - self.0 &= 0b10111111; // Clear - } - } - - pub fn get_h(&self) -> bool { - ((self.0 >> 5) & 0x01) == 1 - } - - pub fn set_h(&mut self, enabled: bool) { - if enabled { - self.0 |= 0b00100000; // Set - } else { - self.0 &= 0b11011111; // Clear - } - } - - pub fn get_cy(&self) -> bool { - ((self.0 >> 4) & 0x01) == 1 - } - - pub fn set_cy(&mut self, enabled: bool) { - if enabled { - self.0 |= 0b00010000; // Set - } else { - self.0 &= 0b11101111; // Clear +impl IndexMut for Registers { + fn index_mut(&mut self, index: Register) -> &mut Self::Output { + match index { + Register::A => &mut self.a, + Register::B => &mut self.b, + Register::C => &mut self.c, + Register::D => &mut self.d, + Register::E => &mut self.e, + Register::H => &mut self.h, + Register::L => &mut self.l, } } } -impl From for Flag { - fn from(value: u8) -> Self { - Self(value & 0xF0) // Throw out bits 0 -> 3 - } -} - -impl From for u8 { - fn from(flag: Flag) -> Self { - flag.0 - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn flag_zf_works() { - let mut flag: Flag = Default::default(); - - flag.set_zf(true); - assert_eq!(u8::from(flag), 0b10000000); - assert!(flag.get_zf()); - - flag.set_zf(false); - assert_eq!(u8::from(flag), 0b00000000); - assert!(!flag.get_zf()); - } - - #[test] - fn flag_n_works() { - let mut flag: Flag = Default::default(); - - flag.set_n(true); - assert_eq!(u8::from(flag), 0b01000000); - assert!(flag.get_n()); - - flag.set_n(false); - assert_eq!(u8::from(flag), 0b00000000); - assert!(!flag.get_n()); - } - - #[test] - fn flag_h_works() { - let mut flag: Flag = Default::default(); - - flag.set_h(true); - assert_eq!(u8::from(flag), 0b00100000); - assert!(flag.get_h()); - - flag.set_h(false); - assert_eq!(u8::from(flag), 0b00000000); - assert!(!flag.get_h()); - } - - #[test] - fn flags_work_together() { - let mut flag: Flag = Default::default(); - assert_eq!(u8::from(flag), 0b00000000); - - flag.set_zf(true); - flag.set_cy(true); - flag.set_h(true); - flag.set_n(true); - - assert_eq!(u8::from(flag), 0b11110000); - assert!(flag.get_zf()); - assert!(flag.get_n()); - assert!(flag.get_h()); - assert!(flag.get_cy()); - - flag.set_cy(false); - assert_eq!(u8::from(flag), 0b11100000); - assert!(!flag.get_cy()); - - flag.set_n(false); - assert_eq!(u8::from(flag), 0b10100000); - assert!(!flag.get_n()); - } - - #[test] - fn flag_to_u8_and_back_works() { - let flag: Flag = 0b10011111.into(); - assert_eq!(u8::from(flag), 0b10010000); - assert_eq!(flag.0, 0b10010000); - assert!(flag.get_zf()); - assert!(!flag.get_n()); - assert!(!flag.get_h()); - assert!(flag.get_cy()); - - let mut base: Flag = Default::default(); - base.set_h(true); - base.set_zf(true); - - assert_eq!(base.0, 0b10100000); - assert_eq!(u8::from(base), 0b10100000); - } - - #[test] - fn flag_cy_works() { - let mut flag: Flag = Default::default(); - - flag.set_cy(true); - assert_eq!(u8::from(flag), 0b00010000); - assert!(flag.get_cy()); - - flag.set_cy(false); - assert_eq!(u8::from(flag), 0b00000000); - assert!(!flag.get_cy()); - } - - #[test] - fn split_u16_works() { - let num = 0xABCD; - - let (high, low) = Registers::split_u16(num); - assert_eq!(high, 0xAB); - assert_eq!(low, 0xCD); - } - - #[test] - fn merge_u8s_works() { - let left = 0xAB; - let right = 0xCD; - - let res = Registers::merge_u8s(left, right); - assert_eq!(res, 0xABCD); - } -} +#[derive(Debug, Copy, Clone)] +pub enum Register { + A, + B, + C, + D, + E, + H, + L, +} \ No newline at end of file diff --git a/src/instructions.rs b/src/instructions.rs deleted file mode 100644 index ff76221..0000000 --- a/src/instructions.rs +++ /dev/null @@ -1,389 +0,0 @@ -use super::cpu::Flag; -/// Sharp SM83 Instructions -/// ### Definitions -/// * "Any valid 8-bit register" refers to the registers `B`, `C`, `D`, `E`, `H` and `L`. -/// * If `A` is also a valid register, it will be **explicitly** stated as such. -/// * "Any valid 16-bit register" refers to the registers BC, DE and HL. -/// * If `AF` is a valid register, it will be **explicitly** stated as such. -/// * If `SP` is a valid register, it will be **explicitly** stated as such. -/// * the value of any 16-bit register in brackets is the value of the data located at -/// the address of the 16-bit register. -/// * e.g. the value of `(HL)` would be what is at `memory[cpu.reg.get_hl()]` -/// * Since the value is from memory, the value is an 8-bit integer. -pub struct Instruction {} - -impl Instruction { - // *** 8-bit Loads *** - - /// `LD nn, n` Store value nn in n. - /// ### Arguments - /// * `nn` Any valid 8-bit or 16-bit register (including `SP`). - /// * `n` An 8-bit immediate value. - pub fn ld_nn_n(nn: u16, n: &mut u8) { - unimplemented!() - } - - /// `LD r, r` Store value r2 into r1. - /// ### Arguments - /// * `r1` Any valid 8-bit register (including `A`), and `(HL)`. - /// * `r2` Any valid 8-bit register (including `A`), and `(HL)`. - pub fn ld_r1_r2(r1: &mut u8, r2: u8) { - unimplemented!() - } - - /// `LD A, n` Store value n into register A. - /// ### Arguments - /// * `a` The A register - /// * `n` Any valid 8-bit register (including `A`),`(BC)`, `(DE)`, `(HL)`, `(nn)`, and `#`. - /// * `nn` A two byte immediate value (Least significant byte first). - pub fn ld_a_n(a: &mut u8, n: u8) { - unimplemented!() - } - - /// `LD n, A` Store register A into n. - /// ### Arguments - /// * `n` Any valid 8-bit register (including `A`), `(BC)`, `(DE)`, `(HL)`, and `(nn)`. - /// * `nn` A two byte immediate value (Least significant byte first). - /// * `a` The A register. - pub fn ld_n_a(n: &mut u8, a: u8) { - unimplemented!() - } - - /// `LD A, (C)` Store value at $FF00 + register C in register A. - /// ### Arguments - /// * `a` The A register. - /// * `c` The C register. - pub fn ld_a_c(a: &mut u8, c: u8) { - unimplemented!() - } - - /// `LD (C) ,A` Store the value of register A into $FF00 + register C. - /// ### Arguments - /// * `c` The C register. - /// * `a` The A register. - pub fn ld_c_a(c: u8, a: u8) { - unimplemented!() - } - - // `LD A, (HLD)` is identical to `LDD A, (HL)`. - // `LD A, (HL-)` is identical to `LDD A, (HL)`. - - /// `LDD A, (HL)` Put value at $HL into A, then decrement HL. - /// - /// Identical to `LD A, (HLD)`, and `LD A, (HL-)`. - /// ### Arguments - /// * `a` The A register. - /// * `hl` The HL register - pub fn ldd_a_hl(a: &mut u8, hl: u16) { - unimplemented!() - } - - // `LD (HLD), A` is identical to `LDD (HL), A`. - // `LD (HL-), A` is identical to `LDD (HL), A`. - - /// `LDD (HL), A` Store register A in $HL, then decrement HL. - /// - /// Identical to `LD (HLD), A`, and `LD (HL-), A` - /// ### Arguments - /// * `hl` The HL register. - /// * `a` The A register. - pub fn ldd_hl_a(hl: u16, a: u8) { - unimplemented!() - } - - // `LD A, (HLI)` is identical to `LDI A, (HL)`. - // `LD A, (HL+)` is identical to `LDI A, (HL)`. - - /// `LDI A, (HL)` Store value at $HL in register A, then increment HL. - /// - /// Identical to `LD A, (HLI)`, and `LD A, (HL+)`. - /// ### Arguments - /// * `a` The A register. - /// * `hl` The HL register. - pub fn ldi_a_hl(a: &mut u8, hl: u16) { - unimplemented!() - } - - // `LD (HLI), A` is identical to `LDI (HL), A`. - // `LD (HL+), A` is identical to `LDI (HL), A`. - - /// `LDI (HL), A` Store register A in $HL, then increment HL. - /// - /// Identical to `LD (HLI), A`, and `LD (HL+), A`. - /// ### Arguments - /// * `hl` The HL register. - /// * `a` The A register. - pub fn ldi_hl_a(hl: u16, a: u8) { - unimplemented!() - } - - /// `LDH (n), A` Store register A into address $FF00 + n. - /// ### Arguments - /// * `n` An 8-bit immediate value. - /// * `a` The A register. - pub fn ldh_n_a(n: u8, a: u8) { - unimplemented!() - } - - /// `LDH A, (n)` Store address $FF00 + n in the A register. - /// ### Arguments - /// * `a` The A register. - /// * `n` An 8-bit immediate value - pub fn ldh_a_n(a: &mut u8, n: u8) { - unimplemented!() - } - - // *** 16-bit Loads *** - - /// `LD n, nn` Store value nn in n.(really?) - /// ### Arguments - /// * `n` Any 16-bit register (including `SP`). - /// * `nn` A 16-bit immediate value. - pub fn ld_n_nn(n: &mut u16, nn: u16) { - unimplemented!() - } - - /// `LD SP, HL` Put HL into the stack pointer. - /// ### Arguments - /// * `sp` The stack pointer register. - /// * `hl` The HL register. - pub fn ld_sp_hl(sp: &mut u16, hl: u16) { - unimplemented!() - } - - // `LD HL, SP + n` is identical to `LDHL SP, n`. - - /// `LDHL SP, n` "Put SP + n effective address into HL". - /// ### Arguments - /// * `hl` The HL register. - /// * `sp` The stack pointer register. - /// * `n` 8-bit **signed** integer. - /// * `f` CPU flags. - /// - /// ### Flags - /// * `ZF` Reset. - /// * `N` Reset. - /// * `H` Set / Reset depending on operation. - /// * `CY` Set / Reset depending on operation. - pub fn ldhl_sp_n(hl: &mut u16, sp: u16, n: i8, f: &mut Flag) { - unimplemented!() - } - - /// `LD (nn), SP` Store stack pointer at $nn. - /// ### Arguments - /// * `nn` A 16-bit immediate address. - /// * `sp` The stack pointer register. - pub fn ld_nn_sp(nn: u16, sp: u16) { - unimplemented!() - } - - /// `PUSH nn` Push 16-bit register onto the stack, then - /// decrement the stack pointer twice. - /// ### Arguments - /// * `nn` Any valid 16-bit address (including `AF`). - /// * `sp` The stack pointer register. - /// * `stack` The stack. - pub fn push_nn(nn: u16, sp: &mut u16, stack: &[u16]) { - unimplemented!() - } - - /// `POP nn` Pop two bytes of the stack into register pair nn, - /// then increment the stack pointer twice. - /// ### Arguments - /// `nn` Any valid 16-bit address (including `AF`). - /// `sp` The stack pointer register. - /// `stack` The stack. - pub fn pop_nn(nn: &mut u16, sp: &mut u16, stack: &[u16]) { - unimplemented!() - } - - // *** 8-bit ALU *** - - /// `ADD A, n` Add n to register A. - /// ### Arguments - /// `A` The A register - /// `nn` Any valid 8-bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is zero.. - /// `N` Reset. - /// `H` Set if carry from bit 3. - /// `CY` Set if carry from bit 7. - pub fn add_a_n(a: &mut u8, n: u8) { - unimplemented!() - } - - /// `ADC A, n` Add n + carry flag to register A. - /// ### Arguments - /// `A` The A register. - /// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is zero. - /// `N` Reset. - /// `H` Set if carry from bit 3. - /// `CY` Set if carry from bit 7. - pub fn adc_a_n(a: &mut u8, n: u8, f: &mut Flag) { - unimplemented!() - } - - /// `SUB n` or `SUB A, n` Subtract n from register A. - /// ### Arguments - /// `A` The A register. - /// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is 0. - /// `N` Set. - /// `H` Set if no borrow from bit 4. - /// `CY` Set if no borrow. - pub fn sub_a_n(a: &mut u8, n: u8) { - unimplemented!() - } - - /// `SBC A, n` Subtract n + carry flag from register A. - /// ### Arguments - /// `A` The A register. - /// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is 0. - /// `N` Set. - /// `H` Set if no borrow from bit 4. - /// `CY` Set if no borrow. - pub fn sbc_a_n(a: &mut u8, n: u8, f: &mut Flag) { - unimplemented!() - } - - /// `AND n` or `AND A, n` AND n with register A, - /// then store the result in register A. - /// ### Arguments - /// `A` The A register. - /// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is zero. - /// `N` Reset - /// `H` Set - /// `CY` Reset - pub fn and_a_n(a: &mut u8, n: u8, f: &mut Flag) { - unimplemented!() - } - - /// `OR n` or `OR A, n` OR n with register A, then store the result in register A - /// ### Arguments - /// `A` The A register. - /// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is zero. - /// `N` Reset. - /// `H` Reset. - /// `CY` Reset. - pub fn or_a_n(a: &mut u8, n: u8, f: &mut Flag) { - unimplemented!() - } - - /// `XOR n` or `XOR A, n` XOR n with register A, then store the result in register A. - /// ### Arguments - /// `A` The A register. - /// `n` Any valid -bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is zero. - /// `N` Reset. - /// `H` Reset. - /// `CY` Reset. - pub fn xor_a_n(a: &mut u8, n: u8) { - unimplemented!() - } - - /// `CP n` or `CP A, n` Compare register A with n. - /// - /// Note: This is equivalent with `SUB A, n` except that the result of the - /// subtraction is discarded. Only the flags are mutated. - /// ### Arguments - /// `A` The A register. - /// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`. - /// - /// ### Flags - /// `ZF` Set if result is zero ( A == n ). - /// `N` Set. - /// `H` Set if no borrow from bit 4. - /// `CY` Set for no borrow. ( A < n ). - pub fn cp_a_n(a: u8, n: u8) { - unimplemented!() - } - - /// `INC n` Increment register n. - /// ### Arguments - /// `n` Any valid 8-bit register (including `A`), and `(HL)`. - /// - /// ### Flags - /// `ZF` Set if result is zero. - /// `N` Reset. - /// `H` Set if carry from bit 3. - /// `CY` Not affected. - pub fn inc_n(n: &mut u8) { - unimplemented!() - } - - /// `DEC n` decrement register n. - /// ### Arguments - /// `n` Any 8-bit register (including `A`), and `(HL)`. - /// - /// ### Flags - /// `ZF` Set if result is zero. - /// `N` Set. - /// `H` Set if no borrow from bit 4. - /// `CY` Not affected. - pub fn dec_n(n: &mut u8) { - unimplemented!() - } - - // *** 16-bit Arithmetic *** - - /// `ADD HL, n` Add n to HL. - /// ### Arguments - /// `hl` The HL register. - /// `n` Any valid 16-bit address (including `SP`). - /// - /// ### Flags - /// `ZF` Not affected - /// `N` Reset - /// `H` Set if carry from bit 11. - /// `CY` Set if carry from bit 15. - pub fn add_hl_n(hl: &mut u16, n: u16) { - unimplemented!() - } - - /// `ADD SP, n` Add n to the stack pointer. - /// ### Arguments - /// `sp` The stack pointer register. - /// `n` AN 8-bit signed immediate value (#). - /// - /// ### Flags - /// `ZF` Reset - /// `N` Reset - /// `H` Set or reset according to operation. - /// `CY` Set or reset according to operation. - pub fn add_sp_n(sp: &mut u16, n: i8) { - unimplemented!() - } - - /// `INC nn` Increment register nn - /// ### Arguments - /// `nn` Any valid 16-bit register (including `SP`) - pub fn inc_nn(nn: &mut u16) { - unimplemented!() - } - - /// `DEC nn` Increment register nn - /// ### Arguments - /// `nn` Any valid 16-bit register (including `SP`) - pub fn dec_nn(nn: &mut u16) { - unimplemented!() - } - - // *** Miscellaneous *** -} diff --git a/src/lib.rs b/src/lib.rs index 38acf08..7d10108 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,4 @@ -pub mod cpu; -pub mod instructions; +pub use cpu::LR35902; + +pub mod bus; +pub mod cpu; \ No newline at end of file