From d85c7b8a9803fd447ceba48e28d4f420bd079d0e Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Sat, 9 Apr 2022 13:57:50 -0400 Subject: [PATCH] Add support for programatically manipulating 16 bit registers --- src/register.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/register.rs b/src/register.rs index 62dcda1..dda5d33 100644 --- a/src/register.rs +++ b/src/register.rs @@ -23,6 +23,12 @@ pub enum SingleEightBit { L, } +#[derive(Debug, Clone, Copy, strum_macros::Display)] +pub enum SixteenBit { + Combined(Combined), + Single(SingleSixteenBit), +} + // Combined represents a pair of two registers taht can be acted on as a single 8 bit // 16 bit register. #[derive(Debug, Clone, Copy, strum_macros::Display)] @@ -33,6 +39,12 @@ pub enum Combined { HL, } +#[derive(Debug, Clone, Copy, strum_macros::Display)] +pub enum SingleSixteenBit { + StackPointer, + ProgramCounter, +} + /// Registers holds all of the registers for the Gameboy #[derive(Debug, Clone)] pub struct Registers { @@ -141,7 +153,24 @@ impl Registers { *register_ref = value; } - /// Get the value of a pair of registers + /// Get the value of a 16 bit register, whether it's natively a 16 bit register or a combination of + /// 8 bit registers + pub fn get_16bit_register(&self, register: SixteenBit) -> u16 { + match register { + SixteenBit::Single(single) => self.get_single_16bit_register(single), + SixteenBit::Combined(combined) => self.get_combined_register(combined), + } + } + + /// Get the value of a single 16 bit register (i.e. a natively 16 bit register) + pub fn get_single_16bit_register(&self, register: SingleSixteenBit) -> u16 { + match register { + SingleSixteenBit::StackPointer => self.stack_pointer, + SingleSixteenBit::ProgramCounter => self.program_counter, + } + } + + /// Get the value of combined single 16 bit register (i.e. a combination of two 8 bit 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; @@ -151,6 +180,25 @@ impl Registers { res } + /// Set the value of a 16 bit register, whether it's natively a 16 bit register or a combination of + /// 8 bit registers + pub fn set_16bit_register(&mut self, register: SixteenBit, value: u16) { + match register { + SixteenBit::Single(single) => self.set_single_16bit_register(single, value), + SixteenBit::Combined(combined) => self.set_combined_register(combined, value), + } + } + + /// Set the value of a single 16 bit register (i.e. a natively 16 bit register) + pub fn set_single_16bit_register(&mut self, register: SingleSixteenBit, value: u16) { + let register_ref = match register { + SingleSixteenBit::StackPointer => &mut self.stack_pointer, + SingleSixteenBit::ProgramCounter => &mut self.program_counter, + }; + + *register_ref = value; + } + /// 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); @@ -268,4 +316,24 @@ mod tests { "got {combined_value:0b}, expected 0011001111001100" ); } + + #[test_case(Combined::AF)] + #[test_case(Combined::BC)] + #[test_case(Combined::DE)] + #[test_case(Combined::HL)] + fn test_set_sixteen_bit_register_combined(register: Combined) { + let mut registers = Registers::new(); + registers.set_16bit_register(SixteenBit::Combined(register), 0x1122); + + assert_eq!(0x1122, registers.get_combined_register(register)); + } + + #[test_case(SingleSixteenBit::StackPointer)] + #[test_case(SingleSixteenBit::ProgramCounter)] + fn test_set_sixteen_bit_register_single(register: SingleSixteenBit) { + let mut registers = Registers::new(); + registers.set_16bit_register(SixteenBit::Single(register), 0x1122); + + assert_eq!(0x1122, registers.get_single_16bit_register(register)); + } }