From 4ffc735eeb6c5148b7255a954ea36f91cdb777cf Mon Sep 17 00:00:00 2001
From: Aaditya Dhruv <aadityadhruv@mailbox.org>
Date: Thu, 28 Dec 2023 16:28:17 -0600
Subject: Add barebones CPU structure

---
 .gitignore       |   1 +
 Cargo.lock       | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Cargo.toml       |   1 +
 src/cpu/chip.rs  | 109 +++++++++++++++++++++++++++
 src/cpu/dassm.rs |   0
 src/cpu/mod.rs   |   2 +
 src/main.rs      |  20 ++++-
 7 files changed, 355 insertions(+), 1 deletion(-)
 create mode 100644 Cargo.lock
 create mode 100644 src/cpu/chip.rs
 create mode 100644 src/cpu/dassm.rs
 create mode 100644 src/cpu/mod.rs

diff --git a/.gitignore b/.gitignore
index ea8c4bf..ff0915e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
+*.gb
 /target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..98bd4d1
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,223 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anstream"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "clap"
+version = "4.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "gameboy"
+version = "0.1.0"
+dependencies = [
+ "clap",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "syn"
+version = "2.0.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
diff --git a/Cargo.toml b/Cargo.toml
index e212b65..74f5753 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,3 +6,4 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+clap = { version = "4.4.12", features = ["derive"] }
diff --git a/src/cpu/chip.rs b/src/cpu/chip.rs
new file mode 100644
index 0000000..4866ff7
--- /dev/null
+++ b/src/cpu/chip.rs
@@ -0,0 +1,109 @@
+use std::fs::File;
+use std::io::Read;
+
+
+#[derive(Debug)]
+pub struct Flags {
+    pub zero: u8, //Zero flag
+    pub n: u8, //Subtraction flag (BCD)
+    pub h: u8, //Half carry flag (BCD)
+    pub carry: u8, //Carry flag
+}
+
+impl Flags {
+    fn new() -> Self {
+        Flags {
+            zero: 0,
+            n: 0,
+            h: 0,
+            carry: 0,
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct Chip {
+    pub a: u8, //Upper bits of AF, the Accumulator
+    pub b: u8,
+    pub c: u8,
+    pub d: u8,
+    pub e: u8,
+    pub h: u8,
+    pub l: u8,
+    pub instr: u8, //Current instruction
+    pub sp: u16, //Stack pointer
+    pub pc: u16, //Program counter
+    pub byte2: u8,
+    pub byte3: u8,
+    pub flags: Flags, //Lower bits of AF, Flags register
+    pub rom_bank_0: [u8; 16384],
+    pub rom_bank_n: [u8; 16384],
+    pub external_ram_bank_n: [u8; 8192],
+    pub wram_bank_0: [u8; 4096],
+    pub wram_bank_n: [u8; 4096],
+
+}
+
+impl Chip {
+    pub fn new() -> Self {
+        Chip {
+            a: 0,
+            b: 0,
+            c: 0,
+            d: 0,
+            e: 0,
+            h: 0,
+            l: 0,
+            instr: 0,
+            sp: 0,
+            pc: 0,
+            byte2: 0,
+            byte3: 0,
+            flags: Flags::new(),
+            rom_bank_0: [0; 16384],
+            rom_bank_n: [0; 16384],
+            external_ram_bank_n: [00; 8192],
+            wram_bank_0: [0; 4096],
+            wram_bank_n: [0; 4096],
+        }
+    }
+    pub fn load_rom(&mut self, rom_path: &str) {
+        let mut rom_buf = Vec::new();
+        let mut rom = File::open(rom_path).unwrap_or_else(|_err| panic!("Valid ROM needed!"));
+        rom.read_to_end(&mut rom_buf).unwrap_or_else(|_err| panic!("Error reading ROM"));
+
+	for i in 0..self.rom_bank_0.len() {
+            self.rom_bank_0[i] = rom_buf.get(i).unwrap().to_owned();
+        }
+    }
+    pub fn read_memory(&self, pc: usize) -> u8 {
+        let address = match pc {
+            0x0000..=0x3fff => { self.rom_bank_0[self.pc as usize]  }, //Fixed bank, rom_bank_0
+            0x4000..=0x7fff => { self.rom_bank_n[self.pc as usize - 0x4000] },
+            0x8000..=0x9fff => { 0x0 },
+            0xa000..=0xbfff => { 0x0 },
+            0xc000..=0xcfff => { 0x0 },
+            0xd000..=0xdfff => { 0x0 },
+            0xfe00..=0xfe9f => { 0x0 },
+            0xff00..=0xff7f => { 0x0 },
+            0xff80..=0xfffe => { 0x0 },
+            0xffff..=0xffff => { 0x0 },
+            _ => { 0xff }
+        };
+        address
+    }
+    pub fn fetch(&mut self) {
+        self.instr = self.read_memory(self.pc as usize);
+        let arg1 = self.read_memory(self.pc as usize + 1);
+        let arg2 = self.read_memory(self.pc as usize + 2);
+        self.byte2 = arg1;
+        self.byte3 = arg2;
+        self.pc += 1;
+    }
+    pub fn execute(&self) {
+
+        match self.instr {
+            _ => { panic!("Error: 0x{:02X} not implemented!", self.instr) }
+        }
+    }
+}
diff --git a/src/cpu/dassm.rs b/src/cpu/dassm.rs
new file mode 100644
index 0000000..e69de29
diff --git a/src/cpu/mod.rs b/src/cpu/mod.rs
new file mode 100644
index 0000000..ba87d03
--- /dev/null
+++ b/src/cpu/mod.rs
@@ -0,0 +1,2 @@
+pub mod chip;
+pub mod dassm;
diff --git a/src/main.rs b/src/main.rs
index e7a11a9..5a29737 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,21 @@
+use clap::Parser;
+mod cpu;
+
+#[derive(Parser, Debug)]
+#[command(author, version, about, long_about = None)]
+struct Args {
+    // Name of the ROM file
+    #[arg(short, long)]
+    name: String,
+}
+
+
 fn main() {
-    println!("Hello, world!");
+    let args = Args::parse();
+    let mut cpu = cpu::chip::Chip::new();
+    cpu.load_rom(&args.name);
+    loop {
+        cpu.fetch();
+        cpu.execute();
+    }
 }
-- 
cgit