use crate::gameboy::{testutils::*, StepResult};
use crate::registers;
#[test]
fn test_add_no_carry() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0xFA, 0x06, 0x05, 0x80, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xFF);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_add_half_carry() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x0F, 0x06, 0x01, 0x80, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x10);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_add_causes_carry_zero() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0xFA, 0x06, 0x06, 0x80, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_add_causes_carry_nonzero() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0xFA, 0x06, 0x07, 0x80, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x01);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_sub_no_carry() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x06, 0x06, 0x05, 0x90, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x01);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_sub_half_carry() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x10, 0x06, 0x01, 0x90, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x0F);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_sub_causes_zero() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x06, 0x06, 0x06, 0x90, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_sub_causes_carry() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x06, 0x06, 0x07, 0x90, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xFF);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_adc_no_carry() -> StepResult<()> {
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x04, 0x3F, 0x88, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xFE);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 24);
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x04, 0x37, 0x88, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xFF);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_adc_causes_carry_zero() -> StepResult<()> {
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x06, 0x3F, 0x88, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 24);
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x05, 0x37, 0x88, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_adc_causes_carry_nonzero() -> StepResult<()> {
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x07, 0x3F, 0x88, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x01);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 24);
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x06, 0x37, 0x88, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x01);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_sbc_no_carry() -> StepResult<()> {
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x04, 0x3F, 0x98, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xF6);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 24);
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0x04, 0x37, 0x98, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xF5);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_sbc_zero() -> StepResult<()> {
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0xFA, 0x3F, 0x98, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 24);
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0xF9, 0x37, 0x98, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_sbc_carry() -> StepResult<()> {
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0xFB, 0x3F, 0x98, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xFF);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 24);
let gb = run_program(
4,
&[
0x3E, 0xFA, 0x06, 0xFA, 0x37, 0x98, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0xFF);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_and() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x06, 0x06, 0x05, 0xA0, ],
)?;
assert_eq!(
gb.cpu.read_register_u8(registers::ByteRegister::A),
0x06 & 0x05
);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
let gb = run_program(
3,
&[
0x3E, 0x06, 0x06, 0x10, 0xA0, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_or() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x06, 0x06, 0x05, 0xB0, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x07);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
let gb = run_program(
3,
&[
0x3E, 0x00, 0x06, 0x00, 0xB0, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x0);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_xor() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x0C, 0x06, 0x0F, 0xA8, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x03);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
let gb = run_program(
3,
&[
0x3E, 0x0F, 0x06, 0x0F, 0xA8, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x0);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_cp_greater() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x0C, 0x06, 0x0F, 0xB8, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x0C);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_cp_equal() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x0C, 0x06, 0x0C, 0xB8, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x0C);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_cp_less() -> StepResult<()> {
let gb = run_program(
3,
&[
0x3E, 0x0C, 0x06, 0x08, 0xB8, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::A), 0x0C);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 20);
Ok(())
}
#[test]
fn test_increment_8() -> StepResult<()> {
let gb = run_program(
2,
&[
0x2E, 0xFE, 0x2C, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::L), 0xFF);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 12);
let gb = run_program(
2,
&[
0x2E, 0xFF, 0x2C, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::L), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 12);
Ok(())
}
#[test]
fn test_decrement_8() -> StepResult<()> {
let gb = run_program(
2,
&[
0x2E, 0x02, 0x2D, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::L), 0x01);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 12);
let gb = run_program(
2,
&[
0x2E, 0x01, 0x2D, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::L), 0x00);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 12);
let gb = run_program(
2,
&[
0x2E, 0x00, 0x2D, ],
)?;
assert_eq!(gb.cpu.read_register_u8(registers::ByteRegister::L), 0xFF);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), true);
assert_eq!(gb.clocks_elapsed(), 12);
Ok(())
}
#[test]
fn test_increment_16() -> StepResult<()> {
let gb = run_program(
3,
&[
0x26, 0x01, 0x2E, 0xFF, 0x23, ],
)?;
assert_eq!(gb.cpu.read_register_u16(registers::WordRegister::HL), 0x200);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_decrement_16() -> StepResult<()> {
let gb = run_program(
3,
&[
0x26, 0x01, 0x2E, 0x00, 0x2B, ],
)?;
assert_eq!(gb.cpu.read_register_u16(registers::WordRegister::HL), 0xFF);
assert_eq!(gb.clocks_elapsed(), 24);
Ok(())
}
#[test]
fn test_add_16() -> StepResult<()> {
let gb = run_program(
5,
&[
0x26, 0x0F, 0x2E, 0xFF, 0x06, 0x00, 0x0E, 0x01, 0x09, ],
)?;
assert_eq!(
gb.cpu.read_register_u16(registers::WordRegister::HL),
0x1000
);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 40);
Ok(())
}
#[test]
fn test_add_16_carry() -> StepResult<()> {
let gb = run_program(
5,
&[
0x26, 0x0F, 0x2E, 0xFF, 0x06, 0xF0, 0x0E, 0x02, 0x09, ],
)?;
assert_eq!(
gb.cpu.read_register_u16(registers::WordRegister::HL),
0x0001
);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), false);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 40);
Ok(())
}
#[test]
fn test_add_16_zero() -> StepResult<()> {
let gb = run_program(
5,
&[
0x26, 0xFF, 0x2E, 0xFF, 0x06, 0x00, 0x0E, 0x01, 0x09, ],
)?;
assert_eq!(gb.cpu.read_register_u16(registers::WordRegister::HL), 0x0);
assert_eq!(gb.cpu.read_flag(registers::Flag::Zero), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::Carry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::HalfCarry), true);
assert_eq!(gb.cpu.read_flag(registers::Flag::AddSubtract), false);
assert_eq!(gb.clocks_elapsed(), 40);
Ok(())
}