Skip to content

Commit

Permalink
conditional jmps
Browse files Browse the repository at this point in the history
  • Loading branch information
pcasaretto committed Apr 20, 2024
1 parent 17f7d9d commit 4508ac6
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 29 deletions.
46 changes: 32 additions & 14 deletions src/instructions/and.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,21 @@ pub fn and(target: RegisterTarget) -> impl Fn(&mut Gameboy) -> u8 {
}
}

pub fn and_mem_at_r16(reg: Register16bTarget) -> impl Fn(&mut Gameboy) -> u8 {
move |gameboy: &mut Gameboy| {
let addr = gameboy.cpu.registers.get_u16(reg);
let value = gameboy.bus.read_byte(addr);
let a = gameboy.cpu.registers.get_u8(RegisterTarget::A);
pub fn and_mem_at_r16(gameboy: &mut Gameboy) -> u8 {
let addr = gameboy.cpu.registers.get_u16(Register16bTarget::HL);
let value = gameboy.bus.read_byte(addr);
let a = gameboy.cpu.registers.get_u8(RegisterTarget::A);

let result = a & value;
let result = a & value;

gameboy.cpu.registers.set_u8(RegisterTarget::A, result);
gameboy.cpu.registers.set_u8(RegisterTarget::A, result);

gameboy.cpu.registers.f.zero = result == 0;
gameboy.cpu.registers.f.subtract = false;
gameboy.cpu.registers.f.half_carry = true;
gameboy.cpu.registers.f.carry = false;
const TICKS: u8 = 8;
TICKS
}
gameboy.cpu.registers.f.zero = result == 0;
gameboy.cpu.registers.f.subtract = false;
gameboy.cpu.registers.f.half_carry = true;
gameboy.cpu.registers.f.carry = false;
const TICKS: u8 = 8;
TICKS
}

pub fn and_d8(gameboy: &mut Gameboy) -> u8 {
Expand Down Expand Up @@ -118,4 +116,24 @@ mod tests {
and(RegisterTarget::B)(&mut gameboy);
assert!(!gameboy.cpu.registers.f.subtract);
}

#[test]
fn test_and_mem_at_r16() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.set_u16(Register16bTarget::HL, 0xC050);
gameboy.cpu.registers.set_u8(RegisterTarget::A, 0b1000_1010);
gameboy.bus.write_byte(0xC050, 0b1010_1010);
and_mem_at_r16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.a, 0b1000_1010);
}

#[test]
fn test_and_d8() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.set_u8(RegisterTarget::A, 0b1010_1010);
gameboy.bus.write_byte(0xC051, 0b1100_1010);
and_d8(&mut gameboy);
assert_eq!(gameboy.cpu.registers.a, 0b1000_1010);
}
}
140 changes: 140 additions & 0 deletions src/instructions/jmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,58 @@ pub fn jmp_a16(gameboy: &mut Gameboy) -> u8 {
return TICKS;
}

pub fn jp_nz_a16(gameboy: &mut Gameboy) -> u8 {
if gameboy.cpu.registers.f.zero {
gameboy.cpu.registers.pc = gameboy.cpu.registers.pc.wrapping_add(3);
const TICKS: u8 = 12;
return TICKS;
}
let low = gameboy.read_next_byte();
let high = gameboy.read_next_byte();
gameboy.cpu.registers.pc = u16::from_be_bytes([high, low]);
const TICKS: u8 = 16;
return TICKS;
}

pub fn jp_z_a16(gameboy: &mut Gameboy) -> u8 {
if !gameboy.cpu.registers.f.zero {
gameboy.cpu.registers.pc = gameboy.cpu.registers.pc.wrapping_add(3);
const TICKS: u8 = 12;
return TICKS;
}
let low = gameboy.read_next_byte();
let high = gameboy.read_next_byte();
gameboy.cpu.registers.pc = u16::from_be_bytes([high, low]);
const TICKS: u8 = 16;
return TICKS;
}

pub fn jp_nc_a16(gameboy: &mut Gameboy) -> u8 {
if gameboy.cpu.registers.f.carry {
gameboy.cpu.registers.pc = gameboy.cpu.registers.pc.wrapping_add(3);
const TICKS: u8 = 12;
return TICKS;
}
let low = gameboy.read_next_byte();
let high = gameboy.read_next_byte();
gameboy.cpu.registers.pc = u16::from_be_bytes([high, low]);
const TICKS: u8 = 16;
return TICKS;
}

pub fn jp_c_a16(gameboy: &mut Gameboy) -> u8 {
if !gameboy.cpu.registers.f.carry {
gameboy.cpu.registers.pc = gameboy.cpu.registers.pc.wrapping_add(3);
const TICKS: u8 = 12;
return TICKS;
}
let low = gameboy.read_next_byte();
let high = gameboy.read_next_byte();
gameboy.cpu.registers.pc = u16::from_be_bytes([high, low]);
const TICKS: u8 = 16;
return TICKS;
}

pub fn jr_z(gameboy: &mut Gameboy) -> u8 {
if !gameboy.cpu.registers.f.zero {
gameboy.cpu.registers.pc = gameboy.cpu.registers.pc.wrapping_add(2);
Expand Down Expand Up @@ -103,6 +155,94 @@ mod tests {
assert_eq!(gameboy.cpu.registers.pc, 0x0201);
}

#[test]
fn test_jp_nc_a16_flag_set() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.carry = true;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_nc_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0xC053);
}

#[test]
fn test_jp_nc_a16_flag_unset() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.carry = false;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_nc_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0x0201);
}

#[test]
fn test_jp_c_a16_flag_set() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.carry = false;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_c_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0xC053);
}

#[test]
fn test_jp_c_a16_flag_unset() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.carry = true;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_c_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0x0201);
}

#[test]
fn test_jp_nz_a16_flag_set() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.zero = true;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_nz_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0xC053);
}

#[test]
fn test_jp_nz_a16_flag_unset() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.zero = false;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_nz_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0x0201);
}

#[test]
fn test_jp_z_a16_flag_set() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.zero = false;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_z_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0xC053);
}

#[test]
fn test_jp_z_a16_flag_unset() {
let mut gameboy = Gameboy::default();
gameboy.cpu.registers.pc = 0xC050;
gameboy.cpu.registers.f.zero = true;
gameboy.bus.memory[0xC051] = 0x01;
gameboy.bus.memory[0xC052] = 0x02;
jp_z_a16(&mut gameboy);
assert_eq!(gameboy.cpu.registers.pc, 0x0201);
}

#[test]
fn test_jr() {
let mut gameboy = Gameboy::default();
Expand Down
11 changes: 8 additions & 3 deletions src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ pub fn from_byte(byte: u8) -> Box<Instruction> {
0x2C => Box::new(pai(inc::inc_r(RegisterTarget::L))),
0x3C => Box::new(pai(inc::inc_r(RegisterTarget::A))),

0x35 => Box::new(pai(dec::dec_mem_at_hl)),
0x05 => Box::new(pai(dec::dec_r(RegisterTarget::B))),
0x15 => Box::new(pai(dec::dec_r(RegisterTarget::D))),
0x25 => Box::new(pai(dec::dec_r(RegisterTarget::H))),
0x35 => Box::new(pai(dec::dec_mem_at_hl)),
0x0D => Box::new(pai(dec::dec_r(RegisterTarget::C))),
0x1D => Box::new(pai(dec::dec_r(RegisterTarget::E))),
0x2D => Box::new(pai(dec::dec_r(RegisterTarget::L))),
Expand Down Expand Up @@ -234,7 +234,7 @@ pub fn from_byte(byte: u8) -> Box<Instruction> {
0xA3 => Box::new(pai(and::and(RegisterTarget::E))),
0xA4 => Box::new(pai(and::and(RegisterTarget::H))),
0xA5 => Box::new(pai(and::and(RegisterTarget::L))),
0xA6 => Box::new(pai(and::and_mem_at_r16(Register16bTarget::HL))),
0xA6 => Box::new(pai(and::and_mem_at_r16)),
0xA7 => Box::new(pai(and::and(RegisterTarget::A))),

0xA8 => Box::new(pai(xor::xor(RegisterTarget::B))),
Expand Down Expand Up @@ -269,6 +269,11 @@ pub fn from_byte(byte: u8) -> Box<Instruction> {
0xE1 => Box::new(pai(stack::pop(Register16bTarget::HL))),
0xF1 => Box::new(pai(stack::pop(Register16bTarget::AF))),

0xC2 => Box::new(jmp::jp_nz_a16),
0xD2 => Box::new(jmp::jp_nc_a16),
0xCA => Box::new(jmp::jp_z_a16),
0xDA => Box::new(jmp::jp_c_a16),

0xC4 => Box::new(call::call_nz_a16),
0xD4 => Box::new(call::call_nc_a16),

Expand All @@ -285,7 +290,7 @@ pub fn from_byte(byte: u8) -> Box<Instruction> {
0xCD => Box::new(call::call_a16),
0xC9 => Box::new(call::ret),

0xE9 => Box::new(pai(jmp::jp_hl)),
0xE9 => Box::new(jmp::jp_hl),

0xC6 => Box::new(pai(add::add_d8)),
0xD6 => Box::new(pai(sub::sub_d8)),
Expand Down
24 changes: 12 additions & 12 deletions src/instructions/sbc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,15 @@ mod tests {
cpu: CPU {
registers: Registers {
a: 4,
pc: 0x0012,
pc: 0xC051,
f: FlagsRegister::from(0),
..Default::default()
},
..Default::default()
},
..Default::default()
};
gameboy.bus.memory[0x0012] = 1;
gameboy.bus.memory[0xC051] = 1;
sbc_n8(&mut gameboy);
assert_eq!(gameboy.cpu.registers.a, 3);
}
Expand All @@ -196,7 +196,7 @@ mod tests {
let mut gameboy = Gameboy {
cpu: CPU {
registers: Registers {
pc: 0x0012,
pc: 0xC051,
a: 4,
f: FlagsRegister::from(0),
..Default::default()
Expand All @@ -205,7 +205,7 @@ mod tests {
},
..Default::default()
};
gameboy.bus.memory[0x0012] = 5;
gameboy.bus.memory[0xC051] = 5;
sbc_n8(&mut gameboy);
assert_eq!(gameboy.cpu.registers.a, 255);
}
Expand All @@ -216,15 +216,15 @@ mod tests {
cpu: CPU {
registers: Registers {
a: 4,
pc: 0x0012,
pc: 0xC051,
f: FlagsRegister::from(0),
..Default::default()
},
..Default::default()
},
..Default::default()
};
gameboy.bus.memory[0x0012] = 5;
gameboy.bus.memory[0xC051] = 5;
sbc_n8(&mut gameboy);
assert!(gameboy.cpu.registers.f.carry);
}
Expand All @@ -234,7 +234,7 @@ mod tests {
let mut gameboy = Gameboy {
cpu: CPU {
registers: Registers {
pc: 0x0012,
pc: 0xC051,
a: 5,
f: FlagsRegister::from(0),
..Default::default()
Expand All @@ -243,7 +243,7 @@ mod tests {
},
..Default::default()
};
gameboy.bus.memory[0x0012] = 5;
gameboy.bus.memory[0xC051] = 5;
sbc_n8(&mut gameboy);
assert!(gameboy.cpu.registers.f.zero);
}
Expand All @@ -253,7 +253,7 @@ mod tests {
let mut gameboy = Gameboy {
cpu: CPU {
registers: Registers {
pc: 0x0012,
pc: 0xC051,
a: 5,
f: FlagsRegister::from(0),
..Default::default()
Expand All @@ -262,7 +262,7 @@ mod tests {
},
..Default::default()
};
gameboy.bus.memory[0x0012] = 5;
gameboy.bus.memory[0xC051] = 5;
sbc_n8(&mut gameboy);
assert!(gameboy.cpu.registers.f.subtract);
}
Expand All @@ -272,7 +272,7 @@ mod tests {
let mut gameboy = Gameboy {
cpu: CPU {
registers: Registers {
pc: 0x0012,
pc: 0xC051,
a: 0b00010000,
f: FlagsRegister::from(0),
..Default::default()
Expand All @@ -281,7 +281,7 @@ mod tests {
},
..Default::default()
};
gameboy.bus.memory[0x0012] = 1;
gameboy.bus.memory[0xC051] = 1;
sbc_n8(&mut gameboy);
assert!(gameboy.cpu.registers.f.half_carry);
}
Expand Down

0 comments on commit 4508ac6

Please sign in to comment.