From 39f6ddc3e27b80c17efe4f2d81ce99ed3a297b9a Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sun, 24 Jun 2018 23:31:28 -0400 Subject: add gb_config_t, gb_disasm(), refactor logic, misc cleanups --- ops.yaml | 750 ++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 358 insertions(+), 392 deletions(-) (limited to 'ops.yaml') diff --git a/ops.yaml b/ops.yaml index 9266820..b1d2ad3 100644 --- a/ops.yaml +++ b/ops.yaml @@ -761,6 +761,7 @@ ops: c: code: | cpu_wb(ctx, RB_A, cpu_rb(ctx, RB_A) ^ 0xFF); + cpu_wf(ctx, F_N | F_H, F_N | F_H); - id: JR NC, r8 hex: 0x30 cat: "jumps/calls" @@ -3746,7 +3747,8 @@ ops: h: c: code: | - cpu_ww(ctx, RW_PC, mmu_rw(ctx, cpu_rw(ctx, RW_HL))); + // cpu_ww(ctx, RW_PC, mmu_rw(ctx, cpu_rw(ctx, RW_HL))); + cpu_ww(ctx, RW_PC, cpu_rw(ctx, RW_HL)); - id: LD (a16), A hex: 0xEA cat: "8-bit load/store/move" @@ -8073,6 +8075,7 @@ templates: #include // memset() #include // uint8_t ,etc #include // bool + #include // snprintf() #include "gb.h" #define UNUSED(a) ((void) (a)) @@ -8227,7 +8230,7 @@ templates: (((ctx->mmu.mbc1.rom_ram_mode ? 0 : ctx->mmu.mbc1.ram_bank) & 0x3) << 19) | // B: rom_bank (5 bits, low bit set) - (((ctx->mmu.mbc1.rom_bank & 0x1F) | 0x1) << 15) | + (((ctx->mmu.mbc1.rom_bank & 0x1F) | 0x1) << 14) | // C: address (14 bits) ((addr - 0x4000) & 0x3FFF) @@ -8262,9 +8265,11 @@ templates: case 0x6000: case 0x7000: // ROM1 (16k, banked) - // FIXME: clamp to rom size? - // mbc1 rom1 banking (TCAGBD.pdf, 11.2.2) - return ctx->mmu.rom[mbc1_rom_get_addr(ctx, addr)]; + { + // mbc1 rom1 banking (TCAGBD.pdf, 11.2.2) + const uint32_t addr_ofs = mbc1_rom_get_addr(ctx, addr); + return addr_ofs < ctx->mmu.rom_size ? ctx->mmu.rom[addr_ofs] : 0; + } default: // never reached return 0; @@ -8285,13 +8290,24 @@ templates: break; case 0x2000: case 0x3000: - // set rom bank ctx->mmu.mbc1.rom_bank = val & 0x1F; + + if (ctx->config && ctx->config->on_set_rom_bank) { + // notify callback + ctx->config->on_set_rom_bank(ctx, val & 0x1F); + } + break; case 0x4000: case 0x5000: // set ram_bank/upper_rom_bank bits - ctx->mmu.mbc1.ram_bank = val & 0x3; + ctx->mmu.mbc1.ram_bank = val & 0x03; + + if (ctx->config && ctx->config->on_set_ram_bank) { + // notify callback + ctx->config->on_set_ram_bank(ctx, val & 0x03); + } + break; case 0x6000: case 0x7000: @@ -8393,8 +8409,10 @@ templates: case 0x6000: case 0x7000: // ROM1 (16k, banked) - // FIXME: clamp to rom size? - return ctx->mmu.rom[mbc2_rom_get_addr(ctx, addr)]; + { + const uint32_t addr_ofs = mbc2_rom_get_addr(ctx, addr); + return addr_ofs < ctx->mmu.rom_size ? ctx->mmu.rom[addr_ofs] : 0; + } default: // never reached return 0; @@ -8633,6 +8651,9 @@ templates: } } + // forward reference for mmu_wp() + static void gpu_set_line(gb_t * const ctx, const uint8_t line); + static void mmu_wp( gb_t * const ctx, @@ -8700,8 +8721,9 @@ templates: break; case PORT_LY: - // FIXME: according to URL below writing to this register zeroes it: + // NOTE: according to URL below writing to this register zeroes it: // (src: http://gbdev.gg8.se/wiki/articles/Video_Display) + gpu_set_line(ctx, 0); break; case PORT_LYC: @@ -8782,7 +8804,7 @@ templates: const gb_t * const ctx, const uint16_t addr ) { - switch (ctx->gpu.mode) { + switch (ctx->gpu.mode & 0x3) { case GPU_MODE_VRAM: return 0xFF; default: @@ -8796,7 +8818,7 @@ templates: const gb_t * const ctx, const uint16_t addr ) { - switch (ctx->gpu.mode) { + switch (ctx->gpu.mode & 0x3) { case GPU_MODE_HBLANK: case GPU_MODE_VBLANK: // oam memory (160 bytes): @@ -8932,7 +8954,7 @@ templates: const uint16_t addr, const uint8_t val ) { - switch (ctx->gpu.mode) { + switch (ctx->gpu.mode & 0x3) { case GPU_MODE_HBLANK: case GPU_MODE_VBLANK: case GPU_MODE_OAM: @@ -8951,7 +8973,7 @@ templates: const uint16_t addr, const uint8_t val ) { - switch (ctx->gpu.mode) { + switch (ctx->gpu.mode & 0x3) { case GPU_MODE_HBLANK: case GPU_MODE_VBLANK: // oam memory (160 bytes): @@ -9171,7 +9193,12 @@ templates: const gb_cpu_state_t state ) { ctx->cpu.state = state; + UNUSED(pc); + + if (ctx->config && ctx->config->on_set_cpu_state) { + ctx->config->on_set_cpu_state(ctx, state); + } } static void @@ -9274,13 +9301,12 @@ templates: } static void - add_rb( + add( gb_t * const ctx, - const rb_t reg + const uint8_t n ) { // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = cpu_rb(ctx, reg); + const uint8_t o = cpu_rb(ctx, RB_A); const uint16_t v = o + n; // write value @@ -9294,45 +9320,27 @@ templates: )); } + static void + add_rb( + gb_t * const ctx, + const rb_t reg + ) { + add(ctx, cpu_rb(ctx, reg)); + } + static void add_d8( gb_t * const ctx, const uint16_t addr ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rb(ctx, addr); - const uint16_t v = o + n; - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - ((v & 0xFF) ? 0 : F_Z) | - ((((o & 0x0F) + (n & 0x0F)) & 0xF0) ? F_H : 0) | - ((v & 0x100) ? F_C : 0) - )); + add(ctx, mmu_rb(ctx, addr)); } static void add_hl_ptr( gb_t * const ctx ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rw(ctx, cpu_rw(ctx, RW_HL)); - const uint16_t v = o + n; - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - ((v & 0xFF) ? 0 : F_Z) | - ((((o & 0x0F) + (n & 0x0F)) & 0xF0) ? F_H : 0) | - ((v & 0x100) ? F_C : 0) - )); + add(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))); } static void @@ -9359,11 +9367,11 @@ templates: static void ld_hl_sp_r8( gb_t * const ctx, - const uint16_t addr + const uint16_t ofs_addr ) { // get src values const uint16_t a = cpu_rw(ctx, RW_SP); - const int8_t b = (int8_t) mmu_rb(ctx, addr); + const int8_t b = (int8_t) mmu_rb(ctx, ofs_addr); const uint16_t v = a + b; // write dst value @@ -9377,13 +9385,12 @@ templates: } static void - adc_rb( + adc( gb_t * const ctx, - const rb_t reg + const uint8_t n ) { - // get old and new value + // get old value and carry flag const uint8_t o = cpu_rb(ctx, RB_A), - n = cpu_rb(ctx, reg), c = FLAG(ctx, C) ? 1 : 0; const uint16_t v = o + n + c; @@ -9398,25 +9405,19 @@ templates: )); } + static void + adc_rb( + gb_t * const ctx, + const rb_t reg + ) { + adc(ctx, cpu_rb(ctx, reg)); + } + static void adc_hl_ptr( gb_t * const ctx ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = cpu_rb(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))), - c = FLAG(ctx, C) ? 1 : 0; - const uint16_t v = o + n + c; - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - ((v & 0xFF) ? 0 : F_Z) | - ((((o & 0x0F) + (n & 0x0F) + c) & 0xF0) ? F_H : 0) | - ((v & 0x100) ? F_C : 0) - )); + adc(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))); } static void @@ -9424,31 +9425,16 @@ templates: gb_t * const ctx, const uint16_t addr ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rb(ctx, addr), - c = FLAG(ctx, C) ? 1 : 0; - const uint16_t v = o + n + c; - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - ((v & 0xFF) ? 0 : F_Z) | - ((((o & 0x0F) + (n & 0x0F) + c) & 0xF0) ? F_H : 0) | - ((v & 0x100) ? F_C : 0) - )); + adc(ctx, mmu_rb(ctx, addr)); } static void - sub_rb( + sub( gb_t * const ctx, - const rb_t reg + const uint8_t n ) { // get old and new value const uint8_t o = cpu_rb(ctx, RB_A), - n = cpu_rb(ctx, reg), v = o - n; // write value @@ -9463,25 +9449,19 @@ templates: )); } + static void + sub_rb( + gb_t * const ctx, + const rb_t reg + ) { + sub(ctx, cpu_rb(ctx, reg)); + } + static void sub_hl_ptr( gb_t * const ctx ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rb(ctx, cpu_rw(ctx, RW_HL)), - v = o - n; - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - F_N | - ((((o & 0x0F) - (n & 0x0F)) & 0xF0) ? F_H : 0) | - ((n > o) ? F_C : 0) - )); + sub(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))); } static void @@ -9489,31 +9469,16 @@ templates: gb_t * const ctx, const uint16_t addr ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rb(ctx, addr), - v = o - n; - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - F_N | - ((((o & 0x0F) - (n & 0x0F)) & 0xF0) ? F_H : 0) | - ((n > o) ? F_C : 0) - )); + sub(ctx, mmu_rb(ctx, addr)); } static void - sbc_rb( + sbc( gb_t * const ctx, - const rb_t reg + const uint8_t n ) { // get old and new value const uint8_t o = cpu_rb(ctx, RB_A), - n = cpu_rb(ctx, reg), c = FLAG(ctx, C) ? 1 : 0, v = o - (n + c); @@ -9529,35 +9494,28 @@ templates: )); } + static void + sbc_rb( + gb_t * const ctx, + const rb_t reg + ) { + sbc(ctx, cpu_rb(ctx, reg)); + } + static void sbc_hl_ptr( gb_t * const ctx ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rb(ctx, cpu_rw(ctx, RW_HL)), - c = FLAG(ctx, C) ? 1 : 0, - v = o - (n + c); - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - F_N | - ((((o & 0x0F) - (n & 0x0F)) & 0xF0) ? F_H : 0) | - (((((uint16_t) n) + c) > o) ? F_C : 0) // FIXME: is this right for sub/sbc? - )); + sbc(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))); } static void - and_rb( + and( gb_t * const ctx, - const rb_t reg + const uint8_t val ) { // get value - const uint8_t v = cpu_rb(ctx, RB_A) & cpu_rb(ctx, reg); + const uint8_t v = cpu_rb(ctx, RB_A) & val; // write value cpu_wb(ctx, RB_A, v); @@ -9569,30 +9527,36 @@ templates: )); } + static void + and_rb( + gb_t * const ctx, + const rb_t reg + ) { + and(ctx, cpu_rb(ctx, reg)); + } + static void and_hl_ptr( gb_t * const ctx ) { - // get value - const uint8_t v = cpu_rb(ctx, RB_A) & mmu_rb(ctx, cpu_rb(ctx, RW_HL)); - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - F_H - )); + and(ctx, mmu_rb(ctx, cpu_rb(ctx, RW_HL))); } static void and_d8( gb_t * const ctx, const uint16_t addr + ) { + and(ctx, mmu_rb(ctx, addr)); + } + + static void + xor( + gb_t * const ctx, + const uint8_t val ) { // get value - const uint8_t v = cpu_rb(ctx, RB_A) & mmu_rb(ctx, addr); + const uint8_t v = cpu_rb(ctx, RB_A) ^ val; // write value cpu_wb(ctx, RB_A, v); @@ -9608,32 +9572,14 @@ templates: gb_t * const ctx, const rb_t reg ) { - // get value - const uint8_t v = cpu_rb(ctx, RB_A) ^ cpu_rb(ctx, reg); - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) - )); + xor(ctx, cpu_rb(ctx, reg)); } static void xor_hl_ptr( gb_t * const ctx ) { - // get value - const uint8_t v = cpu_rb(ctx, RB_A) ^ mmu_rb(ctx, cpu_rw(ctx, RW_HL)); - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) - )); + xor(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))); } static void @@ -9641,8 +9587,15 @@ templates: gb_t * const ctx, const uint16_t addr ) { - // get value - const uint8_t v = cpu_rb(ctx, RB_A) ^ mmu_rb(ctx, addr); + xor(ctx, mmu_rb(ctx, addr)); + } + + static void + or( + gb_t * const ctx, + const uint8_t val + ) { + const uint8_t v = cpu_rb(ctx, RB_A) | val; // write value cpu_wb(ctx, RB_A, v); @@ -9658,30 +9611,14 @@ templates: gb_t * const ctx, const rb_t reg ) { - const uint8_t v = cpu_rb(ctx, RB_A) | cpu_rb(ctx, reg); - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) - )); + or(ctx, cpu_rb(ctx, reg)); } static void or_hl_ptr( gb_t * const ctx ) { - // get value - const uint8_t v = cpu_rb(ctx, RB_A) | mmu_rb(ctx, cpu_rw(ctx, RW_HL)); - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) - )); + or(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))); } static void @@ -9689,26 +9626,16 @@ templates: gb_t * const ctx, const uint16_t addr ) { - // get value - const uint8_t v = cpu_rb(ctx, RB_A) | mmu_rb(ctx, addr); - - // write value - cpu_wb(ctx, RB_A, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) - )); + or(ctx, mmu_rb(ctx, addr)); } static void - cp_rb( + cp( gb_t * const ctx, - const rb_t reg + const uint8_t n ) { // get old and new value const uint8_t o = cpu_rb(ctx, RB_A), - n = cpu_rb(ctx, reg), v = o - n; // set flags @@ -9720,22 +9647,19 @@ templates: )); } + static void + cp_rb( + gb_t * const ctx, + const rb_t reg + ) { + cp(ctx, cpu_rb(ctx, reg)); + } + static void cp_hl_ptr( gb_t * const ctx ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rb(ctx, cpu_rw(ctx, RW_HL)), - v = o - n; - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - F_N | - ((((o & 0x0F) - (n & 0x0F)) & 0xF0) ? F_H : 0) | - ((n > o) ? F_C : 0) - )); + cp(ctx, mmu_rb(ctx, cpu_rw(ctx, RW_HL))); } static void @@ -9743,18 +9667,7 @@ templates: gb_t * const ctx, const uint16_t addr ) { - // get old and new value - const uint8_t o = cpu_rb(ctx, RB_A), - n = mmu_rb(ctx, addr), - v = o - n; - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - F_N | - ((((o & 0x0F) - (n & 0x0F)) & 0xF0) ? F_H : 0) | - ((n > o) ? F_C : 0) - )); + cp(ctx, mmu_rb(ctx, addr)); } static void @@ -9787,42 +9700,56 @@ templates: cpu_ww(ctx, RW_SP, sp + 2); } - static void - rlc_rb( + static uint8_t + rlc( gb_t * const ctx, - const rb_t reg + const uint8_t o ) { - // get old value, carry bit, and new value - const uint8_t o = cpu_rb(ctx, reg), - c = (o & 0x80) ? 1 : 0, + // get carry bit and new value + const uint8_t c = (o & 0x80) ? 1 : 0, n = ((o & 0x7F) << 1) + c; - // set value - cpu_wb(ctx, reg, n); - // set flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( (n ? 0 : F_Z) | (c ? F_C : 0) )); + + // return new value + return n; + } + + static void + rlc_rb( + gb_t * const ctx, + const rb_t reg + ) { + cpu_wb(ctx, reg, rlc(ctx, cpu_rb(ctx, reg))); } static void rlc_hl( gb_t * const ctx ) { - // get old value, carry bit, and new value const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t o = mmu_rb(ctx, addr), - c = (o & 0x80) ? 1 : 0, - n = ((o & 0x7F) << 1) + c; - // set value - mmu_wb(ctx, addr, n); + mmu_wb(ctx, addr, rlc(ctx, mmu_rb(ctx, addr))); + } + static uint8_t + rrc( + gb_t * const ctx, + const uint8_t o + ) { + // get carry bit and new value + const uint8_t c = (o & 0x01) ? 1 : 0, + n = (o >> 1) | (c ? 0x80 : 0); // set flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( (n ? 0 : F_Z) | (c ? F_C : 0) )); + + // return new value + return n; } static void @@ -9830,37 +9757,32 @@ templates: gb_t * const ctx, const rb_t reg ) { - // get old value, carry bit, and new value - const uint8_t o = cpu_rb(ctx, reg), - c = (o & 0x01) ? 1 : 0, - n = (o >> 1) | (c ? 0x80 : 0); - // set value - cpu_wb(ctx, reg, n); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (n ? 0 : F_Z) | - (c ? F_C : 0) - )); + cpu_wb(ctx, reg, rrc(ctx, cpu_rb(ctx, reg))); } static void rrc_hl_ptr( gb_t * const ctx ) { - // get old value, carry bit, and new value const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t o = mmu_rb(ctx, addr), - c = (o & 0x01) ? 1 : 0, - n = (o >> 1) | (c ? 0x80 : 0); - // set value - mmu_wb(ctx, addr, n); + mmu_wb(ctx, addr, rrc(ctx, mmu_rb(ctx, addr))); + } + + static uint8_t + rl( + gb_t * const ctx, + const uint8_t o + ) { + const uint8_t n = (o << 1) + (FLAG(ctx, C) ? 1 : 0); // set flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( (n ? 0 : F_Z) | - (c ? F_C : 0) + ((o & 0x80) ? F_C : 0) )); + + // return result + return n; } static void @@ -9868,35 +9790,32 @@ templates: gb_t * const ctx, const rb_t reg ) { - // get old value and new value - const uint8_t o = cpu_rb(ctx, reg), - n = (o << 1) + (FLAG(ctx, C) ? 1 : 0); - // set value - cpu_wb(ctx, reg, n); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (n ? 0 : F_Z) | - ((o & 0x80) ? F_C : 0) - )); + cpu_wb(ctx, reg, rl(ctx, cpu_rb(ctx, reg))); } static void rl_hl_ptr( gb_t * const ctx ) { - // get old value and new value const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t o = mmu_rb(ctx, addr), - n = (o << 1) + (FLAG(ctx, C) ? 1 : 0); - // set value - mmu_wb(ctx, addr, n); + mmu_wb(ctx, addr, rl(ctx, mmu_rb(ctx, addr))); + } + + static uint8_t + rr( + gb_t * const ctx, + const uint8_t o + ) { + const uint8_t n = (FLAG(ctx, C) ? 0x80 : 0) | (o >> 1); // set flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( (n ? 0 : F_Z) | - ((o & 0x80) ? F_C : 0) + ((o & 0x01) ? F_C : 0) )); + + // return result + return n; } static void @@ -9904,35 +9823,32 @@ templates: gb_t * const ctx, const rb_t reg ) { - // get old value and new value - const uint8_t o = cpu_rb(ctx, reg), - n = (FLAG(ctx, C) ? 0x80 : 0) | (o >> 1); - // set value - cpu_wb(ctx, reg, n); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (n ? 0 : F_Z) | - ((o & 0x01) ? F_C : 0) - )); + cpu_wb(ctx, reg, rr(ctx, cpu_rb(ctx, reg))); } static void rr_hl_ptr( gb_t * const ctx ) { - // get old value and new value const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t o = mmu_rb(ctx, addr), - n = (FLAG(ctx, C) ? 0x80 : 0) | (o >> 1); - // set value - mmu_wb(ctx, addr, n); + mmu_wb(ctx, addr, rr(ctx, mmu_rb(ctx, addr))); + } + + static uint8_t + sla( + gb_t * const ctx, + const uint8_t o + ) { + const uint8_t v = o << 1; // set flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (n ? 0 : F_Z) | - ((o & 0x01) ? F_C : 0) + (v ? 0 : F_Z) | + ((o & 0x80) ? F_C : 0) )); + + // return value + return v; } static void @@ -9940,17 +9856,7 @@ templates: gb_t * const ctx, const rb_t reg ) { - const uint8_t o = cpu_rb(ctx, reg), - v = o << 1; - - // set value - cpu_wb(ctx, reg, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - ((o & 0x80) ? F_C : 0) - )); + cpu_wb(ctx, reg, sla(ctx, cpu_rb(ctx, reg))); } static void @@ -9958,17 +9864,24 @@ templates: gb_t * const ctx ) { const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t o = mmu_rb(ctx, addr), - v = o << 1; + mmu_wb(ctx, addr, sla(ctx, mmu_rb(ctx, addr))); + } - // set value - mmu_wb(ctx, addr, v); + static uint8_t + sra( + gb_t * const ctx, + const uint8_t o + ) { + const uint8_t v = ((o & 0x80) ? 0x80 : 0) | (o >> 1); // set flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( (v ? 0 : F_Z) | - ((o & 0x80) ? F_C : 0) + ((o & 0x01) ? F_C : 0) )); + + // return result + return v; } static void @@ -9976,17 +9889,7 @@ templates: gb_t * const ctx, const rb_t reg ) { - const uint8_t o = cpu_rb(ctx, reg), - v = ((o & 0x80) ? 0x80 : 0) | (o >> 1); - - // set value - cpu_wb(ctx, reg, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - ((o & 0x01) ? F_C : 0) - )); + cpu_wb(ctx, reg, sra(ctx, cpu_rb(ctx, reg))); } static void @@ -9994,17 +9897,24 @@ templates: gb_t * const ctx ) { const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t o = mmu_rb(ctx, addr), - v = ((o & 0x80) ? 0x80 : 0) | (o >> 1); + mmu_wb(ctx, addr, sra(ctx, mmu_rb(ctx, addr))); + } - // set value - mmu_wb(ctx, addr, v); + static uint8_t + srl( + gb_t * const ctx, + const uint8_t o + ) { + const uint8_t v = (o >> 1); // set flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( (v ? 0 : F_Z) | ((o & 0x01) ? F_C : 0) )); + + // return result + return v; } static void @@ -10012,17 +9922,7 @@ templates: gb_t * const ctx, const rb_t reg ) { - const uint8_t o = cpu_rb(ctx, reg), - v = (o >> 1); - - // set value - cpu_wb(ctx, reg, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - ((o & 0x01) ? F_C : 0) - )); + cpu_wb(ctx, reg, srl(ctx, cpu_rb(ctx, reg))); } static void @@ -10030,17 +9930,7 @@ templates: gb_t * const ctx ) { const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t o = mmu_rb(ctx, addr), - v = (o >> 1); - - // set value - mmu_wb(ctx, addr, v); - - // set flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) | - ((o & 0x01) ? F_C : 0) - )); + mmu_wb(ctx, addr, srl(ctx, mmu_rb(ctx, addr))); } static void @@ -10121,21 +10011,25 @@ templates: mmu_wb(ctx, addr, mmu_rb(ctx, addr) | ~(bit ? (1 << bit) : 1)); } - static void - swap_rb( + static uint8_t + swap( gb_t * const ctx, - const rb_t reg + const uint8_t v ) { - // get old value - const uint8_t v = cpu_rb(ctx, reg); - - // write value - cpu_wb(ctx, reg, ((v & (0x0F)) << 4) | ((v & 0xF0) >> 4)); - // write flags cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( (v ? 0 : F_Z) )); + + return ((v & (0x0F)) << 4) | ((v & 0xF0) >> 4); + } + + static void + swap_rb( + gb_t * const ctx, + const rb_t reg + ) { + cpu_wb(ctx, reg, swap(ctx, cpu_rb(ctx, reg))); } static void @@ -10143,15 +10037,7 @@ templates: gb_t * const ctx ) { const uint16_t addr = cpu_rw(ctx, RW_HL); - const uint8_t v = mmu_rb(ctx, addr); - - // write value - mmu_wb(ctx, addr, ((v & (0x0F)) << 4) | ((v & 0xF0) >> 4)); - - // write flags - cpu_wf(ctx, F_Z | F_N | F_H | F_C, ( - (v ? 0 : F_Z) - )); + mmu_wb(ctx, addr, swap(ctx, mmu_rb(ctx, addr))); } static void @@ -10203,6 +10089,13 @@ templates: } } + static uint8_t + gpu_get_mode( + const gb_t * const ctx + ) { + return ctx->gpu.mode & 0x3; + } + static void gpu_set_mode( gb_t * const ctx, @@ -10210,18 +10103,29 @@ templates: ) { ctx->gpu.mode = mode; - switch (mode) { + if (ctx->config && ctx->config->on_gpu_set_mode) { + ctx->config->on_gpu_set_mode(ctx, mode); + } + + switch (gpu_get_mode(ctx)) { case GPU_MODE_OAM: if (ctx->gpu.stat & (1 << 5)) { - // vblank interrupt is enabled, trigger LCDC interrupt + // lcd status interrupt is enabled, trigger LCDC interrupt mmu_wb(ctx, PORT_IF, mmu_rb(ctx, PORT_IF) & (1 << 1)); } + break; + case GPU_MODE_VRAM: + // do nothing break; case GPU_MODE_HBLANK: if (ctx->gpu.stat & (1 << 3)) { - // hblank interrupt is enabled, trigger LCDC interrupt + // lcd status interrupt is enabled, trigger LCDC interrupt mmu_wb(ctx, PORT_IF, mmu_rb(ctx, PORT_IF) & (1 << 1)); + + if (ctx->config && ctx->config->on_hblank) { + ctx->config->on_hblank(ctx); + } } break; @@ -10229,11 +10133,12 @@ templates: if (ctx->gpu.stat & (1 << 4)) { // vblank interrupt is enabled, trigger vblank interrupt mmu_wb(ctx, PORT_IF, mmu_rb(ctx, PORT_IF) & 1); + + if (ctx->config && ctx->config->on_vblank) { + ctx->config->on_vblank(ctx); + } } - break; - default: - // do nothing break; } } @@ -10332,19 +10237,21 @@ templates: // increment clock ctx->gpu.clock += clock; - switch (ctx->gpu.mode) { + if (ctx->config && ctx->config->on_gpu_step) { + ctx->config->on_gpu_step(ctx); + } + + switch (gpu_get_mode(ctx)) { case GPU_MODE_OAM: - if (ctx->gpu.clock > 80) { + if (ctx->gpu.clock > 79) { // clear clock, set mode ctx->gpu.clock = 0; - ctx->gpu.mode = GPU_MODE_VRAM; + gpu_set_mode(ctx, GPU_MODE_VRAM); } break; case GPU_MODE_VRAM: - if (ctx->gpu.clock > 172) { - // TODO: write scanline - + if (ctx->gpu.clock > 171) { // clear clock, set mode ctx->gpu.clock = 0; gpu_set_mode(ctx, GPU_MODE_HBLANK); @@ -10352,13 +10259,13 @@ templates: break; case GPU_MODE_HBLANK: - if (ctx->gpu.clock > 204) { + if (ctx->gpu.clock > 203) { // clear clock, draw line, increment line ctx->gpu.clock = 0; gpu_draw(ctx); gpu_set_line(ctx, ctx->gpu.line + 1); - if (ctx->gpu.line < 143) { + if (ctx->gpu.line < 144) { // set mode gpu_set_mode(ctx, GPU_MODE_OAM); } else { @@ -10385,9 +10292,6 @@ templates: } } - break; - default: - /* do nothing, unknown gpu mode */ break; } } @@ -10412,6 +10316,11 @@ templates: // trigger timer interrupt mmu_wb(ctx, PORT_IF, mmu_rb(ctx, PORT_IF) & (1 << 2)); + + if (ctx->config && ctx->config->on_timer) { + // notify callback + ctx->config->on_timer(ctx); + } } } } @@ -10450,8 +10359,8 @@ templates: // return 4 clock step return 4; } else { - // return 4 clock step - return 0; + // return 0 clock step + return 1; } } @@ -10461,7 +10370,7 @@ templates: ) { if (ctx->cpu.state == GB_CPU_STATE_RUN) { if (ctx->cpu.ime) { - // get interrupt vector (masked against enabled interrupts) + // get interrupt flags, masked against enabled interrupts const uint8_t iv = mmu_rb(ctx, PORT_IE) & mmu_rb(ctx, PORT_IF); bool done = false; @@ -10546,6 +10455,59 @@ templates: gpu_step(ctx, clock); } + static const struct { + const char * const name; + const uint8_t len; + } OPS[] = { + <%= ops %> + }; + + bool + gb_disasm( + gb_t * const ctx, + char * const dst_buf, + size_t * const dst_len + ) { + if (!dst_buf || !dst_len) { + return false; + } + + const uint8_t op = mmu_rb(ctx, cpu_rw(ctx, RW_PC)); + const uint16_t ofs = (op == 0xCB) ? (255 + mmu_rb(ctx, cpu_rw(ctx, RW_PC) + 1)) : op; + int len = -1; + + switch (OPS[ofs].len) { + case 1: + len = snprintf(dst_buf, *dst_len, "%s; %02x", + OPS[ofs].name, + op + ); + + break; + case 2: + len = snprintf(dst_buf, *dst_len, "%s; %02x %02x", + OPS[ofs].name, + op, + mmu_rb(ctx, cpu_rw(ctx, RW_PC) + 1) + ); + + break; + case 3: + len = snprintf(dst_buf, *dst_len, "%s; %02x %02x %02x", + OPS[ofs].name, + op, + mmu_rb(ctx, cpu_rw(ctx, RW_PC) + 1), + mmu_rb(ctx, cpu_rw(ctx, RW_PC) + 2) + ); + + break; + default: + len = snprintf(dst_buf, *dst_len, "%s", OPS[ofs].name); + } + + return (len > 0) && (len < (int) *dst_len); + } + void gb_set_buttons( gb_t * const ctx, @@ -10584,9 +10546,6 @@ templates: cpu_init( gb_t * const ctx ) { - // set cpu state - cpu_set_state(ctx, 0, GB_CPU_STATE_RUN); - // init cpu registers // (src: TCAGBD.pdf, 3.2) // TODO: this varies by model (DGB/CGB/SGB/GBA/etc) @@ -10596,16 +10555,23 @@ templates: ctx->cpu.rs[RW_HL] = 0x014D; ctx->cpu.rs[RW_SP] = 0xFFFE; ctx->cpu.rs[RW_PC] = 0x0100; + + // set cpu state + cpu_set_state(ctx, 0, GB_CPU_STATE_RUN); } void gb_init( gb_t * const ctx, - const uint8_t * const rom, + const gb_config_t * const config, + const uint8_t *rom, const uint32_t rom_size ) { // clear context memset(ctx, 0, sizeof(gb_t)); + // save config + ctx->config = config; + // init cpu cpu_init(ctx); @@ -10614,6 +10580,6 @@ templates: ctx->mmu.rom_size = rom_size; // init gpu - ctx->gpu.mode = GPU_MODE_OAM; - ctx->gpu.line = 0; + gpu_set_mode(ctx, GPU_MODE_OAM); + gpu_set_line(ctx, 0); } -- cgit v1.2.3