diff --git a/libgambatte/src/cpu.cpp b/libgambatte/src/cpu.cpp index f884e897a6..2de9fc51c4 100644 --- a/libgambatte/src/cpu.cpp +++ b/libgambatte/src/cpu.cpp @@ -1,21 +1,21 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ +// +// Copyright (C) 2007 by sinamas +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License version 2 for more details. +// +// You should have received a copy of the GNU General Public License +// version 2 along with this program; if not, write to the +// Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +// + #include "cpu.h" #include "memory.h" #include "savestate.h" @@ -23,229 +23,229 @@ namespace gambatte { CPU::CPU() -: memory(Interrupter(SP, PC), SP, PC), - cycleCounter_(0), - PC(0x100), - SP(0xFFFE), - HF1(0xF), - HF2(0xF), - ZF(0), - CF(0x100), - A(0x01), - B(0x00), - C(0x13), - D(0x00), - E(0xD8), - H(0x01), - L(0x4D), - skip(false), - numInterruptAddresses(), - tracecallback(0) +: mem_(Interrupter(sp, pc), sp, pc) +, cycleCounter_(0) +, pc(0x100) +, sp(0xFFFE) +, hf1(0xF) +, hf2(0xF) +, zf(0) +, cf(0x100) +, a(0x01) +, b(0x00) +, c(0x13) +, d(0x00) +, e(0xD8) +, h(0x01) +, l(0x4D) +, skip_(false) +, numInterruptAddresses() +, tracecallback(0) { } -long CPU::runFor(const unsigned long cycles) { - memory.setBasetime(cycleCounter_); - process(cycles/* << memory.isDoubleSpeed()*/); +long CPU::runFor(unsigned long const cycles) { + mem_.setBasetime(cycleCounter_); + process(cycles); - const long csb = memory.cyclesSinceBlit(cycleCounter_); + long const csb = mem_.cyclesSinceBlit(cycleCounter_); if (cycleCounter_ & 0x80000000) - cycleCounter_ = memory.resetCounters(cycleCounter_); + cycleCounter_ = mem_.resetCounters(cycleCounter_); return csb; } -// (HF2 & 0x200) == true means HF is set. -// (HF2 & 0x400) marks the subtract flag. -// (HF2 & 0x800) is set for inc/dec. -// (HF2 & 0x100) is set if there's a carry to add. -static void calcHF(const unsigned HF1, unsigned& HF2) { - unsigned arg1 = HF1 & 0xF; - unsigned arg2 = (HF2 & 0xF) + (HF2 >> 8 & 1); +enum { hf2_hcf = 0x200, hf2_subf = 0x400, hf2_incf = 0x800 }; - if (HF2 & 0x800) { - arg1 = arg2; - arg2 = 1; +static unsigned updateHf2FromHf1(unsigned const hf1, unsigned hf2) { + unsigned lhs = hf1 & 0xF; + unsigned rhs = (hf2 & 0xF) + (hf2 >> 8 & 1); + if (hf2 & hf2_incf) { + lhs = rhs; + rhs = 1; } - if (HF2 & 0x400) - arg1 -= arg2; - else - arg1 = (arg1 + arg2) << 5; + unsigned res = hf2 & hf2_subf + ? lhs - rhs + : (lhs + rhs) << 5; - HF2 |= arg1 & 0x200; + hf2 |= res & hf2_hcf; + return hf2; } -#define F() (((HF2 & 0x600) | (CF & 0x100)) >> 4 | ((ZF & 0xFF) ? 0 : 0x80)) +static inline unsigned toF(unsigned hf2, unsigned cf, unsigned zf) { + return ((hf2 & (hf2_subf | hf2_hcf)) | (cf & 0x100)) >> 4 + | (zf & 0xFF ? 0 : 0x80); +} -#define FROM_F(f_in) do { \ - unsigned from_f_var = f_in; \ -\ - ZF = ~from_f_var & 0x80; \ - HF2 = from_f_var << 4 & 0x600; \ - CF = from_f_var << 4 & 0x100; \ -} while (0) +static inline unsigned zfFromF(unsigned f) { return ~f & 0x80; } +static inline unsigned hf2FromF(unsigned f) { return f << 4 & (hf2_subf | hf2_hcf); } +static inline unsigned cfFromF(unsigned f) { return f << 4 & 0x100; } void CPU::setStatePtrs(SaveState &state) { - memory.setStatePtrs(state); + mem_.setStatePtrs(state); } -void CPU::loadState(const SaveState &state) { - memory.loadState(state/*, cycleCounter_*/); +void CPU::loadState(SaveState const &state) { + mem_.loadState(state); cycleCounter_ = state.cpu.cycleCounter; - PC = state.cpu.PC & 0xFFFF; - SP = state.cpu.SP & 0xFFFF; - A = state.cpu.A & 0xFF; - B = state.cpu.B & 0xFF; - C = state.cpu.C & 0xFF; - D = state.cpu.D & 0xFF; - E = state.cpu.E & 0xFF; - FROM_F(state.cpu.F); - H = state.cpu.H & 0xFF; - L = state.cpu.L & 0xFF; - skip = state.cpu.skip; + pc = state.cpu.pc & 0xFFFF; + sp = state.cpu.sp & 0xFFFF; + a = state.cpu.a & 0xFF; + b = state.cpu.b & 0xFF; + c = state.cpu.c & 0xFF; + d = state.cpu.d & 0xFF; + e = state.cpu.e & 0xFF; + zf = zfFromF(state.cpu.f); + hf2 = hf2FromF(state.cpu.f); + cf = cfFromF(state.cpu.f); + h = state.cpu.h & 0xFF; + l = state.cpu.l & 0xFF; + skip_ = state.cpu.skip; } -#define BC() ( B << 8 | C ) -#define DE() ( D << 8 | E ) -#define HL() ( H << 8 | L ) +// The main reasons for the use of macros is to more conveniently be able to tweak +// which variables are local and which are not, combined with the fact that at the +// time they were written GCC had a tendency to not be able to keep hot variables +// in regs if you took an address/reference in an inline function. -#define READ(dest, addr) do { (dest) = memory.read(addr, cycleCounter); cycleCounter += 4; } while (0) -#define PEEK(dest, addr) do { (dest) = memory.read(addr, cycleCounter); } while(0) -// #define PC_READ(dest, addr) do { (dest) = memory.pc_read(addr, cycleCounter); cycleCounter += 4; } while (0) -#define PC_READ(dest) do { (dest) = memory.read_excb(PC, cycleCounter, false); PC = (PC + 1) & 0xFFFF; cycleCounter += 4; } while (0) -#define PC_READ_FIRST(dest) do { (dest) = memory.read_excb(PC, cycleCounter, true); PC = (PC + 1) & 0xFFFF; cycleCounter += 4; } while (0) -#define FF_READ(dest, addr) do { (dest) = memory.ff_read(addr, cycleCounter); cycleCounter += 4; } while (0) +#define bc() ( b << 8 | c ) +#define de() ( d << 8 | e ) +#define hl() ( h << 8 | l ) -#define WRITE(addr, data) do { memory.write(addr, data, cycleCounter); cycleCounter += 4; } while (0) -#define FF_WRITE(addr, data) do { memory.ff_write(addr, data, cycleCounter); cycleCounter += 4; } while (0) +#define READ(dest, addr) do { (dest) = mem_.read(addr, cycleCounter); cycleCounter += 4; } while (0) +#define PEEK(dest, addr) do { (dest) = mem_.read(addr, cycleCounter); } while(0) +#define PC_READ(dest) do { (dest) = mem_.read_excb(pc, cycleCounter, false); pc = (pc + 1) & 0xFFFF; cycleCounter += 4; } while (0) +#define PC_READ_FIRST(dest) do { (dest) = mem_.read_excb(pc, cycleCounter, true); pc = (pc + 1) & 0xFFFF; cycleCounter += 4; } while (0) +#define FF_READ(dest, addr) do { (dest) = mem_.ff_read(addr, cycleCounter); cycleCounter += 4; } while (0) -#define PC_MOD(data) do { PC = data; cycleCounter += 4; } while (0) +#define WRITE(addr, data) do { mem_.write(addr, data, cycleCounter); cycleCounter += 4; } while (0) +#define FF_WRITE(addr, data) do { mem_.ff_write(addr, data, cycleCounter); cycleCounter += 4; } while (0) + +#define PC_MOD(data) do { pc = data; cycleCounter += 4; } while (0) #define PUSH(r1, r2) do { \ - SP = (SP - 1) & 0xFFFF; \ - WRITE(SP, (r1)); \ - SP = (SP - 1) & 0xFFFF; \ - WRITE(SP, (r2)); \ + sp = (sp - 1) & 0xFFFF; \ + WRITE(sp, (r1)); \ + sp = (sp - 1) & 0xFFFF; \ + WRITE(sp, (r2)); \ } while (0) -//CB OPCODES (Shifts, rotates and bits): -//swap r (8 cycles): -//Swap upper and lower nibbles of 8-bit register, reset flags, check zero flag: +// CB OPCODES (Shifts, rotates and bits): +// swap r (8 cycles): +// Swap upper and lower nibbles of 8-bit register, reset flags, check zero flag: #define swap_r(r) do { \ - CF = HF2 = 0; \ - ZF = (r); \ - (r) = (ZF << 4 | ZF >> 4) & 0xFF; \ + cf = hf2 = 0; \ + zf = (r); \ + (r) = (zf << 4 | zf >> 4) & 0xFF; \ } while (0) -//rlc r (8 cycles): -//Rotate 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF: +// rlc r (8 cycles): +// Rotate 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF: #define rlc_r(r) do { \ - CF = (r) << 1; \ - ZF = CF | CF >> 8; \ - (r) = ZF & 0xFF; \ - HF2 = 0; \ + cf = (r) << 1; \ + zf = cf | cf >> 8; \ + (r) = zf & 0xFF; \ + hf2 = 0; \ } while (0) -//rl r (8 cycles): -//Rotate 8-bit register left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF and HCF, Check ZF: +// rl r (8 cycles): +// Rotate 8-bit register left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF and HCF, Check ZF: #define rl_r(r) do { \ - const unsigned rl_r_var_oldcf = CF >> 8 & 1; \ - CF = (r) << 1; \ - ZF = CF | rl_r_var_oldcf; \ - (r) = ZF & 0xFF; \ - HF2 = 0; \ + unsigned const oldcf = cf >> 8 & 1; \ + cf = (r) << 1; \ + zf = cf | oldcf; \ + (r) = zf & 0xFF; \ + hf2 = 0; \ } while (0) -//rrc r (8 cycles): -//Rotate 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF: +// rrc r (8 cycles): +// Rotate 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF: #define rrc_r(r) do { \ - ZF = (r); \ - CF = ZF << 8; \ - (r) = (ZF | CF) >> 1 & 0xFF; \ - HF2 = 0; \ + zf = (r); \ + cf = zf << 8; \ + (r) = (zf | cf) >> 1 & 0xFF; \ + hf2 = 0; \ } while (0) -//rr r (8 cycles): -//Rotate 8-bit register right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF and HCF, Check ZF: +// rr r (8 cycles): +// Rotate 8-bit register right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF and HCF, Check ZF: #define rr_r(r) do { \ - const unsigned rr_r_var_oldcf = CF & 0x100; \ - CF = (r) << 8; \ - (r) = ZF = ((r) | rr_r_var_oldcf) >> 1; \ - HF2 = 0; \ + unsigned const oldcf = cf & 0x100; \ + cf = (r) << 8; \ + (r) = zf = ((r) | oldcf) >> 1; \ + hf2 = 0; \ } while (0) -//sla r (8 cycles): -//Shift 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF: +// sla r (8 cycles): +// Shift 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF: #define sla_r(r) do { \ - ZF = CF = (r) << 1; \ - (r) = ZF & 0xFF; \ - HF2 = 0; \ + zf = cf = (r) << 1; \ + (r) = zf & 0xFF; \ + hf2 = 0; \ } while (0) -//sra r (8 cycles): -//Shift 8-bit register right, store old bit0 in CF. bit7=old bit7. Reset SF and HCF, Check ZF: +// sra r (8 cycles): +// Shift 8-bit register right, store old bit0 in CF. bit7=old bit7. Reset SF and HCF, Check ZF: #define sra_r(r) do { \ - CF = (r) << 8; \ - ZF = (r) >> 1; \ - (r) = ZF | ((r) & 0x80); \ - HF2 = 0; \ + cf = (r) << 8; \ + zf = (r) >> 1; \ + (r) = zf | ((r) & 0x80); \ + hf2 = 0; \ } while (0) -//srl r (8 cycles): -//Shift 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF: +// srl r (8 cycles): +// Shift 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF: #define srl_r(r) do { \ - ZF = (r); \ - CF = (r) << 8; \ - ZF >>= 1; \ - (r) = ZF; \ - HF2 = 0; \ + zf = (r); \ + cf = (r) << 8; \ + zf >>= 1; \ + (r) = zf; \ + hf2 = 0; \ } while (0) -//bit n,r (8 cycles): -//bit n,(hl) (12 cycles): -//Test bitn in 8-bit value, check ZF, unset SF, set HCF: +// bit n,r (8 cycles): +// bit n,(hl) (12 cycles): +// Test bitn in 8-bit value, check ZF, unset SF, set HCF: #define bitn_u8(bitmask, u8) do { \ - ZF = (u8) & (bitmask); \ - HF2 = 0x200; \ + zf = (u8) & (bitmask); \ + hf2 = hf2_hcf; \ } while (0) -#define bit0_u8(u8) bitn_u8(1, (u8)) -#define bit1_u8(u8) bitn_u8(2, (u8)) -#define bit2_u8(u8) bitn_u8(4, (u8)) -#define bit3_u8(u8) bitn_u8(8, (u8)) +#define bit0_u8(u8) bitn_u8(0x01, (u8)) +#define bit1_u8(u8) bitn_u8(0x02, (u8)) +#define bit2_u8(u8) bitn_u8(0x04, (u8)) +#define bit3_u8(u8) bitn_u8(0x08, (u8)) #define bit4_u8(u8) bitn_u8(0x10, (u8)) #define bit5_u8(u8) bitn_u8(0x20, (u8)) #define bit6_u8(u8) bitn_u8(0x40, (u8)) #define bit7_u8(u8) bitn_u8(0x80, (u8)) -//set n,r (8 cycles): -//Set bitn of 8-bit register: -#define set0_r(r) ( (r) |= 0x1 ) -#define set1_r(r) ( (r) |= 0x2 ) -#define set2_r(r) ( (r) |= 0x4 ) -#define set3_r(r) ( (r) |= 0x8 ) +// set n,r (8 cycles): +// Set bitn of 8-bit register: +#define set0_r(r) ( (r) |= 0x01 ) +#define set1_r(r) ( (r) |= 0x02 ) +#define set2_r(r) ( (r) |= 0x04 ) +#define set3_r(r) ( (r) |= 0x08 ) #define set4_r(r) ( (r) |= 0x10 ) #define set5_r(r) ( (r) |= 0x20 ) #define set6_r(r) ( (r) |= 0x40 ) #define set7_r(r) ( (r) |= 0x80 ) -//set n,(hl) (16 cycles): -//Set bitn of value at address stored in HL: +// set n,(hl) (16 cycles): +// Set bitn of value at address stored in HL: #define setn_mem_hl(n) do { \ - const unsigned setn_mem_hl_var_addr = HL(); \ - unsigned setn_mem_hl_var_tmp; \ -\ - READ(setn_mem_hl_var_tmp, setn_mem_hl_var_addr); \ - setn_mem_hl_var_tmp |= 1 << (n); \ -\ - WRITE(setn_mem_hl_var_addr, setn_mem_hl_var_tmp); \ + unsigned const hl = hl(); \ + unsigned val; \ + READ(val, hl); \ + val |= 1 << (n); \ + WRITE(hl, val); \ } while (0) -//res n,r (8 cycles): -//Unset bitn of 8-bit register: +// res n,r (8 cycles): +// Unset bitn of 8-bit register: #define res0_r(r) ( (r) &= 0xFE ) #define res1_r(r) ( (r) &= 0xFD ) #define res2_r(r) ( (r) &= 0xFB ) @@ -255,269 +255,252 @@ void CPU::loadState(const SaveState &state) { #define res6_r(r) ( (r) &= 0xBF ) #define res7_r(r) ( (r) &= 0x7F ) -//res n,(hl) (16 cycles): -//Unset bitn of value at address stored in HL: +// res n,(hl) (16 cycles): +// Unset bitn of value at address stored in HL: #define resn_mem_hl(n) do { \ - const unsigned resn_mem_hl_var_addr = HL(); \ - unsigned resn_mem_hl_var_tmp; \ -\ - READ(resn_mem_hl_var_tmp, resn_mem_hl_var_addr); \ - resn_mem_hl_var_tmp &= ~(1 << (n)); \ -\ - WRITE(resn_mem_hl_var_addr, resn_mem_hl_var_tmp); \ + unsigned const hl = hl(); \ + unsigned val; \ + READ(val, hl); \ + val &= ~(1 << (n)); \ + WRITE(hl, val); \ } while (0) -//16-BIT LOADS: -//ld rr,nn (12 cycles) -//set rr to 16-bit value of next 2 bytes in memory +// 16-BIT LOADS: +// ld rr,nn (12 cycles) +// set rr to 16-bit value of next 2 bytes in memory #define ld_rr_nn(r1, r2) do { \ PC_READ(r2); \ PC_READ(r1); \ } while (0) -//push rr (16 cycles): -//Push value of register pair onto stack: +// push rr (16 cycles): +// Push value of register pair onto stack: #define push_rr(r1, r2) do { \ PUSH(r1, r2); \ cycleCounter += 4; \ } while (0) -//pop rr (12 cycles): -//Pop two bytes off stack into register pair: +// pop rr (12 cycles): +// Pop two bytes off stack into register pair: #define pop_rr(r1, r2) do { \ - READ(r2, SP); \ - SP = (SP + 1) & 0xFFFF; \ - READ(r1, SP); \ - SP = (SP + 1) & 0xFFFF; \ + READ(r2, sp); \ + sp = (sp + 1) & 0xFFFF; \ + READ(r1, sp); \ + sp = (sp + 1) & 0xFFFF; \ } while (0) -//8-BIT ALU: -//add a,r (4 cycles): -//add a,(addr) (8 cycles): -//Add 8-bit value to A, check flags: +// 8-BIT ALU: +// add a,r (4 cycles): +// add a,(addr) (8 cycles): +// Add 8-bit value to A, check flags: #define add_a_u8(u8) do { \ - HF1 = A; \ - HF2 = u8; \ - ZF = CF = A + HF2; \ - A = ZF & 0xFF; \ + hf1 = a; \ + hf2 = u8; \ + zf = cf = a + hf2; \ + a = zf & 0xFF; \ } while (0) -//adc a,r (4 cycles): -//adc a,(addr) (8 cycles): -//Add 8-bit value+CF to A, check flags: +// adc a,r (4 cycles): +// adc a,(addr) (8 cycles): +// Add 8-bit value+CF to A, check flags: #define adc_a_u8(u8) do { \ - HF1 = A; \ - HF2 = (CF & 0x100) | (u8); \ - ZF = CF = (CF >> 8 & 1) + (u8) + A; \ - A = ZF & 0xFF; \ + hf1 = a; \ + hf2 = (cf & 0x100) | (u8); \ + zf = cf = (cf >> 8 & 1) + (u8) + a; \ + a = zf & 0xFF; \ } while (0) -//sub a,r (4 cycles): -//sub a,(addr) (8 cycles): -//Subtract 8-bit value from A, check flags: +// sub a,r (4 cycles): +// sub a,(addr) (8 cycles): +// Subtract 8-bit value from A, check flags: #define sub_a_u8(u8) do { \ - HF1 = A; \ - HF2 = u8; \ - ZF = CF = A - HF2; \ - A = ZF & 0xFF; \ - HF2 |= 0x400; \ + hf1 = a; \ + hf2 = u8; \ + zf = cf = a - hf2; \ + a = zf & 0xFF; \ + hf2 |= hf2_subf; \ } while (0) -//sbc a,r (4 cycles): -//sbc a,(addr) (8 cycles): -//Subtract CF and 8-bit value from A, check flags: +// sbc a,r (4 cycles): +// sbc a,(addr) (8 cycles): +// Subtract CF and 8-bit value from A, check flags: #define sbc_a_u8(u8) do { \ - HF1 = A; \ - HF2 = 0x400 | (CF & 0x100) | (u8); \ - ZF = CF = A - ((CF >> 8) & 1) - (u8); \ - A = ZF & 0xFF; \ + hf1 = a; \ + hf2 = hf2_subf | (cf & 0x100) | (u8); \ + zf = cf = a - ((cf >> 8) & 1) - (u8); \ + a = zf & 0xFF; \ } while (0) -//and a,r (4 cycles): -//and a,(addr) (8 cycles): -//bitwise and 8-bit value into A, check flags: +// and a,r (4 cycles): +// and a,(addr) (8 cycles): +// bitwise and 8-bit value into A, check flags: #define and_a_u8(u8) do { \ - HF2 = 0x200; \ - CF = 0; \ - A &= (u8); \ - ZF = A; \ + hf2 = hf2_hcf; \ + cf = 0; \ + a &= (u8); \ + zf = a; \ } while (0) -//or a,r (4 cycles): -//or a,(hl) (8 cycles): -//bitwise or 8-bit value into A, check flags: +// or a,r (4 cycles): +// or a,(hl) (8 cycles): +// bitwise or 8-bit value into A, check flags: #define or_a_u8(u8) do { \ - CF = HF2 = 0; \ - A |= (u8); \ - ZF = A; \ + cf = hf2 = 0; \ + a |= (u8); \ + zf = a; \ } while (0) -//xor a,r (4 cycles): -//xor a,(hl) (8 cycles): -//bitwise xor 8-bit value into A, check flags: +// xor a,r (4 cycles): +// xor a,(hl) (8 cycles): +// bitwise xor 8-bit value into A, check flags: #define xor_a_u8(u8) do { \ - CF = HF2 = 0; \ - A ^= (u8); \ - ZF = A; \ + cf = hf2 = 0; \ + a ^= (u8); \ + zf = a; \ } while (0) -//cp a,r (4 cycles): -//cp a,(addr) (8 cycles): -//Compare (subtract without storing result) 8-bit value to A, check flags: +// cp a,r (4 cycles): +// cp a,(addr) (8 cycles): +// Compare (subtract without storing result) 8-bit value to A, check flags: #define cp_a_u8(u8) do { \ - HF1 = A; \ - HF2 = u8; \ - ZF = CF = A - HF2; \ - HF2 |= 0x400; \ + hf1 = a; \ + hf2 = u8; \ + zf = cf = a - hf2; \ + hf2 |= hf2_subf; \ } while (0) -//inc r (4 cycles): -//Increment value of 8-bit register, check flags except CF: +// inc r (4 cycles): +// Increment value of 8-bit register, check flags except CF: #define inc_r(r) do { \ - HF2 = (r) | 0x800; \ - ZF = (r) + 1; \ - (r) = ZF & 0xFF; \ + hf2 = (r) | hf2_incf; \ + zf = (r) + 1; \ + (r) = zf & 0xFF; \ } while (0) -//dec r (4 cycles): -//Decrement value of 8-bit register, check flags except CF: +// dec r (4 cycles): +// Decrement value of 8-bit register, check flags except CF: #define dec_r(r) do { \ - HF2 = (r) | 0xC00; \ - ZF = (r) - 1; \ - (r) = ZF & 0xFF; \ + hf2 = (r) | hf2_incf | hf2_subf; \ + zf = (r) - 1; \ + (r) = zf & 0xFF; \ } while (0) -//16-BIT ARITHMETIC -//add hl,rr (8 cycles): -//add 16-bit register to HL, check flags except ZF: -/*#define add_hl_rr(rh, rl) do { \ - L = HF1 = L + (rl); \ - HF1 >>= 8; \ - HF1 += H; \ - HF2 = (rh); \ - H = CF = HF1 + (rh); \ - cycleCounter += 4; \ -} while (0)*/ - +// 16-BIT ARITHMETIC +// add hl,rr (8 cycles): +// add 16-bit register to HL, check flags except ZF: #define add_hl_rr(rh, rl) do { \ - CF = L + (rl); \ - L = CF & 0xFF; \ - HF1 = H; \ - HF2 = (CF & 0x100) | (rh); \ - CF = H + (CF >> 8) + (rh); \ - H = CF & 0xFF; \ + cf = l + (rl); \ + l = cf & 0xFF; \ + hf1 = h; \ + hf2 = (cf & 0x100) | (rh); \ + cf = h + (cf >> 8) + (rh); \ + h = cf & 0xFF; \ cycleCounter += 4; \ } while (0) -//inc rr (8 cycles): -//Increment 16-bit register: +// inc rr (8 cycles): +// Increment 16-bit register: #define inc_rr(rh, rl) do { \ - const unsigned inc_rr_var_tmp = (rl) + 1; \ - (rl) = inc_rr_var_tmp & 0xFF; \ - (rh) = ((rh) + (inc_rr_var_tmp >> 8)) & 0xFF; \ + unsigned const lowinc = (rl) + 1; \ + (rl) = lowinc & 0xFF; \ + (rh) = ((rh) + (lowinc >> 8)) & 0xFF; \ cycleCounter += 4; \ } while (0) -//dec rr (8 cycles): -//Decrement 16-bit register: +// dec rr (8 cycles): +// Decrement 16-bit register: #define dec_rr(rh, rl) do { \ - const unsigned dec_rr_var_tmp = (rl) - 1; \ - (rl) = dec_rr_var_tmp & 0xFF; \ - (rh) = ((rh) - (dec_rr_var_tmp >> 8 & 1)) & 0xFF; \ + unsigned const lowdec = (rl) - 1; \ + (rl) = lowdec & 0xFF; \ + (rh) = ((rh) - (lowdec >> 8 & 1)) & 0xFF; \ cycleCounter += 4; \ } while (0) #define sp_plus_n(sumout) do { \ - unsigned sp_plus_n_var_n; \ - PC_READ(sp_plus_n_var_n); \ - sp_plus_n_var_n = (sp_plus_n_var_n ^ 0x80) - 0x80; \ - \ - const unsigned sp_plus_n_var_sum = SP + sp_plus_n_var_n; \ - CF = SP ^ sp_plus_n_var_n ^ sp_plus_n_var_sum; \ - HF2 = CF << 5 & 0x200; \ - ZF = 1; \ + unsigned disp; \ + PC_READ(disp); \ + disp = (disp ^ 0x80) - 0x80; \ +\ + unsigned const res = sp + disp; \ + cf = sp ^ disp ^ res; \ + hf2 = cf << 5 & hf2_hcf; \ + zf = 1; \ cycleCounter += 4; \ - (sumout) = sp_plus_n_var_sum & 0xFFFF; \ + (sumout) = res & 0xFFFF; \ } while (0) -//JUMPS: -//jp nn (16 cycles): -//Jump to address stored in the next two bytes in memory: +// JUMPS: +// jp nn (16 cycles): +// Jump to address stored in the next two bytes in memory: #define jp_nn() do { \ - unsigned jp_nn_var_l, jp_nn_var_h; \ -\ - PC_READ(jp_nn_var_l); \ - PC_READ(jp_nn_var_h); \ -\ - PC_MOD(jp_nn_var_h << 8 | jp_nn_var_l); \ + unsigned imm0, imm1; \ + PC_READ(imm0); \ + PC_READ(imm1); \ + PC_MOD(imm1 << 8 | imm0); \ } while (0) -//jr disp (12 cycles): -//Jump to value of next (signed) byte in memory+current address: +// jr disp (12 cycles): +// Jump to value of next (signed) byte in memory+current address: #define jr_disp() do { \ - unsigned jr_disp_var_tmp; \ -\ - PC_READ(jr_disp_var_tmp); \ - jr_disp_var_tmp = (jr_disp_var_tmp ^ 0x80) - 0x80; \ -\ - PC_MOD((PC + jr_disp_var_tmp) & 0xFFFF); \ + unsigned disp; \ + PC_READ(disp); \ + disp = (disp ^ 0x80) - 0x80; \ + PC_MOD((pc + disp) & 0xFFFF); \ } while (0) // CALLS, RESTARTS AND RETURNS: // call nn (24 cycles): // Jump to 16-bit immediate operand and push return address onto stack: #define call_nn() do { \ - unsigned const npc = (PC + 2) & 0xFFFF; \ + unsigned const npc = (pc + 2) & 0xFFFF; \ jp_nn(); \ PUSH(npc >> 8, npc & 0xFF); \ } while (0) -//rst n (16 Cycles): -//Push present address onto stack, jump to address n (one of 00h,08h,10h,18h,20h,28h,30h,38h): +// rst n (16 Cycles): +// Push present address onto stack, jump to address n (one of 00h,08h,10h,18h,20h,28h,30h,38h): #define rst_n(n) do { \ - PUSH(PC >> 8, PC & 0xFF); \ + PUSH(pc >> 8, pc & 0xFF); \ PC_MOD(n); \ } while (0) -//ret (16 cycles): -//Pop two bytes from the stack and jump to that address: +// ret (16 cycles): +// Pop two bytes from the stack and jump to that address: #define ret() do { \ - unsigned ret_var_l, ret_var_h; \ -\ - pop_rr(ret_var_h, ret_var_l); \ -\ - PC_MOD(ret_var_h << 8 | ret_var_l); \ + unsigned low, high; \ + pop_rr(high, low); \ + PC_MOD(high << 8 | low); \ } while (0) -void CPU::process(const unsigned long cycles) { - memory.setEndtime(cycleCounter_, cycles); +void CPU::process(unsigned long const cycles) { + mem_.setEndtime(cycleCounter_, cycles); hitInterruptAddress = 0; - memory.updateInput(); + mem_.updateInput(); - //unsigned char A = A_; + //unsigned char a = a_; unsigned long cycleCounter = cycleCounter_; - while (memory.isActive()) { - //unsigned short PC = PC_; + while (mem_.isActive()) { + //unsigned short pc = pc_; - if (memory.halted()) { - if (cycleCounter < memory.nextEventTime()) { - const unsigned long cycles = memory.nextEventTime() - cycleCounter; + if (mem_.halted()) { + if (cycleCounter < mem_.nextEventTime()) { + unsigned long cycles = mem_.nextEventTime() - cycleCounter; cycleCounter += cycles + (-cycles & 3); } - } else while (cycleCounter < memory.nextEventTime()) { + } else while (cycleCounter < mem_.nextEventTime()) { unsigned char opcode = 0x00; - int FullPC = PC; + int FullPC = pc; - if (PC >= 0x4000 && PC <= 0x7FFF) - FullPC |= memory.curRomBank() << 16; + if (pc >= 0x4000 && pc <= 0x7FFF) + FullPC |= mem_.curRomBank() << 16; for (int i = 0; i < numInterruptAddresses; i++) { if (FullPC == interruptAddresses[i]) { hitInterruptAddress = interruptAddresses[i]; - memory.setEndtime(cycleCounter, 0); + mem_.setEndtime(cycleCounter, 0); break; } } @@ -527,2384 +510,1560 @@ void CPU::process(const unsigned long cycles) { if (tracecallback) { int result[14]; result[0] = cycleCounter; - result[1] = PC; - result[2] = SP; - result[3] = A; - result[4] = B; - result[5] = C; - result[6] = D; - result[7] = E; - result[8] = F(); - result[9] = H; - result[10] = L; - result[11] = skip; + result[1] = pc; + result[2] = sp; + result[3] = a; + result[4] = b; + result[5] = c; + result[6] = d; + result[7] = e; + result[8] = toF(hf2, cf, zf); + result[9] = h; + result[10] = l; + result[11] = skip_; PC_READ_FIRST(opcode); result[12] = opcode; - result[13] = memory.debugGetLY(); + result[13] = mem_.debugGetLY(); tracecallback((void *)result); } else { PC_READ_FIRST(opcode); } - if (skip) { - PC = (PC - 1) & 0xFFFF; - skip = false; + if (skip_) { + pc = (pc - 1) & 0xFFFF; + skip_ = false; } } switch (opcode) { - //nop (4 cycles): - //Do nothing for 4 cycles: case 0x00: break; case 0x01: - ld_rr_nn(B, C); + ld_rr_nn(b, c); break; case 0x02: - WRITE(BC(), A); + WRITE(bc(), a); break; case 0x03: - inc_rr(B, C); + inc_rr(b, c); break; case 0x04: - inc_r(B); + inc_r(b); break; case 0x05: - dec_r(B); + dec_r(b); break; case 0x06: - PC_READ(B); + PC_READ(b); break; - //rlca (4 cycles): - //Rotate 8-bit register A left, store old bit7 in CF. Reset SF, HCF, ZF: + // rlca (4 cycles): + // Rotate 8-bit register A left, store old bit7 in CF. Reset SF, HCF, ZF: case 0x07: - CF = A << 1; - A = (CF | CF >> 8) & 0xFF; - HF2 = 0; - ZF = 1; + cf = a << 1; + a = (cf | cf >> 8) & 0xFF; + hf2 = 0; + zf = 1; break; - //ld (nn),SP (20 cycles): - //Put value of SP into address given by next 2 bytes in memory: + // ld (nn),SP (20 cycles): + // Put value of SP into address given by next 2 bytes in memory: case 0x08: { - unsigned l, h; + unsigned imml, immh; + PC_READ(imml); + PC_READ(immh); - PC_READ(l); - PC_READ(h); - - const unsigned addr = h << 8 | l; - - WRITE(addr, SP & 0xFF); - WRITE((addr + 1) & 0xFFFF, SP >> 8); + unsigned const addr = immh << 8 | imml; + WRITE(addr, sp & 0xFF); + WRITE((addr + 1) & 0xFFFF, sp >> 8); } + break; case 0x09: - add_hl_rr(B, C); + add_hl_rr(b, c); break; case 0x0A: - READ(A, BC()); + READ(a, bc()); break; case 0x0B: - dec_rr(B, C); + dec_rr(b, c); break; case 0x0C: - inc_r(C); + inc_r(c); break; case 0x0D: - dec_r(C); + dec_r(c); break; case 0x0E: - PC_READ(C); + PC_READ(c); break; - //rrca (4 cycles): - //Rotate 8-bit register A right, store old bit0 in CF. Reset SF, HCF, ZF: + // rrca (4 cycles): + // Rotate 8-bit register A right, store old bit0 in CF. Reset SF, HCF, ZF: case 0x0F: - CF = A << 8 | A; - A = CF >> 1 & 0xFF; - HF2 = 0; - ZF = 1; + cf = a << 8 | a; + a = cf >> 1 & 0xFF; + hf2 = 0; + zf = 1; break; - //stop (4 cycles): - //Halt CPU and LCD display until button pressed: + // stop (4 cycles): + // Halt CPU and LCD display until button pressed: case 0x10: { - cycleCounter = memory.stop(cycleCounter); + cycleCounter = mem_.stop(cycleCounter); - if (cycleCounter < memory.nextEventTime()) { - const unsigned long cycles = memory.nextEventTime() - cycleCounter; + if (cycleCounter < mem_.nextEventTime()) { + unsigned long cycles = mem_.nextEventTime() - cycleCounter; cycleCounter += cycles + (-cycles & 3); } } break; + case 0x11: - ld_rr_nn(D, E); + ld_rr_nn(d, e); break; case 0x12: - WRITE(DE(), A); + WRITE(de(), a); break; case 0x13: - inc_rr(D, E); + inc_rr(d, e); break; case 0x14: - inc_r(D); + inc_r(d); break; case 0x15: - dec_r(D); + dec_r(d); break; case 0x16: - PC_READ(D); + PC_READ(d); break; - //rla (4 cycles): - //Rotate 8-bit register A left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF, HCF, ZF: + // rla (4 cycles): + // Rotate 8-bit register A left through CF, store old bit7 in CF, + // old CF value becomes bit0. Reset SF, HCF, ZF: case 0x17: { - const unsigned oldcf = CF >> 8 & 1; - CF = A << 1; - A = (CF | oldcf) & 0xFF; + unsigned oldcf = cf >> 8 & 1; + cf = a << 1; + a = (cf | oldcf) & 0xFF; } - HF2 = 0; - ZF = 1; + hf2 = 0; + zf = 1; break; case 0x18: jr_disp(); break; case 0x19: - add_hl_rr(D, E); + add_hl_rr(d, e); break; case 0x1A: - READ(A, DE()); + READ(a, de()); break; case 0x1B: - dec_rr(D, E); + dec_rr(d, e); break; case 0x1C: - inc_r(E); + inc_r(e); break; case 0x1D: - dec_r(E); + dec_r(e); break; case 0x1E: - PC_READ(E); + PC_READ(e); break; - //rra (4 cycles): - //Rotate 8-bit register A right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF, HCF, ZF: + // rra (4 cycles): + // Rotate 8-bit register A right through CF, store old bit0 in CF, + // old CF value becomes bit7. Reset SF, HCF, ZF: case 0x1F: { - const unsigned oldcf = CF & 0x100; - CF = A << 8; - A = (A | oldcf) >> 1; + unsigned oldcf = cf & 0x100; + cf = a << 8; + a = (a | oldcf) >> 1; } - HF2 = 0; - ZF = 1; - break; + hf2 = 0; + zf = 1; + break; - //jr nz,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if ZF is unset: + // jr nz,disp (12;8 cycles): + // Jump to value of next (signed) byte in memory+current address if ZF is unset: case 0x20: - if (ZF & 0xFF) { + if (zf & 0xFF) { jr_disp(); } else { - PC_MOD((PC + 1) & 0xFFFF); + PC_MOD((pc + 1) & 0xFFFF); } + break; - case 0x21: - ld_rr_nn(H, L); - break; + case 0x21: ld_rr_nn(h, l); break; - //ldi (hl),a (8 cycles): - //Put A into memory address in hl. Increment HL: + // ldi (hl),a (8 cycles): + // Put A into memory address in hl. Increment HL: case 0x22: { - unsigned addr = HL(); - - WRITE(addr, A); + unsigned addr = hl(); + WRITE(addr, a); addr = (addr + 1) & 0xFFFF; - L = addr; - H = addr >> 8; + l = addr; + h = addr >> 8; } + break; case 0x23: - inc_rr(H, L); + inc_rr(h, l); break; case 0x24: - inc_r(H); + inc_r(h); break; case 0x25: - dec_r(H); + dec_r(h); break; case 0x26: - PC_READ(H); + PC_READ(h); break; - - //daa (4 cycles): - //Adjust register A to correctly represent a BCD. Check ZF, HF and CF: + // daa (4 cycles): + // Adjust register A to correctly represent a BCD. Check ZF, HF and CF: case 0x27: - /*{ - unsigned correction = ((A > 0x99) || (CF & 0x100)) ? 0x60 : 0x00; - - calcHF(HF1, HF2); - - if ((A & 0x0F) > 0x09 || (HF2 & 0x200)) - correction |= 0x06; - - HF1 = A; - HF2 = (HF2 & 0x400) | correction; - CF = (correction & 0x40) << 2; - A = (HF2 & 0x400) ? A - correction : (A + correction); - ZF = A; - }*/ - - calcHF(HF1, HF2); + hf2 = updateHf2FromHf1(hf1, hf2); { - unsigned correction = (CF & 0x100) ? 0x60 : 0x00; + unsigned correction = cf & 0x100 ? 0x60 : 0x00; - if (HF2 & 0x200) + if (hf2 & hf2_hcf) correction |= 0x06; - if (!(HF2 &= 0x400)) { - if ((A & 0x0F) > 0x09) + if (!(hf2 &= hf2_subf)) { + if ((a & 0x0F) > 0x09) correction |= 0x06; - - if (A > 0x99) + if (a > 0x99) correction |= 0x60; - A += correction; + a += correction; } else - A -= correction; + a -= correction; - CF = correction << 2 & 0x100; - ZF = A; - A &= 0xFF; + cf = correction << 2 & 0x100; + zf = a; + a &= 0xFF; } + break; - //jr z,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if ZF is set: + // jr z,disp (12;8 cycles): + // Jump to value of next (signed) byte in memory+current address if ZF is set: case 0x28: - if (ZF & 0xFF) { - PC_MOD((PC + 1) & 0xFFFF); + if (zf & 0xFF) { + PC_MOD((pc + 1) & 0xFFFF); } else { jr_disp(); } + break; - //add hl,hl (8 cycles): - //add 16-bit register HL to HL, check flags except ZF: case 0x29: - add_hl_rr(H, L); + add_hl_rr(h, l); break; - //ldi a,(hl) (8 cycles): - //Put value at address in hl into A. Increment HL: + // ldi a,(hl) (8 cycles): + // Put value at address in hl into A. Increment HL: case 0x2A: { - unsigned addr = HL(); - - READ(A, addr); + unsigned addr = hl(); + READ(a, addr); addr = (addr + 1) & 0xFFFF; - L = addr; - H = addr >> 8; + l = addr; + h = addr >> 8; } + break; case 0x2B: - dec_rr(H, L); + dec_rr(h, l); break; case 0x2C: - inc_r(L); + inc_r(l); break; case 0x2D: - dec_r(L); + dec_r(l); break; case 0x2E: - PC_READ(L); + PC_READ(l); break; - //cpl (4 cycles): - //Complement register A. (Flip all bits), set SF and HCF: - case 0x2F: /*setSubtractFlag(); setHalfCarryFlag();*/ - HF2 = 0x600; - A ^= 0xFF; + // cpl (4 cycles): + // Complement register A. (Flip all bits), set SF and HCF: + case 0x2F: + hf2 = hf2_subf | hf2_hcf; + a ^= 0xFF; break; - //jr nc,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if CF is unset: + // jr nc,disp (12;8 cycles): + // Jump to value of next (signed) byte in memory+current address if CF is unset: case 0x30: - if (CF & 0x100) { - PC_MOD((PC + 1) & 0xFFFF); + if (cf & 0x100) { + PC_MOD((pc + 1) & 0xFFFF); } else { jr_disp(); } + break; - //ld sp,nn (12 cycles) - //set sp to 16-bit value of next 2 bytes in memory + // ld sp,nn (12 cycles) + // set sp to 16-bit value of next 2 bytes in memory case 0x31: { - unsigned l, h; + unsigned imml, immh; + PC_READ(imml); + PC_READ(immh); - PC_READ(l); - PC_READ(h); - - SP = h << 8 | l; + sp = immh << 8 | imml; } + break; - //ldd (hl),a (8 cycles): - //Put A into memory address in hl. Decrement HL: + // ldd (hl),a (8 cycles): + // Put A into memory address in hl. Decrement HL: case 0x32: { - unsigned addr = HL(); - - WRITE(addr, A); + unsigned addr = hl(); + WRITE(addr, a); addr = (addr - 1) & 0xFFFF; - L = addr; - H = addr >> 8; + l = addr; + h = addr >> 8; } + break; case 0x33: - SP = (SP + 1) & 0xFFFF; + sp = (sp + 1) & 0xFFFF; cycleCounter += 4; break; - //inc (hl) (12 cycles): - //Increment value at address in hl, check flags except CF: + // inc (hl) (12 cycles): + // Increment value at address in hl, check flags except CF: case 0x34: { - const unsigned addr = HL(); - - READ(HF2, addr); - ZF = HF2 + 1; - WRITE(addr, ZF & 0xFF); - HF2 |= 0x800; + unsigned const addr = hl(); + READ(hf2, addr); + zf = hf2 + 1; + WRITE(addr, zf & 0xFF); + hf2 |= hf2_incf; } + break; - //dec (hl) (12 cycles): - //Decrement value at address in hl, check flags except CF: + // dec (hl) (12 cycles): + // Decrement value at address in hl, check flags except CF: case 0x35: { - const unsigned addr = HL(); - - READ(HF2, addr); - ZF = HF2 - 1; - WRITE(addr, ZF & 0xFF); - HF2 |= 0xC00; + unsigned const addr = hl(); + READ(hf2, addr); + zf = hf2 - 1; + WRITE(addr, zf & 0xFF); + hf2 |= hf2_incf | hf2_subf; } + break; - //ld (hl),n (12 cycles): - //set memory at address in hl to value of next byte in memory: + // ld (hl),n (12 cycles): + // set memory at address in hl to value of next byte in memory: case 0x36: { - unsigned tmp; - - PC_READ(tmp); - WRITE(HL(), tmp); + unsigned imm; + PC_READ(imm); + WRITE(hl(), imm); } + break; - //scf (4 cycles): - //Set CF. Unset SF and HCF: - case 0x37: /*setCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/ - CF = 0x100; - HF2 = 0; + // scf (4 cycles): + // Set CF. Unset SF and HCF: + case 0x37: + cf = 0x100; + hf2 = 0; break; - //jr c,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if CF is set: - case 0x38: //PC+=(((int8_t)memory.read(PC++))*CarryFlag()); Cycles(8); break; - if (CF & 0x100) { + // jr c,disp (12;8 cycles): + // Jump to value of next (signed) byte in memory+current address if CF is set: + case 0x38: + if (cf & 0x100) { jr_disp(); } else { - PC_MOD((PC + 1) & 0xFFFF); + PC_MOD((pc + 1) & 0xFFFF); } + break; - //add hl,sp (8 cycles): - //add SP to HL, check flags except ZF: - case 0x39: /*add_hl_rr(SP>>8, SP); break;*/ - CF = L + SP; - L = CF & 0xFF; - HF1 = H; - HF2 = ((CF ^ SP) & 0x100) | SP >> 8; - CF >>= 8; - CF += H; - H = CF & 0xFF; + // add hl,sp (8 cycles): + // add SP to HL, check flags except ZF: + case 0x39: + cf = l + sp; + l = cf & 0xFF; + hf1 = h; + hf2 = ((cf ^ sp) & 0x100) | sp >> 8; + cf >>= 8; + cf += h; + h = cf & 0xFF; cycleCounter += 4; break; - //ldd a,(hl) (8 cycles): - //Put value at address in hl into A. Decrement HL: + // ldd a,(hl) (8 cycles): + // Put value at address in hl into A. Decrement HL: case 0x3A: { - unsigned addr = HL(); - - A = memory.read(addr, cycleCounter); + unsigned addr = hl(); + a = mem_.read(addr, cycleCounter); cycleCounter += 4; addr = (addr - 1) & 0xFFFF; - L = addr; - H = addr >> 8; + l = addr; + h = addr >> 8; } + break; case 0x3B: - SP = (SP - 1) & 0xFFFF; + sp = (sp - 1) & 0xFFFF; cycleCounter += 4; break; + case 0x3C: - inc_r(A); + inc_r(a); break; case 0x3D: - dec_r(A); + dec_r(a); break; case 0x3E: - PC_READ(A); + PC_READ(a); break; - //ccf (4 cycles): - //Complement CF (unset if set vv.) Unset SF and HCF. - case 0x3F: /*complementCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/ - CF ^= 0x100; - HF2 = 0; + // ccf (4 cycles): + // Complement CF (unset if set vv.) Unset SF and HCF. + case 0x3F: + cf ^= 0x100; + hf2 = 0; break; - //ld r,r (4 cycles):next_irqEventTime - //ld r,(r) (8 cycles): - case 0x40: - B = B; - break; - case 0x41: - B = C; - break; - case 0x42: - B = D; - break; - case 0x43: - B = E; - break; - case 0x44: - B = H; - break; - case 0x45: - B = L; - break; - case 0x46: - READ(B, HL()); - break; - case 0x47: - B = A; - break; - case 0x48: - C = B; - break; - case 0x49: - C = C; - break; - case 0x4A: - C = D; - break; - case 0x4B: - C = E; - break; - case 0x4C: - C = H; - break; - case 0x4D: - C = L; - break; - case 0x4E: - READ(C, HL()); - break; - case 0x4F: - C = A; - break; - case 0x50: - D = B; - break; - case 0x51: - D = C; - break; - case 0x52: - D = D; - break; - case 0x53: - D = E; - break; - case 0x54: - D = H; - break; - case 0x55: - D = L; - break; - case 0x56: - READ(D, HL()); - break; - case 0x57: - D = A; - break; - case 0x58: - E = B; - break; - case 0x59: - E = C; - break; - case 0x5A: - E = D; - break; - case 0x5B: - E = E; - break; - case 0x5C: - E = H; - break; - case 0x5D: - E = L; - break; - case 0x5E: - READ(E, HL()); - break; - case 0x5F: - E = A; - break; - case 0x60: - H = B; - break; - case 0x61: - H = C; - break; - case 0x62: - H = D; - break; - case 0x63: - H = E; - break; - case 0x64: - H = H; - break; - case 0x65: - H = L; - break; - case 0x66: - READ(H, HL()); - break; - case 0x67: - H = A; - break; - case 0x68: - L = B; - break; - case 0x69: - L = C; - break; - case 0x6A: - L = D; - break; - case 0x6B: - L = E; - break; - case 0x6C: - L = H; - break; - case 0x6D: - L = L; - break; - case 0x6E: - READ(L, HL()); - break; - case 0x6F: - L = A; - break; - case 0x70: - WRITE(HL(), B); - break; - case 0x71: - WRITE(HL(), C); - break; - case 0x72: - WRITE(HL(), D); - break; - case 0x73: - WRITE(HL(), E); - break; - case 0x74: - WRITE(HL(), H); - break; - case 0x75: - WRITE(HL(), L); - break; + case 0x40: /*b = b;*/ break; + case 0x41: b = c; break; + case 0x42: b = d; break; + case 0x43: b = e; break; + case 0x44: b = h; break; + case 0x45: b = l; break; + case 0x46: READ(b, hl()); break; + case 0x47: b = a; break; - //halt (4 cycles): + case 0x48: c = b; break; + case 0x49: /*c = c;*/ break; + case 0x4A: c = d; break; + case 0x4B: c = e; break; + case 0x4C: c = h; break; + case 0x4D: c = l; break; + case 0x4E: READ(c, hl()); break; + case 0x4F: c = a; break; + + case 0x50: d = b; break; + case 0x51: d = c; break; + case 0x52: /*d = d;*/ break; + case 0x53: d = e; break; + case 0x54: d = h; break; + case 0x55: d = l; break; + case 0x56: READ(d, hl()); break; + case 0x57: d = a; break; + + case 0x58: e = b; break; + case 0x59: e = c; break; + case 0x5A: e = d; break; + case 0x5B: /*e = e;*/ break; + case 0x5C: e = h; break; + case 0x5D: e = l; break; + case 0x5E: READ(e, hl()); break; + case 0x5F: e = a; break; + + case 0x60: h = b; break; + case 0x61: h = c; break; + case 0x62: h = d; break; + case 0x63: h = e; break; + case 0x64: /*h = h;*/ break; + case 0x65: h = l; break; + case 0x66: READ(h, hl()); break; + case 0x67: h = a; break; + + case 0x68: l = b; break; + case 0x69: l = c; break; + case 0x6A: l = d; break; + case 0x6B: l = e; break; + case 0x6C: l = h; break; + case 0x6D: /*l = l;*/ break; + case 0x6E: READ(l, hl()); break; + case 0x6F: l = a; break; + + case 0x70: WRITE(hl(), b); break; + case 0x71: WRITE(hl(), c); break; + case 0x72: WRITE(hl(), d); break; + case 0x73: WRITE(hl(), e); break; + case 0x74: WRITE(hl(), h); break; + case 0x75: WRITE(hl(), l); break; + + // halt (4 cycles): case 0x76: - if (memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter) & 0x1F) { - if (memory.ime()) - PC = (PC - 1) & 0xFFFF; + if (mem_.ff_read(0x0F, cycleCounter) & mem_.ff_read(0xFF, cycleCounter) & 0x1F) { + if (mem_.ime()) + pc = (pc - 1) & 0xFFFF; else - skip = true; + skip_ = true; } else { - memory.halt(cycleCounter); + mem_.halt(cycleCounter); - if (cycleCounter < memory.nextEventTime()) { - const unsigned long cycles = memory.nextEventTime() - cycleCounter; + if (cycleCounter < mem_.nextEventTime()) { + unsigned long cycles = mem_.nextEventTime() - cycleCounter; cycleCounter += cycles + (-cycles & 3); } } break; - case 0x77: - WRITE(HL(), A); - break; - case 0x78: - A = B; - break; - case 0x79: - A = C; - break; - case 0x7A: - A = D; - break; - case 0x7B: - A = E; - break; - case 0x7C: - A = H; - break; - case 0x7D: - A = L; - break; - case 0x7E: - READ(A, HL()); - break; - case 0x7F: - // A = A; - break; - case 0x80: - add_a_u8(B); - break; - case 0x81: - add_a_u8(C); - break; - case 0x82: - add_a_u8(D); - break; - case 0x83: - add_a_u8(E); - break; - case 0x84: - add_a_u8(H); - break; - case 0x85: - add_a_u8(L); - break; - case 0x86: - { - unsigned data; - READ(data, HL()); + case 0x77: WRITE(hl(), a); break; + case 0x78: a = b; break; + case 0x79: a = c; break; + case 0x7A: a = d; break; + case 0x7B: a = e; break; + case 0x7C: a = h; break; + case 0x7D: a = l; break; + case 0x7E: READ(a, hl()); break; + case 0x7F: /*a = a;*/ break; - add_a_u8(data); - } - break; - case 0x87: - add_a_u8(A); - break; - case 0x88: - adc_a_u8(B); - break; - case 0x89: - adc_a_u8(C); - break; - case 0x8A: - adc_a_u8(D); - break; - case 0x8B: - adc_a_u8(E); - break; - case 0x8C: - adc_a_u8(H); - break; - case 0x8D: - adc_a_u8(L); - break; - case 0x8E: - { - unsigned data; + case 0x80: add_a_u8(b); break; + case 0x81: add_a_u8(c); break; + case 0x82: add_a_u8(d); break; + case 0x83: add_a_u8(e); break; + case 0x84: add_a_u8(h); break; + case 0x85: add_a_u8(l); break; + case 0x86: { unsigned data; READ(data, hl()); add_a_u8(data); } break; + case 0x87: add_a_u8(a); break; - READ(data, HL()); + case 0x88: adc_a_u8(b); break; + case 0x89: adc_a_u8(c); break; + case 0x8A: adc_a_u8(d); break; + case 0x8B: adc_a_u8(e); break; + case 0x8C: adc_a_u8(h); break; + case 0x8D: adc_a_u8(l); break; + case 0x8E: { unsigned data; READ(data, hl()); adc_a_u8(data); } break; + case 0x8F: adc_a_u8(a); break; - adc_a_u8(data); - } - break; - case 0x8F: - adc_a_u8(A); - break; - case 0x90: - sub_a_u8(B); - break; - case 0x91: - sub_a_u8(C); - break; - case 0x92: - sub_a_u8(D); - break; - case 0x93: - sub_a_u8(E); - break; - case 0x94: - sub_a_u8(H); - break; - case 0x95: - sub_a_u8(L); - break; - case 0x96: - { - unsigned data; + case 0x90: sub_a_u8(b); break; + case 0x91: sub_a_u8(c); break; + case 0x92: sub_a_u8(d); break; + case 0x93: sub_a_u8(e); break; + case 0x94: sub_a_u8(h); break; + case 0x95: sub_a_u8(l); break; + case 0x96: { unsigned data; READ(data, hl()); sub_a_u8(data); } break; - READ(data, HL()); - - sub_a_u8(data); - } - break; - //A-A is always 0: + // A-A is always 0: case 0x97: - HF2 = 0x400; - CF = ZF = A = 0; + hf2 = hf2_subf; + cf = zf = a = 0; break; - case 0x98: - sbc_a_u8(B); - break; - case 0x99: - sbc_a_u8(C); - break; - case 0x9A: - sbc_a_u8(D); - break; - case 0x9B: - sbc_a_u8(E); - break; - case 0x9C: - sbc_a_u8(H); - break; - case 0x9D: - sbc_a_u8(L); - break; - case 0x9E: - { - unsigned data; - READ(data, HL()); + case 0x98: sbc_a_u8(b); break; + case 0x99: sbc_a_u8(c); break; + case 0x9A: sbc_a_u8(d); break; + case 0x9B: sbc_a_u8(e); break; + case 0x9C: sbc_a_u8(h); break; + case 0x9D: sbc_a_u8(l); break; + case 0x9E: { unsigned data; READ(data, hl()); sbc_a_u8(data); } break; + case 0x9F: sbc_a_u8(a); break; - sbc_a_u8(data); - } - break; - case 0x9F: - sbc_a_u8(A); - break; - case 0xA0: - and_a_u8(B); - break; - case 0xA1: - and_a_u8(C); - break; - case 0xA2: - and_a_u8(D); - break; - case 0xA3: - and_a_u8(E); - break; - case 0xA4: - and_a_u8(H); - break; - case 0xA5: - and_a_u8(L); - break; - case 0xA6: - { - unsigned data; + case 0xA0: and_a_u8(b); break; + case 0xA1: and_a_u8(c); break; + case 0xA2: and_a_u8(d); break; + case 0xA3: and_a_u8(e); break; + case 0xA4: and_a_u8(h); break; + case 0xA5: and_a_u8(l); break; + case 0xA6: { unsigned data; READ(data, hl()); and_a_u8(data); } break; - READ(data, HL()); - - and_a_u8(data); - } - break; - //A&A will always be A: + // A&A will always be A: case 0xA7: - ZF = A; - CF = 0; - HF2 = 0x200; + zf = a; + cf = 0; + hf2 = hf2_hcf; break; - case 0xA8: - xor_a_u8(B); - break; - case 0xA9: - xor_a_u8(C); - break; - case 0xAA: - xor_a_u8(D); - break; - case 0xAB: - xor_a_u8(E); - break; - case 0xAC: - xor_a_u8(H); - break; - case 0xAD: - xor_a_u8(L); - break; - case 0xAE: - { - unsigned data; - READ(data, HL()); + case 0xA8: xor_a_u8(b); break; + case 0xA9: xor_a_u8(c); break; + case 0xAA: xor_a_u8(d); break; + case 0xAB: xor_a_u8(e); break; + case 0xAC: xor_a_u8(h); break; + case 0xAD: xor_a_u8(l); break; + case 0xAE: { unsigned data; READ(data, hl()); xor_a_u8(data); } break; - xor_a_u8(data); - } - break; - //A^A will always be 0: - case 0xAF: - CF = HF2 = ZF = A = 0; - break; - case 0xB0: - or_a_u8(B); - break; - case 0xB1: - or_a_u8(C); - break; - case 0xB2: - or_a_u8(D); - break; - case 0xB3: - or_a_u8(E); - break; - case 0xB4: - or_a_u8(H); - break; - case 0xB5: - or_a_u8(L); - break; - case 0xB6: - { - unsigned data; + // A^A will always be 0: + case 0xAF: cf = hf2 = zf = a = 0; break; - READ(data, HL()); + case 0xB0: or_a_u8(b); break; + case 0xB1: or_a_u8(c); break; + case 0xB2: or_a_u8(d); break; + case 0xB3: or_a_u8(e); break; + case 0xB4: or_a_u8(h); break; + case 0xB5: or_a_u8(l); break; + case 0xB6: { unsigned data; READ(data, hl()); or_a_u8(data); } break; - or_a_u8(data); - } - break; - //A|A will always be A: + // A|A will always be A: case 0xB7: - ZF = A; - HF2 = CF = 0; + zf = a; + hf2 = cf = 0; break; - case 0xB8: - cp_a_u8(B); - break; - case 0xB9: - cp_a_u8(C); - break; - case 0xBA: - cp_a_u8(D); - break; - case 0xBB: - cp_a_u8(E); - break; - case 0xBC: - cp_a_u8(H); - break; - case 0xBD: - cp_a_u8(L); - break; - case 0xBE: - { - unsigned data; - READ(data, HL()); + case 0xB8: cp_a_u8(b); break; + case 0xB9: cp_a_u8(c); break; + case 0xBA: cp_a_u8(d); break; + case 0xBB: cp_a_u8(e); break; + case 0xBC: cp_a_u8(h); break; + case 0xBD: cp_a_u8(l); break; + case 0xBE: { unsigned data; READ(data, hl()); cp_a_u8(data); } break; - cp_a_u8(data); - } - break; - //A always equals A: + // A always equals A: case 0xBF: - CF = ZF = 0; - HF2 = 0x400; + cf = zf = 0; + hf2 = hf2_subf; break; - //ret nz (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if ZF is unset: + // ret nz (20;8 cycles): + // Pop two bytes from the stack and jump to that address, if ZF is unset: case 0xC0: cycleCounter += 4; - if (ZF & 0xFF) { + if (zf & 0xFF) ret(); - } + break; case 0xC1: - pop_rr(B, C); + pop_rr(b, c); break; - //jp nz,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if ZF is unset: + // jp nz,nn (16;12 cycles): + // Jump to address stored in next two bytes in memory if ZF is unset: case 0xC2: - if (ZF & 0xFF) { + if (zf & 0xFF) { jp_nn(); } else { - PC_MOD((PC + 2) & 0xFFFF); + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } + break; case 0xC3: jp_nn(); break; - //call nz,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if ZF is unset: + // call nz,nn (24;12 cycles): + // Push address of next instruction onto stack and then jump to + // address stored in next two bytes in memory, if ZF is unset: case 0xC4: - if (ZF & 0xFF) { + if (zf & 0xFF) { call_nn(); } else { - PC_MOD((PC + 2) & 0xFFFF); + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } + break; case 0xC5: - push_rr(B, C); + push_rr(b, c); break; case 0xC6: { unsigned data; - PC_READ(data); - add_a_u8(data); } + break; + case 0xC7: rst_n(0x00); break; - //ret z (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if ZF is set: + // ret z (20;8 cycles): + // Pop two bytes from the stack and jump to that address, if ZF is set: case 0xC8: cycleCounter += 4; - if (!(ZF & 0xFF)) { + if (!(zf & 0xFF)) ret(); - } break; - //ret (16 cycles): - //Pop two bytes from the stack and jump to that address: + // ret (16 cycles): + // Pop two bytes from the stack and jump to that address: case 0xC9: ret(); break; - //jp z,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if ZF is set: + // jp z,nn (16;12 cycles): + // Jump to address stored in next two bytes in memory if ZF is set: case 0xCA: - if (ZF & 0xFF) { - PC_MOD((PC + 2) & 0xFFFF); + if (zf & 0xFF) { + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } else { jp_nn(); } + break; - //CB OPCODES (Shifts, rotates and bits): + // CB OPCODES (Shifts, rotates and bits): case 0xCB: PC_READ(opcode); switch (opcode) { - case 0x00: - rlc_r(B); - break; - case 0x01: - rlc_r(C); - break; - case 0x02: - rlc_r(D); - break; - case 0x03: - rlc_r(E); - break; - case 0x04: - rlc_r(H); - break; - case 0x05: - rlc_r(L); - break; - //rlc (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL left, store old bit7 in CF. Reset SF and HCF. Check ZF: + case 0x00: rlc_r(b); break; + case 0x01: rlc_r(c); break; + case 0x02: rlc_r(d); break; + case 0x03: rlc_r(e); break; + case 0x04: rlc_r(h); break; + case 0x05: rlc_r(l); break; + + // rlc (hl) (16 cycles): + // Rotate 8-bit value stored at address in HL left, store old bit7 in CF. + // Reset SF and HCF. Check ZF: case 0x06: { - const unsigned addr = HL(); - - READ(CF, addr); - CF <<= 1; - - ZF = CF | (CF >> 8); - - WRITE(addr, ZF & 0xFF); - - HF2 = 0; + unsigned const addr = hl(); + READ(cf, addr); + cf <<= 1; + zf = cf | (cf >> 8); + WRITE(addr, zf & 0xFF); + hf2 = 0; } + break; - case 0x07: - rlc_r(A); - break; - case 0x08: - rrc_r(B); - break; - case 0x09: - rrc_r(C); - break; - case 0x0A: - rrc_r(D); - break; - case 0x0B: - rrc_r(E); - break; - case 0x0C: - rrc_r(H); - break; - case 0x0D: - rrc_r(L); - break; - //rrc (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL right, store old bit0 in CF. Reset SF and HCF. Check ZF: + + case 0x07: rlc_r(a); break; + + case 0x08: rrc_r(b); break; + case 0x09: rrc_r(c); break; + case 0x0A: rrc_r(d); break; + case 0x0B: rrc_r(e); break; + case 0x0C: rrc_r(h); break; + case 0x0D: rrc_r(l); break; + + // rrc (hl) (16 cycles): + // Rotate 8-bit value stored at address in HL right, store old bit0 in CF. + // Reset SF and HCF. Check ZF: case 0x0E: { - const unsigned addr = HL(); - - READ(ZF, addr); - - CF = ZF << 8; - - WRITE(addr, (ZF | CF) >> 1 & 0xFF); - - HF2 = 0; + unsigned const addr = hl(); + READ(zf, addr); + cf = zf << 8; + WRITE(addr, (zf | cf) >> 1 & 0xFF); + hf2 = 0; } + break; - case 0x0F: - rrc_r(A); - break; - case 0x10: - rl_r(B); - break; - case 0x11: - rl_r(C); - break; - case 0x12: - rl_r(D); - break; - case 0x13: - rl_r(E); - break; - case 0x14: - rl_r(H); - break; - case 0x15: - rl_r(L); - break; - //rl (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL left thorugh CF, store old bit7 in CF, old CF value becoms bit0. Reset SF and HCF. Check ZF: + + case 0x0F: rrc_r(a); break; + + case 0x10: rl_r(b); break; + case 0x11: rl_r(c); break; + case 0x12: rl_r(d); break; + case 0x13: rl_r(e); break; + case 0x14: rl_r(h); break; + case 0x15: rl_r(l); break; + + // rl (hl) (16 cycles): + // Rotate 8-bit value stored at address in HL left thorugh CF, + // store old bit7 in CF, old CF value becoms bit0. Reset SF and HCF. Check ZF: case 0x16: { - const unsigned addr = HL(); - const unsigned oldcf = CF >> 8 & 1; - - READ(CF, addr); - CF <<= 1; - - ZF = CF | oldcf; - - WRITE(addr, ZF & 0xFF); - - HF2 = 0; + unsigned const addr = hl(); + unsigned const oldcf = cf >> 8 & 1; + READ(cf, addr); + cf <<= 1; + zf = cf | oldcf; + WRITE(addr, zf & 0xFF); + hf2 = 0; } break; - case 0x17: - rl_r(A); - break; - case 0x18: - rr_r(B); - break; - case 0x19: - rr_r(C); - break; - case 0x1A: - rr_r(D); - break; - case 0x1B: - rr_r(E); - break; - case 0x1C: - rr_r(H); - break; - case 0x1D: - rr_r(L); - break; - //rr (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL right thorugh CF, store old bit0 in CF, old CF value becoms bit7. Reset SF and HCF. Check ZF: + + case 0x17: rl_r(a); break; + + case 0x18: rr_r(b); break; + case 0x19: rr_r(c); break; + case 0x1A: rr_r(d); break; + case 0x1B: rr_r(e); break; + case 0x1C: rr_r(h); break; + case 0x1D: rr_r(l); break; + + // rr (hl) (16 cycles): + // Rotate 8-bit value stored at address in HL right thorugh CF, + // store old bit0 in CF, old CF value becoms bit7. Reset SF and HCF. Check ZF: case 0x1E: { - const unsigned addr = HL(); + unsigned const addr = hl(); + READ(zf, addr); - READ(ZF, addr); - - const unsigned oldcf = CF & 0x100; - CF = ZF << 8; - ZF = (ZF | oldcf) >> 1; - - WRITE(addr, ZF); - - HF2 = 0; + unsigned const oldcf = cf & 0x100; + cf = zf << 8; + zf = (zf | oldcf) >> 1; + WRITE(addr, zf); + hf2 = 0; } + break; - case 0x1F: - rr_r(A); - break; - case 0x20: - sla_r(B); - break; - case 0x21: - sla_r(C); - break; - case 0x22: - sla_r(D); - break; - case 0x23: - sla_r(E); - break; - case 0x24: - sla_r(H); - break; - case 0x25: - sla_r(L); - break; - //sla (hl) (16 cycles): - //Shift 8-bit value stored at address in HL left, store old bit7 in CF. Reset SF and HCF. Check ZF: + + case 0x1F: rr_r(a); break; + + case 0x20: sla_r(b); break; + case 0x21: sla_r(c); break; + case 0x22: sla_r(d); break; + case 0x23: sla_r(e); break; + case 0x24: sla_r(h); break; + case 0x25: sla_r(l); break; + + // sla (hl) (16 cycles): + // Shift 8-bit value stored at address in HL left, store old bit7 in CF. + // Reset SF and HCF. Check ZF: case 0x26: { - const unsigned addr = HL(); - - READ(CF, addr); - CF <<= 1; - - ZF = CF; - - WRITE(addr, ZF & 0xFF); - - HF2 = 0; + unsigned const addr = hl(); + READ(cf, addr); + cf <<= 1; + zf = cf; + WRITE(addr, zf & 0xFF); + hf2 = 0; } + break; - case 0x27: - sla_r(A); - break; - case 0x28: - sra_r(B); - break; - case 0x29: - sra_r(C); - break; - case 0x2A: - sra_r(D); - break; - case 0x2B: - sra_r(E); - break; - case 0x2C: - sra_r(H); - break; - case 0x2D: - sra_r(L); - break; - //sra (hl) (16 cycles): - //Shift 8-bit value stored at address in HL right, store old bit0 in CF, bit7=old bit7. Reset SF and HCF. Check ZF: + + case 0x27: sla_r(a); break; + + case 0x28: sra_r(b); break; + case 0x29: sra_r(c); break; + case 0x2A: sra_r(d); break; + case 0x2B: sra_r(e); break; + case 0x2C: sra_r(h); break; + case 0x2D: sra_r(l); break; + + // sra (hl) (16 cycles): + // Shift 8-bit value stored at address in HL right, store old bit0 in CF, + // bit7=old bit7. Reset SF and HCF. Check ZF: case 0x2E: { - const unsigned addr = HL(); - - READ(CF, addr); - - ZF = CF >> 1; - - WRITE(addr, ZF | (CF & 0x80)); - - CF <<= 8; - HF2 = 0; + unsigned const addr = hl(); + READ(cf, addr); + zf = cf >> 1; + WRITE(addr, zf | (cf & 0x80)); + cf <<= 8; + hf2 = 0; } + break; - case 0x2F: - sra_r(A); - break; - case 0x30: - swap_r(B); - break; - case 0x31: - swap_r(C); - break; - case 0x32: - swap_r(D); - break; - case 0x33: - swap_r(E); - break; - case 0x34: - swap_r(H); - break; - case 0x35: - swap_r(L); - break; - //swap (hl) (16 cycles): - //Swap upper and lower nibbles of 8-bit value stored at address in HL, reset flags, check zero flag: + + case 0x2F: sra_r(a); break; + + case 0x30: swap_r(b); break; + case 0x31: swap_r(c); break; + case 0x32: swap_r(d); break; + case 0x33: swap_r(e); break; + case 0x34: swap_r(h); break; + case 0x35: swap_r(l); break; + + // swap (hl) (16 cycles): + // Swap upper and lower nibbles of 8-bit value stored at address in HL, + // reset flags, check zero flag: case 0x36: { - const unsigned addr = HL(); - - READ(ZF, addr); - - WRITE(addr, (ZF << 4 | ZF >> 4) & 0xFF); - - CF = HF2 = 0; + unsigned const addr = hl(); + READ(zf, addr); + WRITE(addr, (zf << 4 | zf >> 4) & 0xFF); + cf = hf2 = 0; } + break; - case 0x37: - swap_r(A); - break; - case 0x38: - srl_r(B); - break; - case 0x39: - srl_r(C); - break; - case 0x3A: - srl_r(D); - break; - case 0x3B: - srl_r(E); - break; - case 0x3C: - srl_r(H); - break; - case 0x3D: - srl_r(L); - break; - //srl (hl) (16 cycles): - //Shift 8-bit value stored at address in HL right, store old bit0 in CF. Reset SF and HCF. Check ZF: + + case 0x37: swap_r(a); break; + + case 0x38: srl_r(b); break; + case 0x39: srl_r(c); break; + case 0x3A: srl_r(d); break; + case 0x3B: srl_r(e); break; + case 0x3C: srl_r(h); break; + case 0x3D: srl_r(l); break; + + // srl (hl) (16 cycles): + // Shift 8-bit value stored at address in HL right, + // store old bit0 in CF. Reset SF and HCF. Check ZF: case 0x3E: { - const unsigned addr = HL(); - - READ(CF, addr); - - ZF = CF >> 1; - - WRITE(addr, ZF); - - CF <<= 8; - HF2 = 0; + unsigned const addr = hl(); + READ(cf, addr); + zf = cf >> 1; + WRITE(addr, zf); + cf <<= 8; + hf2 = 0; } - break; - case 0x3F: - srl_r(A); - break; - case 0x40: - bit0_u8(B); - break; - case 0x41: - bit0_u8(C); - break; - case 0x42: - bit0_u8(D); - break; - case 0x43: - bit0_u8(E); - break; - case 0x44: - bit0_u8(H); - break; - case 0x45: - bit0_u8(L); - break; - case 0x46: - { - unsigned data; - READ(data, HL()); + break; - bit0_u8(data); - } - break; - case 0x47: - bit0_u8(A); - break; - case 0x48: - bit1_u8(B); - break; - case 0x49: - bit1_u8(C); - break; - case 0x4A: - bit1_u8(D); - break; - case 0x4B: - bit1_u8(E); - break; - case 0x4C: - bit1_u8(H); - break; - case 0x4D: - bit1_u8(L); - break; - case 0x4E: - { - unsigned data; + case 0x3F: srl_r(a); break; - READ(data, HL()); + case 0x40: bit0_u8(b); break; + case 0x41: bit0_u8(c); break; + case 0x42: bit0_u8(d); break; + case 0x43: bit0_u8(e); break; + case 0x44: bit0_u8(h); break; + case 0x45: bit0_u8(l); break; + case 0x46: { unsigned data; READ(data, hl()); bit0_u8(data); } break; + case 0x47: bit0_u8(a); break; - bit1_u8(data); - } - break; - case 0x4F: - bit1_u8(A); - break; - case 0x50: - bit2_u8(B); - break; - case 0x51: - bit2_u8(C); - break; - case 0x52: - bit2_u8(D); - break; - case 0x53: - bit2_u8(E); - break; - case 0x54: - bit2_u8(H); - break; - case 0x55: - bit2_u8(L); - break; - case 0x56: - { - unsigned data; + case 0x48: bit1_u8(b); break; + case 0x49: bit1_u8(c); break; + case 0x4A: bit1_u8(d); break; + case 0x4B: bit1_u8(e); break; + case 0x4C: bit1_u8(h); break; + case 0x4D: bit1_u8(l); break; + case 0x4E: { unsigned data; READ(data, hl()); bit1_u8(data); } break; + case 0x4F: bit1_u8(a); break; - READ(data, HL()); + case 0x50: bit2_u8(b); break; + case 0x51: bit2_u8(c); break; + case 0x52: bit2_u8(d); break; + case 0x53: bit2_u8(e); break; + case 0x54: bit2_u8(h); break; + case 0x55: bit2_u8(l); break; + case 0x56: { unsigned data; READ(data, hl()); bit2_u8(data); } break; + case 0x57: bit2_u8(a); break; - bit2_u8(data); - } - break; - case 0x57: - bit2_u8(A); - break; - case 0x58: - bit3_u8(B); - break; - case 0x59: - bit3_u8(C); - break; - case 0x5A: - bit3_u8(D); - break; - case 0x5B: - bit3_u8(E); - break; - case 0x5C: - bit3_u8(H); - break; - case 0x5D: - bit3_u8(L); - break; - case 0x5E: - { - unsigned data; + case 0x58: bit3_u8(b); break; + case 0x59: bit3_u8(c); break; + case 0x5A: bit3_u8(d); break; + case 0x5B: bit3_u8(e); break; + case 0x5C: bit3_u8(h); break; + case 0x5D: bit3_u8(l); break; + case 0x5E: { unsigned data; READ(data, hl()); bit3_u8(data); } break; + case 0x5F: bit3_u8(a); break; - READ(data, HL()); + case 0x60: bit4_u8(b); break; + case 0x61: bit4_u8(c); break; + case 0x62: bit4_u8(d); break; + case 0x63: bit4_u8(e); break; + case 0x64: bit4_u8(h); break; + case 0x65: bit4_u8(l); break; + case 0x66: { unsigned data; READ(data, hl()); bit4_u8(data); } break; + case 0x67: bit4_u8(a); break; - bit3_u8(data); - } - break; - case 0x5F: - bit3_u8(A); - break; - case 0x60: - bit4_u8(B); - break; - case 0x61: - bit4_u8(C); - break; - case 0x62: - bit4_u8(D); - break; - case 0x63: - bit4_u8(E); - break; - case 0x64: - bit4_u8(H); - break; - case 0x65: - bit4_u8(L); - break; - case 0x66: - { - unsigned data; + case 0x68: bit5_u8(b); break; + case 0x69: bit5_u8(c); break; + case 0x6A: bit5_u8(d); break; + case 0x6B: bit5_u8(e); break; + case 0x6C: bit5_u8(h); break; + case 0x6D: bit5_u8(l); break; + case 0x6E: { unsigned data; READ(data, hl()); bit5_u8(data); } break; + case 0x6F: bit5_u8(a); break; - READ(data, HL()); + case 0x70: bit6_u8(b); break; + case 0x71: bit6_u8(c); break; + case 0x72: bit6_u8(d); break; + case 0x73: bit6_u8(e); break; + case 0x74: bit6_u8(h); break; + case 0x75: bit6_u8(l); break; + case 0x76: { unsigned data; READ(data, hl()); bit6_u8(data); } break; + case 0x77: bit6_u8(a); break; - bit4_u8(data); - } - break; - case 0x67: - bit4_u8(A); - break; - case 0x68: - bit5_u8(B); - break; - case 0x69: - bit5_u8(C); - break; - case 0x6A: - bit5_u8(D); - break; - case 0x6B: - bit5_u8(E); - break; - case 0x6C: - bit5_u8(H); - break; - case 0x6D: - bit5_u8(L); - break; - case 0x6E: - { - unsigned data; + case 0x78: bit7_u8(b); break; + case 0x79: bit7_u8(c); break; + case 0x7A: bit7_u8(d); break; + case 0x7B: bit7_u8(e); break; + case 0x7C: bit7_u8(h); break; + case 0x7D: bit7_u8(l); break; + case 0x7E: { unsigned data; READ(data, hl()); bit7_u8(data); } break; + case 0x7F: bit7_u8(a); break; - READ(data, HL()); + case 0x80: res0_r(b); break; + case 0x81: res0_r(c); break; + case 0x82: res0_r(d); break; + case 0x83: res0_r(e); break; + case 0x84: res0_r(h); break; + case 0x85: res0_r(l); break; + case 0x86: resn_mem_hl(0); break; + case 0x87: res0_r(a); break; - bit5_u8(data); - } - break; - case 0x6F: - bit5_u8(A); - break; - case 0x70: - bit6_u8(B); - break; - case 0x71: - bit6_u8(C); - break; - case 0x72: - bit6_u8(D); - break; - case 0x73: - bit6_u8(E); - break; - case 0x74: - bit6_u8(H); - break; - case 0x75: - bit6_u8(L); - break; - case 0x76: - { - unsigned data; + case 0x88: res1_r(b); break; + case 0x89: res1_r(c); break; + case 0x8A: res1_r(d); break; + case 0x8B: res1_r(e); break; + case 0x8C: res1_r(h); break; + case 0x8D: res1_r(l); break; + case 0x8E: resn_mem_hl(1); break; + case 0x8F: res1_r(a); break; - READ(data, HL()); + case 0x90: res2_r(b); break; + case 0x91: res2_r(c); break; + case 0x92: res2_r(d); break; + case 0x93: res2_r(e); break; + case 0x94: res2_r(h); break; + case 0x95: res2_r(l); break; + case 0x96: resn_mem_hl(2); break; + case 0x97: res2_r(a); break; - bit6_u8(data); - } - break; - case 0x77: - bit6_u8(A); - break; - case 0x78: - bit7_u8(B); - break; - case 0x79: - bit7_u8(C); - break; - case 0x7A: - bit7_u8(D); - break; - case 0x7B: - bit7_u8(E); - break; - case 0x7C: - bit7_u8(H); - break; - case 0x7D: - bit7_u8(L); - break; - case 0x7E: - { - unsigned data; + case 0x98: res3_r(b); break; + case 0x99: res3_r(c); break; + case 0x9A: res3_r(d); break; + case 0x9B: res3_r(e); break; + case 0x9C: res3_r(h); break; + case 0x9D: res3_r(l); break; + case 0x9E: resn_mem_hl(3); break; + case 0x9F: res3_r(a); break; - READ(data, HL()); + case 0xA0: res4_r(b); break; + case 0xA1: res4_r(c); break; + case 0xA2: res4_r(d); break; + case 0xA3: res4_r(e); break; + case 0xA4: res4_r(h); break; + case 0xA5: res4_r(l); break; + case 0xA6: resn_mem_hl(4); break; + case 0xA7: res4_r(a); break; - bit7_u8(data); - } - break; - case 0x7F: - bit7_u8(A); - break; - case 0x80: - res0_r(B); - break; - case 0x81: - res0_r(C); - break; - case 0x82: - res0_r(D); - break; - case 0x83: - res0_r(E); - break; - case 0x84: - res0_r(H); - break; - case 0x85: - res0_r(L); - break; - case 0x86: - resn_mem_hl(0); - break; - case 0x87: - res0_r(A); - break; - case 0x88: - res1_r(B); - break; - case 0x89: - res1_r(C); - break; - case 0x8A: - res1_r(D); - break; - case 0x8B: - res1_r(E); - break; - case 0x8C: - res1_r(H); - break; - case 0x8D: - res1_r(L); - break; - case 0x8E: - resn_mem_hl(1); - break; - case 0x8F: - res1_r(A); - break; - case 0x90: - res2_r(B); - break; - case 0x91: - res2_r(C); - break; - case 0x92: - res2_r(D); - break; - case 0x93: - res2_r(E); - break; - case 0x94: - res2_r(H); - break; - case 0x95: - res2_r(L); - break; - case 0x96: - resn_mem_hl(2); - break; - case 0x97: - res2_r(A); - break; - case 0x98: - res3_r(B); - break; - case 0x99: - res3_r(C); - break; - case 0x9A: - res3_r(D); - break; - case 0x9B: - res3_r(E); - break; - case 0x9C: - res3_r(H); - break; - case 0x9D: - res3_r(L); - break; - case 0x9E: - resn_mem_hl(3); - break; - case 0x9F: - res3_r(A); - break; - case 0xA0: - res4_r(B); - break; - case 0xA1: - res4_r(C); - break; - case 0xA2: - res4_r(D); - break; - case 0xA3: - res4_r(E); - break; - case 0xA4: - res4_r(H); - break; - case 0xA5: - res4_r(L); - break; - case 0xA6: - resn_mem_hl(4); - break; - case 0xA7: - res4_r(A); - break; - case 0xA8: - res5_r(B); - break; - case 0xA9: - res5_r(C); - break; - case 0xAA: - res5_r(D); - break; - case 0xAB: - res5_r(E); - break; - case 0xAC: - res5_r(H); - break; - case 0xAD: - res5_r(L); - break; - case 0xAE: - resn_mem_hl(5); - break; - case 0xAF: - res5_r(A); - break; - case 0xB0: - res6_r(B); - break; - case 0xB1: - res6_r(C); - break; - case 0xB2: - res6_r(D); - break; - case 0xB3: - res6_r(E); - break; - case 0xB4: - res6_r(H); - break; - case 0xB5: - res6_r(L); - break; - case 0xB6: - resn_mem_hl(6); - break; - case 0xB7: - res6_r(A); - break; - case 0xB8: - res7_r(B); - break; - case 0xB9: - res7_r(C); - break; - case 0xBA: - res7_r(D); - break; - case 0xBB: - res7_r(E); - break; - case 0xBC: - res7_r(H); - break; - case 0xBD: - res7_r(L); - break; - case 0xBE: - resn_mem_hl(7); - break; - case 0xBF: - res7_r(A); - break; - case 0xC0: - set0_r(B); - break; - case 0xC1: - set0_r(C); - break; - case 0xC2: - set0_r(D); - break; - case 0xC3: - set0_r(E); - break; - case 0xC4: - set0_r(H); - break; - case 0xC5: - set0_r(L); - break; - case 0xC6: - setn_mem_hl(0); - break; - case 0xC7: - set0_r(A); - break; - case 0xC8: - set1_r(B); - break; - case 0xC9: - set1_r(C); - break; - case 0xCA: - set1_r(D); - break; - case 0xCB: - set1_r(E); - break; - case 0xCC: - set1_r(H); - break; - case 0xCD: - set1_r(L); - break; - case 0xCE: - setn_mem_hl(1); - break; - case 0xCF: - set1_r(A); - break; - case 0xD0: - set2_r(B); - break; - case 0xD1: - set2_r(C); - break; - case 0xD2: - set2_r(D); - break; - case 0xD3: - set2_r(E); - break; - case 0xD4: - set2_r(H); - break; - case 0xD5: - set2_r(L); - break; - case 0xD6: - setn_mem_hl(2); - break; - case 0xD7: - set2_r(A); - break; - case 0xD8: - set3_r(B); - break; - case 0xD9: - set3_r(C); - break; - case 0xDA: - set3_r(D); - break; - case 0xDB: - set3_r(E); - break; - case 0xDC: - set3_r(H); - break; - case 0xDD: - set3_r(L); - break; - case 0xDE: - setn_mem_hl(3); - break; - case 0xDF: - set3_r(A); - break; - case 0xE0: - set4_r(B); - break; - case 0xE1: - set4_r(C); - break; - case 0xE2: - set4_r(D); - break; - case 0xE3: - set4_r(E); - break; - case 0xE4: - set4_r(H); - break; - case 0xE5: - set4_r(L); - break; - case 0xE6: - setn_mem_hl(4); - break; - case 0xE7: - set4_r(A); - break; - case 0xE8: - set5_r(B); - break; - case 0xE9: - set5_r(C); - break; - case 0xEA: - set5_r(D); - break; - case 0xEB: - set5_r(E); - break; - case 0xEC: - set5_r(H); - break; - case 0xED: - set5_r(L); - break; - case 0xEE: - setn_mem_hl(5); - break; - case 0xEF: - set5_r(A); - break; - case 0xF0: - set6_r(B); - break; - case 0xF1: - set6_r(C); - break; - case 0xF2: - set6_r(D); - break; - case 0xF3: - set6_r(E); - break; - case 0xF4: - set6_r(H); - break; - case 0xF5: - set6_r(L); - break; - case 0xF6: - setn_mem_hl(6); - break; - case 0xF7: - set6_r(A); - break; - case 0xF8: - set7_r(B); - break; - case 0xF9: - set7_r(C); - break; - case 0xFA: - set7_r(D); - break; - case 0xFB: - set7_r(E); - break; - case 0xFC: - set7_r(H); - break; - case 0xFD: - set7_r(L); - break; - case 0xFE: - setn_mem_hl(7); - break; - case 0xFF: - set7_r(A); - break; -// default: break; + case 0xA8: res5_r(b); break; + case 0xA9: res5_r(c); break; + case 0xAA: res5_r(d); break; + case 0xAB: res5_r(e); break; + case 0xAC: res5_r(h); break; + case 0xAD: res5_r(l); break; + case 0xAE: resn_mem_hl(5); break; + case 0xAF: res5_r(a); break; + + case 0xB0: res6_r(b); break; + case 0xB1: res6_r(c); break; + case 0xB2: res6_r(d); break; + case 0xB3: res6_r(e); break; + case 0xB4: res6_r(h); break; + case 0xB5: res6_r(l); break; + case 0xB6: resn_mem_hl(6); break; + case 0xB7: res6_r(a); break; + + case 0xB8: res7_r(b); break; + case 0xB9: res7_r(c); break; + case 0xBA: res7_r(d); break; + case 0xBB: res7_r(e); break; + case 0xBC: res7_r(h); break; + case 0xBD: res7_r(l); break; + case 0xBE: resn_mem_hl(7); break; + case 0xBF: res7_r(a); break; + + case 0xC0: set0_r(b); break; + case 0xC1: set0_r(c); break; + case 0xC2: set0_r(d); break; + case 0xC3: set0_r(e); break; + case 0xC4: set0_r(h); break; + case 0xC5: set0_r(l); break; + case 0xC6: setn_mem_hl(0); break; + case 0xC7: set0_r(a); break; + + case 0xC8: set1_r(b); break; + case 0xC9: set1_r(c); break; + case 0xCA: set1_r(d); break; + case 0xCB: set1_r(e); break; + case 0xCC: set1_r(h); break; + case 0xCD: set1_r(l); break; + case 0xCE: setn_mem_hl(1); break; + case 0xCF: set1_r(a); break; + + case 0xD0: set2_r(b); break; + case 0xD1: set2_r(c); break; + case 0xD2: set2_r(d); break; + case 0xD3: set2_r(e); break; + case 0xD4: set2_r(h); break; + case 0xD5: set2_r(l); break; + case 0xD6: setn_mem_hl(2); break; + case 0xD7: set2_r(a); break; + + case 0xD8: set3_r(b); break; + case 0xD9: set3_r(c); break; + case 0xDA: set3_r(d); break; + case 0xDB: set3_r(e); break; + case 0xDC: set3_r(h); break; + case 0xDD: set3_r(l); break; + case 0xDE: setn_mem_hl(3); break; + case 0xDF: set3_r(a); break; + + case 0xE0: set4_r(b); break; + case 0xE1: set4_r(c); break; + case 0xE2: set4_r(d); break; + case 0xE3: set4_r(e); break; + case 0xE4: set4_r(h); break; + case 0xE5: set4_r(l); break; + case 0xE6: setn_mem_hl(4); break; + case 0xE7: set4_r(a); break; + + case 0xE8: set5_r(b); break; + case 0xE9: set5_r(c); break; + case 0xEA: set5_r(d); break; + case 0xEB: set5_r(e); break; + case 0xEC: set5_r(h); break; + case 0xED: set5_r(l); break; + case 0xEE: setn_mem_hl(5); break; + case 0xEF: set5_r(a); break; + + case 0xF0: set6_r(b); break; + case 0xF1: set6_r(c); break; + case 0xF2: set6_r(d); break; + case 0xF3: set6_r(e); break; + case 0xF4: set6_r(h); break; + case 0xF5: set6_r(l); break; + case 0xF6: setn_mem_hl(6); break; + case 0xF7: set6_r(a); break; + + case 0xF8: set7_r(b); break; + case 0xF9: set7_r(c); break; + case 0xFA: set7_r(d); break; + case 0xFB: set7_r(e); break; + case 0xFC: set7_r(h); break; + case 0xFD: set7_r(l); break; + case 0xFE: setn_mem_hl(7); break; + case 0xFF: set7_r(a); break; } + break; - //call z,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if ZF is set: + // call z,nn (24;12 cycles): + // Push address of next instruction onto stack and then jump to + // address stored in next two bytes in memory, if ZF is set: case 0xCC: - if (ZF & 0xFF) { - PC_MOD((PC + 2) & 0xFFFF); + if (zf & 0xFF) { + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } else { call_nn(); } + break; case 0xCD: call_nn(); break; + case 0xCE: { unsigned data; - PC_READ(data); - adc_a_u8(data); } + break; + case 0xCF: rst_n(0x08); break; - //ret nc (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if CF is unset: + // ret nc (20;8 cycles): + // Pop two bytes from the stack and jump to that address, if CF is unset: case 0xD0: cycleCounter += 4; - if (!(CF & 0x100)) { + if (!(cf & 0x100)) ret(); - } break; case 0xD1: - pop_rr(D, E); + pop_rr(d, e); break; - //jp nc,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if CF is unset: + // jp nc,nn (16;12 cycles): + // Jump to address stored in next two bytes in memory if CF is unset: case 0xD2: - if (CF & 0x100) { - PC_MOD((PC + 2) & 0xFFFF); + if (cf & 0x100) { + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } else { jp_nn(); } + break; case 0xD3: /*doesn't exist*/ - skip = true; - memory.di(); + skip_ = true; + mem_.di(); break; - //call nc,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if CF is unset: + // call nc,nn (24;12 cycles): + // Push address of next instruction onto stack and then jump to + // address stored in next two bytes in memory, if CF is unset: case 0xD4: - if (CF & 0x100) { - PC_MOD((PC + 2) & 0xFFFF); + if (cf & 0x100) { + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } else { call_nn(); } + break; case 0xD5: - push_rr(D, E); + push_rr(d, e); break; + case 0xD6: { unsigned data; - PC_READ(data); - sub_a_u8(data); } + break; + case 0xD7: rst_n(0x10); break; - //ret c (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if CF is set: + // ret c (20;8 cycles): + // Pop two bytes from the stack and jump to that address, if CF is set: case 0xD8: cycleCounter += 4; - if (CF & 0x100) { + if (cf & 0x100) ret(); - } break; - //reti (16 cycles): - //Pop two bytes from the stack and jump to that address, then enable interrupts: + // reti (16 cycles): + // Pop two bytes from the stack and jump to that address, then enable interrupts: case 0xD9: { - unsigned l, h; - - pop_rr(h, l); - - memory.ei(cycleCounter); - - PC_MOD(h << 8 | l); + unsigned sl, sh; + pop_rr(sh, sl); + mem_.ei(cycleCounter); + PC_MOD(sh << 8 | sl); } + break; - //jp c,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if CF is set: - case 0xDA: //PC=( ((PC+2)*(1-CarryFlag())) + (((memory.read(PC+1)<<8)+memory.read(PC))*CarryFlag()) ); Cycles(12); break; - if (CF & 0x100) { + // jp c,nn (16;12 cycles): + // Jump to address stored in next two bytes in memory if CF is set: + case 0xDA: + if (cf & 0x100) { jp_nn(); } else { - PC_MOD((PC + 2) & 0xFFFF); + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } + break; case 0xDB: /*doesn't exist*/ - skip = true; - memory.di(); + skip_ = true; + mem_.di(); break; - //call z,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if CF is set: + // call z,nn (24;12 cycles): + // Push address of next instruction onto stack and then jump to + // address stored in next two bytes in memory, if CF is set: case 0xDC: - if (CF & 0x100) { + if (cf & 0x100) { call_nn(); } else { - PC_MOD((PC + 2) & 0xFFFF); + PC_MOD((pc + 2) & 0xFFFF); cycleCounter += 4; } + break; case 0xDD: /*doesn't exist*/ - skip = true; - memory.di(); + skip_ = true; + mem_.di(); break; case 0xDE: { unsigned data; - PC_READ(data); - sbc_a_u8(data); } + break; + case 0xDF: rst_n(0x18); break; - //ld ($FF00+n),a (12 cycles): - //Put value in A into address (0xFF00 + next byte in memory): + // ld ($FF00+n),a (12 cycles): + // Put value in A into address (0xFF00 + next byte in memory): case 0xE0: { - unsigned tmp; - - PC_READ(tmp); - - FF_WRITE(0xFF00 | tmp, A); + unsigned imm; + PC_READ(imm); + FF_WRITE(imm, a); } + break; case 0xE1: - pop_rr(H, L); + pop_rr(h, l); break; - //ld ($FF00+C),a (8 ycles): - //Put A into address (0xFF00 + register C): + // ld ($FF00+C),a (8 ycles): + // Put A into address (0xFF00 + register C): case 0xE2: - FF_WRITE(0xFF00 | C, A); - break; - case 0xE3: /*doesn't exist*/ - skip = true; - memory.di(); + FF_WRITE(c, a); break; + case 0xE3: case 0xE4: /*doesn't exist*/ - skip = true; - memory.di(); + skip_ = true; + mem_.di(); break; + case 0xE5: - push_rr(H, L); + push_rr(h, l); break; + case 0xE6: { unsigned data; - PC_READ(data); - and_a_u8(data); } + break; + case 0xE7: rst_n(0x20); break; - //add sp,n (16 cycles): - //Add next (signed) byte in memory to SP, reset ZF and SF, check HCF and CF: + // add sp,n (16 cycles): + // Add next (signed) byte in memory to SP, reset ZF and SF, check HCF and CF: case 0xE8: - /*{ - int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter)); - HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200; - CF = SP + tmp; - SP = CF; - CF >>= 8; - ZF = 1; - cycleCounter += 12; - }*/ - sp_plus_n(SP); + sp_plus_n(sp); cycleCounter += 4; - break; - - //jp hl (4 cycles): - //Jump to address in hl: - case 0xE9: - PC = HL(); break; - //ld (nn),a (16 cycles): - //set memory at address given by the next 2 bytes to value in A: - //Incrementing PC before call, because of possible interrupt. + // jp hl (4 cycles): + // Jump to address in hl: + case 0xE9: + pc = hl(); + break; + + // ld (nn),a (16 cycles): + // set memory at address given by the next 2 bytes to value in A: + // Incrementing PC before call, because of possible interrupt. case 0xEA: { - unsigned l, h; - - PC_READ(l); - PC_READ(h); - - WRITE(h << 8 | l, A); + unsigned imml, immh; + PC_READ(imml); + PC_READ(immh); + WRITE(immh << 8 | imml, a); } + + break; + case 0xEB: + case 0xEC: + case 0xED: /*doesn't exist*/ + skip_ = true; + mem_.di(); break; - case 0xEB: /*doesn't exist*/ - skip = true; - memory.di(); - break; - case 0xEC: /*doesn't exist*/ - skip = true; - memory.di(); - break; - case 0xED: /*doesn't exist*/ - skip = true; - memory.di(); - break; case 0xEE: { unsigned data; - PC_READ(data); - xor_a_u8(data); } + break; + case 0xEF: rst_n(0x28); break; - //ld a,($FF00+n) (12 cycles): - //Put value at address (0xFF00 + next byte in memory) into A: + // ld a,($FF00+n) (12 cycles): + // Put value at address (0xFF00 + next byte in memory) into A: case 0xF0: { - unsigned tmp; - - PC_READ(tmp); - - FF_READ(A, 0xFF00 | tmp); + unsigned imm; + PC_READ(imm); + FF_READ(a, imm); } + break; - case 0xF1: /*pop_rr(A, F); Cycles(12); break;*/ + case 0xF1: { unsigned F; - - pop_rr(A, F); - - FROM_F(F); + pop_rr(a, F); + zf = zfFromF(F); + hf2 = hf2FromF(F); + cf = cfFromF(F); } + break; - //ld a,($FF00+C) (8 cycles): - //Put value at address (0xFF00 + register C) into A: + // ld a,($FF00+C) (8 cycles): + // Put value at address (0xFF00 + register C) into A: case 0xF2: - FF_READ(A, 0xFF00 | C); + FF_READ(a, c); break; - //di (4 cycles): + // di (4 cycles): case 0xF3: - memory.di(); + mem_.di(); break; case 0xF4: /*doesn't exist*/ - skip = true; - memory.di(); + skip_ = true; + mem_.di(); break; - case 0xF5: /*push_rr(A, F); Cycles(16); break;*/ - calcHF(HF1, HF2); + + case 0xF5: + hf2 = updateHf2FromHf1(hf1, hf2); { - unsigned F = F(); - - push_rr(A, F); + unsigned F = toF(hf2, cf, zf); + push_rr(a, F); } + break; case 0xF6: { unsigned data; - PC_READ(data); - or_a_u8(data); } + break; + case 0xF7: rst_n(0x30); break; - //ldhl sp,n (12 cycles): - //Put (sp+next (signed) byte in memory) into hl (unsets ZF and SF, may enable HF and CF): + // ldhl sp,n (12 cycles): + // Put (sp+next (signed) byte in memory) into hl (unsets ZF and SF, may enable HF and CF): case 0xF8: - /*{ - int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter)); - HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200; - CF = SP + tmp; - L = CF; - CF >>= 8; - H = CF; - ZF = 1; - cycleCounter += 8; - }*/ { unsigned sum; sp_plus_n(sum); - L = sum & 0xFF; - H = sum >> 8; + l = sum & 0xFF; + h = sum >> 8; } + break; - //ld sp,hl (8 cycles): - //Put value in HL into SP + // ld sp,hl (8 cycles): + // Put value in HL into SP case 0xF9: - SP = HL(); + sp = hl(); cycleCounter += 4; break; - //ld a,(nn) (16 cycles): - //set A to value in memory at address given by the 2 next bytes. + // ld a,(nn) (16 cycles): + // set A to value in memory at address given by the 2 next bytes. case 0xFA: { - unsigned l, h; + unsigned imml, immh; + PC_READ(imml); + PC_READ(immh); - PC_READ(l); - PC_READ(h); - - READ(A, h << 8 | l); + READ(a, immh << 8 | imml); } + break; - //ei (4 cycles): - //Enable Interrupts after next instruction: + // ei (4 cycles): + // Enable Interrupts after next instruction: case 0xFB: - memory.ei(cycleCounter); + mem_.ei(cycleCounter); break; - case 0xFC: /*doesn't exist*/ - skip = true; - memory.di(); - break; + case 0xFC: case 0xFD: /*doesn't exist*/ - skip = true; - memory.di(); + skip_ = true; + mem_.di(); break; case 0xFE: { unsigned data; - PC_READ(data); cp_a_u8(data); } + break; + case 0xFF: rst_n(0x38); break; -// default: break; } } - //PC_ = PC; - cycleCounter = memory.event(cycleCounter); + //pc_ = pc; + cycleCounter = mem_.event(cycleCounter); } - //A_ = A; + //a_ = a; cycleCounter_ = cycleCounter; } -void CPU::GetRegs(int *dest) -{ - dest[0] = PC; - dest[1] = SP; - dest[2] = A; - dest[3] = B; - dest[4] = C; - dest[5] = D; - dest[6] = E; - dest[7] = F(); - dest[8] = H; - dest[9] = L; +void CPU::getRegs(int *dest) { + hf2 = updateHf2FromHf1(hf1, hf2); + + dest[0] = pc; + dest[1] = sp; + dest[2] = a; + dest[3] = b; + dest[4] = c; + dest[5] = d; + dest[6] = e; + dest[7] = toF(hf2, cf, zf); + dest[8] = h; + dest[9] = l; } -void CPU::SetInterruptAddresses(int *addrs, int numAddrs) -{ +void CPU::setInterruptAddresses(int *addrs, int numAddrs) { interruptAddresses = addrs; numInterruptAddresses = numAddrs; } -int CPU::GetHitInterruptAddress() -{ +int CPU::getHitInterruptAddress() { return hitInterruptAddress; } SYNCFUNC(CPU) { - SSS(memory); + SSS(mem_); NSS(cycleCounter_); - NSS(PC); - NSS(SP); - NSS(HF1); - NSS(HF2); - NSS(ZF); - NSS(CF); - NSS(A); - NSS(B); - NSS(C); - NSS(D); - NSS(E); - NSS(H); - NSS(L); - NSS(skip); + NSS(pc); + NSS(sp); + NSS(hf1); + NSS(hf2); + NSS(zf); + NSS(cf); + NSS(a); + NSS(b); + NSS(c); + NSS(d); + NSS(e); + NSS(h); + NSS(l); + NSS(skip_); } } diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h index d7ffcd7b17..0e37bb7066 100644 --- a/libgambatte/src/cpu.h +++ b/libgambatte/src/cpu.h @@ -1,21 +1,21 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ +// +// Copyright (C) 2007 by sinamas +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License version 2 for more details. +// +// You should have received a copy of the GNU General Public License +// version 2 along with this program; if not, write to the +// Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +// + #ifndef CPU_H #define CPU_H @@ -25,18 +25,100 @@ namespace gambatte { class CPU { - Memory memory; +public: + CPU(); + long runFor(unsigned long cycles); + void setStatePtrs(SaveState &state); + void loadState(SaveState const &state); + void setLayers(unsigned mask) { mem_.setLayers(mask); } + void loadSavedata(const char *data) { mem_.loadSavedata(data); } + int saveSavedataLength() {return mem_.saveSavedataLength(); } + void saveSavedata(char *dest) { mem_.saveSavedata(dest); } + bool getMemoryArea(int which, unsigned char **data, int *length) { return mem_.getMemoryArea(which, data, length); } + + void setVideoBuffer(uint_least32_t *videoBuf, std::ptrdiff_t pitch) { + mem_.setVideoBuffer(videoBuf, pitch); + } + + void setInputGetter(unsigned (*getInput)()) { + mem_.setInputGetter(getInput); + } + + void setReadCallback(MemoryCallback callback) { + mem_.setReadCallback(callback); + } + + void setWriteCallback(MemoryCallback callback) { + mem_.setWriteCallback(callback); + } + + void setExecCallback(MemoryCallback callback) { + mem_.setExecCallback(callback); + } + + void setCDCallback(CDCallback cdc) { + mem_.setCDCallback(cdc); + } + + void setTraceCallback(void (*callback)(void *)) { + tracecallback = callback; + } + + void setScanlineCallback(void (*callback)(), int sl) { + mem_.setScanlineCallback(callback, sl); + } + + void setRTCCallback(std::uint32_t (*callback)()) { + mem_.setRTCCallback(callback); + } + + void setLinkCallback(void(*callback)()) { + mem_.setLinkCallback(callback); + } + + LoadRes load(char const *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) { + return mem_.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat); + } + + bool loaded() const { return mem_.loaded(); } + char const * romTitle() const { return mem_.romTitle(); } + void setSoundBuffer(uint_least32_t *buf) { mem_.setSoundBuffer(buf); } + std::size_t fillSoundBuffer() { return mem_.fillSoundBuffer(cycleCounter_); } + bool isCgb() const { return mem_.isCgb(); } + + void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) { + mem_.setDmgPaletteColor(palNum, colorNum, rgb32); + } + + void setCgbPalette(unsigned *lut) { + mem_.setCgbPalette(lut); + } + + unsigned char* cgbBiosBuffer() { return mem_.cgbBiosBuffer(); } + unsigned char* dmgBiosBuffer() { return mem_.dmgBiosBuffer(); } + bool gbIsCgb() { return mem_.gbIsCgb(); } + + unsigned char externalRead(unsigned short addr) {return mem_.peek(addr); } + + void externalWrite(unsigned short addr, unsigned char val) { + mem_.write_nocb(addr, val, cycleCounter_); + } + + int LinkStatus(int which) { return mem_.LinkStatus(which); } + + void getRegs(int *dest); + void setInterruptAddresses(int *addrs, int numAddrs); + int getHitInterruptAddress(); + +private: + Memory mem_; unsigned long cycleCounter_; - - unsigned short PC; - unsigned short SP; - - unsigned HF1, HF2, ZF, CF; - - unsigned char A, B, C, D, E, /*F,*/ H, L; - - bool skip; + unsigned short pc; + unsigned short sp; + unsigned hf1, hf2, zf, cf; + unsigned char a, b, c, d, e, /*f,*/ h, l; + bool skip_; int *interruptAddresses; int numInterruptAddresses; @@ -47,98 +129,6 @@ class CPU { void (*tracecallback)(void *); public: - - CPU(); -// void halt(); - -// unsigned interrupt(unsigned address, unsigned cycleCounter); - - long runFor(unsigned long cycles); - void setStatePtrs(SaveState &state); - void loadState(const SaveState &state); - void setLayers(unsigned mask) { memory.setLayers(mask); } - - void loadSavedata(const char *data) { memory.loadSavedata(data); } - int saveSavedataLength() {return memory.saveSavedataLength(); } - void saveSavedata(char *dest) { memory.saveSavedata(dest); } - - bool getMemoryArea(int which, unsigned char **data, int *length) { return memory.getMemoryArea(which, data, length); } - - void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) { - memory.setVideoBuffer(videoBuf, pitch); - } - - void setInputGetter(unsigned (*getInput)()) { - memory.setInputGetter(getInput); - } - - void setReadCallback(MemoryCallback callback) { - memory.setReadCallback(callback); - } - - void setWriteCallback(MemoryCallback callback) { - memory.setWriteCallback(callback); - } - - void setExecCallback(MemoryCallback callback) { - memory.setExecCallback(callback); - } - - void setCDCallback(CDCallback cdc) { - memory.setCDCallback(cdc); - } - - void setTraceCallback(void (*callback)(void *)) { - tracecallback = callback; - } - - void setScanlineCallback(void (*callback)(), int sl) { - memory.setScanlineCallback(callback, sl); - } - - void setRTCCallback(std::uint32_t (*callback)()) { - memory.setRTCCallback(callback); - } - - void setLinkCallback(void(*callback)()) { - memory.setLinkCallback(callback); - } - - LoadRes load(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) { - return memory.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat); - } - - bool loaded() const { return memory.loaded(); } - const char * romTitle() const { return memory.romTitle(); } - - void setSoundBuffer(uint_least32_t *const buf) { memory.setSoundBuffer(buf); } - unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); } - - bool isCgb() const { return memory.isCgb(); } - - void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) { - memory.setDmgPaletteColor(palNum, colorNum, rgb32); - } - - void setCgbPalette(unsigned *lut) { - memory.setCgbPalette(lut); - } - - unsigned char* cgbBiosBuffer() { return memory.cgbBiosBuffer(); } - unsigned char* dmgBiosBuffer() { return memory.dmgBiosBuffer(); } - bool gbIsCgb() { return memory.gbIsCgb(); } - - //unsigned char ExternalRead(unsigned short addr) { return memory.read(addr, cycleCounter_); } - unsigned char ExternalRead(unsigned short addr) { return memory.peek(addr); } - void ExternalWrite(unsigned short addr, unsigned char val) { memory.write_nocb(addr, val, cycleCounter_); } - - int LinkStatus(int which) { return memory.LinkStatus(which); } - - void GetRegs(int *dest); - - void SetInterruptAddresses(int *addrs, int numAddrs); - int GetHitInterruptAddress(); - templatevoid SyncState(NewState *ns); }; diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index e8580829c5..2e260620cc 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -200,14 +200,14 @@ bool GB::getMemoryArea(int which, unsigned char **data, int *length) { unsigned char GB::ExternalRead(unsigned short addr) { if (p_->cpu.loaded()) - return p_->cpu.ExternalRead(addr); + return p_->cpu.externalRead(addr); else return 0; } void GB::ExternalWrite(unsigned short addr, unsigned char val) { if (p_->cpu.loaded()) - p_->cpu.ExternalWrite(addr, val); + p_->cpu.externalWrite(addr, val); } @@ -235,17 +235,17 @@ int GB::LinkStatus(int which) { } void GB::GetRegs(int *dest) { - p_->cpu.GetRegs(dest); + p_->cpu.getRegs(dest); } void GB::SetInterruptAddresses(int *addrs, int numAddrs) { - p_->cpu.SetInterruptAddresses(addrs, numAddrs); + p_->cpu.setInterruptAddresses(addrs, numAddrs); } int GB::GetHitInterruptAddress() { - return p_->cpu.GetHitInterruptAddress(); + return p_->cpu.getHitInterruptAddress(); } SYNCFUNC(GB) diff --git a/libgambatte/src/initstate.cpp b/libgambatte/src/initstate.cpp index 362f6701a0..5b89a79044 100644 --- a/libgambatte/src/initstate.cpp +++ b/libgambatte/src/initstate.cpp @@ -1167,16 +1167,16 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM }; state.cpu.cycleCounter = 8; - state.cpu.PC = 0; - state.cpu.SP = 0; - state.cpu.A = 0; - state.cpu.B = 0; - state.cpu.C = 0; - state.cpu.D = 0; - state.cpu.E = 0; - state.cpu.F = 0; - state.cpu.H = 0; - state.cpu.L = 0; + state.cpu.pc = 0; + state.cpu.sp = 0; + state.cpu.a = 0; + state.cpu.b = 0; + state.cpu.c = 0; + state.cpu.d = 0; + state.cpu.e = 0; + state.cpu.f = 0; + state.cpu.h = 0; + state.cpu.l = 0; state.cpu.skip = false; state.mem.biosMode = true; state.mem.cgbSwitching = false; diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp index f244cf00d0..ad8d1d69f0 100644 --- a/libgambatte/src/memory.cpp +++ b/libgambatte/src/memory.cpp @@ -471,7 +471,7 @@ unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleC if (lastOamDmaUpdate != disabled_time) updateOamDma(cycleCounter); - switch (P & 0x7F) { + switch (P) { case 0x00: updateInput(); break; @@ -531,7 +531,7 @@ unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleC default: break; } - return ioamhram[P - 0xFE00]; + return ioamhram[P + 0x100]; } static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned addr, const bool cgb) { @@ -589,8 +589,9 @@ unsigned Memory::nontrivial_read(const unsigned P, const unsigned long cycleCoun if (P < 0xFE00) return cart.wramdata(P >> 12 & 1)[P & 0xFFF]; - if (P >= 0xFF00) - return nontrivial_ff_read(P, cycleCounter); + long const ffp = long(P) - 0xFF00; + if (ffp >= 0) + return nontrivial_ff_read(ffp, cycleCounter); if (!display.oamReadable(cycleCounter) || oamDmaPos < 0xA0) return 0xFF; @@ -794,7 +795,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned sound.generateSamples(cycleCounter, isDoubleSpeed()); if (!(data & 0x80)) { - for (unsigned i = 0xFF10; i < 0xFF26; ++i) + for (unsigned i = 0x10; i < 0x26; ++i) ff_write(i, 0, cycleCounter); sound.setEnabled(false); @@ -1016,7 +1017,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned return; } - ioamhram[P - 0xFE00] = data; + ioamhram[P + 0x100] = data; } void Memory::nontrivial_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { @@ -1045,13 +1046,14 @@ void Memory::nontrivial_write(const unsigned P, const unsigned data, const unsig } else cart.wramdata(P >> 12 & 1)[P & 0xFFF] = data; } else if (P - 0xFF80u >= 0x7Fu) { - if (P < 0xFF00) { + long const ffp = long(P) - 0xFF00; + if (ffp < 0) { if (display.oamWritable(cycleCounter) && oamDmaPos >= 0xA0 && (P < 0xFEA0 || isCgb())) { display.oamChange(cycleCounter); ioamhram[P - 0xFE00] = data; } } else - nontrivial_ff_write(P, data, cycleCounter); + nontrivial_ff_write(ffp, data, cycleCounter); } else ioamhram[P - 0xFE00] = data; } diff --git a/libgambatte/src/memory.h b/libgambatte/src/memory.h index 4c3b3a2f7b..2228caf60e 100644 --- a/libgambatte/src/memory.h +++ b/libgambatte/src/memory.h @@ -139,7 +139,7 @@ public: unsigned ff_read(const unsigned P, const unsigned long cycleCounter) { if (readCallback) readCallback(P, (cycleCounter - basetime) >> 1); - return P < 0xFF80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P - 0xFE00]; + return P < 0x80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P + 0x100]; } struct CDMapResult @@ -279,8 +279,8 @@ public: } void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (P - 0xFF80u < 0x7Fu) { - ioamhram[P - 0xFE00] = data; + if (P - 0x80u < 0x7Fu) { + ioamhram[P + 0x100] = data; } else nontrivial_ff_write(P, data, cycleCounter); if (writeCallback) diff --git a/libgambatte/src/savestate.h b/libgambatte/src/savestate.h index 13707b1e53..950244f1c0 100644 --- a/libgambatte/src/savestate.h +++ b/libgambatte/src/savestate.h @@ -43,17 +43,17 @@ struct SaveState { struct CPU { unsigned long cycleCounter; - unsigned short PC; - unsigned short SP; - unsigned char A; - unsigned char B; - unsigned char C; - unsigned char D; - unsigned char E; - unsigned char F; - unsigned char H; - unsigned char L; - bool skip; + unsigned short pc; + unsigned short sp; + unsigned char a; + unsigned char b; + unsigned char c; + unsigned char d; + unsigned char e; + unsigned char f; + unsigned char h; + unsigned char l; + unsigned char /*bool*/ skip; } cpu; struct Mem { diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll index d4cbc43034..3e789a1ab5 100644 Binary files a/output/dll/libgambatte.dll and b/output/dll/libgambatte.dll differ