Add support for combined registers
parent
607e4ab2df
commit
ac6097794d
121
src/register.rs
121
src/register.rs
|
@ -3,7 +3,7 @@
|
|||
|
||||
const INITIAL_PROGRAM_COUNTER_VALUE: u16 = 0x100;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Flag {
|
||||
Zero,
|
||||
Subtract,
|
||||
|
@ -11,6 +11,16 @@ pub enum Flag {
|
|||
Carry,
|
||||
}
|
||||
|
||||
// Combined represents a pair of two registers taht can be acted on as a single
|
||||
// 16 bit register.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Combined {
|
||||
AF,
|
||||
BC,
|
||||
DE,
|
||||
HL,
|
||||
}
|
||||
|
||||
/// Registers holds all of the registers for the Gameboy
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Registers {
|
||||
|
@ -90,6 +100,45 @@ impl Registers {
|
|||
// ... and set it to our new value
|
||||
self.flags |= bit << pos;
|
||||
}
|
||||
|
||||
/// Get the value of a pair of registers
|
||||
pub fn get_combined_register(&self, registers: Combined) -> u16 {
|
||||
let (left_register, right_register) = self.get_register_values_for_combined(registers);
|
||||
let mut res = 0_u16;
|
||||
res |= u16::from(left_register) << 8;
|
||||
res |= u16::from(right_register);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Set the value of a pair of registers
|
||||
pub fn set_combined_register(&mut self, registers: Combined, value: u16) {
|
||||
let (left_register, right_register) = self.get_register_mut_refs_for_combined(registers);
|
||||
let [left_value, right_value] = value.to_be_bytes();
|
||||
|
||||
*left_register = left_value;
|
||||
*right_register = right_value;
|
||||
}
|
||||
|
||||
// TODO: These two could be simplified with macros
|
||||
|
||||
fn get_register_values_for_combined(&self, registers: Combined) -> (u8, u8) {
|
||||
match registers {
|
||||
Combined::AF => (self.a, self.f),
|
||||
Combined::BC => (self.b, self.c),
|
||||
Combined::DE => (self.d, self.e),
|
||||
Combined::HL => (self.h, self.l),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_register_mut_refs_for_combined(&mut self, registers: Combined) -> (&mut u8, &mut u8) {
|
||||
match registers {
|
||||
Combined::AF => (&mut self.a, &mut self.f),
|
||||
Combined::BC => (&mut self.b, &mut self.c),
|
||||
Combined::DE => (&mut self.d, &mut self.e),
|
||||
Combined::HL => (&mut self.h, &mut self.l),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -109,4 +158,74 @@ mod tests {
|
|||
registers.set_flag_bit(flag, 0);
|
||||
assert_eq!(0, registers.get_flag_bit(flag));
|
||||
}
|
||||
|
||||
#[test_case(Combined::AF)]
|
||||
#[test_case(Combined::BC)]
|
||||
#[test_case(Combined::DE)]
|
||||
#[test_case(Combined::HL)]
|
||||
fn test_combined_registers(registers: Combined) {
|
||||
let mut register = Registers::new();
|
||||
register.set_combined_register(registers, 0xF0_0F);
|
||||
|
||||
let stored_value = register.get_combined_register(registers);
|
||||
assert_eq!(
|
||||
0xF0_0F, stored_value,
|
||||
"got {stored_value:0x}, expected 0xF0_0F"
|
||||
);
|
||||
}
|
||||
|
||||
// I don't think there's a nice way to parametrize these tests without
|
||||
// it being more work than its worth
|
||||
|
||||
#[test]
|
||||
fn test_get_combined_registers_af() {
|
||||
let mut registers = Registers::new();
|
||||
registers.a = 0b11_10_00_01;
|
||||
registers.f = 0b10_00_01_11;
|
||||
|
||||
let combined_value = registers.get_combined_register(Combined::AF);
|
||||
assert_eq!(
|
||||
0b11_10_00_01_10_00_01_11, combined_value,
|
||||
"got {combined_value:0b}, expected 1110000110000111"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_combined_registers_bc() {
|
||||
let mut registers = Registers::new();
|
||||
registers.b = 0b00_11_00_11;
|
||||
registers.c = 0b11_00_11_00;
|
||||
|
||||
let combined_value = registers.get_combined_register(Combined::BC);
|
||||
assert_eq!(
|
||||
0b00_11_00_11_11_00_11_00, combined_value,
|
||||
"got {combined_value:0b}, expected 0011001111001100"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_combined_registers_de() {
|
||||
let mut registers = Registers::new();
|
||||
registers.d = 0b11_10_00_01;
|
||||
registers.e = 0b10_00_01_11;
|
||||
|
||||
let combined_value = registers.get_combined_register(Combined::DE);
|
||||
assert_eq!(
|
||||
0b11_10_00_01_10_00_01_11, combined_value,
|
||||
"got {combined_value:0b}, expected 1110000110000111"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_combined_registers_hl() {
|
||||
let mut registers = Registers::new();
|
||||
registers.h = 0b00_11_00_11;
|
||||
registers.l = 0b11_00_11_00;
|
||||
|
||||
let combined_value = registers.get_combined_register(Combined::HL);
|
||||
assert_eq!(
|
||||
0b00_11_00_11_11_00_11_00, combined_value,
|
||||
"got {combined_value:0b}, expected 0011001111001100"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue