diff options
author | Aaditya Dhruv <[email protected]> | 2025-06-05 16:47:37 -0500 |
---|---|---|
committer | Aaditya Dhruv <[email protected]> | 2025-08-26 22:32:33 -0500 |
commit | f2c7452d9e9bce50961f25df26721f8e038656bf (patch) | |
tree | 74f36cb93df1fdd3ca7c5fa150be20ac952e913d | |
parent | 688851c6c56776dc57cb6159840e868f6544d157 (diff) |
Update get/set register methods
Create R8/R16 enums, From<u8> trait
Update method usage
-rw-r--r-- | src/cpu/chip.rs | 264 |
1 files changed, 181 insertions, 83 deletions
diff --git a/src/cpu/chip.rs b/src/cpu/chip.rs index e5af381..cf9ef2b 100644 --- a/src/cpu/chip.rs +++ b/src/cpu/chip.rs @@ -3,6 +3,77 @@ use std::io::Read; #[derive(Debug)] +enum REGISTER8 { + UD = -1, + B = 0, + C = 1, + D = 2, + E = 3, + H = 4, + L = 5, + HL = 6, + A = 7, +} + +impl From<u8> for REGISTER8 { + fn from(value: u8) -> Self { + match value { + 0 => REGISTER8::B, + 1 => REGISTER8::C, + 2 => REGISTER8::D, + 3 => REGISTER8::E, + 4 => REGISTER8::H, + 5 => REGISTER8::L, + 6 => REGISTER8::HL, + 7 => REGISTER8::B, + _ => REGISTER8::UD + } + } +} + +#[derive(Debug)] +enum REGISTER16 { + UD = -1, + BC = 0b001, + DE = 0b011, + HL = 0b101, + SP = 0b111, +} + +impl From<u8> for REGISTER16 { + fn from(value: u8) -> Self { + match value { + 0b001 => REGISTER16::BC, + 0b011 => REGISTER16::DE, + 0b101 => REGISTER16::HL, + 0b111 => REGISTER16::SP, + _ => REGISTER16::UD + } + } +} + +#[derive(Debug)] +enum REGISTER16MEM { + UD = -1, + BC = 0b001, + DE = 0b011, + HLI = 0b101, //HL+ + HLD = 0b111, //HL- +} + +impl From<u8> for REGISTER16MEM { + fn from(value: u8) -> Self { + match value { + 0b001 => REGISTER16MEM::BC, + 0b011 => REGISTER16MEM::DE, + 0b101 => REGISTER16MEM::HLI, + 0b111 => REGISTER16MEM::HLD, + _ => REGISTER16MEM::UD + } + } +} + +#[derive(Debug)] pub struct Flags { pub zero: u8, //Zero flag pub n: u8, //Subtraction flag (BCD) @@ -78,10 +149,17 @@ impl Chip { } self.pc = 0x0100; } - pub fn write_memory(&mut self, pc: u16, value: u8) { - match pc { - 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 }, + /// Write to memory + /// Write a 8 bit value to memory addressed in 16 bits + /// The function decides which bank to write to based on the address value + /// # Arguments + /// + /// * `address` - Address to write to + /// * `value` - Value to write to address + pub fn write_memory(&mut self, address: u16, value: u8) { + match address { + 0x0000..=0x3fff => { println!("Writing: ROM Bank 0"); self.rom_bank_0[address as usize] = value }, //Fixed bank, rom_bank_0 + 0x4000..=0x7fff => { println!("Writing: ROM Bank 1"); self.rom_bank_n[address as usize - 0x4000] = value }, 0x8000..=0x9fff => { }, 0xa000..=0xbfff => { }, 0xc000..=0xcfff => { }, @@ -93,10 +171,16 @@ impl Chip { _ => { } }; } - pub fn read_memory(&self, pc: u16) -> u8 { - let address = match pc { - 0x0000..=0x3fff => { println!("ROM Bank 0"); self.rom_bank_0[pc as usize] }, //Fixed bank, rom_bank_0 - 0x4000..=0x7fff => { println!("ROM Bank 1"); self.rom_bank_n[pc as usize - 0x4000] }, + /// Read from memory + /// Same as write_memory, but read from the correct rom bank instead + /// # Arguments + /// + /// * `address` - 16 bit address to access + /// + pub fn read_memory(&self, address: u16) -> u8 { + let address = match address { + 0x0000..=0x3fff => { println!("ROM Bank 0"); self.rom_bank_0[address as usize] }, //Fixed bank, rom_bank_0 + 0x4000..=0x7fff => { println!("ROM Bank 1"); self.rom_bank_n[address as usize - 0x4000] }, 0x8000..=0x9fff => { 0x0 }, 0xa000..=0xbfff => { 0x0 }, 0xc000..=0xcfff => { 0x0 }, @@ -120,84 +204,98 @@ impl Chip { println!("0x{:02X?}", &self.rom_bank_0[self.pc as usize..(self.pc + 10) as usize]); } - //Lookup the u8 register table to get the u16 address we want to look at. We are constructing the address - //to read/write from/to based on this table - fn get_r16_register_address(&self, register_code: u8) -> u16 { - //Example - // reg b = 0x00ca - // reg c = 0x00fe - // reg b << 8 = 0xca00 - // bitwise OR with reg c results in 0xcafe + + /// Return the value of a register + /// + /// # Arguments + /// + /// * `register_code` - The code of the register to access + /// + fn get_r8_register(&mut self, register_code: REGISTER8) -> u8 { match register_code { - 0b001 => { (self.b as u16) << 8 | self.c as u16 }, - 0b011 => { (self.d as u16) << 8 | self.e as u16 }, - 0b101 => {(self.h as u16) << 8 | self.l as u16 }, - 0b111 => { self.sp }, - _ => { panic!("Cannot get register address: Unknown register code {}", register_code) } + REGISTER8::B => { self.b }, + REGISTER8::C => { self.c }, + REGISTER8::D => { self.d }, + REGISTER8::E => { self.e }, + REGISTER8::H => { self.h }, + REGISTER8::L => { self.l }, + REGISTER8::HL=> { let memory_address = self.get_r16_register(REGISTER16::HL); self.read_memory(memory_address) }, //[HL] + REGISTER8::A => { self.a }, + _ => { panic!("Cannot get register code: Unknown register code {:?}", register_code) } + } } - - fn get_r8_register(&mut self, register_code: u8) -> u8 { + /// Set a register's value + /// + /// # Arguments + /// + /// * `register_code` - The register to change + /// * `value` - New value of register + /// + fn set_r8_register(&mut self, register_code: REGISTER8, value: u8) { match register_code { - 0 => { self.b }, - 1 => { self.c }, - 2 => { self.d }, - 3 => { self.e }, - 4 => { self.h }, - 5 => { self.l }, - 6 => { let memory_address = self.get_r16_register_memory_address(0b101); self.read_memory(memory_address) }, //[HL] - 7 => { self.a }, - _ => { panic!("Cannot get register code: Unknown register code {}", register_code) } + REGISTER8::B => { self.b = value }, + REGISTER8::C => { self.c = value }, + REGISTER8::D => { self.d = value }, + REGISTER8::E => { self.e = value }, + REGISTER8::H => { self.h = value }, + REGISTER8::L => { self.l = value }, + REGISTER8::HL => { let memory_address = self.get_r16_register(REGISTER16::HL); self.write_memory(memory_address, value) }, //[HL] + REGISTER8::A => { self.a = value }, + _ => { panic!("Cannot get register code: Unknown register code {:?}", register_code) } } } - fn set_r8_register(&mut self, register_code: u8, value: u8) { + //Lookup the u8 register table to get the u16 address we want to look at. We are constructing the address + //to read/write from/to based on this table + fn get_r16_register(&self, register_code: REGISTER16) -> u16 { + //Example + // reg b = 0x00ca + // reg c = 0x00fe + // reg b << 8 = 0xca00 + // bitwise OR with reg c results in 0xcafe match register_code { - 0 => { self.b = value }, - 1 => { self.c = value }, - 2 => { self.d = value }, - 3 => { self.e = value }, - 4 => { self.h = value }, - 5 => { self.l = value }, - 6 => { let memory_address = self.get_r16_register_memory_address(0b101); self.write_memory(memory_address, value) }, //[HL] - 7 => { self.a = value }, - _ => { panic!("Cannot get register code: Unknown register code {}", register_code) } - + REGISTER16::BC => { (self.b as u16) << 8 | self.c as u16 }, + REGISTER16::DE => { (self.d as u16) << 8 | self.e as u16 }, + REGISTER16::HL => {(self.h as u16) << 8 | self.l as u16 }, + REGISTER16::SP => { self.sp }, + _ => { panic!("Cannot get register address: Unknown register code {:?}", register_code) } } } + // Write a 16 bit value to a pair of registers based on the usual pairing - fn set_r16_register_address(&mut self, register_code: u8, value: u16) { + fn set_r16_register(&mut self, register_code: REGISTER16, value: u16) { let high = (value >> 8) as u8; let low = (value & 0xff) as u8; match register_code { - 0b001 => { self.b = high; self.c = low; }, - 0b011 => { self.d = high; self.e = low; }, - 0b101 => { self.h = high; self.l = low; }, - 0b111 => { self.sp = value; }, - _ => { panic!("Cannot set register address: Unknown register code {}", register_code) } + REGISTER16::BC => { self.b = high; self.c = low; }, + REGISTER16::DE => { self.d = high; self.e = low; }, + REGISTER16::HL => { self.h = high; self.l = low; }, + REGISTER16::SP => { self.sp = value; }, + _ => { panic!("Cannot set register address: Unknown register code {:?}", register_code) } }; } // Get the memory address pointed to by a register pair. This is basically the r16mem table // This returns a 16 bit memory address - fn get_r16_register_memory_address(&mut self, register_code: u8) -> u16 { + fn get_r16mem_register(&mut self, register_code: REGISTER16MEM) -> u16 { match register_code { - 0b001 => { (self.b as u16) << 8 | self.c as u16 }, - 0b011 => { (self.d as u16) << 8 | self.e as u16 }, - 0b101 => { + REGISTER16MEM::BC => { (self.b as u16) << 8 | self.c as u16 }, + REGISTER16MEM::DE => { (self.d as u16) << 8 | self.e as u16 }, + REGISTER16MEM::HLI => { let hl = (self.h as u16) << 8 | self.l as u16; //Get current HL value - self.set_r16_register_address(0b101, hl+1); //Increment HL value and set it back to HL (ptr++) + self.set_r16_register(REGISTER16::HL, hl+1); //Increment HL value and set it back to HL (ptr++) hl //Return HL }, - 0b111 => { + REGISTER16MEM::HLD => { let hl = (self.h as u16) << 8 | self.l as u16; //Get current HL value - self.set_r16_register_address(0b101, hl-1); //Decrement HL value and set it back to HL (ptr--) + self.set_r16_register(REGISTER16::HL, hl-1); //Decrement HL value and set it back to HL (ptr--) hl //Return HL }, - _ => { panic!("Cannot get register address: Unknown register code {}", register_code) } + _ => { panic!("Cannot get register address: Unknown register code {:?}", register_code) } } } @@ -271,15 +369,15 @@ impl Chip { // Load value from dst_r8 into src_r8. When called as LD r1 r2, this method // is called as ld_r8_r8(r2, r1) (Notice the inversion) fn ld_r8_r8(&mut self, src_r8: u8, dst_r8: u8) { - let value = self.get_r8_register(src_r8); - self.set_r8_register(dst_r8, value); + let value = self.get_r8_register(src_r8.into()); + self.set_r8_register(dst_r8.into(), value); } fn ldh_r16_a(&mut self, memory: u8) { let memory: u16 = 0xFF00 + memory as u16; if memory < 0xffff && memory > 0xff00 { - let value = self.get_r8_register(7); + let value = self.get_r8_register(REGISTER8::L); self.write_memory(memory, value); } } @@ -296,61 +394,61 @@ impl Chip { //Increment value in register r8 by 1 fn inc_r8(&mut self, register_lookup: u8) { - let register = self.get_r8_register(register_lookup); + let register = self.get_r8_register(register_lookup.into()); let sum = register.wrapping_add(1); if sum == 0 { self.flags.zero = 0 } self.flags.n = 0; let (half_carry, _) = self.check_carry_add_u8(register, 1); if half_carry { self.flags.h = 1 } - self.set_r8_register(register_lookup, sum); + self.set_r8_register(register_lookup.into(), sum); } //Decrement value in register r8 by 1 fn dec_r8(&mut self, register_lookup: u8) { - let register = self.get_r8_register(register_lookup); + let register = self.get_r8_register(register_lookup.into()); let sum = register.wrapping_sub(1); if sum == 0 { self.flags.zero = 0 } self.flags.n = 1; let (half_carry, _) = self.check_carry_sub_u8(register, 1); if half_carry{ self.flags.h = 1 } - self.set_r8_register(register_lookup, sum); + self.set_r8_register(register_lookup.into(), sum); } //Increment value in register r16 by 1 fn inc_r16(&mut self, register_lookup: u8) { - let mut register = self.get_r16_register_address(register_lookup); + let mut register = self.get_r16_register(register_lookup.into()); register = register.wrapping_add(1); - self.set_r16_register_address(register_lookup, register); + self.set_r16_register(register_lookup.into(), register); } //Decrement value in register r16 by 1 fn dec_r16(&mut self, register_lookup: u8) { - let mut register = self.get_r16_register_address(register_lookup); + let mut register = self.get_r16_register(register_lookup.into()); register = register.wrapping_sub(1); - self.set_r16_register_address(register_lookup, register); + self.set_r16_register(register_lookup.into(), register); } //Load value n8 into register r8 fn ld_r8_n8(&mut self, r8: u8) { - self.set_r8_register(r8, self.byte2); + self.set_r8_register(r8.into(), self.byte2); } //Load value pointed in memory by r16 register pair into register A fn ld_a_r16_addr(&mut self, register_lookup: u8) { - let memory_address = self.get_r16_register_memory_address(register_lookup); + let memory_address = self.get_r16mem_register(register_lookup.into()); self.a = self.read_memory(memory_address); } // Load the 8 bit value in register A to the memory address pointed by the register from the // table fn ld_r16_addr_a(&mut self, register_lookup: u8) { - let memory_address = self.get_r16_register_memory_address(register_lookup); + let memory_address = self.get_r16mem_register(register_lookup.into()); self.write_memory(memory_address, self.a); } //Add register r16 value to HL fn add_hl_r16(&mut self, register_lookup: u8) { - let r16 = self.get_r16_register_address(register_lookup); - let hl = self.get_r16_register_address(0b101); //0b101 == HL register pair + let r16 = self.get_r16_register(register_lookup.into()); + let hl = self.get_r16_register(REGISTER16::HL); //0b101 == HL register pair let (sum, overflow_high) = r16.overflowing_add(hl); //Additions reset the n flag @@ -360,13 +458,13 @@ impl Chip { //Check 15th to 16th bit overflow if overflow_high { self.flags.carry = 1 } - self.set_r16_register_address(0b101, sum); + self.set_r16_register(REGISTER16::HL, sum); } //Load value u16 into register r16 fn ld_r16_u16(&mut self, register_lookup: u8) { let address = (self.byte2 as u16) << 8 | self.byte3 as u16; - self.set_r16_register_address(register_lookup, address); + self.set_r16_register(register_lookup.into(), address); } //Conditional Jump @@ -415,7 +513,7 @@ impl Chip { //Add the value in r8 to the a register fn add_a_r8(&mut self, r8: u8) { - let reg_val = self.get_r8_register(r8); + let reg_val = self.get_r8_register(r8.into()); let (half_carry, carry) = self.check_carry_add_u8(self.a, reg_val); self.a = self.a.wrapping_add(reg_val); if half_carry { self.flags.h = 1 } @@ -425,7 +523,7 @@ impl Chip { } //Add the value in r8 to the a register, along with the value of the carry flag fn adc_a_r8(&mut self, r8: u8) { - let sum = self.get_r8_register(r8).wrapping_add(self.flags.carry); + let sum = self.get_r8_register(r8.into()).wrapping_add(self.flags.carry); let (half_carry, carry) = self.check_carry_add_u8(self.a, sum); self.a = self.a.wrapping_add(sum); @@ -437,7 +535,7 @@ impl Chip { } //Sub the value in r8 from the a register fn sub_a_r8(&mut self, r8: u8) { - let reg_val = self.get_r8_register(r8); + let reg_val = self.get_r8_register(r8.into()); let (half_carry, carry) = self.check_carry_sub_u8(self.a, reg_val); self.a = self.a.wrapping_sub(reg_val); @@ -448,7 +546,7 @@ impl Chip { } //Sub the value in r8 from the a register along with the value of the carry flag fn sbc_a_r8(&mut self, r8: u8) { - let sum = self.get_r8_register(r8).wrapping_add(self.flags.carry); + let sum = self.get_r8_register(r8.into()).wrapping_add(self.flags.carry); let (half_carry, carry) = self.check_carry_sub_u8(self.a, sum); self.a = self.a.wrapping_sub(sum); @@ -460,7 +558,7 @@ impl Chip { //Bitwise AND between r8 value and A fn and_a_r8(&mut self, r8: u8) { - self.a = self.a & self.get_r8_register(r8); + self.a = self.a & self.get_r8_register(r8.into()); if self.a == 0 { self.flags.zero = 0 } self.flags.n = 0; self.flags.h = 1; @@ -469,7 +567,7 @@ impl Chip { //Bitwise XOR between r8 value and A fn xor_a_r8(&mut self, r8: u8) { - self.a = self.a ^ self.get_r8_register(r8); + self.a = self.a ^ self.get_r8_register(r8.into()); if self.a == 0 { self.flags.zero = 0 } self.flags.n = 0; self.flags.h = 0; @@ -478,7 +576,7 @@ impl Chip { //Bitwise OR between r8 value and A fn or_a_r8(&mut self, r8: u8) { - self.a = self.a | self.get_r8_register(r8); + self.a = self.a | self.get_r8_register(r8.into()); if self.a == 0 { self.flags.zero = 0 } self.flags.n = 0; self.flags.h = 0; @@ -487,7 +585,7 @@ impl Chip { //Subtract value in r8 from A, but don't store the result, only set flags fn cp_a_r8(&mut self, r8: u8) { - let reg_val = self.get_r8_register(r8); + let reg_val = self.get_r8_register(r8.into()); let (half_carry, carry) = self.check_carry_sub_u8(self.a, reg_val); let tmp = self.a.wrapping_sub(reg_val); |