diff options
author | Aaditya Dhruv <[email protected]> | 2024-08-06 05:58:43 -0500 |
---|---|---|
committer | Aaditya Dhruv <[email protected]> | 2024-08-06 05:58:43 -0500 |
commit | 9e085ccd25a74a330cf472678f6a8cf52c2ee865 (patch) | |
tree | bff37c3d714037fdd3e2abe3922a6fd6bf0315ea | |
parent | 45fec56a9ee8231fb129f4250f24e8bceefd6eec (diff) |
Add more opcode implementation
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/cpu/chip.rs | 157 |
2 files changed, 134 insertions, 24 deletions
@@ -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; |