Skip to content

Commit

Permalink
Define macro DEBUG to enable gbz instruction test
Browse files Browse the repository at this point in the history
  • Loading branch information
Rsysz committed Jan 5, 2021
1 parent 433f520 commit cf3f35b
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ $(OUT)/cpu_instrs.h: tests/cpu_instrs.gb tests/rom2h.c

$(OUT)/bench: $(OUT)/cpu_instrs.h prof.h cpu.c bench.c gameboy.h
$(VECHO) " CC+LD\t$@\n"
$(Q)$(CC) -DENABLE_LCD=0 -o $@ cpu.c bench.c
$(Q)$(CC) -DENABLE_LCD=0 -DDEBUG -o $@ gbit/lib/*.c cpu.c bench.c

# Download Game Boy ROMs with full source
download_rom:
Expand Down
108 changes: 90 additions & 18 deletions bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "gbit/lib/tester.h"

struct gb_s gb;
static size_t instruction_mem_size;
static uint8_t *instruction_mem;

static int num_mem_accesses;
static struct mem_access mem_accesses[16];

/* Return byte from Blarrg test ROM, written by Shay Green <gblargg@gmail.com>
* https://github.com/retrio/gb-test-roms/tree/master/cpu_instrs
Expand All @@ -42,17 +51,21 @@ void gb_cart_ram_write(struct gb_s *gb,
const uint8_t val)
{
(void) gb;
(void) addr;
(void) val;
struct mem_access *access = &mem_accesses[num_mem_accesses++];
access->type = MEM_ACCESS_WRITE;
access->addr = addr;
access->val = val;
return;
}

/* Ignore cart RAM reads */
uint8_t gb_cart_ram_read(struct gb_s *gb, const uint_fast32_t addr)
{
(void) gb;
(void) addr;
return 0xFF;
if (addr < instruction_mem_size)
return instruction_mem[addr];
else
return 0xaa;
}

/* Ignore all errors */
Expand All @@ -64,26 +77,85 @@ void gb_error(struct gb_s *gb, const gb_error_t gb_err, const uint16_t val)
return;
}

int main(void)
static void mycpu_init(size_t tester_instruction_mem_size,
uint8_t *tester_instruction_mem)
{
const unsigned short pc_end = 0x06F1; /* Test ends when PC is this value. */
struct gb_s gb;
int ret;
instruction_mem_size = tester_instruction_mem_size;
instruction_mem = tester_instruction_mem;
/* ... Initialize your CPU here ... */
gb_init(&gb, &gb_rom_read, &gb_cart_ram_read, &gb_cart_ram_write, &gb_error,
NULL);
}

PROF_START();
/*
* * Resets the CPU state (e.g., registers) to a given state state.
* */
static void mycpu_set_state(struct state *state)
{
gb.cpu_reg.a = state->reg8.A;
gb.cpu_reg.f = state->reg8.F;
gb.cpu_reg.bc = state->reg16.BC;
gb.cpu_reg.de = state->reg16.DE;
gb.cpu_reg.hl = state->reg16.HL;
gb.cpu_reg.sp = state->SP;
gb.cpu_reg.pc = state->PC;
gb.gb_halt = state->halted;
gb.gb_ime = state->interrupts_master_enabled;
/* ... Load your CPU with state as described (e.g., registers) ... */
}

ret = gb_init(&gb, &gb_rom_read, &gb_cart_ram_read, &gb_cart_ram_write,
&gb_error, NULL);
/*
* * Query the current state of the CPU.
* */
static void mycpu_get_state(struct state *state)
{
state->num_mem_accesses = num_mem_accesses;
memcpy(state->mem_accesses, mem_accesses, sizeof(mem_accesses));
state->reg8.A = gb.cpu_reg.a;
state->reg8.F = gb.cpu_reg.f;
state->reg16.BC = gb.cpu_reg.bc;
state->reg16.DE = gb.cpu_reg.de;
state->reg16.HL = gb.cpu_reg.hl;
state->SP = gb.cpu_reg.sp;
state->PC = gb.cpu_reg.pc;
state->halted = gb.gb_halt;
state->interrupts_master_enabled = gb.gb_ime;
num_mem_accesses = 0;
/* ... Copy your current CPU state into the provided struct ... */
}

/*
* * Step a single instruction of the CPU. Returns the amount of cycles this
* took
* * (e.g., NOP should return 4).
* */
static int mycpu_step(void)
{
int cycles = 0;

/* ... Execute a single instruction in your CPU ... */
cycles = __gb_step_cpu(&gb);
return cycles;
}

if (ret != GB_INIT_NO_ERROR) {
printf("Error: %d\n", ret);
exit(EXIT_FAILURE);
}
static struct tester_flags flags = {
.keep_going_on_mismatch = 0,
.enable_cb_instruction_testing = 1,
.print_tested_instruction = 0,
.print_verbose_inputs = 0,
};

/* Step CPU until test is complete */
while (gb.cpu_reg.pc != pc_end)
gb_run_frame(&gb);
struct tester_operations myops = {
.init = mycpu_init,
.set_state = mycpu_set_state,
.get_state = mycpu_get_state,
.step = mycpu_step,
};

int main(void)
{
PROF_START();
tester_run(&flags, &myops);
PROF_STDOUT();

return 0;
Expand Down
14 changes: 10 additions & 4 deletions cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

uint8_t __gb_read(struct gb_s *gb, const uint_fast16_t addr);
/* Internal function used to write bytes */
void __gb_write(struct gb_s *gb,
const uint_fast16_t addr,
const uint8_t val);
void __gb_write(struct gb_s *gb, const uint_fast16_t addr, const uint8_t val);
#ifdef ENABLE_LCD
void __gb_draw_line(struct gb_s *gb);
#endif
Expand Down Expand Up @@ -186,7 +184,11 @@ static uint8_t __gb_execute_cb(struct gb_s *gb)
}

/* Internal function used to step the CPU */
#ifdef DEBUG
uint8_t __gb_step_cpu(struct gb_s *gb)
#else
static void __gb_step_cpu(struct gb_s *gb)
#endif
{
uint8_t opcode, inst_cycles;
static const uint8_t op_cycles[0x100] = {
Expand Down Expand Up @@ -345,7 +347,7 @@ static void __gb_step_cpu(struct gb_s *gb)
break;

case 0x10: /* STOP */
// gb->gb_halt = 1;
gb->gb_halt = 1;
break;

case 0x11: /* LD DE, imm */
Expand Down Expand Up @@ -1954,6 +1956,9 @@ static void __gb_step_cpu(struct gb_s *gb)
(gb->gb_error)(gb, GB_INVALID_OPCODE, opcode);
}

#ifdef DEBUG
return inst_cycles;
#else
/* DIV register timing */
gb->counter.div_count += inst_cycles;

Expand Down Expand Up @@ -2101,6 +2106,7 @@ static void __gb_step_cpu(struct gb_s *gb)
__gb_draw_line(gb);
#endif
}
#endif
}

void gb_run_frame(struct gb_s *gb)
Expand Down
3 changes: 3 additions & 0 deletions cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@

#include "core.h"

#ifdef DEBUG
uint8_t __gb_step_cpu(struct gb_s *gb);
#endif
void gb_run_frame(struct gb_s *gb);
15 changes: 11 additions & 4 deletions gameboy.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ void gb_set_rtc(struct gb_s *gb, const struct tm *const time)
/* Internal function used to read bytes. */
uint8_t __gb_read(struct gb_s *gb, const uint_fast16_t addr)
{
#ifdef DEBUG
return gb->gb_cart_ram_read(gb, addr);
#else
switch (addr >> 12) {
case 0x0:

Expand Down Expand Up @@ -223,13 +226,15 @@ uint8_t __gb_read(struct gb_s *gb, const uint_fast16_t addr)

(gb->gb_error)(gb, GB_INVALID_READ, addr);
return 0xFF;
#endif
}

/* Internal function used to write bytes */
void __gb_write(struct gb_s *gb,
const uint_fast16_t addr,
const uint8_t val)
void __gb_write(struct gb_s *gb, const uint_fast16_t addr, const uint8_t val)
{
#ifdef DEBUG
gb->gb_cart_ram_write(gb, addr, val);
#else
switch (addr >> 12) {
case 0x0:
case 0x1:
Expand Down Expand Up @@ -496,6 +501,7 @@ void __gb_write(struct gb_s *gb,
}

(gb->gb_error)(gb, GB_INVALID_WRITE, addr);
#endif
}

#if ENABLE_LCD
Expand Down Expand Up @@ -817,10 +823,11 @@ void gb_reset(struct gb_s *gb)
gb->gb_reg.SC = 0x7E;
gb->gb_reg.STAT = 0;
gb->gb_reg.LY = 0;

#ifndef DEBUG
__gb_write(gb, 0xFF47, 0xFC); /* BGP */
__gb_write(gb, 0xFF48, 0xFF); /* OBJP0 */
__gb_write(gb, 0xFF49, 0x0F); /* OBJP1 */
#endif
gb->gb_reg.WY = 0x00;
gb->gb_reg.WX = 0x00;
gb->gb_reg.IE = 0x00;
Expand Down

0 comments on commit cf3f35b

Please sign in to comment.