2017-12-02 19:05:53 +00:00
|
|
|
#include <criterion/criterion.h>
|
|
|
|
|
|
|
|
#include "mos6502.h"
|
|
|
|
#include "mos6502.enums.h"
|
2017-12-06 21:57:15 +00:00
|
|
|
#include "mos6502.tests.h"
|
2017-12-02 19:05:53 +00:00
|
|
|
|
2017-12-06 21:57:15 +00:00
|
|
|
TestSuite(mos6502, .init = setup, .fini = teardown);
|
2017-12-02 19:05:53 +00:00
|
|
|
|
2018-01-07 21:47:26 +00:00
|
|
|
/* Test(mos6502, free) */
|
|
|
|
|
2017-12-06 21:57:15 +00:00
|
|
|
Test(mos6502, create)
|
|
|
|
{
|
2017-12-02 19:05:53 +00:00
|
|
|
cr_assert_neq(cpu, NULL);
|
|
|
|
|
2018-01-11 03:28:05 +00:00
|
|
|
cr_assert_eq(cpu->rmem->size, MOS6502_MEMSIZE);
|
|
|
|
cr_assert_eq(cpu->wmem->size, MOS6502_MEMSIZE);
|
2017-12-02 19:05:53 +00:00
|
|
|
|
|
|
|
cr_assert_eq(cpu->PC, 0);
|
|
|
|
cr_assert_eq(cpu->A, 0);
|
|
|
|
cr_assert_eq(cpu->X, 0);
|
|
|
|
cr_assert_eq(cpu->Y, 0);
|
2018-01-23 22:16:59 +00:00
|
|
|
cr_assert_eq(cpu->P, MOS_STATUS_DEFAULT);
|
|
|
|
cr_assert_eq(cpu->S, 0xff);
|
2017-12-02 19:05:53 +00:00
|
|
|
}
|
|
|
|
|
2017-12-02 19:27:30 +00:00
|
|
|
Test(mos6502, push_stack)
|
|
|
|
{
|
2018-01-23 22:16:59 +00:00
|
|
|
mos6502_push_stack(cpu, 0x34);
|
2018-01-23 22:21:43 +00:00
|
|
|
cr_assert_eq(mos6502_get(cpu, 0x01ff), 0x34);
|
2017-12-02 19:27:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Test(mos6502, pop_stack)
|
|
|
|
{
|
2018-01-23 22:16:59 +00:00
|
|
|
mos6502_push_stack(cpu, 0x34);
|
|
|
|
cr_assert_eq(mos6502_pop_stack(cpu), 0x34);
|
2017-12-02 19:27:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Test(mos6502, modify_status)
|
|
|
|
{
|
2018-01-21 03:01:26 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_NEGATIVE, 130, 130);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_eq(cpu->P & MOS_NEGATIVE, MOS_NEGATIVE);
|
2018-01-21 03:01:26 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_NEGATIVE, 123, 123);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_neq(cpu->P & MOS_NEGATIVE, MOS_NEGATIVE);
|
2017-12-02 19:27:30 +00:00
|
|
|
|
2018-01-21 03:01:26 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_OVERFLOW, 123, 133);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_eq(cpu->P & MOS_OVERFLOW, MOS_OVERFLOW);
|
2018-01-21 03:01:26 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_OVERFLOW, 44, 44);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_neq(cpu->P & MOS_OVERFLOW, MOS_OVERFLOW);
|
2017-12-02 19:27:30 +00:00
|
|
|
|
2018-01-23 22:20:33 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_CARRY, 230, 260);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY);
|
2018-01-21 03:01:26 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_CARRY, 30, 190);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_neq(cpu->P & MOS_CARRY, MOS_CARRY);
|
2017-12-02 19:27:30 +00:00
|
|
|
|
2018-01-21 03:01:26 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_ZERO, 0, 0);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_eq(cpu->P & MOS_ZERO, MOS_ZERO);
|
2018-01-21 03:01:26 +00:00
|
|
|
mos6502_modify_status(cpu, MOS_ZERO, 1, 1);
|
2018-01-05 20:18:39 +00:00
|
|
|
cr_assert_neq(cpu->P & MOS_ZERO, MOS_ZERO);
|
2017-12-02 19:27:30 +00:00
|
|
|
}
|
2017-12-04 02:19:17 +00:00
|
|
|
|
|
|
|
Test(mos6502, set_status)
|
|
|
|
{
|
2018-01-05 20:18:39 +00:00
|
|
|
mos6502_set_status(cpu, MOS_BREAK | MOS_INTERRUPT | MOS_DECIMAL);
|
|
|
|
cr_assert_eq(cpu->P & (MOS_BREAK | MOS_INTERRUPT | MOS_DECIMAL), MOS_BREAK | MOS_INTERRUPT | MOS_DECIMAL);
|
2017-12-04 02:19:17 +00:00
|
|
|
}
|
2017-12-05 05:30:18 +00:00
|
|
|
|
|
|
|
Test(mos6502, instruction)
|
|
|
|
{
|
|
|
|
cr_assert_eq(mos6502_instruction(0x1D), ORA);
|
|
|
|
cr_assert_eq(mos6502_instruction(0xD8), CLD);
|
|
|
|
cr_assert_eq(mos6502_instruction(0x98), TYA);
|
|
|
|
}
|
|
|
|
|
|
|
|
Test(mos6502, cycles)
|
|
|
|
{
|
|
|
|
cr_assert_eq(mos6502_cycles(cpu, 0x76), 6);
|
|
|
|
cr_assert_eq(mos6502_cycles(cpu, 0xBA), 2);
|
|
|
|
|
|
|
|
// In this case, we aren't cross a page boundary, and the number of
|
|
|
|
// cycles should stay at 4
|
2018-01-12 19:57:48 +00:00
|
|
|
cpu->eff_addr = 0x5070;
|
2017-12-05 05:30:18 +00:00
|
|
|
cpu->X = 23;
|
|
|
|
cr_assert_eq(mos6502_cycles(cpu, 0x1D), 4);
|
|
|
|
|
|
|
|
// Testing that crossing a page boundary adds one to the number of
|
|
|
|
// cycles
|
|
|
|
cpu->X = 200;
|
|
|
|
cr_assert_eq(mos6502_cycles(cpu, 0x1D), 5);
|
|
|
|
}
|
2017-12-06 00:38:36 +00:00
|
|
|
|
|
|
|
Test(mos6502, get_instruction_handler)
|
|
|
|
{
|
|
|
|
cr_assert_eq(mos6502_get_instruction_handler(0x00), mos6502_handle_brk);
|
|
|
|
cr_assert_eq(mos6502_get_instruction_handler(0x1D), mos6502_handle_ora);
|
|
|
|
cr_assert_eq(mos6502_get_instruction_handler(0x20), mos6502_handle_jsr);
|
|
|
|
}
|
2017-12-06 02:40:35 +00:00
|
|
|
|
|
|
|
Test(mos6502, execute)
|
|
|
|
{
|
2018-01-11 03:28:05 +00:00
|
|
|
mos6502_set(cpu, 11, 34);
|
|
|
|
mos6502_set(cpu, 10, 0x69);
|
2018-01-10 02:59:14 +00:00
|
|
|
cpu->PC = 10;
|
2018-01-23 22:16:59 +00:00
|
|
|
|
|
|
|
// Make sure we don't have carry turned on, or else we'll get 35!
|
|
|
|
cpu->P &= ~MOS_CARRY;
|
|
|
|
|
2018-01-10 02:59:14 +00:00
|
|
|
mos6502_execute(cpu);
|
2017-12-06 02:40:35 +00:00
|
|
|
cr_assert_eq(cpu->A, 34);
|
|
|
|
}
|
|
|
|
|
2018-01-07 21:47:26 +00:00
|
|
|
Test(mos6502, would_jump)
|
|
|
|
{
|
|
|
|
bool expect;
|
|
|
|
for (int inst = 0; inst <= TYA; inst++) {
|
|
|
|
switch (inst) {
|
|
|
|
case BCC:
|
|
|
|
case BCS:
|
|
|
|
case BEQ:
|
|
|
|
case BMI:
|
|
|
|
case BNE:
|
|
|
|
case BPL:
|
|
|
|
case BRK:
|
|
|
|
case BVC:
|
|
|
|
case BVS:
|
|
|
|
case JMP:
|
|
|
|
case JSR:
|
2018-01-10 02:59:14 +00:00
|
|
|
case RTS:
|
|
|
|
case RTI:
|
2018-01-07 21:47:26 +00:00
|
|
|
expect = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
expect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cr_assert_eq(mos6502_would_jump(inst), expect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-07 21:50:06 +00:00
|
|
|
Test(mos6502, get_address_resolver)
|
|
|
|
{
|
2018-01-23 22:18:22 +00:00
|
|
|
cr_assert_eq(mos6502_get_address_resolver(ACC), mos6502_resolve_acc);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(ABS), mos6502_resolve_abs);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(ABX), mos6502_resolve_abx);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(ABY), mos6502_resolve_aby);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(IMM), mos6502_resolve_imm);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(IND), mos6502_resolve_ind);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(IDX), mos6502_resolve_idx);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(IDY), mos6502_resolve_idy);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(REL), mos6502_resolve_rel);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(ZPG), mos6502_resolve_zpg);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(ZPX), mos6502_resolve_zpx);
|
|
|
|
cr_assert_eq(mos6502_get_address_resolver(ZPY), mos6502_resolve_zpy);
|
2018-01-07 21:50:06 +00:00
|
|
|
}
|
|
|
|
|
2018-01-12 03:58:17 +00:00
|
|
|
|
|
|
|
Test(mos6502, get)
|
|
|
|
{
|
|
|
|
vm_segment_set(cpu->wmem, 0, 123);
|
|
|
|
cr_assert_eq(mos6502_get(cpu, 0), 123);
|
|
|
|
}
|
|
|
|
|
|
|
|
Test(mos6502, get16)
|
|
|
|
{
|
|
|
|
vm_segment_set16(cpu->wmem, 0, 0x3344);
|
|
|
|
cr_assert_eq(mos6502_get16(cpu, 0), 0x3344);
|
|
|
|
}
|
|
|
|
|
|
|
|
Test(mos6502, set)
|
|
|
|
{
|
|
|
|
mos6502_set(cpu, 0, 111);
|
|
|
|
cr_assert_eq(vm_segment_get(cpu->rmem, 0), 111);
|
|
|
|
}
|
|
|
|
|
|
|
|
Test(mos6502, set16)
|
|
|
|
{
|
|
|
|
mos6502_set16(cpu, 0, 0x2255);
|
|
|
|
cr_assert_eq(vm_segment_get16(cpu->rmem, 0), 0x2255);
|
|
|
|
}
|
|
|
|
|
|
|
|
Test(mos6502, set_memory)
|
|
|
|
{
|
|
|
|
vm_segment *rmem, *wmem;
|
|
|
|
|
|
|
|
rmem = (vm_segment *)111;
|
|
|
|
wmem = (vm_segment *)222;
|
|
|
|
|
|
|
|
mos6502_set_memory(cpu, rmem, wmem);
|
|
|
|
|
|
|
|
cr_assert_eq(cpu->rmem, rmem);
|
|
|
|
cr_assert_eq(cpu->wmem, wmem);
|
|
|
|
}
|
2018-01-13 06:38:29 +00:00
|
|
|
|
|
|
|
Test(mos6502, last_executed)
|
|
|
|
{
|
|
|
|
vm_8bit opcode, operand;
|
|
|
|
vm_16bit addr;
|
|
|
|
|
|
|
|
mos6502_set(cpu, 0, 0xA9); // LDA #$EE
|
|
|
|
mos6502_set(cpu, 1, 0xEE);
|
|
|
|
mos6502_set(cpu, 2, 0x8D); // STA $1234
|
|
|
|
mos6502_set16(cpu, 3, 0x1234);
|
|
|
|
|
|
|
|
mos6502_execute(cpu);
|
|
|
|
mos6502_last_executed(cpu, &opcode, &operand, NULL);
|
|
|
|
cr_assert_eq(opcode, 0xA9);
|
|
|
|
cr_assert_eq(operand, 0xEE);
|
|
|
|
|
|
|
|
mos6502_execute(cpu);
|
|
|
|
mos6502_last_executed(cpu, &opcode, NULL, &addr);
|
|
|
|
cr_assert_eq(opcode, 0x8D);
|
|
|
|
cr_assert_eq(addr, 0x1234);
|
|
|
|
}
|