working on mooneye test suite

This commit is contained in:
2025-05-30 00:35:44 -06:00
parent 4d6973304d
commit 1f55455a65
7 changed files with 87 additions and 44 deletions

View File

@ -7,6 +7,8 @@ typedef struct {
u8 tima; u8 tima;
u8 tma; u8 tma;
u8 tac; u8 tac;
bool tima_needs_reset;
bool tima_just_reset;
} timer_context; } timer_context;
typedef struct { typedef struct {

View File

@ -18,7 +18,7 @@ FILE *log;
void cpu_init() { void cpu_init() {
ctx.regs.a = 0x01; ctx.regs.a = 0x01;
ctx.regs.f = 0xB0; ctx.regs.f = 0xB0;
ctx.regs.b = 0x00; ctx.regs.b = 0x19;
ctx.regs.c = 0x13; ctx.regs.c = 0x13;
ctx.regs.d = 0x00; ctx.regs.d = 0x00;
ctx.regs.e = 0xD8; ctx.regs.e = 0xD8;
@ -55,6 +55,10 @@ static void execute() {
bool cpu_step() { bool cpu_step() {
if(ctx.regs.pc == 0x4348) {
printf("made it!\n");
}
if(!ctx.halted) { if(!ctx.halted) {
u16 pc = ctx.regs.pc; u16 pc = ctx.regs.pc;
fetch_instruction(); fetch_instruction();

View File

@ -74,7 +74,9 @@ void fetch_data() {
cpu_set_reg(RT_HL, cpu_read_reg(RT_HL)-1); cpu_set_reg(RT_HL, cpu_read_reg(RT_HL)-1);
return; return;
case AM_R_A8: case AM_R_A8:
ctx.fetched_data = bus_read(ctx.regs.pc); u16 addr = bus_read(ctx.regs.pc) | 0xFF00;
emu_cycles(1);
ctx.fetched_data = bus_read(addr);
emu_cycles(1); emu_cycles(1);
ctx.regs.pc++; ctx.regs.pc++;
return; return;

View File

@ -2,6 +2,7 @@
#include <emu.h> #include <emu.h>
#include <bus.h> #include <bus.h>
#include <stack.h> #include <stack.h>
#include <timer.h>
reg_type decode_reg(u8 reg); reg_type decode_reg(u8 reg);
@ -51,7 +52,7 @@ static void proc_daa(cpu_context *ctx) {
ctx->regs.a += CPU_FLAG_N ? -u : u; ctx->regs.a += CPU_FLAG_N ? -u : u;
cpu_set_flags(ctx, ctx->regs.a == 0, -1, 0, fc); cpu_set_flags(ctx, ctx->regs.a == 0, CPU_FLAG_N, 0, fc);
} }
static void proc_cpl(cpu_context *ctx) { static void proc_cpl(cpu_context *ctx) {
@ -72,6 +73,7 @@ static void proc_halt(cpu_context *ctx) {
} }
static void proc_stop(cpu_context *ctx) { static void proc_stop(cpu_context *ctx) {
timer_get_context()->div = 0;
printf("CPU STOP!\n"); printf("CPU STOP!\n");
} }
@ -303,10 +305,6 @@ static void proc_add(cpu_context *ctx) {
bool is_16bit = is_16_bit(ctx->cur_inst->reg_1); bool is_16bit = is_16_bit(ctx->cur_inst->reg_1);
if(is_16bit) {
emu_cycles(1);
}
if(ctx->cur_inst->reg_1 == RT_SP) { if(ctx->cur_inst->reg_1 == RT_SP) {
val = cpu_read_reg(ctx->cur_inst->reg_1) + (char)ctx->fetched_data; val = cpu_read_reg(ctx->cur_inst->reg_1) + (char)ctx->fetched_data;
} }
@ -329,6 +327,12 @@ static void proc_add(cpu_context *ctx) {
} }
cpu_set_reg(ctx->cur_inst->reg_1, val & 0xFFFF); cpu_set_reg(ctx->cur_inst->reg_1, val & 0xFFFF);
if(is_16bit) {
emu_cycles(1);
}
if(ctx->cur_inst->reg_1 == RT_SP) {
emu_cycles(1);
}
cpu_set_flags(ctx, z, 0, h, c); cpu_set_flags(ctx, z, 0, h, c);
} }
@ -358,10 +362,6 @@ static void proc_inc(cpu_context *ctx) {
static void proc_dec(cpu_context *ctx) { static void proc_dec(cpu_context *ctx) {
u16 val = cpu_read_reg(ctx->cur_inst->reg_1) - 1; u16 val = cpu_read_reg(ctx->cur_inst->reg_1) - 1;
if(is_16_bit(ctx->cur_inst->reg_1)) {
//emu_cycles(1);
}
if (ctx->cur_inst->reg_1 == RT_HL && ctx->dest_is_mem) { if (ctx->cur_inst->reg_1 == RT_HL && ctx->dest_is_mem) {
val = ctx->fetched_data - 1; val = ctx->fetched_data - 1;
val &= 0xFF; val &= 0xFF;
@ -371,6 +371,10 @@ static void proc_dec(cpu_context *ctx) {
val = cpu_read_reg(ctx->cur_inst->reg_1); val = cpu_read_reg(ctx->cur_inst->reg_1);
} }
if(is_16_bit(ctx->cur_inst->reg_1)) {
emu_cycles(1);
}
if((ctx->cur_opcode & 0x0B) == 0x0B) { if((ctx->cur_opcode & 0x0B) == 0x0B) {
return; return;
} }
@ -394,21 +398,20 @@ static void proc_pop(cpu_context *ctx) {
static void proc_push(cpu_context *ctx) { static void proc_push(cpu_context *ctx) {
u16 val = cpu_read_reg(ctx->cur_inst->reg_1); u16 val = cpu_read_reg(ctx->cur_inst->reg_1);
emu_cycles(1);
stack_push((val >> 8) & 0xFF); stack_push((val >> 8) & 0xFF);
emu_cycles(1); emu_cycles(1);
stack_push((val & 0xFF)); stack_push((val & 0xFF));
emu_cycles(1); emu_cycles(1);
emu_cycles(1);
} }
static void proc_ldh(cpu_context *ctx) { static void proc_ldh(cpu_context *ctx) {
if (!ctx->dest_is_mem) { if (!ctx->dest_is_mem) {
cpu_set_reg(ctx->cur_inst->reg_1, bus_read(0XFF00 | ctx->fetched_data)); cpu_set_reg(ctx->cur_inst->reg_1, ctx->fetched_data);
} else { } else {
bus_write(0xFF00 | ctx->mem_dest, cpu_read_reg(ctx->cur_inst->reg_2)); bus_write(0xFF00 | ctx->mem_dest, cpu_read_reg(ctx->cur_inst->reg_2));
emu_cycles(1);
} }
emu_cycles(1);
} }
static void proc_di(cpu_context *ctx) { static void proc_di(cpu_context *ctx) {
@ -458,12 +461,12 @@ static bool check_condition(cpu_context *ctx) {
static void goto_addr(cpu_context *ctx, u16 addr, bool pushpc){ static void goto_addr(cpu_context *ctx, u16 addr, bool pushpc){
if (check_condition(ctx)) { if (check_condition(ctx)) {
emu_cycles(1);
if(pushpc) { if(pushpc) {
stack_push16(ctx->regs.pc); stack_push16(ctx->regs.pc);
emu_cycles(2); emu_cycles(2);
} }
ctx->regs.pc = addr; ctx->regs.pc = addr;
emu_cycles(1);
} }
} }

View File

@ -7,7 +7,7 @@ void int_handle(cpu_context *ctx, u16 address) {
stack_push16(ctx->regs.pc); stack_push16(ctx->regs.pc);
emu_cycles(2); emu_cycles(2);
ctx->regs.pc = address; ctx->regs.pc = address;
emu_cycles(1); //emu_cycles(1);
} }
bool int_check(cpu_context *ctx, u16 address, interrupt_type t){ bool int_check(cpu_context *ctx, u16 address, interrupt_type t){
@ -25,14 +25,14 @@ void cpu_request_interrupt(interrupt_type t);
void cpu_handle_interrupts(cpu_context *ctx) { void cpu_handle_interrupts(cpu_context *ctx) {
if (int_check(ctx, 0x40, IT_VBLANK)) { if (int_check(ctx, 0x40, IT_VBLANK)) {
//printf("VBLANK!\n");
} else if(int_check(ctx, 0x48, IT_LCD_STAT)){ } else if(int_check(ctx, 0x48, IT_LCD_STAT)){
//printf("LCD!\n");
} else if(int_check(ctx, 0x50, IT_TIMER)){ } else if(int_check(ctx, 0x50, IT_TIMER)){
//printf("TIMER!\n");
} else if(int_check(ctx, 0x58, IT_SERIAL)){ } else if(int_check(ctx, 0x58, IT_SERIAL)){
//printf("Serial!\n");
} else if(int_check(ctx, 0x60, IT_JOYPAD)){ } else if(int_check(ctx, 0x60, IT_JOYPAD)){
//printf("Joy!\n");
} }
} }

View File

@ -37,7 +37,7 @@ u8 io_read(u16 address){
} }
printf("UNSUPPORTED io_read(%04X)\n", address); printf("UNSUPPORTED io_read(%04X)\n", address);
return 0; return 0xFF;
} }

View File

@ -5,40 +5,58 @@
static timer_context ctx = {0}; static timer_context ctx = {0};
bool selected_bit() {
switch(ctx.tac & 0b11) {
case 0b00:
return (ctx.div & (1 << 9));
break;
case 0b01:
return (ctx.div & (1 << 3));
break;
case 0b10:
return (ctx.div & (1 << 5));
break;
case 0b11:
return (ctx.div & (1 << 7));
break;
}
}
void inc_tima() {
ctx.tima++;
if(ctx.tima == 0x00){
ctx.tima_needs_reset = true;
}
}
void timer_init() { void timer_init() {
ctx.div = 0XAC00; ctx.div = 0XAC00;
} }
void timer_tick() { void timer_tick() {
u16 prev_div = ctx.div; u16 prev_div = ctx.div;
bool old = selected_bit();
ctx.div++; ctx.div++;
bool timer_update = false; bool new = selected_bit();
switch(ctx.tac & 0b11) {
case 0b00:
timer_update = (prev_div & (1 << 9)) && (!(ctx.div & (1 << 9)));
break;
case 0b01: if((prev_div & (1 << 1)) && (!(ctx.div & (1 << 1)))){
timer_update = (prev_div & (1 << 3)) && (!(ctx.div & (1 << 3))); if(ctx.tima_just_reset)
break; ctx.tima_just_reset = false;
if(ctx.tima_needs_reset){
case 0b10:
timer_update = (prev_div & (1 << 5)) && (!(ctx.div & (1 << 5)));
break;
case 0b11:
timer_update = (prev_div & (1 << 7)) && (!(ctx.div & (1 << 7)));
break;
}
if(timer_update && ctx.tac & (1 << 2)) {
ctx.tima++;
if(ctx.tima == 0xFF){
ctx.tima = ctx.tma; ctx.tima = ctx.tma;
ctx.tima_needs_reset = false;
ctx.tima_just_reset = true;
cpu_request_interrupt(IT_TIMER); cpu_request_interrupt(IT_TIMER);
} }
} }
if(ctx.tac & 0b100 && old && !new) {
inc_tima();
}
audio_sample_tick(); audio_sample_tick();
if((prev_div & (1 << 12)) && (!(ctx.div & (1 << 12)))){ if((prev_div & (1 << 12)) && (!(ctx.div & (1 << 12)))){
@ -54,22 +72,36 @@ void timer_write(u16 address, u8 value){
switch(address) { switch(address) {
case 0xFF04: case 0xFF04:
//DIV //DIV
if(selected_bit()) {
inc_tima();
}
ctx.div = 0; ctx.div = 0;
break; break;
case 0xFF05: case 0xFF05:
//TIMA //TIMA
if(ctx.tima_just_reset)
return;
ctx.tima_needs_reset = false;
ctx.tima = value; ctx.tima = value;
break; break;
case 0xFF06: case 0xFF06:
//TMA //TMA
if(ctx.tima_just_reset)
ctx.tima = value;
ctx.tma = value; ctx.tma = value;
break; break;
case 0xFF07: case 0xFF07:
//TAC //TAC
bool current = selected_bit();
bool old_enable = ctx.tac & 0b100;
ctx.tac = value; ctx.tac = value;
bool new = selected_bit();
if(((current && !new) && (ctx.tac & 0b100)) || (current && old_enable && !(ctx.tac & 0b100))) {
inc_tima();
}
break; break;
} }
} }