#include #include #include #include "6502.h" #include "bus.h" #include "memory.h" enum { ROM_START = 0xf800, ROM_END = 0xffff, ROM_SIZE = 2048, RAM_START = 0x0000, RAM_END = 0x01ff, RAM_SIZE = 512 }; static cpu_6502_t cpu; static bus_t bus; static memory_t rom; static memory_t ram; static uint8_t code[ROM_SIZE]; static int codesize; void setup( void ) { bus_init( &bus ); cpu_6502_init( &cpu, &bus, true ); cpu.debug_flags |= DEBUG_STATUS | DEBUG_STACK | DEBUG_ZERO_PAGE; memory_init( &rom, MEMORY_ROM, ROM_START, ROM_SIZE, true ); bus_register( &bus, &rom.base, ROM_START, ROM_END ); memory_init( &ram, MEMORY_RAM, RAM_START, RAM_SIZE, true ); bus_register( &bus, &ram.base, RAM_START, RAM_END ); // install code start vector code[0] = ROM_START & 0x00ff; code[1] = ( ROM_START & 0xff00 ) >> 8; codesize = 2; memory_set( &rom, 0x07fc, code, codesize ); } void teardown( void ) { bus_deinit( &bus ); } #define INIT_CPU_TEST \ cpu_6502_reset( &cpu ); \ memory_reset( &rom ); \ memory_reset( &ram ); #define COPY_CPU_TEST \ cpu_6502_t before_cpu; \ memory_t before_ram; \ \ memcpy( &before_cpu, &cpu, sizeof( cpu ) ); \ memory_copy( &before_ram, &ram ); #define DEINIT_CPU_TEST \ memory_deinit( &before_ram ); #define PRINT_CPU_TEST \ fprintf( stderr, "state before:\n" ); \ cpu_6502_print_debug( &before_cpu ); \ fprintf( stderr, "state after:\n" ); \ cpu_6502_print_debug( &cpu ); #define CODE_SET1( op1 ) \ memset( code, 0, ROM_SIZE ); \ code[0] = op1; \ codesize = 1; \ memory_set( &rom, 0x00, code, codesize ); #define CODE_SET2( op1, op2 ) \ memset( code, 0, ROM_SIZE ); \ code[0] = op1; \ code[1] = op2; \ codesize = 2; \ memory_set( &rom, 0x00, code, codesize ); #define CODE_SET3( op1, op2, op3 ) \ memset( code, 0, ROM_SIZE ); \ code[0] = op1; \ code[1] = op2; \ code[2] = op3; \ codesize = 3; \ memory_set( &rom, 0x00, code, codesize ); // NOP START_TEST( test_cpu_6502_nop ) { INIT_CPU_TEST CODE_SET1( 0xea ); // NOP COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // TXS START_TEST( test_cpu_6502_txs ) { INIT_CPU_TEST CODE_SET1( 0x9a ); // TXS cpu.X = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, cpu.X ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0xff ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // LDA START_TEST( test_cpu_6502_lda_flags_positive ) { INIT_CPU_TEST CODE_SET2( 0xa9, 0x01 ); // LDA #$1 cpu.A = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, 0x01 ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_lda_flags_negative ) { INIT_CPU_TEST CODE_SET2( 0xa9, 0xff ); // LDA #-1 COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, 0xff ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_lda_flags_zero ) { INIT_CPU_TEST CODE_SET2( 0xa9, 0x0 ); // LDA #$0 cpu.A = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, 0x00 ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // LDY START_TEST( test_cpu_6502_ldy_flags_positive ) { INIT_CPU_TEST CODE_SET2( 0xa0, 0x01 ); // LDY #$1 cpu.Y = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0x01 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_ldy_flags_negative ) { INIT_CPU_TEST CODE_SET2( 0xa0, 0xff ); // LDY #-1 COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0xff ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_ldy_flags_zero ) { INIT_CPU_TEST CODE_SET2( 0xa0, 0x0 ); // LDY #$0 cpu.Y = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0x00 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // LDX START_TEST( test_cpu_6502_ldx_flags_positive ) { INIT_CPU_TEST CODE_SET2( 0xa2, 0x01 ); // LDX #$1 cpu.X = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0x01 ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_ldx_flags_negative ) { INIT_CPU_TEST CODE_SET2( 0xa2, 0xff ); // LDX #-1 COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0xff ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_ldx_flags_zero ) { INIT_CPU_TEST CODE_SET2( 0xa2, 0x0 ); // LDX #$0 cpu.X = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0x00 ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // STX START_TEST( test_cpu_6502_stx_addr_zero ) { INIT_CPU_TEST CODE_SET2( 0x86, 0x03 ); // STX $03 cpu.X = 0xea; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 3 ); ck_assert_int_eq( ram.cell[0x03], 0xea ); ck_assert_mem_eq( &ram.cell[0x04], &before_ram.cell[0x04], 0x1FF - 0x03 ); ck_assert_int_eq( cpu.cycles, 3 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_stx_addr_abs ) { INIT_CPU_TEST CODE_SET3( 0x8e, 0x03, 0x01 ); // STX #$0103 cpu.X = 0xea; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+3 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 0x102 ); ck_assert_int_eq( ram.cell[0x0103], 0xea ); // modified value in memory ck_assert_mem_eq( &ram.cell[0x104], &before_ram.cell[0x104], 0x1FF - 0x103 ); ck_assert_int_eq( cpu.cycles, 4 ); DEINIT_CPU_TEST } END_TEST // INC START_TEST( test_cpu_6502_inc_flags_positive ) { INIT_CPU_TEST CODE_SET2( 0xe6, 0x22 ); // INC $22 ram.cell[0x22] = 0x51; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 0x21 ); ck_assert_int_eq( ram.cell[0x22], 0x52 ); // modified value in memory ck_assert_mem_eq( &ram.cell[0x23], &before_ram.cell[0x23], 0x1FF - 0x23 ); ck_assert_int_eq( cpu.cycles, 5 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_inc_flags_negative ) { INIT_CPU_TEST CODE_SET2( 0xe6, 0x22 ); // INC $22 ram.cell[0x22] = 0xf1; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 0x21 ); ck_assert_int_eq( ram.cell[0x22], 0xf2 ); // modified value in memory ck_assert_mem_eq( &ram.cell[0x23], &before_ram.cell[0x23], 0x1FF - 0x23 ); ck_assert_int_eq( cpu.cycles, 5 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_inc_flags_zero ) { INIT_CPU_TEST CODE_SET2( 0xe6, 0x22 ); // INC $22 ram.cell[0x22] = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 0x21 ); ck_assert_int_eq( ram.cell[0x22], 0x00 ); // modified value in memory ck_assert_mem_eq( &ram.cell[0x23], &before_ram.cell[0x23], 0x1FF - 0x23 ); ck_assert_int_eq( cpu.cycles, 5 ); DEINIT_CPU_TEST } END_TEST // INX START_TEST( test_cpu_6502_inx_flags_positive ) { INIT_CPU_TEST CODE_SET1( 0xc8 ); // INX cpu.Y = 0x34; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0x35 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_inx_flags_negative ) { INIT_CPU_TEST CODE_SET1( 0xc8 ); // INX cpu.Y = 0xf6; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0xf7 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_inx_flags_zero ) { INIT_CPU_TEST CODE_SET1( 0xc8 ); // INX cpu.Y = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0x00 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // DEX START_TEST( test_cpu_6502_dex_flags_positive ) { INIT_CPU_TEST CODE_SET1( 0xca ); // DEX cpu.X = 0x56; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0x55 ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_dex_flags_negative ) { INIT_CPU_TEST CODE_SET1( 0xca ); // DEX cpu.X = 0x93; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0x92 ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_dex_flags_zero ) { INIT_CPU_TEST CODE_SET1( 0xca ); // DEX cpu.X = 0x01; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0x00 ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // DEY START_TEST( test_cpu_6502_dey_flags_positive ) { INIT_CPU_TEST CODE_SET1( 0x88 ); // DEY cpu.Y = 0x56; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0x55 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_dey_flags_negative ) { INIT_CPU_TEST CODE_SET1( 0x88 ); // DEY cpu.Y = 0x93; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0x92 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_dey_flags_zero ) { INIT_CPU_TEST CODE_SET1( 0x88 ); // DEY cpu.Y = 0x01; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, 0x00 ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // ROL START_TEST( test_cpu_6502_rol_flags_accumulator_carry ) { INIT_CPU_TEST CODE_SET1( 0x2a ); // ROL cpu.PS |= PS_C; cpu.A = 0xf0; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_C | PS_N | PS_Z ), before_cpu.PS & ~( PS_C | PS_N | PS_Z ) ); ck_assert( cpu_6502_is_carry( &cpu ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, 0xe1 ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // CPX START_TEST( test_cpu_6502_cpx_flags_equals ) { INIT_CPU_TEST CODE_SET2( 0xe0, 0x10 ); // CPX #$10 cpu.X = 0x10; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_C | PS_N | PS_Z ), before_cpu.PS & ~( PS_C | PS_N | PS_Z ) ); ck_assert( cpu_6502_is_carry( &cpu ) ); ck_assert( cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_cpx_flags_less ) { INIT_CPU_TEST CODE_SET2( 0xe0, 0x10 ); // CPX #$10 cpu.X = 0x01; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_C | PS_N | PS_Z ), before_cpu.PS & ~( PS_C | PS_N | PS_Z ) ); ck_assert( !cpu_6502_is_carry( &cpu ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_cpx_flags_greater ) { INIT_CPU_TEST CODE_SET2( 0xe0, 0x10 ); // CPX #$10 cpu.X = 0x20; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS & ~( PS_C | PS_N | PS_Z ), before_cpu.PS & ~( PS_C | PS_N | PS_Z ) ); ck_assert( cpu_6502_is_carry( &cpu ) ); ck_assert( !cpu_6502_is_zero( &cpu ) ); ck_assert( !cpu_6502_is_negative( &cpu ) ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // BCC START_TEST( test_cpu_6502_bcc_carry_clear ) { INIT_CPU_TEST CODE_SET2( 0x90, 0x12 ); // BCC $12 cpu.PS &= ~PS_C; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC + 2 + 0x12 ); // carry is clear, jump taken ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 3 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_bcc_carry_set ) { INIT_CPU_TEST CODE_SET2( 0x90, 0x12 ); // BCC $12 cpu.PS |= PS_C; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); // carry is set, execute next opcode, don't jump ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // BCS START_TEST( test_cpu_6502_bcs_carry_set ) { INIT_CPU_TEST CODE_SET2( 0xb0, 0x12 ); // BCS $12 cpu.PS |= PS_C; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC + 2 + 0x12 ); // carry is set, jump taken ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 3 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_bcs_carry_clear ) { INIT_CPU_TEST CODE_SET2( 0xb0, 0x12 ); // BCS $12 cpu.PS &= ~PS_C; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); // carry is clear, execute next opcode, don't jump ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // BNE START_TEST( test_cpu_6502_bne_zero_clear ) { INIT_CPU_TEST CODE_SET2( 0xD0, 0x12 ); // BNE $12 cpu.PS &= ~PS_Z; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC + 2 + 0x12 ); // zero is clear, jump taken ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 3 ); DEINIT_CPU_TEST } END_TEST START_TEST( test_cpu_6502_bne_zero_set ) { INIT_CPU_TEST CODE_SET2( 0xD0, 0x12 ); // BNE $12 cpu.PS |= PS_Z; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); // zero is set, execute next opcode, don't jump ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 2 ); DEINIT_CPU_TEST } END_TEST // JMP START_TEST( test_cpu_6502_jmp_abs ) { INIT_CPU_TEST CODE_SET3( 0x4c, 0x0c, 0xf8 ); // JMP $f80c COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, 0xf80c ); // jump destination is next operation to process ck_assert_int_eq( cpu.SP, before_cpu.SP ); ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 3 ); DEINIT_CPU_TEST } END_TEST // JSR START_TEST( test_cpu_6502_jsr_abs ) { INIT_CPU_TEST CODE_SET3( 0x20, 0x1f, 0xf8 ); // JSR $f81f cpu.SP = 0xff; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, 0xf81f ); // jump destination is next operation to process ck_assert_int_eq( cpu.SP, before_cpu.SP-2 ); // return address/2 bytes on stack ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 0x1fd ); ck_assert_int_eq( ram.cell[0x01fe], 0x02 ); // next PC after return on stack ck_assert_int_eq( ram.cell[0x01ff], 0xf8 ); ck_assert_int_eq( cpu.cycles, 6 ); DEINIT_CPU_TEST } END_TEST // RTS START_TEST( test_cpu_6502_rts ) { INIT_CPU_TEST CODE_SET1( 0x60 ); // RTS cpu.SP = 0xfd; ram.cell[0x01fe] = 0x02; ram.cell[0x01ff] = 0xf8; COPY_CPU_TEST cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, 0xf802 + 1 ); // PC restored to the value on the stack ck_assert_int_eq( cpu.SP, 0xff ); // stack empty ck_assert_int_eq( cpu.PS, before_cpu.PS ); ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); ck_assert_int_eq( cpu.cycles, 6 ); DEINIT_CPU_TEST } END_TEST static void create_cpu_6502_testcase( Suite *suite, const char *name, const TTest *test_func ) { TCase *tc; tc = tcase_create( name ); tcase_add_unchecked_fixture( tc, setup, teardown); tcase_add_test( tc, test_func ); suite_add_tcase( suite, tc ); } static Suite *make_cpu_6502_testsuite( void ) { Suite *suite; suite = suite_create( "6502 CPU tests" ); create_cpu_6502_testcase( suite, "NOP", test_cpu_6502_nop ); create_cpu_6502_testcase( suite, "TXS", test_cpu_6502_txs ); create_cpu_6502_testcase( suite, "LDA (flags, positive)", test_cpu_6502_lda_flags_positive ); create_cpu_6502_testcase( suite, "LDA (flags, negative)", test_cpu_6502_lda_flags_negative ); create_cpu_6502_testcase( suite, "LDA (flags, zero)", test_cpu_6502_lda_flags_zero ); create_cpu_6502_testcase( suite, "LDX (flags, positive)", test_cpu_6502_ldx_flags_positive ); create_cpu_6502_testcase( suite, "LDX (flags, negative)", test_cpu_6502_ldx_flags_negative ); create_cpu_6502_testcase( suite, "LDX (flags, zero)", test_cpu_6502_ldx_flags_zero ); create_cpu_6502_testcase( suite, "LDY (flags, positive)", test_cpu_6502_ldy_flags_positive ); create_cpu_6502_testcase( suite, "LDY (flags, negative)", test_cpu_6502_ldy_flags_negative ); create_cpu_6502_testcase( suite, "LDY (flags, zero)", test_cpu_6502_ldy_flags_zero ); create_cpu_6502_testcase( suite, "STX (addr, zero)", test_cpu_6502_stx_addr_zero ); create_cpu_6502_testcase( suite, "STX (addr, absolute)", test_cpu_6502_stx_addr_abs ); create_cpu_6502_testcase( suite, "INC (flags, positive)", test_cpu_6502_inc_flags_positive ); create_cpu_6502_testcase( suite, "INC (flags, negative)", test_cpu_6502_inc_flags_negative ); create_cpu_6502_testcase( suite, "INC (flags, zero)", test_cpu_6502_inc_flags_zero ); create_cpu_6502_testcase( suite, "INX (flags, positive)", test_cpu_6502_inx_flags_positive ); create_cpu_6502_testcase( suite, "INX (flags, negative)", test_cpu_6502_inx_flags_negative ); create_cpu_6502_testcase( suite, "INX (flags, zero)", test_cpu_6502_inx_flags_zero ); create_cpu_6502_testcase( suite, "DEX (flags, positive)", test_cpu_6502_dex_flags_positive ); create_cpu_6502_testcase( suite, "DEX (flags, negative)", test_cpu_6502_dex_flags_negative ); create_cpu_6502_testcase( suite, "DEX (flags, zero)", test_cpu_6502_dex_flags_zero ); create_cpu_6502_testcase( suite, "DEY (flags, positive)", test_cpu_6502_dey_flags_positive ); create_cpu_6502_testcase( suite, "DEY (flags, negative)", test_cpu_6502_dey_flags_negative ); create_cpu_6502_testcase( suite, "DEY (flags, zero)", test_cpu_6502_dey_flags_zero ); create_cpu_6502_testcase( suite, "ROL (flags, carry)", test_cpu_6502_rol_flags_accumulator_carry ); create_cpu_6502_testcase( suite, "CPX (flags, equals)", test_cpu_6502_cpx_flags_equals ); create_cpu_6502_testcase( suite, "CPX (flags, less)", test_cpu_6502_cpx_flags_less ); create_cpu_6502_testcase( suite, "CPX (flags, greater)", test_cpu_6502_cpx_flags_greater ); create_cpu_6502_testcase( suite, "BCC (branch taken, carry clear)", test_cpu_6502_bcc_carry_clear ); create_cpu_6502_testcase( suite, "BCC (branch not taken, carry set)", test_cpu_6502_bcc_carry_set ); create_cpu_6502_testcase( suite, "BCS (branch taken, carry set)", test_cpu_6502_bcs_carry_set ); create_cpu_6502_testcase( suite, "BCS (branch not taken, carry clear)", test_cpu_6502_bcs_carry_clear ); create_cpu_6502_testcase( suite, "BNE (branch not taken, zero clear)", test_cpu_6502_bne_zero_clear ); create_cpu_6502_testcase( suite, "BNE (branch taken, zero set)", test_cpu_6502_bne_zero_set ); create_cpu_6502_testcase( suite, "JMP (absolute)", test_cpu_6502_jmp_abs ); create_cpu_6502_testcase( suite, "JSR (absolute)", test_cpu_6502_jsr_abs ); create_cpu_6502_testcase( suite, "RTS", test_cpu_6502_rts ); return suite; } int main( void ) { SRunner *runner; int tests_failed = 0; runner = srunner_create( make_cpu_6502_testsuite( ) ); srunner_set_fork_status( runner, CK_NOFORK ); srunner_set_log( runner, "test.log" ); srunner_set_xml( runner, "test.xml" ); srunner_run_all( runner, CK_VERBOSE ); tests_failed = srunner_ntests_failed( runner ); srunner_free( runner ); exit( ( tests_failed == 0 ) ? EXIT_SUCCESS : EXIT_FAILURE ); }