From 953231925d799402c27d57bea42533ceb650b40b Mon Sep 17 00:00:00 2001 From: velllu <91963404+velllu@users.noreply.github.com> Date: Sun, 15 Sep 2024 00:36:26 +0200 Subject: [PATCH] Implemented subtraction flag --- examples/json.rs | 19 ++++----- src/bus.rs | 10 +++++ src/cpu/opcodes.rs | 92 +++++++++++++++++++++++++++++++++---------- src/cpu/opcodes_cb.rs | 29 ++++++++------ src/flags.rs | 8 ++-- 5 files changed, 113 insertions(+), 45 deletions(-) diff --git a/examples/json.rs b/examples/json.rs index 5ee8636..32b32fc 100644 --- a/examples/json.rs +++ b/examples/json.rs @@ -83,7 +83,7 @@ fn run_test(schemas: Vec) { // Setting values in ram for (address, value) in &schema.initial.ram { - gameboy.bus[*address] = *value; + gameboy.bus.direct_write(*address, *value); } // Setting registers @@ -99,8 +99,7 @@ fn run_test(schemas: Vec) { let final_registers = register_schema_to_registers(&schema.final_); let final_flags = register_schema_to_flags(&schema.final_); - // These are not implemented yet - gameboy.flags.substraction = false; + // Half carry flag is not yet implemented gameboy.flags.half_carry = false; if gameboy.registers == final_registers { @@ -158,16 +157,18 @@ fn run_test(schemas: Vec) { if were_flags_wrong { println!("Your flags:"); println!( - "Zero: {}, Carry: {}", + "Zero: {}, Carry: {}, Subtraction: {}", bool_to_symbol(gameboy.flags.zero), - bool_to_symbol(gameboy.flags.carry) + bool_to_symbol(gameboy.flags.carry), + bool_to_symbol(gameboy.flags.subtraction), ); println!("\nCorrect flags:"); println!( - "Zero: {}, Carry: {}", + "Zero: {}, Carry: {}, Subtraction: {}", bool_to_symbol(final_flags.zero), - bool_to_symbol(final_flags.carry) + bool_to_symbol(final_flags.carry), + bool_to_symbol(final_flags.subtraction), ); println!(""); @@ -207,9 +208,9 @@ fn register_schema_to_registers(schema: &RegisterSchema) -> Registers { fn register_schema_to_flags(schema: &RegisterSchema) -> Flags { Flags { zero: (schema.f >> 7) != 0, - carry: ((schema.f & 0b0001_0000) >> 4) != 0, + subtraction: ((schema.f >> 6) & 0b1) != 0, half_carry: false, - substraction: false, + carry: ((schema.f >> 4) & 0b1) != 0, } } diff --git a/src/bus.rs b/src/bus.rs index 0deb347..c1dc91b 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -164,6 +164,16 @@ impl core::ops::IndexMut for Bus { } impl Bus { + /// Like write but can write to rom + pub fn direct_write(&mut self, address: u16, value: u8) { + if (0x0000..=0x7FFF).contains(&address) { + self.rom_clone[address as usize] = value; + return; + } + + self[address] = value; + } + /// Returns the byte X times after the `PC` register pub(crate) fn next(&self, offset: u16, registers: &Registers) -> u8 { self[registers.pc.wrapping_add(offset)] diff --git a/src/cpu/opcodes.rs b/src/cpu/opcodes.rs index d3ac85f..fead4de 100644 --- a/src/cpu/opcodes.rs +++ b/src/cpu/opcodes.rs @@ -53,23 +53,19 @@ impl Cpu { 0x03 | 0x13 | 0x23 | 0x33 => { let new_value = regs.get_register_couple(opcode >> 4).wrapping_add(1); regs.set_register_couple(opcode >> 4, new_value); - (1, 2) - } - // Instruction `DEC rr` - 00rr0011 - // Decrements by one given register couple - 0x0B | 0x1B | 0x2B | 0x3B => { - let new_value = regs.get_register_couple(opcode >> 4).wrapping_sub(1); - regs.set_register_couple(opcode >> 4, new_value); (1, 2) } // Instruction `INC r` - 00rrr100 // Increments by one given register and update flags 0x04 | 0x0C | 0x14 | 0x1C | 0x24 | 0x2C | 0x34 | 0x3C => { - let new_value = regs.get_register(opcode >> 3, bus).wrapping_add(1); - regs.set_register(opcode >> 3, new_value, bus); + let register_r = regs.get_register(opcode >> 3, bus); + let new_value = register_r.wrapping_add(1); + flags.zero = new_value == 0; + flags.subtraction = false; + regs.set_register(opcode >> 3, new_value, bus); (1, 1) } @@ -77,13 +73,24 @@ impl Cpu { // Instruction `DEC r` - 00rrr101 // Decrements by one given register and update flags 0x05 | 0x0D | 0x15 | 0x1D | 0x25 | 0x2D | 0x35 | 0x3D => { - let new_value = regs.get_register(opcode >> 3, bus).wrapping_sub(1); - regs.set_register(opcode >> 3, new_value, bus); + let register_r = regs.get_register(opcode >> 3, bus); + let new_value = register_r.wrapping_sub(1); + flags.zero = new_value == 0; + flags.subtraction = true; + regs.set_register(opcode >> 3, new_value, bus); (1, 1) } + // Instruction `DEC rr` - 00rr0011 + // Decrements by one given register couple + 0x0B | 0x1B | 0x2B | 0x3B => { + let new_value = regs.get_register_couple(opcode >> 4).wrapping_sub(1); + regs.set_register_couple(opcode >> 4, new_value); + (1, 2) + } + // Instruction `LD r, immediate data` - 00rrr110 // Loads immediate data into register 0x06 | 0x0E | 0x16 | 0x1E | 0x26 | 0x2E | 0x36 | 0x3E => { @@ -98,6 +105,9 @@ impl Cpu { 0x07 => { self.interpret_cb_opcode(opcode, flags, regs, bus); flags.zero = false; + flags.subtraction = false; + flags.half_carry = false; + (1, 1) } @@ -117,11 +127,13 @@ impl Cpu { // Instruction `ADD HL, rr` - 00rr1001 // Add given register to register HL. TODO: Handle carry flag 0x09 | 0x19 | 0x29 | 0x39 => { - let register_r = regs.get_register_couple(opcode >> 4); let register_hl = merge_two_u8s_into_u16(regs.h, regs.l); + let register_r = regs.get_register_couple(opcode >> 4); let (result, has_oveflown) = register_hl.overflowing_add(register_r); flags.carry = has_oveflown; + flags.subtraction = false; + (regs.h, regs.l) = split_u16_into_two_u8s(result); (1, 2) @@ -142,6 +154,9 @@ impl Cpu { 0x0F => { self.interpret_cb_opcode(opcode, flags, regs, bus); flags.zero = false; + flags.subtraction = false; + flags.half_carry = false; + (1, 1) } @@ -151,6 +166,9 @@ impl Cpu { 0x17 => { self.interpret_cb_opcode(opcode, flags, regs, bus); flags.zero = false; + flags.subtraction = false; + flags.half_carry = false; + (1, 1) } @@ -169,6 +187,9 @@ impl Cpu { 0x1F => { self.interpret_cb_opcode(opcode, flags, regs, bus); flags.zero = false; + flags.subtraction = false; + flags.half_carry = false; + (1, 1) } @@ -195,6 +216,8 @@ impl Cpu { // Flip the bits of register A 0x2F => { regs.a = !regs.a; + flags.subtraction = true; + flags.half_carry = true; (1, 1) } @@ -203,6 +226,8 @@ impl Cpu { // Set carry flag 0x37 => { flags.carry = true; + flags.subtraction = false; + flags.half_carry = false; (1, 1) } @@ -211,6 +236,7 @@ impl Cpu { // Flip carry flag 0x3F => { flags.carry = !flags.carry; + flags.subtraction = false; (1, 1) } @@ -236,11 +262,13 @@ impl Cpu { // Do operation "o" on register r and register A, store result in register A 0x80..=0xB7 => { let register_r = regs.get_register(opcode, bus); - let (result, carry) = do_operation(opcode >> 3, regs.a, register_r, flags); + let (result, carry, subtraction) = + do_operation(opcode >> 3, regs.a, register_r, flags); regs.a = result; flags.zero = result == 0; flags.carry = carry; + flags.subtraction = subtraction; (1, 1) } @@ -253,6 +281,7 @@ impl Cpu { flags.zero = result == 0; flags.carry = has_overflown; + flags.subtraction = true; (1, 1) } @@ -333,11 +362,13 @@ impl Cpu { // register A 0xC6 | 0xCE | 0xD6 | 0xDE | 0xE6 | 0xEE | 0xF6 => { let immediate_data = bus.next_one(regs); - let (result, carry) = do_operation(opcode >> 3, regs.a, immediate_data, flags); + let (result, carry, subtraction) = + do_operation(opcode >> 3, regs.a, immediate_data, flags); regs.a = result; flags.zero = result == 0; flags.carry = carry; + flags.subtraction = subtraction; (2, 2) } @@ -437,10 +468,11 @@ impl Cpu { // In this instruction, the carry flag is set if the lower bits of sp and // the unsigned byte of immediate data overflows let p = (regs.sp & 0x00FF) as u8; - flags.carry = p.checked_add(immediate_data).is_none(); + regs.sp = add_i8_to_u16(regs.sp, immediate_data_signed); flags.zero = false; - regs.sp = add_i8_to_u16(regs.sp, immediate_data_signed); + flags.carry = p.checked_add(immediate_data).is_none(); + flags.subtraction = false; (2, 4) } @@ -497,9 +529,10 @@ impl Cpu { // In this instruction, the carry flag is set if the lower bits of sp and // the unsigned byte of immediate data overflows let p = (regs.sp & 0x00FF) as u8; - flags.carry = p.checked_add(immediate_data).is_none(); + flags.carry = p.checked_add(immediate_data).is_none(); flags.zero = false; + flags.subtraction = false; let new_value = add_i8_to_u16(regs.sp, immediate_data_signed); (regs.h, regs.l) = split_u16_into_two_u8s(new_value); @@ -539,6 +572,7 @@ impl Cpu { flags.zero = result == 0; flags.carry = has_overflown; + flags.subtraction = true; (2, 2) } @@ -555,7 +589,8 @@ fn add_i8_to_u16(u16: u16, i8: i8) -> u16 { } } -/// Cases: +/// Returns (result, carry flag, subtraction flag). TODO: Rewrite this +/// # Cases /// - 0: num1 + num2 /// - 1: num1 + num2 + carry flag /// - 2: num1 - num2 @@ -563,8 +598,9 @@ fn add_i8_to_u16(u16: u16, i8: i8) -> u16 { /// - 4: num1 & num2 /// - 5: num1 ^ num2 /// - 6: num1 | num2 -fn do_operation(operation_num: u8, num1: u8, num2: u8, flags: &Flags) -> (u8, bool) { - match operation_num & 0b00000111 { +fn do_operation(operation_num: u8, num1: u8, num2: u8, flags: &Flags) -> (u8, bool, bool) { + // Calculating result and carry flag + let (result, carry_flag) = match operation_num & 0b00000111 { 0 => num1.overflowing_add(num2), 1 => { let (result_c, has_overflown_c) = num2.overflowing_add(flags.carry as u8); @@ -581,5 +617,19 @@ fn do_operation(operation_num: u8, num1: u8, num2: u8, flags: &Flags) -> (u8, bo 5 => (num1 ^ num2, false), 6 => (num1 | num2, false), _ => unreachable!(), - } + }; + + // Calculating subtraction flag + let subtraction_flag = match operation_num & 0b00000111 { + 0 => false, + 1 => false, + 2 => true, + 3 => true, + 4 => false, + 5 => false, + 6 => false, + _ => unreachable!(), + }; + + (result, carry_flag, subtraction_flag) } diff --git a/src/cpu/opcodes_cb.rs b/src/cpu/opcodes_cb.rs index 65cecc9..3911aa5 100644 --- a/src/cpu/opcodes_cb.rs +++ b/src/cpu/opcodes_cb.rs @@ -20,10 +20,10 @@ impl Cpu { let bit_7 = register_r.get_bit(7); new_value.set_bit(0, bit_7); + regs.set_register(opcode, new_value, bus); flags.zero = new_value == 0; flags.carry = bit_7; - - regs.set_register(opcode, new_value, bus); + flags.subtraction = false; (1, 1) } @@ -37,10 +37,10 @@ impl Cpu { let bit_0 = register_r.get_bit(0); new_value.set_bit(7, bit_0); + regs.set_register(opcode, new_value, bus); flags.zero = new_value == 0; flags.carry = bit_0; - - regs.set_register(opcode, new_value, bus); + flags.subtraction = false; (1, 1) } @@ -52,9 +52,10 @@ impl Cpu { let mut new_value = register_r.rotate_left(1); new_value.set_bit(0, flags.carry); + regs.set_register(opcode, new_value, bus); flags.zero = new_value == 0; flags.carry = register_r.get_bit(7); - regs.set_register(opcode, new_value, bus); + flags.subtraction = false; (1, 1) } @@ -66,9 +67,10 @@ impl Cpu { let mut new_value = register_r.rotate_right(1); new_value.set_bit(7, flags.carry); + regs.set_register(opcode, new_value, bus); flags.zero = new_value == 0; flags.carry = register_r.get_bit(0); - regs.set_register(opcode, new_value, bus); + flags.subtraction = false; (1, 1) } @@ -79,9 +81,10 @@ impl Cpu { let register_r = regs.get_register(opcode, bus); let new_value = register_r << 1; + regs.set_register(opcode, new_value, bus); flags.carry = register_r.get_bit(7); flags.zero = new_value == 0; - regs.set_register(opcode, new_value, bus); + flags.subtraction = false; (1, 1) } @@ -95,9 +98,10 @@ impl Cpu { let mut new_value = register_r >> 1; new_value.set_bit(7, bit_7); - flags.carry = register_r.get_bit(0); - flags.zero = new_value == 0; regs.set_register(opcode, new_value, bus); + flags.zero = new_value == 0; + flags.carry = register_r.get_bit(0); + flags.subtraction = false; (1, 1) } @@ -110,9 +114,10 @@ impl Cpu { let low = register_r << 4; let new_value = high | low; + regs.set_register(opcode, new_value, bus); flags.zero = new_value == 0; flags.carry = false; - regs.set_register(opcode, new_value, bus); + flags.subtraction = false; (1, 1) } @@ -123,9 +128,10 @@ impl Cpu { let register_r = regs.get_register(opcode, bus); let new_value = register_r >> 1; + regs.set_register(opcode, new_value, bus); flags.carry = register_r.get_bit(0); flags.zero = new_value == 0; - regs.set_register(opcode, new_value, bus); + flags.subtraction = false; (1, 1) } @@ -137,6 +143,7 @@ impl Cpu { let register = regs.get_register(opcode, bus); flags.zero = !register.get_bit(number); + flags.subtraction = false; (1, 1) } diff --git a/src/flags.rs b/src/flags.rs index 5e70384..e1ad529 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -6,7 +6,7 @@ pub struct Flags { pub zero: bool, /// This is set when the operation is a subtraction - pub substraction: bool, + pub subtraction: bool, /// This is set if the lower 4 bits overflow pub half_carry: bool, @@ -19,7 +19,7 @@ impl Flags { pub(crate) fn new() -> Self { Self { zero: true, - substraction: false, + subtraction: false, half_carry: true, carry: true, } @@ -39,7 +39,7 @@ impl Flags { let mut byte = 0; byte |= (self.zero as u8) << 7; - byte |= (self.substraction as u8) << 6; + byte |= (self.subtraction as u8) << 6; byte |= (self.half_carry as u8) << 5; byte |= (self.carry as u8) << 4; @@ -48,7 +48,7 @@ impl Flags { pub(crate) fn set_from_byte(&mut self, byte: u8) { self.zero = byte.get_bit(7); - self.substraction = byte.get_bit(6); + self.subtraction = byte.get_bit(6); self.half_carry = byte.get_bit(5); self.carry = byte.get_bit(4); }