aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaditya Dhruv <[email protected]>2024-08-06 05:58:43 -0500
committerAaditya Dhruv <[email protected]>2024-08-06 05:58:43 -0500
commit9e085ccd25a74a330cf472678f6a8cf52c2ee865 (patch)
treebff37c3d714037fdd3e2abe3922a6fd6bf0315ea
parent45fec56a9ee8231fb129f4250f24e8bceefd6eec (diff)
Add more opcode implementation
-rw-r--r--.gitignore1
-rw-r--r--src/cpu/chip.rs157
2 files changed, 134 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore
index ff0915e..6cee822 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
*.gb
+**tags**
/target
diff --git a/src/cpu/chip.rs b/src/cpu/chip.rs
index ed373b3..fe869d3 100644
--- a/src/cpu/chip.rs
+++ b/src/cpu/chip.rs
@@ -41,6 +41,7 @@ pub struct Chip {
pub external_ram_bank_n: [u8; 8192],
pub wram_bank_0: [u8; 4096],
pub wram_bank_n: [u8; 4096],
+ pub rom: Vec<u8>,
}
@@ -65,22 +66,22 @@ impl Chip {
external_ram_bank_n: [00; 8192],
wram_bank_0: [0; 4096],
wram_bank_n: [0; 4096],
+ rom: Vec::new(),
}
}
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"));
+ rom.read_to_end(&mut self.rom).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();
+ self.rom_bank_0[i] = self.rom.get(i).unwrap().to_owned();
}
self.pc = 0x0100;
}
- pub fn write_memory(&mut self, pc: usize, value: u8) {
+ pub fn write_memory(&mut self, pc: u16, value: u8) {
match pc {
- 0x0000..=0x3fff => { println!("ROM Bank 0"); self.rom_bank_0[pc as usize] = value }, //Fixed bank, rom_bank_0
- 0x4000..=0x7fff => { println!("ROM Bank 1"); self.rom_bank_n[pc as usize - 0x4000] = value },
+ 0x0000..=0x3fff => { println!("Writing: ROM Bank 0"); self.rom_bank_0[pc as usize] = value }, //Fixed bank, rom_bank_0
+ 0x4000..=0x7fff => { println!("Writing: ROM Bank 1"); self.rom_bank_n[pc as usize - 0x4000] = value },
0x8000..=0x9fff => { },
0xa000..=0xbfff => { },
0xc000..=0xcfff => { },
@@ -122,18 +123,123 @@ impl Chip {
pub fn execute(&mut self) {
let mut next = 0;
- match self.instr {
- 0x00 => { println!("NOOP!") }
- 0x32 => { self.ldd_hl_a() }
- 0x0e | 0x06 => { self.ld_rr(); next = 1; }
- 0xc3 => { self.jmp_nn() }
- 0xa8..=0xaf => { self.xor_r() }
- 0x01 | 0x11 | 0x21 | 0x31 => { self.ld_rr_nn(); next = 2; },
- _ => { println!("Error: 0x{:02X} not implemented!", self.instr); std::process::exit(1); }
+ println!("{:b}", self.instr);
+ let oct1 = (self.instr & 0b11000000) >> 6;
+ let oct2 = (self.instr & 0b00111000) >> 3;
+ let oct3 = self.instr & 0b00000111;
+ println!("{:b} {:b} {:b}", oct1, oct2, oct3);
+
+ match (oct1, oct2, oct3) {
+ (0b11, 0b001, 0b001) => { }, //CB-prefixed instructions
+ (0b00, 0b000, 0b000) => { println!("NOOP") }, //noop
+ (0b00, 0b001, 0b000) => { self.ld_xx_sp() }, //LD (u16), SP
+ (0b00, 0b010, 0b000) => { println!("STOP") }, //STOP
+ (0b00, 0b011, 0b000) => { self.jr() }, //JR
+ (0b00, 0b100..=0b111, 0b000) => { self.jr_cond(oct2) }, //JR conditonal
+ (0b00,0b000|0b010|0b100|0b110, 0b001) => { self.ld_xx_rr(oct2) }, //LD r16, u16
+ (0b00,0b001|0b011|0b101|0b111, 0b001) => { self.add_hl_rr(oct22) }, //ADD HL, r16
+ (0b00,0b000|0b010|0b100|0b110, 0b010) => { }, //LD (r16), A
+ (0b00,0b001|0b011|0b101|0b111, 0b010) => { }, //LD A, (r16)
+ (0b00,0b000|0b010|0b100|0b110, 0b011) => { }, //INC r16
+ (0b00,0b001|0b011|0b101|0b111, 0b011) => { }, //DEC r16
+ (0b00, r8, 0b100) => { }, //INC r8
+ (0b00, r8, 0b101) => { }, //DEC r8
+ (0b00, r8, 0b110) => { }, //LD r8, u8
+ (0b00, opcode, 0b111) => { }, //Opcode grp 1
+ (0b01, 0b110, 0b110) => { }, //HALT
+ (0b01, src_r8, dst_r8) => { }, //LD r8, r8
+ (0b10, op, r8) => { self.alu_a_r8(op, r8); }, //ALU A, r8
+ (0b11, 0b000..=0b011, 0b000) => { }, //RET condition
+ (0b11, 0b100, 0b000) => { }, //LD (FF00 + u8), A
+ (0b11, 0b101, 0b000) => { }, //ADD SP, i8
+ (0b11, 0b110, 0b000) => { }, //LD A, (FF00 + u8)
+ (0b11, 0b111, 0b000) => { }, //LD HL, SP + i8
+ (0b11, 0b000|0b010|0b100|0b110, 0b001) => { }, //POP r16
+ (0b11, 0b001|0b011|0b101|0b111, 0b001) => { }, //0: RET, 1: RETI, 2: JP HL, 3: LD SP, HL
+ (0b11, 0b000..=0b011, 0b010) => { }, //JP
+ (0b11, 0b100, 0b010) => { }, //LD (FF00 + C), A
+ (0b11, 0b101, 0b010) => { }, //LD (u16), A
+ (0b11, 0b110, 0b010) => { }, //LD A, (FF00 + C)
+ (0b11, 0b111, 0b010) => { }, //LD A, (u16)
+ (0b11, opcode, 0b011) => { }, //0: JP u16, 1: CB prefix, 6: DI, 7: EI
+ (0b11, 0b000..=0b011, 0b100) => { }, //CALL condition
+ (0b11, 0b000|0b010|0b100|0b110, 0b101) => { }, //PUSH r16
+ (0b11, 0b001, 0b101) => { }, //CALL u16
+ (0b11, opcode, 0b110) => { }, //ALU a, u8
+ (0b11, exp, 0b111) => { }, //RST
+ _ => { println!("Error: 0x{:02X} not implemented!", self.instr); std::process::exit(1); },
}
+
+// match self.instr {
+// 0x00 => { println!("NOOP!") }
+// 0x32 => { self.ldd_hl_a() }
+// 0x0e | 0x06 => { self.ld_rr(); next = 1; }
+// 0xa8..=0xaf => { self.xor_r() }
+// 0x01 | 0x11 | 0x21 | 0x31 => { self.ld_rr_nn(); next = 2; },
+// _ => { println!("Error: 0x{:02X} not implemented!", self.instr); std::process::exit(1); }
+// }
self.pc += next;
}
+
+ //Add register r16 value to HL
+ fn add_hl_rr(&mut self, register: u8) {
+ self.h = self.byte3;
+ self.l = self.byte2;
+ //Additions reset the n flag
+ self.flags.n = 0;
+
+ }
+
+ //Load value u16 into register r16
+ fn ld_xx_rr(&mut self, register: u8) {
+ match register {
+ 0b000 => {self.b = self.byte3; self.c = self.byte2; },
+ 0b010 => { self.d = self.byte3; self.e = self.byte2; },
+ 0b100 => { self.h = self.byte3; self.l = self.byte2; },
+ 0b110 => { self.sp = (self.byte3 as u16) << 8 | self.byte2 as u16; },
+ _c => { panic!("Unknown condition {}", _c) }
+ }
+ }
+
+ //Conditional Jump
+ fn jr_cond(&mut self, condition: u8) {
+
+ let mut should_execute = false;
+ match condition {
+ 0b100 => { should_execute = self.flags.zero != 0 },
+ 0b101 => { should_execute = self.flags.zero == 0},
+ 0b110 => { should_execute = self.flags.carry != 0 },
+ 0b111 => { should_execute = self.flags.carry == 0 },
+ _c => { panic!("Unknown condition {}", _c) }
+ }
+ if should_execute {
+ let offset: i8 = self.byte2 as i8;
+ self.pc.wrapping_add_signed(offset.into());
+ }
+ }
+
+ //Unconditional Jump
+ fn jr(&mut self) {
+ let offset: i8 = self.byte2 as i8;
+ self.pc.wrapping_add_signed(offset.into());
+ }
+
+ //Store SP lower at address u16, and SP upper at address u16 + 1
+ fn ld_xx_sp(&mut self) {
+ let address: u16 = (self.byte2 << 8) as u16 | self.byte3 as u16;
+ self.write_memory(address, (self.sp & 0xff) as u8);
+ self.write_memory(address + 1, (self.sp & 0xff00 >> 8) as u8);
+ }
+
+ fn alu_a_r8(&mut self, opcode: u8, r8: u8) {
+ match opcode {
+ 1 => { self.adc_r(r8) },
+ 5 => { self.xor_r(r8) },
+ _ => {}
+ }
+ }
+
fn ld_rr(&mut self) {
match self.instr {
0x0e => { self.c = self.byte2 },
@@ -150,19 +256,22 @@ impl Chip {
self.l = (pc << 8 >> 8) as u8;
}
- fn xor_r(&mut self) {
- let value = match self.instr & 0x0f {
- 0x8 => { self.b },
- 0x9 => { self.c },
- 0xa => { self.d },
- 0xb => { self.e },
- 0xc => { self.h },
- 0xd => { self.l },
- 0xe => {
+ fn adc_r(&mut self, r8: u8) {
+ self.a += (self.flags.carry + r8);
+ }
+ fn xor_r(&mut self, r8: u8) {
+ let value = match r8 {
+ 0 => { self.b },
+ 1 => { self.c },
+ 2 => { self.d },
+ 3 => { self.e },
+ 4 => { self.h },
+ 5 => { self.l },
+ 6 => {
let ptr = ((self.h as u16) << 8) as u16 | self.l as u16;
self.read_memory(ptr as usize)
},
- 0xf => { self.a },
+ 7 => { self.a },
_ => { panic!("Wrong register read for XOR_R") }
};
self.a = self.a ^ value;