From 8952ff3546692b79170677a952d6b06cd84fa55b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sat, 25 Jun 2022 17:23:07 +0100
Subject: [PATCH] feat: more instructions added

---
 src/cpu.rs | 202 +++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 164 insertions(+), 38 deletions(-)

diff --git a/src/cpu.rs b/src/cpu.rs
index f655d593..7034b441 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -1,10 +1,17 @@
 pub const RAM_SIZE: usize = 8192;
 
-pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 4] = [
+pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 11] = [
     // 0x0 opcodes
     (nop, 4, "NOP"),
     (ld_bc_u16, 12, "LD BC, NN"),
-    (ld_bc_a, 8, "LD BC, A"),
+    (ld_mbc_a, 8, "LD [BC], A"),
+    (inc_bc, 8, "INC BC"),
+    (inc_b, 4, "INC B"),
+    (dec_b, 4, "DEC B"),
+    (ld_b_u8, 8, "LD B, N"),
+    (rlca, 4, "RLCA"),
+    (ld_mu16_sp, 20, "LD [u16], SP"),
+    (add_hl_bc, 8, "ADD HL, BC"),
     // 0x2 opcodes
     (ld_sp_u16, 12, "LD SP, NN"),
 ];
@@ -12,14 +19,17 @@ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 4] = [
 pub struct Cpu {
     pc: u16,
     sp: u16,
-    reg_a: u8,
-    reg_b: u8,
-    reg_c: u8,
-    reg_d: u8,
-    reg_e: u8,
-    reg_f: u8,
-    reg_h: u8,
-    reg_l: u8,
+    a: u8,
+    b: u8,
+    c: u8,
+    d: u8,
+    e: u8,
+    h: u8,
+    l: u8,
+    zero: bool,
+    sub: bool,
+    half_carry: bool,
+    carry: bool,
     ram: [u8; RAM_SIZE],
 }
 
@@ -28,14 +38,17 @@ impl Cpu {
         Cpu {
             pc: 0x0,
             sp: 0x0,
-            reg_a: 0x0,
-            reg_b: 0x0,
-            reg_c: 0x0,
-            reg_d: 0x0,
-            reg_e: 0x0,
-            reg_f: 0x0,
-            reg_h: 0x0,
-            reg_l: 0x0,
+            a: 0x0,
+            b: 0x0,
+            c: 0x0,
+            d: 0x0,
+            e: 0x0,
+            h: 0x0,
+            l: 0x0,
+            zero: false,
+            sub: false,
+            half_carry: false,
+            carry: false,
             ram: [0u8; RAM_SIZE],
         }
     }
@@ -43,74 +56,187 @@ impl Cpu {
     pub fn clock(&mut self) {
         // fetches the current instruction and increments
         // the PC (program counter) accordingly
-        let instruction = self.ram[self.pc as usize];
+        let _instruction = self.ram[self.pc as usize];
         self.pc += 1;
     }
 
     #[inline(always)]
-    fn reg_af(&self) -> u16 {
-        (self.reg_a as u16) << 8 | self.reg_f as u16
+    fn af(&self) -> u16 {
+        (self.a as u16) << 8 | self.f() as u16
     }
 
     #[inline(always)]
-    fn reg_bc(&self) -> u16 {
-        (self.reg_b as u16) << 8 | self.reg_c as u16
+    fn bc(&self) -> u16 {
+        (self.b as u16) << 8 | self.c as u16
     }
 
     #[inline(always)]
-    fn reg_de(&self) -> u16 {
-        (self.reg_d as u16) << 8 | self.reg_e as u16
+    fn f(&self) -> u8 {
+        let mut f = 0x0u8;
+        if self.zero {
+            f |= 0x80;
+        }
+        if self.sub {
+            f |= 0x40;
+        }
+        if self.half_carry {
+            f |= 0x20;
+        }
+        if self.carry {
+            f |= 0x10;
+        }
+        f
+    }
+
+    #[inline(always)]
+    fn set_bc(&mut self, value: u16) {
+        self.b = (value >> 8) as u8;
+        self.c = value as u8;
+    }
+
+    #[inline(always)]
+    fn de(&self) -> u16 {
+        (self.d as u16) << 8 | self.e as u16
+    }
+
+    #[inline(always)]
+    fn set_de(&mut self, value: u16) {
+        self.d = (value >> 8) as u8;
+        self.e = value as u8;
     }
 
     #[inline(always)]
-    fn reg_hl(&self) -> u16 {
-        (self.reg_h as u16) << 8 | self.reg_l as u16
+    fn hl(&self) -> u16 {
+        (self.h as u16) << 8 | self.l as u16
+    }
+
+    #[inline(always)]
+    fn set_hl(&mut self, value: u16) {
+        self.h = (value >> 8) as u8;
+        self.l = value as u8;
     }
 
     #[inline(always)]
     fn read_u8(&mut self) -> u8 {
         let byte = self.ram[self.pc as usize];
-        self.pc += 1;
+        self.pc = self.pc.wrapping_add(1);
         byte
     }
 
     #[inline(always)]
     fn read_u16(&mut self) -> u16 {
-        let word = (self.ram[self.pc as usize] as u16) << 8 | self.ram[self.pc as usize + 1] as u16;
-        self.pc += 2;
+        let byte1 = self.read_u8();
+        let byte2 = self.read_u8();
+        let word = byte1 as u16 | ((byte2 as u16) << 8);
         word
     }
 
     #[inline(always)]
     fn get_zero(&self) -> bool {
-        self.reg_f & 0x40 == 1
+        self.zero
+    }
+
+    #[inline(always)]
+    fn set_zero(&mut self, value: bool) {
+        self.zero = value
     }
 
     #[inline(always)]
     fn get_sub(&self) -> bool {
-        self.reg_f & 0x20 == 1
+        self.sub
+    }
+
+    #[inline(always)]
+    fn set_sub(&mut self, value: bool) {
+        self.sub = value;
     }
 
     #[inline(always)]
     fn get_half_carry(&self) -> bool {
-        self.reg_f & 0x10 == 1
+        self.half_carry
+    }
+
+    #[inline(always)]
+    fn set_half_carry(&mut self, value: bool) {
+        self.half_carry = value
     }
 
     #[inline(always)]
     fn get_carry(&self) -> bool {
-        self.reg_f & 0x08 == 1
+        self.carry
+    }
+
+    #[inline(always)]
+    fn set_carry(&mut self, value: bool) {
+        self.carry = value;
     }
 }
 
 fn nop(_cpu: &mut Cpu) {}
 
 fn ld_bc_u16(cpu: &mut Cpu) {
-    cpu.reg_b = cpu.read_u8();
-    cpu.reg_c = cpu.read_u8();
+    let word = cpu.read_u16();
+    cpu.set_bc(word);
+}
+
+fn ld_mbc_a(cpu: &mut Cpu) {
+    cpu.ram[cpu.bc() as usize] = cpu.a;
+}
+
+fn inc_bc(cpu: &mut Cpu) {
+    cpu.set_bc(cpu.bc().wrapping_add(1));
 }
 
-fn ld_bc_a(cpu: &mut Cpu) {
-    cpu.ram[cpu.reg_bc() as usize] = cpu.reg_a;
+fn inc_b(cpu: &mut Cpu) {
+    let value = cpu.b.wrapping_add(1);
+
+    cpu.set_sub(false);
+    cpu.set_zero(value == 0);
+    cpu.set_half_carry((value & 0xf) == 0xf);
+
+    cpu.b = value;
+}
+
+fn dec_b(cpu: &mut Cpu) {
+    let value = cpu.b.wrapping_sub(1);
+
+    cpu.set_sub(true);
+    cpu.set_zero(value == 0);
+    cpu.set_half_carry((value & 0xf) == 0xf);
+
+    cpu.b = value;
+}
+
+fn ld_b_u8(cpu: &mut Cpu) {
+    let byte = cpu.read_u8();
+    cpu.b = byte;
+}
+
+fn rlca(cpu: &mut Cpu) {
+    let carry = cpu.a >> 7;
+
+    cpu.a = cpu.a << 1 | carry;
+
+    cpu.set_sub(false);
+    cpu.set_zero(false);
+    cpu.set_half_carry(false);
+    cpu.set_carry(carry == 1);
+}
+
+fn ld_mu16_sp(cpu: &mut Cpu) {
+    let word = cpu.read_u16();
+    cpu.ram[word as usize] = cpu.sp as u8;
+    cpu.ram[word as usize + 1] = (cpu.sp >> 8) as u8;
+}
+
+fn add_hl_bc(cpu: &mut Cpu) {
+    let value = cpu.hl() as u32 + cpu.bc() as u32;
+
+    cpu.set_sub(false);
+    cpu.set_carry(value & 0x1000 == 0x1000);
+    cpu.set_half_carry((value & 0xff) == 0xff); //@todo I'm not sure about this one
+
+    cpu.set_hl(value as u16);
 }
 
 fn ld_sp_u16(cpu: &mut Cpu) {
-- 
GitLab