diff --git a/src/agb/GBA-arm.cpp b/src/agb/GBA-arm.cpp deleted file mode 100644 index dfb583db..00000000 --- a/src/agb/GBA-arm.cpp +++ /dev/null @@ -1,2966 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include -#include -#include -#include - -#include "GBA.h" -#include "GBAcpu.h" -#include "GBAinline.h" -#include "../Globals.h" -#include "../EEprom.h" -#include "../Flash.h" -#include "../Sound.h" -#include "../Sram.h" -#include "../bios.h" -#include "../Cheats.h" -#include "../NLS.h" -#include "../elf.h" -#include "../Util.h" -#include "../Port.h" -#include "agbprint.h" -#ifdef PROFILING -#include "prof/prof.h" -#endif - -#ifdef _MSC_VER - // Disable "empty statement" warnings - #pragma warning(disable: 4390) - // Visual C's inline assembler treats "offset" as a reserved word, so we - // tell it otherwise. If you want to use it, write "OFFSET" in capitals. - #define offset offset_ -#endif - -/////////////////////////////////////////////////////////////////////////// - -static int clockTicks; - -static INSN_REGPARM void armUnknownInsn(u32 opcode) -{ -#ifdef GBA_LOGGING - if (systemVerbose & VERBOSE_UNDEFINED) { - log("Undefined ARM instruction %08x at %08x\n", opcode, - armNextPC-4); - } -#endif - CPUUndefinedException(); -} - -#ifdef BKPT_SUPPORT -static INSN_REGPARM void armBreakpoint(u32 opcode) -{ - extern void (*dbgSignal)(int,int); - reg[15].I -= 4; - armNextPC -= 4; - dbgSignal(5, (opcode & 0x0f) | ((opcode>>4) & 0xfff0)); - clockTicks = -1; -} -#endif - - -// Subroutine to count instructions (for debugging/optimizing) -//#define INSN_COUNTER // comment out if you don't want it -#ifdef INSN_COUNTER -static void count(u32 opcode, int cond_res) -{ - static int insncount = 0; // number of insns seen - static int executed = 0; // number of insns executed - static int mergewith[4096]; // map instructions to routines - static int count[4096]; // count of each 12-bit code - int index = ((opcode>>16)&0xFF0) | ((opcode>>4)&0x0F); - static FILE *outfile = NULL; - - if (!insncount) { - for (int i = 0; i < 4096; i++) { - for (int j = 0; j < i; j++) { - if (armInsnTable[i] == armInsnTable[j]) - break; - } - mergewith[i] = j; - } - outfile = fopen("VBA-armcount.txt", "w"); - } - if (cond_res) { - count[mergewith[index]]++; - executed++; - } - insncount++; - if (outfile && insncount%1000000 == 0) { - fprintf(outfile, "Total instructions: %d\n", insncount); - fprintf(outfile, "Instructions executed: %d\n", executed); - for (int i = 0; i < 4096; i++) { - if (count[i]) - fprintf(outfile, "arm%03X: %d\n", i, count[i]); - } - } -} -#endif - -// Common macros ////////////////////////////////////////////////////////// - -#ifdef BKPT_SUPPORT -#define CONSOLE_OUTPUT(a,b) do { \ - extern void (*dbgOutput)(char *, u32); \ - if ((opcode == 0xe0000000) && (reg[0].I == 0xC0DED00D)) { \ - dbgOutput((a), (b)); \ -} while (0) -#else -#define CONSOLE_OUTPUT(a,b) /* nothing */ -#endif - -#define NEG(i) ((i) >> 31) -#define POS(i) ((~(i)) >> 31) - -// The following macros are used for optimization; any not defined for a -// particular compiler/CPU combination default to the C core versions. -// -// ALU_INIT_C: Used at the beginning of ALU instructions (AND/EOR/...). -// (ALU_INIT_NC) Can consist of variable declarations, like the C core, -// or the start of a continued assembly block, like the -// x86-optimized version. The _C version is used when the -// carry flag from the shift operation is needed (logical -// operations that set condition codes, like ANDS); the -// _NC version is used when the carry result is ignored. -// VALUE_XXX: Retrieve the second operand's value for an ALU instruction. -// The _C and _NC versions are used the same way as ALU_INIT. -// OP_XXX: ALU operations. XXX is the instruction name. -// ALU_FINISH: Appended to all ALU instructions. Usually empty, but if -// ALU_INIT started a block ALU_FINISH can be used to end it -// (as with the asm(...) statement in the x86 core). -// SETCOND_NONE: Used in multiply instructions in place of SETCOND_MUL -// when the condition codes are not set. Usually empty. -// SETCOND_MUL: Used in multiply instructions to set the condition codes. -// ROR_IMM_MSR: Used to rotate the immediate operand for MSR. -// ROR_OFFSET: Used to rotate the `offset' parameter for LDR and STR -// instructions. -// RRX_OFFSET: Used to rotate (RRX) the `offset' parameter for LDR and -// STR instructions. - -#ifndef C_CORE - -#if 0 // definitions have changed -//#ifdef __POWERPC__ - #define OP_SUBS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define OP_RSBS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subfco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define OP_ADDS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("addco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define OP_ADCS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("mtspr xer, %4\n" \ - "addeo. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value), \ - "r" (C_FLAG << 29) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define OP_SBCS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("mtspr xer, %4\n" \ - "subfeo. %0, %3, %2\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value), \ - "r" (C_FLAG << 29) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define OP_RSCS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("mtspr xer, %4\n" \ - "subfeo. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value), \ - "r" (C_FLAG << 29) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define OP_CMP \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value) \ - ); \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define OP_CMN \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("addco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[base].I), \ - "r" (value) \ - ); \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - -#else // !__POWERPC__ - -// Macros to emit instructions in the format used by the particular compiler. -// We use GNU assembler syntax: "op src, dest" rather than "op dest, src" - -#ifdef __GNUC__ - #define ALU_HEADER asm("mov %%ecx, %%edi; " - #define ALU_TRAILER : "=D" (opcode) : "c" (opcode) : "eax", "ebx", "edx", "esi") - #define EMIT0(op) #op"; " - #define EMIT1(op,arg) #op" "arg"; " - #define EMIT2(op,src,dest) #op" "src", "dest"; " - #define CONST(val) "$"#val - #define VAR(var) "_"#var - #define VARL(var) "_"#var - #define REGREF1(index) "_reg("index")" - #define REGREF2(index,scale) "_reg(,"index","#scale")" - #define LABEL(n) #n": " - #define LABELREF(n,dir) #n#dir - #define al "%%al" - #define ah "%%ah" - #define eax "%%eax" - #define bl "%%bl" - #define bh "%%bh" - #define ebx "%%ebx" - #define cl "%%cl" - #define ch "%%ch" - #define ecx "%%ecx" - #define dl "%%dl" - #define dh "%%dh" - #define edx "%%edx" - #define esp "%%esp" - #define ebp "%%ebp" - #define esi "%%esi" - #define edi "%%edi" - #define movzx movzb -#else - #define ALU_HEADER __asm { __asm mov ecx, opcode - #define ALU_TRAILER } - #define EMIT0(op) __asm op - #define EMIT1(op,arg) __asm op arg - #define EMIT2(op,src,dest) __asm op dest, src - #define CONST(val) val - #define VAR(var) var - #define VARL(var) dword ptr var - #define REGREF1(index) reg[index] - #define REGREF2(index,scale) reg[index*scale] - #define LABEL(n) __asm l##n: - #define LABELREF(n,dir) l##n -#endif - -//X//#ifndef _MSC_VER -// ALU op register usage: -// EAX -> 2nd operand value, result (RSB/RSC) -// EBX -> C_OUT (carry flag from shift/rotate) -// ECX -> opcode (input), shift/rotate count -// EDX -> Rn (base) value, result (all except RSB/RSC) -// ESI -> Rd (destination) index * 4 - -// Helper macros for loading value / shift count -#define VALUE_LOAD_IMM \ - EMIT2(and, CONST(0x0F), eax) \ - EMIT2(mov, REGREF2(eax,4), eax) \ - EMIT2(shr, CONST(7), ecx) \ - EMIT2(and, CONST(0x1F), ecx) -#define VALUE_LOAD_REG \ - EMIT2(and, CONST(0x0F), eax) \ - EMIT2(mov, REGREF2(eax,4), eax) \ - EMIT2(movzx, ch, ecx) \ - EMIT2(and, CONST(0x0F), ecx) \ - EMIT2(mov, REGREF2(ecx,4), ecx) - -// Helper macros for setting flags -#define SETCOND_LOGICAL \ - EMIT1(sets, VAR(N_FLAG)) \ - EMIT1(setz, VAR(Z_FLAG)) \ - EMIT2(mov, bl, VAR(C_FLAG)) -#define SETCOND_ADD \ - EMIT1(sets, VAR(N_FLAG)) \ - EMIT1(setz, VAR(Z_FLAG)) \ - EMIT1(seto, VAR(V_FLAG)) \ - EMIT1(setc, VAR(C_FLAG)) -#define SETCOND_SUB \ - EMIT1(sets, VAR(N_FLAG)) \ - EMIT1(setz, VAR(Z_FLAG)) \ - EMIT1(seto, VAR(V_FLAG)) \ - EMIT1(setnc, VAR(C_FLAG)) - -// ALU initialization -#define ALU_INIT(LOAD_C_FLAG) \ - ALU_HEADER \ - LOAD_C_FLAG \ - EMIT2(mov, ecx, edx) \ - EMIT2(shr, CONST(14), edx) \ - EMIT2(mov, ecx, eax) \ - EMIT2(mov, ecx, esi) \ - EMIT2(shr, CONST(10), esi) \ - EMIT2(and, CONST(0x3C), edx) \ - EMIT2(mov, REGREF1(edx), edx) \ - EMIT2(and, CONST(0x3C), esi) - -#define LOAD_C_FLAG_YES EMIT2(mov, VAR(C_FLAG), bl) -#define LOAD_C_FLAG_NO /*nothing*/ -#define ALU_INIT_C ALU_INIT(LOAD_C_FLAG_YES) -#define ALU_INIT_NC ALU_INIT(LOAD_C_FLAG_NO) - -// Macros to load the value operand for an ALU op; these all set N/Z -// according to the value - -// OP Rd,Rb,Rm LSL # -#define VALUE_LSL_IMM_C \ - VALUE_LOAD_IMM \ - EMIT1(jnz, LABELREF(1,f)) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(shl, cl, eax) \ - EMIT1(setc, bl) \ - LABEL(0) -#define VALUE_LSL_IMM_NC \ - VALUE_LOAD_IMM \ - EMIT2(shl, cl, eax) - -// OP Rd,Rb,Rm LSL Rs -#define VALUE_LSL_REG_C \ - VALUE_LOAD_REG \ - EMIT2(test, cl, cl) \ - EMIT1(jz, LABELREF(0,f)) \ - EMIT2(cmp, CONST(0x20), cl) \ - EMIT1(je, LABELREF(1,f)) \ - EMIT1(ja, LABELREF(2,f)) \ - EMIT2(shl, cl, eax) \ - EMIT1(setc, bl) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(test, CONST(1), al) \ - EMIT1(setnz, bl) \ - EMIT2(xor, eax, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(2) \ - EMIT2(xor, ebx, ebx) \ - EMIT2(xor, eax, eax) \ - LABEL(0) -#define VALUE_LSL_REG_NC \ - VALUE_LOAD_REG \ - EMIT2(cmp, CONST(0x20), cl) \ - EMIT1(jae, LABELREF(1,f)) \ - EMIT2(shl, cl, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(xor, eax, eax) \ - LABEL(0) - -// OP Rd,Rb,Rm LSR # -#define VALUE_LSR_IMM_C \ - VALUE_LOAD_IMM \ - EMIT1(jz, LABELREF(1,f)) \ - EMIT2(shr, cl, eax) \ - EMIT1(setc, bl) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(test, eax, eax) \ - EMIT1(sets, bl) \ - EMIT2(xor, eax, eax) \ - LABEL(0) -#define VALUE_LSR_IMM_NC \ - VALUE_LOAD_IMM \ - EMIT1(jz, LABELREF(1,f)) \ - EMIT2(shr, cl, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(xor, eax, eax) \ - LABEL(0) - -// OP Rd,Rb,Rm LSR Rs -#define VALUE_LSR_REG_C \ - VALUE_LOAD_REG \ - EMIT2(test, cl, cl) \ - EMIT1(jz, LABELREF(0,f)) \ - EMIT2(cmp, CONST(0x20), cl) \ - EMIT1(je, LABELREF(1,f)) \ - EMIT1(ja, LABELREF(2,f)) \ - EMIT2(shr, cl, eax) \ - EMIT1(setc, bl) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(test, eax, eax) \ - EMIT1(sets, bl) \ - EMIT2(xor, eax, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(2) \ - EMIT2(xor, ebx, ebx) \ - EMIT2(xor, eax, eax) \ - LABEL(0) -#define VALUE_LSR_REG_NC \ - VALUE_LOAD_REG \ - EMIT2(cmp, CONST(0x20), cl) \ - EMIT1(jae, LABELREF(1,f)) \ - EMIT2(shr, cl, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(xor, eax, eax) \ - LABEL(0) - -// OP Rd,Rb,Rm ASR # -#define VALUE_ASR_IMM_C \ - VALUE_LOAD_IMM \ - EMIT1(jz, LABELREF(1,f)) \ - EMIT2(sar, cl, eax) \ - EMIT1(setc, bl) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ - EMIT1(sets, bl) \ - LABEL(0) -#define VALUE_ASR_IMM_NC \ - VALUE_LOAD_IMM \ - EMIT1(jz, LABELREF(1,f)) \ - EMIT2(sar, cl, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ - LABEL(0) - -// OP Rd,Rb,Rm ASR Rs -#define VALUE_ASR_REG_C \ - VALUE_LOAD_REG \ - EMIT2(test, cl, cl) \ - EMIT1(jz, LABELREF(0,f)) \ - EMIT2(cmp, CONST(0x20), cl) \ - EMIT1(jae, LABELREF(1,f)) \ - EMIT2(sar, cl, eax) \ - EMIT1(setc, bl) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ - EMIT1(sets, bl) \ - LABEL(0) -#define VALUE_ASR_REG_NC \ - VALUE_LOAD_REG \ - EMIT2(cmp, CONST(0x20), cl) \ - EMIT1(jae, LABELREF(1,f)) \ - EMIT2(sar, cl, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ - LABEL(0) - -// OP Rd,Rb,Rm ROR # -#define VALUE_ROR_IMM_C \ - VALUE_LOAD_IMM \ - EMIT1(jz, LABELREF(1,f)) \ - EMIT2(ror, cl, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(bt, CONST(0), ebx) \ - EMIT2(rcr, CONST(1), eax) \ - LABEL(0) \ - EMIT1(setc, bl) -#define VALUE_ROR_IMM_NC \ - VALUE_LOAD_IMM \ - EMIT1(jz, LABELREF(1,f)) \ - EMIT2(ror, cl, eax) \ - EMIT1(jmp, LABELREF(0,f)) \ - LABEL(1) \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ - EMIT2(rcr, CONST(1), eax) \ - LABEL(0) - -// OP Rd,Rb,Rm ROR Rs -#define VALUE_ROR_REG_C \ - VALUE_LOAD_REG \ - EMIT2(bt, CONST(0), ebx) \ - EMIT2(ror, cl, eax) \ - EMIT1(setc, bl) -#define VALUE_ROR_REG_NC \ - VALUE_LOAD_REG \ - EMIT2(ror, cl, eax) - -// OP Rd,Rb,# ROR # -#define VALUE_IMM_C \ - EMIT2(movzx, ch, ecx) \ - EMIT2(add, ecx, ecx) \ - EMIT2(movzx, al, eax) \ - EMIT2(bt, CONST(0), ebx) \ - EMIT2(ror, cl, eax) \ - EMIT1(setc, bl) -#define VALUE_IMM_NC \ - EMIT2(movzx, ch, ecx) \ - EMIT2(add, ecx, ecx) \ - EMIT2(movzx, al, eax) \ - EMIT2(ror, cl, eax) - -// Macros to perform ALU ops - -// Set condition codes iff the destination register is not R15 (PC) -#define CHECK_PC(OP, SETCOND) \ - EMIT2(cmp, CONST(0x3C), esi) \ - EMIT1(je, LABELREF(8,f)) \ - OP SETCOND \ - EMIT1(jmp, LABELREF(9,f)) \ - LABEL(8) \ - OP \ - LABEL(9) - -#define OP_AND \ - EMIT2(and, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_ANDS CHECK_PC(OP_AND, SETCOND_LOGICAL) -#define OP_EOR \ - EMIT2(xor, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_EORS CHECK_PC(OP_EOR, SETCOND_LOGICAL) -#define OP_SUB \ - EMIT2(sub, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_SUBS CHECK_PC(OP_SUB, SETCOND_SUB) -#define OP_RSB \ - EMIT2(sub, edx, eax) \ - EMIT2(mov, eax, REGREF1(esi)) -#define OP_RSBS CHECK_PC(OP_RSB, SETCOND_SUB) -#define OP_ADD \ - EMIT2(add, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_ADDS CHECK_PC(OP_ADD, SETCOND_ADD) -#define OP_ADC \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ - EMIT2(adc, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_ADCS CHECK_PC(OP_ADC, SETCOND_ADD) -#define OP_SBC \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ - EMIT0(cmc) \ - EMIT2(sbb, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_SBCS CHECK_PC(OP_SBC, SETCOND_SUB) -#define OP_RSC \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ - EMIT0(cmc) \ - EMIT2(sbb, edx, eax) \ - EMIT2(mov, eax, REGREF1(esi)) -#define OP_RSCS CHECK_PC(OP_RSC, SETCOND_SUB) -#define OP_TST \ - EMIT2(and, eax, edx) \ - SETCOND_LOGICAL -#define OP_TEQ \ - EMIT2(xor, eax, edx) \ - SETCOND_LOGICAL -#define OP_CMP \ - EMIT2(sub, eax, edx) \ - SETCOND_SUB -#define OP_CMN \ - EMIT2(add, eax, edx) \ - SETCOND_ADD -#define OP_ORR \ - EMIT2(or, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_ORRS CHECK_PC(OP_ORR, SETCOND_LOGICAL) -#define OP_MOV \ - EMIT2(mov, eax, REGREF1(esi)) -#define OP_MOVS CHECK_PC(EMIT2(test,eax,eax) EMIT2(mov,eax,REGREF1(esi)), SETCOND_LOGICAL) -#define OP_BIC \ - EMIT1(not, eax) \ - EMIT2(and, eax, edx) \ - EMIT2(mov, edx, REGREF1(esi)) -#define OP_BICS CHECK_PC(OP_BIC, SETCOND_LOGICAL) -#define OP_MVN \ - EMIT1(not, eax) \ - EMIT2(mov, eax, REGREF1(esi)) -#define OP_MVNS CHECK_PC(OP_MVN, SETCOND_LOGICAL) - -// ALU cleanup macro -#define ALU_FINISH ALU_TRAILER - -// End of ALU macros -//X//#endif //_MSC_VER - -#ifdef __GNUC__ - -#define ROR_IMM_MSR \ - asm ("ror %%cl, %%eax;" \ - : "=a" (value) \ - : "a" (opcode & 0xFF), "c" (shift)); - -#define ROR_OFFSET \ - asm("ror %%cl, %0" \ - : "=r" (offset) \ - : "0" (offset), "c" (shift)); - -#define RRX_OFFSET \ - asm("btl $0, _C_FLAG;" \ - "rcr $1, %0" \ - : "=r" (offset) \ - : "0" (offset)); - -#else // !__GNUC__, i.e. Visual C++ - -#define ROR_IMM_MSR \ - __asm { \ - __asm mov ecx, shift \ - __asm ror value, cl \ - } - - -#define ROR_OFFSET \ - __asm { \ - __asm mov ecx, shift \ - __asm ror offset, cl \ - } - -#define RRX_OFFSET \ - __asm { \ - __asm bt dword ptr C_FLAG, 0 \ - __asm rcr offset, 1 \ - } - -#endif // !__GNUC__ - -#endif // !__POWERPC__ -#endif // !C_CORE - -// C core - -#define C_SETCOND_LOGICAL \ - N_FLAG = ((s32)res < 0) ? true : false; \ - Z_FLAG = (res == 0) ? true : false; \ - C_FLAG = C_OUT; -#define C_SETCOND_ADD \ - N_FLAG = ((s32)res < 0) ? true : false; \ - Z_FLAG = (res == 0) ? true : false; \ - V_FLAG = ((NEG(lhs) & NEG(rhs) & POS(res)) | \ - (POS(lhs) & POS(rhs) & NEG(res))) ? true : false;\ - C_FLAG = ((NEG(lhs) & NEG(rhs)) | \ - (NEG(lhs) & POS(res)) | \ - (NEG(rhs) & POS(res))) ? true : false; -#define C_SETCOND_SUB \ - N_FLAG = ((s32)res < 0) ? true : false; \ - Z_FLAG = (res == 0) ? true : false; \ - V_FLAG = ((NEG(lhs) & POS(rhs) & POS(res)) | \ - (POS(lhs) & NEG(rhs) & NEG(res))) ? true : false;\ - C_FLAG = ((NEG(lhs) & POS(rhs)) | \ - (NEG(lhs) & POS(res)) | \ - (POS(rhs) & POS(res))) ? true : false; - -#ifndef ALU_INIT_C - #define ALU_INIT_C \ - int dest = (opcode>>12) & 15; \ - bool C_OUT = C_FLAG; \ - u32 value; -#endif -// OP Rd,Rb,Rm LSL # -#ifndef VALUE_LSL_IMM_C - #define VALUE_LSL_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (LIKELY(!shift)) { /* LSL #0 most common? */ \ - value = reg[opcode & 0x0F].I; \ - } else { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (32 - shift)) & 1 ? true : false; \ - value = v << shift; \ - } -#endif -// OP Rd,Rb,Rm LSL Rs -#ifndef VALUE_LSL_REG_C - #define VALUE_LSL_REG_C \ - unsigned int shift = reg[(opcode >> 8)&15].B.B0; \ - if (LIKELY(shift)) { \ - if (shift == 32) { \ - value = 0; \ - C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\ - } else if (LIKELY(shift < 32)) { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (32 - shift)) & 1 ? true : false;\ - value = v << shift; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } else { \ - value = reg[opcode & 0x0F].I; \ - } -#endif -// OP Rd,Rb,Rm LSR # -#ifndef VALUE_LSR_IMM_C - #define VALUE_LSR_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (LIKELY(shift)) { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = v >> shift; \ - } else { \ - value = 0; \ - C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\ - } -#endif -// OP Rd,Rb,Rm LSR Rs -#ifndef VALUE_LSR_REG_C - #define VALUE_LSR_REG_C \ - unsigned int shift = reg[(opcode >> 8)&15].B.B0; \ - if (LIKELY(shift)) { \ - if (shift == 32) { \ - value = 0; \ - C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\ - } else if (LIKELY(shift < 32)) { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false;\ - value = v >> shift; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } else { \ - value = reg[opcode & 0x0F].I; \ - } -#endif -// OP Rd,Rb,Rm ASR # -#ifndef VALUE_ASR_IMM_C - #define VALUE_ASR_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (LIKELY(shift)) { \ - /* VC++ BUG: u32 v; (s32)v>>n is optimized to shr! */ \ - s32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\ - value = v >> (int)shift; \ - } else { \ - if (reg[opcode & 0x0F].I & 0x80000000) { \ - value = 0xFFFFFFFF; \ - C_OUT = true; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } -#endif -// OP Rd,Rb,Rm ASR Rs -#ifndef VALUE_ASR_REG_C - #define VALUE_ASR_REG_C \ - unsigned int shift = reg[(opcode >> 8)&15].B.B0; \ - if (LIKELY(shift < 32)) { \ - if (LIKELY(shift)) { \ - s32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\ - value = v >> (int)shift; \ - } else { \ - value = reg[opcode & 0x0F].I; \ - } \ - } else { \ - if (reg[opcode & 0x0F].I & 0x80000000) { \ - value = 0xFFFFFFFF; \ - C_OUT = true; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } -#endif -// OP Rd,Rb,Rm ROR # -#ifndef VALUE_ROR_IMM_C - #define VALUE_ROR_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (LIKELY(shift)) { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = ((v << (32 - shift)) | \ - (v >> shift)); \ - } else { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v & 1) ? true : false; \ - value = ((v >> 1) | \ - (C_FLAG << 31)); \ - } -#endif -// OP Rd,Rb,Rm ROR Rs -#ifndef VALUE_ROR_REG_C - #define VALUE_ROR_REG_C \ - unsigned int shift = reg[(opcode >> 8)&15].B.B0; \ - if (LIKELY(shift & 0x1F)) { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = ((v << (32 - shift)) | \ - (v >> shift)); \ - } else { \ - value = reg[opcode & 0x0F].I; \ - if (shift) \ - C_OUT = (value & 0x80000000 ? true : false);\ - } -#endif -// OP Rd,Rb,# ROR # -#ifndef VALUE_IMM_C - #define VALUE_IMM_C \ - int shift = (opcode & 0xF00) >> 7; \ - if (UNLIKELY(shift)) { \ - u32 v = opcode & 0xFF; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = ((v << (32 - shift)) | \ - (v >> shift)); \ - } else { \ - value = opcode & 0xFF; \ - } -#endif - -// Make the non-carry versions default to the carry versions -// (this is fine for C--the compiler will optimize the dead code out) -#ifndef ALU_INIT_NC - #define ALU_INIT_NC ALU_INIT_C -#endif -#ifndef VALUE_LSL_IMM_NC - #define VALUE_LSL_IMM_NC VALUE_LSL_IMM_C -#endif -#ifndef VALUE_LSL_REG_NC - #define VALUE_LSL_REG_NC VALUE_LSL_REG_C -#endif -#ifndef VALUE_LSR_IMM_NC - #define VALUE_LSR_IMM_NC VALUE_LSR_IMM_C -#endif -#ifndef VALUE_LSR_REG_NC - #define VALUE_LSR_REG_NC VALUE_LSR_REG_C -#endif -#ifndef VALUE_ASR_IMM_NC - #define VALUE_ASR_IMM_NC VALUE_ASR_IMM_C -#endif -#ifndef VALUE_ASR_REG_NC - #define VALUE_ASR_REG_NC VALUE_ASR_REG_C -#endif -#ifndef VALUE_ROR_IMM_NC - #define VALUE_ROR_IMM_NC VALUE_ROR_IMM_C -#endif -#ifndef VALUE_ROR_REG_NC - #define VALUE_ROR_REG_NC VALUE_ROR_REG_C -#endif -#ifndef VALUE_IMM_NC - #define VALUE_IMM_NC VALUE_IMM_C -#endif - -#define C_CHECK_PC(SETCOND) if (LIKELY(dest != 15)) { SETCOND } -#ifndef OP_AND - #define OP_AND \ - u32 res = reg[(opcode>>16)&15].I & value; \ - reg[dest].I = res; -#endif -#ifndef OP_ANDS - #define OP_ANDS OP_AND C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_EOR - #define OP_EOR \ - u32 res = reg[(opcode>>16)&15].I ^ value; \ - reg[dest].I = res; -#endif -#ifndef OP_EORS - #define OP_EORS OP_EOR C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_SUB - #define OP_SUB \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs - rhs; \ - reg[dest].I = res; -#endif -#ifndef OP_SUBS - #define OP_SUBS OP_SUB C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_RSB - #define OP_RSB \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = rhs - lhs; \ - reg[dest].I = res; -#endif -#ifndef OP_RSBS - #define OP_RSBS OP_RSB C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_ADD - #define OP_ADD \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs + rhs; \ - reg[dest].I = res; -#endif -#ifndef OP_ADDS - #define OP_ADDS OP_ADD C_CHECK_PC(C_SETCOND_ADD) -#endif -#ifndef OP_ADC - #define OP_ADC \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs + rhs + (u32)C_FLAG; \ - reg[dest].I = res; -#endif -#ifndef OP_ADCS - #define OP_ADCS OP_ADC C_CHECK_PC(C_SETCOND_ADD) -#endif -#ifndef OP_SBC - #define OP_SBC \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs - rhs - !((u32)C_FLAG); \ - reg[dest].I = res; -#endif -#ifndef OP_SBCS - #define OP_SBCS OP_SBC C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_RSC - #define OP_RSC \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = rhs - lhs - !((u32)C_FLAG); \ - reg[dest].I = res; -#endif -#ifndef OP_RSCS - #define OP_RSCS OP_RSC C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_TST - #define OP_TST \ - u32 res = reg[(opcode >> 16) & 0x0F].I & value; \ - C_SETCOND_LOGICAL; -#endif -#ifndef OP_TEQ - #define OP_TEQ \ - u32 res = reg[(opcode >> 16) & 0x0F].I ^ value; \ - C_SETCOND_LOGICAL; -#endif -#ifndef OP_CMP - #define OP_CMP \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs - rhs; \ - C_SETCOND_SUB; -#endif -#ifndef OP_CMN - #define OP_CMN \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs + rhs; \ - C_SETCOND_ADD; -#endif -#ifndef OP_ORR - #define OP_ORR \ - u32 res = reg[(opcode >> 16) & 0x0F].I | value; \ - reg[dest].I = res; -#endif -#ifndef OP_ORRS - #define OP_ORRS OP_ORR C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_MOV - #define OP_MOV \ - u32 res = value; \ - reg[dest].I = res; -#endif -#ifndef OP_MOVS - #define OP_MOVS OP_MOV C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_BIC - #define OP_BIC \ - u32 res = reg[(opcode >> 16) & 0x0F].I & (~value); \ - reg[dest].I = res; -#endif -#ifndef OP_BICS - #define OP_BICS OP_BIC C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_MVN - #define OP_MVN \ - u32 res = ~value; \ - reg[dest].I = res; -#endif -#ifndef OP_MVNS - #define OP_MVNS OP_MVN C_CHECK_PC(C_SETCOND_LOGICAL) -#endif - -#ifndef SETCOND_NONE - #define SETCOND_NONE /*nothing*/ -#endif -#ifndef SETCOND_MUL - #define SETCOND_MUL \ - N_FLAG = ((s32)reg[dest].I < 0) ? true : false; \ - Z_FLAG = reg[dest].I ? false : true; -#endif -#ifndef SETCOND_MULL - #define SETCOND_MULL \ - N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\ - Z_FLAG = reg[dest].I || reg[acc].I ? false : true; -#endif - -#ifndef ALU_FINISH - #define ALU_FINISH /*nothing*/ -#endif - -#ifndef ROR_IMM_MSR - #define ROR_IMM_MSR \ - u32 v = opcode & 0xff; \ - value = ((v << (32 - shift)) | (v >> shift)); -#endif -#ifndef ROR_OFFSET - #define ROR_OFFSET \ - offset = ((offset << (32 - shift)) | (offset >> shift)); -#endif -#ifndef RRX_OFFSET - #define RRX_OFFSET \ - offset = ((offset >> 1) | ((int)C_FLAG << 31)); -#endif - -// ALU ops (except multiply) ////////////////////////////////////////////// - -// ALU_INIT: init code (ALU_INIT_C or ALU_INIT_NC) -// GETVALUE: load value and shift/rotate (VALUE_XXX) -// OP: ALU operation (OP_XXX) -// MODECHANGE: MODECHANGE_NO or MODECHANGE_YES -// ISREGSHIFT: 1 for insns of the form ...,Rn LSL/etc Rs; 0 otherwise -// ALU_INIT, GETVALUE, OP, and ALU_FINISH are concatenated in order. -#define ALU_INSN(ALU_INIT, GETVALUE, OP, MODECHANGE, ISREGSHIFT) \ - ALU_INIT GETVALUE OP ALU_FINISH; \ - if (LIKELY((opcode & 0x0000F000) != 0x0000F000)) { \ - clockTicks = 1 + ISREGSHIFT \ - + codeTicksAccessSeq32(armNextPC); \ - } else { \ - MODECHANGE; \ - if (armState) { \ - reg[15].I &= 0xFFFFFFFC; \ - armNextPC = reg[15].I; \ - reg[15].I += 4; \ - ARM_PREFETCH; \ - } else { \ - reg[15].I &= 0xFFFFFFFE; \ - armNextPC = reg[15].I; \ - reg[15].I += 2; \ - THUMB_PREFETCH; \ - } \ - clockTicks = 3 + ISREGSHIFT \ - + codeTicksAccess32(armNextPC) \ - + codeTicksAccessSeq32(armNextPC) \ - + codeTicksAccessSeq32(armNextPC); \ - } - -#define MODECHANGE_NO /*nothing*/ -#define MODECHANGE_YES CPUSwitchMode(reg[17].I & 0x1f, false); - -#define DEFINE_ALU_INSN_C(CODE1, CODE2, OP, MODECHANGE) \ - static INSN_REGPARM void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); } -#define DEFINE_ALU_INSN_NC(CODE1, CODE2, OP, MODECHANGE) \ - static INSN_REGPARM void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - static INSN_REGPARM void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - static INSN_REGPARM void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); } - -// AND -DEFINE_ALU_INSN_NC(00, 20, AND, NO) -// ANDS -DEFINE_ALU_INSN_C (01, 21, ANDS, YES) - -// EOR -DEFINE_ALU_INSN_NC(02, 22, EOR, NO) -// EORS -DEFINE_ALU_INSN_C (03, 23, EORS, YES) - -// SUB -DEFINE_ALU_INSN_NC(04, 24, SUB, NO) -// SUBS -DEFINE_ALU_INSN_NC(05, 25, SUBS, YES) - -// RSB -DEFINE_ALU_INSN_NC(06, 26, RSB, NO) -// RSBS -DEFINE_ALU_INSN_NC(07, 27, RSBS, YES) - -// ADD -DEFINE_ALU_INSN_NC(08, 28, ADD, NO) -// ADDS -DEFINE_ALU_INSN_NC(09, 29, ADDS, YES) - -// ADC -DEFINE_ALU_INSN_NC(0A, 2A, ADC, NO) -// ADCS -DEFINE_ALU_INSN_NC(0B, 2B, ADCS, YES) - -// SBC -DEFINE_ALU_INSN_NC(0C, 2C, SBC, NO) -// SBCS -DEFINE_ALU_INSN_NC(0D, 2D, SBCS, YES) - -// RSC -DEFINE_ALU_INSN_NC(0E, 2E, RSC, NO) -// RSCS -DEFINE_ALU_INSN_NC(0F, 2F, RSCS, YES) - -// TST -DEFINE_ALU_INSN_C (11, 31, TST, NO) - -// TEQ -DEFINE_ALU_INSN_C (13, 33, TEQ, NO) - -// CMP -DEFINE_ALU_INSN_NC(15, 35, CMP, NO) - -// CMN -DEFINE_ALU_INSN_NC(17, 37, CMN, NO) - -// ORR -DEFINE_ALU_INSN_NC(18, 38, ORR, NO) -// ORRS -DEFINE_ALU_INSN_C (19, 39, ORRS, YES) - -// MOV -DEFINE_ALU_INSN_NC(1A, 3A, MOV, NO) -// MOVS -DEFINE_ALU_INSN_C (1B, 3B, MOVS, YES) - -// BIC -DEFINE_ALU_INSN_NC(1C, 3C, BIC, NO) -// BICS -DEFINE_ALU_INSN_C (1D, 3D, BICS, YES) - -// MVN -DEFINE_ALU_INSN_NC(1E, 3E, MVN, NO) -// MVNS -DEFINE_ALU_INSN_C (1F, 3F, MVNS, YES) - -// Multiply instructions ////////////////////////////////////////////////// - -// OP: OP_MUL, OP_MLA etc. -// SETCOND: SETCOND_NONE, SETCOND_MUL, or SETCOND_MULL -// CYCLES: base cycle count (1, 2, or 3) -#define MUL_INSN(OP, SETCOND, CYCLES) \ - int mult = (opcode & 0x0F); \ - u32 rs = reg[(opcode >> 8) & 0x0F].I; \ - int acc = (opcode >> 12) & 0x0F; /* or destLo */ \ - int dest = (opcode >> 16) & 0x0F; /* or destHi */ \ - OP; \ - SETCOND; \ - if ((s32)rs < 0) \ - rs = ~rs; \ - if ((rs & 0xFFFFFF00) == 0) \ - clockTicks += 0; \ - else if ((rs & 0xFFFF0000) == 0) \ - clockTicks += 1; \ - else if ((rs & 0xFF000000) == 0) \ - clockTicks += 2; \ - else \ - clockTicks += 3; \ - if (busPrefetchCount == 0) \ - busPrefetchCount = ((busPrefetchCount+1)<> 32); -#define OP_MLAL(SIGN) \ - SIGN##64 res = ((SIGN##64)reg[dest].I<<32 | reg[acc].I)\ - + ((SIGN##64)(SIGN##32)reg[mult].I \ - * (SIGN##64)(SIGN##32)rs); \ - reg[acc].I = (u32)res; \ - reg[dest].I = (u32)(res >> 32); -#define OP_UMULL OP_MULL(u) -#define OP_UMLAL OP_MLAL(u) -#define OP_SMULL OP_MULL(s) -#define OP_SMLAL OP_MLAL(s) - -// MUL Rd, Rm, Rs -static INSN_REGPARM void arm009(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_NONE, 1); } -// MULS Rd, Rm, Rs -static INSN_REGPARM void arm019(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_MUL, 1); } - -// MLA Rd, Rm, Rs, Rn -static INSN_REGPARM void arm029(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_NONE, 2); } -// MLAS Rd, Rm, Rs, Rn -static INSN_REGPARM void arm039(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_MUL, 2); } - -// UMULL RdLo, RdHi, Rn, Rs -static INSN_REGPARM void arm089(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_NONE, 2); } -// UMULLS RdLo, RdHi, Rn, Rs -static INSN_REGPARM void arm099(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_MULL, 2); } - -// UMLAL RdLo, RdHi, Rn, Rs -static INSN_REGPARM void arm0A9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_NONE, 3); } -// UMLALS RdLo, RdHi, Rn, Rs -static INSN_REGPARM void arm0B9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_MULL, 3); } - -// SMULL RdLo, RdHi, Rm, Rs -static INSN_REGPARM void arm0C9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_NONE, 2); } -// SMULLS RdLo, RdHi, Rm, Rs -static INSN_REGPARM void arm0D9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_MULL, 2); } - -// SMLAL RdLo, RdHi, Rm, Rs -static INSN_REGPARM void arm0E9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_NONE, 3); } -// SMLALS RdLo, RdHi, Rm, Rs -static INSN_REGPARM void arm0F9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_MULL, 3); } - -// Misc instructions ////////////////////////////////////////////////////// - -// SWP Rd, Rm, [Rn] -static INSN_REGPARM void arm109(u32 opcode) -{ - u32 address = reg[(opcode >> 16) & 15].I; - u32 temp = CPUReadMemory(address); - CPUWriteMemory(address, reg[opcode&15].I); - reg[(opcode >> 12) & 15].I = temp; - clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) - + codeTicksAccess32(armNextPC); -} - -// SWPB Rd, Rm, [Rn] -static INSN_REGPARM void arm149(u32 opcode) -{ - u32 address = reg[(opcode >> 16) & 15].I; - u32 temp = CPUReadByte(address); - CPUWriteByte(address, reg[opcode&15].B.B0); - reg[(opcode>>12)&15].I = temp; - clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) - + codeTicksAccess32(armNextPC); -} - -// MRS Rd, CPSR -static INSN_REGPARM void arm100(u32 opcode) -{ - if (LIKELY((opcode & 0x0FFF0FFF) == 0x010F0000)) { - CPUUpdateCPSR(); - reg[(opcode >> 12) & 0x0F].I = reg[16].I; - } else { - armUnknownInsn(opcode); - } -} - -// MRS Rd, SPSR -static INSN_REGPARM void arm140(u32 opcode) -{ - if (LIKELY((opcode & 0x0FFF0FFF) == 0x014F0000)) { - reg[(opcode >> 12) & 0x0F].I = reg[17].I; - } else { - armUnknownInsn(opcode); - } -} - -// MSR CPSR_fields, Rm -static INSN_REGPARM void arm120(u32 opcode) -{ - if (LIKELY((opcode & 0x0FF0FFF0) == 0x0120F000)) { - CPUUpdateCPSR(); - u32 value = reg[opcode & 15].I; - u32 newValue = reg[16].I; - if (armMode > 0x10) { - if (opcode & 0x00010000) - newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); - } - if (opcode & 0x00080000) - newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); - newValue |= 0x10; - CPUSwitchMode(newValue & 0x1F, false); - reg[16].I = newValue; - CPUUpdateFlags(); - if (!armState) { // this should not be allowed, but it seems to work - THUMB_PREFETCH; - reg[15].I = armNextPC + 2; - } - } else { - armUnknownInsn(opcode); - } -} - -// MSR SPSR_fields, Rm -static INSN_REGPARM void arm160(u32 opcode) -{ - if (LIKELY((opcode & 0x0FF0FFF0) == 0x0160F000)) { - u32 value = reg[opcode & 15].I; - if (armMode > 0x10 && armMode < 0x1F) { - if (opcode & 0x00010000) - reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); - if (opcode & 0x00080000) - reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); - } - } else { - armUnknownInsn(opcode); - } -} - -// MSR CPSR_fields, # -static INSN_REGPARM void arm320(u32 opcode) -{ - if (LIKELY((opcode & 0x0FF0F000) == 0x0320F000)) { - CPUUpdateCPSR(); - u32 value = opcode & 0xFF; - int shift = (opcode & 0xF00) >> 7; - if (shift) { - ROR_IMM_MSR; - } - u32 newValue = reg[16].I; - if (armMode > 0x10) { - if (opcode & 0x00010000) - newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); - } - if (opcode & 0x00080000) - newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); - - newValue |= 0x10; - - CPUSwitchMode(newValue & 0x1F, false); - reg[16].I = newValue; - CPUUpdateFlags(); - if (!armState) { // this should not be allowed, but it seems to work - THUMB_PREFETCH; - reg[15].I = armNextPC + 2; - } - } else { - armUnknownInsn(opcode); - } -} - -// MSR SPSR_fields, # -static INSN_REGPARM void arm360(u32 opcode) -{ - if (LIKELY((opcode & 0x0FF0F000) == 0x0360F000)) { - if (armMode > 0x10 && armMode < 0x1F) { - u32 value = opcode & 0xFF; - int shift = (opcode & 0xF00) >> 7; - if (shift) { - ROR_IMM_MSR; - } - if (opcode & 0x00010000) - reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); - if (opcode & 0x00080000) - reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); - } - } else { - armUnknownInsn(opcode); - } -} - -// BX Rm -static INSN_REGPARM void arm121(u32 opcode) -{ - if (LIKELY((opcode & 0x0FFFFFF0) == 0x012FFF10)) { - int base = opcode & 0x0F; - busPrefetchCount = 0; - armState = reg[base].I & 1 ? false : true; - if (armState) { - reg[15].I = reg[base].I & 0xFFFFFFFC; - armNextPC = reg[15].I; - reg[15].I += 4; - ARM_PREFETCH; - clockTicks = 3 + codeTicksAccessSeq32(armNextPC) - + codeTicksAccessSeq32(armNextPC) - + codeTicksAccess32(armNextPC); - } else { - reg[15].I = reg[base].I & 0xFFFFFFFE; - armNextPC = reg[15].I; - reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = 3 + codeTicksAccessSeq16(armNextPC) - + codeTicksAccessSeq16(armNextPC) - + codeTicksAccess16(armNextPC); - } - } else { - armUnknownInsn(opcode); - } -} - -// Load/store ///////////////////////////////////////////////////////////// - -#define OFFSET_IMM \ - int offset = opcode & 0xFFF; -#define OFFSET_IMM8 \ - int offset = ((opcode & 0x0F) | ((opcode>>4) & 0xF0)); -#define OFFSET_REG \ - int offset = reg[opcode & 15].I; -#define OFFSET_LSL \ - int offset = reg[opcode & 15].I << ((opcode>>7) & 31); -#define OFFSET_LSR \ - int shift = (opcode >> 7) & 31; \ - int offset = shift ? reg[opcode & 15].I >> shift : 0; -#define OFFSET_ASR \ - int shift = (opcode >> 7) & 31; \ - int offset; \ - if (shift) \ - offset = (int)((s32)reg[opcode & 15].I >> shift);\ - else if (reg[opcode & 15].I & 0x80000000) \ - offset = 0xFFFFFFFF; \ - else \ - offset = 0; -#define OFFSET_ROR \ - int shift = (opcode >> 7) & 31; \ - u32 offset = reg[opcode & 15].I; \ - if (shift) { \ - ROR_OFFSET; \ - } else { \ - RRX_OFFSET; \ - } - -#define ADDRESS_POST (reg[base].I) -#define ADDRESS_PREDEC (reg[base].I - offset) -#define ADDRESS_PREINC (reg[base].I + offset) - -#define OP_STR CPUWriteMemory(address, reg[dest].I) -#define OP_STRH CPUWriteHalfWord(address, reg[dest].W.W0) -#define OP_STRB CPUWriteByte(address, reg[dest].B.B0) -#define OP_LDR reg[dest].I = CPUReadMemory(address) -#define OP_LDRH reg[dest].I = CPUReadHalfWord(address) -#define OP_LDRB reg[dest].I = CPUReadByte(address) -#define OP_LDRSH reg[dest].I = (s16)CPUReadHalfWordSigned(address) -#define OP_LDRSB reg[dest].I = (s8)CPUReadByte(address) - -#define WRITEBACK_NONE /*nothing*/ -#define WRITEBACK_PRE reg[base].I = address -#define WRITEBACK_POSTDEC reg[base].I = address - offset -#define WRITEBACK_POSTINC reg[base].I = address + offset - -#define LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS) \ - if (busPrefetchCount == 0) \ - busPrefetch = busPrefetchEnable; \ - int dest = (opcode >> 12) & 15; \ - int base = (opcode >> 16) & 15; \ - CALC_OFFSET; \ - u32 address = CALC_ADDRESS; - -#define STR(CALC_OFFSET, CALC_ADDRESS, STORE_DATA, WRITEBACK1, WRITEBACK2, SIZE) \ - LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \ - WRITEBACK1; \ - STORE_DATA; \ - WRITEBACK2; \ - clockTicks = 2 + dataTicksAccess##SIZE(address) \ - + codeTicksAccess32(armNextPC); -#define LDR(CALC_OFFSET, CALC_ADDRESS, LOAD_DATA, WRITEBACK, SIZE) \ - LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \ - LOAD_DATA; \ - if (dest != base) \ - { \ - WRITEBACK; \ - } \ - clockTicks = 0; \ - if (dest == 15) { \ - reg[15].I &= 0xFFFFFFFC; \ - armNextPC = reg[15].I; \ - reg[15].I += 4; \ - ARM_PREFETCH; \ - clockTicks += 2 + dataTicksAccessSeq32(address) \ - + dataTicksAccessSeq32(address);\ - } \ - clockTicks += 3 + dataTicksAccess##SIZE(address) \ - + codeTicksAccess32(armNextPC); -#define STR_POSTDEC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTDEC, SIZE) -#define STR_POSTINC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTINC, SIZE) -#define STR_PREDEC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE) -#define STR_PREDEC_WB(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE) -#define STR_PREINC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE) -#define STR_PREINC_WB(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE) -#define LDR_POSTDEC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTDEC, SIZE) -#define LDR_POSTINC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTINC, SIZE) -#define LDR_PREDEC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_NONE, SIZE) -#define LDR_PREDEC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_PRE, SIZE) -#define LDR_PREINC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_NONE, SIZE) -#define LDR_PREINC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_PRE, SIZE) - -// STRH Rd, [Rn], -Rm -static INSN_REGPARM void arm00B(u32 opcode) { STR_POSTDEC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn], #-offset -static INSN_REGPARM void arm04B(u32 opcode) { STR_POSTDEC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn], Rm -static INSN_REGPARM void arm08B(u32 opcode) { STR_POSTINC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn], #offset -static INSN_REGPARM void arm0CB(u32 opcode) { STR_POSTINC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, -Rm] -static INSN_REGPARM void arm10B(u32 opcode) { STR_PREDEC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, -Rm]! -static INSN_REGPARM void arm12B(u32 opcode) { STR_PREDEC_WB(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, -#offset] -static INSN_REGPARM void arm14B(u32 opcode) { STR_PREDEC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, -#offset]! -static INSN_REGPARM void arm16B(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, Rm] -static INSN_REGPARM void arm18B(u32 opcode) { STR_PREINC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, Rm]! -static INSN_REGPARM void arm1AB(u32 opcode) { STR_PREINC_WB(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, #offset] -static INSN_REGPARM void arm1CB(u32 opcode) { STR_PREINC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, #offset]! -static INSN_REGPARM void arm1EB(u32 opcode) { STR_PREINC_WB(OFFSET_IMM8, OP_STRH, 16); } - -// LDRH Rd, [Rn], -Rm -static INSN_REGPARM void arm01B(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn], #-offset -static INSN_REGPARM void arm05B(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn], Rm -static INSN_REGPARM void arm09B(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn], #offset -static INSN_REGPARM void arm0DB(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, -Rm] -static INSN_REGPARM void arm11B(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, -Rm]! -static INSN_REGPARM void arm13B(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, -#offset] -static INSN_REGPARM void arm15B(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, -#offset]! -static INSN_REGPARM void arm17B(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, Rm] -static INSN_REGPARM void arm19B(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, Rm]! -static INSN_REGPARM void arm1BB(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, #offset] -static INSN_REGPARM void arm1DB(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, #offset]! -static INSN_REGPARM void arm1FB(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRH, 16); } - -// LDRSB Rd, [Rn], -Rm -static INSN_REGPARM void arm01D(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn], #-offset -static INSN_REGPARM void arm05D(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn], Rm -static INSN_REGPARM void arm09D(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn], #offset -static INSN_REGPARM void arm0DD(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -Rm] -static INSN_REGPARM void arm11D(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -Rm]! -static INSN_REGPARM void arm13D(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -#offset] -static INSN_REGPARM void arm15D(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -#offset]! -static INSN_REGPARM void arm17D(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, Rm] -static INSN_REGPARM void arm19D(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, Rm]! -static INSN_REGPARM void arm1BD(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, #offset] -static INSN_REGPARM void arm1DD(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, #offset]! -static INSN_REGPARM void arm1FD(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSB, 16); } - -// LDRSH Rd, [Rn], -Rm -static INSN_REGPARM void arm01F(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn], #-offset -static INSN_REGPARM void arm05F(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn], Rm -static INSN_REGPARM void arm09F(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn], #offset -static INSN_REGPARM void arm0DF(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -Rm] -static INSN_REGPARM void arm11F(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -Rm]! -static INSN_REGPARM void arm13F(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -#offset] -static INSN_REGPARM void arm15F(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -#offset]! -static INSN_REGPARM void arm17F(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, Rm] -static INSN_REGPARM void arm19F(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, Rm]! -static INSN_REGPARM void arm1BF(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, #offset] -static INSN_REGPARM void arm1DF(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, #offset]! -static INSN_REGPARM void arm1FF(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSH, 16); } - -// STR[T] Rd, [Rn], -# -// Note: STR and STRT do the same thing on the GBA (likewise for LDR/LDRT etc) -static INSN_REGPARM void arm400(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STR, 32); } -// LDR[T] Rd, [Rn], -# -static INSN_REGPARM void arm410(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDR, 32); } -// STRB[T] Rd, [Rn], -# -static INSN_REGPARM void arm440(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], -# -static INSN_REGPARM void arm450(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDRB, 16); } -// STR[T] Rd, [Rn], # -static INSN_REGPARM void arm480(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn], # -static INSN_REGPARM void arm490(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDR, 32); } -// STRB[T] Rd, [Rn], # -static INSN_REGPARM void arm4C0(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], # -static INSN_REGPARM void arm4D0(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDRB, 16); } -// STR Rd, [Rn, -#] -static INSN_REGPARM void arm500(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, -#] -static INSN_REGPARM void arm510(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDR, 32); } -// STR Rd, [Rn, -#]! -static INSN_REGPARM void arm520(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, -#]! -static INSN_REGPARM void arm530(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDR, 32); } -// STRB Rd, [Rn, -#] -static INSN_REGPARM void arm540(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, -#] -static INSN_REGPARM void arm550(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDRB, 16); } -// STRB Rd, [Rn, -#]! -static INSN_REGPARM void arm560(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, -#]! -static INSN_REGPARM void arm570(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDRB, 16); } -// STR Rd, [Rn, #] -static INSN_REGPARM void arm580(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, #] -static INSN_REGPARM void arm590(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDR, 32); } -// STR Rd, [Rn, #]! -static INSN_REGPARM void arm5A0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, #]! -static INSN_REGPARM void arm5B0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDR, 32); } -// STRB Rd, [Rn, #] -static INSN_REGPARM void arm5C0(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, #] -static INSN_REGPARM void arm5D0(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDRB, 16); } -// STRB Rd, [Rn, #]! -static INSN_REGPARM void arm5E0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, #]! -static INSN_REGPARM void arm5F0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDRB, 16); } - -// STR[T] Rd, [Rn], -Rm, LSL # -static INSN_REGPARM void arm600(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STR, 32); } -// STR[T] Rd, [Rn], -Rm, LSR # -static INSN_REGPARM void arm602(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STR, 32); } -// STR[T] Rd, [Rn], -Rm, ASR # -static INSN_REGPARM void arm604(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STR, 32); } -// STR[T] Rd, [Rn], -Rm, ROR # -static INSN_REGPARM void arm606(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STR, 32); } -// LDR[T] Rd, [Rn], -Rm, LSL # -static INSN_REGPARM void arm610(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDR, 32); } -// LDR[T] Rd, [Rn], -Rm, LSR # -static INSN_REGPARM void arm612(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], -Rm, ASR # -static INSN_REGPARM void arm614(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], -Rm, ROR # -static INSN_REGPARM void arm616(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDR, 32); } -// STRB[T] Rd, [Rn], -Rm, LSL # -static INSN_REGPARM void arm640(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STRB, 16); } -// STRB[T] Rd, [Rn], -Rm, LSR # -static INSN_REGPARM void arm642(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], -Rm, ASR # -static INSN_REGPARM void arm644(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], -Rm, ROR # -static INSN_REGPARM void arm646(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], -Rm, LSL # -static INSN_REGPARM void arm650(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], -Rm, LSR # -static INSN_REGPARM void arm652(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], -Rm, ASR # -static INSN_REGPARM void arm654(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn], -Rm, ROR # -static INSN_REGPARM void arm656(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDRB, 16); } -// STR[T] Rd, [Rn], Rm, LSL # -static INSN_REGPARM void arm680(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STR, 32); } -// STR[T] Rd, [Rn], Rm, LSR # -static INSN_REGPARM void arm682(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STR, 32); } -// STR[T] Rd, [Rn], Rm, ASR # -static INSN_REGPARM void arm684(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STR, 32); } -// STR[T] Rd, [Rn], Rm, ROR # -static INSN_REGPARM void arm686(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STR, 32); } -// LDR[T] Rd, [Rn], Rm, LSL # -static INSN_REGPARM void arm690(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDR, 32); } -// LDR[T] Rd, [Rn], Rm, LSR # -static INSN_REGPARM void arm692(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], Rm, ASR # -static INSN_REGPARM void arm694(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], Rm, ROR # -static INSN_REGPARM void arm696(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDR, 32); } -// STRB[T] Rd, [Rn], Rm, LSL # -static INSN_REGPARM void arm6C0(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STRB, 16); } -// STRB[T] Rd, [Rn], Rm, LSR # -static INSN_REGPARM void arm6C2(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], Rm, ASR # -static INSN_REGPARM void arm6C4(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], Rm, ROR # -static INSN_REGPARM void arm6C6(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], Rm, LSL # -static INSN_REGPARM void arm6D0(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], Rm, LSR # -static INSN_REGPARM void arm6D2(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], Rm, ASR # -static INSN_REGPARM void arm6D4(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], Rm, ROR # -static INSN_REGPARM void arm6D6(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDRB, 16); } -// STR Rd, [Rn, -Rm, LSL #] -static INSN_REGPARM void arm700(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, -Rm, LSR #] -static INSN_REGPARM void arm702(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ASR #] -static INSN_REGPARM void arm704(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ROR #] -static INSN_REGPARM void arm706(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, -Rm, LSL #] -static INSN_REGPARM void arm710(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, LSR #] -static INSN_REGPARM void arm712(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ASR #] -static INSN_REGPARM void arm714(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ROR #] -static INSN_REGPARM void arm716(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDR, 32); } -// STR Rd, [Rn, -Rm, LSL #]! -static INSN_REGPARM void arm720(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, -Rm, LSR #]! -static INSN_REGPARM void arm722(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ASR #]! -static INSN_REGPARM void arm724(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ROR #]! -static INSN_REGPARM void arm726(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, -Rm, LSL #]! -static INSN_REGPARM void arm730(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, LSR #]! -static INSN_REGPARM void arm732(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ASR #]! -static INSN_REGPARM void arm734(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ROR #]! -static INSN_REGPARM void arm736(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDR, 32); } -// STRB Rd, [Rn, -Rm, LSL #] -static INSN_REGPARM void arm740(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, LSR #] -static INSN_REGPARM void arm742(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ASR #] -static INSN_REGPARM void arm744(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ROR #] -static INSN_REGPARM void arm746(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, -Rm, LSL #] -static INSN_REGPARM void arm750(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, LSR #] -static INSN_REGPARM void arm752(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ASR #] -static INSN_REGPARM void arm754(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ROR #] -static INSN_REGPARM void arm756(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDRB, 16); } -// STRB Rd, [Rn, -Rm, LSL #]! -static INSN_REGPARM void arm760(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, LSR #]! -static INSN_REGPARM void arm762(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ASR #]! -static INSN_REGPARM void arm764(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ROR #]! -static INSN_REGPARM void arm766(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, -Rm, LSL #]! -static INSN_REGPARM void arm770(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, LSR #]! -static INSN_REGPARM void arm772(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ASR #]! -static INSN_REGPARM void arm774(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ROR #]! -static INSN_REGPARM void arm776(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDRB, 16); } -// STR Rd, [Rn, Rm, LSL #] -static INSN_REGPARM void arm780(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, Rm, LSR #] -static INSN_REGPARM void arm782(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ASR #] -static INSN_REGPARM void arm784(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ROR #] -static INSN_REGPARM void arm786(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, Rm, LSL #] -static INSN_REGPARM void arm790(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, LSR #] -static INSN_REGPARM void arm792(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ASR #] -static INSN_REGPARM void arm794(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ROR #] -static INSN_REGPARM void arm796(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDR, 32); } -// STR Rd, [Rn, Rm, LSL #]! -static INSN_REGPARM void arm7A0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, Rm, LSR #]! -static INSN_REGPARM void arm7A2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ASR #]! -static INSN_REGPARM void arm7A4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ROR #]! -static INSN_REGPARM void arm7A6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, Rm, LSL #]! -static INSN_REGPARM void arm7B0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, LSR #]! -static INSN_REGPARM void arm7B2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ASR #]! -static INSN_REGPARM void arm7B4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ROR #]! -static INSN_REGPARM void arm7B6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDR, 32); } -// STRB Rd, [Rn, Rm, LSL #] -static INSN_REGPARM void arm7C0(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, LSR #] -static INSN_REGPARM void arm7C2(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ASR #] -static INSN_REGPARM void arm7C4(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ROR #] -static INSN_REGPARM void arm7C6(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, Rm, LSL #] -static INSN_REGPARM void arm7D0(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, LSR #] -static INSN_REGPARM void arm7D2(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ASR #] -static INSN_REGPARM void arm7D4(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ROR #] -static INSN_REGPARM void arm7D6(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDRB, 16); } -// STRB Rd, [Rn, Rm, LSL #]! -static INSN_REGPARM void arm7E0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, LSR #]! -static INSN_REGPARM void arm7E2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ASR #]! -static INSN_REGPARM void arm7E4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ROR #]! -static INSN_REGPARM void arm7E6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, Rm, LSL #]! -static INSN_REGPARM void arm7F0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, LSR #]! -static INSN_REGPARM void arm7F2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ASR #]! -static INSN_REGPARM void arm7F4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ROR #]! -static INSN_REGPARM void arm7F6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDRB, 16); } - -// STM/LDM //////////////////////////////////////////////////////////////// - -#define STM_REG(bit,num) \ - if (opcode & (1U<<(bit))) { \ - CPUWriteMemory(address, reg[(num)].I); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address);\ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address);\ - } \ - count++; \ - address += 4; \ - } -#define STMW_REG(bit,num) \ - if (opcode & (1U<<(bit))) { \ - CPUWriteMemory(address, reg[(num)].I); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address);\ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address);\ - } \ - reg[base].I = temp; \ - count++; \ - address += 4; \ - } -#define LDM_REG(bit,num) \ - if (opcode & (1U<<(bit))) { \ - reg[(num)].I = CPUReadMemory(address); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address);\ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address);\ - } \ - count++; \ - address += 4; \ - } -#define STM_LOW(STORE_REG) \ - STORE_REG(0, 0); \ - STORE_REG(1, 1); \ - STORE_REG(2, 2); \ - STORE_REG(3, 3); \ - STORE_REG(4, 4); \ - STORE_REG(5, 5); \ - STORE_REG(6, 6); \ - STORE_REG(7, 7); -#define STM_HIGH(STORE_REG) \ - STORE_REG(8, 8); \ - STORE_REG(9, 9); \ - STORE_REG(10, 10); \ - STORE_REG(11, 11); \ - STORE_REG(12, 12); \ - STORE_REG(13, 13); \ - STORE_REG(14, 14); -#define STM_HIGH_2(STORE_REG) \ - if (armMode == 0x11) { \ - STORE_REG(8, R8_FIQ); \ - STORE_REG(9, R9_FIQ); \ - STORE_REG(10, R10_FIQ); \ - STORE_REG(11, R11_FIQ); \ - STORE_REG(12, R12_FIQ); \ - } else { \ - STORE_REG(8, 8); \ - STORE_REG(9, 9); \ - STORE_REG(10, 10); \ - STORE_REG(11, 11); \ - STORE_REG(12, 12); \ - } \ - if (armMode != 0x10 && armMode != 0x1F) { \ - STORE_REG(13, R13_USR); \ - STORE_REG(14, R14_USR); \ - } else { \ - STORE_REG(13, 13); \ - STORE_REG(14, 14); \ - } -#define STM_PC \ - if (opcode & (1U<<15)) { \ - CPUWriteMemory(address, reg[15].I+4); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address);\ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address);\ - } \ - count++; \ - } -#define STMW_PC \ - if (opcode & (1U<<15)) { \ - CPUWriteMemory(address, reg[15].I+4); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address);\ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address);\ - } \ - reg[base].I = temp; \ - count++; \ - } -#define LDM_LOW \ - LDM_REG(0, 0); \ - LDM_REG(1, 1); \ - LDM_REG(2, 2); \ - LDM_REG(3, 3); \ - LDM_REG(4, 4); \ - LDM_REG(5, 5); \ - LDM_REG(6, 6); \ - LDM_REG(7, 7); -#define LDM_HIGH \ - LDM_REG(8, 8); \ - LDM_REG(9, 9); \ - LDM_REG(10, 10); \ - LDM_REG(11, 11); \ - LDM_REG(12, 12); \ - LDM_REG(13, 13); \ - LDM_REG(14, 14); -#define LDM_HIGH_2 \ - if (armMode == 0x11) { \ - LDM_REG(8, R8_FIQ); \ - LDM_REG(9, R9_FIQ); \ - LDM_REG(10, R10_FIQ); \ - LDM_REG(11, R11_FIQ); \ - LDM_REG(12, R12_FIQ); \ - } else { \ - LDM_REG(8, 8); \ - LDM_REG(9, 9); \ - LDM_REG(10, 10); \ - LDM_REG(11, 11); \ - LDM_REG(12, 12); \ - } \ - if (armMode != 0x10 && armMode != 0x1F) { \ - LDM_REG(13, R13_USR); \ - LDM_REG(14, R14_USR); \ - } else { \ - LDM_REG(13, 13); \ - LDM_REG(14, 14); \ - } -#define STM_ALL \ - STM_LOW(STM_REG); \ - STM_HIGH(STM_REG); \ - STM_PC; -#define STMW_ALL \ - STM_LOW(STMW_REG); \ - STM_HIGH(STMW_REG); \ - STMW_PC; -#define LDM_ALL \ - LDM_LOW; \ - LDM_HIGH; \ - if (opcode & (1U<<15)) { \ - reg[15].I = CPUReadMemory(address); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address);\ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address);\ - } \ - count++; \ - } \ - if (opcode & (1U<<15)) { \ - armNextPC = reg[15].I; \ - reg[15].I += 4; \ - ARM_PREFETCH; \ - clockTicks += 1 + codeTicksAccessSeq32(armNextPC);\ - } -#define STM_ALL_2 \ - STM_LOW(STM_REG); \ - STM_HIGH_2(STM_REG); \ - STM_PC; -#define STMW_ALL_2 \ - STM_LOW(STMW_REG); \ - STM_HIGH_2(STMW_REG); \ - STMW_PC; -#define LDM_ALL_2 \ - LDM_LOW; \ - if (opcode & (1U<<15)) { \ - LDM_HIGH; \ - reg[15].I = CPUReadMemory(address); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address); \ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address); \ - } \ - count++; \ - } else { \ - LDM_HIGH_2; \ - } -#define LDM_ALL_2B \ - if (opcode & (1U<<15)) { \ - CPUSwitchMode(reg[17].I & 0x1F, false); \ - if (armState) { \ - armNextPC = reg[15].I & 0xFFFFFFFC; \ - reg[15].I = armNextPC + 4; \ - ARM_PREFETCH; \ - } else { \ - armNextPC = reg[15].I & 0xFFFFFFFE; \ - reg[15].I = armNextPC + 2; \ - THUMB_PREFETCH; \ - } \ - clockTicks += 1 + codeTicksAccessSeq32(armNextPC);\ - } - - -// STMDA Rn, {Rlist} -static INSN_REGPARM void arm800(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDA Rn, {Rlist} -static INSN_REGPARM void arm810(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMDA Rn!, {Rlist} -static INSN_REGPARM void arm820(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp+4) & 0xFFFFFFFC; - int count = 0; - STMW_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDA Rn!, {Rlist} -static INSN_REGPARM void arm830(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); - if (!(opcode & (1U << base))) - reg[base].I = temp; -} - -// STMDA Rn, {Rlist}^ -static INSN_REGPARM void arm840(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp+4) & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDA Rn, {Rlist}^ -static INSN_REGPARM void arm850(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMDA Rn!, {Rlist}^ -static INSN_REGPARM void arm860(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp+4) & 0xFFFFFFFC; - int count = 0; - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDA Rn!, {Rlist}^ -static INSN_REGPARM void arm870(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMIA Rn, {Rlist} -static INSN_REGPARM void arm880(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIA Rn, {Rlist} -static INSN_REGPARM void arm890(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMIA Rn!, {Rlist} -static INSN_REGPARM void arm8A0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIA Rn!, {Rlist} -static INSN_REGPARM void arm8B0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); - if (!(opcode & (1U << base))) - reg[base].I = temp; -} - -// STMIA Rn, {Rlist}^ -static INSN_REGPARM void arm8C0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIA Rn, {Rlist}^ -static INSN_REGPARM void arm8D0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMIA Rn!, {Rlist}^ -static INSN_REGPARM void arm8E0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIA Rn!, {Rlist}^ -static INSN_REGPARM void arm8F0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMDB Rn, {Rlist} -static INSN_REGPARM void arm900(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDB Rn, {Rlist} -static INSN_REGPARM void arm910(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMDB Rn!, {Rlist} -static INSN_REGPARM void arm920(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STMW_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDB Rn!, {Rlist} -static INSN_REGPARM void arm930(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); - if (!(opcode & (1U << base))) - reg[base].I = temp; -} - -// STMDB Rn, {Rlist}^ -static INSN_REGPARM void arm940(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDB Rn, {Rlist}^ -static INSN_REGPARM void arm950(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMDB Rn!, {Rlist}^ -static INSN_REGPARM void arm960(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMDB Rn!, {Rlist}^ -static INSN_REGPARM void arm970(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMIB Rn, {Rlist} -static INSN_REGPARM void arm980(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIB Rn, {Rlist} -static INSN_REGPARM void arm990(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMIB Rn!, {Rlist} -static INSN_REGPARM void arm9A0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIB Rn!, {Rlist} -static INSN_REGPARM void arm9B0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess32(armNextPC); - if (!(opcode & (1U << base))) - reg[base].I = temp; -} - -// STMIB Rn, {Rlist}^ -static INSN_REGPARM void arm9C0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIB Rn, {Rlist}^ -static INSN_REGPARM void arm9D0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// STMIB Rn!, {Rlist}^ -static INSN_REGPARM void arm9E0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess32(armNextPC); -} - -// LDMIB Rn!, {Rlist}^ -static INSN_REGPARM void arm9F0(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess32(armNextPC); -} - -// B/BL/SWI and (unimplemented) coproc support //////////////////////////// - -// B -static INSN_REGPARM void armA00(u32 opcode) -{ - int offset = opcode & 0x00FFFFFF; - if (offset & 0x00800000) - offset |= 0xFF000000; // negative offset - reg[15].I += offset<<2; - armNextPC = reg[15].I; - reg[15].I += 4; - ARM_PREFETCH; - clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); - busPrefetchCount = 0; -} - -// BL -static INSN_REGPARM void armB00(u32 opcode) -{ - int offset = opcode & 0x00FFFFFF; - if (offset & 0x00800000) - offset |= 0xFF000000; // negative offset - reg[14].I = reg[15].I - 4; - reg[15].I += offset<<2; - armNextPC = reg[15].I; - reg[15].I += 4; - ARM_PREFETCH; - clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); - busPrefetchCount = 0; -} - - -#ifdef GP_SUPPORT -// MRC -static INSN_REGPARM void armE01(u32 opcode) -{ -} -#else - #define armE01 armUnknownInsn -#endif - - -// SWI -static INSN_REGPARM void armF00(u32 opcode) -{ - clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); - busPrefetchCount = 0; - CPUSoftwareInterrupt(opcode & 0x00FFFFFF); -} - -// Instruction table ////////////////////////////////////////////////////// - -typedef INSN_REGPARM void (*insnfunc_t)(u32 opcode); -#define REP16(insn) \ - insn,insn,insn,insn,insn,insn,insn,insn,\ - insn,insn,insn,insn,insn,insn,insn,insn -#define REP256(insn) \ - REP16(insn),REP16(insn),REP16(insn),REP16(insn),\ - REP16(insn),REP16(insn),REP16(insn),REP16(insn),\ - REP16(insn),REP16(insn),REP16(insn),REP16(insn),\ - REP16(insn),REP16(insn),REP16(insn),REP16(insn) -#define arm_UI armUnknownInsn -#ifdef BKPT_SUPPORT - #define arm_BP armBreakpoint -#else - #define arm_BP armUnknownInsn -#endif -static insnfunc_t armInsnTable[4096] = { - arm000,arm001,arm002,arm003,arm004,arm005,arm006,arm007, // 000 - arm000,arm009,arm002,arm00B,arm004,arm_UI,arm006,arm_UI, // 008 - arm010,arm011,arm012,arm013,arm014,arm015,arm016,arm017, // 010 - arm010,arm019,arm012,arm01B,arm014,arm01D,arm016,arm01F, // 018 - arm020,arm021,arm022,arm023,arm024,arm025,arm026,arm027, // 020 - arm020,arm029,arm022,arm_UI,arm024,arm_UI,arm026,arm_UI, // 028 - arm030,arm031,arm032,arm033,arm034,arm035,arm036,arm037, // 030 - arm030,arm039,arm032,arm_UI,arm034,arm01D,arm036,arm01F, // 038 - arm040,arm041,arm042,arm043,arm044,arm045,arm046,arm047, // 040 - arm040,arm_UI,arm042,arm04B,arm044,arm_UI,arm046,arm_UI, // 048 - arm050,arm051,arm052,arm053,arm054,arm055,arm056,arm057, // 050 - arm050,arm_UI,arm052,arm05B,arm054,arm05D,arm056,arm05F, // 058 - arm060,arm061,arm062,arm063,arm064,arm065,arm066,arm067, // 060 - arm060,arm_UI,arm062,arm_UI,arm064,arm_UI,arm066,arm_UI, // 068 - arm070,arm071,arm072,arm073,arm074,arm075,arm076,arm077, // 070 - arm070,arm_UI,arm072,arm_UI,arm074,arm05D,arm076,arm05F, // 078 - arm080,arm081,arm082,arm083,arm084,arm085,arm086,arm087, // 080 - arm080,arm089,arm082,arm08B,arm084,arm_UI,arm086,arm_UI, // 088 - arm090,arm091,arm092,arm093,arm094,arm095,arm096,arm097, // 090 - arm090,arm099,arm092,arm09B,arm094,arm09D,arm096,arm09F, // 098 - arm0A0,arm0A1,arm0A2,arm0A3,arm0A4,arm0A5,arm0A6,arm0A7, // 0A0 - arm0A0,arm0A9,arm0A2,arm_UI,arm0A4,arm_UI,arm0A6,arm_UI, // 0A8 - arm0B0,arm0B1,arm0B2,arm0B3,arm0B4,arm0B5,arm0B6,arm0B7, // 0B0 - arm0B0,arm0B9,arm0B2,arm_UI,arm0B4,arm09D,arm0B6,arm09F, // 0B8 - arm0C0,arm0C1,arm0C2,arm0C3,arm0C4,arm0C5,arm0C6,arm0C7, // 0C0 - arm0C0,arm0C9,arm0C2,arm0CB,arm0C4,arm_UI,arm0C6,arm_UI, // 0C8 - arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7, // 0D0 - arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF, // 0D8 - arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0 - arm0E0,arm0E9,arm0E2,arm_UI,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8 - arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0 - arm0F0,arm0F9,arm0F2,arm_UI,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8 - - arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100 - arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108 - arm110,arm111,arm112,arm113,arm114,arm115,arm116,arm117, // 110 - arm110,arm_UI,arm112,arm11B,arm114,arm11D,arm116,arm11F, // 118 - arm120,arm121,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_BP, // 120 - arm_UI,arm_UI,arm_UI,arm12B,arm_UI,arm_UI,arm_UI,arm_UI, // 128 - arm130,arm131,arm132,arm133,arm134,arm135,arm136,arm137, // 130 - arm130,arm_UI,arm132,arm13B,arm134,arm13D,arm136,arm13F, // 138 - arm140,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 140 - arm_UI,arm149,arm_UI,arm14B,arm_UI,arm_UI,arm_UI,arm_UI, // 148 - arm150,arm151,arm152,arm153,arm154,arm155,arm156,arm157, // 150 - arm150,arm_UI,arm152,arm15B,arm154,arm15D,arm156,arm15F, // 158 - arm160,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 160 - arm_UI,arm_UI,arm_UI,arm16B,arm_UI,arm_UI,arm_UI,arm_UI, // 168 - arm170,arm171,arm172,arm173,arm174,arm175,arm176,arm177, // 170 - arm170,arm_UI,arm172,arm17B,arm174,arm17D,arm176,arm17F, // 178 - arm180,arm181,arm182,arm183,arm184,arm185,arm186,arm187, // 180 - arm180,arm_UI,arm182,arm18B,arm184,arm_UI,arm186,arm_UI, // 188 - arm190,arm191,arm192,arm193,arm194,arm195,arm196,arm197, // 190 - arm190,arm_UI,arm192,arm19B,arm194,arm19D,arm196,arm19F, // 198 - arm1A0,arm1A1,arm1A2,arm1A3,arm1A4,arm1A5,arm1A6,arm1A7, // 1A0 - arm1A0,arm_UI,arm1A2,arm1AB,arm1A4,arm_UI,arm1A6,arm_UI, // 1A8 - arm1B0,arm1B1,arm1B2,arm1B3,arm1B4,arm1B5,arm1B6,arm1B7, // 1B0 - arm1B0,arm_UI,arm1B2,arm1BB,arm1B4,arm1BD,arm1B6,arm1BF, // 1B8 - arm1C0,arm1C1,arm1C2,arm1C3,arm1C4,arm1C5,arm1C6,arm1C7, // 1C0 - arm1C0,arm_UI,arm1C2,arm1CB,arm1C4,arm_UI,arm1C6,arm_UI, // 1C8 - arm1D0,arm1D1,arm1D2,arm1D3,arm1D4,arm1D5,arm1D6,arm1D7, // 1D0 - arm1D0,arm_UI,arm1D2,arm1DB,arm1D4,arm1DD,arm1D6,arm1DF, // 1D8 - arm1E0,arm1E1,arm1E2,arm1E3,arm1E4,arm1E5,arm1E6,arm1E7, // 1E0 - arm1E0,arm_UI,arm1E2,arm1EB,arm1E4,arm_UI,arm1E6,arm_UI, // 1E8 - arm1F0,arm1F1,arm1F2,arm1F3,arm1F4,arm1F5,arm1F6,arm1F7, // 1F0 - arm1F0,arm_UI,arm1F2,arm1FB,arm1F4,arm1FD,arm1F6,arm1FF, // 1F8 - - REP16(arm200),REP16(arm210),REP16(arm220),REP16(arm230), // 200 - REP16(arm240),REP16(arm250),REP16(arm260),REP16(arm270), // 240 - REP16(arm280),REP16(arm290),REP16(arm2A0),REP16(arm2B0), // 280 - REP16(arm2C0),REP16(arm2D0),REP16(arm2E0),REP16(arm2F0), // 2C0 - REP16(arm_UI),REP16(arm310),REP16(arm320),REP16(arm330), // 300 - REP16(arm_UI),REP16(arm350),REP16(arm360),REP16(arm370), // 340 - REP16(arm380),REP16(arm390),REP16(arm3A0),REP16(arm3B0), // 380 - REP16(arm3C0),REP16(arm3D0),REP16(arm3E0),REP16(arm3F0), // 3C0 - - REP16(arm400),REP16(arm410),REP16(arm400),REP16(arm410), // 400 - REP16(arm440),REP16(arm450),REP16(arm440),REP16(arm450), // 440 - REP16(arm480),REP16(arm490),REP16(arm480),REP16(arm490), // 480 - REP16(arm4C0),REP16(arm4D0),REP16(arm4C0),REP16(arm4D0), // 4C0 - REP16(arm500),REP16(arm510),REP16(arm520),REP16(arm530), // 500 - REP16(arm540),REP16(arm550),REP16(arm560),REP16(arm570), // 540 - REP16(arm580),REP16(arm590),REP16(arm5A0),REP16(arm5B0), // 580 - REP16(arm5C0),REP16(arm5D0),REP16(arm5E0),REP16(arm5F0), // 5C0 - - arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 600 - arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 608 - arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 610 - arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 618 - arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 620 - arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 628 - arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 630 - arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 638 - arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 640 - arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 648 - arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 650 - arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 658 - arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 660 - arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 668 - arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 670 - arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 678 - arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 680 - arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 688 - arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 690 - arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 698 - arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A0 - arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A8 - arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B0 - arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B8 - arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C0 - arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C8 - arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D0 - arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D8 - arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E0 - arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E8 - arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F0 - arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F8 - - arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 700 - arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 708 - arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 710 - arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 718 - arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 720 - arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 728 - arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 730 - arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 738 - arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 740 - arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 748 - arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 750 - arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 758 - arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 760 - arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 768 - arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 770 - arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 778 - arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 780 - arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 788 - arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 790 - arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 798 - arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A0 - arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A8 - arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B0 - arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B8 - arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C0 - arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C8 - arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D0 - arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D8 - arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E0 - arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E8 - arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_UI, // 7F0 - arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_BP, // 7F8 - - REP16(arm800),REP16(arm810),REP16(arm820),REP16(arm830), // 800 - REP16(arm840),REP16(arm850),REP16(arm860),REP16(arm870), // 840 - REP16(arm880),REP16(arm890),REP16(arm8A0),REP16(arm8B0), // 880 - REP16(arm8C0),REP16(arm8D0),REP16(arm8E0),REP16(arm8F0), // 8C0 - REP16(arm900),REP16(arm910),REP16(arm920),REP16(arm930), // 900 - REP16(arm940),REP16(arm950),REP16(arm960),REP16(arm970), // 940 - REP16(arm980),REP16(arm990),REP16(arm9A0),REP16(arm9B0), // 980 - REP16(arm9C0),REP16(arm9D0),REP16(arm9E0),REP16(arm9F0), // 9C0 - - REP256(armA00), // A00 - REP256(armB00), // B00 - REP256(arm_UI), // C00 - REP256(arm_UI), // D00 - - arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E00 - arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E08 - arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E10 - arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E18 - REP16(arm_UI), // E20 - REP16(arm_UI), // E30 - REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E40 - REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E80 - REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // EC0 - - REP256(armF00), // F00 -}; - -// Wrapper routine (execution loop) /////////////////////////////////////// - -#include -static void tester(void) { - static int ran=0;if(ran)return;ran=1; - FILE*f=fopen("p:\\timing.txt","w");if(!f)return; - for (int op=/*0*/9; op> 28; - bool cond_res = true; - if (UNLIKELY(cond != 0x0E)) { // most opcodes are AL (always) - switch(cond) { - case 0x00: // EQ - cond_res = Z_FLAG; - break; - case 0x01: // NE - cond_res = !Z_FLAG; - break; - case 0x02: // CS - cond_res = C_FLAG; - break; - case 0x03: // CC - cond_res = !C_FLAG; - break; - case 0x04: // MI - cond_res = N_FLAG; - break; - case 0x05: // PL - cond_res = !N_FLAG; - break; - case 0x06: // VS - cond_res = V_FLAG; - break; - case 0x07: // VC - cond_res = !V_FLAG; - break; - case 0x08: // HI - cond_res = C_FLAG && !Z_FLAG; - break; - case 0x09: // LS - cond_res = !C_FLAG || Z_FLAG; - break; - case 0x0A: // GE - cond_res = N_FLAG == V_FLAG; - break; - case 0x0B: // LT - cond_res = N_FLAG != V_FLAG; - break; - case 0x0C: // GT - cond_res = !Z_FLAG &&(N_FLAG == V_FLAG); - break; - case 0x0D: // LE - cond_res = Z_FLAG || (N_FLAG != V_FLAG); - break; - case 0x0E: // AL (impossible, checked above) - cond_res = true; - break; - case 0x0F: - default: - // ??? - cond_res = false; - break; - } - } - - if (cond_res) - (*armInsnTable[((opcode>>16)&0xFF0) | ((opcode>>4)&0x0F)])(opcode); -#ifdef INSN_COUNTER - count(opcode, cond_res); -#endif - if (clockTicks < 0) - return 0; - if (clockTicks == 0) - clockTicks = 1 + codeTicksAccessSeq32(oldArmNextPC); - cpuTotalTicks += clockTicks; - - } while (cpuTotalTicks -#include -#include -#include -#include - -#include "GBA.h" -#include "GBAcpu.h" -#include "GBAinline.h" -#include "../Globals.h" -#include "../EEprom.h" -#include "../Flash.h" -#include "../Sound.h" -#include "../Sram.h" -#include "../bios.h" -#include "../Cheats.h" -#include "../NLS.h" -#include "../elf.h" -#include "../Util.h" -#include "../Port.h" -#include "agbprint.h" -#ifdef PROFILING -#include "prof/prof.h" -#endif - -#ifdef _MSC_VER -#define snprintf _snprintf -#endif - -/////////////////////////////////////////////////////////////////////////// - -static int clockTicks; - -static INSN_REGPARM void thumbUnknownInsn(u32 opcode) -{ -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_UNDEFINED) - log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC-2); -#endif - CPUUndefinedException(); -} - -#ifdef BKPT_SUPPORT -static INSN_REGPARM void thumbBreakpoint(u32 opcode) -{ - extern void (*dbgSignal)(int,int); - reg[15].I -= 2; - armNextPC -= 2; - dbgSignal(5, opcode & 255); - clockTicks = -1; -} -#endif - -// Common macros ////////////////////////////////////////////////////////// - -#ifdef BKPT_SUPPORT -# define THUMB_CONSOLE_OUTPUT(a,b) do { \ - if ((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) { \ - extern void (*dbgOutput)(const char *, u32); \ - dbgOutput((a), (b)); \ - } \ -} while (0) -# define UPDATE_OLDREG do { \ - if (debugger_last) { \ - snprintf(oldbuffer, sizeof(oldbuffer), "%08X", \ - armState ? reg[15].I - 4 : reg[15].I - 2); \ - int i; \ - for (i = 0; i < 18; i++) { \ - oldreg[i] = reg[i].I; \ - } \ - } \ -} while (0) -#else -# define THUMB_CONSOLE_OUTPUT(a,b) -# define UPDATE_OLDREG -#endif - -#define NEG(i) ((i) >> 31) -#define POS(i) ((~(i)) >> 31) - -#ifndef C_CORE -#ifdef __GNUC__ -#ifdef __POWERPC__ - #define ADD_RD_RS_RN(N) \ - { \ - register int Flags; \ - register int Result; \ - asm volatile("addco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[source].I), \ - "r" (reg[N].I) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define ADD_RD_RS_O3(N) \ - { \ - register int Flags; \ - register int Result; \ - asm volatile("addco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[source].I), \ - "r" (N) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define ADD_RD_RS_O3_0 ADD_RD_RS_O3 - #define ADD_RN_O8(d) \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("addco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[(d)].I), \ - "r" (opcode & 255) \ - ); \ - reg[(d)].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define CMN_RD_RS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("addco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[dest].I), \ - "r" (value) \ - ); \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define ADC_RD_RS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("mtspr xer, %4\n" \ - "addeo. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[dest].I), \ - "r" (value), \ - "r" (C_FLAG << 29) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define SUB_RD_RS_RN(N) \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[source].I), \ - "r" (reg[N].I) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define SUB_RD_RS_O3(N) \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[source].I), \ - "r" (N) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define SUB_RD_RS_O3_0 SUB_RD_RS_O3 - #define SUB_RN_O8(d) \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[(d)].I), \ - "r" (opcode & 255) \ - ); \ - reg[(d)].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define CMP_RN_O8(d) \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[(d)].I), \ - "r" (opcode & 255) \ - ); \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define SBC_RD_RS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("mtspr xer, %4\n" \ - "subfeo. %0, %3, %2\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[dest].I), \ - "r" (value), \ - "r" (C_FLAG << 29) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define NEG_RD_RS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subfco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[source].I), \ - "r" (0) \ - ); \ - reg[dest].I = Result; \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } - #define CMP_RD_RS \ - {\ - register int Flags; \ - register int Result; \ - asm volatile("subco. %0, %2, %3\n" \ - "mcrxr cr1\n" \ - "mfcr %1\n" \ - : "=r" (Result), \ - "=r" (Flags) \ - : "r" (reg[dest].I), \ - "r" (value) \ - ); \ - Z_FLAG = (Flags >> 29) & 1; \ - N_FLAG = (Flags >> 31) & 1; \ - C_FLAG = (Flags >> 25) & 1; \ - V_FLAG = (Flags >> 26) & 1; \ - } -#else - #define ADD_RN_O8(d) \ - asm ("andl $0xFF, %%eax;"\ - "addl %%eax, %0;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setcb _C_FLAG;"\ - "setob _V_FLAG;"\ - : "=m" (reg[(d)].I)); - #define CMN_RD_RS \ - asm ("add %0, %1;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setcb _C_FLAG;"\ - "setob _V_FLAG;"\ - : \ - : "r" (value), "r" (reg[dest].I):"1"); - #define ADC_RD_RS \ - asm ("bt $0, _C_FLAG;"\ - "adc %1, %%ebx;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setcb _C_FLAG;"\ - "setob _V_FLAG;"\ - : "=b" (reg[dest].I)\ - : "r" (value), "b" (reg[dest].I)); - #define SUB_RN_O8(d) \ - asm ("andl $0xFF, %%eax;"\ - "subl %%eax, %0;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setncb _C_FLAG;"\ - "setob _V_FLAG;"\ - : "=m" (reg[(d)].I)); - #define MOV_RN_O8(d) \ - asm ("andl $0xFF, %%eax;"\ - "movb $0, _N_FLAG;"\ - "movl %%eax, %0;"\ - "setzb _Z_FLAG;"\ - : "=m" (reg[(d)].I)); - #define CMP_RN_O8(d) \ - asm ("andl $0xFF, %%eax;"\ - "cmpl %%eax, %0;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setncb _C_FLAG;"\ - "setob _V_FLAG;"\ - : \ - : "m" (reg[(d)].I)); - #define SBC_RD_RS \ - asm volatile ("bt $0, _C_FLAG;"\ - "cmc;"\ - "sbb %1, %%ebx;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setncb _C_FLAG;"\ - "setob _V_FLAG;"\ - : "=b" (reg[dest].I)\ - : "r" (value), "b" (reg[dest].I) : "cc", "memory"); - #define LSL_RD_RS \ - asm ("shl %%cl, %%eax;"\ - "setcb _C_FLAG;"\ - : "=a" (value)\ - : "a" (reg[dest].I), "c" (value)); - #define LSR_RD_RS \ - asm ("shr %%cl, %%eax;"\ - "setcb _C_FLAG;"\ - : "=a" (value)\ - : "a" (reg[dest].I), "c" (value)); - #define ASR_RD_RS \ - asm ("sar %%cl, %%eax;"\ - "setcb _C_FLAG;"\ - : "=a" (value)\ - : "a" (reg[dest].I), "c" (value)); - #define ROR_RD_RS \ - asm ("ror %%cl, %%eax;"\ - "setcb _C_FLAG;"\ - : "=a" (value)\ - : "a" (reg[dest].I), "c" (value)); - #define NEG_RD_RS \ - asm ("neg %%ebx;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setncb _C_FLAG;"\ - "setob _V_FLAG;"\ - : "=b" (reg[dest].I)\ - : "b" (reg[source].I)); - #define CMP_RD_RS \ - asm ("sub %0, %1;"\ - "setsb _N_FLAG;"\ - "setzb _Z_FLAG;"\ - "setncb _C_FLAG;"\ - "setob _V_FLAG;"\ - : \ - : "r" (value), "r" (reg[dest].I):"1"); - #define IMM5_INSN(OP,N) \ - asm("movl %%eax,%%ecx;" \ - "shrl $1,%%eax;" \ - "andl $7,%%ecx;" \ - "andl $0x1C,%%eax;" \ - "movl _reg(%%eax),%%edx;" \ - OP \ - "setsb _N_FLAG;" \ - "setzb _Z_FLAG;" \ - "movl %%edx,_reg(,%%ecx,4);" \ - : : "i" (N)) - #define IMM5_INSN_0(OP) \ - asm("movl %%eax,%%ecx;" \ - "shrl $1,%%eax;" \ - "andl $7,%%ecx;" \ - "andl $0x1C,%%eax;" \ - "movl _reg(%%eax),%%edx;" \ - OP \ - "setsb _N_FLAG;" \ - "setzb _Z_FLAG;" \ - "movl %%edx,_reg(,%%ecx,4);" \ - : : ) - #define IMM5_LSL \ - "shll %0,%%edx;"\ - "setcb _C_FLAG;" - #define IMM5_LSL_0 \ - "testl %%edx,%%edx;" - #define IMM5_LSR \ - "shrl %0,%%edx;"\ - "setcb _C_FLAG;" - #define IMM5_LSR_0 \ - "testl %%edx,%%edx;"\ - "setsb _C_FLAG;"\ - "xorl %%edx,%%edx;" - #define IMM5_ASR \ - "sarl %0,%%edx;"\ - "setcb _C_FLAG;" - #define IMM5_ASR_0 \ - "sarl $31,%%edx;"\ - "setsb _C_FLAG;" - #define THREEARG_INSN(OP,N) \ - asm("movl %%eax,%%edx;" \ - "shrl $1,%%edx;" \ - "andl $0x1C,%%edx;" \ - "andl $7,%%eax;" \ - "movl _reg(%%edx),%%ecx;" \ - OP(N) \ - "setsb _N_FLAG;" \ - "setzb _Z_FLAG;" \ - "movl %%ecx,_reg(,%%eax,4)"::) - #define ADD_RD_RS_RN(N) \ - "add (_reg+"#N"*4),%%ecx;" \ - "setcb _C_FLAG;" \ - "setob _V_FLAG;" - #define ADD_RD_RS_O3(N) \ - "add $"#N",%%ecx;" \ - "setcb _C_FLAG;" \ - "setob _V_FLAG;" - #define ADD_RD_RS_O3_0(N) \ - "movb $0,_C_FLAG;" \ - "add $0,%%ecx;" \ - "movb $0,_V_FLAG;" - #define SUB_RD_RS_RN(N) \ - "sub (_reg+"#N"*4),%%ecx;" \ - "setncb _C_FLAG;" \ - "setob _V_FLAG;" - #define SUB_RD_RS_O3(N) \ - "sub $"#N",%%ecx;" \ - "setncb _C_FLAG;" \ - "setob _V_FLAG;" - #define SUB_RD_RS_O3_0(N) \ - "movb $1,_C_FLAG;" \ - "sub $0,%%ecx;" \ - "movb $0,_V_FLAG;" -#endif -#else // !__GNUC__ - #define ADD_RD_RS_RN(N) \ - {\ - __asm mov eax, source\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm add ebx, dword ptr [OFFSET reg+4*N]\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define ADD_RD_RS_O3(N) \ - {\ - __asm mov eax, source\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm add ebx, N\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define ADD_RD_RS_O3_0 \ - {\ - __asm mov eax, source\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm add ebx, 0\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm mov byte ptr C_FLAG, 0\ - __asm mov byte ptr V_FLAG, 0\ - } - #define ADD_RN_O8(d) \ - {\ - __asm mov ebx, opcode\ - __asm and ebx, 255\ - __asm add dword ptr [OFFSET reg+4*(d)], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define CMN_RD_RS \ - {\ - __asm mov eax, dest\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm add ebx, value\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define ADC_RD_RS \ - {\ - __asm mov ebx, dest\ - __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\ - __asm bt word ptr C_FLAG, 0\ - __asm adc ebx, value\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define SUB_RD_RS_RN(N) \ - {\ - __asm mov eax, source\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm sub ebx, dword ptr [OFFSET reg+4*N]\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setnc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define SUB_RD_RS_O3(N) \ - {\ - __asm mov eax, source\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm sub ebx, N\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setnc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define SUB_RD_RS_O3_0 \ - {\ - __asm mov eax, source\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm sub ebx, 0\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm mov byte ptr C_FLAG, 1\ - __asm mov byte ptr V_FLAG, 0\ - } - #define SUB_RN_O8(d) \ - {\ - __asm mov ebx, opcode\ - __asm and ebx, 255\ - __asm sub dword ptr [OFFSET reg + 4*(d)], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setnc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define MOV_RN_O8(d) \ - {\ - __asm mov eax, opcode\ - __asm and eax, 255\ - __asm mov dword ptr [OFFSET reg+4*(d)], eax\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - } - #define CMP_RN_O8(d) \ - {\ - __asm mov eax, dword ptr [OFFSET reg+4*(d)]\ - __asm mov ebx, opcode\ - __asm and ebx, 255\ - __asm sub eax, ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setnc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define SBC_RD_RS \ - {\ - __asm mov ebx, dest\ - __asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\ - __asm mov eax, value\ - __asm bt word ptr C_FLAG, 0\ - __asm cmc\ - __asm sbb ebx, eax\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg + 4*eax], ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setnc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define LSL_RD_RM_I5 \ - {\ - __asm mov eax, source\ - __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\ - __asm mov cl, byte ptr shift\ - __asm shl eax, cl\ - __asm mov value, eax\ - __asm setc byte ptr C_FLAG\ - } - #define LSL_RD_RS \ - {\ - __asm mov eax, dest\ - __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\ - __asm mov cl, byte ptr value\ - __asm shl eax, cl\ - __asm mov value, eax\ - __asm setc byte ptr C_FLAG\ - } - #define LSR_RD_RM_I5 \ - {\ - __asm mov eax, source\ - __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\ - __asm mov cl, byte ptr shift\ - __asm shr eax, cl\ - __asm mov value, eax\ - __asm setc byte ptr C_FLAG\ - } - #define LSR_RD_RS \ - {\ - __asm mov eax, dest\ - __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\ - __asm mov cl, byte ptr value\ - __asm shr eax, cl\ - __asm mov value, eax\ - __asm setc byte ptr C_FLAG\ - } - #define ASR_RD_RM_I5 \ - {\ - __asm mov eax, source\ - __asm mov eax, dword ptr [OFFSET reg + 4*eax]\ - __asm mov cl, byte ptr shift\ - __asm sar eax, cl\ - __asm mov value, eax\ - __asm setc byte ptr C_FLAG\ - } - #define ASR_RD_RS \ - {\ - __asm mov eax, dest\ - __asm mov eax, dword ptr [OFFSET reg + 4*eax]\ - __asm mov cl, byte ptr value\ - __asm sar eax, cl\ - __asm mov value, eax\ - __asm setc byte ptr C_FLAG\ - } - #define ROR_RD_RS \ - {\ - __asm mov eax, dest\ - __asm mov eax, dword ptr [OFFSET reg + 4*eax]\ - __asm mov cl, byte ptr value\ - __asm ror eax, cl\ - __asm mov value, eax\ - __asm setc byte ptr C_FLAG\ - } - #define NEG_RD_RS \ - {\ - __asm mov ebx, source\ - __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\ - __asm neg ebx\ - __asm mov eax, dest\ - __asm mov dword ptr [OFFSET reg+4*eax],ebx\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setnc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } - #define CMP_RD_RS \ - {\ - __asm mov eax, dest\ - __asm mov ebx, dword ptr [OFFSET reg+4*eax]\ - __asm sub ebx, value\ - __asm sets byte ptr N_FLAG\ - __asm setz byte ptr Z_FLAG\ - __asm setnc byte ptr C_FLAG\ - __asm seto byte ptr V_FLAG\ - } -#endif -#endif - -// C core -#ifndef ADDCARRY - #define ADDCARRY(a, b, c) \ - C_FLAG = ((NEG(a) & NEG(b)) |\ - (NEG(a) & POS(c)) |\ - (NEG(b) & POS(c))) ? true : false; -#endif -#ifndef ADDOVERFLOW - #define ADDOVERFLOW(a, b, c) \ - V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\ - (POS(a) & POS(b) & NEG(c))) ? true : false; -#endif -#ifndef SUBCARRY - #define SUBCARRY(a, b, c) \ - C_FLAG = ((NEG(a) & POS(b)) |\ - (NEG(a) & POS(c)) |\ - (POS(b) & POS(c))) ? true : false; -#endif -#ifndef SUBOVERFLOW - #define SUBOVERFLOW(a, b, c)\ - V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\ - (POS(a) & NEG(b) & NEG(c))) ? true : false; -#endif -#ifndef ADD_RD_RS_RN - #define ADD_RD_RS_RN(N) \ - {\ - u32 lhs = reg[source].I;\ - u32 rhs = reg[N].I;\ - u32 res = lhs + rhs;\ - reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef ADD_RD_RS_O3 - #define ADD_RD_RS_O3(N) \ - {\ - u32 lhs = reg[source].I;\ - u32 rhs = N;\ - u32 res = lhs + rhs;\ - reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef ADD_RD_RS_O3_0 -# define ADD_RD_RS_O3_0 ADD_RD_RS_O3 -#endif -#ifndef ADD_RN_O8 - #define ADD_RN_O8(d) \ - {\ - u32 lhs = reg[(d)].I;\ - u32 rhs = (opcode & 255);\ - u32 res = lhs + rhs;\ - reg[(d)].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef CMN_RD_RS - #define CMN_RD_RS \ - {\ - u32 lhs = reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs + rhs;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef ADC_RD_RS - #define ADC_RD_RS \ - {\ - u32 lhs = reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs + rhs + (u32)C_FLAG;\ - reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef SUB_RD_RS_RN - #define SUB_RD_RS_RN(N) \ - {\ - u32 lhs = reg[source].I;\ - u32 rhs = reg[N].I;\ - u32 res = lhs - rhs;\ - reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef SUB_RD_RS_O3 - #define SUB_RD_RS_O3(N) \ - {\ - u32 lhs = reg[source].I;\ - u32 rhs = N;\ - u32 res = lhs - rhs;\ - reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef SUB_RD_RS_O3_0 -# define SUB_RD_RS_O3_0 SUB_RD_RS_O3 -#endif -#ifndef SUB_RN_O8 - #define SUB_RN_O8(d) \ - {\ - u32 lhs = reg[(d)].I;\ - u32 rhs = (opcode & 255);\ - u32 res = lhs - rhs;\ - reg[(d)].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef MOV_RN_O8 - #define MOV_RN_O8(d) \ - {\ - reg[d].I = opcode & 255;\ - N_FLAG = false;\ - Z_FLAG = (reg[d].I ? false : true);\ - } -#endif -#ifndef CMP_RN_O8 - #define CMP_RN_O8(d) \ - {\ - u32 lhs = reg[(d)].I;\ - u32 rhs = (opcode & 255);\ - u32 res = lhs - rhs;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef SBC_RD_RS - #define SBC_RD_RS \ - {\ - u32 lhs = reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs - rhs - !((u32)C_FLAG);\ - reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef LSL_RD_RM_I5 - #define LSL_RD_RM_I5 \ - {\ - C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false;\ - value = reg[source].I << shift;\ - } -#endif -#ifndef LSL_RD_RS - #define LSL_RD_RS \ - {\ - C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false;\ - value = reg[dest].I << value;\ - } -#endif -#ifndef LSR_RD_RM_I5 - #define LSR_RD_RM_I5 \ - {\ - C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false;\ - value = reg[source].I >> shift;\ - } -#endif -#ifndef LSR_RD_RS - #define LSR_RD_RS \ - {\ - C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\ - value = reg[dest].I >> value;\ - } -#endif -#ifndef ASR_RD_RM_I5 - #define ASR_RD_RM_I5 \ - {\ - C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\ - value = (s32)reg[source].I >> (int)shift;\ - } -#endif -#ifndef ASR_RD_RS - #define ASR_RD_RS \ - {\ - C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\ - value = (s32)reg[dest].I >> (int)value;\ - } -#endif -#ifndef ROR_RD_RS - #define ROR_RD_RS \ - {\ - C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\ - value = ((reg[dest].I << (32 - value)) |\ - (reg[dest].I >> value));\ - } -#endif -#ifndef NEG_RD_RS - #define NEG_RD_RS \ - {\ - u32 lhs = reg[source].I;\ - u32 rhs = 0;\ - u32 res = rhs - lhs;\ - reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(rhs, lhs, res);\ - SUBOVERFLOW(rhs, lhs, res);\ - } -#endif -#ifndef CMP_RD_RS - #define CMP_RD_RS \ - {\ - u32 lhs = reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs - rhs;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef IMM5_INSN - #define IMM5_INSN(OP,N) \ - int dest = opcode & 0x07;\ - int source = (opcode >> 3) & 0x07;\ - u32 value;\ - OP(N);\ - reg[dest].I = value;\ - N_FLAG = (value & 0x80000000 ? true : false);\ - Z_FLAG = (value ? false : true); - #define IMM5_INSN_0(OP) \ - int dest = opcode & 0x07;\ - int source = (opcode >> 3) & 0x07;\ - u32 value;\ - OP;\ - reg[dest].I = value;\ - N_FLAG = (value & 0x80000000 ? true : false);\ - Z_FLAG = (value ? false : true); - #define IMM5_LSL(N) \ - int shift = N;\ - LSL_RD_RM_I5; - #define IMM5_LSL_0 \ - value = reg[source].I; - #define IMM5_LSR(N) \ - int shift = N;\ - LSR_RD_RM_I5; - #define IMM5_LSR_0 \ - C_FLAG = reg[source].I & 0x80000000 ? true : false;\ - value = 0; - #define IMM5_ASR(N) \ - int shift = N;\ - ASR_RD_RM_I5; - #define IMM5_ASR_0 \ - if(reg[source].I & 0x80000000) {\ - value = 0xFFFFFFFF;\ - C_FLAG = true;\ - } else {\ - value = 0;\ - C_FLAG = false;\ - } -#endif -#ifndef THREEARG_INSN - #define THREEARG_INSN(OP,N) \ - int dest = opcode & 0x07; \ - int source = (opcode >> 3) & 0x07; \ - OP(N); -#endif - -// Shift instructions ///////////////////////////////////////////////////// - -#define DEFINE_IMM5_INSN(OP,BASE) \ - static INSN_REGPARM void thumb##BASE##_00(u32 opcode) { IMM5_INSN_0(OP##_0); } \ - static INSN_REGPARM void thumb##BASE##_01(u32 opcode) { IMM5_INSN(OP, 1); } \ - static INSN_REGPARM void thumb##BASE##_02(u32 opcode) { IMM5_INSN(OP, 2); } \ - static INSN_REGPARM void thumb##BASE##_03(u32 opcode) { IMM5_INSN(OP, 3); } \ - static INSN_REGPARM void thumb##BASE##_04(u32 opcode) { IMM5_INSN(OP, 4); } \ - static INSN_REGPARM void thumb##BASE##_05(u32 opcode) { IMM5_INSN(OP, 5); } \ - static INSN_REGPARM void thumb##BASE##_06(u32 opcode) { IMM5_INSN(OP, 6); } \ - static INSN_REGPARM void thumb##BASE##_07(u32 opcode) { IMM5_INSN(OP, 7); } \ - static INSN_REGPARM void thumb##BASE##_08(u32 opcode) { IMM5_INSN(OP, 8); } \ - static INSN_REGPARM void thumb##BASE##_09(u32 opcode) { IMM5_INSN(OP, 9); } \ - static INSN_REGPARM void thumb##BASE##_0A(u32 opcode) { IMM5_INSN(OP,10); } \ - static INSN_REGPARM void thumb##BASE##_0B(u32 opcode) { IMM5_INSN(OP,11); } \ - static INSN_REGPARM void thumb##BASE##_0C(u32 opcode) { IMM5_INSN(OP,12); } \ - static INSN_REGPARM void thumb##BASE##_0D(u32 opcode) { IMM5_INSN(OP,13); } \ - static INSN_REGPARM void thumb##BASE##_0E(u32 opcode) { IMM5_INSN(OP,14); } \ - static INSN_REGPARM void thumb##BASE##_0F(u32 opcode) { IMM5_INSN(OP,15); } \ - static INSN_REGPARM void thumb##BASE##_10(u32 opcode) { IMM5_INSN(OP,16); } \ - static INSN_REGPARM void thumb##BASE##_11(u32 opcode) { IMM5_INSN(OP,17); } \ - static INSN_REGPARM void thumb##BASE##_12(u32 opcode) { IMM5_INSN(OP,18); } \ - static INSN_REGPARM void thumb##BASE##_13(u32 opcode) { IMM5_INSN(OP,19); } \ - static INSN_REGPARM void thumb##BASE##_14(u32 opcode) { IMM5_INSN(OP,20); } \ - static INSN_REGPARM void thumb##BASE##_15(u32 opcode) { IMM5_INSN(OP,21); } \ - static INSN_REGPARM void thumb##BASE##_16(u32 opcode) { IMM5_INSN(OP,22); } \ - static INSN_REGPARM void thumb##BASE##_17(u32 opcode) { IMM5_INSN(OP,23); } \ - static INSN_REGPARM void thumb##BASE##_18(u32 opcode) { IMM5_INSN(OP,24); } \ - static INSN_REGPARM void thumb##BASE##_19(u32 opcode) { IMM5_INSN(OP,25); } \ - static INSN_REGPARM void thumb##BASE##_1A(u32 opcode) { IMM5_INSN(OP,26); } \ - static INSN_REGPARM void thumb##BASE##_1B(u32 opcode) { IMM5_INSN(OP,27); } \ - static INSN_REGPARM void thumb##BASE##_1C(u32 opcode) { IMM5_INSN(OP,28); } \ - static INSN_REGPARM void thumb##BASE##_1D(u32 opcode) { IMM5_INSN(OP,29); } \ - static INSN_REGPARM void thumb##BASE##_1E(u32 opcode) { IMM5_INSN(OP,30); } \ - static INSN_REGPARM void thumb##BASE##_1F(u32 opcode) { IMM5_INSN(OP,31); } - -// LSL Rd, Rm, #Imm 5 -DEFINE_IMM5_INSN(IMM5_LSL,00) -// LSR Rd, Rm, #Imm 5 -DEFINE_IMM5_INSN(IMM5_LSR,08) -// ASR Rd, Rm, #Imm 5 -DEFINE_IMM5_INSN(IMM5_ASR,10) - -// 3-argument ADD/SUB ///////////////////////////////////////////////////// - -#define DEFINE_REG3_INSN(OP,BASE) \ - static INSN_REGPARM void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP,0); } \ - static INSN_REGPARM void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \ - static INSN_REGPARM void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \ - static INSN_REGPARM void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \ - static INSN_REGPARM void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \ - static INSN_REGPARM void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \ - static INSN_REGPARM void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \ - static INSN_REGPARM void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); } - -#define DEFINE_IMM3_INSN(OP,BASE) \ - static INSN_REGPARM void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP##_0,0); } \ - static INSN_REGPARM void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \ - static INSN_REGPARM void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \ - static INSN_REGPARM void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \ - static INSN_REGPARM void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \ - static INSN_REGPARM void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \ - static INSN_REGPARM void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \ - static INSN_REGPARM void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); } - -// ADD Rd, Rs, Rn -DEFINE_REG3_INSN(ADD_RD_RS_RN,18) -// SUB Rd, Rs, Rn -DEFINE_REG3_INSN(SUB_RD_RS_RN,1A) -// ADD Rd, Rs, #Offset3 -DEFINE_IMM3_INSN(ADD_RD_RS_O3,1C) -// SUB Rd, Rs, #Offset3 -DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E) - -// MOV/CMP/ADD/SUB immediate ////////////////////////////////////////////// - -// MOV R0, #Offset8 -static INSN_REGPARM void thumb20(u32 opcode) { MOV_RN_O8(0); } -// MOV R1, #Offset8 -static INSN_REGPARM void thumb21(u32 opcode) { MOV_RN_O8(1); } -// MOV R2, #Offset8 -static INSN_REGPARM void thumb22(u32 opcode) { MOV_RN_O8(2); } -// MOV R3, #Offset8 -static INSN_REGPARM void thumb23(u32 opcode) { MOV_RN_O8(3); } -// MOV R4, #Offset8 -static INSN_REGPARM void thumb24(u32 opcode) { MOV_RN_O8(4); } -// MOV R5, #Offset8 -static INSN_REGPARM void thumb25(u32 opcode) { MOV_RN_O8(5); } -// MOV R6, #Offset8 -static INSN_REGPARM void thumb26(u32 opcode) { MOV_RN_O8(6); } -// MOV R7, #Offset8 -static INSN_REGPARM void thumb27(u32 opcode) { MOV_RN_O8(7); } - -// CMP R0, #Offset8 -static INSN_REGPARM void thumb28(u32 opcode) { CMP_RN_O8(0); } -// CMP R1, #Offset8 -static INSN_REGPARM void thumb29(u32 opcode) { CMP_RN_O8(1); } -// CMP R2, #Offset8 -static INSN_REGPARM void thumb2A(u32 opcode) { CMP_RN_O8(2); } -// CMP R3, #Offset8 -static INSN_REGPARM void thumb2B(u32 opcode) { CMP_RN_O8(3); } -// CMP R4, #Offset8 -static INSN_REGPARM void thumb2C(u32 opcode) { CMP_RN_O8(4); } -// CMP R5, #Offset8 -static INSN_REGPARM void thumb2D(u32 opcode) { CMP_RN_O8(5); } -// CMP R6, #Offset8 -static INSN_REGPARM void thumb2E(u32 opcode) { CMP_RN_O8(6); } -// CMP R7, #Offset8 -static INSN_REGPARM void thumb2F(u32 opcode) { CMP_RN_O8(7); } - -// ADD R0,#Offset8 -static INSN_REGPARM void thumb30(u32 opcode) { ADD_RN_O8(0); } -// ADD R1,#Offset8 -static INSN_REGPARM void thumb31(u32 opcode) { ADD_RN_O8(1); } -// ADD R2,#Offset8 -static INSN_REGPARM void thumb32(u32 opcode) { ADD_RN_O8(2); } -// ADD R3,#Offset8 -static INSN_REGPARM void thumb33(u32 opcode) { ADD_RN_O8(3); } -// ADD R4,#Offset8 -static INSN_REGPARM void thumb34(u32 opcode) { ADD_RN_O8(4); } -// ADD R5,#Offset8 -static INSN_REGPARM void thumb35(u32 opcode) { ADD_RN_O8(5); } -// ADD R6,#Offset8 -static INSN_REGPARM void thumb36(u32 opcode) { ADD_RN_O8(6); } -// ADD R7,#Offset8 -static INSN_REGPARM void thumb37(u32 opcode) { ADD_RN_O8(7); } - -// SUB R0,#Offset8 -static INSN_REGPARM void thumb38(u32 opcode) { SUB_RN_O8(0); } -// SUB R1,#Offset8 -static INSN_REGPARM void thumb39(u32 opcode) { SUB_RN_O8(1); } -// SUB R2,#Offset8 -static INSN_REGPARM void thumb3A(u32 opcode) { SUB_RN_O8(2); } -// SUB R3,#Offset8 -static INSN_REGPARM void thumb3B(u32 opcode) { SUB_RN_O8(3); } -// SUB R4,#Offset8 -static INSN_REGPARM void thumb3C(u32 opcode) { SUB_RN_O8(4); } -// SUB R5,#Offset8 -static INSN_REGPARM void thumb3D(u32 opcode) { SUB_RN_O8(5); } -// SUB R6,#Offset8 -static INSN_REGPARM void thumb3E(u32 opcode) { SUB_RN_O8(6); } -// SUB R7,#Offset8 -static INSN_REGPARM void thumb3F(u32 opcode) { SUB_RN_O8(7); } - -// ALU operations ///////////////////////////////////////////////////////// - -// AND Rd, Rs -static INSN_REGPARM void thumb40_0(u32 opcode) -{ - int dest = opcode & 7; - reg[dest].I &= reg[(opcode >> 3)&7].I; - N_FLAG = reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = reg[dest].I ? false : true; - THUMB_CONSOLE_OUTPUT(NULL, reg[2].I); -} - -// EOR Rd, Rs -static INSN_REGPARM void thumb40_1(u32 opcode) -{ - int dest = opcode & 7; - reg[dest].I ^= reg[(opcode >> 3)&7].I; - N_FLAG = reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = reg[dest].I ? false : true; -} - -// LSL Rd, Rs -static INSN_REGPARM void thumb40_2(u32 opcode) -{ - int dest = opcode & 7; - u32 value = reg[(opcode >> 3)&7].B.B0; - if(value) { - if(value == 32) { - value = 0; - C_FLAG = (reg[dest].I & 1 ? true : false); - } else if(value < 32) { - LSL_RD_RS; - } else { - value = 0; - C_FLAG = false; - } - reg[dest].I = value; - } - N_FLAG = reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = reg[dest].I ? false : true; - clockTicks = codeTicksAccess16(armNextPC)+2; -} - -// LSR Rd, Rs -static INSN_REGPARM void thumb40_3(u32 opcode) -{ - int dest = opcode & 7; - u32 value = reg[(opcode >> 3)&7].B.B0; - if(value) { - if(value == 32) { - value = 0; - C_FLAG = (reg[dest].I & 0x80000000 ? true : false); - } else if(value < 32) { - LSR_RD_RS; - } else { - value = 0; - C_FLAG = false; - } - reg[dest].I = value; - } - N_FLAG = reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = reg[dest].I ? false : true; - clockTicks = codeTicksAccess16(armNextPC)+2; -} - -// ASR Rd, Rs -static INSN_REGPARM void thumb41_0(u32 opcode) -{ - int dest = opcode & 7; - u32 value = reg[(opcode >> 3)&7].B.B0; - if(value) { - if(value < 32) { - ASR_RD_RS; - reg[dest].I = value; - } else { - if(reg[dest].I & 0x80000000){ - reg[dest].I = 0xFFFFFFFF; - C_FLAG = true; - } else { - reg[dest].I = 0x00000000; - C_FLAG = false; - } - } - } - N_FLAG = reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = reg[dest].I ? false : true; - clockTicks = codeTicksAccess16(armNextPC)+2; -} - -// ADC Rd, Rs -static INSN_REGPARM void thumb41_1(u32 opcode) -{ - int dest = opcode & 0x07; - u32 value = reg[(opcode >> 3)&7].I; - ADC_RD_RS; -} - -// SBC Rd, Rs -static INSN_REGPARM void thumb41_2(u32 opcode) -{ - int dest = opcode & 0x07; - u32 value = reg[(opcode >> 3)&7].I; - SBC_RD_RS; -} - -// ROR Rd, Rs -static INSN_REGPARM void thumb41_3(u32 opcode) -{ - int dest = opcode & 7; - u32 value = reg[(opcode >> 3)&7].B.B0; - - if(value) { - value = value & 0x1f; - if(value == 0) { - C_FLAG = (reg[dest].I & 0x80000000 ? true : false); - } else { - ROR_RD_RS; - reg[dest].I = value; - } - } - clockTicks = codeTicksAccess16(armNextPC)+2; - N_FLAG = reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = reg[dest].I ? false : true; -} - -// TST Rd, Rs -static INSN_REGPARM void thumb42_0(u32 opcode) -{ - u32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I; - N_FLAG = value & 0x80000000 ? true : false; - Z_FLAG = value ? false : true; -} - -// NEG Rd, Rs -static INSN_REGPARM void thumb42_1(u32 opcode) -{ - int dest = opcode & 7; - int source = (opcode >> 3) & 7; - NEG_RD_RS; -} - -// CMP Rd, Rs -static INSN_REGPARM void thumb42_2(u32 opcode) -{ - int dest = opcode & 7; - u32 value = reg[(opcode >> 3)&7].I; - CMP_RD_RS; -} - -// CMN Rd, Rs -static INSN_REGPARM void thumb42_3(u32 opcode) -{ - int dest = opcode & 7; - u32 value = reg[(opcode >> 3)&7].I; - CMN_RD_RS; -} - -// ORR Rd, Rs -static INSN_REGPARM void thumb43_0(u32 opcode) -{ - int dest = opcode & 7; - reg[dest].I |= reg[(opcode >> 3) & 7].I; - Z_FLAG = reg[dest].I ? false : true; - N_FLAG = reg[dest].I & 0x80000000 ? true : false; -} - -// MUL Rd, Rs -static INSN_REGPARM void thumb43_1(u32 opcode) -{ - clockTicks = 1; - int dest = opcode & 7; - u32 rm = reg[dest].I; - reg[dest].I = reg[(opcode >> 3) & 7].I * rm; - if (((s32)rm) < 0) - rm = ~rm; - if ((rm & 0xFFFFFF00) == 0) - clockTicks += 0; - else if ((rm & 0xFFFF0000) == 0) - clockTicks += 1; - else if ((rm & 0xFF000000) == 0) - clockTicks += 2; - else - clockTicks += 3; - busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); - clockTicks += codeTicksAccess16(armNextPC) + 1; - Z_FLAG = reg[dest].I ? false : true; - N_FLAG = reg[dest].I & 0x80000000 ? true : false; -} - -// BIC Rd, Rs -static INSN_REGPARM void thumb43_2(u32 opcode) -{ - int dest = opcode & 7; - reg[dest].I &= (~reg[(opcode >> 3) & 7].I); - Z_FLAG = reg[dest].I ? false : true; - N_FLAG = reg[dest].I & 0x80000000 ? true : false; -} - -// MVN Rd, Rs -static INSN_REGPARM void thumb43_3(u32 opcode) -{ - int dest = opcode & 7; - reg[dest].I = ~reg[(opcode >> 3) & 7].I; - Z_FLAG = reg[dest].I ? false : true; - N_FLAG = reg[dest].I & 0x80000000 ? true : false; -} - -// High-register instructions and BX ////////////////////////////////////// - -// ADD Rd, Hs -static INSN_REGPARM void thumb44_1(u32 opcode) -{ - reg[opcode&7].I += reg[((opcode>>3)&7)+8].I; -} - -// ADD Hd, Rs -static INSN_REGPARM void thumb44_2(u32 opcode) -{ - reg[(opcode&7)+8].I += reg[(opcode>>3)&7].I; - if((opcode&7) == 7) { - reg[15].I &= 0xFFFFFFFE; - armNextPC = reg[15].I; - reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC)*2 - + codeTicksAccess16(armNextPC) + 3; - } -} - -// ADD Hd, Hs -static INSN_REGPARM void thumb44_3(u32 opcode) -{ - reg[(opcode&7)+8].I += reg[((opcode>>3)&7)+8].I; - if((opcode&7) == 7) { - reg[15].I &= 0xFFFFFFFE; - armNextPC = reg[15].I; - reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC)*2 - + codeTicksAccess16(armNextPC) + 3; - } -} - -// CMP Rd, Hs -static INSN_REGPARM void thumb45_1(u32 opcode) -{ - int dest = opcode & 7; - u32 value = reg[((opcode>>3)&7)+8].I; - CMP_RD_RS; -} - -// CMP Hd, Rs -static INSN_REGPARM void thumb45_2(u32 opcode) -{ - int dest = (opcode & 7) + 8; - u32 value = reg[(opcode>>3)&7].I; - CMP_RD_RS; -} - -// CMP Hd, Hs -static INSN_REGPARM void thumb45_3(u32 opcode) -{ - int dest = (opcode & 7) + 8; - u32 value = reg[((opcode>>3)&7)+8].I; - CMP_RD_RS; -} - -// MOV Rd, Hs -static INSN_REGPARM void thumb46_1(u32 opcode) -{ - reg[opcode&7].I = reg[((opcode>>3)&7)+8].I; -} - -// MOV Hd, Rs -static INSN_REGPARM void thumb46_2(u32 opcode) -{ - reg[(opcode&7)+8].I = reg[(opcode>>3)&7].I; - if((opcode&7) == 7) { - UPDATE_OLDREG; - reg[15].I &= 0xFFFFFFFE; - armNextPC = reg[15].I; - reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC)*2 - + codeTicksAccess16(armNextPC) + 3; - } -} - -// MOV Hd, Hs -static INSN_REGPARM void thumb46_3(u32 opcode) -{ - reg[(opcode&7)+8].I = reg[((opcode>>3)&7)+8].I; - if((opcode&7) == 7) { - UPDATE_OLDREG; - reg[15].I &= 0xFFFFFFFE; - armNextPC = reg[15].I; - reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC)*2 - + codeTicksAccess16(armNextPC) + 3; - } -} - - -// BX Rs -static INSN_REGPARM void thumb47(u32 opcode) -{ - int base = (opcode >> 3) & 15; - busPrefetchCount=0; - UPDATE_OLDREG; - reg[15].I = reg[base].I; - if(reg[base].I & 1) { - armState = false; - reg[15].I &= 0xFFFFFFFE; - armNextPC = reg[15].I; - reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) - + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3; - } else { - armState = true; - reg[15].I &= 0xFFFFFFFC; - armNextPC = reg[15].I; - reg[15].I += 4; - ARM_PREFETCH; - clockTicks = codeTicksAccessSeq32(armNextPC) - + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3; - } -} - -// Load/store instructions //////////////////////////////////////////////// - -// LDR R0~R7,[PC, #Imm] -static INSN_REGPARM void thumb48(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[regist].I = CPUReadMemoryQuick(address); - busPrefetchCount=0; - clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC); -} - -// STR Rd, [Rs, Rn] -static INSN_REGPARM void thumb50(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - CPUWriteMemory(address, reg[opcode & 7].I); - clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2; -} - -// STRH Rd, [Rs, Rn] -static INSN_REGPARM void thumb52(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - CPUWriteHalfWord(address, reg[opcode&7].W.W0); - clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; -} - -// STRB Rd, [Rs, Rn] -static INSN_REGPARM void thumb54(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I; - CPUWriteByte(address, reg[opcode & 7].B.B0); - clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; -} - -// LDSB Rd, [Rs, Rn] -static INSN_REGPARM void thumb56(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - reg[opcode&7].I = (s8)CPUReadByte(address); - clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC); -} - -// LDR Rd, [Rs, Rn] -static INSN_REGPARM void thumb58(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - reg[opcode&7].I = CPUReadMemory(address); - clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC); -} - -// LDRH Rd, [Rs, Rn] -static INSN_REGPARM void thumb5A(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - reg[opcode&7].I = CPUReadHalfWord(address); - clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC); -} - -// LDRB Rd, [Rs, Rn] -static INSN_REGPARM void thumb5C(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - reg[opcode&7].I = CPUReadByte(address); - clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC); -} - -// LDSH Rd, [Rs, Rn] -static INSN_REGPARM void thumb5E(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address); - clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC); -} - -// STR Rd, [Rs, #Imm] -static INSN_REGPARM void thumb60(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); - CPUWriteMemory(address, reg[opcode&7].I); - clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2; -} - -// LDR Rd, [Rs, #Imm] -static INSN_REGPARM void thumb68(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); - reg[opcode&7].I = CPUReadMemory(address); - clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC); -} - -// STRB Rd, [Rs, #Imm] -static INSN_REGPARM void thumb70(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)); - CPUWriteByte(address, reg[opcode&7].B.B0); - clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; -} - -// LDRB Rd, [Rs, #Imm] -static INSN_REGPARM void thumb78(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)); - reg[opcode&7].I = CPUReadByte(address); - clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC); -} - -// STRH Rd, [Rs, #Imm] -static INSN_REGPARM void thumb80(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); - CPUWriteHalfWord(address, reg[opcode&7].W.W0); - clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; -} - -// LDRH Rd, [Rs, #Imm] -static INSN_REGPARM void thumb88(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); - reg[opcode&7].I = CPUReadHalfWord(address); - clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC); -} - -// STR R0~R7, [SP, #Imm] -static INSN_REGPARM void thumb90(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[regist].I); - clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2; -} - -// LDR R0~R7, [SP, #Imm] -static INSN_REGPARM void thumb98(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[13].I + ((opcode&255)<<2); - reg[regist].I = CPUReadMemoryQuick(address); - clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC); -} - -// PC/stack-related /////////////////////////////////////////////////////// - -// ADD R0~R7, PC, Imm -static INSN_REGPARM void thumbA0(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); -} - -// ADD R0~R7, SP, Imm -static INSN_REGPARM void thumbA8(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - reg[regist].I = reg[13].I + ((opcode&255)<<2); -} - -// ADD SP, Imm -static INSN_REGPARM void thumbB0(u32 opcode) -{ - int offset = (opcode & 127) << 2; - if(opcode & 0x80) - offset = -offset; - reg[13].I += offset; -} - -// Push and pop /////////////////////////////////////////////////////////// - -#define PUSH_REG(val, r) \ - if (opcode & (val)) { \ - CPUWriteMemory(address, reg[(r)].I); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address); \ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address); \ - } \ - count++; \ - address += 4; \ - } - -#define POP_REG(val, r) \ - if (opcode & (val)) { \ - reg[(r)].I = CPUReadMemory(address); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address); \ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address); \ - } \ - count++; \ - address += 4; \ - } - -// PUSH {Rlist} -static INSN_REGPARM void thumbB4(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int count = 0; - u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff]; - u32 address = temp & 0xFFFFFFFC; - PUSH_REG(1, 0); - PUSH_REG(2, 1); - PUSH_REG(4, 2); - PUSH_REG(8, 3); - PUSH_REG(16, 4); - PUSH_REG(32, 5); - PUSH_REG(64, 6); - PUSH_REG(128, 7); - clockTicks += 1 + codeTicksAccess16(armNextPC); - reg[13].I = temp; -} - -// PUSH {Rlist, LR} -static INSN_REGPARM void thumbB5(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int count = 0; - u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff]; - u32 address = temp & 0xFFFFFFFC; - PUSH_REG(1, 0); - PUSH_REG(2, 1); - PUSH_REG(4, 2); - PUSH_REG(8, 3); - PUSH_REG(16, 4); - PUSH_REG(32, 5); - PUSH_REG(64, 6); - PUSH_REG(128, 7); - PUSH_REG(256, 14); - clockTicks += 1 + codeTicksAccess16(armNextPC); - reg[13].I = temp; -} - -// POP {Rlist} -static INSN_REGPARM void thumbBC(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int count = 0; - u32 address = reg[13].I & 0xFFFFFFFC; - u32 temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF]; - POP_REG(1, 0); - POP_REG(2, 1); - POP_REG(4, 2); - POP_REG(8, 3); - POP_REG(16, 4); - POP_REG(32, 5); - POP_REG(64, 6); - POP_REG(128, 7); - reg[13].I = temp; - clockTicks = 2 + codeTicksAccess16(armNextPC); -} - -// POP {Rlist, PC} -static INSN_REGPARM void thumbBD(u32 opcode) -{ - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - int count = 0; - u32 address = reg[13].I & 0xFFFFFFFC; - u32 temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF]; - POP_REG(1, 0); - POP_REG(2, 1); - POP_REG(4, 2); - POP_REG(8, 3); - POP_REG(16, 4); - POP_REG(32, 5); - POP_REG(64, 6); - POP_REG(128, 7); - reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE); - if (!count) { - clockTicks += 1 + dataTicksAccess32(address); - } else { - clockTicks += 1 + dataTicksAccessSeq32(address); - } - count++; - armNextPC = reg[15].I; - reg[15].I += 2; - reg[13].I = temp; - THUMB_PREFETCH; - busPrefetchCount = 0; - clockTicks += 3 + codeTicksAccess16(armNextPC) + codeTicksAccess16(armNextPC); -} - -// Load/store multiple //////////////////////////////////////////////////// - -#define THUMB_STM_REG(val,r,b) \ - if(opcode & (val)) { \ - CPUWriteMemory(address, reg[(r)].I); \ - reg[(b)].I = temp; \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address); \ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address); \ - } \ - count++; \ - address += 4; \ - } - -#define THUMB_LDM_REG(val,r) \ - if(opcode & (val)) { \ - reg[(r)].I = CPUReadMemory(address); \ - if (!count) { \ - clockTicks += 1 + dataTicksAccess32(address); \ - } else { \ - clockTicks += 1 + dataTicksAccessSeq32(address); \ - } \ - count++; \ - address += 4; \ - } - -// STM R0~7!, {Rlist} -static INSN_REGPARM void thumbC0(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[regist].I & 0xFFFFFFFC; - u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xff]; - int count = 0; - // store - THUMB_STM_REG(1, 0, regist); - THUMB_STM_REG(2, 1, regist); - THUMB_STM_REG(4, 2, regist); - THUMB_STM_REG(8, 3, regist); - THUMB_STM_REG(16, 4, regist); - THUMB_STM_REG(32, 5, regist); - THUMB_STM_REG(64, 6, regist); - THUMB_STM_REG(128, 7, regist); - clockTicks = 1 + codeTicksAccess16(armNextPC); -} - -// LDM R0~R7!, {Rlist} -static INSN_REGPARM void thumbC8(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (busPrefetchCount == 0) - busPrefetch = busPrefetchEnable; - u32 address = reg[regist].I & 0xFFFFFFFC; - u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xFF]; - int count = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - clockTicks = 2 + codeTicksAccess16(armNextPC); - if(!(opcode & (1<>6])(opcode); - - if (clockTicks < 0) - return 0; - if (clockTicks==0) - clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1; - cpuTotalTicks += clockTicks; - - } while (cpuTotalTicks < cpuNextEvent && !armState && !holdState && !SWITicks); - return 1; -} diff --git a/src/agb/GBA.cpp b/src/agb/GBA.cpp deleted file mode 100644 index 91cdf2ef..00000000 --- a/src/agb/GBA.cpp +++ /dev/null @@ -1,3983 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team -// Copyright (C) VBA-M development team -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include -#include -#include -#include -#include "GBA.h" -#include "GBAcpu.h" -#include "GBAinline.h" -#include "../Globals.h" -#include "GBAGfx.h" -#include "../EEprom.h" -#include "../Flash.h" -#include "../Sound.h" -#include "../Sram.h" -#include "../bios.h" -#include "../Cheats.h" -#include "../NLS.h" -#include "../elf.h" -#include "../Util.h" -#include "../Port.h" -#include "agbprint.h" -#ifdef PROFILING -#include "prof/prof.h" -#endif - -#ifdef __GNUC__ -#define _stricmp strcasecmp -#endif - - -extern int emulating; -#ifdef LINK_EMULATION -extern int linktime; -extern void StartLink(u16); -extern void StartJOYLink(u16); -extern void StartGPLink(u16); -extern void LinkSSend(u16); -extern void LinkUpdate(int); -extern int linktime2; -#endif -int SWITicks = 0; -int IRQTicks = 0; - -u32 mastercode = 0; -int layerEnableDelay = 0; -bool busPrefetch = false; -bool busPrefetchEnable = false; -u32 busPrefetchCount = 0; -int cpuDmaTicksToUpdate = 0; -int cpuDmaCount = 0; -bool cpuDmaHack = false; -u32 cpuDmaLast = 0; -int dummyAddress = 0; - -bool cpuBreakLoop = false; -int cpuNextEvent = 0; - -int gbaSaveType = 0; // used to remember the save type on reset -bool intState = false; -bool stopState = false; -bool holdState = false; -int holdType = 0; -bool cpuSramEnabled = true; -bool cpuFlashEnabled = true; -bool cpuEEPROMEnabled = true; -bool cpuEEPROMSensorEnabled = false; - -u32 cpuPrefetch[2]; - -int cpuTotalTicks = 0; -#ifdef PROFILING -int profilingTicks = 0; -int profilingTicksReload = 0; -static profile_segment *profilSegment = NULL; -#endif - -#ifdef BKPT_SUPPORT -u8 freezeWorkRAM[0x40000]; -u8 freezeInternalRAM[0x8000]; -u8 freezeVRAM[0x18000]; -u8 freezePRAM[0x400]; -u8 freezeOAM[0x400]; -bool debugger_last; -#endif - -int lcdTicks = (useBios && !skipBios) ? 1008 : 208; -u8 timerOnOffDelay = 0; -u16 timer0Value = 0; -bool timer0On = false; -int timer0Ticks = 0; -int timer0Reload = 0; -int timer0ClockReload = 0; -u16 timer1Value = 0; -bool timer1On = false; -int timer1Ticks = 0; -int timer1Reload = 0; -int timer1ClockReload = 0; -u16 timer2Value = 0; -bool timer2On = false; -int timer2Ticks = 0; -int timer2Reload = 0; -int timer2ClockReload = 0; -u16 timer3Value = 0; -bool timer3On = false; -int timer3Ticks = 0; -int timer3Reload = 0; -int timer3ClockReload = 0; -u32 dma0Source = 0; -u32 dma0Dest = 0; -u32 dma1Source = 0; -u32 dma1Dest = 0; -u32 dma2Source = 0; -u32 dma2Dest = 0; -u32 dma3Source = 0; -u32 dma3Dest = 0; -void (*cpuSaveGameFunc)(u32,u8) = flashSaveDecide; -void (*renderLine)() = mode0RenderLine; -bool fxOn = false; -bool windowOn = false; -int frameCount = 0; -char buffer[1024]; -FILE *out = NULL; -u32 lastTime = 0; -int count = 0; - -int capture = 0; -int capturePrevious = 0; -int captureNumber = 0; - -const int TIMER_TICKS[4] = { - 0, - 6, - 8, - 10 -}; - -const u32 objTilesAddress [3] = {0x010000, 0x014000, 0x014000}; -const u8 gamepakRamWaitState[4] = { 4, 3, 2, 8 }; -const u8 gamepakWaitState[4] = { 4, 3, 2, 8 }; -const u8 gamepakWaitState0[2] = { 2, 1 }; -const u8 gamepakWaitState1[2] = { 4, 1 }; -const u8 gamepakWaitState2[2] = { 8, 1 }; -const bool isInRom [16]= - { false, false, false, false, false, false, false, false, - true, true, true, true, true, true, false, false }; - -u8 memoryWait[16] = - { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 }; -u8 memoryWait32[16] = - { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 }; -u8 memoryWaitSeq[16] = - { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 }; -u8 memoryWaitSeq32[16] = - { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 }; - -// The videoMemoryWait constants are used to add some waitstates -// if the opcode access video memory data outside of vblank/hblank -// It seems to happen on only one ticks for each pixel. -// Not used for now (too problematic with current code). -//const u8 videoMemoryWait[16] = -// {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - -u8 biosProtected[4]; - -#ifdef WORDS_BIGENDIAN -bool cpuBiosSwapped = false; -#endif - -u32 myROM[] = { -0xEA000006, -0xEA000093, -0xEA000006, -0x00000000, -0x00000000, -0x00000000, -0xEA000088, -0x00000000, -0xE3A00302, -0xE1A0F000, -0xE92D5800, -0xE55EC002, -0xE28FB03C, -0xE79BC10C, -0xE14FB000, -0xE92D0800, -0xE20BB080, -0xE38BB01F, -0xE129F00B, -0xE92D4004, -0xE1A0E00F, -0xE12FFF1C, -0xE8BD4004, -0xE3A0C0D3, -0xE129F00C, -0xE8BD0800, -0xE169F00B, -0xE8BD5800, -0xE1B0F00E, -0x0000009C, -0x0000009C, -0x0000009C, -0x0000009C, -0x000001F8, -0x000001F0, -0x000000AC, -0x000000A0, -0x000000FC, -0x00000168, -0xE12FFF1E, -0xE1A03000, -0xE1A00001, -0xE1A01003, -0xE2113102, -0x42611000, -0xE033C040, -0x22600000, -0xE1B02001, -0xE15200A0, -0x91A02082, -0x3AFFFFFC, -0xE1500002, -0xE0A33003, -0x20400002, -0xE1320001, -0x11A020A2, -0x1AFFFFF9, -0xE1A01000, -0xE1A00003, -0xE1B0C08C, -0x22600000, -0x42611000, -0xE12FFF1E, -0xE92D0010, -0xE1A0C000, -0xE3A01001, -0xE1500001, -0x81A000A0, -0x81A01081, -0x8AFFFFFB, -0xE1A0000C, -0xE1A04001, -0xE3A03000, -0xE1A02001, -0xE15200A0, -0x91A02082, -0x3AFFFFFC, -0xE1500002, -0xE0A33003, -0x20400002, -0xE1320001, -0x11A020A2, -0x1AFFFFF9, -0xE0811003, -0xE1B010A1, -0xE1510004, -0x3AFFFFEE, -0xE1A00004, -0xE8BD0010, -0xE12FFF1E, -0xE0010090, -0xE1A01741, -0xE2611000, -0xE3A030A9, -0xE0030391, -0xE1A03743, -0xE2833E39, -0xE0030391, -0xE1A03743, -0xE2833C09, -0xE283301C, -0xE0030391, -0xE1A03743, -0xE2833C0F, -0xE28330B6, -0xE0030391, -0xE1A03743, -0xE2833C16, -0xE28330AA, -0xE0030391, -0xE1A03743, -0xE2833A02, -0xE2833081, -0xE0030391, -0xE1A03743, -0xE2833C36, -0xE2833051, -0xE0030391, -0xE1A03743, -0xE2833CA2, -0xE28330F9, -0xE0000093, -0xE1A00840, -0xE12FFF1E, -0xE3A00001, -0xE3A01001, -0xE92D4010, -0xE3A03000, -0xE3A04001, -0xE3500000, -0x1B000004, -0xE5CC3301, -0xEB000002, -0x0AFFFFFC, -0xE8BD4010, -0xE12FFF1E, -0xE3A0C301, -0xE5CC3208, -0xE15C20B8, -0xE0110002, -0x10222000, -0x114C20B8, -0xE5CC4208, -0xE12FFF1E, -0xE92D500F, -0xE3A00301, -0xE1A0E00F, -0xE510F004, -0xE8BD500F, -0xE25EF004, -0xE59FD044, -0xE92D5000, -0xE14FC000, -0xE10FE000, -0xE92D5000, -0xE3A0C302, -0xE5DCE09C, -0xE35E00A5, -0x1A000004, -0x05DCE0B4, -0x021EE080, -0xE28FE004, -0x159FF018, -0x059FF018, -0xE59FD018, -0xE8BD5000, -0xE169F00C, -0xE8BD5000, -0xE25EF004, -0x03007FF0, -0x09FE2000, -0x09FFC000, -0x03007FE0 -}; - -variable_desc saveGameStruct[] = { - { &DISPCNT , sizeof(u16) }, - { &DISPSTAT , sizeof(u16) }, - { &VCOUNT , sizeof(u16) }, - { &BG0CNT , sizeof(u16) }, - { &BG1CNT , sizeof(u16) }, - { &BG2CNT , sizeof(u16) }, - { &BG3CNT , sizeof(u16) }, - { &BG0HOFS , sizeof(u16) }, - { &BG0VOFS , sizeof(u16) }, - { &BG1HOFS , sizeof(u16) }, - { &BG1VOFS , sizeof(u16) }, - { &BG2HOFS , sizeof(u16) }, - { &BG2VOFS , sizeof(u16) }, - { &BG3HOFS , sizeof(u16) }, - { &BG3VOFS , sizeof(u16) }, - { &BG2PA , sizeof(u16) }, - { &BG2PB , sizeof(u16) }, - { &BG2PC , sizeof(u16) }, - { &BG2PD , sizeof(u16) }, - { &BG2X_L , sizeof(u16) }, - { &BG2X_H , sizeof(u16) }, - { &BG2Y_L , sizeof(u16) }, - { &BG2Y_H , sizeof(u16) }, - { &BG3PA , sizeof(u16) }, - { &BG3PB , sizeof(u16) }, - { &BG3PC , sizeof(u16) }, - { &BG3PD , sizeof(u16) }, - { &BG3X_L , sizeof(u16) }, - { &BG3X_H , sizeof(u16) }, - { &BG3Y_L , sizeof(u16) }, - { &BG3Y_H , sizeof(u16) }, - { &WIN0H , sizeof(u16) }, - { &WIN1H , sizeof(u16) }, - { &WIN0V , sizeof(u16) }, - { &WIN1V , sizeof(u16) }, - { &WININ , sizeof(u16) }, - { &WINOUT , sizeof(u16) }, - { &MOSAIC , sizeof(u16) }, - { &BLDMOD , sizeof(u16) }, - { &COLEV , sizeof(u16) }, - { &COLY , sizeof(u16) }, - { &DM0SAD_L , sizeof(u16) }, - { &DM0SAD_H , sizeof(u16) }, - { &DM0DAD_L , sizeof(u16) }, - { &DM0DAD_H , sizeof(u16) }, - { &DM0CNT_L , sizeof(u16) }, - { &DM0CNT_H , sizeof(u16) }, - { &DM1SAD_L , sizeof(u16) }, - { &DM1SAD_H , sizeof(u16) }, - { &DM1DAD_L , sizeof(u16) }, - { &DM1DAD_H , sizeof(u16) }, - { &DM1CNT_L , sizeof(u16) }, - { &DM1CNT_H , sizeof(u16) }, - { &DM2SAD_L , sizeof(u16) }, - { &DM2SAD_H , sizeof(u16) }, - { &DM2DAD_L , sizeof(u16) }, - { &DM2DAD_H , sizeof(u16) }, - { &DM2CNT_L , sizeof(u16) }, - { &DM2CNT_H , sizeof(u16) }, - { &DM3SAD_L , sizeof(u16) }, - { &DM3SAD_H , sizeof(u16) }, - { &DM3DAD_L , sizeof(u16) }, - { &DM3DAD_H , sizeof(u16) }, - { &DM3CNT_L , sizeof(u16) }, - { &DM3CNT_H , sizeof(u16) }, - { &TM0D , sizeof(u16) }, - { &TM0CNT , sizeof(u16) }, - { &TM1D , sizeof(u16) }, - { &TM1CNT , sizeof(u16) }, - { &TM2D , sizeof(u16) }, - { &TM2CNT , sizeof(u16) }, - { &TM3D , sizeof(u16) }, - { &TM3CNT , sizeof(u16) }, - { &P1 , sizeof(u16) }, - { &IE , sizeof(u16) }, - { &IF , sizeof(u16) }, - { &IME , sizeof(u16) }, - { &holdState, sizeof(bool) }, - { &holdType, sizeof(int) }, - { &lcdTicks, sizeof(int) }, - { &timer0On , sizeof(bool) }, - { &timer0Ticks , sizeof(int) }, - { &timer0Reload , sizeof(int) }, - { &timer0ClockReload , sizeof(int) }, - { &timer1On , sizeof(bool) }, - { &timer1Ticks , sizeof(int) }, - { &timer1Reload , sizeof(int) }, - { &timer1ClockReload , sizeof(int) }, - { &timer2On , sizeof(bool) }, - { &timer2Ticks , sizeof(int) }, - { &timer2Reload , sizeof(int) }, - { &timer2ClockReload , sizeof(int) }, - { &timer3On , sizeof(bool) }, - { &timer3Ticks , sizeof(int) }, - { &timer3Reload , sizeof(int) }, - { &timer3ClockReload , sizeof(int) }, - { &dma0Source , sizeof(u32) }, - { &dma0Dest , sizeof(u32) }, - { &dma1Source , sizeof(u32) }, - { &dma1Dest , sizeof(u32) }, - { &dma2Source , sizeof(u32) }, - { &dma2Dest , sizeof(u32) }, - { &dma3Source , sizeof(u32) }, - { &dma3Dest , sizeof(u32) }, - { &fxOn, sizeof(bool) }, - { &windowOn, sizeof(bool) }, - { &N_FLAG , sizeof(bool) }, - { &C_FLAG , sizeof(bool) }, - { &Z_FLAG , sizeof(bool) }, - { &V_FLAG , sizeof(bool) }, - { &armState , sizeof(bool) }, - { &armIrqEnable , sizeof(bool) }, - { &armNextPC , sizeof(u32) }, - { &armMode , sizeof(int) }, - { &saveType , sizeof(int) }, - { NULL, 0 } -}; - -static int romSize = 0x2000000; - -#ifdef PROFILING -void cpuProfil(profile_segment *seg) -{ - profilSegment = seg; -} - -void cpuEnableProfiling(int hz) -{ - if(hz == 0) - hz = 100; - profilingTicks = profilingTicksReload = 16777216 / hz; - profSetHertz(hz); -} -#endif - - -inline int CPUUpdateTicks() -{ - int cpuLoopTicks = lcdTicks; - - if(soundTicks < cpuLoopTicks) - cpuLoopTicks = soundTicks; - - if(timer0On && (timer0Ticks < cpuLoopTicks)) { - cpuLoopTicks = timer0Ticks; - } - if(timer1On && !(TM1CNT & 4) && (timer1Ticks < cpuLoopTicks)) { - cpuLoopTicks = timer1Ticks; - } - if(timer2On && !(TM2CNT & 4) && (timer2Ticks < cpuLoopTicks)) { - cpuLoopTicks = timer2Ticks; - } - if(timer3On && !(TM3CNT & 4) && (timer3Ticks < cpuLoopTicks)) { - cpuLoopTicks = timer3Ticks; - } -#ifdef PROFILING - if(profilingTicksReload != 0) { - if(profilingTicks < cpuLoopTicks) { - cpuLoopTicks = profilingTicks; - } - } -#endif - - if (SWITicks) { - if (SWITicks < cpuLoopTicks) - cpuLoopTicks = SWITicks; - } - - if (IRQTicks) { - if (IRQTicks < cpuLoopTicks) - cpuLoopTicks = IRQTicks; - } - - return cpuLoopTicks; -} - -void CPUUpdateWindow0() -{ - int x00 = WIN0H>>8; - int x01 = WIN0H & 255; - - if(x00 <= x01) { - for(int i = 0; i < 240; i++) { - gfxInWin0[i] = (i >= x00 && i < x01); - } - } else { - for(int i = 0; i < 240; i++) { - gfxInWin0[i] = (i >= x00 || i < x01); - } - } -} - -void CPUUpdateWindow1() -{ - int x00 = WIN1H>>8; - int x01 = WIN1H & 255; - - if(x00 <= x01) { - for(int i = 0; i < 240; i++) { - gfxInWin1[i] = (i >= x00 && i < x01); - } - } else { - for(int i = 0; i < 240; i++) { - gfxInWin1[i] = (i >= x00 || i < x01); - } - } -} - -extern u32 line0[240]; -extern u32 line1[240]; -extern u32 line2[240]; -extern u32 line3[240]; - -#define CLEAR_ARRAY(a) \ - {\ - u32 *array = (a);\ - for(int i = 0; i < 240; i++) {\ - *array++ = 0x80000000;\ - }\ - }\ - -void CPUUpdateRenderBuffers(bool force) -{ - if(!(layerEnable & 0x0100) || force) { - CLEAR_ARRAY(line0); - } - if(!(layerEnable & 0x0200) || force) { - CLEAR_ARRAY(line1); - } - if(!(layerEnable & 0x0400) || force) { - CLEAR_ARRAY(line2); - } - if(!(layerEnable & 0x0800) || force) { - CLEAR_ARRAY(line3); - } -} - -static bool CPUWriteState(gzFile gzFile) -{ - utilWriteInt(gzFile, SAVE_GAME_VERSION); - - utilGzWrite(gzFile, &rom[0xa0], 16); - - utilWriteInt(gzFile, useBios); - - utilGzWrite(gzFile, ®[0], sizeof(reg)); - - utilWriteData(gzFile, saveGameStruct); - - // new to version 0.7.1 - utilWriteInt(gzFile, stopState); - // new to version 0.8 - utilWriteInt(gzFile, IRQTicks); - - utilGzWrite(gzFile, internalRAM, 0x8000); - utilGzWrite(gzFile, paletteRAM, 0x400); - utilGzWrite(gzFile, workRAM, 0x40000); - utilGzWrite(gzFile, vram, 0x20000); - utilGzWrite(gzFile, oam, 0x400); - utilGzWrite(gzFile, pix, 4*241*162); - utilGzWrite(gzFile, ioMem, 0x400); - - eepromSaveGame(gzFile); - flashSaveGame(gzFile); - soundSaveGame(gzFile); - - cheatsSaveGame(gzFile); - - // version 1.5 - rtcSaveGame(gzFile); - - return true; -} - -bool CPUWriteState(const char *file) -{ - gzFile gzFile = utilGzOpen(file, "wb"); - - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), file); - return false; - } - - bool res = CPUWriteState(gzFile); - - utilGzClose(gzFile); - - return res; -} - -bool CPUWriteMemState(char *memory, int available) -{ - gzFile gzFile = utilMemGzOpen(memory, available, "w"); - - if(gzFile == NULL) { - return false; - } - - bool res = CPUWriteState(gzFile); - - long pos = utilGzMemTell(gzFile)+8; - - if(pos >= (available)) - res = false; - - utilGzClose(gzFile); - - return res; -} - -static bool CPUReadState(gzFile gzFile) -{ - int version = utilReadInt(gzFile); - - if(version > SAVE_GAME_VERSION || version < SAVE_GAME_VERSION_1) { - systemMessage(MSG_UNSUPPORTED_VBA_SGM, - N_("Unsupported VisualBoyAdvance save game version %d"), - version); - return false; - } - - u8 romname[17]; - - utilGzRead(gzFile, romname, 16); - - if(memcmp(&rom[0xa0], romname, 16) != 0) { - romname[16]=0; - for(int i = 0; i < 16; i++) - if(romname[i] < 32) - romname[i] = 32; - systemMessage(MSG_CANNOT_LOAD_SGM, N_("Cannot load save game for %s"), romname); - return false; - } - - bool ub = utilReadInt(gzFile) ? true : false; - - if(ub != useBios) { - if(useBios) - systemMessage(MSG_SAVE_GAME_NOT_USING_BIOS, - N_("Save game is not using the BIOS files")); - else - systemMessage(MSG_SAVE_GAME_USING_BIOS, - N_("Save game is using the BIOS file")); - return false; - } - - utilGzRead(gzFile, ®[0], sizeof(reg)); - - utilReadData(gzFile, saveGameStruct); - - if(version < SAVE_GAME_VERSION_3) - stopState = false; - else - stopState = utilReadInt(gzFile) ? true : false; - - if(version < SAVE_GAME_VERSION_4) - { - IRQTicks = 0; - intState = false; - } - else - { - IRQTicks = utilReadInt(gzFile); - if (IRQTicks>0) - intState = true; - else - { - intState = false; - IRQTicks = 0; - } - } - - utilGzRead(gzFile, internalRAM, 0x8000); - utilGzRead(gzFile, paletteRAM, 0x400); - utilGzRead(gzFile, workRAM, 0x40000); - utilGzRead(gzFile, vram, 0x20000); - utilGzRead(gzFile, oam, 0x400); - if(version < SAVE_GAME_VERSION_6) - utilGzRead(gzFile, pix, 4*240*160); - else - utilGzRead(gzFile, pix, 4*241*162); - utilGzRead(gzFile, ioMem, 0x400); - - eepromReadGame(gzFile, version); - flashReadGame(gzFile, version); - soundReadGame(gzFile, version); - - if(version > SAVE_GAME_VERSION_1) { - cheatsReadGame(gzFile, version); - } - if(version > SAVE_GAME_VERSION_6) { - rtcReadGame(gzFile); - } - - if(version <= SAVE_GAME_VERSION_7) { - u32 temp; -#define SWAP(a,b,c) \ - temp = (a);\ - (a) = (b)<<16|(c);\ - (b) = (temp) >> 16;\ - (c) = (temp) & 0xFFFF; - - SWAP(dma0Source, DM0SAD_H, DM0SAD_L); - SWAP(dma0Dest, DM0DAD_H, DM0DAD_L); - SWAP(dma1Source, DM1SAD_H, DM1SAD_L); - SWAP(dma1Dest, DM1DAD_H, DM1DAD_L); - SWAP(dma2Source, DM2SAD_H, DM2SAD_L); - SWAP(dma2Dest, DM2DAD_H, DM2DAD_L); - SWAP(dma3Source, DM3SAD_H, DM3SAD_L); - SWAP(dma3Dest, DM3DAD_H, DM3DAD_L); - } - - if(version <= SAVE_GAME_VERSION_8) { - timer0ClockReload = TIMER_TICKS[TM0CNT & 3]; - timer1ClockReload = TIMER_TICKS[TM1CNT & 3]; - timer2ClockReload = TIMER_TICKS[TM2CNT & 3]; - timer3ClockReload = TIMER_TICKS[TM3CNT & 3]; - - timer0Ticks = ((0x10000 - TM0D) << timer0ClockReload) - timer0Ticks; - timer1Ticks = ((0x10000 - TM1D) << timer1ClockReload) - timer1Ticks; - timer2Ticks = ((0x10000 - TM2D) << timer2ClockReload) - timer2Ticks; - timer3Ticks = ((0x10000 - TM3D) << timer3ClockReload) - timer3Ticks; - interp_rate(); - } - - // set pointers! - layerEnable = layerSettings & DISPCNT; - - CPUUpdateRender(); - CPUUpdateRenderBuffers(true); - CPUUpdateWindow0(); - CPUUpdateWindow1(); - gbaSaveType = 0; - switch(saveType) { - case 0: - cpuSaveGameFunc = flashSaveDecide; - break; - case 1: - cpuSaveGameFunc = sramWrite; - gbaSaveType = 1; - break; - case 2: - cpuSaveGameFunc = flashWrite; - gbaSaveType = 2; - break; - case 3: - break; - case 5: - gbaSaveType = 5; - break; - default: - systemMessage(MSG_UNSUPPORTED_SAVE_TYPE, - N_("Unsupported save type %d"), saveType); - break; - } - if(eepromInUse) - gbaSaveType = 3; - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - if(armState) { - ARM_PREFETCH; - } else { - THUMB_PREFETCH; - } - - CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204)); - - return true; -} - -bool CPUReadMemState(char *memory, int available) -{ - gzFile gzFile = utilMemGzOpen(memory, available, "r"); - - bool res = CPUReadState(gzFile); - - utilGzClose(gzFile); - - return res; -} - -bool CPUReadState(const char * file) -{ - gzFile gzFile = utilGzOpen(file, "rb"); - - if(gzFile == NULL) - return false; - - bool res = CPUReadState(gzFile); - - utilGzClose(gzFile); - - return res; -} - -bool CPUExportEepromFile(const char *fileName) -{ - if(eepromInUse) { - FILE *file = fopen(fileName, "wb"); - - if(!file) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), - fileName); - return false; - } - - for(int i = 0; i < eepromSize;) { - for(int j = 0; j < 8; j++) { - if(fwrite(&eepromData[i+7-j], 1, 1, file) != 1) { - fclose(file); - return false; - } - } - i += 8; - } - fclose(file); - } - return true; -} - -bool CPUWriteBatteryFile(const char *fileName) -{ - if(gbaSaveType == 0) { - if(eepromInUse) - gbaSaveType = 3; - else switch(saveType) { - case 1: - gbaSaveType = 1; - break; - case 2: - gbaSaveType = 2; - break; - } - } - - if((gbaSaveType) && (gbaSaveType!=5)) { - FILE *file = fopen(fileName, "wb"); - - if(!file) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), - fileName); - return false; - } - - // only save if Flash/Sram in use or EEprom in use - if(gbaSaveType != 3) { - if(gbaSaveType == 2) { - if(fwrite(flashSaveMemory, 1, flashSize, file) != (size_t)flashSize) { - fclose(file); - return false; - } - } else { - if(fwrite(flashSaveMemory, 1, 0x10000, file) != 0x10000) { - fclose(file); - return false; - } - } - } else { - if(fwrite(eepromData, 1, eepromSize, file) != (size_t)eepromSize) { - fclose(file); - return false; - } - } - fclose(file); - } - return true; -} - -bool CPUReadGSASnapshot(const char *fileName) -{ - int i; - FILE *file = fopen(fileName, "rb"); - - if(!file) { - systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); - return false; - } - - // check file size to know what we should read - fseek(file, 0, SEEK_END); - - // long size = ftell(file); - fseek(file, 0x0, SEEK_SET); - fread(&i, 1, 4, file); - fseek(file, i, SEEK_CUR); // Skip SharkPortSave - fseek(file, 4, SEEK_CUR); // skip some sort of flag - fread(&i, 1, 4, file); // name length - fseek(file, i, SEEK_CUR); // skip name - fread(&i, 1, 4, file); // desc length - fseek(file, i, SEEK_CUR); // skip desc - fread(&i, 1, 4, file); // notes length - fseek(file, i, SEEK_CUR); // skip notes - int saveSize; - fread(&saveSize, 1, 4, file); // read length - saveSize -= 0x1c; // remove header size - char buffer[17]; - char buffer2[17]; - fread(buffer, 1, 16, file); - buffer[16] = 0; - for(i = 0; i < 16; i++) - if(buffer[i] < 32) - buffer[i] = 32; - memcpy(buffer2, &rom[0xa0], 16); - buffer2[16] = 0; - for(i = 0; i < 16; i++) - if(buffer2[i] < 32) - buffer2[i] = 32; - if(memcmp(buffer, buffer2, 16)) { - systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR, - N_("Cannot import snapshot for %s. Current game is %s"), - buffer, - buffer2); - fclose(file); - return false; - } - fseek(file, 12, SEEK_CUR); // skip some flags - if(saveSize >= 65536) { - if(fread(flashSaveMemory, 1, saveSize, file) != (size_t)saveSize) { - fclose(file); - return false; - } - } else { - systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE, - N_("Unsupported snapshot file %s"), - fileName); - fclose(file); - return false; - } - fclose(file); - CPUReset(); - return true; -} - -bool CPUWriteGSASnapshot(const char *fileName, - const char *title, - const char *desc, - const char *notes) -{ - FILE *file = fopen(fileName, "wb"); - - if(!file) { - systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); - return false; - } - - u8 buffer[17]; - - utilPutDword(buffer, 0x0d); // SharkPortSave length - fwrite(buffer, 1, 4, file); - fwrite("SharkPortSave", 1, 0x0d, file); - utilPutDword(buffer, 0x000f0000); - fwrite(buffer, 1, 4, file); // save type 0x000f0000 = GBA save - utilPutDword(buffer, (u32)strlen(title)); - fwrite(buffer, 1, 4, file); // title length - fwrite(title, 1, strlen(title), file); - utilPutDword(buffer, (u32)strlen(desc)); - fwrite(buffer, 1, 4, file); // desc length - fwrite(desc, 1, strlen(desc), file); - utilPutDword(buffer, (u32)strlen(notes)); - fwrite(buffer, 1, 4, file); // notes length - fwrite(notes, 1, strlen(notes), file); - int saveSize = 0x10000; - if(gbaSaveType == 2) - saveSize = flashSize; - int totalSize = saveSize + 0x1c; - - utilPutDword(buffer, totalSize); // length of remainder of save - CRC - fwrite(buffer, 1, 4, file); - - char temp[0x2001c]; - memset(temp, 0, 28); - memcpy(temp, &rom[0xa0], 16); // copy internal name - temp[0x10] = rom[0xbe]; // reserved area (old checksum) - temp[0x11] = rom[0xbf]; // reserved area (old checksum) - temp[0x12] = rom[0xbd]; // complement check - temp[0x13] = rom[0xb0]; // maker - temp[0x14] = 1; // 1 save ? - memcpy(&temp[0x1c], flashSaveMemory, saveSize); // copy save - fwrite(temp, 1, totalSize, file); // write save + header - u32 crc = 0; - - for(int i = 0; i < totalSize; i++) { - crc += ((u32)temp[i] << (crc % 0x18)); - } - - utilPutDword(buffer, crc); - fwrite(buffer, 1, 4, file); // CRC? - - fclose(file); - return true; -} - -bool CPUImportEepromFile(const char *fileName) -{ - FILE *file = fopen(fileName, "rb"); - - if(!file) - return false; - - // check file size to know what we should read - fseek(file, 0, SEEK_END); - - long size = ftell(file); - fseek(file, 0, SEEK_SET); - if(size == 512 || size == 0x2000) { - if(fread(eepromData, 1, size, file) != (size_t)size) { - fclose(file); - return false; - } - for(int i = 0; i < size;) { - u8 tmp = eepromData[i]; - eepromData[i] = eepromData[7-i]; - eepromData[7-i] = tmp; - i++; - tmp = eepromData[i]; - eepromData[i] = eepromData[7-i]; - eepromData[7-i] = tmp; - i++; - tmp = eepromData[i]; - eepromData[i] = eepromData[7-i]; - eepromData[7-i] = tmp; - i++; - tmp = eepromData[i]; - eepromData[i] = eepromData[7-i]; - eepromData[7-i] = tmp; - i++; - i += 4; - } - } else - return false; - fclose(file); - return true; -} - -bool CPUReadBatteryFile(const char *fileName) -{ - FILE *file = fopen(fileName, "rb"); - - if(!file) - return false; - - // check file size to know what we should read - fseek(file, 0, SEEK_END); - - long size = ftell(file); - fseek(file, 0, SEEK_SET); - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - - if(size == 512 || size == 0x2000) { - if(fread(eepromData, 1, size, file) != (size_t)size) { - fclose(file); - return false; - } - } else { - if(size == 0x20000) { - if(fread(flashSaveMemory, 1, 0x20000, file) != 0x20000) { - fclose(file); - return false; - } - flashSetSize(0x20000); - } else { - if(fread(flashSaveMemory, 1, 0x10000, file) != 0x10000) { - fclose(file); - return false; - } - flashSetSize(0x10000); - } - } - fclose(file); - return true; -} - -bool CPUWritePNGFile(const char *fileName) -{ - return utilWritePNGFile(fileName, 240, 160, pix); -} - -bool CPUWriteBMPFile(const char *fileName) -{ - return utilWriteBMPFile(fileName, 240, 160, pix); -} - -bool CPUIsZipFile(const char * file) -{ - if(strlen(file) > 4) { - const char * p = strrchr(file,'.'); - - if(p != NULL) { - if(_stricmp(p, ".zip") == 0) - return true; - } - } - - return false; -} - -bool CPUIsGBAImage(const char * file) -{ - cpuIsMultiBoot = false; - if(strlen(file) > 4) { - const char * p = strrchr(file,'.'); - - if(p != NULL) { - if(_stricmp(p, ".gba") == 0) - return true; - if(_stricmp(p, ".agb") == 0) - return true; - if(_stricmp(p, ".bin") == 0) - return true; - if(_stricmp(p, ".elf") == 0) - return true; - if(_stricmp(p, ".mb") == 0) { - cpuIsMultiBoot = true; - return true; - } - } - } - - return false; -} - -bool CPUIsGBABios(const char * file) -{ - if(strlen(file) > 4) { - const char * p = strrchr(file,'.'); - - if(p != NULL) { - if(_stricmp(p, ".gba") == 0) - return true; - if(_stricmp(p, ".agb") == 0) - return true; - if(_stricmp(p, ".bin") == 0) - return true; - if(_stricmp(p, ".bios") == 0) - return true; - if(_stricmp(p, ".rom") == 0) - return true; - } - } - - return false; -} - -bool CPUIsELF(const char *file) -{ - if(strlen(file) > 4) { - const char * p = strrchr(file,'.'); - - if(p != NULL) { - if(_stricmp(p, ".elf") == 0) - return true; - } - } - return false; -} - -void CPUCleanUp() -{ -#ifdef PROFILING - if(profilingTicksReload) { - profCleanup(); - } -#endif - - if(rom != NULL) { - free(rom); - rom = NULL; - } - - if(vram != NULL) { - free(vram); - vram = NULL; - } - - if(paletteRAM != NULL) { - free(paletteRAM); - paletteRAM = NULL; - } - - if(internalRAM != NULL) { - free(internalRAM); - internalRAM = NULL; - } - - if(workRAM != NULL) { - free(workRAM); - workRAM = NULL; - } - - if(bios != NULL) { - free(bios); - bios = NULL; - } - - if(pix != NULL) { - free(pix); - pix = NULL; - } - - if(oam != NULL) { - free(oam); - oam = NULL; - } - - if(ioMem != NULL) { - free(ioMem); - ioMem = NULL; - } - - elfCleanUp(); - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - - emulating = 0; -} - -int CPULoadRom(const char *szFile) -{ - romSize = 0x2000000; - if(rom != NULL) { - CPUCleanUp(); - } - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - - rom = (u8 *)malloc(0x2000000); - if(rom == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "ROM"); - return 0; - } - workRAM = (u8 *)calloc(1, 0x40000); - if(workRAM == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "WRAM"); - return 0; - } - - u8 *whereToLoad = cpuIsMultiBoot ? workRAM : rom; - - if(CPUIsELF(szFile)) { - FILE *f = fopen(szFile, "rb"); - if(!f) { - systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), - szFile); - free(rom); - rom = NULL; - free(workRAM); - workRAM = NULL; - return 0; - } - bool res = elfRead(szFile, romSize, f); - if(!res || romSize == 0) { - free(rom); - rom = NULL; - free(workRAM); - workRAM = NULL; - elfCleanUp(); - return 0; - } - } else if(!utilLoad(szFile, - utilIsGBAImage, - whereToLoad, - romSize)) { - free(rom); - rom = NULL; - free(workRAM); - workRAM = NULL; - return 0; - } - - u16 *temp = (u16 *)(rom+((romSize+1)&~1)); - int i; - for(i = (romSize+1)&~1; i < 0x2000000; i+=2) { - WRITE16LE(temp, (i >> 1) & 0xFFFF); - temp++; - } - - bios = (u8 *)calloc(1,0x4000); - if(bios == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "BIOS"); - CPUCleanUp(); - return 0; - } - internalRAM = (u8 *)calloc(1,0x8000); - if(internalRAM == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "IRAM"); - CPUCleanUp(); - return 0; - } - paletteRAM = (u8 *)calloc(1,0x400); - if(paletteRAM == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "PRAM"); - CPUCleanUp(); - return 0; - } - vram = (u8 *)calloc(1, 0x20000); - if(vram == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "VRAM"); - CPUCleanUp(); - return 0; - } - oam = (u8 *)calloc(1, 0x400); - if(oam == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "OAM"); - CPUCleanUp(); - return 0; - } - pix = (u8 *)calloc(1, 4 * 241 * 162); - if(pix == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "PIX"); - CPUCleanUp(); - return 0; - } - ioMem = (u8 *)calloc(1, 0x400); - if(ioMem == NULL) { - systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), - "IO"); - CPUCleanUp(); - return 0; - } - - flashInit(); - eepromInit(); - - CPUUpdateRenderBuffers(true); - - return romSize; -} - -void doMirroring (bool b) -{ - u32 mirroredRomSize = (((romSize)>>20) & 0x3F)<<20; - u32 mirroredRomAddress = romSize; - if ((mirroredRomSize <=0x800000) && (b)) - { - mirroredRomAddress = mirroredRomSize; - if (mirroredRomSize==0) - mirroredRomSize=0x100000; - while (mirroredRomAddress<0x01000000) - { - memcpy ((u16 *)(rom+mirroredRomAddress), (u16 *)(rom), mirroredRomSize); - mirroredRomAddress+=mirroredRomSize; - } - } -} - -void CPUUpdateRender() -{ - switch(DISPCNT & 7) { - case 0: - if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || - cpuDisableSfx) - renderLine = mode0RenderLine; - else if(fxOn && !windowOn && !(layerEnable & 0x8000)) - renderLine = mode0RenderLineNoWindow; - else - renderLine = mode0RenderLineAll; - break; - case 1: - if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || - cpuDisableSfx) - renderLine = mode1RenderLine; - else if(fxOn && !windowOn && !(layerEnable & 0x8000)) - renderLine = mode1RenderLineNoWindow; - else - renderLine = mode1RenderLineAll; - break; - case 2: - if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || - cpuDisableSfx) - renderLine = mode2RenderLine; - else if(fxOn && !windowOn && !(layerEnable & 0x8000)) - renderLine = mode2RenderLineNoWindow; - else - renderLine = mode2RenderLineAll; - break; - case 3: - if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || - cpuDisableSfx) - renderLine = mode3RenderLine; - else if(fxOn && !windowOn && !(layerEnable & 0x8000)) - renderLine = mode3RenderLineNoWindow; - else - renderLine = mode3RenderLineAll; - break; - case 4: - if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || - cpuDisableSfx) - renderLine = mode4RenderLine; - else if(fxOn && !windowOn && !(layerEnable & 0x8000)) - renderLine = mode4RenderLineNoWindow; - else - renderLine = mode4RenderLineAll; - break; - case 5: - if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || - cpuDisableSfx) - renderLine = mode5RenderLine; - else if(fxOn && !windowOn && !(layerEnable & 0x8000)) - renderLine = mode5RenderLineNoWindow; - else - renderLine = mode5RenderLineAll; - default: - break; - } -} - -void CPUUpdateCPSR() -{ - u32 CPSR = reg[16].I & 0x40; - if(N_FLAG) - CPSR |= 0x80000000; - if(Z_FLAG) - CPSR |= 0x40000000; - if(C_FLAG) - CPSR |= 0x20000000; - if(V_FLAG) - CPSR |= 0x10000000; - if(!armState) - CPSR |= 0x00000020; - if(!armIrqEnable) - CPSR |= 0x80; - CPSR |= (armMode & 0x1F); - reg[16].I = CPSR; -} - -void CPUUpdateFlags(bool breakLoop) -{ - u32 CPSR = reg[16].I; - - N_FLAG = (CPSR & 0x80000000) ? true: false; - Z_FLAG = (CPSR & 0x40000000) ? true: false; - C_FLAG = (CPSR & 0x20000000) ? true: false; - V_FLAG = (CPSR & 0x10000000) ? true: false; - armState = (CPSR & 0x20) ? false : true; - armIrqEnable = (CPSR & 0x80) ? false : true; - if(breakLoop) { - if (armIrqEnable && (IF & IE) && (IME & 1)) - cpuNextEvent = cpuTotalTicks; - } -} - -void CPUUpdateFlags() -{ - CPUUpdateFlags(true); -} - -#ifdef WORDS_BIGENDIAN -static void CPUSwap(volatile u32 *a, volatile u32 *b) -{ - volatile u32 c = *b; - *b = *a; - *a = c; -} -#else -static void CPUSwap(u32 *a, u32 *b) -{ - u32 c = *b; - *b = *a; - *a = c; -} -#endif - -void CPUSwitchMode(int mode, bool saveState, bool breakLoop) -{ - // if(armMode == mode) - // return; - - CPUUpdateCPSR(); - - switch(armMode) { - case 0x10: - case 0x1F: - reg[R13_USR].I = reg[13].I; - reg[R14_USR].I = reg[14].I; - reg[17].I = reg[16].I; - break; - case 0x11: - CPUSwap(®[R8_FIQ].I, ®[8].I); - CPUSwap(®[R9_FIQ].I, ®[9].I); - CPUSwap(®[R10_FIQ].I, ®[10].I); - CPUSwap(®[R11_FIQ].I, ®[11].I); - CPUSwap(®[R12_FIQ].I, ®[12].I); - reg[R13_FIQ].I = reg[13].I; - reg[R14_FIQ].I = reg[14].I; - reg[SPSR_FIQ].I = reg[17].I; - break; - case 0x12: - reg[R13_IRQ].I = reg[13].I; - reg[R14_IRQ].I = reg[14].I; - reg[SPSR_IRQ].I = reg[17].I; - break; - case 0x13: - reg[R13_SVC].I = reg[13].I; - reg[R14_SVC].I = reg[14].I; - reg[SPSR_SVC].I = reg[17].I; - break; - case 0x17: - reg[R13_ABT].I = reg[13].I; - reg[R14_ABT].I = reg[14].I; - reg[SPSR_ABT].I = reg[17].I; - break; - case 0x1b: - reg[R13_UND].I = reg[13].I; - reg[R14_UND].I = reg[14].I; - reg[SPSR_UND].I = reg[17].I; - break; - } - - u32 CPSR = reg[16].I; - u32 SPSR = reg[17].I; - - switch(mode) { - case 0x10: - case 0x1F: - reg[13].I = reg[R13_USR].I; - reg[14].I = reg[R14_USR].I; - reg[16].I = SPSR; - break; - case 0x11: - CPUSwap(®[8].I, ®[R8_FIQ].I); - CPUSwap(®[9].I, ®[R9_FIQ].I); - CPUSwap(®[10].I, ®[R10_FIQ].I); - CPUSwap(®[11].I, ®[R11_FIQ].I); - CPUSwap(®[12].I, ®[R12_FIQ].I); - reg[13].I = reg[R13_FIQ].I; - reg[14].I = reg[R14_FIQ].I; - if(saveState) - reg[17].I = CPSR; - else - reg[17].I = reg[SPSR_FIQ].I; - break; - case 0x12: - reg[13].I = reg[R13_IRQ].I; - reg[14].I = reg[R14_IRQ].I; - reg[16].I = SPSR; - if(saveState) - reg[17].I = CPSR; - else - reg[17].I = reg[SPSR_IRQ].I; - break; - case 0x13: - reg[13].I = reg[R13_SVC].I; - reg[14].I = reg[R14_SVC].I; - reg[16].I = SPSR; - if(saveState) - reg[17].I = CPSR; - else - reg[17].I = reg[SPSR_SVC].I; - break; - case 0x17: - reg[13].I = reg[R13_ABT].I; - reg[14].I = reg[R14_ABT].I; - reg[16].I = SPSR; - if(saveState) - reg[17].I = CPSR; - else - reg[17].I = reg[SPSR_ABT].I; - break; - case 0x1b: - reg[13].I = reg[R13_UND].I; - reg[14].I = reg[R14_UND].I; - reg[16].I = SPSR; - if(saveState) - reg[17].I = CPSR; - else - reg[17].I = reg[SPSR_UND].I; - break; - default: - systemMessage(MSG_UNSUPPORTED_ARM_MODE, N_("Unsupported ARM mode %02x"), mode); - break; - } - armMode = mode; - CPUUpdateFlags(breakLoop); - CPUUpdateCPSR(); -} - -void CPUSwitchMode(int mode, bool saveState) -{ - CPUSwitchMode(mode, saveState, true); -} - -void CPUUndefinedException() -{ - u32 PC = reg[15].I; - bool savedArmState = armState; - CPUSwitchMode(0x1b, true, false); - reg[14].I = PC - (savedArmState ? 4 : 2); - reg[15].I = 0x04; - armState = true; - armIrqEnable = false; - armNextPC = 0x04; - ARM_PREFETCH; - reg[15].I += 4; -} - -void CPUSoftwareInterrupt() -{ - u32 PC = reg[15].I; - bool savedArmState = armState; - CPUSwitchMode(0x13, true, false); - reg[14].I = PC - (savedArmState ? 4 : 2); - reg[15].I = 0x08; - armState = true; - armIrqEnable = false; - armNextPC = 0x08; - ARM_PREFETCH; - reg[15].I += 4; -} - -void CPUSoftwareInterrupt(int comment) -{ - static bool disableMessage = false; - if(armState) comment >>= 16; -#ifdef BKPT_SUPPORT - if(comment == 0xff) { - extern void (*dbgOutput)(const char *, u32); - dbgOutput(NULL, reg[0].I); - return; - } -#endif -#ifdef PROFILING - if(comment == 0xfe) { - profStartup(reg[0].I, reg[1].I); - return; - } - if(comment == 0xfd) { - profControl(reg[0].I); - return; - } - if(comment == 0xfc) { - profCleanup(); - return; - } - if(comment == 0xfb) { - profCount(); - return; - } -#endif - if(comment == 0xfa) { - agbPrintFlush(); - return; - } -#ifdef SDL - if(comment == 0xf9) { - emulating = 0; - cpuNextEvent = cpuTotalTicks; - cpuBreakLoop = true; - return; - } -#endif - if(useBios) { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_SWI) { - log("SWI: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment, - armState ? armNextPC - 4: armNextPC -2, - reg[0].I, - reg[1].I, - reg[2].I, - VCOUNT); - } -#endif - CPUSoftwareInterrupt(); - return; - } - // This would be correct, but it causes problems if uncommented - // else { - // biosProtected = 0xe3a02004; - // } - - switch(comment) { - case 0x00: - BIOS_SoftReset(); - ARM_PREFETCH; - break; - case 0x01: - BIOS_RegisterRamReset(); - break; - case 0x02: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_SWI) { - log("Halt: (VCOUNT = %2d)\n", - VCOUNT); - } -#endif - holdState = true; - holdType = -1; - cpuNextEvent = cpuTotalTicks; - break; - case 0x03: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_SWI) { - log("Stop: (VCOUNT = %2d)\n", - VCOUNT); - } -#endif - holdState = true; - holdType = -1; - stopState = true; - cpuNextEvent = cpuTotalTicks; - break; - case 0x04: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_SWI) { - log("IntrWait: 0x%08x,0x%08x (VCOUNT = %2d)\n", - reg[0].I, - reg[1].I, - VCOUNT); - } -#endif - CPUSoftwareInterrupt(); - break; - case 0x05: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_SWI) { - log("VBlankIntrWait: (VCOUNT = %2d)\n", - VCOUNT); - } -#endif - CPUSoftwareInterrupt(); - break; - case 0x06: - CPUSoftwareInterrupt(); - break; - case 0x07: - CPUSoftwareInterrupt(); - break; - case 0x08: - BIOS_Sqrt(); - break; - case 0x09: - BIOS_ArcTan(); - break; - case 0x0A: - BIOS_ArcTan2(); - break; - case 0x0B: - { - int len = (reg[2].I & 0x1FFFFF) >>1; - if (!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + len) & 0xe000000) == 0)) - { - if ((reg[2].I >> 24) & 1) - { - if ((reg[2].I >> 26) & 1) - SWITicks = (7 + memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1); - else - SWITicks = (8 + memoryWait[(reg[1].I>>24) & 0xF]) * (len); - } - else - { - if ((reg[2].I >> 26) & 1) - SWITicks = (10 + memoryWait32[(reg[0].I>>24) & 0xF] + - memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1); - else - SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] + - memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - } - } - BIOS_CpuSet(); - break; - case 0x0C: - { - int len = (reg[2].I & 0x1FFFFF) >>5; - if (!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + len) & 0xe000000) == 0)) - { - if ((reg[2].I >> 24) & 1) - SWITicks = (6 + memoryWait32[(reg[1].I>>24) & 0xF] + - 7 * (memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 1)) * len; - else - SWITicks = (9 + memoryWait32[(reg[0].I>>24) & 0xF] + - memoryWait32[(reg[1].I>>24) & 0xF] + - 7 * (memoryWaitSeq32[(reg[0].I>>24) & 0xF] + - memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 2)) * len; - } - } - BIOS_CpuFastSet(); - break; - case 0x0D: - BIOS_GetBiosChecksum(); - break; - case 0x0E: - BIOS_BgAffineSet(); - break; - case 0x0F: - BIOS_ObjAffineSet(); - break; - case 0x10: - { - int len = CPUReadHalfWord(reg[2].I); - if (!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + len) & 0xe000000) == 0)) - SWITicks = (32 + memoryWait[(reg[0].I>>24) & 0xF]) * len; - } - BIOS_BitUnPack(); - break; - case 0x11: - { - u32 len = CPUReadMemory(reg[0].I) >> 8; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (9 + memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - BIOS_LZ77UnCompWram(); - break; - case 0x12: - { - u32 len = CPUReadMemory(reg[0].I) >> 8; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (19 + memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - BIOS_LZ77UnCompVram(); - break; - case 0x13: - { - u32 len = CPUReadMemory(reg[0].I) >> 8; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (29 + (memoryWait[(reg[0].I>>24) & 0xF]<<1)) * len; - } - BIOS_HuffUnComp(); - break; - case 0x14: - { - u32 len = CPUReadMemory(reg[0].I) >> 8; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] + - memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - BIOS_RLUnCompWram(); - break; - case 0x15: - { - u32 len = CPUReadMemory(reg[0].I) >> 9; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (34 + (memoryWait[(reg[0].I>>24) & 0xF] << 1) + - memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - BIOS_RLUnCompVram(); - break; - case 0x16: - { - u32 len = CPUReadMemory(reg[0].I) >> 8; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] + - memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - BIOS_Diff8bitUnFilterWram(); - break; - case 0x17: - { - u32 len = CPUReadMemory(reg[0].I) >> 9; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (39 + (memoryWait[(reg[0].I>>24) & 0xF]<<1) + - memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - BIOS_Diff8bitUnFilterVram(); - break; - case 0x18: - { - u32 len = CPUReadMemory(reg[0].I) >> 9; - if(!(((reg[0].I & 0xe000000) == 0) || - ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) - SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] + - memoryWait[(reg[1].I>>24) & 0xF]) * len; - } - BIOS_Diff16bitUnFilter(); - break; - case 0x19: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_SWI) { - log("SoundBiasSet: 0x%08x (VCOUNT = %2d)\n", - reg[0].I, - VCOUNT); - } -#endif - if(reg[0].I) - systemSoundPause(); - else - systemSoundResume(); - break; - case 0x1F: - BIOS_MidiKey2Freq(); - break; - case 0x2A: - BIOS_SndDriverJmpTableCopy(); - // let it go, because we don't really emulate this function - default: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_SWI) { - log("SWI: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment, - armState ? armNextPC - 4: armNextPC -2, - reg[0].I, - reg[1].I, - reg[2].I, - VCOUNT); - } -#endif - - if(!disableMessage) { - systemMessage(MSG_UNSUPPORTED_BIOS_FUNCTION, - N_("Unsupported BIOS function %02x called from %08x. A BIOS file is needed in order to get correct behaviour."), - comment, - armMode ? armNextPC - 4: armNextPC - 2); - disableMessage = true; - } - break; - } -} - -void CPUCompareVCOUNT() -{ - if(VCOUNT == (DISPSTAT >> 8)) { - DISPSTAT |= 4; - UPDATE_REG(0x04, DISPSTAT); - - if(DISPSTAT & 0x20) { - IF |= 4; - UPDATE_REG(0x202, IF); - } - } else { - DISPSTAT &= 0xFFFB; - UPDATE_REG(0x4, DISPSTAT); - } - if (layerEnableDelay>0) - { - layerEnableDelay--; - if (layerEnableDelay==1) - layerEnable = layerSettings & DISPCNT; - } - -} - -void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) -{ - int sm = s >> 24; - int dm = d >> 24; - int sw = 0; - int dw = 0; - int sc = c; - - cpuDmaCount = c; - // This is done to get the correct waitstates. - if (sm>15) - sm=15; - if (dm>15) - dm=15; - - //if ((sm>=0x05) && (sm<=0x07) || (dm>=0x05) && (dm <=0x07)) - // blank = (((DISPSTAT | ((DISPSTAT>>1)&1))==1) ? true : false); - - if(transfer32) { - s &= 0xFFFFFFFC; - if(s < 0x02000000 && (reg[15].I >> 24)) { - while(c != 0) { - CPUWriteMemory(d, 0); - d += di; - c--; - } - } else { - while(c != 0) { - cpuDmaLast = CPUReadMemory(s); - CPUWriteMemory(d, cpuDmaLast); - d += di; - s += si; - c--; - } - } - } else { - s &= 0xFFFFFFFE; - si = (int)si >> 1; - di = (int)di >> 1; - if(s < 0x02000000 && (reg[15].I >> 24)) { - while(c != 0) { - CPUWriteHalfWord(d, 0); - d += di; - c--; - } - } else { - while(c != 0) { - cpuDmaLast = CPUReadHalfWord(s); - CPUWriteHalfWord(d, cpuDmaLast); - cpuDmaLast |= (cpuDmaLast<<16); - d += di; - s += si; - c--; - } - } - } - - cpuDmaCount = 0; - - int totalTicks = 0; - - if(transfer32) { - sw =1+memoryWaitSeq32[sm & 15]; - dw =1+memoryWaitSeq32[dm & 15]; - totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] + - memoryWaitSeq32[dm & 15]; - } - else - { - sw = 1+memoryWaitSeq[sm & 15]; - dw = 1+memoryWaitSeq[dm & 15]; - totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] + - memoryWaitSeq[dm & 15]; - } - - cpuDmaTicksToUpdate += totalTicks; - -} - -void CPUCheckDMA(int reason, int dmamask) -{ - // DMA 0 - if((DM0CNT_H & 0x8000) && (dmamask & 1)) { - if(((DM0CNT_H >> 12) & 3) == reason) { - u32 sourceIncrement = 4; - u32 destIncrement = 4; - switch((DM0CNT_H >> 7) & 3) { - case 0: - break; - case 1: - sourceIncrement = (u32)-4; - break; - case 2: - sourceIncrement = 0; - break; - } - switch((DM0CNT_H >> 5) & 3) { - case 0: - break; - case 1: - destIncrement = (u32)-4; - break; - case 2: - destIncrement = 0; - break; - } -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_DMA0) { - int count = (DM0CNT_L ? DM0CNT_L : 0x4000) << 1; - if(DM0CNT_H & 0x0400) - count <<= 1; - log("DMA0: s=%08x d=%08x c=%04x count=%08x\n", dma0Source, dma0Dest, - DM0CNT_H, - count); - } -#endif - doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement, - DM0CNT_L ? DM0CNT_L : 0x4000, - DM0CNT_H & 0x0400); - cpuDmaHack = true; - - if(DM0CNT_H & 0x4000) { - IF |= 0x0100; - UPDATE_REG(0x202, IF); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM0CNT_H >> 5) & 3) == 3) { - dma0Dest = DM0DAD_L | (DM0DAD_H << 16); - } - - if(!(DM0CNT_H & 0x0200) || (reason == 0)) { - DM0CNT_H &= 0x7FFF; - UPDATE_REG(0xBA, DM0CNT_H); - } - } - } - - // DMA 1 - if((DM1CNT_H & 0x8000) && (dmamask & 2)) { - if(((DM1CNT_H >> 12) & 3) == reason) { - u32 sourceIncrement = 4; - u32 destIncrement = 4; - switch((DM1CNT_H >> 7) & 3) { - case 0: - break; - case 1: - sourceIncrement = (u32)-4; - break; - case 2: - sourceIncrement = 0; - break; - } - switch((DM1CNT_H >> 5) & 3) { - case 0: - break; - case 1: - destIncrement = (u32)-4; - break; - case 2: - destIncrement = 0; - break; - } - if(reason == 3) { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_DMA1) { - log("DMA1: s=%08x d=%08x c=%04x count=%08x\n", dma1Source, dma1Dest, - DM1CNT_H, - 16); - } -#endif - doDMA(dma1Source, dma1Dest, sourceIncrement, 0, 4, - 0x0400); - } else { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_DMA1) { - int count = (DM1CNT_L ? DM1CNT_L : 0x4000) << 1; - if(DM1CNT_H & 0x0400) - count <<= 1; - log("DMA1: s=%08x d=%08x c=%04x count=%08x\n", dma1Source, dma1Dest, - DM1CNT_H, - count); - } -#endif - doDMA(dma1Source, dma1Dest, sourceIncrement, destIncrement, - DM1CNT_L ? DM1CNT_L : 0x4000, - DM1CNT_H & 0x0400); - } - cpuDmaHack = true; - - if(DM1CNT_H & 0x4000) { - IF |= 0x0200; - UPDATE_REG(0x202, IF); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM1CNT_H >> 5) & 3) == 3) { - dma1Dest = DM1DAD_L | (DM1DAD_H << 16); - } - - if(!(DM1CNT_H & 0x0200) || (reason == 0)) { - DM1CNT_H &= 0x7FFF; - UPDATE_REG(0xC6, DM1CNT_H); - } - } - } - - // DMA 2 - if((DM2CNT_H & 0x8000) && (dmamask & 4)) { - if(((DM2CNT_H >> 12) & 3) == reason) { - u32 sourceIncrement = 4; - u32 destIncrement = 4; - switch((DM2CNT_H >> 7) & 3) { - case 0: - break; - case 1: - sourceIncrement = (u32)-4; - break; - case 2: - sourceIncrement = 0; - break; - } - switch((DM2CNT_H >> 5) & 3) { - case 0: - break; - case 1: - destIncrement = (u32)-4; - break; - case 2: - destIncrement = 0; - break; - } - if(reason == 3) { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_DMA2) { - int count = (4) << 2; - log("DMA2: s=%08x d=%08x c=%04x count=%08x\n", dma2Source, dma2Dest, - DM2CNT_H, - count); - } -#endif - doDMA(dma2Source, dma2Dest, sourceIncrement, 0, 4, - 0x0400); - } else { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_DMA2) { - int count = (DM2CNT_L ? DM2CNT_L : 0x4000) << 1; - if(DM2CNT_H & 0x0400) - count <<= 1; - log("DMA2: s=%08x d=%08x c=%04x count=%08x\n", dma2Source, dma2Dest, - DM2CNT_H, - count); - } -#endif - doDMA(dma2Source, dma2Dest, sourceIncrement, destIncrement, - DM2CNT_L ? DM2CNT_L : 0x4000, - DM2CNT_H & 0x0400); - } - cpuDmaHack = true; - - if(DM2CNT_H & 0x4000) { - IF |= 0x0400; - UPDATE_REG(0x202, IF); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM2CNT_H >> 5) & 3) == 3) { - dma2Dest = DM2DAD_L | (DM2DAD_H << 16); - } - - if(!(DM2CNT_H & 0x0200) || (reason == 0)) { - DM2CNT_H &= 0x7FFF; - UPDATE_REG(0xD2, DM2CNT_H); - } - } - } - - // DMA 3 - if((DM3CNT_H & 0x8000) && (dmamask & 8)) { - if(((DM3CNT_H >> 12) & 3) == reason) { - u32 sourceIncrement = 4; - u32 destIncrement = 4; - switch((DM3CNT_H >> 7) & 3) { - case 0: - break; - case 1: - sourceIncrement = (u32)-4; - break; - case 2: - sourceIncrement = 0; - break; - } - switch((DM3CNT_H >> 5) & 3) { - case 0: - break; - case 1: - destIncrement = (u32)-4; - break; - case 2: - destIncrement = 0; - break; - } -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_DMA3) { - int count = (DM3CNT_L ? DM3CNT_L : 0x10000) << 1; - if(DM3CNT_H & 0x0400) - count <<= 1; - log("DMA3: s=%08x d=%08x c=%04x count=%08x\n", dma3Source, dma3Dest, - DM3CNT_H, - count); - } -#endif - doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement, - DM3CNT_L ? DM3CNT_L : 0x10000, - DM3CNT_H & 0x0400); - if(DM3CNT_H & 0x4000) { - IF |= 0x0800; - UPDATE_REG(0x202, IF); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM3CNT_H >> 5) & 3) == 3) { - dma3Dest = DM3DAD_L | (DM3DAD_H << 16); - } - - if(!(DM3CNT_H & 0x0200) || (reason == 0)) { - DM3CNT_H &= 0x7FFF; - UPDATE_REG(0xDE, DM3CNT_H); - } - } - } -} - -void CPUUpdateRegister(u32 address, u16 value) -{ - switch(address) { - case 0x00: - { - if ((value & 7) >5) - DISPCNT = (value &7); - bool change = ((DISPCNT ^ value) & 0x80) ? true : false; - bool changeBG = ((DISPCNT ^ value) & 0x0F00) ? true : false; - u16 changeBGon = (((~DISPCNT) & value) & 0x0F00); - DISPCNT = (value & 0xFFF7); - UPDATE_REG(0x00, DISPCNT); - - if (changeBGon) - { - layerEnableDelay=4; - layerEnable = layerSettings & value & (~changeBGon); - } - else - layerEnable = layerSettings & value; - // CPUUpdateTicks(); - - windowOn = (layerEnable & 0x6000) ? true : false; - if(change && !((value & 0x80))) { - if(!(DISPSTAT & 1)) { - lcdTicks = 1008; - // VCOUNT = 0; - // UPDATE_REG(0x06, VCOUNT); - DISPSTAT &= 0xFFFC; - UPDATE_REG(0x04, DISPSTAT); - CPUCompareVCOUNT(); - } - // (*renderLine)(); - } - CPUUpdateRender(); - // we only care about changes in BG0-BG3 - if(changeBG) - CPUUpdateRenderBuffers(false); - } - break; - case 0x04: - DISPSTAT = (value & 0xFF38) | (DISPSTAT & 7); - UPDATE_REG(0x04, DISPSTAT); - break; - case 0x06: - // not writable - break; - case 0x08: - BG0CNT = (value & 0xDFCF); - UPDATE_REG(0x08, BG0CNT); - break; - case 0x0A: - BG1CNT = (value & 0xDFCF); - UPDATE_REG(0x0A, BG1CNT); - break; - case 0x0C: - BG2CNT = (value & 0xFFCF); - UPDATE_REG(0x0C, BG2CNT); - break; - case 0x0E: - BG3CNT = (value & 0xFFCF); - UPDATE_REG(0x0E, BG3CNT); - break; - case 0x10: - BG0HOFS = value & 511; - UPDATE_REG(0x10, BG0HOFS); - break; - case 0x12: - BG0VOFS = value & 511; - UPDATE_REG(0x12, BG0VOFS); - break; - case 0x14: - BG1HOFS = value & 511; - UPDATE_REG(0x14, BG1HOFS); - break; - case 0x16: - BG1VOFS = value & 511; - UPDATE_REG(0x16, BG1VOFS); - break; - case 0x18: - BG2HOFS = value & 511; - UPDATE_REG(0x18, BG2HOFS); - break; - case 0x1A: - BG2VOFS = value & 511; - UPDATE_REG(0x1A, BG2VOFS); - break; - case 0x1C: - BG3HOFS = value & 511; - UPDATE_REG(0x1C, BG3HOFS); - break; - case 0x1E: - BG3VOFS = value & 511; - UPDATE_REG(0x1E, BG3VOFS); - break; - case 0x20: - BG2PA = value; - UPDATE_REG(0x20, BG2PA); - break; - case 0x22: - BG2PB = value; - UPDATE_REG(0x22, BG2PB); - break; - case 0x24: - BG2PC = value; - UPDATE_REG(0x24, BG2PC); - break; - case 0x26: - BG2PD = value; - UPDATE_REG(0x26, BG2PD); - break; - case 0x28: - BG2X_L = value; - UPDATE_REG(0x28, BG2X_L); - gfxBG2Changed |= 1; - break; - case 0x2A: - BG2X_H = (value & 0xFFF); - UPDATE_REG(0x2A, BG2X_H); - gfxBG2Changed |= 1; - break; - case 0x2C: - BG2Y_L = value; - UPDATE_REG(0x2C, BG2Y_L); - gfxBG2Changed |= 2; - break; - case 0x2E: - BG2Y_H = value & 0xFFF; - UPDATE_REG(0x2E, BG2Y_H); - gfxBG2Changed |= 2; - break; - case 0x30: - BG3PA = value; - UPDATE_REG(0x30, BG3PA); - break; - case 0x32: - BG3PB = value; - UPDATE_REG(0x32, BG3PB); - break; - case 0x34: - BG3PC = value; - UPDATE_REG(0x34, BG3PC); - break; - case 0x36: - BG3PD = value; - UPDATE_REG(0x36, BG3PD); - break; - case 0x38: - BG3X_L = value; - UPDATE_REG(0x38, BG3X_L); - gfxBG3Changed |= 1; - break; - case 0x3A: - BG3X_H = value & 0xFFF; - UPDATE_REG(0x3A, BG3X_H); - gfxBG3Changed |= 1; - break; - case 0x3C: - BG3Y_L = value; - UPDATE_REG(0x3C, BG3Y_L); - gfxBG3Changed |= 2; - break; - case 0x3E: - BG3Y_H = value & 0xFFF; - UPDATE_REG(0x3E, BG3Y_H); - gfxBG3Changed |= 2; - break; - case 0x40: - WIN0H = value; - UPDATE_REG(0x40, WIN0H); - CPUUpdateWindow0(); - break; - case 0x42: - WIN1H = value; - UPDATE_REG(0x42, WIN1H); - CPUUpdateWindow1(); - break; - case 0x44: - WIN0V = value; - UPDATE_REG(0x44, WIN0V); - break; - case 0x46: - WIN1V = value; - UPDATE_REG(0x46, WIN1V); - break; - case 0x48: - WININ = value & 0x3F3F; - UPDATE_REG(0x48, WININ); - break; - case 0x4A: - WINOUT = value & 0x3F3F; - UPDATE_REG(0x4A, WINOUT); - break; - case 0x4C: - MOSAIC = value; - UPDATE_REG(0x4C, MOSAIC); - break; - case 0x50: - BLDMOD = value & 0x3FFF; - UPDATE_REG(0x50, BLDMOD); - fxOn = ((BLDMOD>>6)&3) != 0; - CPUUpdateRender(); - break; - case 0x52: - COLEV = value & 0x1F1F; - UPDATE_REG(0x52, COLEV); - break; - case 0x54: - COLY = value & 0x1F; - UPDATE_REG(0x54, COLY); - break; - case 0x60: - case 0x62: - case 0x64: - case 0x68: - case 0x6c: - case 0x70: - case 0x72: - case 0x74: - case 0x78: - case 0x7c: - case 0x80: - case 0x84: - soundEvent(address&0xFF, (u8)(value & 0xFF)); - soundEvent((address&0xFF)+1, (u8)(value>>8)); - break; - case 0x82: - case 0x88: - case 0xa0: - case 0xa2: - case 0xa4: - case 0xa6: - case 0x90: - case 0x92: - case 0x94: - case 0x96: - case 0x98: - case 0x9a: - case 0x9c: - case 0x9e: - soundEvent(address&0xFF, value); - break; - case 0xB0: - DM0SAD_L = value; - UPDATE_REG(0xB0, DM0SAD_L); - break; - case 0xB2: - DM0SAD_H = value & 0x07FF; - UPDATE_REG(0xB2, DM0SAD_H); - break; - case 0xB4: - DM0DAD_L = value; - UPDATE_REG(0xB4, DM0DAD_L); - break; - case 0xB6: - DM0DAD_H = value & 0x07FF; - UPDATE_REG(0xB6, DM0DAD_H); - break; - case 0xB8: - DM0CNT_L = value & 0x3FFF; - UPDATE_REG(0xB8, 0); - break; - case 0xBA: - { - bool start = ((DM0CNT_H ^ value) & 0x8000) ? true : false; - value &= 0xF7E0; - - DM0CNT_H = value; - UPDATE_REG(0xBA, DM0CNT_H); - - if(start && (value & 0x8000)) { - dma0Source = DM0SAD_L | (DM0SAD_H << 16); - dma0Dest = DM0DAD_L | (DM0DAD_H << 16); - CPUCheckDMA(0, 1); - } - } - break; - case 0xBC: - DM1SAD_L = value; - UPDATE_REG(0xBC, DM1SAD_L); - break; - case 0xBE: - DM1SAD_H = value & 0x0FFF; - UPDATE_REG(0xBE, DM1SAD_H); - break; - case 0xC0: - DM1DAD_L = value; - UPDATE_REG(0xC0, DM1DAD_L); - break; - case 0xC2: - DM1DAD_H = value & 0x07FF; - UPDATE_REG(0xC2, DM1DAD_H); - break; - case 0xC4: - DM1CNT_L = value & 0x3FFF; - UPDATE_REG(0xC4, 0); - break; - case 0xC6: - { - bool start = ((DM1CNT_H ^ value) & 0x8000) ? true : false; - value &= 0xF7E0; - - DM1CNT_H = value; - UPDATE_REG(0xC6, DM1CNT_H); - - if(start && (value & 0x8000)) { - dma1Source = DM1SAD_L | (DM1SAD_H << 16); - dma1Dest = DM1DAD_L | (DM1DAD_H << 16); - CPUCheckDMA(0, 2); - } - } - break; - case 0xC8: - DM2SAD_L = value; - UPDATE_REG(0xC8, DM2SAD_L); - break; - case 0xCA: - DM2SAD_H = value & 0x0FFF; - UPDATE_REG(0xCA, DM2SAD_H); - break; - case 0xCC: - DM2DAD_L = value; - UPDATE_REG(0xCC, DM2DAD_L); - break; - case 0xCE: - DM2DAD_H = value & 0x07FF; - UPDATE_REG(0xCE, DM2DAD_H); - break; - case 0xD0: - DM2CNT_L = value & 0x3FFF; - UPDATE_REG(0xD0, 0); - break; - case 0xD2: - { - bool start = ((DM2CNT_H ^ value) & 0x8000) ? true : false; - - value &= 0xF7E0; - - DM2CNT_H = value; - UPDATE_REG(0xD2, DM2CNT_H); - - if(start && (value & 0x8000)) { - dma2Source = DM2SAD_L | (DM2SAD_H << 16); - dma2Dest = DM2DAD_L | (DM2DAD_H << 16); - - CPUCheckDMA(0, 4); - } - } - break; - case 0xD4: - DM3SAD_L = value; - UPDATE_REG(0xD4, DM3SAD_L); - break; - case 0xD6: - DM3SAD_H = value & 0x0FFF; - UPDATE_REG(0xD6, DM3SAD_H); - break; - case 0xD8: - DM3DAD_L = value; - UPDATE_REG(0xD8, DM3DAD_L); - break; - case 0xDA: - DM3DAD_H = value & 0x0FFF; - UPDATE_REG(0xDA, DM3DAD_H); - break; - case 0xDC: - DM3CNT_L = value; - UPDATE_REG(0xDC, 0); - break; - case 0xDE: - { - bool start = ((DM3CNT_H ^ value) & 0x8000) ? true : false; - - value &= 0xFFE0; - - DM3CNT_H = value; - UPDATE_REG(0xDE, DM3CNT_H); - - if(start && (value & 0x8000)) { - dma3Source = DM3SAD_L | (DM3SAD_H << 16); - dma3Dest = DM3DAD_L | (DM3DAD_H << 16); - CPUCheckDMA(0,8); - } - } - break; - case 0x100: - timer0Reload = value; - interp_rate(); - break; - case 0x102: - timer0Value = value; - timerOnOffDelay|=1; - cpuNextEvent = cpuTotalTicks; - break; - case 0x104: - timer1Reload = value; - interp_rate(); - break; - case 0x106: - timer1Value = value; - timerOnOffDelay|=2; - cpuNextEvent = cpuTotalTicks; - break; - case 0x108: - timer2Reload = value; - break; - case 0x10A: - timer2Value = value; - timerOnOffDelay|=4; - cpuNextEvent = cpuTotalTicks; - break; - case 0x10C: - timer3Reload = value; - break; - case 0x10E: - timer3Value = value; - timerOnOffDelay|=8; - cpuNextEvent = cpuTotalTicks; - break; - case 0x128: - #ifdef LINK_EMULATION - if (linkenable) - { - StartLink(value); - } - else -#endif - { - if(value & 0x80) { - value &= 0xff7f; - if(value & 1 && (value & 0x4000)) { - UPDATE_REG(0x12a, 0xFF); - IF |= 0x80; - UPDATE_REG(0x202, IF); - value &= 0x7f7f; - } - } - UPDATE_REG(0x128, value); - } - break; - case 0x12a: - #ifdef LINK_EMULATION - if(linkenable && lspeed) - LinkSSend(value); - #endif - { - UPDATE_REG(0x134, value); - } - break; - case 0x130: - P1 |= (value & 0x3FF); - UPDATE_REG(0x130, P1); - break; - case 0x132: - UPDATE_REG(0x132, value & 0xC3FF); - break; - case 0x134: -#ifdef LINK_EMULATION - if (linkenable) - StartGPLink(value); - else -#endif - UPDATE_REG(0x134, value); - - break; - case 0x140: -#ifdef LINK_EMULATION - if (linkenable) - StartJOYLink(value); - else -#endif - UPDATE_REG(0x140, value); - - break; - case 0x200: - IE = value & 0x3FFF; - UPDATE_REG(0x200, IE); - if ((IME & 1) && (IF & IE) && armIrqEnable) - cpuNextEvent = cpuTotalTicks; - break; - case 0x202: - IF ^= (value & IF); - UPDATE_REG(0x202, IF); - break; - case 0x204: - { - memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3]; - - if(!speedHack) { - memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 3]; - memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = - gamepakWaitState0[(value >> 4) & 1]; - - memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 3]; - memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = - gamepakWaitState1[(value >> 7) & 1]; - - memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 3]; - memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = - gamepakWaitState2[(value >> 10) & 1]; - } else { - memoryWait[0x08] = memoryWait[0x09] = 3; - memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 1; - - memoryWait[0x0a] = memoryWait[0x0b] = 3; - memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 1; - - memoryWait[0x0c] = memoryWait[0x0d] = 3; - memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 1; - } - - for(int i = 8; i < 15; i++) { - memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1; - memoryWaitSeq32[i] = memoryWaitSeq[i]*2 + 1; - } - - if((value & 0x4000) == 0x4000) { - busPrefetchEnable = true; - busPrefetch = false; - busPrefetchCount = 0; - } else { - busPrefetchEnable = false; - busPrefetch = false; - busPrefetchCount = 0; - } - UPDATE_REG(0x204, value & 0x7FFF); - - } - break; - case 0x208: - IME = value & 1; - UPDATE_REG(0x208, IME); - if ((IME & 1) && (IF & IE) && armIrqEnable) - cpuNextEvent = cpuTotalTicks; - break; - case 0x300: - if(value != 0) - value &= 0xFFFE; - UPDATE_REG(0x300, value); - break; - default: - UPDATE_REG(address&0x3FE, value); - break; - } -} - -void applyTimer () -{ - if (timerOnOffDelay & 1) - { - timer0ClockReload = TIMER_TICKS[timer0Value & 3]; - if(!timer0On && (timer0Value & 0x80)) { - // reload the counter - TM0D = timer0Reload; - timer0Ticks = (0x10000 - TM0D) << timer0ClockReload; - UPDATE_REG(0x100, TM0D); - } - timer0On = timer0Value & 0x80 ? true : false; - TM0CNT = timer0Value & 0xC7; - interp_rate(); - UPDATE_REG(0x102, TM0CNT); - // CPUUpdateTicks(); - } - if (timerOnOffDelay & 2) - { - timer1ClockReload = TIMER_TICKS[timer1Value & 3]; - if(!timer1On && (timer1Value & 0x80)) { - // reload the counter - TM1D = timer1Reload; - timer1Ticks = (0x10000 - TM1D) << timer1ClockReload; - UPDATE_REG(0x104, TM1D); - } - timer1On = timer1Value & 0x80 ? true : false; - TM1CNT = timer1Value & 0xC7; - interp_rate(); - UPDATE_REG(0x106, TM1CNT); - } - if (timerOnOffDelay & 4) - { - timer2ClockReload = TIMER_TICKS[timer2Value & 3]; - if(!timer2On && (timer2Value & 0x80)) { - // reload the counter - TM2D = timer2Reload; - timer2Ticks = (0x10000 - TM2D) << timer2ClockReload; - UPDATE_REG(0x108, TM2D); - } - timer2On = timer2Value & 0x80 ? true : false; - TM2CNT = timer2Value & 0xC7; - UPDATE_REG(0x10A, TM2CNT); - } - if (timerOnOffDelay & 8) - { - timer3ClockReload = TIMER_TICKS[timer3Value & 3]; - if(!timer3On && (timer3Value & 0x80)) { - // reload the counter - TM3D = timer3Reload; - timer3Ticks = (0x10000 - TM3D) << timer3ClockReload; - UPDATE_REG(0x10C, TM3D); - } - timer3On = timer3Value & 0x80 ? true : false; - TM3CNT = timer3Value & 0xC7; - UPDATE_REG(0x10E, TM3CNT); - } - cpuNextEvent = CPUUpdateTicks(); - timerOnOffDelay = 0; -} - -u8 cpuBitsSet[256]; -u8 cpuLowestBitSet[256]; - -void CPUInit(const char *biosFileName, bool useBiosFile) -{ -#ifdef WORDS_BIGENDIAN - if(!cpuBiosSwapped) { - for(unsigned int i = 0; i < sizeof(myROM)/4; i++) { - WRITE32LE(&myROM[i], myROM[i]); - } - cpuBiosSwapped = true; - } -#endif - gbaSaveType = 0; - eepromInUse = 0; - saveType = 0; - useBios = false; - - if(useBiosFile) { - int size = 0x4000; - if(utilLoad(biosFileName, - CPUIsGBABios, - bios, - size)) { - if(size == 0x4000) - useBios = true; - else - systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BIOS file size")); - } - } - - if(!useBios) { - memcpy(bios, myROM, sizeof(myROM)); - } - - int i = 0; - - biosProtected[0] = 0x00; - biosProtected[1] = 0xf0; - biosProtected[2] = 0x29; - biosProtected[3] = 0xe1; - - for(i = 0; i < 256; i++) { - int count = 0; - int j; - for(j = 0; j < 8; j++) - if(i & (1 << j)) - count++; - cpuBitsSet[i] = count; - - for(j = 0; j < 8; j++) - if(i & (1 << j)) - break; - cpuLowestBitSet[i] = j; - } - - for(i = 0; i < 0x400; i++) - ioReadable[i] = true; - for(i = 0x10; i < 0x48; i++) - ioReadable[i] = false; - for(i = 0x4c; i < 0x50; i++) - ioReadable[i] = false; - for(i = 0x54; i < 0x60; i++) - ioReadable[i] = false; - for(i = 0x8c; i < 0x90; i++) - ioReadable[i] = false; - for(i = 0xa0; i < 0xb8; i++) - ioReadable[i] = false; - for(i = 0xbc; i < 0xc4; i++) - ioReadable[i] = false; - for(i = 0xc8; i < 0xd0; i++) - ioReadable[i] = false; - for(i = 0xd4; i < 0xdc; i++) - ioReadable[i] = false; - for(i = 0xe0; i < 0x100; i++) - ioReadable[i] = false; - for(i = 0x110; i < 0x120; i++) - ioReadable[i] = false; - for(i = 0x12c; i < 0x130; i++) - ioReadable[i] = false; - for(i = 0x138; i < 0x140; i++) - ioReadable[i] = false; - for(i = 0x144; i < 0x150; i++) - ioReadable[i] = false; - for(i = 0x15c; i < 0x200; i++) - ioReadable[i] = false; - for(i = 0x20c; i < 0x300; i++) - ioReadable[i] = false; - for(i = 0x304; i < 0x400; i++) - ioReadable[i] = false; - - if(romSize < 0x1fe2000) { - *((u16 *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA - *((u16 *)&rom[0x1fe209e]) = 0x4770; // BX LR - } else { - agbPrintEnable(false); - } -} - -void CPUReset() -{ - if(gbaSaveType == 0) { - if(eepromInUse) - gbaSaveType = 3; - else - switch(saveType) { - case 1: - gbaSaveType = 1; - break; - case 2: - gbaSaveType = 2; - break; - } - } - rtcReset(); - // clean registers - memset(®[0], 0, sizeof(reg)); - // clean OAM - memset(oam, 0, 0x400); - // clean palette - memset(paletteRAM, 0, 0x400); - // clean picture - memset(pix, 0, 4*160*240); - // clean vram - memset(vram, 0, 0x20000); - // clean io memory - memset(ioMem, 0, 0x400); - - DISPCNT = 0x0080; - DISPSTAT = 0x0000; - VCOUNT = (useBios && !skipBios) ? 0 :0x007E; - BG0CNT = 0x0000; - BG1CNT = 0x0000; - BG2CNT = 0x0000; - BG3CNT = 0x0000; - BG0HOFS = 0x0000; - BG0VOFS = 0x0000; - BG1HOFS = 0x0000; - BG1VOFS = 0x0000; - BG2HOFS = 0x0000; - BG2VOFS = 0x0000; - BG3HOFS = 0x0000; - BG3VOFS = 0x0000; - BG2PA = 0x0100; - BG2PB = 0x0000; - BG2PC = 0x0000; - BG2PD = 0x0100; - BG2X_L = 0x0000; - BG2X_H = 0x0000; - BG2Y_L = 0x0000; - BG2Y_H = 0x0000; - BG3PA = 0x0100; - BG3PB = 0x0000; - BG3PC = 0x0000; - BG3PD = 0x0100; - BG3X_L = 0x0000; - BG3X_H = 0x0000; - BG3Y_L = 0x0000; - BG3Y_H = 0x0000; - WIN0H = 0x0000; - WIN1H = 0x0000; - WIN0V = 0x0000; - WIN1V = 0x0000; - WININ = 0x0000; - WINOUT = 0x0000; - MOSAIC = 0x0000; - BLDMOD = 0x0000; - COLEV = 0x0000; - COLY = 0x0000; - DM0SAD_L = 0x0000; - DM0SAD_H = 0x0000; - DM0DAD_L = 0x0000; - DM0DAD_H = 0x0000; - DM0CNT_L = 0x0000; - DM0CNT_H = 0x0000; - DM1SAD_L = 0x0000; - DM1SAD_H = 0x0000; - DM1DAD_L = 0x0000; - DM1DAD_H = 0x0000; - DM1CNT_L = 0x0000; - DM1CNT_H = 0x0000; - DM2SAD_L = 0x0000; - DM2SAD_H = 0x0000; - DM2DAD_L = 0x0000; - DM2DAD_H = 0x0000; - DM2CNT_L = 0x0000; - DM2CNT_H = 0x0000; - DM3SAD_L = 0x0000; - DM3SAD_H = 0x0000; - DM3DAD_L = 0x0000; - DM3DAD_H = 0x0000; - DM3CNT_L = 0x0000; - DM3CNT_H = 0x0000; - TM0D = 0x0000; - TM0CNT = 0x0000; - TM1D = 0x0000; - TM1CNT = 0x0000; - TM2D = 0x0000; - TM2CNT = 0x0000; - TM3D = 0x0000; - TM3CNT = 0x0000; - P1 = 0x03FF; - IE = 0x0000; - IF = 0x0000; - IME = 0x0000; - - armMode = 0x1F; - - if(cpuIsMultiBoot) { - reg[13].I = 0x03007F00; - reg[15].I = 0x02000000; - reg[16].I = 0x00000000; - reg[R13_IRQ].I = 0x03007FA0; - reg[R13_SVC].I = 0x03007FE0; - armIrqEnable = true; - } else { - if(useBios && !skipBios) { - reg[15].I = 0x00000000; - armMode = 0x13; - armIrqEnable = false; - } else { - reg[13].I = 0x03007F00; - reg[15].I = 0x08000000; - reg[16].I = 0x00000000; - reg[R13_IRQ].I = 0x03007FA0; - reg[R13_SVC].I = 0x03007FE0; - armIrqEnable = true; - } - } - armState = true; - C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false; - UPDATE_REG(0x00, DISPCNT); - UPDATE_REG(0x06, VCOUNT); - UPDATE_REG(0x20, BG2PA); - UPDATE_REG(0x26, BG2PD); - UPDATE_REG(0x30, BG3PA); - UPDATE_REG(0x36, BG3PD); - UPDATE_REG(0x130, P1); - UPDATE_REG(0x88, 0x200); - - // disable FIQ - reg[16].I |= 0x40; - - CPUUpdateCPSR(); - - armNextPC = reg[15].I; - reg[15].I += 4; - - // reset internal state - holdState = false; - holdType = 0; - - biosProtected[0] = 0x00; - biosProtected[1] = 0xf0; - biosProtected[2] = 0x29; - biosProtected[3] = 0xe1; - - lcdTicks = (useBios && !skipBios) ? 1008 : 208; - timer0On = false; - timer0Ticks = 0; - timer0Reload = 0; - timer0ClockReload = 0; - timer1On = false; - timer1Ticks = 0; - timer1Reload = 0; - timer1ClockReload = 0; - timer2On = false; - timer2Ticks = 0; - timer2Reload = 0; - timer2ClockReload = 0; - timer3On = false; - timer3Ticks = 0; - timer3Reload = 0; - timer3ClockReload = 0; - dma0Source = 0; - dma0Dest = 0; - dma1Source = 0; - dma1Dest = 0; - dma2Source = 0; - dma2Dest = 0; - dma3Source = 0; - dma3Dest = 0; - cpuSaveGameFunc = flashSaveDecide; - renderLine = mode0RenderLine; - fxOn = false; - windowOn = false; - frameCount = 0; - saveType = 0; - layerEnable = DISPCNT & layerSettings; - - CPUUpdateRenderBuffers(true); - - for(int i = 0; i < 256; i++) { - map[i].address = (u8 *)&dummyAddress; - map[i].mask = 0; - } - - map[0].address = bios; - map[0].mask = 0x3FFF; - map[2].address = workRAM; - map[2].mask = 0x3FFFF; - map[3].address = internalRAM; - map[3].mask = 0x7FFF; - map[4].address = ioMem; - map[4].mask = 0x3FF; - map[5].address = paletteRAM; - map[5].mask = 0x3FF; - map[6].address = vram; - map[6].mask = 0x1FFFF; - map[7].address = oam; - map[7].mask = 0x3FF; - map[8].address = rom; - map[8].mask = 0x1FFFFFF; - map[9].address = rom; - map[9].mask = 0x1FFFFFF; - map[10].address = rom; - map[10].mask = 0x1FFFFFF; - map[12].address = rom; - map[12].mask = 0x1FFFFFF; - map[14].address = flashSaveMemory; - map[14].mask = 0xFFFF; - - eepromReset(); - flashReset(); - - soundReset(); - - CPUUpdateWindow0(); - CPUUpdateWindow1(); - - // make sure registers are correctly initialized if not using BIOS - if(!useBios) { - if(cpuIsMultiBoot) - BIOS_RegisterRamReset(0xfe); - else - BIOS_RegisterRamReset(0xff); - } else { - if(cpuIsMultiBoot) - BIOS_RegisterRamReset(0xfe); - } - - switch(cpuSaveType) { - case 0: // automatic - cpuSramEnabled = true; - cpuFlashEnabled = true; - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = false; - saveType = gbaSaveType = 0; - break; - case 1: // EEPROM - cpuSramEnabled = false; - cpuFlashEnabled = false; - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = false; - saveType = gbaSaveType = 3; - // EEPROM usage is automatically detected - break; - case 2: // SRAM - cpuSramEnabled = true; - cpuFlashEnabled = false; - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = sramDelayedWrite; // to insure we detect the write - saveType = gbaSaveType = 1; - break; - case 3: // FLASH - cpuSramEnabled = false; - cpuFlashEnabled = true; - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = flashDelayedWrite; // to insure we detect the write - saveType = gbaSaveType = 2; - break; - case 4: // EEPROM+Sensor - cpuSramEnabled = false; - cpuFlashEnabled = false; - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = true; - // EEPROM usage is automatically detected - saveType = gbaSaveType = 3; - break; - case 5: // NONE - cpuSramEnabled = false; - cpuFlashEnabled = false; - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - // no save at all - saveType = gbaSaveType = 5; - break; - } - - ARM_PREFETCH; - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - - cpuDmaHack = false; - - lastTime = systemGetClock(); - - SWITicks = 0; -} - -void CPUInterrupt() -{ - u32 PC = reg[15].I; - bool savedState = armState; - CPUSwitchMode(0x12, true, false); - reg[14].I = PC; - if(!savedState) - reg[14].I += 2; - reg[15].I = 0x18; - armState = true; - armIrqEnable = false; - - armNextPC = reg[15].I; - reg[15].I += 4; - ARM_PREFETCH; - - // if(!holdState) - biosProtected[0] = 0x02; - biosProtected[1] = 0xc0; - biosProtected[2] = 0x5e; - biosProtected[3] = 0xe5; -} - -#ifdef SDL -void log(const char *defaultMsg, ...) -{ - char buffer[2048]; - va_list valist; - - va_start(valist, defaultMsg); - vsprintf(buffer, defaultMsg, valist); - - if(out == NULL) { - out = fopen("trace.log","w"); - } - - fputs(buffer, out); - - va_end(valist); -} -#else -extern void winlog(const char *, ...); -#endif - -void CPULoop(int ticks) -{ - int clockTicks; - int timerOverflow = 0; - // variable used by the CPU core - cpuTotalTicks = 0; -#ifdef LINK_EMULATION - if(linkenable) - cpuNextEvent = 1; -#endif - cpuBreakLoop = false; - cpuNextEvent = CPUUpdateTicks(); - if(cpuNextEvent > ticks) - cpuNextEvent = ticks; - - - for(;;) { -#ifndef FINAL_VERSION - if(systemDebug) { - if(systemDebug >= 10 && !holdState) { - CPUUpdateCPSR(); -#ifdef BKPT_SUPPORT - if (debugger_last) - { - sprintf(buffer, "R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n", - oldreg[0], oldreg[1], oldreg[2], oldreg[3], oldreg[4], oldreg[5], - oldreg[6], oldreg[7], oldreg[8], oldreg[9], oldreg[10], oldreg[11], - oldreg[12], oldreg[13], oldreg[14], oldreg[15], oldreg[16], - oldreg[17]); - } -#endif - sprintf(buffer, "R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n", - reg[0].I, reg[1].I, reg[2].I, reg[3].I, reg[4].I, reg[5].I, - reg[6].I, reg[7].I, reg[8].I, reg[9].I, reg[10].I, reg[11].I, - reg[12].I, reg[13].I, reg[14].I, reg[15].I, reg[16].I, - reg[17].I); -#ifdef SDL - log(buffer); -#else - winlog(buffer); -#endif - } else if(!holdState) { - sprintf(buffer, "PC=%08x\n", armNextPC); -#ifdef SDL - log(buffer); -#else - winlog(buffer); -#endif - } - } -#endif /* FINAL_VERSION */ - - if(!holdState && !SWITicks) { - if(armState) { - if (!armExecute()) - return; - } else { - if (!thumbExecute()) - return; - } - clockTicks = 0; - } else - clockTicks = CPUUpdateTicks(); - - cpuTotalTicks += clockTicks; - - - if(cpuTotalTicks >= cpuNextEvent) { - int remainingTicks = cpuTotalTicks - cpuNextEvent; - - if (SWITicks) - { - SWITicks-=clockTicks; - if (SWITicks<0) - SWITicks = 0; - } - - clockTicks = cpuNextEvent; - cpuTotalTicks = 0; - cpuDmaHack = false; - - updateLoop: - - if (IRQTicks) - { - IRQTicks -= clockTicks; - if (IRQTicks<0) - IRQTicks = 0; - } - - lcdTicks -= clockTicks; - - - if(lcdTicks <= 0) { - if(DISPSTAT & 1) { // V-BLANK - // if in V-Blank mode, keep computing... - if(DISPSTAT & 2) { - lcdTicks += 1008; - VCOUNT++; - UPDATE_REG(0x06, VCOUNT); - DISPSTAT &= 0xFFFD; - UPDATE_REG(0x04, DISPSTAT); - CPUCompareVCOUNT(); - } else { - lcdTicks += 224; - DISPSTAT |= 2; - UPDATE_REG(0x04, DISPSTAT); - if(DISPSTAT & 16) { - IF |= 2; - UPDATE_REG(0x202, IF); - } - } - - if(VCOUNT >= 228) { //Reaching last line - DISPSTAT &= 0xFFFC; - UPDATE_REG(0x04, DISPSTAT); - VCOUNT = 0; - UPDATE_REG(0x06, VCOUNT); - CPUCompareVCOUNT(); - } - } else { - int framesToSkip = systemFrameSkip; - if(speedup) - framesToSkip = 9; // try 6 FPS during speedup - - if(DISPSTAT & 2) { - // if in H-Blank, leave it and move to drawing mode - VCOUNT++; - UPDATE_REG(0x06, VCOUNT); - - lcdTicks += 1008; - DISPSTAT &= 0xFFFD; - if(VCOUNT == 160) { - count++; - systemFrame(); - - if((count % 10) == 0) { - system10Frames(60); - } - if(count == 60) { - u32 time = systemGetClock(); - if(time != lastTime) { - u32 t = 100000/(time - lastTime); - systemShowSpeed(t); - } else - systemShowSpeed(0); - lastTime = time; - count = 0; - } - u32 joy = 0; - // update joystick information - if(systemReadJoypads()) - // read default joystick - joy = systemReadJoypad(-1); - P1 = 0x03FF ^ (joy & 0x3FF); - if(cpuEEPROMSensorEnabled) - systemUpdateMotionSensor(); - UPDATE_REG(0x130, P1); - u16 P1CNT = READ16LE(((u16 *)&ioMem[0x132])); - // this seems wrong, but there are cases where the game - // can enter the stop state without requesting an IRQ from - // the joypad. - if((P1CNT & 0x4000) || stopState) { - u16 p1 = (0x3FF ^ P1) & 0x3FF; - if(P1CNT & 0x8000) { - if(p1 == (P1CNT & 0x3FF)) { - IF |= 0x1000; - UPDATE_REG(0x202, IF); - } - } else { - if(p1 & P1CNT) { - IF |= 0x1000; - UPDATE_REG(0x202, IF); - } - } - } - - u32 ext = (joy >> 10); - // If no (m) code is enabled, apply the cheats at each LCDline - if((cheatsEnabled) && (mastercode==0)) - remainingTicks += cheatsCheckKeys(P1^0x3FF, ext); - speedup = (ext & 1) ? true : false; - capture = (ext & 2) ? true : false; - - if(capture && !capturePrevious) { - captureNumber++; - systemScreenCapture(captureNumber); - } - capturePrevious = capture; - - DISPSTAT |= 1; - DISPSTAT &= 0xFFFD; - UPDATE_REG(0x04, DISPSTAT); - if(DISPSTAT & 0x0008) { - IF |= 1; - UPDATE_REG(0x202, IF); - } - CPUCheckDMA(1, 0x0f); - if(frameCount >= framesToSkip) { - systemDrawScreen(); - frameCount = 0; - } else - frameCount++; - if(systemPauseOnFrame()) - ticks = 0; - } - - UPDATE_REG(0x04, DISPSTAT); - CPUCompareVCOUNT(); - - } else { - if(frameCount >= framesToSkip) - { - (*renderLine)(); - switch(systemColorDepth) { - case 16: - { - u16 *dest = (u16 *)pix + 242 * (VCOUNT+1); - for(int x = 0; x < 240;) { - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; - } - // for filters that read past the screen - *dest++ = 0; - } - break; - case 24: - { - u8 *dest = (u8 *)pix + 240 * VCOUNT * 3; - for(int x = 0; x < 240;) { - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; - dest += 3; - } - } - break; - case 32: - { - u32 *dest = (u32 *)pix + 241 * (VCOUNT+1); - for(int x = 0; x < 240; ) { - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - } - } - break; - } - } - // entering H-Blank - DISPSTAT |= 2; - UPDATE_REG(0x04, DISPSTAT); - lcdTicks += 224; - CPUCheckDMA(2, 0x0f); - if(DISPSTAT & 16) { - IF |= 2; - UPDATE_REG(0x202, IF); - } - } - } - } - - // we shouldn't be doing sound in stop state, but we loose synchronization - // if sound is disabled, so in stop state, soundTick will just produce - // mute sound - soundTicks -= clockTicks; - if(soundTicks <= 0) { - psoundTickfn(); - soundTicks += SOUND_CLOCK_TICKS; - } - - if(!stopState) { - if(timer0On) { - timer0Ticks -= clockTicks; - if(timer0Ticks <= 0) { - timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload; - timerOverflow |= 1; - soundTimerOverflow(0); - if(TM0CNT & 0x40) { - IF |= 0x08; - UPDATE_REG(0x202, IF); - } - } - TM0D = 0xFFFF - (timer0Ticks >> timer0ClockReload); - UPDATE_REG(0x100, TM0D); - } - - if(timer1On) { - if(TM1CNT & 4) { - if(timerOverflow & 1) { - TM1D++; - if(TM1D == 0) { - TM1D += timer1Reload; - timerOverflow |= 2; - soundTimerOverflow(1); - if(TM1CNT & 0x40) { - IF |= 0x10; - UPDATE_REG(0x202, IF); - } - } - UPDATE_REG(0x104, TM1D); - } - } else { - timer1Ticks -= clockTicks; - if(timer1Ticks <= 0) { - timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload; - timerOverflow |= 2; - soundTimerOverflow(1); - if(TM1CNT & 0x40) { - IF |= 0x10; - UPDATE_REG(0x202, IF); - } - } - TM1D = 0xFFFF - (timer1Ticks >> timer1ClockReload); - UPDATE_REG(0x104, TM1D); - } - } - - if(timer2On) { - if(TM2CNT & 4) { - if(timerOverflow & 2) { - TM2D++; - if(TM2D == 0) { - TM2D += timer2Reload; - timerOverflow |= 4; - if(TM2CNT & 0x40) { - IF |= 0x20; - UPDATE_REG(0x202, IF); - } - } - UPDATE_REG(0x108, TM2D); - } - } else { - timer2Ticks -= clockTicks; - if(timer2Ticks <= 0) { - timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload; - timerOverflow |= 4; - if(TM2CNT & 0x40) { - IF |= 0x20; - UPDATE_REG(0x202, IF); - } - } - TM2D = 0xFFFF - (timer2Ticks >> timer2ClockReload); - UPDATE_REG(0x108, TM2D); - } - } - - if(timer3On) { - if(TM3CNT & 4) { - if(timerOverflow & 4) { - TM3D++; - if(TM3D == 0) { - TM3D += timer3Reload; - if(TM3CNT & 0x40) { - IF |= 0x40; - UPDATE_REG(0x202, IF); - } - } - UPDATE_REG(0x10C, TM3D); - } - } else { - timer3Ticks -= clockTicks; - if(timer3Ticks <= 0) { - timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload; - if(TM3CNT & 0x40) { - IF |= 0x40; - UPDATE_REG(0x202, IF); - } - } - TM3D = 0xFFFF - (timer3Ticks >> timer3ClockReload); - UPDATE_REG(0x10C, TM3D); - } - } - } - - timerOverflow = 0; - - - -#ifdef PROFILING - profilingTicks -= clockTicks; - if(profilingTicks <= 0) { - profilingTicks += profilingTicksReload; - if(profilSegment) { - profile_segment *seg = profilSegment; - do { - u16 *b = (u16 *)seg->sbuf; - int pc = ((reg[15].I - seg->s_lowpc) * seg->s_scale)/0x10000; - if(pc >= 0 && pc < seg->ssiz) { - b[pc]++; - break; - } - - seg = seg->next; - } while(seg); - } - } -#endif - - ticks -= clockTicks; -#ifdef LINK_EMULATION - if (linkenable) - LinkUpdate(clockTicks); -#endif - cpuNextEvent = CPUUpdateTicks(); - - if(cpuDmaTicksToUpdate > 0) { - if(cpuDmaTicksToUpdate > cpuNextEvent) - clockTicks = cpuNextEvent; - else - clockTicks = cpuDmaTicksToUpdate; - cpuDmaTicksToUpdate -= clockTicks; - if(cpuDmaTicksToUpdate < 0) - cpuDmaTicksToUpdate = 0; - cpuDmaHack = true; - goto updateLoop; - } -#ifdef LINK_EMULATION - if(linkenable) - cpuNextEvent = 1; -#endif - if(IF && (IME & 1) && armIrqEnable) { - int res = IF & IE; - if(stopState) - res &= 0x3080; - if(res) { - if (intState) - { - if (!IRQTicks) - { - CPUInterrupt(); - intState = false; - holdState = false; - stopState = false; - holdType = 0; - } - } - else - { - if (!holdState) - { - intState = true; - IRQTicks=7; - if (cpuNextEvent> IRQTicks) - cpuNextEvent = IRQTicks; - } - else - { - CPUInterrupt(); - holdState = false; - stopState = false; - holdType = 0; - } - } - - // Stops the SWI Ticks emulation if an IRQ is executed - //(to avoid problems with nested IRQ/SWI) - if (SWITicks) - SWITicks = 0; - } - } - - if(remainingTicks > 0) { - if(remainingTicks > cpuNextEvent) - clockTicks = cpuNextEvent; - else - clockTicks = remainingTicks; - remainingTicks -= clockTicks; - if(remainingTicks < 0) - remainingTicks = 0; - goto updateLoop; - } - - if (timerOnOffDelay) - applyTimer(); - - if(cpuNextEvent > ticks) - cpuNextEvent = ticks; - - if(ticks <= 0 || cpuBreakLoop) - break; - - } - } -} - - - -struct EmulatedSystem GBASystem = { - // emuMain - CPULoop, - // emuReset - CPUReset, - // emuCleanUp - CPUCleanUp, - // emuReadBattery - CPUReadBatteryFile, - // emuWriteBattery - CPUWriteBatteryFile, - // emuReadState - CPUReadState, - // emuWriteState - CPUWriteState, - // emuReadMemState - CPUReadMemState, - // emuWriteMemState - CPUWriteMemState, - // emuWritePNG - CPUWritePNGFile, - // emuWriteBMP - CPUWriteBMPFile, - // emuUpdateCPSR - CPUUpdateCPSR, - // emuHasDebugger - true, - // emuCount -#ifdef FINAL_VERSION - 250000 -#else - 5000 -#endif -}; diff --git a/src/agb/GBA.h b/src/agb/GBA.h deleted file mode 100644 index b173a6ee..00000000 --- a/src/agb/GBA.h +++ /dev/null @@ -1,160 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef VBA_GBA_H -#define VBA_GBA_H - -#include "../System.h" - -#define SAVE_GAME_VERSION_1 1 -#define SAVE_GAME_VERSION_2 2 -#define SAVE_GAME_VERSION_3 3 -#define SAVE_GAME_VERSION_4 4 -#define SAVE_GAME_VERSION_5 5 -#define SAVE_GAME_VERSION_6 6 -#define SAVE_GAME_VERSION_7 7 -#define SAVE_GAME_VERSION_8 8 -#define SAVE_GAME_VERSION_9 9 -#define SAVE_GAME_VERSION_10 10 -#define SAVE_GAME_VERSION SAVE_GAME_VERSION_10 - -typedef struct { - u8 *address; - u32 mask; -} memoryMap; - -typedef union { - struct { -#ifdef WORDS_BIGENDIAN - u8 B3; - u8 B2; - u8 B1; - u8 B0; -#else - u8 B0; - u8 B1; - u8 B2; - u8 B3; -#endif - } B; - struct { -#ifdef WORDS_BIGENDIAN - u16 W1; - u16 W0; -#else - u16 W0; - u16 W1; -#endif - } W; -#ifdef WORDS_BIGENDIAN - volatile u32 I; -#else - u32 I; -#endif -} reg_pair; - -#ifndef NO_GBA_MAP -extern memoryMap map[256]; -#endif - -extern reg_pair reg[45]; -extern u8 biosProtected[4]; - -extern bool N_FLAG; -extern bool Z_FLAG; -extern bool C_FLAG; -extern bool V_FLAG; -extern bool armIrqEnable; -extern bool armState; -extern int armMode; -extern void (*cpuSaveGameFunc)(u32,u8); - -#ifdef BKPT_SUPPORT -extern u8 freezeWorkRAM[0x40000]; -extern u8 freezeInternalRAM[0x8000]; -extern u8 freezeVRAM[0x18000]; -extern u8 freezeOAM[0x400]; -extern u8 freezePRAM[0x400]; -extern bool debugger_last; -extern int oldreg[17]; -extern char oldbuffer[10]; -#endif - -extern bool CPUReadGSASnapshot(const char *); -extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *); -extern bool CPUWriteBatteryFile(const char *); -extern bool CPUReadBatteryFile(const char *); -extern bool CPUExportEepromFile(const char *); -extern bool CPUImportEepromFile(const char *); -extern bool CPUWritePNGFile(const char *); -extern bool CPUWriteBMPFile(const char *); -extern void CPUCleanUp(); -extern void CPUUpdateRender(); -extern void CPUUpdateRenderBuffers(bool); -extern bool CPUReadMemState(char *, int); -extern bool CPUReadState(const char *); -extern bool CPUWriteMemState(char *, int); -extern bool CPUWriteState(const char *); -extern int CPULoadRom(const char *); -extern void doMirroring(bool); -extern void CPUUpdateRegister(u32, u16); -extern void applyTimer (); -extern void CPUInit(const char *,bool); -extern void CPUReset(); -extern void CPULoop(int); -extern void CPUCheckDMA(int,int); -extern bool CPUIsGBAImage(const char *); -extern bool CPUIsZipFile(const char *); -#ifdef PROFILING -#include "prof/prof.h" -extern void cpuProfil(profile_segment *seg); -extern void cpuEnableProfiling(int hz); -#endif - -extern struct EmulatedSystem GBASystem; - -#define R13_IRQ 18 -#define R14_IRQ 19 -#define SPSR_IRQ 20 -#define R13_USR 26 -#define R14_USR 27 -#define R13_SVC 28 -#define R14_SVC 29 -#define SPSR_SVC 30 -#define R13_ABT 31 -#define R14_ABT 32 -#define SPSR_ABT 33 -#define R13_UND 34 -#define R14_UND 35 -#define SPSR_UND 36 -#define R8_FIQ 37 -#define R9_FIQ 38 -#define R10_FIQ 39 -#define R11_FIQ 40 -#define R12_FIQ 41 -#define R13_FIQ 42 -#define R14_FIQ 43 -#define SPSR_FIQ 44 - -#include "../Cheats.h" -#include "../Globals.h" -#include "../EEprom.h" -#include "../Flash.h" - -#endif //VBA_GBA_H diff --git a/src/agb/GBAGfx.cpp b/src/agb/GBAGfx.cpp deleted file mode 100644 index e8284c4d..00000000 --- a/src/agb/GBAGfx.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "../System.h" - -int coeff[32] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; - -u32 line0[240]; -u32 line1[240]; -u32 line2[240]; -u32 line3[240]; -u32 lineOBJ[240]; -u32 lineOBJWin[240]; -u32 lineMix[240]; -bool gfxInWin0[240]; -bool gfxInWin1[240]; -int lineOBJpixleft[128]; - -int gfxBG2Changed = 0; -int gfxBG3Changed = 0; - -int gfxBG2X = 0; -int gfxBG2Y = 0; -int gfxBG2LastX = 0; -int gfxBG2LastY = 0; -int gfxBG3X = 0; -int gfxBG3Y = 0; -int gfxBG3LastX = 0; -int gfxBG3LastY = 0; -int gfxLastVCOUNT = 0; diff --git a/src/agb/GBAGfx.h b/src/agb/GBAGfx.h deleted file mode 100644 index e2632ae0..00000000 --- a/src/agb/GBAGfx.h +++ /dev/null @@ -1,1602 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005 Forgotten and the VBA development team -// Copyright (C) 2008 VBA-M development team -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef VBA_GFX_H -#define VBA_GFX_H - -#include "GBA.h" -#include "GBAGfx.h" -#include "../Globals.h" - -#include "../Port.h" - -//#define SPRITE_DEBUG - -static void gfxDrawTextScreen(u16, u16, u16, u32 *); -static void gfxDrawRotScreen(u16, - u16, u16, - u16, u16, - u16, u16, - u16, u16, - int&, int&, - int, - u32*); -static void gfxDrawRotScreen16Bit(u16, - u16, u16, - u16, u16, - u16, u16, - u16, u16, - int&, int&, - int, - u32*); -static void gfxDrawRotScreen256(u16, - u16, u16, - u16, u16, - u16, u16, - u16, u16, - int&, int&, - int, - u32*); -static void gfxDrawRotScreen16Bit160(u16, - u16, u16, - u16, u16, - u16, u16, - u16, u16, - int&, int&, - int, - u32*); -static void gfxDrawSprites(u32 *); -static void gfxIncreaseBrightness(u32 *line, int coeff); -static void gfxDecreaseBrightness(u32 *line, int coeff); -static void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb); - -void mode0RenderLine(); -void mode0RenderLineNoWindow(); -void mode0RenderLineAll(); - -void mode1RenderLine(); -void mode1RenderLineNoWindow(); -void mode1RenderLineAll(); - -void mode2RenderLine(); -void mode2RenderLineNoWindow(); -void mode2RenderLineAll(); - -void mode3RenderLine(); -void mode3RenderLineNoWindow(); -void mode3RenderLineAll(); - -void mode4RenderLine(); -void mode4RenderLineNoWindow(); -void mode4RenderLineAll(); - -void mode5RenderLine(); -void mode5RenderLineNoWindow(); -void mode5RenderLineAll(); - -extern int coeff[32]; -extern u32 line0[240]; -extern u32 line1[240]; -extern u32 line2[240]; -extern u32 line3[240]; -extern u32 lineOBJ[240]; -extern u32 lineOBJWin[240]; -extern u32 lineMix[240]; -extern bool gfxInWin0[240]; -extern bool gfxInWin1[240]; -extern int lineOBJpixleft[128]; - -extern int gfxBG2Changed; -extern int gfxBG3Changed; - -extern int gfxBG2X; -extern int gfxBG2Y; -extern int gfxBG2LastX; -extern int gfxBG2LastY; -extern int gfxBG3X; -extern int gfxBG3Y; -extern int gfxBG3LastX; -extern int gfxBG3LastY; -extern int gfxLastVCOUNT; - -static inline void gfxClearArray(u32 *array) -{ - for(int i = 0; i < 240; i++) { - *array++ = 0x80000000; - } -} - -static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, - u32 *line) -{ - u16 *palette = (u16 *)paletteRAM; - u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; - u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800]; - u32 prio = ((control & 3)<<25) + 0x1000000; - int sizeX = 256; - int sizeY = 256; - switch((control >> 14) & 3) { - case 0: - break; - case 1: - sizeX = 512; - break; - case 2: - sizeY = 512; - break; - case 3: - sizeX = 512; - sizeY = 512; - break; - } - - int maskX = sizeX-1; - int maskY = sizeY-1; - - bool mosaicOn = (control & 0x40) ? true : false; - - int xxx = hofs & maskX; - int yyy = (vofs + VCOUNT) & maskY; - int mosaicX = (MOSAIC & 0x000F)+1; - int mosaicY = ((MOSAIC & 0x00F0)>>4)+1; - - if(mosaicOn) { - if((VCOUNT % mosaicY) != 0) { - mosaicY = VCOUNT - (VCOUNT % mosaicY); - yyy = (vofs + mosaicY) & maskY; - } - } - - if(yyy > 255 && sizeY > 256) { - yyy &= 255; - screenBase += 0x400; - if(sizeX > 256) - screenBase += 0x400; - } - - int yshift = ((yyy>>3)<<5); - if((control) & 0x80) { - u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift; - for(int x = 0; x < 240; x++) { - u16 data = READ16LE(screenSource); - - int tile = data & 0x3FF; - int tileX = (xxx & 7); - int tileY = yyy & 7; - - if(tileX == 7) - screenSource++; - - if(data & 0x0400) - tileX = 7 - tileX; - if(data & 0x0800) - tileY = 7 - tileY; - - u8 color = charBase[tile * 64 + tileY * 8 + tileX]; - - line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000; - - xxx++; - if(xxx == 256) { - if(sizeX > 256) - screenSource = screenBase + 0x400 + yshift; - else { - screenSource = screenBase + yshift; - xxx = 0; - } - } else if(xxx >= sizeX) { - xxx = 0; - screenSource = screenBase + yshift; - } - } - } else { - u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) + - yshift; - for(int x = 0; x < 240; x++) { - u16 data = READ16LE(screenSource); - - int tile = data & 0x3FF; - int tileX = (xxx & 7); - int tileY = yyy & 7; - - if(tileX == 7) - screenSource++; - - if(data & 0x0400) - tileX = 7 - tileX; - if(data & 0x0800) - tileY = 7 - tileY; - - u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)]; - - if(tileX & 1) { - color = (color >> 4); - } else { - color &= 0x0F; - } - - int pal = (data>>8) & 0xF0; - line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000; - - xxx++; - if(xxx == 256) { - if(sizeX > 256) - screenSource = screenBase + 0x400 + yshift; - else { - screenSource = screenBase + yshift; - xxx = 0; - } - } else if(xxx >= sizeX) { - xxx = 0; - screenSource = screenBase + yshift; - } - } - } - if(mosaicOn) { - if(mosaicX > 1) { - int m = 1; - for(int i = 0; i < 239; i++) { - line[i+1] = line[i]; - m++; - if(m == mosaicX) { - m = 1; - i++; - } - } - } - } -} - -static inline void gfxDrawRotScreen(u16 control, - u16 x_l, u16 x_h, - u16 y_l, u16 y_h, - u16 pa, u16 pb, - u16 pc, u16 pd, - int& currentX, int& currentY, - int changed, - u32 *line) -{ - u16 *palette = (u16 *)paletteRAM; - u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; - u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800]; - int prio = ((control & 3) << 25) + 0x1000000; - - int sizeX = 128; - int sizeY = 128; - switch((control >> 14) & 3) { - case 0: - break; - case 1: - sizeX = sizeY = 256; - break; - case 2: - sizeX = sizeY = 512; - break; - case 3: - sizeX = sizeY = 1024; - break; - } - - int maskX = sizeX-1; - int maskY = sizeY-1; - - int yshift = ((control >> 14) & 3)+4; - - int dx = pa & 0x7FFF; - if(pa & 0x8000) - dx |= 0xFFFF8000; - int dmx = pb & 0x7FFF; - if(pb & 0x8000) - dmx |= 0xFFFF8000; - int dy = pc & 0x7FFF; - if(pc & 0x8000) - dy |= 0xFFFF8000; - int dmy = pd & 0x7FFF; - if(pd & 0x8000) - dmy |= 0xFFFF8000; - - if(VCOUNT == 0) - changed = 3; - - if(changed & 1) { - currentX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - currentX |= 0xF8000000; - } else { - currentX += dmx; - } - - if(changed & 2) { - currentY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - currentY |= 0xF8000000; - } else { - currentY += dmy; - } - - int realX = currentX; - int realY = currentY; - - if(control & 0x40) { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = (VCOUNT % mosaicY); - realX -= y*dmx; - realY -= y*dmy; - } - - if(control & 0x2000) { - for(int x = 0; x < 240; x++) { - int xxx = (realX >> 8) & maskX; - int yyy = (realY >> 8) & maskY; - - int tile = screenBase[(xxx>>3) + ((yyy>>3)<> 8); - int yyy = (realY >> 8); - - if(xxx < 0 || - yyy < 0 || - xxx >= sizeX || - yyy >= sizeY) { - line[x] = 0x80000000; - } else { - int tile = screenBase[(xxx>>3) + ((yyy>>3)< 1) { - int m = 1; - for(int i = 0; i < 239; i++) { - line[i+1] = line[i]; - m++; - if(m == mosaicX) { - m = 1; - i++; - } - } - } - } -} - -static inline void gfxDrawRotScreen16Bit(u16 control, - u16 x_l, u16 x_h, - u16 y_l, u16 y_h, - u16 pa, u16 pb, - u16 pc, u16 pd, - int& currentX, int& currentY, - int changed, - u32 *line) -{ - u16 *screenBase = (u16 *)&vram[0]; - int prio = ((control & 3) << 25) + 0x1000000; - int sizeX = 240; - int sizeY = 160; - - int startX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - startX |= 0xF8000000; - int startY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - startY |= 0xF8000000; - - int dx = pa & 0x7FFF; - if(pa & 0x8000) - dx |= 0xFFFF8000; - int dmx = pb & 0x7FFF; - if(pb & 0x8000) - dmx |= 0xFFFF8000; - int dy = pc & 0x7FFF; - if(pc & 0x8000) - dy |= 0xFFFF8000; - int dmy = pd & 0x7FFF; - if(pd & 0x8000) - dmy |= 0xFFFF8000; - - if(VCOUNT == 0) - changed = 3; - - if(changed & 1) { - currentX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - currentX |= 0xF8000000; - } else - currentX += dmx; - - if(changed & 2) { - currentY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - currentY |= 0xF8000000; - } else { - currentY += dmy; - } - - int realX = currentX; - int realY = currentY; - - if(control & 0x40) { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = (VCOUNT % mosaicY); - realX -= y*dmx; - realY -= y*dmy; - } - - int xxx = (realX >> 8); - int yyy = (realY >> 8); - - for(int x = 0; x < 240; x++) { - if(xxx < 0 || - yyy < 0 || - xxx >= sizeX || - yyy >= sizeY) { - line[x] = 0x80000000; - } else { - line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); - } - realX += dx; - realY += dy; - - xxx = (realX >> 8); - yyy = (realY >> 8); - } - - if(control & 0x40) { - int mosaicX = (MOSAIC & 0xF) + 1; - if(mosaicX > 1) { - int m = 1; - for(int i = 0; i < 239; i++) { - line[i+1] = line[i]; - m++; - if(m == mosaicX) { - m = 1; - i++; - } - } - } - } -} - -static inline void gfxDrawRotScreen256(u16 control, - u16 x_l, u16 x_h, - u16 y_l, u16 y_h, - u16 pa, u16 pb, - u16 pc, u16 pd, - int ¤tX, int& currentY, - int changed, - u32 *line) -{ - u16 *palette = (u16 *)paletteRAM; - u8 *screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000]; - int prio = ((control & 3) << 25) + 0x1000000; - int sizeX = 240; - int sizeY = 160; - - int startX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - startX |= 0xF8000000; - int startY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - startY |= 0xF8000000; - - int dx = pa & 0x7FFF; - if(pa & 0x8000) - dx |= 0xFFFF8000; - int dmx = pb & 0x7FFF; - if(pb & 0x8000) - dmx |= 0xFFFF8000; - int dy = pc & 0x7FFF; - if(pc & 0x8000) - dy |= 0xFFFF8000; - int dmy = pd & 0x7FFF; - if(pd & 0x8000) - dmy |= 0xFFFF8000; - - if(VCOUNT == 0) - changed = 3; - - if(changed & 1) { - currentX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - currentX |= 0xF8000000; - } else { - currentX += dmx; - } - - if(changed & 2) { - currentY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - currentY |= 0xF8000000; - } else { - currentY += dmy; - } - - int realX = currentX; - int realY = currentY; - - if(control & 0x40) { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = VCOUNT - (VCOUNT % mosaicY); - realX = startX + y*dmx; - realY = startY + y*dmy; - } - - int xxx = (realX >> 8); - int yyy = (realY >> 8); - - for(int x = 0; x < 240; x++) { - if(xxx < 0 || - yyy < 0 || - xxx >= sizeX || - yyy >= sizeY) { - line[x] = 0x80000000; - } else { - u8 color = screenBase[yyy * 240 + xxx]; - - line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000; - } - realX += dx; - realY += dy; - - xxx = (realX >> 8); - yyy = (realY >> 8); - } - - if(control & 0x40) { - int mosaicX = (MOSAIC & 0xF) + 1; - if(mosaicX > 1) { - int m = 1; - for(int i = 0; i < 239; i++) { - line[i+1] = line[i]; - m++; - if(m == mosaicX) { - m = 1; - i++; - } - } - } - } -} - -static inline void gfxDrawRotScreen16Bit160(u16 control, - u16 x_l, u16 x_h, - u16 y_l, u16 y_h, - u16 pa, u16 pb, - u16 pc, u16 pd, - int& currentX, int& currentY, - int changed, - u32 *line) -{ - u16 *screenBase = (DISPCNT & 0x0010) ? (u16 *)&vram[0xa000] : - (u16 *)&vram[0]; - int prio = ((control & 3) << 25) + 0x1000000; - int sizeX = 160; - int sizeY = 128; - - int startX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - startX |= 0xF8000000; - int startY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - startY |= 0xF8000000; - - int dx = pa & 0x7FFF; - if(pa & 0x8000) - dx |= 0xFFFF8000; - int dmx = pb & 0x7FFF; - if(pb & 0x8000) - dmx |= 0xFFFF8000; - int dy = pc & 0x7FFF; - if(pc & 0x8000) - dy |= 0xFFFF8000; - int dmy = pd & 0x7FFF; - if(pd & 0x8000) - dmy |= 0xFFFF8000; - - if(VCOUNT == 0) - changed = 3; - - if(changed & 1) { - currentX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - currentX |= 0xF8000000; - } else { - currentX += dmx; - } - - if(changed & 2) { - currentY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - currentY |= 0xF8000000; - } else { - currentY += dmy; - } - - int realX = currentX; - int realY = currentY; - - if(control & 0x40) { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = VCOUNT - (VCOUNT % mosaicY); - realX = startX + y*dmx; - realY = startY + y*dmy; - } - - int xxx = (realX >> 8); - int yyy = (realY >> 8); - - for(int x = 0; x < 240; x++) { - if(xxx < 0 || - yyy < 0 || - xxx >= sizeX || - yyy >= sizeY) { - line[x] = 0x80000000; - } else { - line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); - } - realX += dx; - realY += dy; - - xxx = (realX >> 8); - yyy = (realY >> 8); - } - - if(control & 0x40) { - int mosaicX = (MOSAIC & 0xF) + 1; - if(mosaicX > 1) { - int m = 1; - for(int i = 0; i < 239; i++) { - line[i+1] = line[i]; - m++; - if(m == mosaicX) { - m = 1; - i++; - } - } - } - } -} - -static inline void gfxDrawSprites(u32 *lineOBJ) -{ - // lineOBJpix is used to keep track of the drawn OBJs - // and to stop drawing them if the 'maximum number of OBJ per line' - // has been reached. - int lineOBJpix = (DISPCNT & 0x20) ? 954 : 1226; - int m=0; - gfxClearArray(lineOBJ); - if(layerEnable & 0x1000) { - u16 *sprites = (u16 *)oam; - u16 *spritePalette = &((u16 *)paletteRAM)[256]; - int mosaicY = ((MOSAIC & 0xF000)>>12) + 1; - int mosaicX = ((MOSAIC & 0xF00)>>8) + 1; - for(int x = 0; x < 128 ; x++) { - u16 a0 = READ16LE(sprites++); - u16 a1 = READ16LE(sprites++); - u16 a2 = READ16LE(sprites++); - sprites++; - - lineOBJpixleft[x]=lineOBJpix; - - lineOBJpix-=2; - if (lineOBJpix<=0) - continue; - - if ((a0 & 0x0c00) == 0x0c00) - a0 &=0xF3FF; - - if ((a0>>14) == 3) - { - a0 &= 0x3FFF; - a1 &= 0x3FFF; - } - - int sizeX = 8<<(a1>>14); - int sizeY = sizeX; - - if ((a0>>14) & 1) - { - if (sizeX<32) - sizeX<<=1; - if (sizeY>8) - sizeY>>=1; - } - else if ((a0>>14) & 2) - { - if (sizeX>8) - sizeX>>=1; - if (sizeY<32) - sizeY<<=1; - } - -#ifdef SPRITE_DEBUG - int maskX = sizeX-1; - int maskY = sizeY-1; -#endif - - int sy = (a0 & 255); - int sx = (a1 & 0x1FF); - - // computes ticks used by OBJ-WIN if OBJWIN is enabled - if (((a0 & 0x0c00) == 0x0800) && (layerEnable & 0x8000)) - { - if ((a0 & 0x0300) == 0x0300) - { - sizeX<<=1; - sizeY<<=1; - } - if((sy+sizeY) > 256) - sy -= 256; - if ((sx+sizeX)> 512) - sx-=512; - if (sx<0) - { - sizeX+=sx; - sx = 0; - } - else if ((sx+sizeX)>240) - sizeX=240-sx; - if ((VCOUNT>=sy) && (VCOUNT 256) - sy -= 256; - int t = VCOUNT - sy; - if((t >= 0) && (t < fieldY)) { - int startpix = 0; - if ((sx+fieldX)> 512) - { - startpix=512-sx; - } - if (lineOBJpix>0) - if((sx < 240) || startpix) { - lineOBJpix-=8; - // int t2 = t - (fieldY >> 1); - int rot = (a1 >> 9) & 0x1F; - u16 *OAM = (u16 *)oam; - int dx = READ16LE(&OAM[3 + (rot << 4)]); - if(dx & 0x8000) - dx |= 0xFFFF8000; - int dmx = READ16LE(&OAM[7 + (rot << 4)]); - if(dmx & 0x8000) - dmx |= 0xFFFF8000; - int dy = READ16LE(&OAM[11 + (rot << 4)]); - if(dy & 0x8000) - dy |= 0xFFFF8000; - int dmy = READ16LE(&OAM[15 + (rot << 4)]); - if(dmy & 0x8000) - dmy |= 0xFFFF8000; - - if(a0 & 0x1000) { - t -= (t % mosaicY); - } - - int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx - + t * dmx; - int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy - + t * dmy; - - u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - - if(a0 & 0x2000) { - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - int inc = 32; - if(DISPCNT & 0x40) - inc = sizeX >> 2; - else - c &= 0x3FE; - for(int x = 0; x < fieldX; x++) { - if (x >= startpix) - lineOBJpix-=2; - if (lineOBJpix<0) - continue; - int xxx = realX >> 8; - int yyy = realY >> 8; - - if(xxx < 0 || xxx >= sizeX || - yyy < 0 || yyy >= sizeY || - sx >= 240); - else { - u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + - (xxx & 7))&0x7FFF)]; - if ((color==0) && (((prio >> 25)&3) < - ((lineOBJ[sx]>>25)&3))) { - lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { - lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } - - if (a0 & 0x1000) { - m++; - if (m==mosaicX) - m=0; - } -#ifdef SPRITE_DEBUG - if(t == 0 || t == maskY || x == 0 || x == maskX) - lineOBJ[sx] = 0x001F; -#endif - } - sx = (sx+1)&511; - realX += dx; - realY += dy; - } - } else { - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - if(DISPCNT & 0x40) - inc = sizeX >> 3; - int palette = (a2 >> 8) & 0xF0; - for(int x = 0; x < fieldX; x++) { - if (x >= startpix) - lineOBJpix-=2; - if (lineOBJpix<0) - continue; - int xxx = realX >> 8; - int yyy = realY >> 8; - if(xxx < 0 || xxx >= sizeX || - yyy < 0 || yyy >= sizeY || - sx >= 240); - else { - u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + - ((xxx & 7)>>1))&0x7FFF)]; - if(xxx & 1) - color >>= 4; - else - color &= 0x0F; - - if ((color==0) && (((prio >> 25)&3) < - ((lineOBJ[sx]>>25)&3))) { - lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { - lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } - } - if((a0 & 0x1000) && m) { - m++; - if (m==mosaicX) - m=0; - } - -#ifdef SPRITE_DEBUG - if(t == 0 || t == maskY || x == 0 || x == maskX) - lineOBJ[sx] = 0x001F; -#endif - sx = (sx+1)&511; - realX += dx; - realY += dy; - - } - } - } - } - } else { - if(sy+sizeY > 256) - sy -= 256; - int t = VCOUNT - sy; - if((t >= 0) && (t < sizeY)) { - int startpix = 0; - if ((sx+sizeX)> 512) - { - startpix=512-sx; - } - if((sx < 240) || startpix) { - lineOBJpix+=2; - if(a0 & 0x2000) { - if(a1 & 0x2000) - t = sizeY - t - 1; - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - if(DISPCNT & 0x40) { - inc = sizeX >> 2; - } else { - c &= 0x3FE; - } - int xxx = 0; - if(a1 & 0x1000) - xxx = sizeX-1; - - if(a0 & 0x1000) { - t -= (t % mosaicY); - } - - int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) - + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF); - - if(a1 & 0x1000) - xxx = 7; - u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - - for(int xx = 0; xx < sizeX; xx++) { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) { - u8 color = vram[address]; - if ((color==0) && (((prio >> 25)&3) < - ((lineOBJ[sx]>>25)&3))) { - lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { - lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } - - if (a0 & 0x1000) { - m++; - if (m==mosaicX) - m=0; - } - -#ifdef SPRITE_DEBUG - if(t == 0 || t == maskY || xx == 0 || xx == maskX) - lineOBJ[sx] = 0x001F; -#endif - } - - sx = (sx+1) & 511; - if(a1 & 0x1000) { - xxx--; - address--; - if(xxx == -1) { - address -= 56; - xxx = 7; - } - if(address < 0x10000) - address += 0x8000; - } else { - xxx++; - address++; - if(xxx == 8) { - address += 56; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } else { - if(a1 & 0x2000) - t = sizeY - t - 1; - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - if(DISPCNT & 0x40) { - inc = sizeX >> 3; - } - int xxx = 0; - if(a1 & 0x1000) - xxx = sizeX - 1; - - if(a0 & 0x1000) { - t -= (t % mosaicY); - } - - int address = 0x10000 + ((((c + (t>>3) * inc)<<5) - + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF); - u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - int palette = (a2 >> 8) & 0xF0; - if(a1 & 0x1000) { - xxx = 7; - for(int xx = sizeX - 1; xx >= 0; xx--) { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) { - u8 color = vram[address]; - if(xx & 1) { - color = (color >> 4); - } else - color &= 0x0F; - - if ((color==0) && (((prio >> 25)&3) < - ((lineOBJ[sx]>>25)&3))) { - lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { - lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } - } - if (a0 & 0x1000) { - m++; - if (m==mosaicX) - m=0; - } -#ifdef SPRITE_DEBUG - if(t == 0 || t == maskY || xx == 0 || xx == maskX) - lineOBJ[sx] = 0x001F; -#endif - sx = (sx+1) & 511; - xxx--; - if(!(xx & 1)) - address--; - if(xxx == -1) { - xxx = 7; - address -= 28; - } - if(address < 0x10000) - address += 0x8000; - } - } else { - for(int xx = 0; xx < sizeX; xx++) { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) { - u8 color = vram[address]; - if(xx & 1) { - color = (color >> 4); - } else - color &= 0x0F; - - if ((color==0) && (((prio >> 25)&3) < - ((lineOBJ[sx]>>25)&3))) { - lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { - lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio; - if((a0 & 0x1000) && m) - lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; - - } - } - if (a0 & 0x1000) { - m++; - if (m==mosaicX) - m=0; - } -#ifdef SPRITE_DEBUG - if(t == 0 || t == maskY || xx == 0 || xx == maskX) - lineOBJ[sx] = 0x001F; -#endif - sx = (sx+1) & 511; - xxx++; - if(xx & 1) - address++; - if(xxx == 8) { - address += 28; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } - } - } - } - } - } -} - -static inline void gfxDrawOBJWin(u32 *lineOBJWin) -{ - gfxClearArray(lineOBJWin); - if((layerEnable & 0x9000) == 0x9000) { - u16 *sprites = (u16 *)oam; - // u16 *spritePalette = &((u16 *)paletteRAM)[256]; - for(int x = 0; x < 128 ; x++) { - int lineOBJpix = lineOBJpixleft[x]; - u16 a0 = READ16LE(sprites++); - u16 a1 = READ16LE(sprites++); - u16 a2 = READ16LE(sprites++); - sprites++; - - if (lineOBJpix<=0) - continue; - - // ignores non OBJ-WIN and disabled OBJ-WIN - if(((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200)) - continue; - - if ((a0 & 0x0c00) == 0x0c00) - a0 &=0xF3FF; - - if ((a0>>14) == 3) - { - a0 &= 0x3FFF; - a1 &= 0x3FFF; - } - - int sizeX = 8<<(a1>>14); - int sizeY = sizeX; - - if ((a0>>14) & 1) - { - if (sizeX<32) - sizeX<<=1; - if (sizeY>8) - sizeY>>=1; - } - else if ((a0>>14) & 2) - { - if (sizeX>8) - sizeX>>=1; - if (sizeY<32) - sizeY<<=1; - } - - int sy = (a0 & 255); - - if(a0 & 0x0100) { - int fieldX = sizeX; - int fieldY = sizeY; - if(a0 & 0x0200) { - fieldX <<= 1; - fieldY <<= 1; - } - if((sy+fieldY) > 256) - sy -= 256; - int t = VCOUNT - sy; - if((t >= 0) && (t < fieldY)) { - int sx = (a1 & 0x1FF); - int startpix = 0; - if ((sx+fieldX)> 512) - { - startpix=512-sx; - } - if((sx < 240) || startpix) { - lineOBJpix-=8; - // int t2 = t - (fieldY >> 1); - int rot = (a1 >> 9) & 0x1F; - u16 *OAM = (u16 *)oam; - int dx = READ16LE(&OAM[3 + (rot << 4)]); - if(dx & 0x8000) - dx |= 0xFFFF8000; - int dmx = READ16LE(&OAM[7 + (rot << 4)]); - if(dmx & 0x8000) - dmx |= 0xFFFF8000; - int dy = READ16LE(&OAM[11 + (rot << 4)]); - if(dy & 0x8000) - dy |= 0xFFFF8000; - int dmy = READ16LE(&OAM[15 + (rot << 4)]); - if(dmy & 0x8000) - dmy |= 0xFFFF8000; - - int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx - + t * dmx; - int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy - + t * dmy; - - // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - - if(a0 & 0x2000) { - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - int inc = 32; - if(DISPCNT & 0x40) - inc = sizeX >> 2; - else - c &= 0x3FE; - for(int x = 0; x < fieldX; x++) { - if (x >= startpix) - lineOBJpix-=2; - if (lineOBJpix<0) - continue; - int xxx = realX >> 8; - int yyy = realY >> 8; - - if(xxx < 0 || xxx >= sizeX || - yyy < 0 || yyy >= sizeY || - sx >= 240) { - } else { - u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + - (xxx & 7))&0x7fff)]; - if(color) { - lineOBJWin[sx] = 1; - } - } - sx = (sx+1)&511; - realX += dx; - realY += dy; - } - } else { - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - if(DISPCNT & 0x40) - inc = sizeX >> 3; - // int palette = (a2 >> 8) & 0xF0; - for(int x = 0; x < fieldX; x++) { - if (x >= startpix) - lineOBJpix-=2; - if (lineOBJpix<0) - continue; - int xxx = realX >> 8; - int yyy = realY >> 8; - - // if(x == 0 || x == (sizeX-1) || - // t == 0 || t == (sizeY-1)) { - // lineOBJ[sx] = 0x001F | prio; - // } else { - if(xxx < 0 || xxx >= sizeX || - yyy < 0 || yyy >= sizeY || - sx >= 240) { - } else { - u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + - ((xxx & 7)>>1))&0x7fff)]; - if(xxx & 1) - color >>= 4; - else - color &= 0x0F; - - if(color) { - lineOBJWin[sx] = 1; - } - } - // } - sx = (sx+1)&511; - realX += dx; - realY += dy; - } - } - } - } - } else { - if((sy+sizeY) > 256) - sy -= 256; - int t = VCOUNT - sy; - if((t >= 0) && (t < sizeY)) { - int sx = (a1 & 0x1FF); - int startpix = 0; - if ((sx+sizeX)> 512) - { - startpix=512-sx; - } - if((sx < 240) || startpix) { - lineOBJpix+=2; - if(a0 & 0x2000) { - if(a1 & 0x2000) - t = sizeY - t - 1; - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - if(DISPCNT & 0x40) { - inc = sizeX >> 2; - } else { - c &= 0x3FE; - } - int xxx = 0; - if(a1 & 0x1000) - xxx = sizeX-1; - int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) - + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff); - if(a1 & 0x1000) - xxx = 7; - // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - for(int xx = 0; xx < sizeX; xx++) { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) { - u8 color = vram[address]; - if(color) { - lineOBJWin[sx] = 1; - } - } - - sx = (sx+1) & 511; - if(a1 & 0x1000) { - xxx--; - address--; - if(xxx == -1) { - address -= 56; - xxx = 7; - } - if(address < 0x10000) - address += 0x8000; - } else { - xxx++; - address++; - if(xxx == 8) { - address += 56; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } else { - if(a1 & 0x2000) - t = sizeY - t - 1; - int c = (a2 & 0x3FF); - if((DISPCNT & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - if(DISPCNT & 0x40) { - inc = sizeX >> 3; - } - int xxx = 0; - if(a1 & 0x1000) - xxx = sizeX - 1; - int address = 0x10000 + ((((c + (t>>3) * inc)<<5) - + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff); - // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - // int palette = (a2 >> 8) & 0xF0; - if(a1 & 0x1000) { - xxx = 7; - for(int xx = sizeX - 1; xx >= 0; xx--) { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) { - u8 color = vram[address]; - if(xx & 1) { - color = (color >> 4); - } else - color &= 0x0F; - - if(color) { - lineOBJWin[sx] = 1; - } - } - sx = (sx+1) & 511; - xxx--; - if(!(xx & 1)) - address--; - if(xxx == -1) { - xxx = 7; - address -= 28; - } - if(address < 0x10000) - address += 0x8000; - } - } else { - for(int xx = 0; xx < sizeX; xx++) { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) { - u8 color = vram[address]; - if(xx & 1) { - color = (color >> 4); - } else - color &= 0x0F; - - if(color) { - lineOBJWin[sx] = 1; - } - } - sx = (sx+1) & 511; - xxx++; - if(xx & 1) - address++; - if(xxx == 8) { - address += 28; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } - } - } - } - } - } -} - -static inline u32 gfxIncreaseBrightness(u32 color, int coeff) -{ - color &= 0xffff; - color = ((color << 16) | color) & 0x3E07C1F; - - color = color + (((0x3E07C1F - color) * coeff) >> 4); - color &= 0x3E07C1F; - - return (color >> 16) | color; -} - -static inline void gfxIncreaseBrightness(u32 *line, int coeff) -{ - for(int x = 0; x < 240; x++) { - u32 color = *line; - int r = (color & 0x1F); - int g = ((color >> 5) & 0x1F); - int b = ((color >> 10) & 0x1F); - - r = r + (((31 - r) * coeff) >> 4); - g = g + (((31 - g) * coeff) >> 4); - b = b + (((31 - b) * coeff) >> 4); - if(r > 31) - r = 31; - if(g > 31) - g = 31; - if(b > 31) - b = 31; - *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; - } -} - -static inline u32 gfxDecreaseBrightness(u32 color, int coeff) -{ - color &= 0xffff; - color = ((color << 16) | color) & 0x3E07C1F; - - color = color - (((color * coeff) >> 4) & 0x3E07C1F); - - return (color >> 16) | color; -} - -static inline void gfxDecreaseBrightness(u32 *line, int coeff) -{ - for(int x = 0; x < 240; x++) { - u32 color = *line; - int r = (color & 0x1F); - int g = ((color >> 5) & 0x1F); - int b = ((color >> 10) & 0x1F); - - r = r - ((r * coeff) >> 4); - g = g - ((g * coeff) >> 4); - b = b - ((b * coeff) >> 4); - if(r < 0) - r = 0; - if(g < 0) - g = 0; - if(b < 0) - b = 0; - *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; - } -} - -static inline u32 gfxAlphaBlend(u32 color, u32 color2, int ca, int cb) -{ - if(color < 0x80000000) { - color&=0xffff; - color2&=0xffff; - - color = ((color << 16) | color) & 0x03E07C1F; - color2 = ((color2 << 16) | color2) & 0x03E07C1F; - color = ((color * ca) + (color2 * cb)) >> 4; - - if ((ca + cb)>16) - { - if (color & 0x20) - color |= 0x1f; - if (color & 0x8000) - color |= 0x7C00; - if (color & 0x4000000) - color |= 0x03E00000; - } - - color &= 0x03E07C1F; - color = (color >> 16) | color; - } - return color; -} - -static inline void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb) -{ - for(int x = 0; x < 240; x++) { - u32 color = *ta; - if(color < 0x80000000) { - int r = (color & 0x1F); - int g = ((color >> 5) & 0x1F); - int b = ((color >> 10) & 0x1F); - u32 color2 = (*tb++); - int r0 = (color2 & 0x1F); - int g0 = ((color2 >> 5) & 0x1F); - int b0 = ((color2 >> 10) & 0x1F); - - r = ((r * ca) + (r0 * cb)) >> 4; - g = ((g * ca) + (g0 * cb)) >> 4; - b = ((b * ca) + (b0 * cb)) >> 4; - - if(r > 31) - r = 31; - if(g > 31) - g = 31; - if(b > 31) - b = 31; - - *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; - } else { - ta++; - tb++; - } - } -} - -#endif // VBA_GFX_H diff --git a/src/agb/GBALink.cpp b/src/agb/GBALink.cpp deleted file mode 100644 index fa5479d5..00000000 --- a/src/agb/GBALink.cpp +++ /dev/null @@ -1,1083 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team -// This file was written by denopqrihg - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -// Link.cpp : Emulation of GBA link accessories -// - -#include "GBA.h" -#include -#include "../win32/stdafx.h" -#include "../port.h" -#include "GBALink.h" -#include "../win32/vba.h" -#include "../win32/MainWnd.h" -#include "../win32/LinkOptions.h" -#include "../win32/Reg.h" - -#define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value) -#define GBLINK_READY 8 - -int linktime = 0; -u8 tspeed=3; -u8 transfer=0; -LINKDATA *linkmem=NULL; -int linkid = 0, vbaid = 0; -HANDLE linksync[4]; -int savedlinktime=0; -HANDLE mmf=NULL; -char linkevent[] = "VBA link event "; -static int i, j; -int linktimeout = 1000; -int linklog = 0; -FILE *linklogfile = NULL; -LANLINKDATA lanlink; -u16 linkdata[4]; -int lspeed = 0; -lserver ls; -lclient lc; -bool oncewait = false, after = false; -bool adapter = false; -bool linkenable = false; -u8 rfu_cmd, rfu_qsend, rfu_qrecv; -int rfu_state, rfu_polarity, linktime2, counter, rfu_masterq; -int transferend, numtransfers = 0; -u32 rfu_masterdata[32]; - -extern unsigned char *gbMemory; -extern int gbInterrupt; - -int trtimedata[4][4] = {{34080, 8520, 5680, 2840}, {65536, 16384, 10923, 5461}, {99609, 24903, 16602, 8301}, {133692, 33423, 22282, 11141}}; -int trtimeend[3][4] = {{72527, 18132, 12088, 6044}, {106608, 26652, 17768, 8884}, {133692, 33423, 22282, 11141}}; -int gbtime = 1024; - -DWORD WINAPI LinkClientThread(void *); -DWORD WINAPI LinkServerThread(void *); -int StartServer(void); -int GetSioMode(u16, u16); -u16 StartRFU(u16); - -char *MakeInstanceFilename(const char *Input) -{ - if (vbaid == 0) - return (char *)Input; - - static char *result=NULL; - if (result!=NULL) - free(result); - - result = (char *)malloc(strlen(Input)+3); - char *p = strrchr((char *)Input, '.'); - sprintf(result, "%.*s-%d.%s", (int)(p-Input), Input, vbaid+1, p+1); - return result; -} - - -void StartLink(WORD value){ - if(ioMem==NULL) return; - if(adapter){ - UPDATE_REG(0x128, StartRFU(value)); - return; - } - switch(GetSioMode(value, READ16LE(&ioMem[0x134]))){ - case MULTIPLAYER: - if(value & 0x80){ - if(!linkid){ - if(!transfer){ - if(lanlink.active){ - if(lanlink.connected){ - linkdata[0] = READ16LE(&ioMem[0x12a]); - savedlinktime = linktime; - tspeed = value & 3; - ls.Send(); - transfer = 1; - linktime = 0; - UPDATE_REG(0x120, linkdata[0]); - UPDATE_REG(0x122, 0xffff); - WRITE32LE(&ioMem[0x124], 0xffffffff); - if(lanlink.speed&&oncewait==false) ls.howmanytimes++; - after = false; - } - } else if(linkmem->numgbas>1){ - ResetEvent(linksync[0]); - linkmem->linkcmd[0] = ('M'<<8)+(value&3); - linkmem->linkdata[0] = READ16LE(&ioMem[0x12a]); - if(linkmem->numtransfers!=0) linkmem->lastlinktime = linktime; - else linkmem->lastlinktime = 0; - if((++linkmem->numtransfers)==0) linkmem->numtransfers=2; - transfer = 1; - linktime = 0; - tspeed = value & 3; - WRITE32LE(&ioMem[0x120], 0xffffffff); - WRITE32LE(&ioMem[0x124], 0xffffffff); - } - } - } - value &= 0xff7f; - value |= (transfer!=0)<<7; - } - value &= 0xff8b; - value |= (linkid ? 0xc : 8); - value |= linkid<<4; - UPDATE_REG(0x128, value); - if(linkid) UPDATE_REG(0x134, 7); - else UPDATE_REG(0x134, 3); - break; - case NORMAL8: - if(linklog) fprintf(linklogfile, "Attempt to use 8-bit Normal mode %04x\n", value); - UPDATE_REG(0x128, value); - break; - case NORMAL32: - if(linklog) fprintf(linklogfile, "Attempt to use 32-bit Normal mode %04x %x%x\n", value, READ16LE(&ioMem[0x122]), READ16LE(&ioMem[0x120])); - UPDATE_REG(0x128, value); - break; - case UART: - if(linklog) fprintf(linklogfile, "Attempt to use UART mode %04x\n", value); - UPDATE_REG(0x128, value); - break; - default: - UPDATE_REG(0x128, value); - break; - } -} - -void StartGPLink(u16 value){ - if(!value){ - UPDATE_REG(0x134, 0); - return; - } - switch(GetSioMode(READ16LE(&ioMem[0x128]), value)){ - case MULTIPLAYER: - value &= 0xc0f0; - value |= 3; - if(linkid) value |= 4; - UPDATE_REG(0x134, value); - UPDATE_REG(0x128, ((READ16LE(&ioMem[0x128])&0xff8b)|(linkid ? 0xc : 8)|(linkid<<4))); - return; - break; - case GP: - if(linklog){ - if(value==0x8000) fprintf(linklogfile, "Circuit reset\n"); - else if(!adapter) fprintf(linklogfile, "Attempt to use General-purpose mode %04x\n", value); - } - if(adapter) rfu_state = RFU_INIT; - // This was not there, but sonic games won't start if it's not here. - UPDATE_REG(0x134, value); - break; - case JOYBUS: - UPDATE_REG(0x134, value); - break; - default: - UPDATE_REG(0x134, value); - break; - } - return; -} - -void StartJOYLink(u16 value){ - if(!value){ - UPDATE_REG(0x140, 0); - return; - } - if(GetSioMode(READ16LE(&ioMem[0x128]), READ16LE(&ioMem[0x134]))==JOYBUS&&linklog) fprintf(linklogfile, "Attempt to use JOY-BUS mode %04x\n", value); - return; -} - -void LinkUpdate(int ticks){ - linktime += ticks; - if(adapter){ - linktime2 += ticks; - transferend -= ticks; - if(transfer&&transferend<=0){ - transfer = 0; - if(READ16LE(&ioMem[0x128])&0x4000){ - IF |= 0x80; - UPDATE_REG(0x202, IF); - } - UPDATE_REG(0x128, READ16LE(&ioMem[0x128]) & 0xff7f); - } - return; - } - - if(lanlink.active){ - if(lanlink.connected){ - if(after){ - if(linkid&&linktime>6044){ - lc.Recv(); - oncewait = true; - } else return; - } - if(linkid&&!transfer&&lc.numtransfers>0&&linktime>=savedlinktime){ - linkdata[linkid] = READ16LE(&ioMem[0x12a]); - if(!lc.oncesend) lc.Send(); - lc.oncesend = false; - UPDATE_REG(0x120, linkdata[0]); - UPDATE_REG(0x128, READ16LE(&ioMem[0x128]) | 0x80); - transfer = 1; - if(lc.numtransfers==1) linktime = 0; - else linktime -= savedlinktime; - } - if(transfer&&linktime>=trtimeend[lanlink.numgbas-1][tspeed]){ - if(READ16LE(&ioMem[0x128]) & 0x4000){ - IF |= 0x80; - UPDATE_REG(0x202, IF); - } - UPDATE_REG(0x128, (READ16LE(&ioMem[0x128]) & 0xff0f) | (linkid << 4)); - transfer = 0; - linktime -= trtimeend[lanlink.numgbas-1][tspeed]; - oncewait = false; - if(!lanlink.speed){ - if(linkid) lc.Recv(); - else ls.Recv(); - UPDATE_REG(0x122, linkdata[1]); - UPDATE_REG(0x124, linkdata[2]); - UPDATE_REG(0x126, linkdata[3]); - if(linklog) fprintf(linklogfile, "%04x %04x %04x %04x %10u\n", linkdata[0], linkdata[1], linkdata[2], linkdata[3], savedlinktime); - oncewait = true; - } else { - after = true; - if(lanlink.numgbas==1){ - UPDATE_REG(0x122, linkdata[1]); - UPDATE_REG(0x124, linkdata[2]); - UPDATE_REG(0x126, linkdata[3]); - if(linklog) fprintf(linklogfile, "%04x %04x %04x %04x %10u\n", linkdata[0], linkdata[1], linkdata[2], linkdata[3], savedlinktime); - } - - } - } - } - return; - } - // ** CRASH ** linkmem is NULL, todo investigate why, added null check - if(linkid&&!transfer&&linkmem&&linktime>=linkmem->lastlinktime&&linkmem->numtransfers){ - linkmem->linkdata[linkid] = READ16LE(&ioMem[0x12a]); - - if(linkmem->numtransfers==1){ - linktime = 0; - if(WaitForSingleObject(linksync[linkid], linktimeout)==WAIT_TIMEOUT) linkmem->numtransfers=0; - } else linktime -= linkmem->lastlinktime; - - switch((linkmem->linkcmd[0])>>8){ - case 'M': - tspeed = (linkmem->linkcmd[0]) & 3; - transfer = 1; - WRITE32LE(&ioMem[0x120], 0xffffffff); - WRITE32LE(&ioMem[0x124], 0xffffffff); - UPDATE_REG(0x128, READ16LE(&ioMem[0x128]) | 0x80); - break; - } - } - - if(!transfer) return; - - if(transfer&&linktime>=trtimedata[transfer-1][tspeed]&&transfer<=linkmem->numgbas){ - if(transfer-linkid==2){ - SetEvent(linksync[linkid+1]); - if(WaitForSingleObject(linksync[linkid], linktimeout)==WAIT_TIMEOUT) - linkmem->numtransfers=0; - ResetEvent(linksync[linkid]); - if(linklog) fprintf(linklogfile, "%04x %04x %04x %04x %10u\n", - linkmem->linkdata[0], linkmem->linkdata[1], linkmem->linkdata[2], linkmem->linkdata[3], linkmem->lastlinktime); - } - - - UPDATE_REG(0x11e + (transfer<<1), linkmem->linkdata[transfer-1]); - transfer++; - } - - if(transfer&&linktime>=trtimeend[linkmem->numgbas-2][tspeed]){ - if(linkid==linkmem->numgbas-1){ - SetEvent(linksync[0]); - if(WaitForSingleObject(linksync[linkid], linktimeout)==WAIT_TIMEOUT) - linkmem->numtransfers=0; - ResetEvent(linksync[linkid]); - if(linklog) fprintf(linklogfile, "%04x %04x %04x %04x %10u\n", - linkmem->linkdata[0], linkmem->linkdata[1], linkmem->linkdata[2], linkmem->linkdata[3], linkmem->lastlinktime); - } - transfer = 0; - linktime -= trtimeend[0][tspeed]; - if(READ16LE(&ioMem[0x128]) & 0x4000){ - IF |= 0x80; - UPDATE_REG(0x202, IF); - } - UPDATE_REG(0x128, (READ16LE(&ioMem[0x128]) & 0xff0f) | (linkid << 4)); - linkmem->linkdata[linkid] = 0xffff; - } - - return; -} - -inline int GetSioMode(u16 reg1, u16 reg2){ - if(!(reg2&0x8000)){ - switch(reg1&0x3000){ - case 0x0000: - return NORMAL8; - case 0x1000: - return NORMAL32; - case 0x2000: - return MULTIPLAYER; - case 0x3000: - return UART; - } - } - if(reg2&0x4000) return JOYBUS; - return GP; -} - -u16 StartRFU(u16 value){ - switch(GetSioMode(value, READ16LE(&ioMem[0x134]))){ - case NORMAL8: - rfu_polarity = 0; - return value; - break; - case NORMAL32: - if(value&8) value &= 0xfffb; // A kind of acknowledge procedure - else value |= 4; - if(value&0x80){ - if((value&3)==1) transferend = 2048; - else transferend = 256; - u16 a = READ16LE(&ioMem[0x122]); - switch(rfu_state){ - case RFU_INIT: - if(READ32LE(&ioMem[0x120])==0xb0bb8001){ - rfu_state = RFU_COMM; // end of startup - } - UPDATE_REG(0x122, READ16LE(&ioMem[0x120])); - UPDATE_REG(0x120, a); - break; - case RFU_COMM: - if(a==0x9966){ - rfu_cmd = ioMem[0x120]; - if((rfu_qsend=ioMem[0x121])!=0){ - rfu_state = RFU_SEND; - counter = 0; - } - if(rfu_cmd==0x25||rfu_cmd==0x24){ - linkmem->rfu_q[vbaid] = rfu_qsend; - } - UPDATE_REG(0x120, 0); - UPDATE_REG(0x122, 0x8000); - } else if(a==0x8000){ - switch(rfu_cmd){ - case 0x1a: // check if someone joined - if(linkmem->rfu_request[vbaid]!=0){ - rfu_state = RFU_RECV; - rfu_qrecv = 1; - } - linkid = -1; - rfu_cmd |= 0x80; - break; - case 0x1e: // receive broadcast data - case 0x1d: // no visible difference - rfu_polarity = 0; - rfu_state = RFU_RECV; - rfu_qrecv = 7; - counter = 0; - rfu_cmd |= 0x80; - break; - case 0x30: - linkmem->rfu_request[vbaid] = 0; - linkmem->rfu_q[vbaid] = 0; - linkid = 0; - numtransfers = 0; - rfu_cmd |= 0x80; - if(linkmem->numgbas==2) SetEvent(linksync[1-vbaid]); - break; - case 0x11: // ? always receives 0xff - I suspect it's something for 3+ players - case 0x13: // unknown - case 0x20: // this has something to do with 0x1f - case 0x21: // this too - rfu_cmd |= 0x80; - rfu_polarity = 0; - rfu_state = 3; - rfu_qrecv = 1; - break; - case 0x26: - if(linkid>0){ - rfu_qrecv = rfu_masterq; - } - if((rfu_qrecv=linkmem->rfu_q[1-vbaid])!=0){ - rfu_state = RFU_RECV; - counter = 0; - } - rfu_cmd |= 0x80; - break; - case 0x24: // send data - if((numtransfers++)==0) linktime = 1; - linkmem->rfu_linktime[vbaid] = linktime; - if(linkmem->numgbas==2){ - SetEvent(linksync[1-vbaid]); - WaitForSingleObject(linksync[vbaid], linktimeout); - ResetEvent(linksync[vbaid]); - } - rfu_cmd |= 0x80; - linktime = 0; - linkid = -1; - break; - case 0x25: // send & wait for data - case 0x1f: // pick a server - case 0x10: // init - case 0x16: // send broadcast data - case 0x17: // setup or something ? - case 0x27: // wait for data ? - case 0x3d: // init - default: - rfu_cmd |= 0x80; - break; - case 0xa5: // 2nd part of send&wait function 0x25 - case 0xa7: // 2nd part of wait function 0x27 - if(linkid==-1){ - linkid++; - linkmem->rfu_linktime[vbaid] = 0; - } - if(linkid&&linkmem->rfu_request[1-vbaid]==0){ - linkmem->rfu_q[1-vbaid] = 0; - transferend = 256; - rfu_polarity = 1; - rfu_cmd = 0x29; - linktime = 0; - break; - } - if((numtransfers++)==0) linktime = 0; - linkmem->rfu_linktime[vbaid] = linktime; - if(linkmem->numgbas==2){ - if(!linkid||(linkid&&numtransfers)) SetEvent(linksync[1-vbaid]); - WaitForSingleObject(linksync[vbaid], linktimeout); - ResetEvent(linksync[vbaid]); - } - if(linkid>0){ - memcpy(rfu_masterdata, linkmem->rfu_data[1-vbaid], 128); - rfu_masterq = linkmem->rfu_q[1-vbaid]; - } - transferend = linkmem->rfu_linktime[1-vbaid] - linktime + 256; - if(transferend<256) transferend = 256; - linktime = -transferend; - rfu_polarity = 1; - rfu_cmd = 0x28; - break; - } - UPDATE_REG(0x122, 0x9966); - UPDATE_REG(0x120, (rfu_qrecv<<8) | rfu_cmd); - } else { - UPDATE_REG(0x120, 0); - UPDATE_REG(0x122, 0x8000); - } - break; - case RFU_SEND: - if(--rfu_qsend==0) rfu_state = RFU_COMM; - switch(rfu_cmd){ - case 0x16: - linkmem->rfu_bdata[vbaid][counter++] = READ32LE(&ioMem[0x120]); - break; - case 0x17: - linkid = 1; - break; - case 0x1f: - linkmem->rfu_request[1-vbaid] = 1; - break; - case 0x24: - case 0x25: - linkmem->rfu_data[vbaid][counter++] = READ32LE(&ioMem[0x120]); - break; - } - UPDATE_REG(0x120, 0); - UPDATE_REG(0x122, 0x8000); - break; - case RFU_RECV: - if(--rfu_qrecv==0) rfu_state = RFU_COMM; - switch(rfu_cmd){ - case 0x9d: - case 0x9e: - if(counter==0){ - UPDATE_REG(0x120, 0x61f1); - UPDATE_REG(0x122, 0); - counter++; - break; - } - UPDATE_REG(0x120, linkmem->rfu_bdata[1-vbaid][counter-1]&0xffff); - UPDATE_REG(0x122, linkmem->rfu_bdata[1-vbaid][counter-1]>>16); - counter++; - break; - case 0xa6: - if(linkid>0){ - UPDATE_REG(0x120, rfu_masterdata[counter]&0xffff); - UPDATE_REG(0x122, rfu_masterdata[counter++]>>16); - } else { - UPDATE_REG(0x120, linkmem->rfu_data[1-vbaid][counter]&0xffff); - UPDATE_REG(0x122, linkmem->rfu_data[1-vbaid][counter++]>>16); - } - break; - case 0x93: // it seems like the game doesn't care about this value - UPDATE_REG(0x120, 0x1234); // put anything in here - UPDATE_REG(0x122, 0x0200); // also here, but it should be 0200 - break; - case 0xa0: - case 0xa1: - UPDATE_REG(0x120, 0x641b); - UPDATE_REG(0x122, 0x0000); - break; - case 0x9a: - UPDATE_REG(0x120, 0x61f9); - UPDATE_REG(0x122, 0); - break; - case 0x91: - UPDATE_REG(0x120, 0x00ff); - UPDATE_REG(0x122, 0x0000); - break; - default: - UPDATE_REG(0x120, 0x0173); - UPDATE_REG(0x122, 0x0000); - break; - } - break; - } - transfer = 1; - } - if(rfu_polarity) value ^= 4; // sometimes it's the other way around - default: - return value; - } -} - -void gbLinkStart(u8 value){ -// Not in this version :-) -} - - -void gbLinkUpdate(void){ -} - -int InitLink(void){ - WSADATA wsadata; - BOOL disable = true; - - linkid = 0; - - if(WSAStartup(MAKEWORD(1,1), &wsadata)!=0){ - WSACleanup(); - return 0; - } - - if((lanlink.tcpsocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET){ - MessageBox(NULL, "Couldn't create socket.", "Error!", MB_OK); - WSACleanup(); - return 0; - } - - setsockopt(lanlink.tcpsocket, IPPROTO_TCP, TCP_NODELAY, (char*)&disable, sizeof(BOOL)); - - if((mmf=CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(LINKDATA), "VBA link memory"))==NULL){ - closesocket(lanlink.tcpsocket); - WSACleanup(); - MessageBox(NULL, "Error creating file mapping", "Error", MB_OK|MB_ICONEXCLAMATION); - return 0; - } - - if(GetLastError() == ERROR_ALREADY_EXISTS) - vbaid = 1; - else - vbaid = 0; - - if((linkmem=(LINKDATA *)MapViewOfFile(mmf, FILE_MAP_WRITE, 0, 0, sizeof(LINKDATA)))==NULL){ - closesocket(lanlink.tcpsocket); - WSACleanup(); - CloseHandle(mmf); - MessageBox(NULL, "Error mapping file", "Error", MB_OK|MB_ICONEXCLAMATION); - return 0; - } - - if(linkmem->linkflags&LINK_PARENTLOST) - vbaid = 0; - - if(vbaid==0){ - linkid = 0; - if(linkmem->linkflags&LINK_PARENTLOST){ - linkmem->numgbas++; - linkmem->linkflags &= ~LINK_PARENTLOST; - } - else - linkmem->numgbas=1; - - for(i=0;i<4;i++){ - linkevent[15]=(char)i+'1'; - if((linksync[i]=CreateEvent(NULL, true, false, linkevent))==NULL){ - closesocket(lanlink.tcpsocket); - WSACleanup(); - UnmapViewOfFile(linkmem); - CloseHandle(mmf); - for(j=0;jnumgbas; - linkid = vbaid; - linkmem->numgbas++; - - linklog = 0; - if(linkmem->numgbas>4){ - linkmem->numgbas=4; - closesocket(lanlink.tcpsocket); - WSACleanup(); - MessageBox(NULL, "5 or more GBAs not supported.", "Error!", MB_OK|MB_ICONEXCLAMATION); - UnmapViewOfFile(linkmem); - CloseHandle(mmf); - return 0; - } - for(i=0;i<4;i++){ - linkevent[15]=(char)i+'1'; - if((linksync[i]=OpenEvent(EVENT_ALL_ACCESS, false, linkevent))==NULL){ - closesocket(lanlink.tcpsocket); - WSACleanup(); - CloseHandle(mmf); - UnmapViewOfFile(linkmem); - for(j=0;jlastlinktime=0xffffffff; - linkmem->numtransfers=0; - linkmem->linkflags=0; - lanlink.connected = false; - lanlink.thread = NULL; - lanlink.speed = false; - for(i=0;i<4;i++){ - linkmem->linkdata[i] = 0xffff; - linkdata[i] = 0xffff; - } -return 1; -} - -int openLinkLog(void){ - char filename[20]; - if(linklog){ - sprintf(filename, "vbalog%1d.txt", vbaid+1); - if((linklogfile=fopen(filename, "at"))==NULL){ - linklog=false; - return 0; - } - fprintf(linklogfile, "----- Log opened -----\n"); - } - return 1; -} - -void closeLinkLog() -{ - if(linklogfile) - { - fclose(linklogfile); - linklogfile=NULL; - } -} - -void CloseLink(void){ - if(lanlink.connected){ - if(linkid){ - char outbuffer[4]; - outbuffer[0] = 4; - outbuffer[1] = -32; - if(lanlink.type==0) send(lanlink.tcpsocket, outbuffer, 4, 0); - } else { - char outbuffer[12]; - int i; - outbuffer[0] = 12; - outbuffer[1] = -32; - for(i=1;i<=lanlink.numgbas;i++){ - if(lanlink.type==0){ - send(ls.tcpsocket[i], outbuffer, 12, 0); - } - closesocket(ls.tcpsocket[i]); - } - } - } - linkmem->numgbas--; - if(!linkid&&linkmem->numgbas!=0) - linkmem->linkflags|=LINK_PARENTLOST; - CloseHandle(mmf); - UnmapViewOfFile(linkmem); - - for(i=0;i<4;i++){ - if(linksync[i]!=NULL){ - PulseEvent(linksync[i]); - CloseHandle(linksync[i]); - } - } - regSetDwordValue("LAN", lanlink.active); - if(linklog) closeLinkLog(); - closesocket(lanlink.tcpsocket); - WSACleanup(); -return; -} - -lserver::lserver(void){ - intinbuffer = (int*)inbuffer; - u16inbuffer = (u16*)inbuffer; - intoutbuffer = (int*)outbuffer; - u16outbuffer = (u16*)outbuffer; - oncewait = false; -} - -int lserver::Init(void *serverdlg){ - SOCKADDR_IN info; - DWORD nothing; - char str[100]; - - info.sin_family = AF_INET; - info.sin_addr.S_un.S_addr = INADDR_ANY; - info.sin_port = htons(5738); - - if(bind(lanlink.tcpsocket, (LPSOCKADDR)&info, sizeof(SOCKADDR_IN))==SOCKET_ERROR){ - closesocket(lanlink.tcpsocket); - if((lanlink.tcpsocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) - return WSAGetLastError(); - if(bind(lanlink.tcpsocket, (LPSOCKADDR)&info, sizeof(SOCKADDR_IN))==SOCKET_ERROR) - return WSAGetLastError(); - } - - if(listen(lanlink.tcpsocket, lanlink.numgbas)==SOCKET_ERROR) - return WSAGetLastError(); - - if(lanlink.thread!=NULL){ - lanlink.terminate = true; - WaitForSingleObject(linksync[vbaid], 500); - lanlink.thread = NULL; - } - lanlink.terminate = false; - linkid = 0; - - gethostname(str, 100); - ((ServerWait*)serverdlg)->m_serveraddress.Format("Server IP address is: %s", inet_ntoa(*(LPIN_ADDR)(gethostbyname(str)->h_addr_list[0]))); - - lanlink.thread = CreateThread(NULL, 0, LinkServerThread, serverdlg, 0, ¬hing); - - return 0; - -} - -DWORD WINAPI LinkServerThread(void *serverdlg){ - fd_set fdset; - timeval wsocktimeout; - char inbuffer[256], outbuffer[256]; - int *intinbuffer = (int*)inbuffer; - u16 *u16inbuffer = (u16*)inbuffer; - int *intoutbuffer = (int*)outbuffer; - u16 *u16outbuffer = (u16*)outbuffer; - BOOL disable = true; - - wsocktimeout.tv_sec = 1; - wsocktimeout.tv_usec = 0; - i = 0; - - while(im_plconn[i].Format("Player %d connected", i+1); - ((ServerWait*)serverdlg)->UpdateData(false); - i++; - } - } - ((ServerWait*)serverdlg)->m_prgctrl.StepIt(); - } - MessageBox(NULL, "All players connected", "Link", MB_OK); - ((ServerWait*)serverdlg)->SendMessage(WM_CLOSE, 0, 0); - - for(i=1;i<=lanlink.numgbas;i++){ - outbuffer[0] = 4; - send(ls.tcpsocket[i], outbuffer, 4, 0); - } - - lanlink.connected = true; - - return 0; -} - -void lserver::Send(void){ - if(lanlink.type==0){ // TCP - if(savedlinktime==-1){ - outbuffer[0] = 4; - outbuffer[1] = -32; //0xe0 - for(i=1;i<=lanlink.numgbas;i++){ - send(tcpsocket[i], outbuffer, 4, 0); - recv(tcpsocket[i], inbuffer, 4, 0); - } - } - outbuffer[1] = tspeed; - u16outbuffer[1] = linkdata[0]; - intoutbuffer[1] = savedlinktime; - if(lanlink.numgbas==1){ - if(lanlink.type==0){ - outbuffer[0] = 8; - send(tcpsocket[1], outbuffer, 8, 0); - } - } - else if(lanlink.numgbas==2){ - u16outbuffer[4] = linkdata[2]; - if(lanlink.type==0){ - outbuffer[0] = 10; - send(tcpsocket[1], outbuffer, 10, 0); - u16outbuffer[4] = linkdata[1]; - send(tcpsocket[2], outbuffer, 10, 0); - } - } else { - if(lanlink.type==0){ - outbuffer[0] = 12; - u16outbuffer[4] = linkdata[2]; - u16outbuffer[5] = linkdata[3]; - send(tcpsocket[1], outbuffer, 12, 0); - u16outbuffer[4] = linkdata[1]; - send(tcpsocket[2], outbuffer, 12, 0); - u16outbuffer[5] = linkdata[2]; - send(tcpsocket[3], outbuffer, 12, 0); - } - } - } - return; -} - -void lserver::Recv(void){ - int numbytes; - if(lanlink.type==0){ // TCP - wsocktimeout.tv_usec = 0; - wsocktimeout.tv_sec = linktimeout / 1000; - fdset.fd_count = lanlink.numgbas; - for(i=0;i1) memcpy(inbuffer, inbuffer+inbuffer[0]*(howmanytimes-1), inbuffer[0]); - if(inbuffer[1]==-32){ - char message[30]; - lanlink.connected = false; - sprintf(message, "Player %d disconnected.", i+2); - MessageBox(NULL, message, "Link", MB_OK); - outbuffer[0] = 4; - outbuffer[1] = -32; - for(i=1;ih_addr_list); - - if(ioctlsocket(lanlink.tcpsocket, FIONBIO, ¬block)==SOCKET_ERROR) - return WSAGetLastError(); - - if(lanlink.thread!=NULL){ - lanlink.terminate = true; - WaitForSingleObject(linksync[vbaid], 500); - lanlink.thread = NULL; - } - - ((ServerWait*)waitdlg)->SetWindowText("Connecting..."); - lanlink.terminate = false; - lanlink.thread = CreateThread(NULL, 0, LinkClientThread, waitdlg, 0, ¬hing); - return 0; -} - -DWORD WINAPI LinkClientThread(void *waitdlg){ - fd_set fdset; - timeval wsocktimeout; - int numbytes; - char inbuffer[16]; - u16 *u16inbuffer = (u16*)inbuffer; - unsigned long block = 0; - - if(connect(lanlink.tcpsocket, (LPSOCKADDR)&lc.serverinfo, sizeof(SOCKADDR_IN))==SOCKET_ERROR){ - if(WSAGetLastError()!=WSAEWOULDBLOCK){ - MessageBox(NULL, "Couldn't connect to server.", "Link", MB_OK); - return 1; - } - wsocktimeout.tv_sec = 1; - wsocktimeout.tv_usec = 0; - do{ - if(lanlink.terminate) return 0; - fdset.fd_count = 1; - fdset.fd_array[0] = lanlink.tcpsocket; - ((ServerWait*)waitdlg)->m_prgctrl.StepIt(); - } while(select(0, NULL, &fdset, NULL, &wsocktimeout)!=1&&connect(lanlink.tcpsocket, (LPSOCKADDR)&lc.serverinfo, sizeof(SOCKADDR_IN))!=0); - } - - ioctlsocket(lanlink.tcpsocket, FIONBIO, &block); - - numbytes = 0; - while(numbytes<4) - numbytes += recv(lanlink.tcpsocket, inbuffer+numbytes, 16, 0); - linkid = (int)u16inbuffer[0]; - lanlink.numgbas = (int)u16inbuffer[1]; - - ((ServerWait*)waitdlg)->m_serveraddress.Format("Connected as #%d", linkid+1); - if(lanlink.numgbas!=linkid) ((ServerWait*)waitdlg)->m_plconn[0].Format("Waiting for %d players to join", lanlink.numgbas-linkid); - else ((ServerWait*)waitdlg)->m_plconn[0].Format("All players joined."); - - numbytes = 0; - inbuffer[0] = 1; - while(numbytesSendMessage(WM_CLOSE, 0, 0); - - block = 1; - - ioctlsocket(lanlink.tcpsocket, FIONBIO, &block); - - lanlink.connected = true; - return 0; -} - -void lclient::CheckConn(void){ - if((numbytes=recv(lanlink.tcpsocket, inbuffer, 256, 0))>0){ - while(numbytes - -#ifndef LINKH -#define LINKH -#define LINK_PARENTLOST 0x80 -#define UNSUPPORTED -1 -#define MULTIPLAYER 0 -#define NORMAL8 1 -#define NORMAL32 2 -#define UART 3 -#define JOYBUS 4 -#define GP 5 -#define RFU_INIT 0 -#define RFU_COMM 1 -#define RFU_SEND 2 -#define RFU_RECV 3 - -typedef struct { - WORD linkdata[4]; - WORD linkcmd[4]; - WORD numtransfers; - int lastlinktime; - unsigned char numgbas; - unsigned char linkflags; - int rfu_q[4]; - u8 rfu_request[4]; - int rfu_linktime[4]; - u32 rfu_bdata[4][7]; - u32 rfu_data[4][32]; -} LINKDATA; - -class lserver{ - int numbytes; - fd_set fdset; - timeval wsocktimeout; - //timeval udptimeout; - char inbuffer[256], outbuffer[256]; - int *intinbuffer; - u16 *u16inbuffer; - int *intoutbuffer; - u16 *u16outbuffer; - int counter; - int done; -public: - int howmanytimes; - SOCKET tcpsocket[4]; - SOCKADDR_IN udpaddr[4]; - lserver(void); - int Init(void*); - void Send(void); - void Recv(void); -}; - -class lclient{ - fd_set fdset; - timeval wsocktimeout; - char inbuffer[256], outbuffer[256]; - int *intinbuffer; - u16 *u16inbuffer; - int *intoutbuffer; - u16 *u16outbuffer; - int numbytes; -public: - bool oncesend; - SOCKADDR_IN serverinfo; - SOCKET noblock; - int numtransfers; - lclient(void); - int Init(LPHOSTENT, void*); - void Send(void); - void Recv(void); - void CheckConn(void); -}; - -typedef struct { - SOCKET tcpsocket; - //SOCKET udpsocket; - int numgbas; - HANDLE thread; - u8 type; - u8 server; - bool terminate; - bool connected; - bool speed; - bool active; -} LANLINKDATA; - -extern void LinkUpdate(void); -extern void LinkChildStop(void); -extern void LinkChildSend(u16); -extern int openLinkLog(void); -extern void closeLinkLog(); -extern void CloseLanLink(void); -extern char *MakeInstanceFilename(const char *Input); - -extern LANLINKDATA lanlink; -extern FILE *linklogfile; -extern int vbaid; -extern int linklog; -extern bool adapter; -extern bool linkenable; -extern int linktimeout; -extern lclient lc; -extern int linkid; - -#endif diff --git a/src/agb/GBAcpu.h b/src/agb/GBAcpu.h deleted file mode 100644 index 53384e9d..00000000 --- a/src/agb/GBAcpu.h +++ /dev/null @@ -1,302 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef VBA_GBAcpu_H -#define VBA_GBAcpu_H - -extern int armExecute(); -extern int thumbExecute(); - -#ifdef __GNUC__ -# define INSN_REGPARM __attribute__((regparm(1))) -# define LIKELY(x) __builtin_expect(!!(x),1) -# define UNLIKELY(x) __builtin_expect(!!(x),0) -#else -# define INSN_REGPARM /*nothing*/ -# define LIKELY(x) (x) -# define UNLIKELY(x) (x) -#endif - -#define UPDATE_REG(address, value)\ - {\ - WRITE16LE(((u16 *)&ioMem[address]),value);\ - }\ - -#define ARM_PREFETCH \ - {\ - cpuPrefetch[0] = CPUReadMemoryQuick(armNextPC);\ - cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);\ - } - -#define THUMB_PREFETCH \ - {\ - cpuPrefetch[0] = CPUReadHalfWordQuick(armNextPC);\ - cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);\ - } - -#define ARM_PREFETCH_NEXT \ - cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4); - -#define THUMB_PREFETCH_NEXT\ - cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2); - - -extern int SWITicks; -extern u32 mastercode; -extern bool busPrefetch; -extern bool busPrefetchEnable; -extern u32 busPrefetchCount; -extern int cpuNextEvent; -extern bool holdState; -extern u32 cpuPrefetch[2]; -extern int cpuTotalTicks; -extern u8 memoryWait[16]; -extern u8 memoryWait32[16]; -extern u8 memoryWaitSeq[16]; -extern u8 memoryWaitSeq32[16]; -extern u8 cpuBitsSet[256]; -extern u8 cpuLowestBitSet[256]; -extern void CPUSwitchMode(int mode, bool saveState, bool breakLoop); -extern void CPUSwitchMode(int mode, bool saveState); -extern void CPUUpdateCPSR(); -extern void CPUUpdateFlags(bool breakLoop); -extern void CPUUpdateFlags(); -extern void CPUUndefinedException(); -extern void CPUSoftwareInterrupt(); -extern void CPUSoftwareInterrupt(int comment); - - -// Waitstates when accessing data -inline int dataTicksAccess16(u32 address) // DATA 8/16bits NON SEQ -{ - int addr = (address>>24)&15; - int value = memoryWait[addr]; - - if ((addr>=0x08) || (addr < 0x02)) - { - busPrefetchCount=0; - busPrefetch=false; - } - else if (busPrefetch) - { - int waitState = value; - if (!waitState) - waitState = 1; - busPrefetchCount = ((busPrefetchCount+1)<>24)&15; - int value = memoryWait32[addr]; - - if ((addr>=0x08) || (addr < 0x02)) - { - busPrefetchCount=0; - busPrefetch=false; - } - else if (busPrefetch) - { - int waitState = value; - if (!waitState) - waitState = 1; - busPrefetchCount = ((busPrefetchCount+1)<>24)&15; - int value = memoryWaitSeq[addr]; - - if ((addr>=0x08) || (addr < 0x02)) - { - busPrefetchCount=0; - busPrefetch=false; - } - else if (busPrefetch) - { - int waitState = value; - if (!waitState) - waitState = 1; - busPrefetchCount = ((busPrefetchCount+1)<>24)&15; - int value = memoryWaitSeq32[addr]; - - if ((addr>=0x08) || (addr < 0x02)) - { - busPrefetchCount=0; - busPrefetch=false; - } - else if (busPrefetch) - { - int waitState = value; - if (!waitState) - waitState = 1; - busPrefetchCount = ((busPrefetchCount+1)<>24)&15; - - if ((addr>=0x08) && (addr<=0x0D)) - { - if (busPrefetchCount&0x1) - { - if (busPrefetchCount&0x2) - { - busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00); - return 0; - } - busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); - return memoryWaitSeq[addr]-1; - } - else - { - busPrefetchCount=0; - return memoryWait[addr]; - } - } - else - { - busPrefetchCount = 0; - return memoryWait[addr]; - } -} - -inline int codeTicksAccess32(u32 address) // ARM NON SEQ -{ - int addr = (address>>24)&15; - - if ((addr>=0x08) && (addr<=0x0D)) - { - if (busPrefetchCount&0x1) - { - if (busPrefetchCount&0x2) - { - busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00); - return 0; - } - busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); - return memoryWaitSeq[addr] - 1; - } - else - { - busPrefetchCount = 0; - return memoryWait32[addr]; - } - } - else - { - busPrefetchCount = 0; - return memoryWait32[addr]; - } -} - -inline int codeTicksAccessSeq16(u32 address) // THUMB SEQ -{ - int addr = (address>>24)&15; - - if ((addr>=0x08) && (addr<=0x0D)) - { - if (busPrefetchCount&0x1) - { - busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); - return 0; - } - else - if (busPrefetchCount>0xFF) - { - busPrefetchCount=0; - return memoryWait[addr]; - } - else - return memoryWaitSeq[addr]; - } - else - { - busPrefetchCount = 0; - return memoryWaitSeq[addr]; - } -} - -inline int codeTicksAccessSeq32(u32 address) // ARM SEQ -{ - int addr = (address>>24)&15; - - if ((addr>=0x08) && (addr<=0x0D)) - { - if (busPrefetchCount&0x1) - { - if (busPrefetchCount&0x2) - { - busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00); - return 0; - } - busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); - return memoryWaitSeq[addr]; - } - else - if (busPrefetchCount>0xFF) - { - busPrefetchCount=0; - return memoryWait32[addr]; - } - else - return memoryWaitSeq32[addr]; - } - else - { - return memoryWaitSeq32[addr]; - } -} - - -// Emulates the Cheat System (m) code -inline void cpuMasterCodeCheck() -{ - if((mastercode) && (mastercode == armNextPC)) - { - u32 joy = 0; - if(systemReadJoypads()) - joy = systemReadJoypad(-1); - u32 ext = (joy >> 10); - cpuTotalTicks += cheatsCheckKeys(P1^0x3FF, ext); - } -} - -#endif //VBA_GBAcpu_H diff --git a/src/agb/GBAinline.h b/src/agb/GBAinline.h deleted file mode 100644 index ebd9770e..00000000 --- a/src/agb/GBAinline.h +++ /dev/null @@ -1,739 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef VBA_GBAinline_H -#define VBA_GBAinline_H - -#include "../System.h" -#include "../Port.h" -#include "../RTC.h" -#include "../Sound.h" -#include "agbprint.h" - -extern const u32 objTilesAddress[3]; - -extern bool stopState; -extern bool holdState; -extern int holdType; -extern int cpuNextEvent; -extern bool cpuSramEnabled; -extern bool cpuFlashEnabled; -extern bool cpuEEPROMEnabled; -extern bool cpuEEPROMSensorEnabled; -extern bool cpuDmaHack; -extern u32 cpuDmaLast; -extern bool timer0On; -extern int timer0Ticks; -extern int timer0ClockReload; -extern bool timer1On; -extern int timer1Ticks; -extern int timer1ClockReload; -extern bool timer2On; -extern int timer2Ticks; -extern int timer2ClockReload; -extern bool timer3On; -extern int timer3Ticks; -extern int timer3ClockReload; -extern int cpuTotalTicks; - -#define CPUReadByteQuick(addr) \ - map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] - -#define CPUReadHalfWordQuick(addr) \ - READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) - -#define CPUReadMemoryQuick(addr) \ - READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) - -static inline u32 CPUReadMemory(u32 address) -{ - -#ifdef GBA_LOGGING - if(address & 3) { - if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } - } -#endif - - u32 value; - switch(address >> 24) { - case 0: - if(reg[15].I >> 24) { - if(address < 0x4000) { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - - value = READ32LE(((u32 *)&biosProtected)); - } - else goto unreadable; - } else - value = READ32LE(((u32 *)&bios[address & 0x3FFC])); - break; - case 2: - value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC])); - break; - case 3: - value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); - break; - case 4: - if((address < 0x4000400) && ioReadable[address & 0x3fc]) { - if(ioReadable[(address & 0x3fc) + 2]) - value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); - else - value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); - } else goto unreadable; - break; - case 5: - value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); - break; - case 6: - address = (address & 0x1fffc); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - { - value = 0; - break; - } - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - value = READ32LE(((u32 *)&vram[address])); - break; - case 7: - value = READ32LE(((u32 *)&oam[address & 0x3FC])); - break; - case 8: - case 9: - case 10: - case 11: - case 12: - value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); - break; - case 13: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; - case 14: - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); - // default - default: - unreadable: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - - if(cpuDmaHack) { - value = cpuDmaLast; - } else { - if(armState) { - value = CPUReadMemoryQuick(reg[15].I); - } else { - value = CPUReadHalfWordQuick(reg[15].I) | - CPUReadHalfWordQuick(reg[15].I) << 16; - } - } - } - - if(address & 3) { -#ifdef C_CORE - int shift = (address & 3) << 3; - value = (value >> shift) | (value << (32 - shift)); -#else -#ifdef __GNUC__ - asm("and $3, %%ecx;" - "shl $3 ,%%ecx;" - "ror %%cl, %0" - : "=r" (value) - : "r" (value), "c" (address)); -#else - __asm { - mov ecx, address; - and ecx, 3; - shl ecx, 3; - ror [dword ptr value], cl; - } -#endif -#endif - } - return value; -} - -extern u32 myROM[]; - -static inline u32 CPUReadHalfWord(u32 address) -{ -#ifdef GBA_LOGGING - if(address & 1) { - if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } - } -#endif - - u32 value; - - switch(address >> 24) { - case 0: - if (reg[15].I >> 24) { - if(address < 0x4000) { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - value = READ16LE(((u16 *)&biosProtected[address&2])); - } else goto unreadable; - } else - value = READ16LE(((u16 *)&bios[address & 0x3FFE])); - break; - case 2: - value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE])); - break; - case 3: - value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe])); - break; - case 4: - if((address < 0x4000400) && ioReadable[address & 0x3fe]) - { - value = READ16LE(((u16 *)&ioMem[address & 0x3fe])); - if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E)) - { - if (((address & 0x3fe) == 0x100) && timer0On) - value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload); - else - if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4)) - value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); - else - if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4)) - value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); - else - if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4)) - value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); - } - } - else goto unreadable; - break; - case 5: - value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe])); - break; - case 6: - address = (address & 0x1fffe); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - { - value = 0; - break; - } - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - value = READ16LE(((u16 *)&vram[address])); - break; - case 7: - value = READ16LE(((u16 *)&oam[address & 0x3fe])); - break; - case 8: - case 9: - case 10: - case 11: - case 12: - if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) - value = rtcRead(address); - else - value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); - break; - case 13: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; - case 14: - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); - // default - default: - unreadable: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - if(cpuDmaHack) { - value = cpuDmaLast & 0xFFFF; - } else { - if(armState) { - value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); - } else { - value = CPUReadHalfWordQuick(reg[15].I); - } - } - break; - } - - if(address & 1) { - value = (value >> 8) | (value << 24); - } - - return value; -} - -static inline u16 CPUReadHalfWordSigned(u32 address) -{ - u16 value = CPUReadHalfWord(address); - if((address & 1)) - value = (s8)value; - return value; -} - -static inline u8 CPUReadByte(u32 address) -{ - switch(address >> 24) { - case 0: - if (reg[15].I >> 24) { - if(address < 0x4000) { -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - return biosProtected[address & 3]; - } else goto unreadable; - } - return bios[address & 0x3FFF]; - case 2: - return workRAM[address & 0x3FFFF]; - case 3: - return internalRAM[address & 0x7fff]; - case 4: - if((address < 0x4000400) && ioReadable[address & 0x3ff]) - return ioMem[address & 0x3ff]; - else goto unreadable; - case 5: - return paletteRAM[address & 0x3ff]; - case 6: - address = (address & 0x1ffff); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return 0; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - return vram[address]; - case 7: - return oam[address & 0x3ff]; - case 8: - case 9: - case 10: - case 11: - case 12: - return rom[address & 0x1FFFFFF]; - case 13: - if(cpuEEPROMEnabled) - return eepromRead(address); - goto unreadable; - case 14: - if(cpuSramEnabled | cpuFlashEnabled) - return flashRead(address); - if(cpuEEPROMSensorEnabled) { - switch(address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } - // default - default: - unreadable: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - if(cpuDmaHack) { - return cpuDmaLast & 0xFF; - } else { - if(armState) { - return CPUReadByteQuick(reg[15].I+(address & 3)); - } else { - return CPUReadByteQuick(reg[15].I+(address & 1)); - } - } - break; - } -} - -static inline void CPUWriteMemory(u32 address, u32 value) -{ - -#ifdef GBA_LOGGING - if(address & 3) { - if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned word write: %08x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); - } - } -#endif - - switch(address >> 24) { - case 0x02: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC])) - cheatsWriteMemory(address & 0x203FFFC, - value); - else -#endif - WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); - break; - case 0x03: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeInternalRAM[address & 0x7ffc])) - cheatsWriteMemory(address & 0x3007FFC, - value); - else -#endif - WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); - break; - case 0x04: - if(address < 0x4000400) { - CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); - CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); - } else goto unwritable; - break; - case 0x05: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezePRAM[address & 0x3fc])) - cheatsWriteMemory(address & 0x70003FC, - value); - else -#endif - WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); - break; - case 0x06: - address = (address & 0x1fffc); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeVRAM[address])) - cheatsWriteMemory(address + 0x06000000, value); - else -#endif - - WRITE32LE(((u32 *)&vram[address]), value); - break; - case 0x07: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeOAM[address & 0x3fc])) - cheatsWriteMemory(address & 0x70003FC, - value); - else -#endif - WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); - break; - case 0x0D: - if(cpuEEPROMEnabled) { - eepromWrite(address, value); - break; - } - goto unwritable; - case 0x0E: - if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) { - (*cpuSaveGameFunc)(address, (u8)value); - break; - } - // default - default: - unwritable: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_WRITE) { - log("Illegal word write: %08x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); - } -#endif - break; - } -} - -static inline void CPUWriteHalfWord(u32 address, u16 value) -{ -#ifdef GBA_LOGGING - if(address & 1) { - if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned halfword write: %04x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); - } - } -#endif - - switch(address >> 24) { - case 2: -#ifdef BKPT_SUPPORT - if(*((u16 *)&freezeWorkRAM[address & 0x3FFFE])) - cheatsWriteHalfWord(address & 0x203FFFE, - value); - else -#endif - WRITE16LE(((u16 *)&workRAM[address & 0x3FFFE]),value); - break; - case 3: -#ifdef BKPT_SUPPORT - if(*((u16 *)&freezeInternalRAM[address & 0x7ffe])) - cheatsWriteHalfWord(address & 0x3007ffe, - value); - else -#endif - WRITE16LE(((u16 *)&internalRAM[address & 0x7ffe]), value); - break; - case 4: - if(address < 0x4000400) - CPUUpdateRegister(address & 0x3fe, value); - else goto unwritable; - break; - case 5: -#ifdef BKPT_SUPPORT - if(*((u16 *)&freezePRAM[address & 0x03fe])) - cheatsWriteHalfWord(address & 0x70003fe, - value); - else -#endif - WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value); - break; - case 6: - address = (address & 0x1fffe); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; -#ifdef BKPT_SUPPORT - if(*((u16 *)&freezeVRAM[address])) - cheatsWriteHalfWord(address + 0x06000000, - value); - else -#endif - WRITE16LE(((u16 *)&vram[address]), value); - break; - case 7: -#ifdef BKPT_SUPPORT - if(*((u16 *)&freezeOAM[address & 0x03fe])) - cheatsWriteHalfWord(address & 0x70003fe, - value); - else -#endif - WRITE16LE(((u16 *)&oam[address & 0x3fe]), value); - break; - case 8: - case 9: - if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) { - if(!rtcWrite(address, value)) - goto unwritable; - } else if(!agbPrintWrite(address, value)) goto unwritable; - break; - case 13: - if(cpuEEPROMEnabled) { - eepromWrite(address, (u8)value); - break; - } - goto unwritable; - case 14: - if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) { - (*cpuSaveGameFunc)(address, (u8)value); - break; - } - goto unwritable; - default: - unwritable: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_WRITE) { - log("Illegal halfword write: %04x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); - } -#endif - break; - } -} - -static inline void CPUWriteByte(u32 address, u8 b) -{ - switch(address >> 24) { - case 2: -#ifdef BKPT_SUPPORT - if(freezeWorkRAM[address & 0x3FFFF]) - cheatsWriteByte(address & 0x203FFFF, b); - else -#endif - workRAM[address & 0x3FFFF] = b; - break; - case 3: -#ifdef BKPT_SUPPORT - if(freezeInternalRAM[address & 0x7fff]) - cheatsWriteByte(address & 0x3007fff, b); - else -#endif - internalRAM[address & 0x7fff] = b; - break; - case 4: - if(address < 0x4000400) { - switch(address & 0x3FF) { - case 0x301: - if(b == 0x80) - stopState = true; - holdState = 1; - holdType = -1; - cpuNextEvent = cpuTotalTicks; - break; - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x68: - case 0x69: - case 0x6c: - case 0x6d: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x78: - case 0x79: - case 0x7c: - case 0x7d: - case 0x80: - case 0x81: - case 0x84: - case 0x85: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9a: - case 0x9b: - case 0x9c: - case 0x9d: - case 0x9e: - case 0x9f: - soundEvent(address&0xFF, b); - break; - default: - if(address & 1) - CPUUpdateRegister(address & 0x3fe, - ((READ16LE(((u16 *)&ioMem[address & 0x3fe]))) - & 0x00FF) | - b<<8); - else - CPUUpdateRegister(address & 0x3fe, - ((READ16LE(((u16 *)&ioMem[address & 0x3fe])) & 0xFF00) | b)); - } - break; - } else goto unwritable; - break; - case 5: - // no need to switch - *((u16 *)&paletteRAM[address & 0x3FE]) = (b << 8) | b; - break; - case 6: - address = (address & 0x1fffe); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - - // no need to switch - // byte writes to OBJ VRAM are ignored - if ((address) < objTilesAddress[((DISPCNT&7)+1)>>2]) - { -#ifdef BKPT_SUPPORT - if(freezeVRAM[address]) - cheatsWriteByte(address + 0x06000000, b); - else -#endif - *((u16 *)&vram[address]) = (b << 8) | b; - } - break; - case 7: - // no need to switch - // byte writes to OAM are ignored - // *((u16 *)&oam[address & 0x3FE]) = (b << 8) | b; - break; - case 13: - if(cpuEEPROMEnabled) { - eepromWrite(address, b); - break; - } - goto unwritable; - case 14: - if (!(saveType == 5) && (!eepromInUse | cpuSramEnabled | cpuFlashEnabled)) { - - //if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) { - - (*cpuSaveGameFunc)(address, b); - break; - } - // default - default: - unwritable: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_WRITE) { - log("Illegal byte write: %02x to %08x from %08x\n", - b, - address, - armMode ? armNextPC - 4 : armNextPC -2 ); - } -#endif - break; - } -} - -#endif //VBA_GBAinline_H diff --git a/src/agb/agbprint.cpp b/src/agb/agbprint.cpp deleted file mode 100644 index d07b3e3a..00000000 --- a/src/agb/agbprint.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include - -#include "GBA.h" -#include "../Globals.h" -#include "../Port.h" - -#define debuggerWriteHalfWord(addr, value) \ - WRITE16LE((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], (value)) - -#define debuggerReadHalfWord(addr) \ - READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) - -static bool agbPrintEnabled = false; -static bool agbPrintProtect = false; - -bool agbPrintWrite(u32 address, u16 value) -{ - if(agbPrintEnabled) { - if(address == 0x9fe2ffe) { // protect - agbPrintProtect = (value != 0); - debuggerWriteHalfWord(address, value); - return true; - } else { - if(agbPrintProtect && - ((address >= 0x9fe20f8 && address <= 0x9fe20ff) // control structure - || (address >= 0x8fd0000 && address <= 0x8fdffff) - || (address >= 0x9fd0000 && address <= 0x9fdffff))) { - debuggerWriteHalfWord(address, value); - return true; - } - } - } - return false; -} - -void agbPrintReset() -{ - agbPrintProtect = false; -} - -void agbPrintEnable(bool enable) -{ - agbPrintEnabled = enable; -} - -bool agbPrintIsEnabled() -{ - return agbPrintEnabled; -} - -extern void (*dbgOutput)(const char *, u32); - -void agbPrintFlush() -{ - u16 get = debuggerReadHalfWord(0x9fe20fc); - u16 put = debuggerReadHalfWord(0x9fe20fe); - - u32 address = (debuggerReadHalfWord(0x9fe20fa) << 16); - if(address != 0xfd0000 && address != 0x1fd0000) { - dbgOutput("Did you forget to call AGBPrintInit?\n", 0); - // get rid of the text otherwise we will continue to be called - debuggerWriteHalfWord(0x9fe20fc, put); - return; - } - - u8 *data = &rom[address]; - - while(get != put) { - char c = data[get++]; - char s[2]; - s[0] = c; - s[1] = 0; - - if(systemVerbose & VERBOSE_AGBPRINT) - dbgOutput(s, 0); - if(c == '\n') - break; - } - debuggerWriteHalfWord(0x9fe20fc, get); -} diff --git a/src/agb/agbprint.h b/src/agb/agbprint.h deleted file mode 100644 index d7742dee..00000000 --- a/src/agb/agbprint.h +++ /dev/null @@ -1,27 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef VBA_AGBPRINT_H -#define VBA_AGBPRINT_H -extern void agbPrintEnable(bool); -extern bool agbPrintIsEnabled(); -extern void agbPrintReset(); -extern bool agbPrintWrite(u32, u16); -extern void agbPrintFlush(); -#endif diff --git a/src/agb/gbafilter.cpp b/src/agb/gbafilter.cpp deleted file mode 100644 index 1b5aee99..00000000 --- a/src/agb/gbafilter.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include "gbafilter.h" - -#include - -extern int systemColorDepth; -extern int systemRedShift; -extern int systemGreenShift; -extern int systemBlueShift; - -extern u16 systemColorMap16[0x10000]; -extern u32 systemColorMap32[0x10000]; - -static const unsigned char curve[32] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12, - 0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x30, 0x38, - 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80, - 0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0}; - -// output R G B -static const unsigned char influence[3 * 3] = { 16, 4, 4, // red - 8, 16, 8, // green - 0, 8, 16};// blue - -inline void swap(short & a, short & b) -{ - short temp = a; - a = b; - b = temp; -} - -void gbafilter_pal(u16 * buf, int count) -{ - short temp[3 * 3], s; - unsigned pix; - u8 red, green, blue; - - while (count--) - { - pix = *buf; - - s = curve[(pix >> systemGreenShift) & 0x1f]; - temp[3] = s * influence[3]; - temp[4] = s * influence[4]; - temp[5] = s * influence[5]; - - s = curve[(pix >> systemRedShift) & 0x1f]; - temp[0] = s * influence[0]; - temp[1] = s * influence[1]; - temp[2] = s * influence[2]; - - s = curve[(pix >> systemBlueShift) & 0x1f]; - temp[6] = s * influence[6]; - temp[7] = s * influence[7]; - temp[8] = s * influence[8]; - - if (temp[0] < temp[3]) swap(temp[0], temp[3]); - if (temp[0] < temp[6]) swap(temp[0], temp[6]); - if (temp[3] < temp[6]) swap(temp[3], temp[6]); - temp[3] <<= 1; - temp[0] <<= 2; - temp[0] += temp[3] + temp[6]; - - red = ((int(temp[0]) * 160) >> 17) + 4; - if (red > 31) red = 31; - - if (temp[2] < temp[5]) swap(temp[2], temp[5]); - if (temp[2] < temp[8]) swap(temp[2], temp[8]); - if (temp[5] < temp[8]) swap(temp[5], temp[8]); - temp[5] <<= 1; - temp[2] <<= 2; - temp[2] += temp[5] + temp[8]; - - blue = ((int(temp[2]) * 160) >> 17) + 4; - if (blue > 31) blue = 31; - - if (temp[1] < temp[4]) swap(temp[1], temp[4]); - if (temp[1] < temp[7]) swap(temp[1], temp[7]); - if (temp[4] < temp[7]) swap(temp[4], temp[7]); - temp[4] <<= 1; - temp[1] <<= 2; - temp[1] += temp[4] + temp[7]; - - green = ((int(temp[1]) * 160) >> 17) + 4; - if (green > 31) green = 31; - - pix = red << systemRedShift; - pix += green << systemGreenShift; - pix += blue << systemBlueShift; - - *buf++ = pix; - } -} - -void gbafilter_pal32(u32 * buf, int count) -{ - short temp[3 * 3], s; - unsigned pix; - u8 red, green, blue; - - while (count--) - { - pix = *buf; - - s = curve[(pix >> systemGreenShift) & 0x1f]; - temp[3] = s * influence[3]; - temp[4] = s * influence[4]; - temp[5] = s * influence[5]; - - s = curve[(pix >> systemRedShift) & 0x1f]; - temp[0] = s * influence[0]; - temp[1] = s * influence[1]; - temp[2] = s * influence[2]; - - s = curve[(pix >> systemBlueShift) & 0x1f]; - temp[6] = s * influence[6]; - temp[7] = s * influence[7]; - temp[8] = s * influence[8]; - - if (temp[0] < temp[3]) swap(temp[0], temp[3]); - if (temp[0] < temp[6]) swap(temp[0], temp[6]); - if (temp[3] < temp[6]) swap(temp[3], temp[6]); - temp[3] <<= 1; - temp[0] <<= 2; - temp[0] += temp[3] + temp[6]; - - //red = ((int(temp[0]) * 160) >> 17) + 4; - red = ((int(temp[0]) * 160) >> 14) + 32; - - if (temp[2] < temp[5]) swap(temp[2], temp[5]); - if (temp[2] < temp[8]) swap(temp[2], temp[8]); - if (temp[5] < temp[8]) swap(temp[5], temp[8]); - temp[5] <<= 1; - temp[2] <<= 2; - temp[2] += temp[5] + temp[8]; - - //blue = ((int(temp[2]) * 160) >> 17) + 4; - blue = ((int(temp[2]) * 160) >> 14) + 32; - - if (temp[1] < temp[4]) swap(temp[1], temp[4]); - if (temp[1] < temp[7]) swap(temp[1], temp[7]); - if (temp[4] < temp[7]) swap(temp[4], temp[7]); - temp[4] <<= 1; - temp[1] <<= 2; - temp[1] += temp[4] + temp[7]; - - //green = ((int(temp[1]) * 160) >> 17) + 4; - green = ((int(temp[1]) * 160) >> 14) + 32; - - //pix = red << redshift; - //pix += green << greenshift; - //pix += blue << blueshift; - - pix = red << (systemRedShift - 3); - pix += green << (systemGreenShift - 3); - pix += blue << (systemBlueShift - 3); - - *buf++ = pix; - } -} - -// for palette mode to work with the three spoony filters in 32bpp depth - -void gbafilter_pad(u8 * buf, int count) -{ - union - { - struct - { - u8 r; - u8 g; - u8 b; - u8 a; - } part; - unsigned whole; - } - mask; - - mask.whole = 0x1f << systemRedShift; - mask.whole += 0x1f << systemGreenShift; - mask.whole += 0x1f << systemBlueShift; - - switch (systemColorDepth) - { - case 24: - while (count--) - { - *buf++ &= mask.part.r; - *buf++ &= mask.part.g; - *buf++ &= mask.part.b; - } - break; - case 32: - while (count--) - { - *((u32*)buf) &= mask.whole; - buf += 4; - } - } -} - -/* -void UpdateSystemColorMaps(int lcd) -{ - switch(systemColorDepth) { - case 16: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - if (lcd == 1) gbafilter_pal(systemColorMap16, 0x10000); - } - break; - case 24: - case 32: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - if (lcd == 1) gbafilter_pal32(systemColorMap32, 0x10000); - } - break; - } -} -*/ diff --git a/src/agb/gbafilter.h b/src/agb/gbafilter.h deleted file mode 100644 index 18ff53d3..00000000 --- a/src/agb/gbafilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#include "../System.h" - -void gbafilter_pal(u16 * buf, int count); -void gbafilter_pal32(u32 * buf, int count); -void gbafilter_pad(u8 * buf, int count); diff --git a/src/dmg/GB.cpp b/src/dmg/GB.cpp deleted file mode 100644 index 9f4abab5..00000000 --- a/src/dmg/GB.cpp +++ /dev/null @@ -1,5455 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include -#include -#include - -#include "../System.h" -#include "../NLS.h" -#include "gb.h" -#include "gbCheats.h" -#include "gbGlobals.h" -#include "gbMemory.h" -#include "gbSGB.h" -#include "gbSound.h" -#include "../Util.h" - -#ifdef __GNUC__ -#define _stricmp strcasecmp -#endif - -extern u8 *pix; -extern bool speedup; - -bool gbUpdateSizes(); -bool inBios = false; - -// debugging -bool memorydebug = false; -char gbBuffer[2048]; - -extern u16 gbLineMix[160]; - -// mappers -void (*mapper)(u16,u8) = NULL; -void (*mapperRAM)(u16,u8) = NULL; -u8 (*mapperReadRAM)(u16) = NULL; -void (*mapperUpdateClock)() = NULL; - -// registers -gbRegister PC; -gbRegister SP; -gbRegister AF; -gbRegister BC; -gbRegister DE; -gbRegister HL; -u16 IFF = 0; -// 0xff04 -u8 register_DIV = 0; -// 0xff05 -u8 register_TIMA = 0; -// 0xff06 -u8 register_TMA = 0; -// 0xff07 -u8 register_TAC = 0; -// 0xff0f -u8 register_IF = 0; -// 0xff40 -u8 register_LCDC = 0; -// 0xff41 -u8 register_STAT = 0; -// 0xff42 -u8 register_SCY = 0; -// 0xff43 -u8 register_SCX = 0; -// 0xff44 -u8 register_LY = 0; -// 0xff45 -u8 register_LYC = 0; -// 0xff46 -u8 register_DMA = 0; -// 0xff4a -u8 register_WY = 0; -// 0xff4b -u8 register_WX = 0; -// 0xff4f -u8 register_VBK = 0; -// 0xff51 -u8 register_HDMA1 = 0; -// 0xff52 -u8 register_HDMA2 = 0; -// 0xff53 -u8 register_HDMA3 = 0; -// 0xff54 -u8 register_HDMA4 = 0; -// 0xff55 -u8 register_HDMA5 = 0; -// 0xff70 -u8 register_SVBK = 0; -// 0xffff -u8 register_IE = 0; - -// ticks definition -int GBDIV_CLOCK_TICKS = 64; -int GBLCD_MODE_0_CLOCK_TICKS = 51; -int GBLCD_MODE_1_CLOCK_TICKS = 1140; -int GBLCD_MODE_2_CLOCK_TICKS = 20; -int GBLCD_MODE_3_CLOCK_TICKS = 43; -int GBLY_INCREMENT_CLOCK_TICKS = 114; -int GBTIMER_MODE_0_CLOCK_TICKS = 256; -int GBTIMER_MODE_1_CLOCK_TICKS = 4; -int GBTIMER_MODE_2_CLOCK_TICKS = 16; -int GBTIMER_MODE_3_CLOCK_TICKS = 64; -int GBSERIAL_CLOCK_TICKS = 128; -int GBSYNCHRONIZE_CLOCK_TICKS = 52920; - -// state variables - -// general -int clockTicks = 0; -bool gbSystemMessage = false; -int gbGBCColorType = 0; -int gbHardware = 0; -int gbRomType = 0; -int gbRemainingClockTicks = 0; -int gbOldClockTicks = 0; -int gbIntBreak = 0; -int gbInterruptLaunched = 0; -u8 gbCheatingDevice = 0; // 1 = GS, 2 = GG -// breakpoint -bool breakpoint = false; -// interrupt -int gbInt48Signal = 0; -int gbInterruptWait = 0; -// serial -int gbSerialOn = 0; -int gbSerialTicks = 0; -int gbSerialBits = 0; -// timer -bool gbTimerOn = false; -int gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; -int gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS; -int gbTimerMode = 0; -bool gbIncreased = false; -// The internal timer is always active, and it is -// not reset by writing to register_TIMA/TMA, but by -// writing to register_DIV... -int gbInternalTimer = 0x55; -const u8 gbTimerMask [4] = {0xff, 0x3, 0xf, 0x3f}; -const u8 gbTimerBug [8] = {0x80, 0x80, 0x02, 0x02, 0x0, 0xff, 0x0, 0xff}; -bool gbTimerModeChange = false; -bool gbTimerOnChange = false; -// lcd -bool gbScreenOn = true; -int gbLcdMode = 2; -int gbLcdModeDelayed = 2; -int gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS-1; -int gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS; -int gbLcdLYIncrementTicks = 114; -int gbLcdLYIncrementTicksDelayed = 115; -int gbScreenTicks = 0; -u8 gbSCYLine[300]; -u8 gbSCXLine[300]; -u8 gbBgpLine[300]; -u8 gbObp0Line [300]; -u8 gbObp1Line [300]; -u8 gbSpritesTicks [300]; -u8 oldRegister_WY; -bool gbLYChangeHappened = false; -bool gbLCDChangeHappened = false; -int gbLine99Ticks = 1; -int gbRegisterLYLCDCOffOn = 0; -int inUseRegister_WY = 0; - -// Used to keep track of the line that ellapse -// when screen is off -int gbWhiteScreen = 0; -bool gbBlackScreen = false; -int register_LCDCBusy = 0; - -// div -int gbDivTicks = GBDIV_CLOCK_TICKS; -// cgb -int gbVramBank = 0; -int gbWramBank = 1; -//sgb -bool gbSgbResetFlag = false; -// gbHdmaDestination is 0x99d0 on startup (tested on HW) -// but I'm not sure what gbHdmaSource is... -int gbHdmaSource = 0x99d0; -int gbHdmaDestination = 0x99d0; -int gbHdmaBytes = 0x0000; -int gbHdmaOn = 0; -int gbSpeed = 0; -// frame counting -int gbFrameCount = 0; -int gbFrameSkip = 0; -int gbFrameSkipCount = 0; -// timing -u32 gbLastTime = 0; -u32 gbElapsedTime = 0; -u32 gbTimeNow = 0; -int gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; -// emulator features -int gbBattery = 0; -bool gbBatteryError = false; -int gbCaptureNumber = 0; -bool gbCapture = false; -bool gbCapturePrevious = false; -int gbJoymask[4] = { 0, 0, 0, 0 }; - -int gbRomSizes[] = { 0x00008000, // 32K - 0x00010000, // 64K - 0x00020000, // 128K - 0x00040000, // 256K - 0x00080000, // 512K - 0x00100000, // 1024K - 0x00200000, // 2048K - 0x00400000, // 4096K - 0x00800000 // 8192K -}; -int gbRomSizesMasks[] = { 0x00007fff, - 0x0000ffff, - 0x0001ffff, - 0x0003ffff, - 0x0007ffff, - 0x000fffff, - 0x001fffff, - 0x003fffff, - 0x007fffff -}; - -int gbRamSizes[6] = { 0x00000000, // 0K - 0x00002000, // 2K // Changed to 2000 to avoid problems with gbMemoryMap... - 0x00002000, // 8K - 0x00008000, // 32K - 0x00020000, // 128K - 0x00010000 // 64K -}; - -int gbRamSizesMasks[6] = { 0x00000000, - 0x000007ff, - 0x00001fff, - 0x00007fff, - 0x0001ffff, - 0x0000ffff -}; - -int gbCycles[] = { -// 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, // 0 - 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, // 1 - 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 2 - 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 3 - 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 4 - 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 5 - 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 6 - 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, // 7 - 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 8 - 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 9 - 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a - 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b - 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c - 2, 3, 3, 1, 3, 4, 2, 4, 2, 4, 3, 1, 3, 1, 2, 4, // d - 3, 3, 2, 1, 1, 4, 2, 4, 4, 1, 4, 1, 1, 1, 2, 4, // e - 3, 3, 2, 1, 1, 4, 2, 4, 3, 2, 4, 1, 0, 1, 2, 4 // f -}; - -int gbCyclesCB[] = { -// 0 1 2 3 4 5 6 7 8 9 a b c d e f - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 0 - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 1 - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 2 - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 3 - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 4 - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5 - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6 - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7 - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 8 - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 9 - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // a - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // b - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // c - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // d - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // e - 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2 // f -}; - -u16 DAATable[] = { - 0x0080,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0800,0x0900,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1800,0x1900,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520, - 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, - 0x2800,0x2900,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520, - 0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x3600,0x3700, - 0x3800,0x3900,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4800,0x4900,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5800,0x5900,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520, - 0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700, - 0x6800,0x6900,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520, - 0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x7600,0x7700, - 0x7800,0x7900,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520, - 0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x8600,0x8700, - 0x8800,0x8900,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520, - 0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x9600,0x9700, - 0x9800,0x9900,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, - 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710, - 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, - 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, - 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710, - 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, - 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710, - 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, - 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710, - 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, - 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, - 0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,0x6610,0x6710, - 0x6810,0x6910,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530, - 0x7010,0x7110,0x7210,0x7310,0x7410,0x7510,0x7610,0x7710, - 0x7810,0x7910,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530, - 0x8010,0x8110,0x8210,0x8310,0x8410,0x8510,0x8610,0x8710, - 0x8810,0x8910,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530, - 0x9010,0x9110,0x9210,0x9310,0x9410,0x9510,0x9610,0x9710, - 0x9810,0x9910,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530, - 0xA010,0xA110,0xA210,0xA310,0xA410,0xA510,0xA610,0xA710, - 0xA810,0xA910,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530, - 0xB010,0xB110,0xB210,0xB310,0xB410,0xB510,0xB610,0xB710, - 0xB810,0xB910,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530, - 0xC010,0xC110,0xC210,0xC310,0xC410,0xC510,0xC610,0xC710, - 0xC810,0xC910,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530, - 0xD010,0xD110,0xD210,0xD310,0xD410,0xD510,0xD610,0xD710, - 0xD810,0xD910,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530, - 0xE010,0xE110,0xE210,0xE310,0xE410,0xE510,0xE610,0xE710, - 0xE810,0xE910,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530, - 0xF010,0xF110,0xF210,0xF310,0xF410,0xF510,0xF610,0xF710, - 0xF810,0xF910,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, - 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710, - 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, - 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, - 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710, - 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, - 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710, - 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, - 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710, - 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, - 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, - 0x0600,0x0700,0x0800,0x0900,0x0A00,0x0B00,0x0C00,0x0D00, - 0x0E00,0x0F00,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520, - 0x1600,0x1700,0x1800,0x1900,0x1A00,0x1B00,0x1C00,0x1D00, - 0x1E00,0x1F00,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520, - 0x2600,0x2700,0x2800,0x2900,0x2A00,0x2B00,0x2C00,0x2D00, - 0x2E00,0x2F00,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520, - 0x3600,0x3700,0x3800,0x3900,0x3A00,0x3B00,0x3C00,0x3D00, - 0x3E00,0x3F00,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520, - 0x4600,0x4700,0x4800,0x4900,0x4A00,0x4B00,0x4C00,0x4D00, - 0x4E00,0x4F00,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520, - 0x5600,0x5700,0x5800,0x5900,0x5A00,0x5B00,0x5C00,0x5D00, - 0x5E00,0x5F00,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520, - 0x6600,0x6700,0x6800,0x6900,0x6A00,0x6B00,0x6C00,0x6D00, - 0x6E00,0x6F00,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520, - 0x7600,0x7700,0x7800,0x7900,0x7A00,0x7B00,0x7C00,0x7D00, - 0x7E00,0x7F00,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520, - 0x8600,0x8700,0x8800,0x8900,0x8A00,0x8B00,0x8C00,0x8D00, - 0x8E00,0x8F00,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520, - 0x9600,0x9700,0x9800,0x9900,0x9A00,0x9B00,0x9C00,0x9D00, - 0x9E00,0x9F00,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, - 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10, - 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, - 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10, - 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, - 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10, - 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, - 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10, - 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, - 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10, - 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, - 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10, - 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, - 0x6610,0x6710,0x6810,0x6910,0x6A10,0x6B10,0x6C10,0x6D10, - 0x6E10,0x6F10,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530, - 0x7610,0x7710,0x7810,0x7910,0x7A10,0x7B10,0x7C10,0x7D10, - 0x7E10,0x7F10,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530, - 0x8610,0x8710,0x8810,0x8910,0x8A10,0x8B10,0x8C10,0x8D10, - 0x8E10,0x8F10,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530, - 0x9610,0x9710,0x9810,0x9910,0x9A10,0x9B10,0x9C10,0x9D10, - 0x9E10,0x9F10,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530, - 0xA610,0xA710,0xA810,0xA910,0xAA10,0xAB10,0xAC10,0xAD10, - 0xAE10,0xAF10,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530, - 0xB610,0xB710,0xB810,0xB910,0xBA10,0xBB10,0xBC10,0xBD10, - 0xBE10,0xBF10,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530, - 0xC610,0xC710,0xC810,0xC910,0xCA10,0xCB10,0xCC10,0xCD10, - 0xCE10,0xCF10,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530, - 0xD610,0xD710,0xD810,0xD910,0xDA10,0xDB10,0xDC10,0xDD10, - 0xDE10,0xDF10,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530, - 0xE610,0xE710,0xE810,0xE910,0xEA10,0xEB10,0xEC10,0xED10, - 0xEE10,0xEF10,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530, - 0xF610,0xF710,0xF810,0xF910,0xFA10,0xFB10,0xFC10,0xFD10, - 0xFE10,0xFF10,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, - 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10, - 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, - 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10, - 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, - 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10, - 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, - 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10, - 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, - 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10, - 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, - 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10, - 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, - 0x00C0,0x0140,0x0240,0x0340,0x0440,0x0540,0x0640,0x0740, - 0x0840,0x0940,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940, - 0x1040,0x1140,0x1240,0x1340,0x1440,0x1540,0x1640,0x1740, - 0x1840,0x1940,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940, - 0x2040,0x2140,0x2240,0x2340,0x2440,0x2540,0x2640,0x2740, - 0x2840,0x2940,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940, - 0x3040,0x3140,0x3240,0x3340,0x3440,0x3540,0x3640,0x3740, - 0x3840,0x3940,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940, - 0x4040,0x4140,0x4240,0x4340,0x4440,0x4540,0x4640,0x4740, - 0x4840,0x4940,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940, - 0x5040,0x5140,0x5240,0x5340,0x5440,0x5540,0x5640,0x5740, - 0x5840,0x5940,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940, - 0x6040,0x6140,0x6240,0x6340,0x6440,0x6540,0x6640,0x6740, - 0x6840,0x6940,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940, - 0x7040,0x7140,0x7240,0x7340,0x7440,0x7540,0x7640,0x7740, - 0x7840,0x7940,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940, - 0x8040,0x8140,0x8240,0x8340,0x8440,0x8540,0x8640,0x8740, - 0x8840,0x8940,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940, - 0x9040,0x9140,0x9240,0x9340,0x9440,0x9540,0x9640,0x9740, - 0x9840,0x9940,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, - 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750, - 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, - 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750, - 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, - 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750, - 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, - 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750, - 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, - 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750, - 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, - 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750, - 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, - 0xA050,0xA150,0xA250,0xA350,0xA450,0xA550,0xA650,0xA750, - 0xA850,0xA950,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950, - 0xB050,0xB150,0xB250,0xB350,0xB450,0xB550,0xB650,0xB750, - 0xB850,0xB950,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950, - 0xC050,0xC150,0xC250,0xC350,0xC450,0xC550,0xC650,0xC750, - 0xC850,0xC950,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950, - 0xD050,0xD150,0xD250,0xD350,0xD450,0xD550,0xD650,0xD750, - 0xD850,0xD950,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950, - 0xE050,0xE150,0xE250,0xE350,0xE450,0xE550,0xE650,0xE750, - 0xE850,0xE950,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950, - 0xF050,0xF150,0xF250,0xF350,0xF450,0xF550,0xF650,0xF750, - 0xF850,0xF950,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950, - 0x00D0,0x0150,0x0250,0x0350,0x0450,0x0550,0x0650,0x0750, - 0x0850,0x0950,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950, - 0x1050,0x1150,0x1250,0x1350,0x1450,0x1550,0x1650,0x1750, - 0x1850,0x1950,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950, - 0x2050,0x2150,0x2250,0x2350,0x2450,0x2550,0x2650,0x2750, - 0x2850,0x2950,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950, - 0x3050,0x3150,0x3250,0x3350,0x3450,0x3550,0x3650,0x3750, - 0x3850,0x3950,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, - 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750, - 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, - 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750, - 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, - 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750, - 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, - 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750, - 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, - 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750, - 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, - 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750, - 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, - 0xFA60,0xFB60,0xFC60,0xFD60,0xFE60,0xFF60,0x00C0,0x0140, - 0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940, - 0x0A60,0x0B60,0x0C60,0x0D60,0x0E60,0x0F60,0x1040,0x1140, - 0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940, - 0x1A60,0x1B60,0x1C60,0x1D60,0x1E60,0x1F60,0x2040,0x2140, - 0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940, - 0x2A60,0x2B60,0x2C60,0x2D60,0x2E60,0x2F60,0x3040,0x3140, - 0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940, - 0x3A60,0x3B60,0x3C60,0x3D60,0x3E60,0x3F60,0x4040,0x4140, - 0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940, - 0x4A60,0x4B60,0x4C60,0x4D60,0x4E60,0x4F60,0x5040,0x5140, - 0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940, - 0x5A60,0x5B60,0x5C60,0x5D60,0x5E60,0x5F60,0x6040,0x6140, - 0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940, - 0x6A60,0x6B60,0x6C60,0x6D60,0x6E60,0x6F60,0x7040,0x7140, - 0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940, - 0x7A60,0x7B60,0x7C60,0x7D60,0x7E60,0x7F60,0x8040,0x8140, - 0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940, - 0x8A60,0x8B60,0x8C60,0x8D60,0x8E60,0x8F60,0x9040,0x9140, - 0x9240,0x9340,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, - 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150, - 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, - 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150, - 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, - 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150, - 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, - 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150, - 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, - 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150, - 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, - 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150, - 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, - 0x9A70,0x9B70,0x9C70,0x9D70,0x9E70,0x9F70,0xA050,0xA150, - 0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950, - 0xAA70,0xAB70,0xAC70,0xAD70,0xAE70,0xAF70,0xB050,0xB150, - 0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950, - 0xBA70,0xBB70,0xBC70,0xBD70,0xBE70,0xBF70,0xC050,0xC150, - 0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950, - 0xCA70,0xCB70,0xCC70,0xCD70,0xCE70,0xCF70,0xD050,0xD150, - 0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950, - 0xDA70,0xDB70,0xDC70,0xDD70,0xDE70,0xDF70,0xE050,0xE150, - 0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950, - 0xEA70,0xEB70,0xEC70,0xED70,0xEE70,0xEF70,0xF050,0xF150, - 0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950, - 0xFA70,0xFB70,0xFC70,0xFD70,0xFE70,0xFF70,0x00D0,0x0150, - 0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950, - 0x0A70,0x0B70,0x0C70,0x0D70,0x0E70,0x0F70,0x1050,0x1150, - 0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950, - 0x1A70,0x1B70,0x1C70,0x1D70,0x1E70,0x1F70,0x2050,0x2150, - 0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950, - 0x2A70,0x2B70,0x2C70,0x2D70,0x2E70,0x2F70,0x3050,0x3150, - 0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, - 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150, - 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, - 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150, - 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, - 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150, - 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, - 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150, - 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, - 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150, - 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, - 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150, - 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, -}; - -u8 ZeroTable[256] = { - 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0 -}; - -#define GBSAVE_GAME_VERSION_1 1 -#define GBSAVE_GAME_VERSION_2 2 -#define GBSAVE_GAME_VERSION_3 3 -#define GBSAVE_GAME_VERSION_4 4 -#define GBSAVE_GAME_VERSION_5 5 -#define GBSAVE_GAME_VERSION_6 6 -#define GBSAVE_GAME_VERSION_7 7 -#define GBSAVE_GAME_VERSION_8 8 -#define GBSAVE_GAME_VERSION_9 9 -#define GBSAVE_GAME_VERSION_10 10 -#define GBSAVE_GAME_VERSION_11 11 -#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_11 - -int inline gbGetValue(int min,int max,int v) -{ - return (int)(min+(float)(max-min)*(2.0*(v/31.0)-(v/31.0)*(v/31.0))); -} - -void gbGenFilter() -{ - for (int r=0;r<32;r++) { - for (int g=0;g<32;g++) { - for (int b=0;b<32;b++) { - int nr=gbGetValue(gbGetValue(4,14,g), - gbGetValue(24,29,g),r)-4; - int ng=gbGetValue(gbGetValue(4+gbGetValue(0,5,r), - 14+gbGetValue(0,3,r),b), - gbGetValue(24+gbGetValue(0,3,r), - 29+gbGetValue(0,1,r),b),g)-4; - int nb=gbGetValue(gbGetValue(4+gbGetValue(0,5,r), - 14+gbGetValue(0,3,r),g), - gbGetValue(24+gbGetValue(0,3,r), - 29+gbGetValue(0,1,r),g),b)-4; - gbColorFilter[(b<<10)|(g<<5)|r]=(nb<<10)|(ng<<5)|nr; - } - } - } -} - -bool gbIsGameboyRom(char * file) -{ - if(strlen(file) > 4) { - char * p = strrchr(file,'.'); - - if(p != NULL) { - if(_stricmp(p, ".gb") == 0) - return true; - if(_stricmp(p, ".gbc") == 0) - return true; - if(_stricmp(p, ".cgb") == 0) - return true; - if(_stricmp(p, ".sgb") == 0) - return true; - } - } - - return false; -} - -void gbCopyMemory(u16 d, u16 s, int count) -{ - while(count) { - gbMemoryMap[d>>12][d & 0x0fff] = gbMemoryMap[s>>12][s & 0x0fff]; - s++; - d++; - count--; - } -} - -void gbDoHdma() -{ - - gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000, - gbHdmaSource & 0xfff0, - 0x10); - - gbHdmaDestination += 0x10; - if (gbHdmaDestination == 0xa000) - gbHdmaDestination = 0x8000; - - gbHdmaSource += 0x10; - if (gbHdmaSource == 0x8000) - gbHdmaSource = 0xa000; - - register_HDMA2 = gbHdmaSource & 0xff; - register_HDMA1 = gbHdmaSource>>8; - - register_HDMA4 = gbHdmaDestination & 0xff; - register_HDMA3 = gbHdmaDestination>>8; - - gbHdmaBytes -= 0x10; - gbMemory[0xff55] = --register_HDMA5; - if(register_HDMA5 == 0xff) - gbHdmaOn = 0; - -// We need to add the dmaClockticks for HDMA ! - if(gbSpeed) - gbDmaTicks = 17; - else - gbDmaTicks = 9; - - if (IFF & 0x80) - gbDmaTicks++; - -} - -// fix for Harley and Lego Racers -void gbCompareLYToLYC() -{ - if(register_LCDC & 0x80) { - if(register_LY == register_LYC) { - - // mark that we have a match - register_STAT |= 4; - - // check if we need an interrupt - if (register_STAT & 0x40) - { - // send LCD interrupt only if no interrupt 48h signal... - if (!gbInt48Signal) - { - register_IF |=2; - } - gbInt48Signal |= 8; - } - } - else // no match - { - register_STAT &= 0xfb; - gbInt48Signal &=~8; - } - } -} - -void gbWriteMemory(register u16 address, register u8 value) -{ - - if(address < 0x8000) { -#ifndef FINAL_VERSION - if(memorydebug && (address>0x3fff || address < 0x2000)) { - log("Memory register write %04x=%02x PC=%04x\n", - address, - value, - PC.W); - } - -#endif - if(mapper) - (*mapper)(address, value); - return; - - } - - if(address < 0xa000) { - // No access to Vram during mode 3 - // (used to emulate the gfx differences between GB & GBC-GBA/SP in Stunt Racer) - if ((gbLcdModeDelayed !=3) || - // This part is used to emulate a small difference between hardwares - // (check 8-in-1's arrow on GBA/GBC to verify it) - ((register_LY == 0) && ((gbHardware & 0xa) && (gbScreenOn==false) && - (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) - gbMemoryMap[address>>12][address&0x0fff] = value; - return; - } - - // Used for the mirroring of 0xC000 in 0xE000 - if ((address >= 0xe000) && (address < 0xfe00)) - address &= ~0x2000; - - if(address < 0xc000) { -#ifndef FINAL_VERSION - if(memorydebug) { - log("Memory register write %04x=%02x PC=%04x\n", - address, - value, - PC.W); - } -#endif - - // Is that a correct fix ??? (it used to be 'if (mapper)')... - if(mapperRAM) - (*mapperRAM)(address, value); - return; - } - - - if(address < 0xfe00) { - gbMemoryMap[address>>12][address & 0x0fff] = value; - return; - } - - // OAM not accessible during mode 2 & 3. - if(address < 0xfea0) - { - if (((gbHardware & 0xa) && ((gbLcdMode | gbLcdModeDelayed) &2)) || - ((gbHardware & 5) && (((gbLcdModeDelayed == 2) && - (gbLcdTicksDelayed<=GBLCD_MODE_2_CLOCK_TICKS)) || - (gbLcdModeDelayed == 3)))) - return; - else - { - gbMemory[address] = value; - return; - } - } - - - - if((address > 0xfea0) && (address < 0xff00)){ // GBC allows reading/writing to that area - gbMemory[address] = value; - return; - } - - switch(address & 0x00ff) { - - case 0x00: { - gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) | - (value & 0x30) | 0xc0); - if(gbSgbMode) { - gbSgbDoBitTransfer(value); - } - return; - } - - case 0x01: { - gbMemory[0xff01] = value; - return; - } - - // serial control - case 0x02: { - gbSerialOn = (value & 0x80); - gbMemory[0xff02] = value; - if(gbSerialOn) { - gbSerialTicks = GBSERIAL_CLOCK_TICKS; -#ifdef LINK_EMULATION - if(linkConnected) { - if(value & 1) { - linkSendByte(0x100|gbMemory[0xFF01]); - Sleep(5); - } - } -#endif - } - - gbSerialBits = 0; - return; - } - - case 0x04: { - // DIV register resets on any write - // (not totally perfect, but better than nothing) - gbMemory[0xff04] = register_DIV = 0; - gbDivTicks = GBDIV_CLOCK_TICKS; - // Another weird timer 'bug' : - // Writing to DIV register resets the internal timer, - // and can also increase TIMA/trigger an interrupt - // in some cases... - if (gbTimerOn && !(gbInternalTimer & (gbTimerClockTicks>>1))) - { - gbMemory[0xff05] = ++register_TIMA; - if(register_TIMA == 0) { - // timer overflow! - - // reload timer modulo - gbMemory[0xff05] = register_TIMA = register_TMA; - - // flag interrupt - gbMemory[0xff0f] = register_IF |= 4; - } - } - gbInternalTimer = 0xff; - return; - } - case 0x05: - gbMemory[0xff05] = register_TIMA = value; - return; - - case 0x06: - gbMemory[0xff06] = register_TMA = value; - return; - - // TIMER control - case 0x07: { - - gbTimerModeChange = (((value & 3) != (register_TAC&3)) && (value & register_TAC & 4)) ? true : false; - gbTimerOnChange = (((value ^ register_TAC) & 4) == 4) ? true : false; - - gbTimerOn = (value & 4) ? true : false; - - if (gbTimerOnChange || gbTimerModeChange) - { - gbTimerMode = value & 3; - - switch(gbTimerMode) { - case 0: - gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS; - break; - case 1: - gbTimerClockTicks = GBTIMER_MODE_1_CLOCK_TICKS; - break; - case 2: - gbTimerClockTicks = GBTIMER_MODE_2_CLOCK_TICKS; - break; - case 3: - gbTimerClockTicks = GBTIMER_MODE_3_CLOCK_TICKS; - break; - } - } - - - // This looks weird, but this emulates a bug in which register_TIMA - // is increased when writing to register_TAC - // (This fixes Korodice's long-delay between menus bug). - - if (gbTimerOnChange || gbTimerModeChange) - { - bool temp = false; - - if ((gbTimerOn && !gbTimerModeChange) && (gbTimerMode & 2) && - !(gbInternalTimer & 0x80) && (gbInternalTimer & (gbTimerClockTicks>>1)) && - !(gbInternalTimer & (gbTimerClockTicks>>5))) - temp = true; - else if ((!gbTimerOn && !gbTimerModeChange && gbTimerOnChange ) && ((gbTimerTicks-1) < (gbTimerClockTicks>>1))) - temp = true; - else if (gbTimerOn && gbTimerModeChange && !gbTimerOnChange) - { - switch(gbTimerMode & 3) - { - case 0x00: - temp = false; - break; - case 0x01: - if (((gbInternalTimer & 0x82) == 2) && (gbTimerTicks>(clockTicks+1))) - temp = true; - break; - case 0x02: - if (((gbInternalTimer & 0x88) == 0x8) && (gbTimerTicks>(clockTicks+1))) - temp = true; - break; - case 0x03: - if (((gbInternalTimer & 0xA0) == 0x20) && (gbTimerTicks>(clockTicks+1))) - temp = true; - break; - } - } - - if (temp) - { - gbMemory[0xff05] = ++register_TIMA; - if((register_TIMA & 0xff) == 0) { - // timer overflow! - - // reload timer modulo - gbMemory[0xff05] = register_TIMA = register_TMA; - - // flag interrupt - gbMemory[0xff0f] = register_IF |= 4; - } - } - } - gbMemory[0xff07] = register_TAC = value; - return; - } - - case 0x0f: { - gbMemory[0xff0f] = register_IF = value; - //gbMemory[0xff0f] = register_IE |= value; - return; - } - - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: { - if (gbMemory[NR52] & 0x80) { - SOUND_EVENT(address,value); - return; - } - } - - case 0x26: { - SOUND_EVENT(address,value); - return; - } - - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: { - SOUND_EVENT(address,value); - //gbMemory[address] = value; - return; - } - - case 0x40: { - int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80); - - // don't draw the window if it was not enabled and not being drawn before - if(!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 && - register_LY > register_WY) - gbWindowLine = 146; - // 007 fix : don't draw the first window's 1st line if it's enable 'too late' - // (ie. if register_LY == register_WY when enabling it) - // and move it to the next line - else if (!(register_LCDC & 0x20) && (value & 0x20) && (register_LY == register_WY)) - gbWindowLine = -2; - - - gbMemory[0xff40] = register_LCDC = value; - - - if(lcdChange) { - if((value & 0x80) && (!register_LCDCBusy)) { - - // if (!gbWhiteScreen && !gbSgbMask) - - // systemDrawScreen(); - - - - gbRegisterLYLCDCOffOn = (register_LY + 144) % 154; - - gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 2 : 1); - gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 1 : 0); - gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 2 : 1); - gbLcdLYIncrementTicksDelayed = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 1 : 0); - gbLcdMode = 2; - gbLcdModeDelayed = 2; - gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | 2; - gbMemory[0xff44] = register_LY = 0x00; - gbInt48Signal = 0; - gbLYChangeHappened = false; - gbLCDChangeHappened = false; - gbWindowLine = 146; - oldRegister_WY = 146; - - // Fix for Namco Gallery Vol.2 - // (along with updating register_LCDC at the start of 'case 0x40') : - if(register_STAT & 0x20) - { - // send LCD interrupt only if no interrupt 48h signal... - if (!gbInt48Signal) - { - gbMemory[0xff0f] = register_IF |= 2; - } - gbInt48Signal |= 4; - } - gbCompareLYToLYC(); - - } else { - - register_LCDCBusy = clockTicks+6; - - //used to update the screen with white lines when it's off. - //(it looks strange, but it's pretty accurate) - - gbWhiteScreen = 0; - - gbScreenTicks = ((150-register_LY)*GBLY_INCREMENT_CLOCK_TICKS + - (49<<(gbSpeed ? 1 : 0))); - - // disable the screen rendering - gbScreenOn = false; - gbLcdTicks = 0; - gbLcdMode = 0; - gbLcdModeDelayed = 0; - gbMemory[0xff41] = register_STAT &= 0xfc; - gbInt48Signal = 0; - } - } - return; - } - - // STAT - case 0x41: { - //register_STAT = (register_STAT & 0x87) | - // (value & 0x7c); - gbMemory[0xff41] = register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ? - // GB bug from Devrs FAQ - // Corrected : it happens if Lcd Mode<2, but also if LY == LYC whatever - // Lcd Mode is, and if !gbInt48Signal in all cases. The screen being off - // doesn't matter (the bug will still happen). - // That fixes 'Satoru Nakajima - F-1 Hero' crash bug. - - if((gbHardware & 5) && (((!gbInt48Signal) && (gbLcdMode<2) && (register_LCDC & 0x80)) || - (register_LY == register_LYC))) - { - gbMemory[0xff0f] = register_IF |=2; - } - - gbInt48Signal &= ((register_STAT>>3) & 0xF); - - if((register_LCDC & 0x80)) { - if ((register_STAT & 0x08) && (gbLcdMode == 0)) - { - if (!gbInt48Signal) - { - gbMemory[0xff0f] = register_IF |=2; - } - gbInt48Signal |= 1; - } - if ((register_STAT & 0x10) && (gbLcdMode == 1)) - { - if (!gbInt48Signal) - { - gbMemory[0xff0f] = register_IF |=2; - } - gbInt48Signal |= 2; - } - if ((register_STAT & 0x20) && (gbLcdMode == 2)) - { - if (!gbInt48Signal) - { - gbMemory[0xff0f] = register_IF |=2; - } - gbInt48Signal |= 4; - } - gbCompareLYToLYC(); - - gbMemory[0xff0f] = register_IF; - gbMemory[0xff41] = register_STAT; - - } - return; - } - - // SCY - case 0x42: { - int temp = -1; - - if ((gbLcdMode == 3) || (gbLcdModeDelayed == 3)) - temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - - gbLcdLYIncrementTicks); - - if (temp >=0) - { - for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) - if (temp < 300) - gbSCYLine[i] = value; - } - - else - memset(gbSCYLine, value, sizeof(gbSCYLine)); - - gbMemory[0xff42] = register_SCY = value; - return; - } - - // SCX - case 0x43: { - int temp = -1; - - if (gbLcdModeDelayed == 3) - temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - - gbLcdLYIncrementTicksDelayed); - - if (temp >=0) - { - for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) - if (temp < 300) - gbSCXLine[i] = value; - } - - else - memset(gbSCXLine, value, sizeof(gbSCXLine)); - - gbMemory[0xff43] = register_SCX = value; - return; - } - - // LY - case 0x44: { - // read only - return; - } - - // LYC - case 0x45: { - if (register_LYC != value) - { - gbMemory[0xff45] = register_LYC = value; - if(register_LCDC & 0x80) { - gbCompareLYToLYC(); - } - } - return; - } - - // DMA! - case 0x46: { - int source = value * 0x0100; - - gbCopyMemory(0xfe00, - source, - 0xa0); - gbMemory[0xff46] = register_DMA = value; - return; - } - - // BGP - case 0x47: { - - int temp = -1; - - gbMemory[0xff47] = value; - - if (gbLcdModeDelayed == 3) - temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - - gbLcdLYIncrementTicksDelayed); - - if (temp >=0) - { - for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) - if (temp < 300) - gbBgpLine[i] = value; - } - else - memset(gbBgpLine,value,sizeof(gbBgpLine)); - - gbBgp[0] = value & 0x03; - gbBgp[1] = (value & 0x0c)>>2; - gbBgp[2] = (value & 0x30)>>4; - gbBgp[3] = (value & 0xc0)>>6; - break; - } - - // OBP0 - case 0x48: { - int temp = -1; - - gbMemory[0xff48] = value; - - if (gbLcdModeDelayed == 3) - temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - - gbLcdLYIncrementTicksDelayed); - - if (temp >=0) - { - for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) - if (temp < 300) - gbObp0Line[i] = value; - } - else - memset(gbObp0Line,value,sizeof(gbObp0Line)); - - gbObp0[0] = value & 0x03; - gbObp0[1] = (value & 0x0c)>>2; - gbObp0[2] = (value & 0x30)>>4; - gbObp0[3] = (value & 0xc0)>>6; - break; - } - - // OBP1 - case 0x49: { - int temp = -1; - - gbMemory[0xff49] = value; - - if (gbLcdModeDelayed == 3) - temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - - gbLcdLYIncrementTicksDelayed); - - if (temp >=0) - { - for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) - if (temp < 300) - gbObp1Line[i] = value; - } - else - memset(gbObp1Line,value,sizeof(gbObp1Line)); - - gbObp1[0] = value & 0x03; - gbObp1[1] = (value & 0x0c)>>2; - gbObp1[2] = (value & 0x30)>>4; - gbObp1[3] = (value & 0xc0)>>6; - break; - } - - // WY - case 0x4a: - gbMemory[0xff4a] = register_WY = value; - if ((register_LY <= register_WY) && ((gbWindowLine < 0) || (gbWindowLine>=144))) - { - gbWindowLine = -1; - oldRegister_WY = register_WY; - } - return; - - // WX - case 0x4b: - gbMemory[0xff4b] = register_WX = value; - return; - - // KEY1 - case 0x4d: { - if(gbCgbMode) { - gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1) | 0x7e; - return; - } - } - break; - - // VBK - case 0x4f: { - if(gbCgbMode) { - value = value & 1; - if(value == gbVramBank) - return; - - int vramAddress = value * 0x2000; - gbMemoryMap[0x08] = &gbVram[vramAddress]; - gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000]; - - gbVramBank = value; - register_VBK = value; - } - return; - } - break; - - // BOOTROM disable register (also gbCgbMode enabler if value & 0x10 ?) - case 0x50 : - { - if (useBios && inBios && !skipBios && (value & 1)) - { - gbMemoryMap[0x00] = &gbRom[0x0000]; - memcpy ((u8 *)(gbRom+0x100), (u8 *)(gbMemory + 0x100), 0xF00); - inBios = false; - } - } - - // HDMA1 - case 0x51: { - if(gbCgbMode) { - if(value > 0x7f && value < 0xa0) - value = 0; - - gbHdmaSource = (value << 8) | (gbHdmaSource & 0xf0); - - register_HDMA1 = value; - return; - } - } - break; - - // HDMA2 - case 0x52: { - if(gbCgbMode) { - value = value & 0xf0; - - gbHdmaSource = (gbHdmaSource & 0xff00) | (value); - - register_HDMA2 = value; - return; - } - } - break; - - // HDMA3 - case 0x53: { - if(gbCgbMode) { - value = value & 0x1f; - gbHdmaDestination = (value << 8) | (gbHdmaDestination & 0xf0); - gbHdmaDestination |= 0x8000; - register_HDMA3 = value; - return; - } - } - break; - - // HDMA4 - case 0x54: { - if(gbCgbMode) { - value = value & 0xf0; - gbHdmaDestination = (gbHdmaDestination & 0x1f00) | value; - gbHdmaDestination |= 0x8000; - register_HDMA4 = value; - return; - } - } - break; - - // HDMA5 - case 0x55: { - - if(gbCgbMode) { - gbHdmaBytes = 16 + (value & 0x7f) * 16; - if(gbHdmaOn) { - if(value & 0x80) { - gbMemory[0xff55] = register_HDMA5 = (value & 0x7f); - } else { - register_HDMA5 = 0xff; - gbHdmaOn = 0; - } - } else { - if(value & 0x80) { - gbHdmaOn = 1; - gbMemory[0xff55] = register_HDMA5 = value & 0x7f; - if(gbLcdModeDelayed == 0) - gbDoHdma(); - } else { - // we need to take the time it takes to complete the transfer into - // account... according to GB DEV FAQs, the setup time is the same - // for single and double speed, but the actual transfer takes the - // same time - if(gbSpeed) - gbDmaTicks = 2+16 * ((value & 0x7f) +1); - else - gbDmaTicks = 1+8 * ((value & 0x7f)+1); - - gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000, - gbHdmaSource & 0xfff0, - gbHdmaBytes); - gbHdmaDestination += gbHdmaBytes; - gbHdmaSource += gbHdmaBytes; - - gbMemory[0xff51] = register_HDMA1 = 0xff;// = (gbHdmaSource >> 8) & 0xff; - gbMemory[0xff52] = register_HDMA2 = 0xff;// = gbHdmaSource & 0xf0; - gbMemory[0xff53] = register_HDMA3 = 0xff;// = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f; - gbMemory[0xff54] = register_HDMA4 = 0xff;// = gbHdmaDestination & 0xf0; - gbMemory[0xff55] = register_HDMA5 = 0xff; - } - } - return; - } - } - break; - - // BCPS - case 0x68: { - if(gbCgbMode) { - int paletteIndex = (value & 0x3f) >> 1; - int paletteHiLo = (value & 0x01); - - gbMemory[0xff68] = value; - - gbMemory[0xff69] = (paletteHiLo ? - (gbPalette[paletteIndex] >> 8) : - (gbPalette[paletteIndex] & 0x00ff)); - return; - } - } - break; - - // BCPD - case 0x69: { - if(gbCgbMode) { - int v = gbMemory[0xff68]; - int paletteIndex = (v & 0x3f) >> 1; - int paletteHiLo = (v & 0x01); - - // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) - { - gbMemory[0xff69] = value; - gbPalette[paletteIndex] = (paletteHiLo ? - ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : - ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; - } - - - if(gbMemory[0xff68] & 0x80) { - int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f; - - gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index; - gbMemory[0xff69] = (index & 1 ? - (gbPalette[index>>1] >> 8) : - (gbPalette[index>>1] & 0x00ff)); - } - return; - } - } - break; - - // OCPS - case 0x6a: { - if(gbCgbMode) { - int paletteIndex = (value & 0x3f) >> 1; - int paletteHiLo = (value & 0x01); - - paletteIndex += 32; - - gbMemory[0xff6a] = value; - - gbMemory[0xff6b] = (paletteHiLo ? - (gbPalette[paletteIndex] >> 8) : - (gbPalette[paletteIndex] & 0x00ff)); - return; - } - } - break; - - // OCPD - case 0x6b: { - - if(gbCgbMode) { - int v = gbMemory[0xff6a]; - int paletteIndex = (v & 0x3f) >> 1; - int paletteHiLo = (v & 0x01); - - paletteIndex += 32; - - // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) - { - gbMemory[0xff6b] = value; - gbPalette[paletteIndex] = (paletteHiLo ? - ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : - ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; - } - - if(gbMemory[0xff6a] & 0x80) { - int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f; - - gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index; - - gbMemory[0xff6b] = (index & 1 ? - (gbPalette[(index>>1) + 32] >> 8) : - (gbPalette[(index>>1) + 32] & 0x00ff)); - } - return; - } - } - break; - - case 0x6c: { - gbMemory[0xff6c] = 0xfe | value; - return; - } - - - // SVBK - case 0x70: { - if(gbCgbMode) { - value = value & 7; - - int bank = value; - if(value == 0) - bank = 1; - - if(bank == gbWramBank) - return; - - int wramAddress = bank * 0x1000; - gbMemoryMap[0x0d] = &gbWram[wramAddress]; - - gbWramBank = bank; - gbMemory[0xff70] = register_SVBK = value; - return; - } - } - - case 0x75:{ - gbMemory[0xff75] = 0x8f | value; - return; - } - - case 0xff: { - gbMemory[0xffff] = register_IE = value; - return; - } - } - - if(address < 0xff80) - { - gbMemory[address] = value; - return; - } - - gbMemory[address] = value; -} - -u8 gbReadOpcode(register u16 address) -{ - if(gbCheatMap[address]) - return gbCheatRead(address); - - if(address < 0x8000) - return gbMemoryMap[address>>12][address&0x0fff]; - - if(address < 0xa000) - { - // A lot of 'ugly' checks... But only way to emulate this particular behaviour... - if (((gbHardware & 0xa) && ((gbLcdModeDelayed !=3) || ((register_LY == 0) && - (gbScreenOn==false) && (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) || - ((gbHardware & 0x5) && (gbLcdModeDelayed !=3) && - ((gbLcdMode !=3) || ((register_LY == 0) && ((gbScreenOn==false) && - (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicks ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))))) - return gbMemoryMap[address>>12][address&0x0fff]; - return 0xff; - } - - // Used for the mirroring of 0xC000 in 0xE000 - if ((address >= 0xe000) && (address < 0xfe00)) - address &= ~0x2000; - - switch(address & 0xf000) { - case 0x0a: - case 0x0b: - if(mapperReadRAM) - return mapperReadRAM(address); - break; - case 0x0f: - if(address > 0xff00) { - switch(address & 0x00ff) { - case 0x02: - return (gbMemory[0xff02]); - case 0x03: - return (0xff); - case 0x04: - return register_DIV; - case 0x05: - return register_TIMA; - case 0x06: - return register_TMA; - case 0x07: - return (0xf8 | register_TAC); - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - return (0xff); - case 0x0f: - return (0xe0 | gbMemory[0xff0f]); - case 0x40: - return register_LCDC; - case 0x41: - // This is a GB/C only bug (ie. not GBA/SP). - if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed)) - return (0x80 | gbMemory[0xff41] & 0xFC); - else - return (0x80 | gbMemory[0xff41]); - case 0x42: - return register_SCY; - case 0x43: - return register_SCX; - case 0x44: - if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) || - (!(register_LCDC && 0x80))) - return 0; - else - return register_LY; - case 0x45: - return register_LYC; - case 0x46: - return register_DMA; - case 0x4a: - return register_WY; - case 0x4b: - return register_WX; - case 0x4c: - return 0xff; - case 0x4f: - return (0xfe | register_VBK); - case 0x51: - return register_HDMA1; - case 0x52: - return register_HDMA2; - case 0x53: - return register_HDMA3; - case 0x54: - return register_HDMA4; - case 0x55: - return register_HDMA5; - case 0x68: - case 0x6a: - if (gbCgbMode) - return (0x40 | gbMemory[address]); - else - return 0xc0; - case 0x69: - case 0x6b: - if (gbCgbMode) - { - // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) - return (gbMemory[address]); - else - return 0xff; - } - else - return 0xff; - case 0x70: - if (gbCgbMode) - return (0xf8 | register_SVBK); - else - return 0xff; - case 0xff: - return register_IE; - } - } - // OAM not accessible during mode 2 & 3. - if(((address >= 0xfe00) && (address<0xfea0)) && - ((gbLcdMode | gbLcdModeDelayed) &2)) - return 0xff; - break; - } - - if ((address >= 0xfea0) && (address < 0xff00)) - { - if (gbHardware & 1) - return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff ); - else if (gbHardware & 2) - return gbMemoryMap[address>>12][address & 0x0fff]; - else if (gbHardware & 4) - return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 ); - else if (gbHardware & 8) - return ((address & 0xf0) |((address & 0xf0)>>4)); - } - - return gbMemoryMap[address>>12][address & 0x0fff]; -} - -u8 gbReadMemory(register u16 address) -{ - if(gbCheatMap[address]) - return gbCheatRead(address); - - - if(address < 0x8000) - return gbMemoryMap[address>>12][address&0x0fff]; - - if(address < 0xa000) - { - // A lot of 'ugly' checks... But only way to emulate this particular behaviour... - if (((gbHardware & 0xa) && ((gbLcdModeDelayed !=3) || ((register_LY == 0) && - (gbScreenOn==false) && (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) || - ((gbHardware & 0x5) && (gbLcdModeDelayed !=3) && - ((gbLcdMode !=3) || ((register_LY == 0) && ((gbScreenOn==false) && - (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicks ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))))) - return gbMemoryMap[address>>12][address&0x0fff]; - return 0xff; - } - - if ((address >= 0xe000) && (address < 0xfe00)) - address &= ~0x2000; - - if(address < 0xc000) { -#ifndef FINAL_VERSION - if(memorydebug) { - log("Memory register read %04x PC=%04x\n", - address, - PC.W); - } -#endif - - // for the 2kb ram limit (fixes crash in shawu's story - // but now its sram test fails, as the it expects 8kb and not 2kb... - // So use the 'genericflashcard' option to fix it). - if (address<=(0xa000+gbRamSizeMask)) - { - if(mapperReadRAM) - return mapperReadRAM(address); - return gbMemoryMap[address>>12][address & 0x0fff]; - } - return 0xff; - } - - if(address >= 0xff00) { - if ( address >= 0xFF10 && address <= 0xFF3F ) - return gbSoundRead( address ); - - switch(address & 0x00ff) { - case 0x00: - { - if(gbSgbMode) { - gbSgbReadingController |= 4; - gbSgbResetPacketState(); - } - - int b = gbMemory[0xff00]; - - if((b & 0x30) == 0x20) { - b &= 0xf0; - - int joy = 0; - if(gbSgbMode && gbSgbMultiplayer) { - switch(gbSgbNextController) { - case 0x0f: - joy = 0; - break; - case 0x0e: - joy = 1; - break; - case 0x0d: - joy = 2; - break; - case 0x0c: - joy = 3; - break; - default: - joy = 0; - } - } - int joystate = gbJoymask[joy]; - if(!(joystate & 128)) - b |= 0x08; - if(!(joystate & 64)) - b |= 0x04; - if(!(joystate & 32)) - b |= 0x02; - if(!(joystate & 16)) - b |= 0x01; - - gbMemory[0xff00] = b; - } else if((b & 0x30) == 0x10) { - b &= 0xf0; - - int joy = 0; - if(gbSgbMode && gbSgbMultiplayer) { - switch(gbSgbNextController) { - case 0x0f: - joy = 0; - break; - case 0x0e: - joy = 1; - break; - case 0x0d: - joy = 2; - break; - case 0x0c: - joy = 3; - break; - default: - joy = 0; - } - } - int joystate = gbJoymask[joy]; - if(!(joystate & 8)) - b |= 0x08; - if(!(joystate & 4)) - b |= 0x04; - if(!(joystate & 2)) - b |= 0x02; - if(!(joystate & 1)) - b |= 0x01; - - gbMemory[0xff00] = b; - } else { - if(gbSgbMode && gbSgbMultiplayer) { - gbMemory[0xff00] = 0xf0 | gbSgbNextController; - } else { - gbMemory[0xff00] = 0xff; - } - } - } - return gbMemory[0xff00]; - break; - case 0x01: - return gbMemory[0xff01]; - case 0x02: - return (gbMemory[0xff02]); - case 0x04: - return register_DIV; - case 0x05: - return register_TIMA; - case 0x06: - return register_TMA; - case 0x07: - return (0xf8 | register_TAC); - case 0x0f: - return (0xe0 | gbMemory[0xff0f]); - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - if ((gbMemory[NR30] & 0x80) && (gbMemory[NR34] & 0x80)) - return 0xFF; - else - return gbMemoryMap[address>>12][address & 0x0fff]; - case 0x40: - return register_LCDC; - case 0x41: - // This is a GB/C only bug (ie. not GBA/SP). - if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed)) - return (0x80 | gbMemory[0xff41] & 0xFC); - else - return (0x80 | gbMemory[0xff41]); - case 0x42: - return register_SCY; - case 0x43: - return register_SCX; - case 0x44: - if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) || - (!(register_LCDC && 0x80))) - return (0); - else - return register_LY; - case 0x45: - return register_LYC; - case 0x46: - return register_DMA; - case 0x4a: - return register_WY; - case 0x4b: - return register_WX; - case 0x4f: - return (0xfe | register_VBK); - case 0x51: - return register_HDMA1; - case 0x52: - return register_HDMA2; - case 0x53: - return register_HDMA3; - case 0x54: - return register_HDMA4; - case 0x55: - return register_HDMA5; - case 0x68: - case 0x6a: - if (gbCgbMode) - return (0x40 | gbMemory[address]); - else - return 0xc0; - case 0x69: - case 0x6b: - if (gbCgbMode) - { - // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) - return (gbMemory[address]); - else - return 0xff; - } - else - return 0xff; - case 0x70: - if (gbCgbMode) - return (0xf8 | register_SVBK); - else - return 0xff; - case 0xff: - return register_IE; - } - } - // OAM not accessible during mode 2 & 3. - if(((address >= 0xfe00) && (address<0xfea0)) && - (((gbLcdMode | gbLcdModeDelayed) &2) && - (!(gbSpeed && (gbHardware & 0x2) && !(gbLcdModeDelayed & 2) && (gbLcdMode == 2))) || - (gbSpeed && (gbHardware & 0x2) && (gbLcdModeDelayed == 0) && (gbLcdTicksDelayed == (GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]))))) - return 0xff; - - if ((address >= 0xfea0) && (address < 0xff00)) - { - if (gbHardware & 1) - return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff ); - else if (gbHardware & 2) - return gbMemoryMap[address>>12][address & 0x0fff]; - else if (gbHardware & 4) - return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 ); - else if (gbHardware & 8) - return ((address & 0xf0) |((address & 0xf0)>>4)); - } - - return gbMemoryMap[address>>12][address & 0x0fff]; -} - -void gbVblank_interrupt() -{ - gbCheatWrite(false); // Emulates GS codes. - gbMemory[0xff0f] = register_IF &= 0xfe; - gbWriteMemory(--SP.W, PC.B.B1); - gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x40; -} - -void gbLcd_interrupt() -{ - gbMemory[0xff0f] = register_IF &= 0xfd; - gbWriteMemory(--SP.W, PC.B.B1); - gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x48; -} - -void gbTimer_interrupt() -{ - gbMemory[0xff0f] = register_IF &= 0xfb; - gbWriteMemory(--SP.W, PC.B.B1); - gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x50; -} - -void gbSerial_interrupt() -{ - gbMemory[0xff0f] = register_IF &= 0xf7; - gbWriteMemory(--SP.W, PC.B.B1); - gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x58; -} - -void gbJoypad_interrupt() -{ - gbMemory[0xff0f] = register_IF &= 0xef; - gbWriteMemory(--SP.W, PC.B.B1); - gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x60; -} - -void gbSpeedSwitch() -{ - gbBlackScreen = true; - if(gbSpeed == 0) { - gbSpeed = 1; - GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; - GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2; - GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; - GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; - GBLY_INCREMENT_CLOCK_TICKS = 114 * 2; - GBDIV_CLOCK_TICKS = 64; - GBTIMER_MODE_0_CLOCK_TICKS = 256; - GBTIMER_MODE_1_CLOCK_TICKS = 4; - GBTIMER_MODE_2_CLOCK_TICKS = 16; - GBTIMER_MODE_3_CLOCK_TICKS = 64; - GBSERIAL_CLOCK_TICKS = 128 * 2; - gbLcdTicks *= 2; - gbLcdTicksDelayed *=2; - gbLcdTicksDelayed--; - gbLcdLYIncrementTicks *= 2; - gbLcdLYIncrementTicksDelayed *= 2; - gbLcdLYIncrementTicksDelayed--; - gbSerialTicks *= 2; - //SOUND_CLOCK_TICKS = soundQuality * 24 * 2; - //soundTicks *= 2; - gbLine99Ticks = 3; - } else { - gbSpeed = 0; - GBLCD_MODE_0_CLOCK_TICKS = 51; - GBLCD_MODE_1_CLOCK_TICKS = 1140; - GBLCD_MODE_2_CLOCK_TICKS = 20; - GBLCD_MODE_3_CLOCK_TICKS = 43; - GBLY_INCREMENT_CLOCK_TICKS = 114; - GBDIV_CLOCK_TICKS = 64; - GBTIMER_MODE_0_CLOCK_TICKS = 256; - GBTIMER_MODE_1_CLOCK_TICKS = 4; - GBTIMER_MODE_2_CLOCK_TICKS = 16; - GBTIMER_MODE_3_CLOCK_TICKS = 64; - GBSERIAL_CLOCK_TICKS = 128; - gbLcdTicks >>= 1; - gbLcdTicksDelayed++; - gbLcdTicksDelayed >>=1; - gbLcdLYIncrementTicks >>= 1; - gbLcdLYIncrementTicksDelayed++; - gbLcdLYIncrementTicksDelayed >>= 1; - gbSerialTicks /= 2; - //SOUND_CLOCK_TICKS = soundQuality * 24; - //soundTicks /= 2; - gbLine99Ticks = 1; - if (gbHardware & 8) - gbLine99Ticks++; - } - gbDmaTicks += (134)*GBLY_INCREMENT_CLOCK_TICKS + (37<<(gbSpeed ? 1 : 0)); -} - -bool CPUIsGBBios(const char * file) -{ - if(strlen(file) > 4) { - const char * p = strrchr(file,'.'); - - if(p != NULL) { - if(_stricmp(p, ".gb") == 0) - return true; - if(_stricmp(p, ".bin") == 0) - return true; - if(_stricmp(p, ".bios") == 0) - return true; - if(_stricmp(p, ".rom") == 0) - return true; - } - } - - return false; -} - -void gbCPUInit(const char *biosFileName, bool useBiosFile) -{ - useBios = false; - if (useBiosFile) - { - int size = 0x100; - if(utilLoad(biosFileName, - CPUIsGBBios, - bios, - size)) { - if(size == 0x100) - useBios = true; - else - systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file size")); - } - } -} - -void gbGetHardwareType() -{ - gbCgbMode = 0; - gbSgbMode = 0; - if(gbRom[0x143] & 0x80) { - if((gbEmulatorType == 0) || - gbEmulatorType == 1 || - gbEmulatorType == 4) { - gbCgbMode = 1; - } - } - - if((gbCgbMode == 0 ) && (gbRom[0x146] == 0x03)) { - if(gbEmulatorType == 0 || - gbEmulatorType == 2 || - gbEmulatorType == 5) - gbSgbMode = 1; - } - - gbHardware = 1; // GB - if (((gbCgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 1)) - gbHardware = 2; // GBC - else if (((gbSgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 2) || (gbEmulatorType == 5)) - gbHardware = 4; // SGB(2) - else if (gbEmulatorType == 4) - gbHardware = 8; // GBA - - gbGBCColorType = 0; - if (gbHardware & 8) // If GBA is selected, choose the GBA default settings. - gbGBCColorType = 2; // (0 = GBC, 1 = GBA, 2 = GBASP) -} - -void gbReset() -{ - gbGetHardwareType(); - - oldRegister_WY = 146; - gbInterruptLaunched = 0; - - if(gbCgbMode == 1) { - if (gbVram == NULL) - gbVram = (u8 *)malloc(0x4000); - if (gbWram == NULL) - gbWram = (u8 *)malloc(0x8000); - memset(gbVram,0,0x4000); - memset(gbPalette,0, 2*128); - } - else - { - if(gbVram != NULL) { - free(gbVram); - gbVram = NULL; - } - if(gbWram != NULL) { - free(gbWram); - gbWram = NULL; - } - } - - gbLYChangeHappened = false; - gbLCDChangeHappened = false; - gbBlackScreen = false; - gbInterruptWait = 0; - gbDmaTicks = 0; - clockTicks = 0; - - if(gbSpeed) { - gbSpeedSwitch(); - gbMemory[0xff4d] = 0; - } - - // clean Wram - // This kinda emulates the startup state of Wram on GB/C (not very accurate, - // but way closer to the reality than filling it with 00es or FFes). - // On GBA/GBASP, it's kinda filled with random data. - // In all cases, most of the 2nd bank is filled with 00s. - // The starting data are important for some 'buggy' games, like Buster Brothers or - // Karamuchou ha Oosawagi!. - if (gbMemory != NULL) - { - memset(gbMemory,0xff, 65536); - for (int temp = 0xC000; temp < 0xE000; temp++) - if ((temp & 0x8) ^((temp & 0x800)>>8)) - { - if ((gbHardware & 0x02) && (gbGBCColorType == 0)) - gbMemory[temp] = 0x0; - else - gbMemory[temp] = 0x0f; - } - - else - gbMemory[temp] = 0xff; - } - - - - // clean LineBuffer - if (gbLineBuffer != NULL) - memset(gbLineBuffer, 0, sizeof(gbLineBuffer)); - // clean Pix - if (pix != NULL) - memset(pix, 0, sizeof(pix)); - // clean Vram - if (gbVram != NULL) - memset(gbVram, 0, 0x4000); - // clean Wram 2 - // This kinda emulates the startup state of Wram on GBC (not very accurate, - // but way closer to the reality than filling it with 00es or FFes). - // On GBA/GBASP, it's kinda filled with random data. - // In all cases, most of the 2nd bank is filled with 00s. - // The starting data are important for some 'buggy' games, like Buster Brothers or - // Karamuchou ha Oosawagi! - if (gbWram != NULL) - { - for (int i = 0; i<8; i++) - if (i != 2) - memcpy ((u16 *)(gbWram+i*0x1000), (u16 *)(gbMemory+0xC000), 0x1000); - } - - memset(gbSCYLine,0,sizeof(gbSCYLine)); - memset(gbSCXLine,0,sizeof(gbSCXLine)); - memset(gbBgpLine,0xfc,sizeof(gbBgpLine)); - if (gbHardware & 5) - { - memset(gbObp0Line,0xff,sizeof(gbObp0Line)); - memset(gbObp1Line,0xff,sizeof(gbObp1Line)); - } - else - { - memset(gbObp0Line,0x0,sizeof(gbObp0Line)); - memset(gbObp1Line,0x0,sizeof(gbObp1Line)); - } - memset(gbSpritesTicks,0x0,sizeof(gbSpritesTicks)); - - SP.W = 0xfffe; - AF.W = 0x01b0; - BC.W = 0x0013; - DE.W = 0x00d8; - HL.W = 0x014d; - PC.W = 0x0100; - IFF = 0; - gbInt48Signal = 0; - - register_TIMA = 0; - register_TMA = 0; - register_TAC = 0; - gbMemory[0xff0f] = register_IF = 1; - gbMemory[0xff40] = register_LCDC = 0x91; - gbMemory[0xff47] = 0xfc; - - if (gbCgbMode) - gbMemory[0xff4d] = 0x7e; - else - gbMemory[0xff4d] = 0xff; - - if (!gbCgbMode) - gbMemory[0xff70] = gbMemory[0xff74] = 0xff; - - if (gbCgbMode) - gbMemory[0xff56] = 0x3e; - else - gbMemory[0xff56] = 0xff; - - register_SCY = 0; - register_SCX = 0; - register_LYC = 0; - register_DMA = 0xff; - register_WY = 0; - register_WX = 0; - register_VBK = 0; - register_HDMA1 = 0xff; - register_HDMA2 = 0xff; - register_HDMA3 = 0xff; - register_HDMA4 = 0xff; - register_HDMA5 = 0xff; - register_SVBK = 0; - register_IE = 0; - - if (gbCgbMode) - gbMemory[0xff02] = 0x7c; - else - gbMemory[0xff02] = 0x7e; - - gbMemory[0xff03] = 0xff; - int i; - for (i = 0x8; i<0xf; i++) - gbMemory[0xff00+i] = 0xff; - - gbMemory[0xff13] = 0xff; - gbMemory[0xff15] = 0xff; - gbMemory[0xff18] = 0xff; - gbMemory[0xff1d] = 0xff; - gbMemory[0xff1f] = 0xff; - - for (i = 0x27; i<0x30; i++) - gbMemory[0xff00+i] = 0xff; - - gbMemory[0xff4c] = 0xff; - gbMemory[0xff4e] = 0xff; - gbMemory[0xff50] = 0xff; - - for (i = 0x57; i<0x68; i++) - gbMemory[0xff00+i] = 0xff; - - for (i = 0x5d; i<0x70; i++) - gbMemory[0xff00+i] = 0xff; - - gbMemory[0xff71] = 0xff; - - for (i = 0x78; i<0x80; i++) - gbMemory[0xff00+i] = 0xff; - - if (gbHardware & 0xa) - { - - if (gbHardware & 2) - { - AF.W = 0x1180; - BC.W = 0x0000; - } - else - { - AF.W = 0x1100; - BC.W = 0x0100; // GBA/SP have B = 0x01 (which means GBC & GBA/SP bootrom are different !) - } - - gbMemory[0xff26] = 0xf1; - if (gbCgbMode) - { - - gbMemory[0xff31] = 0xff; - gbMemory[0xff33] = 0xff; - gbMemory[0xff35] = 0xff; - gbMemory[0xff37] = 0xff; - gbMemory[0xff39] = 0xff; - gbMemory[0xff3b] = 0xff; - gbMemory[0xff3d] = 0xff; - - gbMemory[0xff44] = register_LY = 0x90; - gbDivTicks = 0x19 + ((gbHardware & 2) >> 1); - gbInternalTimer = 0x58 + ((gbHardware & 2) >> 1); - gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS - - (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 72 + ((gbHardware & 2) >> 1); - gbLcdLYIncrementTicks = 72 + ((gbHardware & 2) >> 1); - gbMemory[0xff04] = register_DIV = 0x1E; - } - else - { - gbMemory[0xff44] = register_LY = 0x94; - gbDivTicks = 0x22 + ((gbHardware & 2) >> 1); - gbInternalTimer = 0x61 + ((gbHardware & 2) >> 1); - gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS - - (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 25 + ((gbHardware & 2) >> 1); - gbLcdLYIncrementTicks = 25 + ((gbHardware & 2) >> 1); - gbMemory[0xff04] = register_DIV = 0x26; - } - - - DE.W = 0xff56; - HL.W = 0x000d; - - register_HDMA5 = 0xff; - gbMemory[0xff68] = 0xc0; - gbMemory[0xff6a] = 0xc0; - - - gbMemory[0xff41] = register_STAT = 0x81; - gbLcdMode = 1; - } - else - { - if (gbHardware & 4) - { - if(gbEmulatorType == 5) - AF.W = 0xffb0; - else - AF.W = 0x01b0; - BC.W = 0x0013; - DE.W = 0x00d8; - HL.W = 0x014d; - } - gbDivTicks = 14; - gbInternalTimer = gbDivTicks--; - gbMemory[0xff04] = register_DIV = 0xAB; - gbMemory[0xff41] = register_STAT = 0x85; - gbMemory[0xff44] = register_LY = 0x00; - gbLcdTicks = 15; - gbLcdLYIncrementTicks = 114+gbLcdTicks; - gbLcdMode = 1; - - // used for the handling of the gb Boot Rom - if ((gbHardware & 5) && (bios != NULL) && useBios && !skipBios) - { - memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000); - memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100); - gbWhiteScreen = 0; - - gbInternalTimer = 0x3e; - gbDivTicks = 0x3f; - gbMemory[0xff04] = register_DIV = 0x00; - PC.W = 0x0000; - register_LCDC = 0x11; - gbScreenOn = false; - gbLcdTicks = 0; - gbLcdMode = 0; - gbLcdModeDelayed = 0; - gbMemory[0xff41] = register_STAT &= 0xfc; - gbInt48Signal = 0; - gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS; - } - } - - gbLine99Ticks = 1; - if (gbHardware & 8) - gbLine99Ticks++; - - gbLcdModeDelayed = gbLcdMode; - gbLcdTicksDelayed = gbLcdTicks+1; - gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks+1; - - - gbTimerModeChange = false; - gbTimerOnChange = false; - gbTimerOn = false; - - if(gbCgbMode) { - for (int i = 0; i<0x20; i++) - gbPalette[i] = 0x7fff; - - // This is just to show that the starting values of the OBJ palettes are different - // between the 3 consoles, and that they 'kinda' stay the same at each reset - // (they can slightly change, somehow (randomly?)). - // You can check the effects of gbGBCColorType on the "Vila Caldan Color" gbc demo. - // Note that you could also check the Div register to check on which system the game - // is running (GB,GBC and GBA(SP) have different startup values). - // Unfortunatly, I don't have any SGB system, so I can't get their starting values. - - if (gbGBCColorType == 0) // GBC Hardware - { - gbPalette[0x20] = 0x0600; - gbPalette[0x21] = 0xfdf3; - gbPalette[0x22] = 0x041c; - gbPalette[0x23] = 0xf5db; - gbPalette[0x24] = 0x4419; - gbPalette[0x25] = 0x57ea; - gbPalette[0x26] = 0x2808; - gbPalette[0x27] = 0x9b75; - gbPalette[0x28] = 0x129b; - gbPalette[0x29] = 0xfce0; - gbPalette[0x2a] = 0x22da; - gbPalette[0x2b] = 0x4ac5; - gbPalette[0x2c] = 0x2d71; - gbPalette[0x2d] = 0xf0c2; - gbPalette[0x2e] = 0x5137; - gbPalette[0x2f] = 0x2d41; - gbPalette[0x30] = 0x6b2d; - gbPalette[0x31] = 0x2215; - gbPalette[0x32] = 0xbe0a; - gbPalette[0x33] = 0xc053; - gbPalette[0x34] = 0xfe5f; - gbPalette[0x35] = 0xe000; - gbPalette[0x36] = 0xbe10; - gbPalette[0x37] = 0x914d; - gbPalette[0x38] = 0x7f91; - gbPalette[0x39] = 0x02b5; - gbPalette[0x3a] = 0x77ac; - gbPalette[0x3b] = 0x14e5; - gbPalette[0x3c] = 0xcf89; - gbPalette[0x3d] = 0xa03d; - gbPalette[0x3e] = 0xfd50; - gbPalette[0x3f] = 0x91ff; - } - else if (gbGBCColorType == 1) // GBA Hardware - { - gbPalette[0x20] = 0xbe00; - gbPalette[0x21] = 0xfdfd; - gbPalette[0x22] = 0xbd69; - gbPalette[0x23] = 0x7baf; - gbPalette[0x24] = 0xf5ff; - gbPalette[0x25] = 0x3f8f; - gbPalette[0x26] = 0xcee5; - gbPalette[0x27] = 0x5bf7; - gbPalette[0x28] = 0xb35b; - gbPalette[0x29] = 0xef97; - gbPalette[0x2a] = 0xef9f; - gbPalette[0x2b] = 0x97f7; - gbPalette[0x2c] = 0x82bf; - gbPalette[0x2d] = 0x9f3d; - gbPalette[0x2e] = 0xddde; - gbPalette[0x2f] = 0xbad5; - gbPalette[0x30] = 0x3cba; - gbPalette[0x31] = 0xdfd7; - gbPalette[0x32] = 0xedea; - gbPalette[0x33] = 0xfeda; - gbPalette[0x34] = 0xf7f9; - gbPalette[0x35] = 0xfdee; - gbPalette[0x36] = 0x6d2f; - gbPalette[0x37] = 0xf0e6; - gbPalette[0x38] = 0xf7f0; - gbPalette[0x39] = 0xf296; - gbPalette[0x3a] = 0x3bf1; - gbPalette[0x3b] = 0xe211; - gbPalette[0x3c] = 0x69ba; - gbPalette[0x3d] = 0x3d0d; - gbPalette[0x3e] = 0xdfd3; - gbPalette[0x3f] = 0xa6ba; - } - else if (gbGBCColorType == 2) // GBASP Hardware - { - gbPalette[0x20] = 0x9c00; - gbPalette[0x21] = 0x6340; - gbPalette[0x22] = 0x10c6; - gbPalette[0x23] = 0xdb97; - gbPalette[0x24] = 0x7622; - gbPalette[0x25] = 0x3e57; - gbPalette[0x26] = 0x2e12; - gbPalette[0x27] = 0x95c3; - gbPalette[0x28] = 0x1095; - gbPalette[0x29] = 0x488c; - gbPalette[0x2a] = 0x8241; - gbPalette[0x2b] = 0xde8c; - gbPalette[0x2c] = 0xfabc; - gbPalette[0x2d] = 0x0e81; - gbPalette[0x2e] = 0x7675; - gbPalette[0x2f] = 0xfdec; - gbPalette[0x30] = 0xddfd; - gbPalette[0x31] = 0x5995; - gbPalette[0x32] = 0x066a; - gbPalette[0x33] = 0xed1e; - gbPalette[0x34] = 0x1e84; - gbPalette[0x35] = 0x1d14; - gbPalette[0x36] = 0x11c3; - gbPalette[0x37] = 0x2749; - gbPalette[0x38] = 0xa727; - gbPalette[0x39] = 0x6266; - gbPalette[0x3a] = 0xe27b; - gbPalette[0x3b] = 0xe3fc; - gbPalette[0x3c] = 0x1f76; - gbPalette[0x3d] = 0xf158; - gbPalette[0x3e] = 0x468e; - gbPalette[0x3f] = 0xa540; - } - } else { - if(gbSgbMode) { - for(int i = 0; i < 8; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; - - } - for(int i = 0; i < 8; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; - } - - GBTIMER_MODE_0_CLOCK_TICKS = 256; - GBTIMER_MODE_1_CLOCK_TICKS = 4; - GBTIMER_MODE_2_CLOCK_TICKS = 16; - GBTIMER_MODE_3_CLOCK_TICKS = 64; - - GBLY_INCREMENT_CLOCK_TICKS = 114; - gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; - gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS; - gbSerialTicks = 0; - gbSerialBits = 0; - gbSerialOn = 0; - gbWindowLine = -1; - gbTimerOn = false; - gbTimerMode = 0; - gbSpeed = 0; - gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; - - if(gbCgbMode) { - gbSpeed = 0; - gbHdmaOn = 0; - gbHdmaSource = 0x99d0; - gbHdmaDestination = 0x99d0; - gbVramBank = 0; - gbWramBank = 1; - - } - - // used to clean the borders - if (gbSgbMode) - { - gbSgbResetFlag = true; - gbSgbReset(); - if (gbBorderOn) - gbSgbRenderBorder(); - gbSgbResetFlag = false; - } - - for(i = 0; i < 4; i++) - gbBgp[i] = gbObp0[i] = gbObp1[i] = i; - - memset(&gbDataMBC1,0, sizeof(gbDataMBC1)); - gbDataMBC1.mapperROMBank = 1; - - gbDataMBC2.mapperRAMEnable = 0; - gbDataMBC2.mapperROMBank = 1; - - memset(&gbDataMBC3,0, 6 * sizeof(int)); - gbDataMBC3.mapperROMBank = 1; - - memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); - gbDataMBC5.mapperROMBank = 1; - - memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); - gbDataHuC1.mapperROMBank = 1; - - memset(&gbDataHuC3, 0, sizeof(gbDataHuC3)); - gbDataHuC3.mapperROMBank = 1; - - memset(&gbDataTAMA5,0, 26*sizeof(int)); - gbDataTAMA5.mapperROMBank = 1; - - memset(&gbDataMMM01,0, sizeof(gbDataMMM01)); - gbDataMMM01.mapperROMBank = 1; - - if (useBios && !skipBios && (gbHardware & 5)) - { - gbMemoryMap[0x00] = &gbMemory[0x0000]; - inBios = true; - } - else - { - gbMemoryMap[0x00] = &gbRom[0x0000]; - inBios = false; - } - - gbMemoryMap[0x01] = &gbRom[0x1000]; - gbMemoryMap[0x02] = &gbRom[0x2000]; - gbMemoryMap[0x03] = &gbRom[0x3000]; - gbMemoryMap[0x04] = &gbRom[0x4000]; - gbMemoryMap[0x05] = &gbRom[0x5000]; - gbMemoryMap[0x06] = &gbRom[0x6000]; - gbMemoryMap[0x07] = &gbRom[0x7000]; - if(gbCgbMode) { - gbMemoryMap[0x08] = &gbVram[0x0000]; - gbMemoryMap[0x09] = &gbVram[0x1000]; - gbMemoryMap[0x0a] = &gbMemory[0xa000]; - gbMemoryMap[0x0b] = &gbMemory[0xb000]; - gbMemoryMap[0x0c] = &gbMemory[0xc000]; - gbMemoryMap[0x0d] = &gbWram[0x1000]; - gbMemoryMap[0x0e] = &gbMemory[0xe000]; - gbMemoryMap[0x0f] = &gbMemory[0xf000]; - } else { - gbMemoryMap[0x08] = &gbMemory[0x8000]; - gbMemoryMap[0x09] = &gbMemory[0x9000]; - gbMemoryMap[0x0a] = &gbMemory[0xa000]; - gbMemoryMap[0x0b] = &gbMemory[0xb000]; - gbMemoryMap[0x0c] = &gbMemory[0xc000]; - gbMemoryMap[0x0d] = &gbMemory[0xd000]; - gbMemoryMap[0x0e] = &gbMemory[0xe000]; - gbMemoryMap[0x0f] = &gbMemory[0xf000]; - } - - if(gbRam) { - gbMemoryMap[0x0a] = &gbRam[0x0000]; - gbMemoryMap[0x0b] = &gbRam[0x1000]; - } - - gbSoundReset(); - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - - gbLastTime = systemGetClock(); - gbFrameCount = 0; - - gbScreenOn = true; - gbSystemMessage = false; - - gbCheatWrite(true); // Emulates GS codes. - -} - -void gbWriteSaveMBC1(const char * name) -{ - if (gbRam) - { - FILE *gzFile = fopen(name,"wb"); - - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } - - fwrite(gbRam, - 1, - (gbRamSizeMask+1), - gzFile); - - fclose(gzFile); - } -} - -void gbWriteSaveMBC2(const char * name) -{ - if (gbRam) - { - FILE *file = fopen(name, "wb"); - - if(file == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } - - fwrite(&gbMemory[0xa000], - 1, - 256, - file); - - fclose(file); - } -} - -void gbWriteSaveMBC3(const char * name, bool extendedSave) -{ - if (gbRam || extendedSave) - { - FILE *gzFile = fopen(name,"wb"); - if (gbRam) - { - - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } - - fwrite(gbRam, - 1, - (gbRamSizeMask+1), - gzFile); - } - - if(extendedSave) - fwrite(&gbDataMBC3.mapperSeconds, - 1, - 10*sizeof(int) + sizeof(time_t), - gzFile); - - fclose(gzFile); - } -} - -void gbWriteSaveMBC5(const char * name) -{ - if (gbRam) - { - FILE *gzFile = fopen(name,"wb"); - - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } - - fwrite(gbRam, - 1, - (gbRamSizeMask+1), - gzFile); - - fclose(gzFile); - } -} - -void gbWriteSaveMBC7(const char * name) -{ - if (gbRam) - { - FILE *file = fopen(name, "wb"); - - if(file == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } - - fwrite(&gbMemory[0xa000], - 1, - 256, - file); - - fclose(file); - } -} - -void gbWriteSaveTAMA5(const char * name, bool extendedSave) -{ - FILE *gzFile = fopen(name,"wb"); - - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } - if (gbRam) - fwrite(gbRam, - 1, - (gbRamSizeMask+1), - gzFile); - - fwrite(gbTAMA5ram, - 1, - (gbTAMA5ramSize), - gzFile); - - if(extendedSave) - fwrite(&gbDataTAMA5.mapperSeconds, - 1, - 14*sizeof(int) + sizeof(time_t), - gzFile); - - fclose(gzFile); -} - -void gbWriteSaveMMM01(const char * name) -{ - if (gbRam) - { - FILE *gzFile = fopen(name,"wb"); - - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } - - fwrite(gbRam, - 1, - (gbRamSizeMask+1), - gzFile); - - fclose(gzFile); - } -} - - -bool gbReadSaveMBC1(const char * name) -{ - if (gbRam) - { - gzFile gzFile = gzopen(name, "rb"); - - if(gzFile == NULL) { - return false; - } - - int read = gzread(gzFile, - gbRam, - (gbRamSizeMask+1)); - - if(read != (gbRamSizeMask+1)) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gzclose(gzFile); - gbBatteryError = true; - return false; - } - - // Also checks if the battery file it bigger than gbRamSizeMask+1 ! - u8 data[1]; - data[0] = 0; - - read = gzread(gzFile, - data, - 1); - if(read >0) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gzclose(gzFile); - gbBatteryError = true; - return false; - } - - gzclose(gzFile); - return true; - } - else - return false; -} - - -bool gbReadSaveMBC2(const char * name) -{ - if (gbRam) - { - FILE *file = fopen(name, "rb"); - - if(file == NULL) { - return false; - } - - size_t read = fread(&gbMemory[0xa000], - 1, - 256, - file); - - if(read != 256) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - fclose(file); - gbBatteryError = true; - return false; - } - - // Also checks if the battery file it bigger than gbRamSizeMask+1 ! - u8 data[1]; - data[0] = 0; - - read = fread(&data[0], - 1, - 1, - file); - if(read > 0) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - fclose(file); - gbBatteryError = true; - return false; - } - - fclose(file); - return true; - } - else - return false; -} - -bool gbReadSaveMBC3(const char * name) -{ - gzFile gzFile = gzopen(name, "rb"); - - if(gzFile == NULL) { - return false; - } - - int read = 0; - - if (gbRam) - read = gzread(gzFile, - gbRam, - (gbRamSizeMask+1)); - else - read = (gbRamSizeMask+1); - - - bool res = true; - - if(read != (gbRamSizeMask+1)) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gbBatteryError = true; - res = false; - } else if ((gbRomType == 0xf) || (gbRomType == 0x10)){ - read = gzread(gzFile, - &gbDataMBC3.mapperSeconds, - sizeof(int)*10 + sizeof(time_t)); - - if(read != (sizeof(int)*10 + sizeof(time_t)) && read != 0) { - systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), - name); - res = false; - } - else if (read == 0) - { - systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), - name); - res = false; - } - else - { - // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC ! - u8 data[1]; - data[0] = 0; - - read = gzread(gzFile, - data, - 1); - if(read >0) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gbBatteryError = true; - res = false; - } - } - } - - gzclose(gzFile); - return res; -} - -bool gbReadSaveMBC5(const char * name) -{ - if (gbRam) - { - gzFile gzFile = gzopen(name, "rb"); - - if(gzFile == NULL) { - return false; - } - - int read = gzread(gzFile, - gbRam, - (gbRamSizeMask+1)); - - if(read != (gbRamSizeMask+1)) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gzclose(gzFile); - gbBatteryError = true; - return false; - } - - - // Also checks if the battery file it bigger than gbRamSizeMask+1 ! - u8 data[1]; - data[0] = 0; - - read = gzread(gzFile, - data, - 1); - if(read >0) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gzclose(gzFile); - gbBatteryError = true; - return false; - } - - gzclose(gzFile); - return true; - } - else - return false; -} - -bool gbReadSaveMBC7(const char * name) -{ - if (gbRam) - { - FILE *file = fopen(name, "rb"); - - if(file == NULL) { - return false; - } - - size_t read = fread(&gbMemory[0xa000], - 1, - 256, - file); - - if(read != 256) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - fclose(file); - gbBatteryError = true; - return false; - } - - // Also checks if the battery file it bigger than gbRamSizeMask+1 ! - u8 data[1]; - data[0] = 0; - - read = fread(&data[0], - 1, - 1, - file); - if(read > 0) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - fclose(file); - gbBatteryError = true; - return false; - } - - fclose(file); - return true; - } - else - return false; -} - -bool gbReadSaveTAMA5(const char * name) -{ - gzFile gzFile = gzopen(name, "rb"); - - if(gzFile == NULL) { - return false; - } - - int read = 0; - - if (gbRam) - read = gzread(gzFile, - gbRam, - (gbRamSizeMask+1)); - else - read = gbRamSizeMask; - - read += gzread(gzFile, - gbTAMA5ram, - gbTAMA5ramSize); - - bool res = true; - - if(read != (gbRamSizeMask+gbTAMA5ramSize+1)) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gbBatteryError = true; - res = false; - } else { - read = gzread(gzFile, - &gbDataTAMA5.mapperSeconds, - sizeof(int)*14 + sizeof(time_t)); - - if(read != (sizeof(int)*14 + sizeof(time_t)) && read != 0) { - systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), - name); - res = false; - } - else if (read == 0) - { - systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), - name); - res = false; - } - else - { - // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC ! - u8 data[1]; - data[0] = 0; - - read = gzread(gzFile, - data, - 1); - if(read >0) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gbBatteryError = true; - res = false; - } - } - } - - gzclose(gzFile); - return res; -} - - -bool gbReadSaveMMM01(const char * name) -{ - if (gbRam) - { - gzFile gzFile = gzopen(name, "rb"); - - if(gzFile == NULL) { - return false; - } - - int read = gzread(gzFile, - gbRam, - (gbRamSizeMask+1)); - - if(read != (gbRamSizeMask+1)) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gzclose(gzFile); - gbBatteryError = true; - return false; - } - - // Also checks if the battery file it bigger than gbRamSizeMask+1 ! - u8 data[1]; - data[0] = 0; - - read = gzread(gzFile, - data, - 1); - if(read >0) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); - gzclose(gzFile); - gbBatteryError = true; - return false; - } - - gzclose(gzFile); - return true; - } - else - return false; -} - -void gbInit() -{ - gbGenFilter(); - gbSgbInit(); - - gbMemory = (u8 *)malloc(65536); - - pix = (u8 *)calloc(1,4*257*226); - - gbLineBuffer = (u16 *)malloc(160 * sizeof(u16)); -} - -bool gbWriteBatteryFile(const char *file, bool extendedSave) -{ - if(gbBattery) { - switch(gbRomType) { - case 0x03: - gbWriteSaveMBC1(file); - break; - case 0x06: - gbWriteSaveMBC2(file); - break; - case 0x0d: - gbWriteSaveMMM01(file); - break; - case 0x0f: - case 0x10: - gbWriteSaveMBC3(file, extendedSave); - break; - case 0x13: - case 0xfc: - gbWriteSaveMBC3(file, false); - case 0x1b: - case 0x1e: - gbWriteSaveMBC5(file); - break; - case 0x22: - gbWriteSaveMBC7(file); - break; - case 0xfd: - gbWriteSaveTAMA5(file, extendedSave); - break; - case 0xff: - gbWriteSaveMBC1(file); - break; - } - } - return true; -} - -bool gbWriteBatteryFile(const char *file) -{ - if (!gbBatteryError) - { - gbWriteBatteryFile(file, true); - return true; - } - else return false; -} - -bool gbReadBatteryFile(const char *file) -{ - bool res = false; - if(gbBattery) { - switch(gbRomType) { - case 0x03: - res = gbReadSaveMBC1(file); - break; - case 0x06: - res = gbReadSaveMBC2(file); - break; - case 0x0d: - res = gbReadSaveMMM01(file); - break; - case 0x0f: - case 0x10: - if(!gbReadSaveMBC3(file)) { - time(&gbDataMBC3.mapperLastTime); - struct tm *lt; - lt = localtime(&gbDataMBC3.mapperLastTime); - gbDataMBC3.mapperSeconds = lt->tm_sec; - gbDataMBC3.mapperMinutes = lt->tm_min; - gbDataMBC3.mapperHours = lt->tm_hour; - gbDataMBC3.mapperDays = lt->tm_yday & 255; - gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | - (lt->tm_yday > 255 ? 1: 0); - res = false; - break; - } - res = true; - break; - case 0x13: - case 0xfc: - res = gbReadSaveMBC3(file); - case 0x1b: - case 0x1e: - res = gbReadSaveMBC5(file); - break; - case 0x22: - res = gbReadSaveMBC7(file); - case 0xfd: - if(!gbReadSaveTAMA5(file)) { - u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - time(&gbDataTAMA5.mapperLastTime); - struct tm *lt; - lt = localtime(&gbDataTAMA5.mapperLastTime); - gbDataTAMA5.mapperSeconds = lt->tm_sec; - gbDataTAMA5.mapperMinutes = lt->tm_min; - gbDataTAMA5.mapperHours = lt->tm_hour; - gbDataTAMA5.mapperDays = 1; - gbDataTAMA5.mapperMonths = 1; - gbDataTAMA5.mapperYears = 1970; - int days = lt->tm_yday+365*3; - while (days) - { - gbDataTAMA5.mapperDays++; - days--; - if (gbDataTAMA5.mapperDays>gbDaysinMonth[gbDataTAMA5.mapperMonths-1]) - { - gbDataTAMA5.mapperDays = 1; - gbDataTAMA5.mapperMonths++; - if (gbDataTAMA5.mapperMonths>12) - { - gbDataTAMA5.mapperMonths = 1; - gbDataTAMA5.mapperYears++; - if ((gbDataTAMA5.mapperYears & 3) == 0) - gbDaysinMonth[1] = 29; - else - gbDaysinMonth[1] = 28; - } - } - } - gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) | - (lt->tm_yday > 255 ? 1: 0); - res = false; - break; - } - res = true; - break; - case 0xff: - res = gbReadSaveMBC1(file); - break; - } - } - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - return res; -} - -bool gbReadGSASnapshot(const char *fileName) -{ - FILE *file = fopen(fileName, "rb"); - - if(!file) { - systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); - return false; - } - - fseek(file, 0x4, SEEK_SET); - char buffer[16]; - char buffer2[16]; - fread(buffer, 1, 15, file); - buffer[15] = 0; - memcpy(buffer2, &gbRom[0x134], 15); - buffer2[15] = 0; - if(memcmp(buffer, buffer2, 15)) { - systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR, - N_("Cannot import snapshot for %s. Current game is %s"), - buffer, - buffer2); - fclose(file); - return false; - } - fseek(file, 0x13, SEEK_SET); - size_t read = 0; - int toRead = 0; - switch(gbRomType) { - case 0x03: - case 0x0f: - case 0x10: - case 0x13: - case 0x1b: - case 0x1e: - case 0xff: - read = fread(gbRam, 1, (gbRamSizeMask+1), file); - toRead = (gbRamSizeMask+1); - break; - case 0x06: - case 0x22: - read = fread(&gbMemory[0xa000],1,256,file); - toRead = 256; - break; - default: - systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE, - N_("Unsupported snapshot file %s"), - fileName); - fclose(file); - return false; - } - fclose(file); - gbReset(); - return true; -} - -variable_desc gbSaveGameStruct[] = { - { &PC.W, sizeof(u16) }, - { &SP.W, sizeof(u16) }, - { &AF.W, sizeof(u16) }, - { &BC.W, sizeof(u16) }, - { &DE.W, sizeof(u16) }, - { &HL.W, sizeof(u16) }, - { &IFF, sizeof(u8) }, - { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int) }, - { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int) }, - { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int) }, - { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int) }, - { &GBDIV_CLOCK_TICKS, sizeof(int) }, - { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int) }, - { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int) }, - { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int) }, - { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int) }, - { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int) }, - { &GBSERIAL_CLOCK_TICKS, sizeof(int) }, - { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int) }, - { &gbDivTicks, sizeof(int) }, - { &gbLcdMode, sizeof(int) }, - { &gbLcdTicks, sizeof(int) }, - { &gbLcdLYIncrementTicks, sizeof(int) }, - { &gbTimerTicks, sizeof(int) }, - { &gbTimerClockTicks, sizeof(int) }, - { &gbSerialTicks, sizeof(int) }, - { &gbSerialBits, sizeof(int) }, - { &gbInt48Signal, sizeof(int) }, - { &gbInterruptWait, sizeof(int) }, - { &gbSynchronizeTicks, sizeof(int) }, - { &gbTimerOn, sizeof(int) }, - { &gbTimerMode, sizeof(int) }, - { &gbSerialOn, sizeof(int) }, - { &gbWindowLine, sizeof(int) }, - { &gbCgbMode, sizeof(int) }, - { &gbVramBank, sizeof(int) }, - { &gbWramBank, sizeof(int) }, - { &gbHdmaSource, sizeof(int) }, - { &gbHdmaDestination, sizeof(int) }, - { &gbHdmaBytes, sizeof(int) }, - { &gbHdmaOn, sizeof(int) }, - { &gbSpeed, sizeof(int) }, - { &gbSgbMode, sizeof(int) }, - { ®ister_DIV, sizeof(u8) }, - { ®ister_TIMA, sizeof(u8) }, - { ®ister_TMA, sizeof(u8) }, - { ®ister_TAC, sizeof(u8) }, - { ®ister_IF, sizeof(u8) }, - { ®ister_LCDC, sizeof(u8) }, - { ®ister_STAT, sizeof(u8) }, - { ®ister_SCY, sizeof(u8) }, - { ®ister_SCX, sizeof(u8) }, - { ®ister_LY, sizeof(u8) }, - { ®ister_LYC, sizeof(u8) }, - { ®ister_DMA, sizeof(u8) }, - { ®ister_WY, sizeof(u8) }, - { ®ister_WX, sizeof(u8) }, - { ®ister_VBK, sizeof(u8) }, - { ®ister_HDMA1, sizeof(u8) }, - { ®ister_HDMA2, sizeof(u8) }, - { ®ister_HDMA3, sizeof(u8) }, - { ®ister_HDMA4, sizeof(u8) }, - { ®ister_HDMA5, sizeof(u8) }, - { ®ister_SVBK, sizeof(u8) }, - { ®ister_IE , sizeof(u8) }, - { &gbBgp[0], sizeof(u8) }, - { &gbBgp[1], sizeof(u8) }, - { &gbBgp[2], sizeof(u8) }, - { &gbBgp[3], sizeof(u8) }, - { &gbObp0[0], sizeof(u8) }, - { &gbObp0[1], sizeof(u8) }, - { &gbObp0[2], sizeof(u8) }, - { &gbObp0[3], sizeof(u8) }, - { &gbObp1[0], sizeof(u8) }, - { &gbObp1[1], sizeof(u8) }, - { &gbObp1[2], sizeof(u8) }, - { &gbObp1[3], sizeof(u8) }, - { NULL, 0 } -}; - - -static bool gbWriteSaveState(gzFile gzFile) -{ - - utilWriteInt(gzFile, GBSAVE_GAME_VERSION); - - utilGzWrite(gzFile, &gbRom[0x134], 15); - - utilWriteInt(gzFile, useBios); - utilWriteInt(gzFile, inBios); - - utilWriteData(gzFile, gbSaveGameStruct); - - utilGzWrite(gzFile, &IFF, 2); - - if(gbSgbMode) { - gbSgbSaveGame(gzFile); - } - - utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); - utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); - utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); - utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); - utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); - utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); - utilGzWrite(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5)); - if (gbTAMA5ram != NULL) - utilGzWrite(gzFile, gbTAMA5ram, gbTAMA5ramSize); - utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01)); - - utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); - - utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000); - - if(gbRamSize && gbRam) { - utilWriteInt(gzFile, gbRamSize); - utilGzWrite(gzFile, gbRam, gbRamSize); - } - - if(gbCgbMode) { - utilGzWrite(gzFile, gbVram, 0x4000); - utilGzWrite(gzFile, gbWram, 0x8000); - } - - gbSoundSaveGame(gzFile); - - gbCheatsSaveGame(gzFile); - - utilWriteInt(gzFile, gbLcdModeDelayed); - utilWriteInt(gzFile, gbLcdTicksDelayed); - utilWriteInt(gzFile, gbLcdLYIncrementTicksDelayed); - utilWriteInt(gzFile, gbSpritesTicks[299]); - utilWriteInt(gzFile, gbTimerModeChange); - utilWriteInt(gzFile, gbTimerOnChange); - utilWriteInt(gzFile, gbHardware); - utilWriteInt(gzFile, gbBlackScreen); - utilWriteInt(gzFile, oldRegister_WY); - utilWriteInt(gzFile, gbWindowLine); - utilWriteInt(gzFile, inUseRegister_WY); - utilWriteInt(gzFile, gbScreenOn); - return true; -} - -bool gbWriteMemSaveState(char *memory, int available) -{ - gzFile gzFile = utilMemGzOpen(memory, available, "w"); - - if(gzFile == NULL) { - return false; - } - - bool res = gbWriteSaveState(gzFile); - - long pos = utilGzMemTell(gzFile)+8; - - if(pos >= (available)) - res = false; - - utilGzClose(gzFile); - - return res; -} - -bool gbWriteSaveState(const char *name) -{ - gzFile gzFile = utilGzOpen(name,"wb"); - - if(gzFile == NULL) - return false; - - bool res = gbWriteSaveState(gzFile); - - utilGzClose(gzFile); - return res; -} - -static bool gbReadSaveState(gzFile gzFile) -{ - int version = utilReadInt(gzFile); - - if(version > GBSAVE_GAME_VERSION || version < 0) { - systemMessage(MSG_UNSUPPORTED_VB_SGM, - N_("Unsupported VisualBoy save game version %d"), version); - return false; - } - - u8 romname[20]; - - utilGzRead(gzFile, romname, 15); - - if(memcmp(&gbRom[0x134], romname, 15) != 0) { - systemMessage(MSG_CANNOT_LOAD_SGM_FOR, - N_("Cannot load save game for %s. Playing %s"), - romname, &gbRom[0x134]); - return false; - } - - - bool ub = false; - bool ib = false; - - if (version >= 11) - { - ub = utilReadInt(gzFile) ? true : false; - ib = utilReadInt(gzFile) ? true : false; - - if((ub != useBios) && (ib)) { - if(useBios) - systemMessage(MSG_SAVE_GAME_NOT_USING_BIOS, - N_("Save game is not using the BIOS files")); - else - systemMessage(MSG_SAVE_GAME_USING_BIOS, - N_("Save game is using the BIOS file")); - return false; - } - } - - gbReset(); - - inBios = ib; - - utilReadData(gzFile, gbSaveGameStruct); - - - // Correct crash when loading color gameboy save in regular gameboy type. - if (!gbCgbMode) - { - if(gbVram != NULL) { - free(gbVram); - gbVram = NULL; - } - if(gbWram != NULL) { - free(gbWram); - gbWram = NULL; - } - } - else - { - if(gbVram == NULL) - gbVram = (u8 *)malloc(0x4000); - if(gbWram == NULL) - gbWram = (u8 *)malloc(0x8000); - memset(gbVram,0,0x4000); - memset(gbPalette,0, 2*128); - } - - - - if(version >= GBSAVE_GAME_VERSION_7) { - utilGzRead(gzFile, &IFF, 2); - } - - if(gbSgbMode) { - gbSgbReadGame(gzFile, version); - } else { - gbSgbMask = 0; // loading a game at the wrong time causes no display - } - if (version<11) - utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1) - sizeof(int)); - else - utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); - utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); - if(version < GBSAVE_GAME_VERSION_4) - // prior to version 4, there was no adjustment for the time the game - // was last played, so we have less to read. This needs update if the - // structure changes again. - utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)-sizeof(time_t)); - else - utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); - utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); - utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); - utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); - if (version>=11) - { - utilGzRead(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5)); - if (gbTAMA5ram != NULL) - utilGzRead(gzFile, gbTAMA5ram, gbTAMA5ramSize); - utilGzRead(gzFile, &gbDataMMM01, sizeof(gbDataMMM01)); - } - - if(version < GBSAVE_GAME_VERSION_5) { - utilGzRead(gzFile, pix, 256*224*sizeof(u16)); - } - memset(pix, 0, 257*226*sizeof(u32)); - - if(version < GBSAVE_GAME_VERSION_6) { - utilGzRead(gzFile, gbPalette, 64 * sizeof(u16)); - } else - utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); - - if (version < 11) - utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); - - if(version < GBSAVE_GAME_VERSION_10) { - if(!gbCgbMode && !gbSgbMode) { - for(int i = 0; i < 8; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; - } - } - - utilGzRead(gzFile, &gbMemory[0x8000], 0x8000); - - if(gbRamSize && gbRam) { - if (version < 11) - utilGzRead(gzFile, gbRam, gbRamSize); - else - { - int ramSize = utilReadInt(gzFile); - utilGzRead(gzFile, gbRam, (gbRamSize>ramSize) ? ramSize : gbRamSize); - if (ramSize>gbRamSize) - gzseek(gzFile,ramSize-gbRamSize,SEEK_CUR); - } - } - - memset(gbSCYLine, register_SCY, sizeof(gbSCYLine)); - memset(gbSCXLine, register_SCX, sizeof(gbSCXLine)); - memset(gbBgpLine, (gbBgp[0] | (gbBgp[1]<<2) | (gbBgp[2]<<4) | - (gbBgp[3]<<6)), sizeof(gbBgpLine)); - memset(gbObp0Line, (gbObp0[0] | (gbObp0[1]<<2) | (gbObp0[2]<<4) | - (gbObp0[3]<<6)), sizeof(gbObp0Line)); - memset(gbObp1Line, (gbObp1[0] | (gbObp1[1]<<2) | (gbObp1[2]<<4) | - (gbObp1[3]<<6)), sizeof(gbObp1Line)); - memset(gbSpritesTicks, 0x0, sizeof(gbSpritesTicks)); - - if (inBios) - { - gbMemoryMap[0x00] = &gbMemory[0x0000]; - memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000); - memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100); - } - else - gbMemoryMap[0x00] = &gbRom[0x0000]; - gbMemoryMap[0x01] = &gbRom[0x1000]; - gbMemoryMap[0x02] = &gbRom[0x2000]; - gbMemoryMap[0x03] = &gbRom[0x3000]; - gbMemoryMap[0x04] = &gbRom[0x4000]; - gbMemoryMap[0x05] = &gbRom[0x5000]; - gbMemoryMap[0x06] = &gbRom[0x6000]; - gbMemoryMap[0x07] = &gbRom[0x7000]; - gbMemoryMap[0x08] = &gbMemory[0x8000]; - gbMemoryMap[0x09] = &gbMemory[0x9000]; - gbMemoryMap[0x0a] = &gbMemory[0xa000]; - gbMemoryMap[0x0b] = &gbMemory[0xb000]; - gbMemoryMap[0x0c] = &gbMemory[0xc000]; - gbMemoryMap[0x0d] = &gbMemory[0xd000]; - gbMemoryMap[0x0e] = &gbMemory[0xe000]; - gbMemoryMap[0x0f] = &gbMemory[0xf000]; - - switch(gbRomType) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - // MBC 1 - memoryUpdateMapMBC1(); - break; - case 0x05: - case 0x06: - // MBC2 - memoryUpdateMapMBC2(); - break; - case 0x0b: - case 0x0c: - case 0x0d: - // MMM01 - memoryUpdateMapMMM01(); - break; - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - // MBC 3 - memoryUpdateMapMBC3(); - break; - case 0x19: - case 0x1a: - case 0x1b: - // MBC5 - memoryUpdateMapMBC5(); - break; - case 0x1c: - case 0x1d: - case 0x1e: - // MBC 5 Rumble - memoryUpdateMapMBC5(); - break; - case 0x22: - // MBC 7 - memoryUpdateMapMBC7(); - break; - case 0x56: - // GS3 - memoryUpdateMapGS3(); - break; - case 0xfd: - // TAMA5 - memoryUpdateMapTAMA5(); - break; - case 0xfe: - // HuC3 - memoryUpdateMapHuC3(); - break; - case 0xff: - // HuC1 - memoryUpdateMapHuC1(); - break; - } - - if(gbCgbMode) { - utilGzRead(gzFile, gbVram, 0x4000); - utilGzRead(gzFile, gbWram, 0x8000); - - int value = register_SVBK; - if(value == 0) - value = 1; - - gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000]; - gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000]; - gbMemoryMap[0x0d] = &gbWram[value * 0x1000]; - } - - gbSoundReadGame(version, gzFile); - - if (gbCgbMode && gbSgbMode) { - gbSgbMode = 0; - } - - if(gbBorderOn && !gbSgbMask) { - gbSgbRenderBorder(); - } - - systemDrawScreen(); - - if(version > GBSAVE_GAME_VERSION_1) - gbCheatsReadGame(gzFile, version); - - if (version<11) - { - gbWriteMemory(0xff00, 0); - gbMemory[0xff04] = register_DIV; - gbMemory[0xff05] = register_TIMA; - gbMemory[0xff06] = register_TMA; - gbMemory[0xff07] = register_TAC; - gbMemory[0xff40] = register_LCDC; - gbMemory[0xff42] = register_SCY; - gbMemory[0xff43] = register_SCX; - gbMemory[0xff44] = register_LY; - gbMemory[0xff45] = register_LYC; - gbMemory[0xff46] = register_DMA; - gbMemory[0xff4a] = register_WY; - gbMemory[0xff4b] = register_WX; - gbMemory[0xff4f] = register_VBK; - gbMemory[0xff51] = register_HDMA1; - gbMemory[0xff52] = register_HDMA2; - gbMemory[0xff53] = register_HDMA3; - gbMemory[0xff54] = register_HDMA4; - gbMemory[0xff55] = register_HDMA5; - gbMemory[0xff70] = register_SVBK; - gbMemory[0xffff] = register_IE; - GBDIV_CLOCK_TICKS = 64; - - if (gbSpeed) - gbDivTicks /=2; - - if ((gbLcdMode == 0) && (register_STAT & 8)) - gbInt48Signal |= 1; - if ((gbLcdMode == 1) && (register_STAT & 0x10)) - gbInt48Signal |= 2; - if ((gbLcdMode == 2) && (register_STAT & 0x20)) - gbInt48Signal |= 4; - if ((register_LY==register_LYC) && (register_STAT & 0x40)) - gbInt48Signal |= 8; - - gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS; - - if (gbLcdMode == 2) - gbLcdLYIncrementTicks-=GBLCD_MODE_2_CLOCK_TICKS-gbLcdTicks; - else if (gbLcdMode == 3) - gbLcdLYIncrementTicks -=GBLCD_MODE_2_CLOCK_TICKS+GBLCD_MODE_3_CLOCK_TICKS-gbLcdTicks; - else if (gbLcdMode == 0) - gbLcdLYIncrementTicks =gbLcdTicks; - else if (gbLcdMode == 1) - { - gbLcdLYIncrementTicks = gbLcdTicks % GBLY_INCREMENT_CLOCK_TICKS; - if (register_LY == 0x99) - gbLcdLYIncrementTicks =gbLine99Ticks; - else if (register_LY == 0) - gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS; - } - - gbLcdModeDelayed = gbLcdMode; - gbLcdTicksDelayed = gbLcdTicks--; - gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks--; - gbInterruptWait = 0; - memset(gbSpritesTicks,0,sizeof(gbSpritesTicks)); - } - else - { - gbLcdModeDelayed = utilReadInt(gzFile); - gbLcdTicksDelayed = utilReadInt(gzFile); - gbLcdLYIncrementTicksDelayed = utilReadInt(gzFile); - gbSpritesTicks[299] = utilReadInt(gzFile) & 0xff; - gbTimerModeChange = (utilReadInt(gzFile) ? true : false); - gbTimerOnChange = (utilReadInt(gzFile) ? true : false); - gbHardware = utilReadInt(gzFile); - gbBlackScreen = (utilReadInt(gzFile) ? true : false); - oldRegister_WY = utilReadInt(gzFile); - gbWindowLine = utilReadInt(gzFile); - inUseRegister_WY = utilReadInt(gzFile); - gbScreenOn = (utilReadInt(gzFile) ? true : false); - } - - if (gbSpeed) - gbLine99Ticks *= 2; - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - - return true; -} - -bool gbReadMemSaveState(char *memory, int available) -{ - gzFile gzFile = utilMemGzOpen(memory, available, "r"); - - bool res = gbReadSaveState(gzFile); - - utilGzClose(gzFile); - - return res; -} - -bool gbReadSaveState(const char *name) -{ - gzFile gzFile = utilGzOpen(name,"rb"); - - if(gzFile == NULL) { - return false; - } - - bool res = gbReadSaveState(gzFile); - - utilGzClose(gzFile); - - return res; -} - -bool gbWritePNGFile(const char *fileName) -{ - if(gbBorderOn) - return utilWritePNGFile(fileName, 256, 224, pix); - return utilWritePNGFile(fileName, 160, 144, pix); -} - -bool gbWriteBMPFile(const char *fileName) -{ - if(gbBorderOn) - return utilWriteBMPFile(fileName, 256, 224, pix); - return utilWriteBMPFile(fileName, 160, 144, pix); -} - -void gbCleanUp() -{ - if(gbRam != NULL) { - free(gbRam); - gbRam = NULL; - } - - if(gbRom != NULL) { - free(gbRom); - gbRom = NULL; - } - - if(gbMemory != NULL) { - free(gbMemory); - gbMemory = NULL; - } - - if(gbLineBuffer != NULL) { - free(gbLineBuffer); - gbLineBuffer = NULL; - } - - if(pix != NULL) { - free(pix); - pix = NULL; - } - - gbSgbShutdown(); - - //Brunni/ - if (gbExternalVram != NULL) { - free(gbExternalVram); - gbExternalVram = NULL; - } - - if(gbVram != NULL) { - free(gbVram); - gbVram = NULL; - } - - if(gbWram != NULL) { - free(gbWram); - gbWram = NULL; - } - - if(gbTAMA5ram != NULL) { - free(gbTAMA5ram); - gbTAMA5ram = NULL; - } - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; -} - -bool gbLoadRom(const char *szFile) -{ - int size = 0; - - if(gbRom != NULL) { - gbCleanUp(); - } - - systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - - gbRom = utilLoad(szFile, - utilIsGBImage, - NULL, - size); - if(!gbRom) - return false; - - gbRomSize = size; - - gbBatteryError = false; - - if(bios != NULL) { - free(bios); - bios = NULL; - } - bios = (u8 *)calloc(1,0x100); - - return gbUpdateSizes(); -} - -bool gbUpdateSizes() -{ - if(gbRom[0x148] > 8) { - systemMessage(MSG_UNSUPPORTED_ROM_SIZE, - N_("Unsupported rom size %02x"), gbRom[0x148]); - return false; - } - - if(gbRomSize < gbRomSizes[gbRom[0x148]]) { - gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); - for (int i = gbRomSize; igbRomSizes[gbRom[0x148]]) && (genericflashcardEnable)) - { - gbRomSize = gbRomSize>>16; - gbRom[0x148] = 0; - if (gbRomSize) - { - while (!((gbRomSize & 1) || (gbRom[0x148] == 7))) - { - gbRom[0x148]++; - gbRomSize>>=1; - } - gbRom[0x148]++; - } - gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); - } - gbRomSize = gbRomSizes[gbRom[0x148]]; - gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]]; - - - // The 'genericflashcard' option allows some PD to work. - // However, the setting is dangerous (if you let in enabled - // and play a normal game, it might just break everything). - // That's why it is not saved in the emulator options. - // Also I added some checks in VBA to make sure your saves will not be - // overwritten if you wrongly enable this option for a game - // you already played (and vice-versa, ie. if you forgot to - // enable the option for a game you played with it enabled, like Shawu Story). - u8 ramsize = genericflashcardEnable ? 5 : gbRom[0x149]; - gbRom[0x149] = ramsize; - - if ((gbRom[2] == 0x6D) && (gbRom[5] == 0x47) && (gbRom[6] == 0x65) && (gbRom[7] == 0x6E) && - (gbRom[8] == 0x69) && (gbRom[9] == 0x65) && (gbRom[0xA] == 0x28) && (gbRom[0xB] == 0x54)) - { - gbCheatingDevice = 1; // GameGenie - for (int i = 0; i < 0x20; i++) // Cleans GG hardware registers - gbRom[0x4000+i] = 0; - } - else if (((gbRom[0x104] == 0x44) && (gbRom[0x156] == 0xEA) && (gbRom[0x158] == 0x7F) && - (gbRom[0x159] == 0xEA) && (gbRom[0x15B] == 0x7F)) || ((gbRom[0x165] == 0x3E) && - (gbRom[0x166] == 0xD9) && (gbRom[0x16D] == 0xE1) && (gbRom[0x16E] == 0x7F))) - gbCheatingDevice = 2; // GameShark - else gbCheatingDevice = 0; - - if(ramsize > 5) { - systemMessage(MSG_UNSUPPORTED_RAM_SIZE, - N_("Unsupported ram size %02x"), gbRom[0x149]); - return false; - } - - gbRamSize = gbRamSizes[ramsize]; - gbRamSizeMask = gbRamSizesMasks[ramsize]; - - if(gbRamSize) { - gbRam = (u8 *)malloc(gbRamSize); - memset(gbRam, 0xff, gbRamSize); - } - - - gbRomType = gbRom[0x147]; - if (genericflashcardEnable) - { - /*if (gbRomType<2) - gbRomType =3; - else if ((gbRomType == 0xc) || (gbRomType == 0xf) || (gbRomType == 0x12) || - (gbRomType == 0x16) || (gbRomType == 0x1a) || (gbRomType == 0x1d)) - gbRomType++; - else if ((gbRomType == 0xb) || (gbRomType == 0x11) || (gbRomType == 0x15) || - (gbRomType == 0x19) || (gbRomType == 0x1c)) - gbRomType+=2; - else if ((gbRomType == 0x5) || (gbRomType == 0x6)) - gbRomType = 0x1a;*/ - gbRomType = 0x1b; - } - else if (gbCheatingDevice == 1) - gbRomType = 0x55; - else if (gbCheatingDevice == 2) - gbRomType = 0x56; - - gbRom[0x147] = gbRomType; - - mapperReadRAM = NULL; - - switch(gbRomType) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x08: - case 0x09: - // MBC 1 - mapper = mapperMBC1ROM; - mapperRAM = mapperMBC1RAM; - mapperReadRAM = mapperMBC1ReadRAM; - break; - case 0x05: - case 0x06: - // MBC2 - mapper = mapperMBC2ROM; - mapperRAM = mapperMBC2RAM; - gbRamSize = 0x200; - gbRamSizeMask = 0x1ff; - break; - case 0x0b: - case 0x0c: - case 0x0d: - // MMM01 - mapper = mapperMMM01ROM; - mapperRAM = mapperMMM01RAM; - break; - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0xfc: - // MBC 3 - mapper = mapperMBC3ROM; - mapperRAM = mapperMBC3RAM; - mapperReadRAM = mapperMBC3ReadRAM; - break; - case 0x19: - case 0x1a: - case 0x1b: - // MBC5 - mapper = mapperMBC5ROM; - mapperRAM = mapperMBC5RAM; - mapperReadRAM = mapperMBC5ReadRAM; - break; - case 0x1c: - case 0x1d: - case 0x1e: - // MBC 5 Rumble - mapper = mapperMBC5ROM; - mapperRAM = mapperMBC5RAM; - mapperReadRAM = mapperMBC5ReadRAM; - break; - case 0x22: - // MBC 7 - mapper = mapperMBC7ROM; - mapperRAM = mapperMBC7RAM; - mapperReadRAM = mapperMBC7ReadRAM; - break; - // GG (GameGenie) - case 0x55: - mapper = mapperGGROM; - break; - case 0x56: - // GS (GameShark) - mapper = mapperGS3ROM; - break; - case 0xfd: - // TAMA5 - if (gbRam!= NULL) - { - free(gbRam); - gbRam = NULL; - } - - ramsize = 3; - gbRamSize = gbRamSizes[3]; - gbRamSizeMask = gbRamSizesMasks[3]; - gbRam = (u8 *)malloc(gbRamSize); - memset(gbRam, 0x0, gbRamSize); - - gbTAMA5ramSize = 0x100; - - if (gbTAMA5ram == NULL) - gbTAMA5ram = (u8 *)malloc(gbTAMA5ramSize); - memset(gbTAMA5ram, 0x0, gbTAMA5ramSize); - - mapperRAM = mapperTAMA5RAM; - mapperReadRAM = mapperTAMA5ReadRAM; - mapperUpdateClock = memoryUpdateTAMA5Clock; - break; - case 0xfe: - // HuC3 - mapper = mapperHuC3ROM; - mapperRAM = mapperHuC3RAM; - mapperReadRAM = mapperHuC3ReadRAM; - break; - case 0xff: - // HuC1 - mapper = mapperHuC1ROM; - mapperRAM = mapperHuC1RAM; - break; - default: - systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE, - N_("Unknown cartridge type %02x"), gbRomType); - return false; - } - - switch(gbRomType) { - case 0x03: - case 0x06: - case 0x0f: - case 0x10: - case 0x13: - case 0x1b: - case 0x1d: - case 0x1e: - case 0x22: - case 0xfd: - case 0xff: - gbBattery = 1; - break; - } - - gbInit(); - - //gbReset(); - - switch(gbRomType) { - case 0x1c: - case 0x1d: - case 0x1e: - gbDataMBC5.isRumbleCartridge = 1; - } - - return true; -} - -int gbGetNextEvent (int clockTicks) -{ - if (register_LCDC & 0x80) - { - if(gbLcdTicks < clockTicks) - clockTicks = gbLcdTicks; - - if(gbLcdTicksDelayed < clockTicks) - clockTicks = gbLcdTicksDelayed; - - if(gbLcdLYIncrementTicksDelayed < clockTicks) - clockTicks = gbLcdLYIncrementTicksDelayed; - } - - if(gbLcdLYIncrementTicks < clockTicks) - clockTicks = gbLcdLYIncrementTicks; - - if(gbSerialOn && (gbSerialTicks < clockTicks)) - clockTicks = gbSerialTicks; - - if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks)) - clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1; - - //if(soundTicks && (soundTicks < clockTicks)) - // clockTicks = soundTicks; - - if ((clockTicks<=0) || (gbInterruptWait)) - clockTicks = 1; - - return clockTicks; -} - -void gbDrawLine() -{ - switch(systemColorDepth) { - case 16: - { - u16 * dest = (u16 *)pix + - (gbBorderLineSkip+2) * (register_LY + gbBorderRowSkip+1) - + gbBorderColumnSkip; - for(int x = 0; x < 160; ) { - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - } - if(gbBorderOn) - dest += gbBorderColumnSkip; - *dest++ = 0; // for filters that read one pixel more - } - break; - - case 24: - { - u8 *dest = (u8 *)pix + - 3*(gbBorderLineSkip * (register_LY + gbBorderRowSkip) + - gbBorderColumnSkip); - for(int x = 0; x < 160;) { - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - } - } - break; - - case 32: - { - u32 * dest = (u32 *)pix + - (gbBorderLineSkip+1) * (register_LY + gbBorderRowSkip+1) - + gbBorderColumnSkip; - for(int x = 0; x < 160;) { - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - } - } - break; - } -} - -void gbEmulate(int ticksToStop) -{ - gbRegister tempRegister; - u8 tempValue; - s8 offset; - - clockTicks = 0; - gbDmaTicks = 0; - - register int opcode = 0; - - int opcode1 = 0; - int opcode2 = 0; - bool execute = false; - - while(1) { -#ifndef FINAL_VERSION - if(systemDebug) { - if(!(IFF & 0x80)) { - if(systemDebug > 1) { - sprintf(gbBuffer,"PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n", - PC.W, AF.W, BC.W, DE.W,HL.W,SP.W,IFF); - } else { - sprintf(gbBuffer,"PC=%04x I=%02x\n", PC.W, IFF); - } - log(gbBuffer); - } - } -#endif - - u16 oldPCW = PC.W; - - if(IFF & 0x80) { - if(register_LCDC & 0x80) { - clockTicks = gbLcdTicks; - } else - clockTicks = 1000; - - clockTicks = gbGetNextEvent(clockTicks); - - /*if(gbLcdTicksDelayed < clockTicks) - clockTicks = gbLcdTicksDelayed; - - if(gbLcdLYIncrementTicksDelayed < clockTicks) - clockTicks = gbLcdLYIncrementTicksDelayed; - - if(gbLcdLYIncrementTicks < clockTicks) - clockTicks = gbLcdLYIncrementTicks; - - if(gbSerialOn && (gbSerialTicks < clockTicks)) - clockTicks = gbSerialTicks; - - if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks)) - clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1; - - if(soundTicks && (soundTicks < clockTicks)) - clockTicks = soundTicks; - - if ((clockTicks<=0) || (gbInterruptWait)) - clockTicks = 1;*/ - - } else { - - // First we apply the clockTicks, then we execute the opcodes. - opcode1 = 0; - opcode2 = 0; - execute = true; - - opcode2 = opcode1 = opcode = gbReadOpcode(PC.W++); - - // If HALT state was launched while IME = 0 and (register_IF & register_IE & 0x1F), - // PC.W is not incremented for the first byte of the next instruction. - if (IFF & 2) - { - PC.W--; - IFF &= ~2; - } - - clockTicks = gbCycles[opcode]; - - switch(opcode) { - case 0xCB: - // extended opcode - opcode2 = opcode = gbReadOpcode(PC.W++); - clockTicks = gbCyclesCB[opcode]; - break; - } - gbOldClockTicks = clockTicks-1; - gbIntBreak = 1; - } - - - if(!emulating) - return; - - // For 'breakpoint' support (opcode 0xFC is considered as a breakpoint) - if ((clockTicks==0) && execute) - { - PC.W = oldPCW; - return; - } - - - if (!(IFF & 0x80)) - clockTicks = 1; - - gbRedoLoop: - - - - if (gbInterruptWait) - gbInterruptWait = 0; - else - gbInterruptLaunched = 0; - - - // Used for the EI/DI instruction's delay. - if (IFF & 0x38) - { - int tempIFF = (IFF >> 4) & 3; - - if (tempIFF <=clockTicks) - { - tempIFF = 0; - IFF |=1; - } - else - tempIFF -= clockTicks; - IFF = (IFF & 0xCF) | (tempIFF <<4); - - if (IFF & 0x08) - IFF &= 0x82; - } - - - if (register_LCDCBusy) - { - register_LCDCBusy-=clockTicks; - if (register_LCDCBusy<0) - register_LCDCBusy = 0; - } - - - if(gbSgbMode) { - if(gbSgbPacketTimeout) { - gbSgbPacketTimeout -= clockTicks; - - if(gbSgbPacketTimeout <= 0) - gbSgbResetPacketState(); - } - } - - ticksToStop -= clockTicks; - - // DIV register emulation - gbDivTicks -= clockTicks; - while(gbDivTicks <= 0) { - gbMemory[0xff04] = ++register_DIV; - gbDivTicks += GBDIV_CLOCK_TICKS; - } - - if(register_LCDC & 0x80) { - // LCD stuff - - gbLcdTicks -= clockTicks; - gbLcdTicksDelayed -= clockTicks; - gbLcdLYIncrementTicks -= clockTicks; - gbLcdLYIncrementTicksDelayed -= clockTicks; - - - // our counters are off, see what we need to do - - // This looks (and kinda is) complicated, however this - // is the only way I found to emulate properly the way - // the real hardware operates... - while(((gbLcdTicks <= 0) && (gbLCDChangeHappened == false)) || - ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened == true)) || - ((gbLcdLYIncrementTicks <= 0) && (gbLYChangeHappened == false)) || - ((gbLcdLYIncrementTicksDelayed<=0) && (gbLYChangeHappened == true))) - { - - if ((gbLcdLYIncrementTicks <= 0) && (!gbLYChangeHappened)) - { - gbLYChangeHappened = true; - gbMemory[0xff44] = register_LY = (register_LY + 1) % 154; - - if (register_LY == 0x91) - { - /* if (IFF & 0x80) - gbScreenOn = !gbScreenOn; - else*/ if (register_LCDC & 0x80) - gbScreenOn = true; - } - - gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS; - - if (gbLcdMode == 1) - { - - if(register_LY == 153) - gbLcdLYIncrementTicks -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; - else if(register_LY == 0) - gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; - } - - // GB only 'bug' : Halt state is broken one tick before LY==LYC interrupt - // is reflected in the registers. - if ((gbHardware & 5) && (IFF & 0x80) && (register_LY == register_LYC) - && (register_STAT & 0x40) && (register_LY != 0)) - { - if (!((gbLcdModeDelayed != 1) && (register_LY==0))) - { - gbInt48Signal &= ~9; - gbCompareLYToLYC(); - gbLYChangeHappened = false; - gbMemory[0xff41] = register_STAT; - gbMemory[0xff0f] = register_IF; - } - - gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks+1; - } - } - - - if ((gbLcdTicks <= 0) && (!gbLCDChangeHappened)) - { - gbLCDChangeHappened = true; - - switch(gbLcdMode) - { - case 0: - { - // H-Blank - // check if we reached the V-Blank period - if(register_LY == 144) { - // Yes, V-Blank - // set the LY increment counter - if (gbHardware & 0x5) - { - register_IF |= 1; // V-Blank interrupt - } - - gbInt48Signal &= ~6; - if(register_STAT & 0x10) - { - // send LCD interrupt only if no interrupt 48h signal... - if ((!(gbInt48Signal & 1)) && ((!(gbInt48Signal & 8)) || (gbHardware & 0x0a))) - { - register_IF |=2; - gbInterruptLaunched |= 2; - if (gbHardware & 0xa) - gbInterruptWait = 1; - } - gbInt48Signal |= 2; - } - gbInt48Signal &= ~1; - - gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS; - gbLcdMode = 1; - - } else { - // go the the OAM being accessed mode - gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; - gbLcdMode = 2; - - gbInt48Signal &= ~6; - if(register_STAT & 0x20) - { - // send LCD interrupt only if no interrupt 48h signal... - if (!gbInt48Signal) - { - register_IF |= 2; - gbInterruptLaunched |= 2; - } - gbInt48Signal |= 4; - } - gbInt48Signal &= ~1; - } - } - break; - case 1: - { - // V-Blank - // next mode is OAM being accessed mode - gbInt48Signal &= ~5; - if(register_STAT & 0x20) - { - // send LCD interrupt only if no interrupt 48h signal... - if (!gbInt48Signal) - { - register_IF |= 2; - gbInterruptLaunched |= 2; - if ((gbHardware & 0xa) && (IFF & 0x80)) - gbInterruptWait = 1; - } - gbInt48Signal |= 4; - } - gbInt48Signal &= ~2; - - gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; - - gbLcdMode = 2; - register_LY = 0x00; - - } - break; - case 2: - { - - // OAM being accessed mode - // next mode is OAM and VRAM in use - if ((gbScreenOn) && (register_LCDC & 0x80)) - { - gbDrawSprites(false); - // Used to add a one tick delay when a window line is drawn. - //(fixes a part of Carmaggedon problem) - if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) && - (gbWindowLine != -2)) { - - int inUseRegister_WY = 0; - int tempgbWindowLine = gbWindowLine; - - if ((tempgbWindowLine == -1) || (tempgbWindowLine>144)) - { - inUseRegister_WY = oldRegister_WY; - if (register_LY>oldRegister_WY) - tempgbWindowLine = 146; - } - - int wy = inUseRegister_WY; - - if(register_LY >= inUseRegister_WY) { - - if (tempgbWindowLine == -1) - tempgbWindowLine = 0; - - int wx = register_WX; - wx -= 7; - if (wx<0) - wx = 0; - - if((wx <= 159) && (tempgbWindowLine <= 143)) - for (int i = wx; i<300; i++) - if (gbSpeed) - gbSpritesTicks[i]+=3; - else - gbSpritesTicks[i]+=1; - } - } - } - - gbInt48Signal &= ~7; - - gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299]; - gbLcdMode = 3; - } - break; - case 3: - { - // OAM and VRAM in use - // next mode is H-Blank - - - gbInt48Signal &= ~7; - if(register_STAT & 0x08) - { - // send LCD interrupt only if no interrupt 48h signal... - if (!(gbInt48Signal & 8)) - { - register_IF |= 2; - if ((gbHardware & 0xa) && (IFF & 0x80)) - gbInterruptWait = 1; - } - gbInt48Signal |= 1; - } - - gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]; - - gbLcdMode = 0; - - // No HDMA during HALT ! - if(gbHdmaOn && (!(IFF & 0x80) || (register_IE & register_IF & 0x1f))) { - gbDoHdma(); - } - - } - break; - } - } - - - if ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened)) { - int framesToSkip = systemFrameSkip; - if(speedup) - framesToSkip = 9; // try 6 FPS during speedup - //gbLcdTicksDelayed = gbLcdTicks+1; - gbLCDChangeHappened = false; - switch(gbLcdModeDelayed) { - case 0: - { - // H-Blank - - memset(gbSCYLine,gbSCYLine[299],sizeof(gbSCYLine)); - memset(gbSCXLine,gbSCXLine[299],sizeof(gbSCXLine)); - memset(gbBgpLine,gbBgpLine[299],sizeof(gbBgpLine)); - memset(gbObp0Line,gbObp0Line[299],sizeof(gbObp0Line)); - memset(gbObp1Line,gbObp1Line[299],sizeof(gbObp1Line)); - memset(gbSpritesTicks,gbSpritesTicks[299],sizeof(gbSpritesTicks)); - - if (gbWindowLine <0) - oldRegister_WY = register_WY; - // check if we reached the V-Blank period - if(register_LY == 144) { - // Yes, V-Blank - // set the LY increment counter - - if(register_LCDC & 0x80) { - if (gbHardware & 0xa) - { - - register_IF |= 1; // V-Blank interrupt - gbInterruptLaunched |=1; - } - - - } - - gbLcdTicksDelayed += GBLCD_MODE_1_CLOCK_TICKS; - gbLcdModeDelayed = 1; - - gbFrameCount++; - systemFrame(); - - if((gbFrameCount % 10) == 0) - system10Frames(60); - - if(gbFrameCount >= 60) { - u32 currentTime = systemGetClock(); - if(currentTime != gbLastTime) - systemShowSpeed(100000/(currentTime - gbLastTime)); - else - systemShowSpeed(0); - gbLastTime = currentTime; - gbFrameCount = 0; - } - - if(systemReadJoypads()) { - // read joystick - if(gbSgbMode && gbSgbMultiplayer) { - if(gbSgbFourPlayers) { - gbJoymask[0] = systemReadJoypad(0); - gbJoymask[1] = systemReadJoypad(1); - gbJoymask[2] = systemReadJoypad(2); - gbJoymask[3] = systemReadJoypad(3); - } else { - gbJoymask[0] = systemReadJoypad(0); - gbJoymask[1] = systemReadJoypad(1); - } - } else { - gbJoymask[0] = systemReadJoypad(-1); - } - } - int newmask = gbJoymask[0] & 255; - - if(gbRomType == 0x22) { - systemUpdateMotionSensor(); - } - - if(newmask) - { - gbMemory[0xff0f] |= 16; - } - - - newmask = (gbJoymask[0] >> 10); - - speedup = (newmask & 1) ? true : false; - gbCapture = (newmask & 2) ? true : false; - - if(gbCapture && !gbCapturePrevious) { - gbCaptureNumber++; - systemScreenCapture(gbCaptureNumber); - } - gbCapturePrevious = gbCapture; - - if(gbFrameSkipCount >= framesToSkip) { - - if(!gbSgbMask) - { - if (gbBorderOn) - gbSgbRenderBorder(); - //if (gbScreenOn) - systemDrawScreen(); - } - gbFrameSkipCount = 0; - } else - gbFrameSkipCount++; - - } else { - // go the the OAM being accessed mode - gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS; - gbLcdModeDelayed = 2; - gbInt48Signal &= ~3; - } - } - break; - case 1: - { - // V-Blank - // next mode is OAM being accessed mode - - // gbScreenOn = true; - - oldRegister_WY = register_WY; - - gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS; - gbLcdModeDelayed = 2; - - // reset the window line - gbWindowLine = -1; - } - break; - case 2: - { - // OAM being accessed mode - // next mode is OAM and VRAM in use - gbLcdTicksDelayed += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299]; - gbLcdModeDelayed = 3; - } - break; - case 3: - { - - // OAM and VRAM in use - // next mode is H-Blank - if((register_LY < 144) && (register_LCDC & 0x80) && gbScreenOn) { - if(!gbSgbMask) { - if(gbFrameSkipCount >= framesToSkip) { - if (!gbBlackScreen) - { - gbRenderLine(); - gbDrawSprites(true); - } - else if (gbBlackScreen) - { - u16 color = gbColorOption ? gbColorFilter[0] : 0; - if (!gbCgbMode) - color = gbColorOption ? gbColorFilter[gbPalette[3] & 0x7FFF] : - gbPalette[3] & 0x7FFF; - for(int i = 0; i < 160; i++) - { - gbLineMix[i] = color; - gbLineBuffer[i] = 0; - } - } - gbDrawLine(); - } - } - } - gbLcdTicksDelayed += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]; - gbLcdModeDelayed = 0; - } - break; - } - } - - if ((gbLcdLYIncrementTicksDelayed <= 0) && (gbLYChangeHappened == true)) - { - - gbLYChangeHappened = false; - - if (!((gbLcdMode != 1) && (register_LY==0))) - { - { - gbInt48Signal &= ~8; - gbCompareLYToLYC(); - if ((gbInt48Signal == 8) && (!((register_LY == 0) && (gbHardware & 1)))) - gbInterruptLaunched |= 2; - if ((gbHardware & (gbSpeed ? 8 : 2)) && (register_LY==0) && ((register_STAT & 0x44) == 0x44) && (gbLcdLYIncrementTicksDelayed==0)) - { - gbInterruptWait = 1; - - } - } - } - gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS; - - if (gbLcdModeDelayed == 1) - { - - if(register_LY == 153) - gbLcdLYIncrementTicksDelayed -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; - else if(register_LY == 0) - gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; - } - gbMemory[0xff0f] = register_IF; - gbMemory[0xff41] = register_STAT; - } - } - gbMemory[0xff0f] = register_IF; - gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | gbLcdModeDelayed; - } - else - { - - // Used to update the screen with white lines when it's off. - // (it looks strange, but it's kinda accurate :p) - // You can try the Mario Demo Vx.x for exemple - // (check the bottom 2 lines while moving) - if (!gbWhiteScreen) - { - gbScreenTicks -= clockTicks; - gbLcdLYIncrementTicks -= clockTicks; - while (gbLcdLYIncrementTicks <=0) - { - register_LY = ((register_LY+1)%154); - gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS; - } - if (gbScreenTicks <= 0) - { - gbWhiteScreen = 1; - u8 register_LYLcdOff = ((register_LY+154)%154); - for (register_LY=0;register_LY <= 0x90;register_LY++) - { - u16 color = gbColorOption ? gbColorFilter[0x7FFF] : - 0x7FFF; - if (!gbCgbMode) - color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : - gbPalette[0] & 0x7FFF; - for(int i = 0; i < 160; i++) - { - gbLineMix[i] = color; - gbLineBuffer[i] = 0; - } - gbDrawLine(); - } - register_LY = register_LYLcdOff; - } - } - - if (gbWhiteScreen) - { - gbLcdLYIncrementTicks -= clockTicks; - - while (gbLcdLYIncrementTicks <=0) - { - register_LY = ((register_LY+1)%154); - gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS; - if (register_LY<144) - { - - u16 color = gbColorOption ? gbColorFilter[0x7FFF] : - 0x7FFF; - if (!gbCgbMode) - color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : - gbPalette[0] & 0x7FFF; - for(int i = 0; i < 160; i++) - { - gbLineMix[i] = color; - gbLineBuffer[i] = 0; - } - gbDrawLine(); - } - else if ((register_LY==144) && (!systemFrameSkip)) - { - int framesToSkip = systemFrameSkip; - if(speedup) - framesToSkip = 9; // try 6 FPS during speedup - if((gbFrameSkipCount >= framesToSkip) || (gbWhiteScreen == 1)) { - gbWhiteScreen = 2; - - if(!gbSgbMask) - { - if (gbBorderOn) - gbSgbRenderBorder(); - //if (gbScreenOn) - systemDrawScreen(); - } - } - if(systemReadJoypads()) { - // read joystick - if(gbSgbMode && gbSgbMultiplayer) { - if(gbSgbFourPlayers) { - gbJoymask[0] = systemReadJoypad(0); - gbJoymask[1] = systemReadJoypad(1); - gbJoymask[2] = systemReadJoypad(2); - gbJoymask[3] = systemReadJoypad(3); - } else { - gbJoymask[0] = systemReadJoypad(0); - gbJoymask[1] = systemReadJoypad(1); - } - } else { - gbJoymask[0] = systemReadJoypad(-1); - } - } - gbFrameCount++; - - systemFrame(); - - if((gbFrameCount % 10) == 0) - system10Frames(60); - - if(gbFrameCount >= 60) { - u32 currentTime = systemGetClock(); - if(currentTime != gbLastTime) - systemShowSpeed(100000/(currentTime - gbLastTime)); - else - systemShowSpeed(0); - gbLastTime = currentTime; - gbFrameCount = 0; - } - } - } - } - } - - gbMemory[0xff41] = register_STAT; - - // serial emulation - if(gbSerialOn) { -#ifdef LINK_EMULATION - if(linkConnected) { - gbSerialTicks -= clockTicks; - - while(gbSerialTicks <= 0) { - // increment number of shifted bits - gbSerialBits++; - linkProc(); - if(gbSerialOn && (gbMemory[0xff02] & 1)) { - if(gbSerialBits == 8) { - gbSerialBits = 0; - gbMemory[0xff01] = 0xff; - gbMemory[0xff02] &= 0x7f; - gbSerialOn = 0; - gbMemory[0xff0f] = register_IF |= 8; - gbSerialTicks = 0; - } - } - gbSerialTicks += GBSERIAL_CLOCK_TICKS; - } - } else { -#endif - if(gbMemory[0xff02] & 1) { - gbSerialTicks -= clockTicks; - - // overflow - while(gbSerialTicks <= 0) { - // shift serial byte to right and put a 1 bit in its place - // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1); - // increment number of shifted bits - gbSerialBits++; - if(gbSerialBits == 8) { - // end of transmission - if(gbSerialFunction) // external device - gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); - else - gbMemory[0xff01] = 0xff; - gbSerialTicks = 0; - gbMemory[0xff02] &= 0x7f; - gbSerialOn = 0; - gbMemory[0xff0f] = register_IF |= 8; - gbSerialBits = 0; - } else - gbSerialTicks += GBSERIAL_CLOCK_TICKS; - } - } -#ifdef LINK_EMULATION - } -#endif - } - - - soundTicks -= clockTicks; - if ( !gbSpeed ) - soundTicks -= clockTicks; - - while(soundTicks < 0) { - soundTicks += SOUND_CLOCK_TICKS; - - gbSoundTick(); - } - - - // timer emulation - - if(gbTimerOn) { - gbTimerTicks= ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1-clockTicks; - - while(gbTimerTicks <= 0) { - register_TIMA++; - // timer overflow! - if((register_TIMA & 0xff) == 0) { - // reload timer modulo - register_TIMA = register_TMA; - // flag interrupt - gbMemory[0xff0f] = register_IF |= 4; - } - gbTimerTicks += gbTimerClockTicks; - } - gbTimerOnChange = false; - gbTimerModeChange = false; - - gbMemory[0xff05] = register_TIMA; - - } - - gbInternalTimer -= clockTicks; - while (gbInternalTimer<0) - gbInternalTimer+=0x100; - - /* - if(soundOffFlag) { - if(synchronize && !speedup) { - synchronizeTicks -= clockTicks; - - while(synchronizeTicks < 0) { - synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS; - - DWORD now = timeGetTime(); - gbElapsedTime += (now - timeNow); - - if(gbElapsedTime < 50) { - DWORD diff = 50 - gbElapsedTime; - Sleep(diff); - timeNow = timeGetTime(); - elapsedTime = timeNow - now - diff; - if((int)elapsedTime < 0) - elapsedTime = 0; - } else { - timeNow = timeGetTime(); - elapsedTime = 0; - } - } - } - } - */ - - clockTicks = 0; - - if (gbIntBreak == 1) - { - gbIntBreak = 0; - if ((register_IE & register_IF & gbInterruptLaunched & 0x3) && - ((IFF & 0x81) == 1) && (!gbInterruptWait) && (execute)) - { - gbIntBreak = 2; - PC.W = oldPCW; - execute = false; - gbOldClockTicks = 0; - } - if (gbOldClockTicks) - { - clockTicks = gbOldClockTicks; - gbOldClockTicks = 0; - goto gbRedoLoop; - } - } - - // Executes the opcode(s), and apply the instruction's remaining clockTicks (if any). - if (execute) - { - switch(opcode1) { - case 0xCB: - // extended opcode - switch(opcode2) { -#include "gbCodesCB.h" - } - break; -#include "gbCodes.h" - } - execute = false; - - if (clockTicks) - { - gbDmaTicks += clockTicks; - clockTicks = 0; - } - } - - if (gbDmaTicks) - { - clockTicks = gbGetNextEvent(gbDmaTicks); - - if (clockTicks<=gbDmaTicks) - gbDmaTicks -= clockTicks; - else - { - clockTicks = gbDmaTicks; - gbDmaTicks = 0; - } - - goto gbRedoLoop; - } - - - // Remove the 'if an IE is pending' flag if IE has finished being executed. - if ((IFF & 0x40) && !(IFF & 0x30)) - IFF &= 0x81; - - - - if ((register_IE & register_IF & 0x1f) && (IFF & 0x81) && (!gbInterruptWait)) - { - - if (IFF & 1) - { - // Add 5 ticks for the interrupt execution time - gbDmaTicks += 5; - - if (gbIntBreak == 2) - { - gbDmaTicks--; - gbIntBreak = 0; - } - - - if(register_IF & register_IE & 1) - gbVblank_interrupt(); - else if(register_IF & register_IE & 2) - gbLcd_interrupt(); - else if(register_IF & register_IE & 4) - gbTimer_interrupt(); - else if(register_IF & register_IE & 8) - gbSerial_interrupt(); - else if(register_IF & register_IE & 16) - gbJoypad_interrupt(); - } - - IFF &= ~0x81; - } - - if (IFF & 0x08) - IFF &=~0x79; - - // Used to apply the interrupt's execution time. - if (gbDmaTicks) - { - clockTicks = gbGetNextEvent(gbDmaTicks); - - if (clockTicks<=gbDmaTicks) - gbDmaTicks -= clockTicks; - else - { - clockTicks = gbDmaTicks; - gbDmaTicks = 0; - } - goto gbRedoLoop; - } - - - gbBlackScreen = false; - - if((ticksToStop <= 0)) { - if(!(register_LCDC & 0x80)) { - if(systemReadJoypads()) { - // read joystick - if(gbSgbMode && gbSgbMultiplayer) { - if(gbSgbFourPlayers) { - gbJoymask[0] = systemReadJoypad(0); - gbJoymask[1] = systemReadJoypad(1); - gbJoymask[2] = systemReadJoypad(2); - gbJoymask[3] = systemReadJoypad(3); - } else { - gbJoymask[0] = systemReadJoypad(0); - gbJoymask[1] = systemReadJoypad(1); - } - } else { - gbJoymask[0] = systemReadJoypad(-1); - } - } - } - return; - } - } -} - -struct EmulatedSystem GBSystem = { - // emuMain - gbEmulate, - // emuReset - gbReset, - // emuCleanUp - gbCleanUp, - // emuReadBattery - gbReadBatteryFile, - // emuWriteBattery - gbWriteBatteryFile, - // emuReadState - gbReadSaveState, - // emuWriteState - gbWriteSaveState, - // emuReadMemState - gbReadMemSaveState, - // emuWriteMemState - gbWriteMemSaveState, - // emuWritePNG - gbWritePNGFile, - // emuWriteBMP - gbWriteBMPFile, - // emuUpdateCPSR - NULL, - // emuHasDebugger - false, - // emuCount -#ifdef FINAL_VERSION - 70000/4, -#else - 1000, -#endif -}; diff --git a/src/dmg/gb.h b/src/dmg/gb.h deleted file mode 100644 index 26099f14..00000000 --- a/src/dmg/gb.h +++ /dev/null @@ -1,64 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef VBA_GB_GB_H -#define VBA_GB_GB_H - -#define C_FLAG 0x10 -#define H_FLAG 0x20 -#define N_FLAG 0x40 -#define Z_FLAG 0x80 - -typedef union { - struct { -#ifdef WORDS_BIGENDIAN - u8 B1, B0; -#else - u8 B0,B1; -#endif - } B; - u16 W; -} gbRegister; - -extern bool gbLoadRom(const char *); -extern void gbEmulate(int); -extern void gbWriteMemory(register u16, register u8); -extern void gbDrawLine(); -extern bool gbIsGameboyRom(const char *); -extern void gbSoundReset(); -extern void gbSoundSetQuality(int); -extern void gbGetHardwareType(); -extern void gbReset(); -extern void gbCleanUp(); -extern void gbCPUInit(const char *,bool); -extern bool gbWriteBatteryFile(const char *); -extern bool gbWriteBatteryFile(const char *, bool); -extern bool gbReadBatteryFile(const char *); -extern bool gbWriteSaveState(const char *); -extern bool gbWriteMemSaveState(char *, int); -extern bool gbReadSaveState(const char *); -extern bool gbReadMemSaveState(char *, int); -extern void gbSgbRenderBorder(); -extern bool gbWritePNGFile(const char *); -extern bool gbWriteBMPFile(const char *); -extern bool gbReadGSASnapshot(const char *); - -extern struct EmulatedSystem GBSystem; - -#endif diff --git a/src/dmg/gbCheats.cpp b/src/dmg/gbCheats.cpp deleted file mode 100644 index 2463d282..00000000 --- a/src/dmg/gbCheats.cpp +++ /dev/null @@ -1,522 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include -#include -#include - -#include "../System.h" -#include "../NLS.h" -#include "../Util.h" - -#include "gbCheats.h" -#include "gbGlobals.h" -#include "gb.h" - -gbCheat gbCheatList[100]; -int gbCheatNumber = 0; -int gbNextCheat = 0; -bool gbCheatMap[0x10000]; - -extern bool cheatsEnabled; - -#define GBCHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9')) -#define GBCHEAT_HEX_VALUE(a) ( (a) >= 'A' ? (a) - 'A' + 10 : (a) - '0') - -void gbCheatUpdateMap() -{ - memset(gbCheatMap, 0, 0x10000); - - for(int i = 0; i < gbCheatNumber; i++) { - if(gbCheatList[i].enabled) - gbCheatMap[gbCheatList[i].address] = true; - } -} - -void gbCheatsSaveGame(gzFile gzFile) -{ - utilWriteInt(gzFile, gbCheatNumber); - if(gbCheatNumber>0) - utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); -} - -void gbCheatsReadGame(gzFile gzFile, int version) -{ - if(version <= 8) { - int gbGgOn = utilReadInt(gzFile); - - if(gbGgOn) { - int n = utilReadInt(gzFile); - gbXxCheat tmpCheat; - for(int i = 0; i < n; i++) { - utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat)); - gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); - } - } - - int gbGsOn = utilReadInt(gzFile); - - if(gbGsOn) { - int n = utilReadInt(gzFile); - gbXxCheat tmpCheat; - for(int i = 0; i < n; i++) { - utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat)); - gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); - } - } - } else { - gbCheatNumber = utilReadInt(gzFile); - - if(gbCheatNumber>0) { - utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); - } - } - - gbCheatUpdateMap(); -} - -void gbCheatsSaveCheatList(const char *file) -{ - if(gbCheatNumber == 0) - return; - FILE *f = fopen(file, "wb"); - if(f == NULL) - return; - int version = 1; - fwrite(&version, 1, sizeof(version), f); - int type = 1; - fwrite(&type, 1, sizeof(type), f); - fwrite(&gbCheatNumber, 1, sizeof(gbCheatNumber), f); - fwrite(gbCheatList, 1, sizeof(gbCheatList), f); - fclose(f); -} - -bool gbCheatsLoadCheatList(const char *file) -{ - gbCheatNumber = 0; - - gbCheatUpdateMap(); - - int count = 0; - - FILE *f = fopen(file, "rb"); - - if(f == NULL) - return false; - - int version = 0; - - if(fread(&version, 1, sizeof(version), f) != sizeof(version)) { - fclose(f); - return false; - } - - if(version != 1) { - systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION, - N_("Unsupported cheat list version %d"), version); - fclose(f); - return false; - } - - int type = 0; - if(fread(&type, 1, sizeof(type), f) != sizeof(type)) { - fclose(f); - return false; - } - - if(type != 1) { - systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE, - N_("Unsupported cheat list type %d"), type); - fclose(f); - return false; - } - - if(fread(&count, 1, sizeof(count), f) != sizeof(count)) { - fclose(f); - return false; - } - - if(fread(gbCheatList, 1, sizeof(gbCheatList), f) != sizeof(gbCheatList)) { - fclose(f); - return false; - } - - gbCheatNumber = count; - gbCheatUpdateMap(); - - return true; -} - -bool gbVerifyGsCode(const char *code) -{ - size_t len = strlen(code); - - if(len == 0) - return true; - - if(len != 8) - return false; - - for(int i = 0; i < 8; i++) - if(!GBCHEAT_IS_HEX(code[i])) - return false; - - int address = GBCHEAT_HEX_VALUE(code[6]) << 12 | - GBCHEAT_HEX_VALUE(code[7]) << 8 | - GBCHEAT_HEX_VALUE(code[4]) << 4 | - GBCHEAT_HEX_VALUE(code[5]); - - return true; -} - -bool gbAddGsCheat(const char *code, const char *desc) -{ - if(gbCheatNumber > 99) { - systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, - N_("Maximum number of cheats reached.")); - return false; - } - - if(!gbVerifyGsCode(code)) { - systemMessage(MSG_INVALID_GAMESHARK_CODE, - N_("Invalid GameShark code: %s"), code); - return false; - } - - int i = gbCheatNumber; - - strcpy(gbCheatList[i].cheatCode, code); - strcpy(gbCheatList[i].cheatDesc, desc); - - gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 | - GBCHEAT_HEX_VALUE(code[1]); - - gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 | - GBCHEAT_HEX_VALUE(code[3]); - - gbCheatList[i].address = GBCHEAT_HEX_VALUE(code[6]) << 12 | - GBCHEAT_HEX_VALUE(code[7]) << 8 | - GBCHEAT_HEX_VALUE(code[4]) << 4 | - GBCHEAT_HEX_VALUE(code[5]); - - gbCheatList[i].compare = 0; - - gbCheatList[i].enabled = true; - - int gsCode = gbCheatList[i].code; - - if ((gsCode !=1) && ((gsCode & 0xF0) !=0x80) && ((gsCode & 0xF0) !=0x90) && - ((gsCode & 0xF0) !=0xA0) && ((gsCode) !=0xF0) && ((gsCode) !=0xF1)) - systemMessage(MSG_WRONG_GAMESHARK_CODE, - N_("Wrong GameShark code type : %s"), code); - else if (((gsCode & 0xF0) ==0xA0) || ((gsCode) ==0xF0) || ((gsCode) ==0xF1)) - systemMessage(MSG_UNSUPPORTED_GAMESHARK_CODE, - N_("Unsupported GameShark code type : %s"), code); - - gbCheatNumber++; - - return true; -} - -bool gbVerifyGgCode(const char *code) -{ - size_t len = strlen(code); - - if(len != 11 && - len != 7 && - len != 6 && - len != 0) - return false; - - if(len == 0) - return true; - - if(!GBCHEAT_IS_HEX(code[0])) - return false; - if(!GBCHEAT_IS_HEX(code[1])) - return false; - if(!GBCHEAT_IS_HEX(code[2])) - return false; - if(code[3] != '-') - return false; - if(!GBCHEAT_IS_HEX(code[4])) - return false; - if(!GBCHEAT_IS_HEX(code[5])) - return false; - if(!GBCHEAT_IS_HEX(code[6])) - return false; - if(code[7] != 0) { - if(code[7] != '-') - return false; - if(code[8] != 0) { - if(!GBCHEAT_IS_HEX(code[8])) - return false; - if(!GBCHEAT_IS_HEX(code[9])) - return false; - if(!GBCHEAT_IS_HEX(code[10])) - return false; - } - } - - // int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) + - // GBCHEAT_HEX_VALUE(code[1]); - - int address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + - (GBCHEAT_HEX_VALUE(code[4]) << 4) + - (GBCHEAT_HEX_VALUE(code[5])) + - ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12); - - if(address >= 0x8000 && address <= 0x9fff) - return false; - - if(address >= 0xc000) - return false; - - if(code[7] == 0 || code[8] == '0') - return true; - - int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + - (GBCHEAT_HEX_VALUE(code[10])); - compare = compare ^ 0xff; - compare = (compare >> 2) | ( (compare << 6) & 0xc0); - compare ^= 0x45; - - int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9])); - - if(cloak >=1 && cloak <= 7) - return false; - - return true; -} - -bool gbAddGgCheat(const char *code, const char *desc) -{ - if(gbCheatNumber > 99) { - systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, - N_("Maximum number of cheats reached.")); - return false; - } - - if(!gbVerifyGgCode(code)) { - systemMessage(MSG_INVALID_GAMEGENIE_CODE, - N_("Invalid GameGenie code: %s"), code); - return false; - } - - int i = gbCheatNumber; - - size_t len = strlen(code); - - strcpy(gbCheatList[i].cheatCode, code); - strcpy(gbCheatList[i].cheatDesc, desc); - - gbCheatList[i].code = 0x101; - gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) + - GBCHEAT_HEX_VALUE(code[1]); - - gbCheatList[i].address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + - (GBCHEAT_HEX_VALUE(code[4]) << 4) + - (GBCHEAT_HEX_VALUE(code[5])) + - ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12); - - gbCheatList[i].compare = 0; - - if(len != 7 && len != 8) { - - int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + - (GBCHEAT_HEX_VALUE(code[10])); - compare = compare ^ 0xff; - compare = (compare >> 2) | ( (compare << 6) & 0xc0); - compare ^= 0x45; - - gbCheatList[i].compare = compare; - //gbCheatList[i].code = 0; - gbCheatList[i].code = 0x100; // fix for compare value - - } - - - gbCheatList[i].enabled = true; - - gbCheatMap[gbCheatList[i].address] = true; - - gbCheatNumber++; - - return true; -} - -void gbCheatRemove(int i) -{ - if(i < 0 || i >= gbCheatNumber) { - systemMessage(MSG_INVALID_CHEAT_TO_REMOVE, - N_("Invalid cheat to remove %d"), i); - return; - } - - if((i+1) < gbCheatNumber) { - memcpy(&gbCheatList[i], &gbCheatList[i+1], sizeof(gbCheat)* - (gbCheatNumber-i-1)); - } - - gbCheatNumber--; - - gbCheatUpdateMap(); -} - -void gbCheatRemoveAll() -{ - gbCheatNumber = 0; - gbCheatUpdateMap(); -} - -void gbCheatEnable(int i) -{ - if(i >=0 && i < gbCheatNumber) { - if(!gbCheatList[i].enabled) { - gbCheatList[i].enabled = true; - gbCheatUpdateMap(); - } - } -} - -void gbCheatDisable(int i) -{ - if(i >=0 && i < gbCheatNumber) { - if(gbCheatList[i].enabled) { - gbCheatList[i].enabled = false; - gbCheatUpdateMap(); - } - } -} - -bool gbCheatReadGSCodeFile(const char *fileName) -{ - FILE *file = fopen(fileName, "rb"); - - if(!file) { - systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); - return false; - } - - fseek(file, 0x18, SEEK_SET); - int count = 0; - fread(&count, 1, 2, file); - int dummy = 0; - gbCheatRemoveAll(); - char desc[13]; - char code[9]; - int i; - for(i = 0; i < count; i++) { - fread(&dummy, 1, 2, file); - fread(desc, 1, 12, file); - desc[12] = 0; - fread(code, 1, 8, file); - code[8] = 0; - gbAddGsCheat(code, desc); - } - - for(i = 0; i < gbCheatNumber; i++) - gbCheatDisable(i); - - fclose(file); - return true; -} - -// Used to emulated GG codes -u8 gbCheatRead(u16 address) -{ - if(!cheatsEnabled) - return gbMemoryMap[address>>12][address & 0xFFF]; - - for(int i = 0; i < gbCheatNumber; i++) { - if(gbCheatList[i].enabled && gbCheatList[i].address == address) { - switch(gbCheatList[i].code) { - case 0x100: // GameGenie support - if(gbMemoryMap[address>>12][address&0xFFF] == gbCheatList[i].compare) - return gbCheatList[i].value; - break; - case 0x101: // GameGenie 6 digits code support - return gbCheatList[i].value; - break; - } - } - } - return gbMemoryMap[address>>12][address&0xFFF]; -} - - -// Used to emulate GS codes. -void gbCheatWrite(bool reboot) -{ - if(cheatsEnabled) - { - u16 address = 0; - - if (gbNextCheat >= gbCheatNumber) - gbNextCheat = 0; - - for(int i = gbNextCheat; i < gbCheatNumber; i++) { - if(gbCheatList[i].enabled) { - address = gbCheatList[i].address; - if ((!reboot) && (address >= 0x8000) && !((address>=0xA000) && (address<0xC000))) - { // These codes are executed one per one, at each Vblank - switch(gbCheatList[i].code) { - case 0x01: - gbWriteMemory(address, gbCheatList[i].value); - gbNextCheat = i+1; - return; - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9A: - case 0x9B: - case 0x9C: - case 0x9D: - case 0x9E: - case 0x9F: - int oldbank = gbMemory[0xff70]; - gbWriteMemory(0xff70, gbCheatList[i].code & 0xf); - gbWriteMemory(address, gbCheatList[i].value); - gbWriteMemory(0xff70, oldbank); - gbNextCheat = i+1; - return; - } - } - else // These codes are only executed when the game is booted - { - switch(gbCheatList[i].code & 0xF0) { - case 0x80: - gbWriteMemory(0x0000, 0x0A); - gbWriteMemory(0x4000, gbCheatList[i].value & 0xF); - gbWriteMemory(address, gbCheatList[i].value); - gbNextCheat = i+1; - return; - } - } - } - } - } -} diff --git a/src/dmg/gbCheats.h b/src/dmg/gbCheats.h deleted file mode 100644 index 42e53c6f..00000000 --- a/src/dmg/gbCheats.h +++ /dev/null @@ -1,62 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef __VBA_GB_GBCHEATS_H -#define __VBA_GB_GBCHEATS_H - -#include "../System.h" - -struct gbXxCheat { - char cheatDesc[100]; - char cheatCode[20]; -}; - -struct gbCheat { - char cheatCode[20]; - char cheatDesc[32]; - u16 address; - int code; - u8 compare; - u8 value; - bool enabled; -}; - -void gbCheatsSaveGame(gzFile); -void gbCheatsReadGame(gzFile, int); -void gbCheatsSaveCheatList(const char *); -bool gbCheatsLoadCheatList(const char *); -bool gbCheatReadGSCodeFile(const char *); - -bool gbAddGsCheat(const char *, const char*); -bool gbAddGgCheat(const char *, const char*); -void gbCheatRemove(int); -void gbCheatRemoveAll(); -void gbCheatEnable(int); -void gbCheatDisable(int); -u8 gbCheatRead(u16); -void gbCheatWrite(bool); -bool gbVerifyGsCode(const char *code); -bool gbVerifyGgCode(const char *code); - - -extern int gbCheatNumber; -extern gbCheat gbCheatList[100]; -extern bool gbCheatMap[0x10000]; -#endif - diff --git a/src/dmg/gbCodes.h b/src/dmg/gbCodes.h deleted file mode 100644 index 5cbae965..00000000 --- a/src/dmg/gbCodes.h +++ /dev/null @@ -1,1460 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - case 0x00: - // NOP - break; - case 0x01: - // LD BC, NNNN - BC.B.B0=gbReadOpcode(PC.W++); - BC.B.B1=gbReadOpcode(PC.W++); - break; - case 0x02: - // LD (BC),A - gbWriteMemory(BC.W,AF.B.B1); - break; - case 0x03: - // INC BC - BC.W++; - break; - case 0x04: - // INC B - BC.B.B1++; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B1]| (BC.B.B1&0x0F? 0:H_FLAG); - break; - case 0x05: - // DEC B - BC.B.B1--; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B1]| - ((BC.B.B1&0x0F)==0x0F? H_FLAG:0); - break; - case 0x06: - // LD B, NN - BC.B.B1=gbReadOpcode(PC.W++); - break; - case 0x07: - // RLCA - tempValue=AF.B.B1&0x80? C_FLAG:0; - AF.B.B1=(AF.B.B1<<1)|(AF.B.B1>>7); - AF.B.B0=tempValue; - break; - case 0x08: - // LD (NNNN), SP - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - gbWriteMemory(tempRegister.W++,SP.B.B0); - gbWriteMemory(tempRegister.W,SP.B.B1); - break; - case 0x09: - // ADD HL,BC - tempRegister.W=(HL.W+BC.W)&0xFFFF; - AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^BC.W^tempRegister.W)&0x1000? H_FLAG:0)| - (((long)HL.W+(long)BC.W)&0x10000? C_FLAG:0); - HL.W=tempRegister.W; - break; - case 0x0a: - // LD A,(BC) - AF.B.B1=gbReadMemory(BC.W); - break; - case 0x0b: - // DEC BC - BC.W--; - break; - case 0x0c: - // INC C - BC.B.B0++; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B0]| (BC.B.B0&0x0F? 0:H_FLAG); - break; - case 0x0d: - // DEC C - BC.B.B0--; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B0]| - ((BC.B.B0&0x0F)==0x0F? H_FLAG:0); - break; - case 0x0e: - // LD C, NN - BC.B.B0=gbReadOpcode(PC.W++); - break; - case 0x0f: - // RRCA - tempValue=AF.B.B1&0x01; - AF.B.B1=(AF.B.B1>>1)|(tempValue? 0x80:0); - AF.B.B0=(tempValue<<4); - break; - case 0x10: - // STOP - opcode = gbReadOpcode(PC.W++); - if(gbCgbMode) { - if(gbMemory[0xff4d] & 1) { - - gbSpeedSwitch(); - //clockTicks += 228*144-(gbSpeed ? 62 : 63); - - if(gbSpeed == 0) - gbMemory[0xff4d] = 0x00; - else - gbMemory[0xff4d] = 0x80; - } - } - break; - case 0x11: - // LD DE, NNNN - DE.B.B0=gbReadOpcode(PC.W++); - DE.B.B1=gbReadOpcode(PC.W++); - break; - case 0x12: - // LD (DE),A - gbWriteMemory(DE.W,AF.B.B1); - break; - case 0x13: - // INC DE - DE.W++; - break; - case 0x14: - // INC D - DE.B.B1++; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B1]| (DE.B.B1&0x0F? 0:H_FLAG); - break; - case 0x15: - // DEC D - DE.B.B1--; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B1]| - ((DE.B.B1&0x0F)==0x0F? H_FLAG:0); - break; - case 0x16: - // LD D,NN - DE.B.B1=gbReadOpcode(PC.W++); - break; - case 0x17: - // RLA - tempValue=AF.B.B1&0x80? C_FLAG:0; - AF.B.B1=(AF.B.B1<<1)|((AF.B.B0&C_FLAG)>>4); - AF.B.B0=tempValue; - break; - case 0x18: - // JR NN - PC.W+=(s8)gbReadOpcode(PC.W)+1; - break; - case 0x19: - // ADD HL,DE - tempRegister.W=(HL.W+DE.W)&0xFFFF; - AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^DE.W^tempRegister.W)&0x1000? H_FLAG:0)| - (((long)HL.W+(long)DE.W)&0x10000? C_FLAG:0); - HL.W=tempRegister.W; - break; - case 0x1a: - // LD A,(DE) - AF.B.B1=gbReadMemory(DE.W); - break; - case 0x1b: - // DEC DE - DE.W--; - break; - case 0x1c: - // INC E - DE.B.B0++; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B0]| (DE.B.B0&0x0F? 0:H_FLAG); - break; - case 0x1d: - // DEC E - DE.B.B0--; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B0]| - ((DE.B.B0&0x0F)==0x0F? H_FLAG:0); - break; - case 0x1e: - // LD E,NN - DE.B.B0=gbReadOpcode(PC.W++); - break; - case 0x1f: - // RRA - tempValue=AF.B.B1&0x01; - AF.B.B1=(AF.B.B1>>1)|(AF.B.B0&C_FLAG? 0x80:0); - AF.B.B0=(tempValue<<4); - break; - case 0x20: - // JR NZ,NN - if(AF.B.B0&Z_FLAG) - PC.W++; - else { - PC.W+=(s8)gbReadOpcode(PC.W)+1; - clockTicks++; - } - break; - case 0x21: - // LD HL,NNNN - HL.B.B0=gbReadOpcode(PC.W++); - HL.B.B1=gbReadOpcode(PC.W++); - break; - case 0x22: - // LDI (HL),A - gbWriteMemory(HL.W++,AF.B.B1); - break; - case 0x23: - // INC HL - HL.W++; - break; - case 0x24: - // INC H - HL.B.B1++; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B1]| (HL.B.B1&0x0F? 0:H_FLAG); - break; - case 0x25: - // DEC H - HL.B.B1--; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B1]| - ((HL.B.B1&0x0F)==0x0F? H_FLAG:0); - break; - case 0x26: - // LD H,NN - HL.B.B1=gbReadOpcode(PC.W++); - break; - case 0x27: - // DAA - tempRegister.W=AF.B.B1; - if(AF.B.B0&C_FLAG) tempRegister.W|=256; - if(AF.B.B0&H_FLAG) tempRegister.W|=512; - if(AF.B.B0&N_FLAG) tempRegister.W|=1024; - AF.W=DAATable[tempRegister.W]; - break; - case 0x28: - // JR Z,NN - if(AF.B.B0&Z_FLAG) { - PC.W+=(s8)gbReadOpcode(PC.W)+1; - clockTicks++; - } else - PC.W++; - break; - case 0x29: - // ADD HL,HL - tempRegister.W=(HL.W+HL.W)&0xFFFF; AF.B.B0= (AF.B.B0 & Z_FLAG)| - ((HL.W^HL.W^tempRegister.W)&0x1000? H_FLAG:0)| - (((long)HL.W+(long)HL.W)&0x10000? C_FLAG:0); - HL.W=tempRegister.W; - break; - case 0x2a: - // LDI A,(HL) - AF.B.B1 = gbReadMemory(HL.W++); - break; - case 0x2b: - // DEC HL - HL.W--; - break; - case 0x2c: - // INC L - HL.B.B0++; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B0]| (HL.B.B0&0x0F? 0:H_FLAG); - break; - case 0x2d: - // DEC L - HL.B.B0--; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B0]| - ((HL.B.B0&0x0F)==0x0F? H_FLAG:0); - break; - case 0x2e: - // LD L,NN - HL.B.B0=gbReadOpcode(PC.W++); - break; - case 0x2f: - // CPL - AF.B.B1 ^= 255; - AF.B.B0|=N_FLAG|H_FLAG; - break; - case 0x30: - // JR NC,NN - if(AF.B.B0&C_FLAG) - PC.W++; - else { - PC.W+=(s8)gbReadOpcode(PC.W)+1; - clockTicks++; - } - break; - case 0x31: - // LD SP,NNNN - SP.B.B0=gbReadOpcode(PC.W++); - SP.B.B1=gbReadOpcode(PC.W++); - break; - case 0x32: - // LDD (HL),A - gbWriteMemory(HL.W--,AF.B.B1); - break; - case 0x33: - // INC SP - SP.W++; - break; - case 0x34: - // INC (HL) - tempValue=gbReadMemory(HL.W)+1; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[tempValue]| (tempValue&0x0F? 0:H_FLAG); - gbWriteMemory(HL.W,tempValue); - break; - case 0x35: - // DEC (HL) - tempValue=gbReadMemory(HL.W)-1; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[tempValue]| - ((tempValue&0x0F)==0x0F? H_FLAG:0);gbWriteMemory(HL.W,tempValue); - break; - case 0x36: - // LD (HL),NN - gbWriteMemory(HL.W,gbReadOpcode(PC.W++)); - break; - case 0x37: - // SCF - AF.B.B0 = AF.B.B0 & Z_FLAG | C_FLAG; - break; -case 0x38: - // JR C,NN - if(AF.B.B0&C_FLAG) { - PC.W+=(s8)gbReadOpcode(PC.W)+1; - clockTicks ++; - } else - PC.W++; - break; - case 0x39: - // ADD HL,SP - tempRegister.W=(HL.W+SP.W)&0xFFFF; - AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^SP.W^tempRegister.W)&0x1000? H_FLAG:0)| - (((long)HL.W+(long)SP.W)&0x10000? C_FLAG:0); - HL.W=tempRegister.W; - break; - case 0x3a: - // LDD A,(HL) - AF.B.B1 = gbReadMemory(HL.W--); - break; - case 0x3b: - // DEC SP - SP.W--; - break; - case 0x3c: - // INC A - AF.B.B1++; - AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[AF.B.B1]| (AF.B.B1&0x0F? 0:H_FLAG); - break; - case 0x3d: - // DEC A - AF.B.B1--; - AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[AF.B.B1]| - ((AF.B.B1&0x0F)==0x0F? H_FLAG:0); - break; - case 0x3e: - // LD A,NN - AF.B.B1=gbReadOpcode(PC.W++); - break; - case 0x3f: - // CCF - AF.B.B0^=C_FLAG;AF.B.B0&=~(N_FLAG|H_FLAG); - break; - case 0x40: - // LD B,B - BC.B.B1=BC.B.B1; - break; - case 0x41: - // LD B,C - BC.B.B1=BC.B.B0; - break; - case 0x42: - // LD B,D - BC.B.B1=DE.B.B1; - break; - case 0x43: - // LD B,E - BC.B.B1=DE.B.B0; - break; - case 0x44: - // LD B,H - BC.B.B1=HL.B.B1; - break; - case 0x45: - // LD B,L - BC.B.B1=HL.B.B0; - break; - case 0x46: - // LD B,(HL) - BC.B.B1=gbReadMemory(HL.W); - break; - case 0x47: - // LD B,A - BC.B.B1=AF.B.B1; - break; - case 0x48: - // LD C,B - BC.B.B0=BC.B.B1; - break; - case 0x49: - // LD C,C - BC.B.B0=BC.B.B0; - break; - case 0x4a: - // LD C,D - BC.B.B0=DE.B.B1; - break; - case 0x4b: - // LD C,E - BC.B.B0=DE.B.B0; - break; - case 0x4c: - // LD C,H - BC.B.B0=HL.B.B1; - break; - case 0x4d: - // LD C,L - BC.B.B0=HL.B.B0; - break; - case 0x4e: - // LD C,(HL) - BC.B.B0=gbReadMemory(HL.W); - break; - case 0x4f: - // LD C,A - BC.B.B0=AF.B.B1; - break; - case 0x50: - // LD D,B - DE.B.B1=BC.B.B1; - break; - case 0x51: - // LD D,C - DE.B.B1=BC.B.B0; - break; - case 0x52: - // LD D,D - DE.B.B1=DE.B.B1; - break; - case 0x53: - // LD D,E - DE.B.B1=DE.B.B0; - break; - case 0x54: - // LD D,H - DE.B.B1=HL.B.B1; - break; - case 0x55: - // LD D,L - DE.B.B1=HL.B.B0; - break; - case 0x56: - // LD D,(HL) - DE.B.B1=gbReadMemory(HL.W); - break; - case 0x57: - // LD D,A - DE.B.B1=AF.B.B1; - break; - case 0x58: - // LD E,B - DE.B.B0=BC.B.B1; - break; - case 0x59: - // LD E,C - DE.B.B0=BC.B.B0; - break; - case 0x5a: - // LD E,D - DE.B.B0=DE.B.B1; - break; - case 0x5b: - // LD E,E - DE.B.B0=DE.B.B0; - break; - case 0x5c: - // LD E,H - DE.B.B0=HL.B.B1; - break; - case 0x5d: - // LD E,L - DE.B.B0=HL.B.B0; - break; - case 0x5e: - // LD E,(HL) - DE.B.B0=gbReadMemory(HL.W); - break; - case 0x5f: - // LD E,A - DE.B.B0=AF.B.B1; - break; - case 0x60: - // LD H,B - HL.B.B1=BC.B.B1; - break; - case 0x61: - // LD H,C - HL.B.B1=BC.B.B0; - break; - case 0x62: - // LD H,D - HL.B.B1=DE.B.B1; - break; - case 0x63: - // LD H,E - HL.B.B1=DE.B.B0; - break; - case 0x64: - // LD H,H - HL.B.B1=HL.B.B1; - break; - case 0x65: - // LD H,L - HL.B.B1=HL.B.B0; - break; - case 0x66: - // LD H,(HL) - HL.B.B1=gbReadMemory(HL.W); - break; - case 0x67: - // LD H,A - HL.B.B1=AF.B.B1; - break; - case 0x68: - // LD L,B - HL.B.B0=BC.B.B1; - break; - case 0x69: - // LD L,C - HL.B.B0=BC.B.B0; - break; - case 0x6a: - // LD L,D - HL.B.B0=DE.B.B1; - break; - case 0x6b: - // LD L,E - HL.B.B0=DE.B.B0; - break; - case 0x6c: - // LD L,H - HL.B.B0=HL.B.B1; - break; - case 0x6d: - // LD L,L - HL.B.B0=HL.B.B0; - break; - case 0x6e: - // LD L,(HL) - HL.B.B0=gbReadMemory(HL.W); - break; - case 0x6f: - // LD L,A - HL.B.B0=AF.B.B1; - break; - case 0x70: - // LD (HL),B - gbWriteMemory(HL.W,BC.B.B1); - break; - case 0x71: - // LD (HL),C - gbWriteMemory(HL.W,BC.B.B0); - break; - case 0x72: - // LD (HL),D - gbWriteMemory(HL.W,DE.B.B1); - break; - case 0x73: - // LD (HL),E - gbWriteMemory(HL.W,DE.B.B0); - break; - case 0x74: - // LD (HL),H - gbWriteMemory(HL.W,HL.B.B1); - break; - case 0x75: - // LD (HL),L - gbWriteMemory(HL.W,HL.B.B0); - break; - case 0x76: - // HALT - // If an EI is pending, the interrupts are triggered before Halt state !! - // Fix Torpedo Range's intro. - if (IFF & 0x40) - { - IFF &= ~0x70; - IFF |=1; - PC.W--; - } - else - { - // if (IE & IF) and interrupts are disabeld, - // Halt is cancelled. - if ((register_IE & register_IF & 0x1f) && !(IFF & 1)) - { - IFF|=2; - } - else - IFF |= 0x80; - } - break; - case 0x77: - // LD (HL),A - gbWriteMemory(HL.W,AF.B.B1); - break; - case 0x78: - // LD A,B - AF.B.B1=BC.B.B1; - break; - case 0x79: - // LD A,C - AF.B.B1=BC.B.B0; - break; - case 0x7a: - // LD A,D - AF.B.B1=DE.B.B1; - break; - case 0x7b: - // LD A,E - AF.B.B1=DE.B.B0; - break; - case 0x7c: - // LD A,H - AF.B.B1=HL.B.B1; - break; - case 0x7d: - // LD A,L - AF.B.B1=HL.B.B0; - break; - case 0x7e: - // LD A,(HL) - AF.B.B1=gbReadMemory(HL.W); - break; - case 0x7f: - // LD A,A - AF.B.B1=AF.B.B1; - break; - case 0x80: - // ADD B - tempRegister.W=AF.B.B1+BC.B.B1; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x81: - // ADD C - tempRegister.W=AF.B.B1+BC.B.B0; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x82: - // ADD D - tempRegister.W=AF.B.B1+DE.B.B1; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x83: - // ADD E - tempRegister.W=AF.B.B1+DE.B.B0; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x84: - // ADD H - tempRegister.W=AF.B.B1+HL.B.B1; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x85: - // ADD L - tempRegister.W=AF.B.B1+HL.B.B0; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x86: - // ADD (HL) - tempValue=gbReadMemory(HL.W); - tempRegister.W=AF.B.B1+tempValue; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x87: - // ADD A - tempRegister.W=AF.B.B1+AF.B.B1; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x88: - // ADC B: - tempRegister.W=AF.B.B1+BC.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x89: - // ADC C - tempRegister.W=AF.B.B1+BC.B.B0+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x8a: - // ADC D - tempRegister.W=AF.B.B1+DE.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x8b: - // ADC E - tempRegister.W=AF.B.B1+DE.B.B0+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x8c: - // ADC H - tempRegister.W=AF.B.B1+HL.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); AF.B.B1=tempRegister.B.B0; - break; - case 0x8d: - // ADC L - tempRegister.W=AF.B.B1+HL.B.B0+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x8e: - // ADC (HL) - tempValue=gbReadMemory(HL.W); - tempRegister.W=AF.B.B1+tempValue+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x8f: - // ADC A - tempRegister.W=AF.B.B1+AF.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x90: - // SUB B - tempRegister.W=AF.B.B1-BC.B.B1; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x91: - // SUB C - tempRegister.W=AF.B.B1-BC.B.B0; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x92: - // SUB D - tempRegister.W=AF.B.B1-DE.B.B1; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x93: - // SUB E - tempRegister.W=AF.B.B1-DE.B.B0; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x94: - // SUB H - tempRegister.W=AF.B.B1-HL.B.B1; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x95: - // SUB L - tempRegister.W=AF.B.B1-HL.B.B0; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x96: - // SUB (HL) - tempValue=gbReadMemory(HL.W); - tempRegister.W=AF.B.B1-tempValue; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x97: - // SUB A - AF.B.B1=0; - AF.B.B0=N_FLAG|Z_FLAG; - break; - case 0x98: - // SBC B - tempRegister.W=AF.B.B1-BC.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x99: - // SBC C - tempRegister.W=AF.B.B1-BC.B.B0-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x9a: - // SBC D - tempRegister.W=AF.B.B1-DE.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x9b: - // SBC E - tempRegister.W=AF.B.B1-DE.B.B0-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x9c: - // SBC H - tempRegister.W=AF.B.B1-HL.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x9d: - // SBC L - tempRegister.W=AF.B.B1-HL.B.B0-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x9e: - // SBC (HL) - tempValue=gbReadMemory(HL.W); - tempRegister.W=AF.B.B1-tempValue-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0x9f: - // SBC A - tempRegister.W=AF.B.B1-AF.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0xa0: - // AND B - AF.B.B1&=BC.B.B1; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa1: - // AND C - AF.B.B1&=BC.B.B0; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa2: - // AND_D - AF.B.B1&=DE.B.B1; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa3: - // AND E - AF.B.B1&=DE.B.B0; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa4: - // AND H - AF.B.B1&=HL.B.B1; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa5: - // AND L - AF.B.B1&=HL.B.B0; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa6: - // AND (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B1&=tempValue; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa7: - // AND A - AF.B.B1&=AF.B.B1; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xa8: - // XOR B - AF.B.B1^=BC.B.B1; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xa9: - // XOR C - AF.B.B1^=BC.B.B0; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xaa: - // XOR D - AF.B.B1^=DE.B.B1; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xab: - // XOR E - AF.B.B1^=DE.B.B0; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xac: - // XOR H - AF.B.B1^=HL.B.B1; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xad: - // XOR L - AF.B.B1^=HL.B.B0; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xae: - // XOR (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B1^=tempValue; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xaf: - // XOR A - AF.B.B1=0; - AF.B.B0=Z_FLAG; - break; - case 0xb0: - // OR B - AF.B.B1|=BC.B.B1; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb1: - // OR C - AF.B.B1|=BC.B.B0; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb2: - // OR D - AF.B.B1|=DE.B.B1; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb3: - // OR E - AF.B.B1|=DE.B.B0; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb4: - // OR H - AF.B.B1|=HL.B.B1; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb5: - // OR L - AF.B.B1|=HL.B.B0; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb6: - // OR (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B1|=tempValue; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb7: - // OR A - AF.B.B1|=AF.B.B1; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xb8: - // CP B: - tempRegister.W=AF.B.B1-BC.B.B1; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xb9: - // CP C - tempRegister.W=AF.B.B1-BC.B.B0; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xba: - // CP D - tempRegister.W=AF.B.B1-DE.B.B1; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xbb: - // CP E - tempRegister.W=AF.B.B1-DE.B.B0; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xbc: - // CP H - tempRegister.W=AF.B.B1-HL.B.B1; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xbd: - // CP L - tempRegister.W=AF.B.B1-HL.B.B0; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xbe: - // CP (HL) - tempValue=gbReadMemory(HL.W); - tempRegister.W=AF.B.B1-tempValue; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xbf: - // CP A - AF.B.B0=N_FLAG|Z_FLAG; - break; - case 0xc0: - // RET NZ - if(!(AF.B.B0&Z_FLAG)) { - PC.B.B0=gbReadMemory(SP.W++); - PC.B.B1=gbReadMemory(SP.W++); - clockTicks += 3; - } - break; - case 0xc1: - // POP BC - BC.B.B0=gbReadMemory(SP.W++); - BC.B.B1=gbReadMemory(SP.W++); - break; - case 0xc2: - // JP NZ,NNNN - if(AF.B.B0&Z_FLAG) - PC.W+=2; - else { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W); - PC.W=tempRegister.W; - clockTicks++; - } - break; - case 0xc3: - // JP NNNN - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W); - PC.W=tempRegister.W; - break; - case 0xc4: - // CALL NZ,NNNN - if(AF.B.B0&Z_FLAG) - PC.W+=2; - else { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=tempRegister.W; - clockTicks += 3; - } - break; - case 0xc5: - // PUSH BC - gbWriteMemory(--SP.W,BC.B.B1); - gbWriteMemory(--SP.W,BC.B.B0); - break; - case 0xc6: - // ADD NN - tempValue=gbReadOpcode(PC.W++); - tempRegister.W=AF.B.B1+tempValue; - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10 ? H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0xc7: - // RST 00 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0000; - break; - case 0xc8: - // RET Z - if(AF.B.B0&Z_FLAG) { - PC.B.B0=gbReadMemory(SP.W++); - PC.B.B1=gbReadMemory(SP.W++); - clockTicks += 3; - } - break; - case 0xc9: - // RET - PC.B.B0=gbReadMemory(SP.W++); - PC.B.B1=gbReadMemory(SP.W++); - break; - case 0xca: - // JP Z,NNNN - if(AF.B.B0&Z_FLAG) { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W); - PC.W=tempRegister.W; - clockTicks++; - } else - PC.W+=2; - break; - // CB done outside - case 0xcc: - // CALL Z,NNNN - if(AF.B.B0&Z_FLAG) { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=tempRegister.W; - clockTicks += 3; - } else - PC.W+=2; - break; - case 0xcd: - // CALL NNNN - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=tempRegister.W; - break; - case 0xce: - // ADC NN - tempValue=gbReadOpcode(PC.W++); - tempRegister.W=AF.B.B1+tempValue+(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0xcf: - // RST 08 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0008; - break; - case 0xd0: - // RET NC - if(!(AF.B.B0&C_FLAG)) { - PC.B.B0=gbReadMemory(SP.W++); - PC.B.B1=gbReadMemory(SP.W++); - clockTicks += 3; - } - break; - case 0xd1: - // POP DE - DE.B.B0=gbReadMemory(SP.W++); - DE.B.B1=gbReadMemory(SP.W++); - break; - case 0xd2: - // JP NC,NNNN - if(AF.B.B0&C_FLAG) - PC.W+=2; - else { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W); - PC.W=tempRegister.W; - clockTicks++; - } - break; - // D3 illegal - case 0xd3: - PC.W--; - IFF = 0; - break; - case 0xd4: - // CALL NC,NNNN - if(AF.B.B0&C_FLAG) - PC.W+=2; - else { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=tempRegister.W; - clockTicks += 3; - } - break; - case 0xd5: - // PUSH DE - gbWriteMemory(--SP.W,DE.B.B1); - gbWriteMemory(--SP.W,DE.B.B0); - break; - case 0xd6: - // SUB NN - tempValue=gbReadOpcode(PC.W++); - tempRegister.W=AF.B.B1-tempValue; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0xd7: - // RST 10 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0010; - break; - case 0xd8: - // RET C - if(AF.B.B0&C_FLAG) { - PC.B.B0=gbReadMemory(SP.W++); - PC.B.B1=gbReadMemory(SP.W++); - clockTicks += 3; - } - break; - case 0xd9: - // RETI - PC.B.B0=gbReadMemory(SP.W++); - PC.B.B1=gbReadMemory(SP.W++); - IFF |= 0x01; - break; - case 0xda: - // JP C,NNNN - if(AF.B.B0&C_FLAG) { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W); - PC.W=tempRegister.W; - clockTicks++; - } else - PC.W+=2; - break; - // DB illegal - case 0xdb: - PC.W--; - IFF = 0; - break; - case 0xdc: - // CALL C,NNNN - if(AF.B.B0&C_FLAG) { - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=tempRegister.W; - clockTicks += 3; - } else - PC.W+=2; - break; - // DD illegal - case 0xdd: - PC.W--; - IFF = 0; - break; - case 0xde: - // SBC NN - tempValue=gbReadOpcode(PC.W++); - tempRegister.W=AF.B.B1-tempValue-(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - AF.B.B1=tempRegister.B.B0; - break; - case 0xdf: - // RST 18 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0018; - break; - case 0xe0: - // LD (FF00+NN),A - gbWriteMemory(0xff00 + gbReadOpcode(PC.W++),AF.B.B1); - break; - case 0xe1: - // POP HL - HL.B.B0=gbReadMemory(SP.W++); - HL.B.B1=gbReadMemory(SP.W++); - break; - case 0xe2: - // LD (FF00+C),A - gbWriteMemory(0xff00 + BC.B.B0,AF.B.B1); - break; - // E3 illegal - // E4 illegal - case 0xe3: - case 0xe4: - PC.W--; - IFF = 0; - break; - case 0xe5: - // PUSH HL - gbWriteMemory(--SP.W,HL.B.B1); - gbWriteMemory(--SP.W,HL.B.B0); - break; - case 0xe6: - // AND NN - tempValue=gbReadOpcode(PC.W++); - AF.B.B1&=tempValue; - AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; - break; - case 0xe7: - // RST 20 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0020; - break; - case 0xe8: - // ADD SP,NN - offset = (s8)gbReadOpcode(PC.W++); - - if(offset >= 0) { - tempRegister.W = SP.W + offset; - AF.B.B0 = (SP.W > tempRegister.W ? C_FLAG : 0) | - ((SP.W^offset^tempRegister.W)&0x1000? H_FLAG:0); - SP.W = tempRegister.W; - } else { - tempRegister.W = SP.W + offset; - AF.B.B0 = (SP.W < tempRegister.W ? C_FLAG : 0) | - ((SP.W^offset^tempRegister.W)&0x1000?H_FLAG:0); - SP.W = tempRegister.W; - } - break; - case 0xe9: - // LD PC,HL - PC.W=HL.W; - break; - case 0xea: - // LD (NNNN),A - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - gbWriteMemory(tempRegister.W,AF.B.B1); - break; - // EB illegal - // EC illegal - // ED illegal - case 0xeb: - case 0xec: - case 0xed: - PC.W--; - IFF = 0; - break; - case 0xee: - // XOR NN - tempValue=gbReadOpcode(PC.W++); - AF.B.B1^=tempValue; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xef: - // RST 28 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0028; - break; - case 0xf0: - // LD A,(FF00+NN) - AF.B.B1 = gbReadMemory(0xff00+gbReadOpcode(PC.W++)); - break; - case 0xf1: - // POP AF - AF.B.B0=gbReadMemory(SP.W++); - AF.B.B1=gbReadMemory(SP.W++); - break; - case 0xf2: - // LD A,(FF00+C) - AF.B.B1 = gbReadMemory(0xff00+BC.B.B0); - break; - case 0xf3: - // DI - // IFF&=0xFE; - IFF|=0x08; - break; - // F4 illegal - case 0xf4: - PC.W--; - IFF = 0; - break; - case 0xf5: - // PUSH AF - gbWriteMemory(--SP.W,AF.B.B1); - gbWriteMemory(--SP.W,AF.B.B0); - break; - case 0xf6: - // OR NN - tempValue=gbReadOpcode(PC.W++); - AF.B.B1|=tempValue; - AF.B.B0=ZeroTable[AF.B.B1]; - break; - case 0xf7: - // RST 30 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0030; - break; - case 0xf8: - // LD HL,SP+NN - offset = (s8)gbReadOpcode(PC.W++); - if(offset >= 0) { - tempRegister.W = SP.W + offset; - AF.B.B0 = (SP.W > tempRegister.W ? C_FLAG : 0) | - ((SP.W^offset^tempRegister.W)&0x1000? H_FLAG:0); - HL.W = tempRegister.W; - } else { - tempRegister.W = SP.W + offset; - AF.B.B0 = (SP.W < tempRegister.W ? C_FLAG : 0) | - ((SP.W^offset^tempRegister.W)&0x1000?H_FLAG:0); - HL.W = tempRegister.W; - } - break; - case 0xf9: - // LD SP,HL - SP.W=HL.W; - break; - case 0xfa: - // LD A,(NNNN) - tempRegister.B.B0=gbReadOpcode(PC.W++); - tempRegister.B.B1=gbReadOpcode(PC.W++); - AF.B.B1=gbReadMemory(tempRegister.W); - break; - case 0xfb: - // EI - if (!(IFF & 0x30)) - // If an EI is executed right before HALT, - // the interrupts are triggered before the Halt state !! - // Fix Torpedo Range Intro. - // IFF |= 0x10 : 1 ticks before the EI enables the interrupts - // IFF |= 0x40 : marks that an EI is being executed. - IFF|=0x50; - break; - // FC illegal (FC = breakpoint) - case 0xfc: - breakpoint = true; - break; - // FD illegal - case 0xfd: - PC.W--; - IFF = 0; - break; - case 0xfe: - // CP NN - tempValue=gbReadOpcode(PC.W++); - tempRegister.W=AF.B.B1-tempValue; - AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| - ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); - break; - case 0xff: - // RST 38 - gbWriteMemory(--SP.W,PC.B.B1); - gbWriteMemory(--SP.W,PC.B.B0); - PC.W=0x0038; - break; - default: - if (gbSystemMessage == false) - { - systemMessage(0, N_("Unknown opcode %02x at %04x"), - gbReadOpcode(PC.W-1),PC.W-1); - gbSystemMessage =true; - } - return; diff --git a/src/dmg/gbCodesCB.h b/src/dmg/gbCodesCB.h deleted file mode 100644 index 5a09d8d5..00000000 --- a/src/dmg/gbCodesCB.h +++ /dev/null @@ -1,1291 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - case 0x00: - // RLC B - AF.B.B0 = (BC.B.B1 & 0x80)?C_FLAG:0; - BC.B.B1 = (BC.B.B1<<1) | (BC.B.B1>>7); - AF.B.B0 |= ZeroTable[BC.B.B1]; - break; - case 0x01: - // RLC C - AF.B.B0 = (BC.B.B0 & 0x80)?C_FLAG:0; - BC.B.B0 = (BC.B.B0<<1) | (BC.B.B0>>7); - AF.B.B0 |= ZeroTable[BC.B.B0]; - break; - case 0x02: - // RLC D - AF.B.B0 = (DE.B.B1 & 0x80)?C_FLAG:0; - DE.B.B1 = (DE.B.B1<<1) | (DE.B.B1>>7); - AF.B.B0 |= ZeroTable[DE.B.B1]; - break; - case 0x03: - // RLC E - AF.B.B0 = (DE.B.B0 & 0x80)?C_FLAG:0; - DE.B.B0 = (DE.B.B0<<1) | (DE.B.B0>>7); - AF.B.B0 |= ZeroTable[DE.B.B0]; - break; - case 0x04: - // RLC H - AF.B.B0 = (HL.B.B1 & 0x80)?C_FLAG:0; - HL.B.B1 = (HL.B.B1<<1) | (HL.B.B1>>7); - AF.B.B0 |= ZeroTable[HL.B.B1]; - break; - case 0x05: - // RLC L - AF.B.B0 = (HL.B.B0 & 0x80)?C_FLAG:0; - HL.B.B0 = (HL.B.B0<<1) | (HL.B.B0>>7); - AF.B.B0 |= ZeroTable[HL.B.B0]; - break; - case 0x06: - // RLC (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0 = (tempValue & 0x80)?C_FLAG:0; - tempValue = (tempValue<<1) | (tempValue>>7); - AF.B.B0 |= ZeroTable[tempValue]; - gbWriteMemory(HL.W,tempValue); - break; - case 0x07: - // RLC A - AF.B.B0 = (AF.B.B1 & 0x80)?C_FLAG:0; - AF.B.B1 = (AF.B.B1<<1) | (AF.B.B1>>7); - AF.B.B0 |= ZeroTable[AF.B.B1]; - break; - case 0x08: - // RRC B - AF.B.B0=(BC.B.B1&0x01 ? C_FLAG : 0); - BC.B.B1=(BC.B.B1>>1)|(BC.B.B1<<7); - AF.B.B0|=ZeroTable[BC.B.B1]; - break; - case 0x09: - // RRC C - AF.B.B0=(BC.B.B0&0x01 ? C_FLAG : 0); - BC.B.B0=(BC.B.B0>>1)|(BC.B.B0<<7); - AF.B.B0|=ZeroTable[BC.B.B0]; - break; - case 0x0a: - // RRC D - AF.B.B0=(DE.B.B1&0x01 ? C_FLAG : 0); - DE.B.B1=(DE.B.B1>>1)|(DE.B.B1<<7); - AF.B.B0|=ZeroTable[DE.B.B1]; - break; - case 0x0b: - // RRC E - AF.B.B0=(DE.B.B0&0x01 ? C_FLAG : 0); - DE.B.B0=(DE.B.B0>>1)|(DE.B.B0<<7); - AF.B.B0|=ZeroTable[DE.B.B0]; - break; - case 0x0c: - // RRC H - AF.B.B0=(HL.B.B1&0x01 ? C_FLAG : 0); - HL.B.B1=(HL.B.B1>>1)|(HL.B.B1<<7); - AF.B.B0|=ZeroTable[HL.B.B1]; - break; - case 0x0d: - // RRC L - AF.B.B0=(HL.B.B0&0x01 ? C_FLAG : 0); - HL.B.B0=(HL.B.B0>>1)|(HL.B.B0<<7); - AF.B.B0|=ZeroTable[HL.B.B0]; - break; - case 0x0e: - // RRC (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(tempValue&0x01 ? C_FLAG : 0); - tempValue=(tempValue>>1)|(tempValue<<7); - AF.B.B0|=ZeroTable[tempValue]; - gbWriteMemory(HL.W,tempValue); - break; - case 0x0f: - // RRC A - AF.B.B0=(AF.B.B1&0x01 ? C_FLAG : 0); - AF.B.B1=(AF.B.B1>>1)|(AF.B.B1<<7); - AF.B.B0|=ZeroTable[AF.B.B1]; - break; - case 0x10: - // RL B - if(BC.B.B1&0x80) { - BC.B.B1=(BC.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[BC.B.B1]|C_FLAG; - } else { - BC.B.B1=(BC.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[BC.B.B1]; - } - break; - case 0x11: - // RL C - if(BC.B.B0&0x80) { - BC.B.B0=(BC.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[BC.B.B0]|C_FLAG; - } else { - BC.B.B0=(BC.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[BC.B.B0]; - } - break; - case 0x12: - // RL D - if(DE.B.B1&0x80) { - DE.B.B1=(DE.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[DE.B.B1]|C_FLAG; - } else { - DE.B.B1=(DE.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[DE.B.B1]; - } - break; - case 0x13: - // RL E - if(DE.B.B0&0x80) { - DE.B.B0=(DE.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[DE.B.B0]|C_FLAG; - } else { - DE.B.B0=(DE.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[DE.B.B0]; - } - break; - case 0x14: - // RL H - if(HL.B.B1&0x80) { - HL.B.B1=(HL.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[HL.B.B1]|C_FLAG; - } else { - HL.B.B1=(HL.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[HL.B.B1]; - } - break; - case 0x15: - // RL L - if(HL.B.B0&0x80) { - HL.B.B0=(HL.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[HL.B.B0]|C_FLAG; - } else { - HL.B.B0=(HL.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[HL.B.B0]; - } - break; - case 0x16: - // RL (HL) - tempValue=gbReadMemory(HL.W); - if(tempValue&0x80) { - tempValue=(tempValue<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[tempValue]|C_FLAG; - } else { - tempValue=(tempValue<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[tempValue]; - } - gbWriteMemory(HL.W,tempValue); - break; - case 0x17: - // RL A - if(AF.B.B1&0x80) { - AF.B.B1=(AF.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[AF.B.B1]|C_FLAG; - } else { - AF.B.B1=(AF.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0); - AF.B.B0=ZeroTable[AF.B.B1]; - } - break; - case 0x18: - // RR B - if(BC.B.B1&0x01) { - BC.B.B1=(BC.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[BC.B.B1]|C_FLAG; - } else { - BC.B.B1=(BC.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[BC.B.B1]; - } - break; - case 0x19: - // RR C - if(BC.B.B0&0x01) { - BC.B.B0=(BC.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[BC.B.B0]|C_FLAG; - } else { - BC.B.B0=(BC.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[BC.B.B0]; - } - break; - case 0x1a: - // RR D - if(DE.B.B1&0x01) { - DE.B.B1=(DE.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[DE.B.B1]|C_FLAG; - } else { - DE.B.B1=(DE.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[DE.B.B1]; - } - break; - case 0x1b: - // RR E - if(DE.B.B0&0x01) { - DE.B.B0=(DE.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[DE.B.B0]|C_FLAG; - } else { - DE.B.B0=(DE.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[DE.B.B0]; - } - break; - case 0x1c: - // RR H - if(HL.B.B1&0x01) { - HL.B.B1=(HL.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[HL.B.B1]|C_FLAG; - } else { - HL.B.B1=(HL.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[HL.B.B1]; - } - break; - case 0x1d: - // RR L - if(HL.B.B0&0x01) { - HL.B.B0=(HL.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[HL.B.B0]|C_FLAG; - } else { - HL.B.B0=(HL.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[HL.B.B0]; - } - break; - case 0x1e: - // RR (HL) - tempValue=gbReadMemory(HL.W); - if(tempValue&0x01) { - tempValue=(tempValue>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[tempValue]|C_FLAG; - } else { - tempValue=(tempValue>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[tempValue]; - } - gbWriteMemory(HL.W,tempValue); - break; - case 0x1f: - // RR A - if(AF.B.B1&0x01) { - AF.B.B1=(AF.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[AF.B.B1]|C_FLAG; - } else { - AF.B.B1=(AF.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); - AF.B.B0=ZeroTable[AF.B.B1]; - } - break; - case 0x20: - // SLA B - AF.B.B0=(BC.B.B1&0x80?C_FLAG : 0); - BC.B.B1<<=1; - AF.B.B0|=ZeroTable[BC.B.B1]; - break; - case 0x21: - // SLA C - AF.B.B0=(BC.B.B0&0x80?C_FLAG : 0); - BC.B.B0<<=1; - AF.B.B0|=ZeroTable[BC.B.B0]; - break; - case 0x22: - // SLA D - AF.B.B0=(DE.B.B1&0x80?C_FLAG : 0); - DE.B.B1<<=1; - AF.B.B0|=ZeroTable[DE.B.B1]; - break; - case 0x23: - // SLA E - AF.B.B0=(DE.B.B0&0x80?C_FLAG : 0); - DE.B.B0<<=1; - AF.B.B0|=ZeroTable[DE.B.B0]; - break; - case 0x24: - // SLA H - AF.B.B0=(HL.B.B1&0x80?C_FLAG : 0); - HL.B.B1<<=1; - AF.B.B0|=ZeroTable[HL.B.B1]; - break; - case 0x25: - // SLA L - AF.B.B0=(HL.B.B0&0x80?C_FLAG : 0); - HL.B.B0<<=1; - AF.B.B0|=ZeroTable[HL.B.B0]; - break; - case 0x26: - // SLA (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(tempValue&0x80?C_FLAG : 0); - tempValue<<=1; - AF.B.B0|=ZeroTable[tempValue]; - gbWriteMemory(HL.W,tempValue); - break; - case 0x27: - // SLA A - AF.B.B0=(AF.B.B1&0x80?C_FLAG : 0); - AF.B.B1<<=1; - AF.B.B0|=ZeroTable[AF.B.B1]; - break; - case 0x28: - // SRA B - AF.B.B0=(BC.B.B1&0x01 ? C_FLAG: 0); - BC.B.B1=(BC.B.B1>>1)|(BC.B.B1&0x80); - AF.B.B0|=ZeroTable[BC.B.B1]; - break; - case 0x29: - // SRA C - AF.B.B0=(BC.B.B0&0x01 ? C_FLAG: 0); - BC.B.B0=(BC.B.B0>>1)|(BC.B.B0&0x80); - AF.B.B0|=ZeroTable[BC.B.B0]; - break; - case 0x2a: - // SRA D - AF.B.B0=(DE.B.B1&0x01 ? C_FLAG: 0); - DE.B.B1=(DE.B.B1>>1)|(DE.B.B1&0x80); - AF.B.B0|=ZeroTable[DE.B.B1]; - break; - case 0x2b: - // SRA E - AF.B.B0=(DE.B.B0&0x01 ? C_FLAG: 0); - DE.B.B0=(DE.B.B0>>1)|(DE.B.B0&0x80); - AF.B.B0|=ZeroTable[DE.B.B0]; - break; - case 0x2c: - // SRA H - AF.B.B0=(HL.B.B1&0x01 ? C_FLAG: 0); - HL.B.B1=(HL.B.B1>>1)|(HL.B.B1&0x80); - AF.B.B0|=ZeroTable[HL.B.B1]; - break; - case 0x2d: - // SRA L - AF.B.B0=(HL.B.B0&0x01 ? C_FLAG: 0); - HL.B.B0=(HL.B.B0>>1)|(HL.B.B0&0x80); - AF.B.B0|=ZeroTable[HL.B.B0]; - break; - case 0x2e: - // SRA (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(tempValue&0x01 ? C_FLAG: 0); - tempValue=(tempValue>>1)|(tempValue&0x80); - AF.B.B0|=ZeroTable[tempValue]; - gbWriteMemory(HL.W,tempValue); - break; - case 0x2f: - // SRA A - AF.B.B0=(AF.B.B1&0x01 ? C_FLAG: 0); - AF.B.B1=(AF.B.B1>>1)|(AF.B.B1&0x80); - AF.B.B0|=ZeroTable[AF.B.B1]; - break; - case 0x30: - // SWAP B - BC.B.B1 = (BC.B.B1&0xf0)>>4 | (BC.B.B1&0x0f)<<4; - AF.B.B0 = ZeroTable[BC.B.B1]; - break; - case 0x31: - // SWAP C - BC.B.B0 = (BC.B.B0&0xf0)>>4 | (BC.B.B0&0x0f)<<4; - AF.B.B0 = ZeroTable[BC.B.B0]; - break; - case 0x32: - // SWAP D - DE.B.B1 = (DE.B.B1&0xf0)>>4 | (DE.B.B1&0x0f)<<4; - AF.B.B0 = ZeroTable[DE.B.B1]; - break; - case 0x33: - // SWAP E - DE.B.B0 = (DE.B.B0&0xf0)>>4 | (DE.B.B0&0x0f)<<4; - AF.B.B0 = ZeroTable[DE.B.B0]; - break; - case 0x34: - // SWAP H - HL.B.B1 = (HL.B.B1&0xf0)>>4 | (HL.B.B1&0x0f)<<4; - AF.B.B0 = ZeroTable[HL.B.B1]; - break; - case 0x35: - // SWAP L - HL.B.B0 = (HL.B.B0&0xf0)>>4 | (HL.B.B0&0x0f)<<4; - AF.B.B0 = ZeroTable[HL.B.B0]; - break; - case 0x36: - // SWAP (HL) - tempValue=gbReadMemory(HL.W); - tempValue = (tempValue&0xf0)>>4 | (tempValue&0x0f)<<4; - AF.B.B0 = ZeroTable[tempValue]; - gbWriteMemory(HL.W,tempValue); - break; - case 0x37: - // SWAP A - AF.B.B1 = (AF.B.B1&0xf0)>>4 | (AF.B.B1&0x0f)<<4; - AF.B.B0 = ZeroTable[AF.B.B1]; - break; - case 0x38: - // SRL B - AF.B.B0=(BC.B.B1&0x01)?C_FLAG:0; - BC.B.B1>>=1; - AF.B.B0|=ZeroTable[BC.B.B1]; - break; - case 0x39: - // SRL C - AF.B.B0=(BC.B.B0&0x01)?C_FLAG:0; - BC.B.B0>>=1; - AF.B.B0|=ZeroTable[BC.B.B0]; - break; - case 0x3a: - // SRL D - AF.B.B0=(DE.B.B1&0x01)?C_FLAG:0; - DE.B.B1>>=1; - AF.B.B0|=ZeroTable[DE.B.B1]; - break; - case 0x3b: - // SRL E - AF.B.B0=(DE.B.B0&0x01)?C_FLAG:0; - DE.B.B0>>=1; - AF.B.B0|=ZeroTable[DE.B.B0]; - break; - case 0x3c: - // SRL H - AF.B.B0=(HL.B.B1&0x01)?C_FLAG:0; - HL.B.B1>>=1; - AF.B.B0|=ZeroTable[HL.B.B1]; - break; - case 0x3d: - // SRL L - AF.B.B0=(HL.B.B0&0x01)?C_FLAG:0; - HL.B.B0>>=1; - AF.B.B0|=ZeroTable[HL.B.B0]; - break; - case 0x3e: - // SRL (HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(tempValue&0x01)?C_FLAG:0; - tempValue>>=1; - AF.B.B0|=ZeroTable[tempValue]; - gbWriteMemory(HL.W,tempValue); - break; - case 0x3f: - // SRL A - AF.B.B0=(AF.B.B1&0x01)?C_FLAG:0; - AF.B.B1>>=1; - AF.B.B0|=ZeroTable[AF.B.B1]; - break; - case 0x40: - // BIT 0,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<0)? 0:Z_FLAG); - break; - case 0x41: - // BIT 0,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<0)? 0:Z_FLAG); - break; - case 0x42: - // BIT 0,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<0)? 0:Z_FLAG); - break; - case 0x43: - // BIT 0,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<0)? 0:Z_FLAG); - break; - case 0x44: - // BIT 0,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<0)? 0:Z_FLAG); - break; - case 0x45: - // BIT 0,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<0)? 0:Z_FLAG); - break; - case 0x46: - // BIT 0,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<0)? 0:Z_FLAG); - break; - case 0x47: - // BIT 0,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<0)? 0:Z_FLAG); - break; - case 0x48: - // BIT 1,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<1)? 0:Z_FLAG); - break; - case 0x49: - // BIT 1,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<1)? 0:Z_FLAG); - break; - case 0x4a: - // BIT 1,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<1)? 0:Z_FLAG); - break; - case 0x4b: - // BIT 1,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<1)? 0:Z_FLAG); - break; - case 0x4c: - // BIT 1,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<1)? 0:Z_FLAG); - break; - case 0x4d: - // BIT 1,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<1)? 0:Z_FLAG); - break; - case 0x4e: - // BIT 1,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<1)? 0:Z_FLAG); - break; - case 0x4f: - // BIT 1,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<1)? 0:Z_FLAG); - break; - case 0x50: - // BIT 2,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<2)? 0:Z_FLAG); - break; - case 0x51: - // BIT 2,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<2)? 0:Z_FLAG); - break; - case 0x52: - // BIT 2,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<2)? 0:Z_FLAG); - break; - case 0x53: - // BIT 2,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<2)? 0:Z_FLAG); - break; - case 0x54: - // BIT 2,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<2)? 0:Z_FLAG); - break; - case 0x55: - // BIT 2,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<2)? 0:Z_FLAG); - break; - case 0x56: - // BIT 2,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<2)? 0:Z_FLAG); - break; - case 0x57: - // BIT 2,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<2)? 0:Z_FLAG); - break; - case 0x58: - // BIT 3,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<3)? 0:Z_FLAG); - break; - case 0x59: - // BIT 3,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<3)? 0:Z_FLAG); - break; - case 0x5a: - // BIT 3,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<3)? 0:Z_FLAG); - break; - case 0x5b: - // BIT 3,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<3)? 0:Z_FLAG); - break; - case 0x5c: - // BIT 3,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<3)? 0:Z_FLAG); - break; - case 0x5d: - // BIT 3,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<3)? 0:Z_FLAG); - break; - case 0x5e: - // BIT 3,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<3)? 0:Z_FLAG); - break; - case 0x5f: - // BIT 3,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<3)? 0:Z_FLAG); - break; - case 0x60: - // BIT 4,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<4)? 0:Z_FLAG); - break; - case 0x61: - // BIT 4,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<4)? 0:Z_FLAG); - break; - case 0x62: - // BIT 4,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<4)? 0:Z_FLAG); - break; - case 0x63: - // BIT 4,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<4)? 0:Z_FLAG); - break; - case 0x64: - // BIT 4,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<4)? 0:Z_FLAG); - break; - case 0x65: - // BIT 4,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<4)? 0:Z_FLAG); - break; - case 0x66: - // BIT 4,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<4)? 0:Z_FLAG); - break; - case 0x67: - // BIT 4,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<4)? 0:Z_FLAG); - break; - case 0x68: - // BIT 5,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<5)? 0:Z_FLAG); - break; - case 0x69: - // BIT 5,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<5)? 0:Z_FLAG); - break; - case 0x6a: - // BIT 5,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<5)? 0:Z_FLAG); - break; - case 0x6b: - // BIT 5,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<5)? 0:Z_FLAG); - break; - case 0x6c: - // BIT 5,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<5)? 0:Z_FLAG); - break; - case 0x6d: - // BIT 5,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<5)? 0:Z_FLAG); - break; - case 0x6e: - // BIT 5,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<5)? 0:Z_FLAG); - break; - case 0x6f: - // BIT 5,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<5)? 0:Z_FLAG); - break; - case 0x70: - // BIT 6,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<6)? 0:Z_FLAG); - break; - case 0x71: - // BIT 6,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<6)? 0:Z_FLAG); - break; - case 0x72: - // BIT 6,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<6)? 0:Z_FLAG); - break; - case 0x73: - // BIT 6,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<6)? 0:Z_FLAG); - break; - case 0x74: - // BIT 6,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<6)? 0:Z_FLAG); - break; - case 0x75: - // BIT 6,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<6)? 0:Z_FLAG); - break; - case 0x76: - // BIT 6,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<6)? 0:Z_FLAG); - break; - case 0x77: - // BIT 6,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<6)? 0:Z_FLAG); - break; - case 0x78: - // BIT 7,B - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<7)? 0:Z_FLAG); - break; - case 0x79: - // BIT 7,C - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<7)? 0:Z_FLAG); - break; - case 0x7a: - // BIT 7,D - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<7)? 0:Z_FLAG); - break; - case 0x7b: - // BIT 7,E - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<7)? 0:Z_FLAG); - break; - case 0x7c: - // BIT 7,H - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<7)? 0:Z_FLAG); - break; - case 0x7d: - // BIT 7,L - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<7)? 0:Z_FLAG); - break; - case 0x7e: - // BIT 7,(HL) - tempValue=gbReadMemory(HL.W); - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<7)? 0:Z_FLAG); - break; - case 0x7f: - // BIT 7,A - AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<7)? 0:Z_FLAG); - break; - case 0x80: - // RES 0,B - BC.B.B1&=~(1<<0); - break; - case 0x81: - // RES 0,C - BC.B.B0&=~(1<<0); - break; - case 0x82: - // RES 0,D - DE.B.B1&=~(1<<0); - break; - case 0x83: - // RES 0,E - DE.B.B0&=~(1<<0); - break; - case 0x84: - // RES 0,H - HL.B.B1&=~(1<<0); - break; - case 0x85: - // RES 0,L - HL.B.B0&=~(1<<0); - break; - case 0x86: - // RES 0,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<0); - gbWriteMemory(HL.W,tempValue); - break; - case 0x87: - // RES 0,A - AF.B.B1&=~(1<<0); - break; - case 0x88: - // RES 1,B - BC.B.B1&=~(1<<1); - break; - case 0x89: - // RES 1,C - BC.B.B0&=~(1<<1); - break; - case 0x8a: - // RES 1,D - DE.B.B1&=~(1<<1); - break; - case 0x8b: - // RES 1,E - DE.B.B0&=~(1<<1); - break; - case 0x8c: - // RES 1,H - HL.B.B1&=~(1<<1); - break; - case 0x8d: - // RES 1,L - HL.B.B0&=~(1<<1); - break; - case 0x8e: - // RES 1,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<1); - gbWriteMemory(HL.W,tempValue); - break; - case 0x8f: - // RES 1,A - AF.B.B1&=~(1<<1); - break; - case 0x90: - // RES 2,B - BC.B.B1&=~(1<<2); - break; - case 0x91: - // RES 2,C - BC.B.B0&=~(1<<2); - break; - case 0x92: - // RES 2,D - DE.B.B1&=~(1<<2); - break; - case 0x93: - // RES 2,E - DE.B.B0&=~(1<<2); - break; - case 0x94: - // RES 2,H - HL.B.B1&=~(1<<2); - break; - case 0x95: - // RES 2,L - HL.B.B0&=~(1<<2); - break; - case 0x96: - // RES 2,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<2); - gbWriteMemory(HL.W,tempValue); - break; - case 0x97: - // RES 2,A - AF.B.B1&=~(1<<2); - break; - case 0x98: - // RES 3,B - BC.B.B1&=~(1<<3); - break; - case 0x99: - // RES 3,C - BC.B.B0&=~(1<<3); - break; - case 0x9a: - // RES 3,D - DE.B.B1&=~(1<<3); - break; - case 0x9b: - // RES 3,E - DE.B.B0&=~(1<<3); - break; - case 0x9c: - // RES 3,H - HL.B.B1&=~(1<<3); - break; - case 0x9d: - // RES 3,L - HL.B.B0&=~(1<<3); - break; - case 0x9e: - // RES 3,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<3); - gbWriteMemory(HL.W,tempValue); - break; - case 0x9f: - // RES 3,A - AF.B.B1&=~(1<<3); - break; - case 0xa0: - // RES 4,B - BC.B.B1&=~(1<<4); - break; - case 0xa1: - // RES 4,C - BC.B.B0&=~(1<<4); - break; - case 0xa2: - // RES 4,D - DE.B.B1&=~(1<<4); - break; - case 0xa3: - // RES 4,E - DE.B.B0&=~(1<<4); - break; - case 0xa4: - // RES 4,H - HL.B.B1&=~(1<<4); - break; - case 0xa5: - // RES 4,L - HL.B.B0&=~(1<<4); - break; - case 0xa6: - // RES 4,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<4); - gbWriteMemory(HL.W,tempValue); - break; - case 0xa7: - // RES 4,A - AF.B.B1&=~(1<<4); - break; - case 0xa8: - // RES 5,B - BC.B.B1&=~(1<<5); - break; - case 0xa9: - // RES 5,C - BC.B.B0&=~(1<<5); - break; - case 0xaa: - // RES 5,D - DE.B.B1&=~(1<<5); - break; - case 0xab: - // RES 5,E - DE.B.B0&=~(1<<5); - break; - case 0xac: - // RES 5,H - HL.B.B1&=~(1<<5); - break; - case 0xad: - // RES 5,L - HL.B.B0&=~(1<<5); - break; - case 0xae: - // RES 5,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<5); - gbWriteMemory(HL.W,tempValue); - break; - case 0xaf: - // RES 5,A - AF.B.B1&=~(1<<5); - break; - case 0xb0: - // RES 6,B - BC.B.B1&=~(1<<6); - break; - case 0xb1: - // RES 6,C - BC.B.B0&=~(1<<6); - break; - case 0xb2: - // RES 6,D - DE.B.B1&=~(1<<6); - break; - case 0xb3: - // RES 6,E - DE.B.B0&=~(1<<6); - break; - case 0xb4: - // RES 6,H - HL.B.B1&=~(1<<6); - break; - case 0xb5: - // RES 6,L - HL.B.B0&=~(1<<6); - break; - case 0xb6: - // RES 6,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<6); - gbWriteMemory(HL.W,tempValue); - break; - case 0xb7: - // RES 6,A - AF.B.B1&=~(1<<6); - break; - case 0xb8: - // RES 7,B - BC.B.B1&=~(1<<7); - break; - case 0xb9: - // RES 7,C - BC.B.B0&=~(1<<7); - break; - case 0xba: - // RES 7,D - DE.B.B1&=~(1<<7); - break; - case 0xbb: - // RES 7,E - DE.B.B0&=~(1<<7); - break; - case 0xbc: - // RES 7,H - HL.B.B1&=~(1<<7); - break; - case 0xbd: - // RES 7,L - HL.B.B0&=~(1<<7); - break; - case 0xbe: - // RES 7,(HL) - tempValue=gbReadMemory(HL.W); - tempValue&=~(1<<7); - gbWriteMemory(HL.W,tempValue); - break; - case 0xbf: - // RES 7,A - AF.B.B1&=~(1<<7); - break; - case 0xc0: - // SET 0,B - BC.B.B1|=1<<0; - break; - case 0xc1: - // SET 0,C - BC.B.B0|=1<<0; - break; - case 0xc2: - // SET 0,D - DE.B.B1|=1<<0; - break; - case 0xc3: - // SET 0,E - DE.B.B0|=1<<0; - break; - case 0xc4: - // SET 0,H - HL.B.B1|=1<<0; - break; - case 0xc5: - // SET 0,L - HL.B.B0|=1<<0; - break; - case 0xc6: - // SET 0,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<0; - gbWriteMemory(HL.W,tempValue); - break; - case 0xc7: - // SET 0,A - AF.B.B1|=1<<0; - break; - case 0xc8: - // SET 1,B - BC.B.B1|=1<<1; - break; - case 0xc9: - // SET 1,C - BC.B.B0|=1<<1; - break; - case 0xca: - // SET 1,D - DE.B.B1|=1<<1; - break; - case 0xcb: - // SET 1,E - DE.B.B0|=1<<1; - break; - case 0xcc: - // SET 1,H - HL.B.B1|=1<<1; - break; - case 0xcd: - // SET 1,L - HL.B.B0|=1<<1; - break; - case 0xce: - // SET 1,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<1; - gbWriteMemory(HL.W,tempValue); - break; - case 0xcf: - // SET 1,A - AF.B.B1|=1<<1; - break; - case 0xd0: - // SET 2,B - BC.B.B1|=1<<2; - break; - case 0xd1: - // SET 2,C - BC.B.B0|=1<<2; - break; - case 0xd2: - // SET 2,D - DE.B.B1|=1<<2; - break; - case 0xd3: - // SET 2,E - DE.B.B0|=1<<2; - break; - case 0xd4: - // SET 2,H - HL.B.B1|=1<<2; - break; - case 0xd5: - // SET 2,L - HL.B.B0|=1<<2; - break; - case 0xd6: - // SET 2,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<2; - gbWriteMemory(HL.W,tempValue); - break; - case 0xd7: - // SET 2,A - AF.B.B1|=1<<2; - break; - case 0xd8: - // SET 3,B - BC.B.B1|=1<<3; - break; - case 0xd9: - // SET 3,C - BC.B.B0|=1<<3; - break; - case 0xda: - // SET 3,D - DE.B.B1|=1<<3; - break; - case 0xdb: - // SET 3,E - DE.B.B0|=1<<3; - break; - case 0xdc: - // SET 3,H - HL.B.B1|=1<<3; - break; - case 0xdd: - // SET 3,L - HL.B.B0|=1<<3; - break; - case 0xde: - // SET 3,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<3; - gbWriteMemory(HL.W,tempValue); - break; - case 0xdf: - // SET 3,A - AF.B.B1|=1<<3; - break; - case 0xe0: - // SET 4,B - BC.B.B1|=1<<4; - break; - case 0xe1: - // SET 4,C - BC.B.B0|=1<<4; - break; - case 0xe2: - // SET 4,D - DE.B.B1|=1<<4; - break; - case 0xe3: - // SET 4,E - DE.B.B0|=1<<4; - break; - case 0xe4: - // SET 4,H - HL.B.B1|=1<<4; - break; - case 0xe5: - // SET 4,L - HL.B.B0|=1<<4; - break; - case 0xe6: - // SET 4,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<4; - gbWriteMemory(HL.W,tempValue); - break; - case 0xe7: - // SET 4,A - AF.B.B1|=1<<4; - break; - case 0xe8: - // SET 5,B - BC.B.B1|=1<<5; - break; - case 0xe9: - // SET 5,C - BC.B.B0|=1<<5; - break; - case 0xea: - // SET 5,D - DE.B.B1|=1<<5; - break; - case 0xeb: - // SET 5,E - DE.B.B0|=1<<5; - break; - case 0xec: - // SET 5,H - HL.B.B1|=1<<5; - break; - case 0xed: - // SET 5,L - HL.B.B0|=1<<5; - break; - case 0xee: - // SET 5,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<5; - gbWriteMemory(HL.W,tempValue); - break; - case 0xef: - // SET 5,A - AF.B.B1|=1<<5; - break; - case 0xf0: - // SET 6,B - BC.B.B1|=1<<6; - break; - case 0xf1: - // SET 6,C - BC.B.B0|=1<<6; - break; - case 0xf2: - // SET 6,D - DE.B.B1|=1<<6; - break; - case 0xf3: - // SET 6,E - DE.B.B0|=1<<6; - break; - case 0xf4: - // SET 6,H - HL.B.B1|=1<<6; - break; - case 0xf5: - // SET 6,L - HL.B.B0|=1<<6; - break; - case 0xf6: - // SET 6,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<6; - gbWriteMemory(HL.W,tempValue); - break; - case 0xf7: - // SET 6,A - AF.B.B1|=1<<6; - break; - case 0xf8: - // SET 7,B - BC.B.B1|=1<<7; - break; - case 0xf9: - // SET 7,C - BC.B.B0|=1<<7; - break; - case 0xfa: - // SET 7,D - DE.B.B1|=1<<7; - break; - case 0xfb: - // SET 7,E - DE.B.B0|=1<<7; - break; - case 0xfc: - // SET 7,H - HL.B.B1|=1<<7; - break; - case 0xfd: - // SET 7,L - HL.B.B0|=1<<7; - break; - case 0xfe: - // SET 7,(HL) - tempValue=gbReadMemory(HL.W); - tempValue|=1<<7; - gbWriteMemory(HL.W,tempValue); - break; - case 0xff: - // SET 7,A - AF.B.B1|=1<<7; - break; - default: - if (gbSystemMessage == false) - { - systemMessage(0, N_("Unknown opcode %02x at %04x"), - gbReadOpcode(PC.W-1),PC.W-1); - gbSystemMessage =true; - } - return; diff --git a/src/dmg/gbDis.cpp b/src/dmg/gbDis.cpp deleted file mode 100644 index 4a589ae5..00000000 --- a/src/dmg/gbDis.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include - -#include "../System.h" -#include "gbGlobals.h" - -typedef struct { - u8 mask; - u8 value; - const char *mnen; -} GBOPCODE; - -#define GB_READ(x) gbMemoryMap[(x)>>12][(x)&0xfff] - -static const char *registers[] = - { "B", "C", "D", "E", "H", "L", "(HL)", "A" }; - -static const char *registers16[] = - { "BC", "DE", "HL", "SP", // for some operations - "BC", "DE", "HL", "AF" }; // for push/pop - -static const char *cond[] = - { "NZ", "Z", "NC", "C" }; - -static char hexDigits[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -static GBOPCODE opcodes[] = { - { 0xff, 0x00, "NOP" }, - { 0xcf, 0x01, "LD %R4,%W" }, - { 0xff, 0x02, "LD (BC),A" }, - { 0xcf, 0x03, "INC %R4" }, - { 0xc7, 0x04, "INC %r3" }, - { 0xc7, 0x05, "DEC %r3" }, - { 0xc7, 0x06, "LD %r3,%B" }, - { 0xff, 0x07, "RLCA" }, - { 0xff, 0x08, "LD (%W),SP" }, - { 0xcf, 0x09, "ADD HL,%R4" }, - { 0xff, 0x0a, "LD A,(BC)" }, - { 0xcf, 0x0b, "DEC %R4" }, - { 0xff, 0x0f, "RRCA" }, - { 0xff, 0x10, "STOP" }, - { 0xff, 0x12, "LD (DE),A" }, - { 0xff, 0x17, "RLA" }, - { 0xff, 0x18, "JR %d" }, - { 0xff, 0x1a, "LD A,(DE)" }, - { 0xff, 0x1f, "RRA" }, - { 0xe7, 0x20, "JR %c3,%d" }, - { 0xff, 0x22, "LDI (HL),A" }, - { 0xff, 0x27, "DAA" }, - { 0xff, 0x2a, "LDI A,(HL)" }, - { 0xff, 0x2f, "CPL" }, - { 0xff, 0x32, "LDD (HL),A" }, - { 0xff, 0x37, "SCF" }, - { 0xff, 0x3a, "LDD A,(HL)" }, - { 0xff, 0x3f, "CCF" }, - { 0xff, 0x76, "HALT" }, - { 0xc0, 0x40, "LD %r3,%r0" }, - { 0xf8, 0x80, "ADD A,%r0" }, - { 0xf8, 0x88, "ADC A,%r0" }, - { 0xf8, 0x90, "SUB %r0" }, - { 0xf8, 0x98, "SBC A,%r0" }, - { 0xf8, 0xa0, "AND %r0" }, - { 0xf8, 0xa8, "XOR %r0" }, - { 0xf8, 0xb0, "OR %r0" }, - { 0xf8, 0xb8, "CP %r0" }, - { 0xe7, 0xc0, "RET %c3" }, - { 0xcf, 0xc1, "POP %t4" }, - { 0xe7, 0xc2, "JP %c3,%W" }, - { 0xff, 0xc3, "JP %W" }, - { 0xe7, 0xc4, "CALL %c3,%W" }, - { 0xcf, 0xc5, "PUSH %t4" }, - { 0xff, 0xc6, "ADD A,%B" }, - { 0xc7, 0xc7, "RST %P" }, - { 0xff, 0xc9, "RET" }, - { 0xff, 0xcd, "CALL %W" }, - { 0xff, 0xce, "ADC %B" }, - { 0xff, 0xd6, "SUB %B" }, - { 0xff, 0xd9, "RETI" }, - { 0xff, 0xde, "SBC %B" }, - { 0xff, 0xe0, "LD (FF%B),A" }, - { 0xff, 0xe2, "LD (FF00h+C),A" }, - { 0xff, 0xe6, "AND %B" }, - { 0xff, 0xe8, "ADD SP,%D" }, - { 0xff, 0xe9, "LD PC,HL" }, - { 0xff, 0xea, "LD (%W),A" }, - { 0xff, 0xee, "XOR %B" }, - { 0xff, 0xf0, "LD A,(FF%B)" }, - { 0xff, 0xf2, "LD A,(FF00h+C)" }, - { 0xff, 0xf3, "DI" }, - { 0xff, 0xf6, "OR %B" }, - { 0xff, 0xf8, "LD HL,SP%D" }, - { 0xff, 0xf9, "LD SP,HL" }, - { 0xff, 0xfa, "LD A,(%W)" }, - { 0xff, 0xfb, "EI" }, - { 0xff, 0xfe, "CP %B" }, - { 0x00, 0x00, "DB %B" } -}; - -static GBOPCODE cbOpcodes[] = { - { 0xf8, 0x00, "RLC %r0" }, - { 0xf8, 0x08, "RRC %r0" }, - { 0xf8, 0x10, "RL %r0" }, - { 0xf8, 0x18, "RR %r0" }, - { 0xf8, 0x20, "SLA %r0" }, - { 0xf8, 0x28, "SRA %r0" }, - { 0xf8, 0x30, "SWAP %r0" }, - { 0xf8, 0x38, "SRL %r0" }, - { 0xc0, 0x40, "BIT %b,%r0" }, - { 0xc0, 0x80, "RES %b,%r0" }, - { 0xc0, 0xc0, "SET %b,%r0" }, - { 0x00, 0x00, "DB CBh,%B" } -}; - -static char *addHex(char *p, u8 value) -{ - *p++ = hexDigits[value >> 4]; - *p++ = hexDigits[value & 15]; - return p; -} - -static char *addHex16(char *p, u16 value) -{ - p = addHex(p, value>>8); - return addHex(p, value & 255); -} - -static char *addStr(char *p, const char *s) -{ - while(*s) { - *p++ = *s++; - } - return p; -} - -int gbDis(char *buffer, u16 address) -{ - char *p = buffer; - int instr = 1; - u16 addr = address; - sprintf(p, "%04x ", address); - p += 12; - - u8 opcode = GB_READ(address); - address++; - const char *mnen; - GBOPCODE *op; - if(opcode == 0xcb) { - opcode = GB_READ(address); - address++; - instr++; - op = cbOpcodes; - } else { - op = opcodes; - } - while(op->value != (opcode & op->mask)) op++; - mnen = op->mnen; - - u8 b0, b1; - s8 disp; - int shift; - - while(*mnen) { - if(*mnen == '%') { - mnen++; - switch(*mnen++) { - case 'W': - b0 = GB_READ(address); - address++; - b1 = GB_READ(address); - address++; - p = addHex16(p, b0|b1<<8); - instr += 2; - *p++ = 'h'; - break; - case 'B': - p = addHex(p, GB_READ(address)); - *p++ = 'h'; - address++; - instr++; - break; - case 'D': - disp = GB_READ(address); - if(disp >= 0) - *p++ = '+'; - p += sprintf(p, "%d", disp); - instr++; - break; - case 'd': - disp = GB_READ(address); - address++; - p = addHex16(p, address+disp); - *p++ = 'h'; - instr++; - break; - case 'b': - // kind of a hack, but it works :-) - *p++ = hexDigits[(opcode >> 3) & 7]; - break; - case 'r': - shift = *mnen++ - '0'; - p = addStr(p, registers[(opcode >> shift) & 7]); - break; - case 'R': - shift = *mnen++ - '0'; - p = addStr(p, registers16[(opcode >> shift) & 3]); - break; - case 't': - shift = *mnen++ - '0'; - p = addStr(p, registers16[4+((opcode >> shift) & 3)]); - break; - case 'P': - p = addHex(p, ((opcode >> 3) & 7) * 8); - break; - case 'c': - shift = *mnen++ - '0'; - p = addStr(p, cond[(opcode >> shift) & 3]); - break; - } - } else - *p++ = *mnen++; - } - for(int i = 0; i < instr; i++) { - u16 a = addr + i; - addHex(buffer+5+i*2, GB_READ(a)); - } - *p = 0; - return instr; -} diff --git a/src/dmg/gbGfx.cpp b/src/dmg/gbGfx.cpp deleted file mode 100644 index 468a46ac..00000000 --- a/src/dmg/gbGfx.cpp +++ /dev/null @@ -1,742 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include "../Brunni/common.h" -#include "../agb/GBA.h" -#include "gbGlobals.h" -#include "gbSGB.h" - -/** BRUNNI ADDED CODE **/ -int gblModeColorIt=0; -byte tilePalList[384]; -short tilePalPalette[NB_PALETTES][4]; -byte tilePalCrc[384 / 8]; -short tileMapTileList[384]; -int gb_lastVramCrc; -u8 *gbExternalVram; - -void tilePalReinit() { - int i; - memset(tilePalList, 0, sizeof(tilePalList)); - for (i=0;i> 3] & (1 << (i & 7))) - crc = crc32(crc, vram + i * 16, 16); - } - return crc; -} - -void exiting_lcdc() { - //Do nothing in GBC mode (VBA uses another VRAM address) - if (!gblModeColorIt || gbCgbMode) - return; - - u32 crc = tileMapGetVramChecksum(); - if (crc != gb_lastVramCrc /*|| gblConfigAutoShowCrc*/) { - OuvreFichierPalette(crc, NULL); - if (gblConfigAutoShowCrc) { - char temp[256]; - sprintf(temp, "New VRAM CRC: %08x", crc); - systemScreenMessage(temp); - } - gb_lastVramCrc = crc; - } -} - -/** END BRUNNI **/ - -u8 gbInvertTab[256] = { - 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0, - 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0, - 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8, - 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8, - 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4, - 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4, - 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec, - 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc, - 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2, - 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2, - 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea, - 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa, - 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6, - 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6, - 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee, - 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe, - 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1, - 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1, - 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9, - 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9, - 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5, - 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5, - 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed, - 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd, - 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3, - 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3, - 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb, - 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb, - 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7, - 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7, - 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef, - 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff -}; - -u16 gbLineMix[160]; -u16 gbWindowColor[160]; -extern int inUseRegister_WY; - -void gbRenderLine() -{ - memset(gbLineMix, 0, sizeof(gbLineMix)); - u8 * bank0; - u8 * bank1; - //Brunni/ - u8 * externalVram = NULL; - if(gbCgbMode) { - bank0 = &gbVram[0x0000]; - bank1 = &gbVram[0x2000]; - } else { - bank0 = &gbMemory[0x8000]; - bank1 = NULL; - //Brunni/ Additional memory for custom tiles - we should have done just like the GBC, two banks - if (gblModeColorIt) - externalVram = getGbExtVramAddr(); - } - - int tile_map = 0x1800; - if((register_LCDC & 8) != 0) - tile_map = 0x1c00; - - int tile_pattern = 0x0800; - - if((register_LCDC & 16) != 0) - tile_pattern = 0x0000; - - int x = 0; - int y = register_LY; - - if(y >= 144) - return; - - int SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4); - int sx = gbSCXLine[(gbSpeed ? 0 : 4)+SpritesTicks]; - int sy = gbSCYLine[(gbSpeed ? 11 : 5)+SpritesTicks]; - - sy+=y; - - sy &= 255; - - int tx = sx >> 3; - int ty = sy >> 3; - - int bx = 1 << (7 - (sx & 7)); - int by = sy & 7; - - int tile_map_line_y = tile_map + ty * 32; - - int tile_map_address = tile_map_line_y + tx; - - u8 attrs = 0; - if(bank1 != NULL) - attrs = bank1[tile_map_address]; - - u8 tile = bank0[tile_map_address]; - - tile_map_address++; - - if(!(register_LCDC & 0x10)) - tile ^= 0x80; - - int tile_pattern_address = tile_pattern + tile * 16 + by*2; - - if(register_LCDC & 0x80) { - if((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) { - while(x < 160) { - - - - u8 tile_a = 0; - u8 tile_b = 0; - u8 colorItPaletteNb = 0, colorItUseExtVram = 0; - - //Brunni/ Pattern change (custom tile) - if (gblModeColorIt) { - //Brunni/ Get the tile number (+128 if LCDC bit4 is zero) - s16 tilenb = (tile_pattern >> 4) + tile; - colorItPaletteNb = tilePalList[tilenb]; - - //Brunni/ Select the associated custom tile - tilenb = tileMapTileList[tilenb]; - - //Brunni/ Does it use additional GB vram? ("bank 1") - if (tilenb >= 512) - colorItUseExtVram = 1, tilenb -= 512; - - //Brunni/ Nothing to do => return to the normal range (within current bank) - tilenb -= (tile_pattern >> 4); - tile_pattern_address = tile_pattern + tilenb * 16 + by * 2; - } - - if(attrs & 0x40) { - tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; - } - - if(attrs & 0x08) { - tile_a = bank1[tile_pattern_address++]; - tile_b = bank1[tile_pattern_address]; - } - else if (colorItUseExtVram) { - //Brunni/ "bank 1" (additional GB vram) - tile_a = externalVram[tile_pattern_address++]; - tile_b = externalVram[tile_pattern_address]; - } else { - tile_a = bank0[tile_pattern_address++]; - tile_b = bank0[tile_pattern_address]; - } - - if(attrs & 0x20) { - tile_a = gbInvertTab[tile_a]; - tile_b = gbInvertTab[tile_b]; - } - - while(bx > 0) { - u8 c = (tile_a & bx) ? 1 : 0; - c += ((tile_b & bx) ? 2 : 0); - - gbLineBuffer[x] = c; // mark the gbLineBuffer color - - if(attrs & 0x80) - gbLineBuffer[x] |= 0x300; - - if(gbCgbMode) { - c = c + (attrs & 7)*4; - } else { - c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+SpritesTicks]>>(c<<1)) &3; - if(gbSgbMode && !gbCgbMode) { - int dx = x >> 3; - int dy = y >> 3; - - int palette = gbSgbATF[dy * 20 + dx]; - - if(c == 0) - palette = 0; - - c = c + 4*palette; - } - - //Brunni/ Find the right palette - if (gblModeColorIt) - c += 4 * colorItPaletteNb; - } - gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : - gbPalette[c] & 0x7FFF; - x++; - if(x >= 160) - break; - bx >>= 1; - } - - bx = 128; - - SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4); - - sx = gbSCXLine[x+(gbSpeed ? 0 : 4)+SpritesTicks]; - - sy = gbSCYLine[x+(gbSpeed ? 11 : 5)+SpritesTicks]; - - - tx = ((sx+x)>>3) & 0x1f; - - sy+=y; - - sy &= 255; - - ty = sy >> 3; - - by = sy & 7; - - tile_pattern_address = tile_pattern + tile * 16 + by * 2; - - tile_map_line_y = tile_map + ty * 32; - - tile_map_address = tile_map_line_y + tx; - - if(bank1) - attrs = bank1[tile_map_line_y + tx]; - - tile = bank0[tile_map_line_y + tx]; - - if(!(register_LCDC & 0x10)) - tile ^= 0x80; - - tile_pattern_address = tile_pattern + tile * 16 + by * 2; - } - } else { - // Use gbBgp[0] instead of 0 (?) - // (this fixes white flashes on Last Bible II) - // Also added the gbColorOption (fixes Dracula Densetsu II color problems) - for(int i = 0; i < 160; i++) - { - u16 color = gbColorOption ? gbColorFilter[0x7FFF] : - 0x7FFF; - if (!gbCgbMode) - color = gbColorOption ? gbColorFilter[gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF] : - gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF; - gbLineMix[i] = color; - gbLineBuffer[i] = 0; - } - } - - // do the window display - // LCDC.0 also enables/disables the window in !gbCgbMode ?!?! - // (tested on real hardware) - // This fixes Last Bible II & Zankurou Musouken - if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) && - (layerSettings & 0x2000) && (gbWindowLine != -2)) { - int i = 0; - // Fix (accurate emulation) for most of the window display problems - // (ie. Zen - Intergalactic Ninja, Urusei Yatsura...). - if ((gbWindowLine == -1) || (gbWindowLine>144)) - { - inUseRegister_WY = oldRegister_WY; - if (register_LY>oldRegister_WY) - gbWindowLine = 146; - // for (i = 0; i<160; i++) - // gbWindowColor[i] = gbLineMix[i]; - } - - int wy = inUseRegister_WY; - - if(y >= inUseRegister_WY) { - - if (gbWindowLine == -1) - gbWindowLine = 0; - - int wx = register_WX; - int swx = 0; - wx -= 7; - - if( wx <= 159 && gbWindowLine <= 143) { - - tile_map = 0x1800; - - if((register_LCDC & 0x40) != 0) - tile_map = 0x1c00; - - - tx = 0; - ty = gbWindowLine >> 3; - - bx = 128; - by = gbWindowLine & 7; - - // Tries to emulate the 'window scrolling bug' when wx == 0 (ie. wx-7 == -7). - // Nothing close to perfect, but good enought for now... - if (wx == -7) - { - swx = 7-((gbSCXLine[0]-1) & 7); - bx >>= ((gbSCXLine[0]+((swx != 1) ? 1 : 0)) & 7); - if (swx == 1) - swx = 2; - - //bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7); - - if ((swx == 7)) - { - //wx = 0; - if ((gbWindowLine>0) || (wy == 0)) - swx = 0; - } - } - else - if(wx < 0) { - bx >>= (-wx); - wx = 0; - } - - tile_map_line_y = tile_map + ty * 32; - - tile_map_address = tile_map_line_y + tx; - - x = wx; - - tile = bank0[tile_map_address]; - u8 attrs = 0; - if(bank1) - attrs = bank1[tile_map_address]; - tile_map_address++; - - if((register_LCDC & 16) == 0) { - if(tile < 128) tile += 128; - else tile -= 128; - } - - tile_pattern_address = tile_pattern + tile * 16 + by*2; - - if (wx) - for (i = 0; i> 4) + tile; - colorItPaletteNb = tilePalList[tilenb]; - - //Brunni/ Select the associated custom tile - tilenb = tileMapTileList[tilenb]; - - //Brunni/ Does it use additional GB vram? ("bank 1") - if (tilenb >= 512) - colorItUseExtVram = 1, tilenb -= 512; - - //Brunni/ Nothing to do => return to the normal range (within current bank) - tilenb -= (tile_pattern >> 4); - tile_pattern_address = tile_pattern + tilenb * 16 + by * 2; - } - - if(attrs & 0x40) { - tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; - } - - if(attrs & 0x08) { - tile_a = bank1[tile_pattern_address++]; - tile_b = bank1[tile_pattern_address]; - } - else if (colorItUseExtVram) { - //Brunni/ "bank 1" (additional GB vram) - tile_a = externalVram[tile_pattern_address++]; - tile_b = externalVram[tile_pattern_address]; - } else { - tile_a = bank0[tile_pattern_address++]; - tile_b = bank0[tile_pattern_address]; - } - - if(attrs & 0x20) { - tile_a = gbInvertTab[tile_a]; - tile_b = gbInvertTab[tile_b]; - } - - while(bx > 0) { - u8 c = (tile_a & bx) != 0 ? 1 : 0; - c += ((tile_b & bx) != 0 ? 2 : 0); - - if (x>=0) - { - if(attrs & 0x80) - gbLineBuffer[x] = 0x300 + c; - else - gbLineBuffer[x] = 0x100 + c; - - if(gbCgbMode) { - c = c + (attrs & 7) * 4; - } else { - c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(c<<1)) &3; - if(gbSgbMode && !gbCgbMode) { - int dx = x >> 3; - int dy = y >> 3; - - int palette = gbSgbATF[dy * 20 + dx]; - - if(c == 0) - palette = 0; - - c = c + 4*palette; - } - //Brunni/ Find the right palette - if (gblModeColorIt) - c += 4 * colorItPaletteNb; - } - gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : - gbPalette[c] & 0x7FFF; - } - x++; - if(x >= 160) - break; - bx >>= 1; - } - tx++; - if(tx == 32) - tx = 0; - bx = 128; - tile = bank0[tile_map_line_y + tx]; - if(bank1) - attrs = bank1[tile_map_line_y + tx]; - - if((register_LCDC & 16) == 0) { - if(tile < 128) tile += 128; - else tile -= 128; - } - tile_pattern_address = tile_pattern + tile * 16 + by * 2; - } - - //for (i = swx; i<160; i++) - // gbLineMix[i] = gbWindowColor[i]; - gbWindowLine++; - } - } - } - else if (gbWindowLine == -2) - { - inUseRegister_WY = oldRegister_WY; - if (register_LY>oldRegister_WY) - gbWindowLine = 146; - else - gbWindowLine = 0; - } - } else { - u16 color = gbColorOption ? gbColorFilter[0x7FFF] : - 0x7FFF; - if (!gbCgbMode) - color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : - gbPalette[0] & 0x7FFF; - for(int i = 0; i < 160; i++) - { - gbLineMix[i] = color; - gbLineBuffer[i] = 0; - } - } -} - -void gbDrawSpriteTile(int tile, int x,int y,int t, int flags, - int size,int spriteNumber) -{ - u8 * bank0; - u8 * bank1; - //Brunni/ - u8 * externalVram = NULL; - if(gbCgbMode) { - if(register_VBK & 1) { - bank0 = &gbVram[0x0000]; - bank1 = &gbVram[0x2000]; - } else { - bank0 = &gbVram[0x0000]; - bank1 = &gbVram[0x2000]; - } - } else { - bank0 = &gbMemory[0x8000]; - bank1 = NULL; - if (gblModeColorIt) - externalVram = getGbExtVramAddr(); - } - - int init = 0x0000; - - for (int i = 0; i<4; i++) - { - gbObp0[i] = (gbObp0Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3; - gbObp1[i] = (gbObp1Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3; - } - u8 *pal = gbObp0; - - int flipx = (flags & 0x20); - int flipy = (flags & 0x40); - - if((flags & 0x10)) - pal = gbObp1; - - if(flipy) { - t = (size ? 15 : 7) - t; - } - - int prio = flags & 0x80; - - int address = init + tile * 16 + 2*t; - int a = 0; - int b = 0; - u8 colorItPaletteNb = 0, colorItUseExtVram = 0; - - //Brunni/ Define the actual palette and custom pattern for this tile - if (gblModeColorIt) { - //Brunni/ Get the tile number (+128 if LCDC bit4 is zero) - colorItPaletteNb = tilePalList[tile]; - //Brunni/ Associated custom tile - tile = tileMapTileList[tile]; - //Brunni/ Same way as BGs => additional GB vram - if (tile >= 512) - colorItUseExtVram = 1, tile -= 512; - address = init + tile * 16 + 2*t; - } - - if(gbCgbMode && (flags & 0x08)) { - a = bank1[address++]; - b = bank1[address++]; - } else if (colorItUseExtVram) { - //Brunni/ "bank 1" (additional GB vram) - a = externalVram[address++]; - b = externalVram[address++]; - } else { - a = bank0[address++]; - b = bank0[address++]; - } - - for(int xx = 0; xx < 8; xx++) { - u8 mask = 1 << (7-xx); - u8 c = 0; - if( (a & mask)) - c++; - if( (b & mask)) - c+=2; - - if(c==0) continue; - - int xxx = xx+x; - if(flipx) - xxx = (7-xx+x); - - if(xxx < 0 || xxx > 159) - continue; - - u16 color = gbLineBuffer[xxx]; - - // Fixes OAM-BG priority - if(prio && (register_LCDC & 1)) { - if(color < 0x200 && ((color & 0xFF) != 0)) - continue; - } - // Fixes OAM-BG priority for Moorhuhn 2 - if(color >= 0x300 && color != 0x300 && (register_LCDC & 1)) - continue; - else if(color >= 0x200 && color < 0x300) { - int sprite = color & 0xff; - - int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8; - - if(spriteX == x) { - if(sprite < spriteNumber) - continue; - } else { - if(gbCgbMode) { - if(sprite < spriteNumber) - continue; - } else { - // Fixes GB sprites priorities (was '< x + 8' before) - // ('A boy and his blob...' sprites' emulation is now correct) - if(spriteX < x) - continue; - } - } - } - - - gbLineBuffer[xxx] = 0x200 + spriteNumber; - - // make sure that sprites will work even in CGB mode - if(gbCgbMode) { - c = c + (flags & 0x07)*4 + 32; - } else { - c = pal[c]; - - if(gbSgbMode && !gbCgbMode) { - int dx = xxx >> 3; - int dy = y >> 3; - - int palette = gbSgbATF[dy * 20 + dx]; - - if(c == 0) - palette = 0; - - c = c + 4*palette; - } else { - //Brunni/ Set the color palette - if (gblModeColorIt) - c += 4 * colorItPaletteNb; - else - //Brunni/ Normal GB behaviour (first 4 colors for the BG, etc.) - c += 4; - } - } - - gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : - gbPalette[c] & 0x7FFF; - } -} - -void gbDrawSprites(bool draw) -{ - int x = 0; - int y = 0; - int count = 0; - - int size = (register_LCDC & 4); - - if (!draw) - memset (gbSpritesTicks, 0, sizeof(gbSpritesTicks)); - - if(!(register_LCDC & 0x80)) - return; - - if((register_LCDC & 2) && (layerSettings & 0x1000)) { - int yc = register_LY; - - int address = 0xfe00; - for(int i = 0; i < 40; i++) { - y = gbMemory[address++]; - x = gbMemory[address++]; - int tile = gbMemory[address++]; - if(size) - tile &= 254; - int flags = gbMemory[address++]; - - if(x > 0 && y > 0 && x < 168 && y < 160) { - // check if sprite intersects current line - int t = yc -y + 16; - if((size && t >=0 && t < 16) || (!size && t >= 0 && t < 8)) { - if (draw) - gbDrawSpriteTile(tile,x-8,yc,t,flags,size,i); - else - { - for (int j = x-8; j<300; j++) - if (j>=0) - if (gbSpeed) - gbSpritesTicks[j] += 5; - else - gbSpritesTicks[j] += 2+(count&1); - - } - count++; - } else if(!size && t >= 0 && t < 8) { - gbDrawSpriteTile(tile, x-8, yc, t, flags,size,i); - count++; - } - } - // sprite limit reached! - if(count >= 10) - break; - } - } - return; -} diff --git a/src/dmg/gbGlobals.cpp b/src/dmg/gbGlobals.cpp deleted file mode 100644 index 4cf27c84..00000000 --- a/src/dmg/gbGlobals.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "../agb/GBA.h" - -u8 *gbMemoryMap[16]; - -int gbRomSizeMask = 0; -int gbRomSize = 0; -int gbRamSizeMask = 0; -int gbRamSize = 0; -int gbTAMA5ramSize = 0; - -u8 *gbMemory = NULL; -u8 *gbVram = NULL; -u8 *gbRom = NULL; -u8 *gbRam = NULL; -u8 *gbWram = NULL; -u16 *gbLineBuffer = NULL; -u8 *gbTAMA5ram = NULL; - -u16 gbPalette[128]; -u8 gbBgp[4] = { 0, 1, 2, 3}; -u8 gbObp0[4] = { 0, 1, 2, 3}; -u8 gbObp1[4] = { 0, 1, 2, 3}; -int gbWindowLine = -1; - -bool genericflashcardEnable = false; -int gbCgbMode = 0; - -u16 gbColorFilter[32768]; -int gbColorOption = 0; -int gbPaletteOption = 0; -int gbEmulatorType = 0; -int gbBorderOn = 1; -int gbBorderAutomatic = 0; -int gbBorderLineSkip = 160; -int gbBorderRowSkip = 0; -int gbBorderColumnSkip = 0; -int gbDmaTicks = 0; - -u8 (*gbSerialFunction)(u8) = NULL; diff --git a/src/dmg/gbGlobals.h b/src/dmg/gbGlobals.h deleted file mode 100644 index ef9a8838..00000000 --- a/src/dmg/gbGlobals.h +++ /dev/null @@ -1,93 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -extern int gbRomSizeMask; -extern int gbRomSize; -extern int gbRamSize; -extern int gbRamSizeMask; -extern int gbTAMA5ramSize; - -extern bool useBios; -extern bool skipBios; -extern u8 *bios; - -extern u8 *gbRom; -extern u8 *gbRam; -extern u8 *gbVram; -extern u8 *gbWram; -extern u8 *gbMemory; -extern u16 *gbLineBuffer; -extern u8 *gbTAMA5ram; -//Brunni/ Used for custom tiles -extern u8 *gbExternalVram; - -extern u8 *gbMemoryMap[16]; - -extern int gbFrameSkip; -extern u16 gbColorFilter[32768]; -extern int gbColorOption; -extern int gbPaletteOption; -extern int gbEmulatorType; -extern int gbBorderOn; -extern int gbBorderAutomatic; -extern int gbCgbMode; -extern int gbSgbMode; -extern int gbWindowLine; -extern int gbSpeed; -extern u8 gbBgp[4]; -extern u8 gbObp0[4]; -extern u8 gbObp1[4]; -extern u16 gbPalette[128]; -extern bool gbScreenOn; -extern bool gbDrawWindow; -extern u8 gbSCYLine[300]; -// gbSCXLine is used for the emulation (bug) of the SX change -// found in the Artic Zone game. -extern u8 gbSCXLine[300]; -// gbBgpLine is used for the emulation of the -// Prehistorik Man's title screen scroller. -extern u8 gbBgpLine[300]; -extern u8 gbObp0Line [300]; -extern u8 gbObp1Line [300]; -// gbSpritesTicks is used for the emulation of Parodius' Laser Beam. -extern u8 gbSpritesTicks[300]; - -extern u8 register_LCDC; -extern u8 register_LY; -extern u8 register_SCY; -extern u8 register_SCX; -extern u8 register_WY; -extern u8 register_WX; -extern u8 register_VBK; -extern u8 oldRegister_WY; - -extern int emulating; -extern bool genericflashcardEnable; - -extern int gbBorderLineSkip; -extern int gbBorderRowSkip; -extern int gbBorderColumnSkip; -extern int gbDmaTicks; - -extern void gbRenderLine(); -extern void gbDrawSprites(bool); -//Brunni/ Needs to be called when the screen switches from "blank" to "normal" -extern void exiting_lcdc(); - -extern u8 (*gbSerialFunction)(u8); diff --git a/src/dmg/gbMemory.cpp b/src/dmg/gbMemory.cpp deleted file mode 100644 index afc89232..00000000 --- a/src/dmg/gbMemory.cpp +++ /dev/null @@ -1,1717 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "../agb/GBA.h" -#include "../Port.h" -#include "gbGlobals.h" -#include "gbMemory.h" -#include "gb.h" -u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -const u8 gbDisabledRam [8] = {0x80, 0xff, 0xf0, 0x00, 0x30, 0xbf, 0xbf, 0xbf}; -extern int gbHardware; -extern int gbGBCColorType; -extern gbRegister PC; - -mapperMBC1 gbDataMBC1 = { - 0, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // memory model - 0, // ROM high address - 0, // RAM address - 0 // Rom Bank 0 remapping -}; - -// MBC1 ROM write registers -void mapperMBC1ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // RAM enable register - gbDataMBC1.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0); - break; - case 0x2000: // ROM bank select - // value = value & 0x1f; - if ((value == 1) && (address == 0x2100)) - gbDataMBC1.mapperRomBank0Remapping = 1; - - if((value & 0x1f) == 0) - value += 1; - if(value == gbDataMBC1.mapperROMBank) - break; - - tmpAddress = value << 14; - - // check current model - if (gbDataMBC1.mapperRomBank0Remapping == 3) { - tmpAddress = (value & 0xf) << 14; - tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 18; - } - else - if(gbDataMBC1.mapperMemoryModel == 0) { - // model is 16/8, so we have a high address in use - tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 19; - } - - tmpAddress &= gbRomSizeMask; - gbDataMBC1.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - break; - case 0x4000: // RAM bank select - if(gbDataMBC1.mapperMemoryModel == 1) { - if (!gbRamSize) - { - if (gbDataMBC1.mapperRomBank0Remapping == 3) - { - gbDataMBC1.mapperROMHighAddress = value & 0x03; - tmpAddress = (gbDataMBC1.mapperROMHighAddress) << 18; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x00] = &gbRom[tmpAddress]; - gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; - gbMemoryMap[0x04] = &gbRom[tmpAddress + 0x4000]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x5000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x6000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x7000]; - } - else gbDataMBC1.mapperRomBank0Remapping = 0; - } - // 4/32 model, RAM bank switching provided - value = value & 0x03; - if(value == gbDataMBC1.mapperRAMBank) - break; - tmpAddress = value << 13; - tmpAddress &= gbRamSizeMask; - if(gbRamSize) { - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - } - gbDataMBC1.mapperRAMBank = value; - gbDataMBC1.mapperRAMAddress = tmpAddress; - - if (gbDataMBC1.mapperRomBank0Remapping != 3) - gbDataMBC1.mapperROMHighAddress = 0; - } else { - // 16/8, set the high address - gbDataMBC1.mapperROMHighAddress = value & 0x03; - tmpAddress = gbDataMBC1.mapperROMBank << 14; - tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - if(gbRamSize) { - gbMemoryMap[0x0a] = &gbRam[0]; - gbMemoryMap[0x0b] = &gbRam[0x1000]; - } - - gbDataMBC1.mapperRAMBank = 0; - } - break; - case 0x6000: // memory model select - gbDataMBC1.mapperMemoryModel = value & 1; - - if(gbDataMBC1.mapperMemoryModel == 1) { - // 4/32 model, RAM bank switching provided - - value = gbDataMBC1.mapperRAMBank & 0x03; - tmpAddress = value << 13; - tmpAddress &= gbRamSizeMask; - if(gbRamSize) { - gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress]; - gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000]; - gbDataMBC1.mapperRomBank0Remapping = 0; - } - else gbDataMBC1.mapperRomBank0Remapping |=2; - - gbDataMBC1.mapperRAMBank = value; - gbDataMBC1.mapperRAMAddress = tmpAddress; - - tmpAddress = gbDataMBC1.mapperROMBank << 14; - - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - } else { - // 16/8, set the high address - - tmpAddress = gbDataMBC1.mapperROMBank << 14; - tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - if(gbRamSize) { - gbMemoryMap[0x0a] = &gbRam[0]; - gbMemoryMap[0x0b] = &gbRam[0x1000]; - } - } - break; - } -} - -// MBC1 RAM write -void mapperMBC1RAM(u16 address, u8 value) -{ - if(gbDataMBC1.mapperRAMEnable) { - if(gbRamSize) { - gbMemoryMap[address >> 12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } -} - -// MBC1 read RAM -u8 mapperMBC1ReadRAM(u16 address) -{ - - if(gbDataMBC1.mapperRAMEnable) - return gbMemoryMap[address>>12][address & 0x0fff]; - - if (!genericflashcardEnable) - return 0xff; - else - if ((address & 0x1000) >= 0x1000) - { - // The value returned when reading RAM while it's disabled - // is constant, exept for the GBASP hardware. - // (actually, is the address that read is out of the ROM, the returned value if 0xff...) - if (PC.W>=0xff80) - return 0xff; - else - if ((gbHardware & 0x08) && (gbGBCColorType == 2)) - { - if (address & 1) - return 0xfb; - else - return 0x7a; - } - else - return 0x0a; - } - else - return gbDisabledRam[address & 7]; -} - -void memoryUpdateMapMBC1() -{ - int tmpAddress = gbDataMBC1.mapperROMBank << 14; - - // check current model - if (gbDataMBC1.mapperRomBank0Remapping == 3) { - tmpAddress = (gbDataMBC1.mapperROMHighAddress & 3) << 18; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x00] = &gbRom[tmpAddress]; - gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; - - tmpAddress |= (gbDataMBC1.mapperROMBank & 0xf) << 14; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - } - else - { - if(gbDataMBC1.mapperMemoryModel == 0) { - // model is 16/8, so we have a high address in use - tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 19; - } - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - } - - if((gbRamSize) && (gbDataMBC1.mapperMemoryModel == 1)){ - gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress]; - gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000]; - } -} - -mapperMBC2 gbDataMBC2 = { - 0, // RAM enable - 1 // ROM bank -}; - -// MBC2 ROM write registers -void mapperMBC2ROM(u16 address, u8 value) -{ - switch(address & 0x6000) { - case 0x0000: // RAM enable - if(!(address & 0x0100)) { - gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a; - } - break; - case 0x2000: // ROM bank select - if(address & 0x0100) { - value &= 0x0f; - - if(value == 0) - value = 1; - if(gbDataMBC2.mapperROMBank != value) { - gbDataMBC2.mapperROMBank = value; - - int tmpAddress = value << 14; - - tmpAddress &= gbRomSizeMask; - - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - } - } - break; - } -} - -// MBC2 RAM write -void mapperMBC2RAM(u16 address, u8 value) -{ - if(gbDataMBC2.mapperRAMEnable) { - if(gbRamSize && address < 0xa200) { - gbMemoryMap[address >> 12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } -} - -void memoryUpdateMapMBC2() -{ - int tmpAddress = gbDataMBC2.mapperROMBank << 14; - - tmpAddress &= gbRomSizeMask; - - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; -} - -mapperMBC3 gbDataMBC3 = { - 0, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // RAM address - 0, // timer clock latch - 0, // timer clock register - 0, // timer seconds - 0, // timer minutes - 0, // timer hours - 0, // timer days - 0, // timer control - 0, // timer latched seconds - 0, // timer latched minutes - 0, // timer latched hours - 0, // timer latched days - 0, // timer latched control - (time_t)-1 // last time -}; - -void memoryUpdateMBC3Clock() -{ - time_t now = time(NULL); - time_t diff = now - gbDataMBC3.mapperLastTime; - if(diff > 0) { - // update the clock according to the last update time - gbDataMBC3.mapperSeconds += (int)(diff % 60); - if(gbDataMBC3.mapperSeconds > 59) { - gbDataMBC3.mapperSeconds -= 60; - gbDataMBC3.mapperMinutes++; - } - - diff /= 60; - - gbDataMBC3.mapperMinutes += (int)(diff % 60); - if(gbDataMBC3.mapperMinutes > 59) { - gbDataMBC3.mapperMinutes -= 60; - gbDataMBC3.mapperHours++; - } - - diff /= 60; - - gbDataMBC3.mapperHours += (int)(diff % 24); - if(gbDataMBC3.mapperHours > 23) { - gbDataMBC3.mapperHours -= 24; - gbDataMBC3.mapperDays++; - } - diff /= 24; - - gbDataMBC3.mapperDays += (int)(diff & 0xffffffff); - if(gbDataMBC3.mapperDays > 255) { - if(gbDataMBC3.mapperDays > 511) { - gbDataMBC3.mapperDays %= 512; - gbDataMBC3.mapperControl |= 0x80; - } - gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | - (gbDataMBC3.mapperDays>255 ? 1 : 0); - } - } - gbDataMBC3.mapperLastTime = now; -} - -// MBC3 ROM write registers -void mapperMBC3ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // RAM enable register - gbDataMBC3.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0); - break; - case 0x2000: // ROM bank select - value = value & 0x7f; - if(value == 0) - value = 1; - if(value == gbDataMBC3.mapperROMBank) - break; - - tmpAddress = value << 14; - - tmpAddress &= gbRomSizeMask; - gbDataMBC3.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - break; - case 0x4000: // RAM bank select - if(value < 8) { - if(value == gbDataMBC3.mapperRAMBank) - break; - tmpAddress = value << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - gbDataMBC3.mapperRAMBank = value; - gbDataMBC3.mapperRAMAddress = tmpAddress; - } else { - if(gbDataMBC3.mapperRAMEnable) { - gbDataMBC3.mapperRAMBank = -1; - - gbDataMBC3.mapperClockRegister = value; - } - } - break; - case 0x6000: // clock latch - if(gbDataMBC3.mapperClockLatch == 0 && value == 1) { - memoryUpdateMBC3Clock(); - gbDataMBC3.mapperLSeconds = gbDataMBC3.mapperSeconds; - gbDataMBC3.mapperLMinutes = gbDataMBC3.mapperMinutes; - gbDataMBC3.mapperLHours = gbDataMBC3.mapperHours; - gbDataMBC3.mapperLDays = gbDataMBC3.mapperDays; - gbDataMBC3.mapperLControl = gbDataMBC3.mapperControl; - } - if(value == 0x00 || value == 0x01) - gbDataMBC3.mapperClockLatch = value; - break; - } -} - -// MBC3 RAM write -void mapperMBC3RAM(u16 address, u8 value) -{ - if(gbDataMBC3.mapperRAMEnable) { - if(gbDataMBC3.mapperRAMBank != -1) { - if(gbRamSize) { - gbMemoryMap[address>>12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } else { - time(&gbDataMBC3.mapperLastTime); - switch(gbDataMBC3.mapperClockRegister) { - case 0x08: - gbDataMBC3.mapperSeconds = value; - break; - case 0x09: - gbDataMBC3.mapperMinutes = value; - break; - case 0x0a: - gbDataMBC3.mapperHours = value; - break; - case 0x0b: - gbDataMBC3.mapperDays = value; - break; - case 0x0c: - if(gbDataMBC3.mapperControl & 0x80) - gbDataMBC3.mapperControl = 0x80 | value; - else - gbDataMBC3.mapperControl = value; - break; - } - } - } -} - -// MBC3 read RAM -u8 mapperMBC3ReadRAM(u16 address) -{ - if(gbDataMBC3.mapperRAMEnable) { - if(gbDataMBC3.mapperRAMBank != -1) { - return gbMemoryMap[address>>12][address & 0x0fff]; - } - - switch(gbDataMBC3.mapperClockRegister) { - case 0x08: - return gbDataMBC3.mapperLSeconds; - break; - case 0x09: - return gbDataMBC3.mapperLMinutes; - break; - case 0x0a: - return gbDataMBC3.mapperLHours; - break; - case 0x0b: - return gbDataMBC3.mapperLDays; - break; - case 0x0c: - return gbDataMBC3.mapperLControl; - } - } - - if (!genericflashcardEnable) - return 0xff; - else - if ((address & 0x1000) >= 0x1000) - { - // The value returned when reading RAM while it's disabled - // is constant, exept for the GBASP hardware. - // (actually, is the address that read is out of the ROM, the returned value if 0xff...) - if (PC.W>=0xff80) - return 0xff; - else - if ((gbHardware & 0x08) && (gbGBCColorType == 2)) - { - if (address & 1) - return 0xfb; - else - return 0x7a; - } - else - return 0x0a; - } - else - return gbDisabledRam[address & 7]; -} - -void memoryUpdateMapMBC3() -{ - int tmpAddress = gbDataMBC3.mapperROMBank << 14; - - tmpAddress &= gbRomSizeMask; - - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - if(gbDataMBC3.mapperRAMBank >= 0 && gbRamSize) { - tmpAddress = gbDataMBC3.mapperRAMBank << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - } -} - -mapperMBC5 gbDataMBC5 = { - 0, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // ROM high address - 0, // RAM address - 0 // is rumble cartridge? -}; - -// MBC5 ROM write registers -void mapperMBC5ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // RAM enable register - gbDataMBC5.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0); - break; - case 0x2000: // ROM bank select - - if(address < 0x3000) { - value = value & 0xff; - if(value == gbDataMBC5.mapperROMBank) - break; - - tmpAddress = (value << 14) | (gbDataMBC5.mapperROMHighAddress << 22) ; - - tmpAddress &= gbRomSizeMask; - gbDataMBC5.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - } else { - value = value & 1; - if(value == gbDataMBC5.mapperROMHighAddress) - break; - - tmpAddress = (gbDataMBC5.mapperROMBank << 14) | (value << 22); - - tmpAddress &= gbRomSizeMask; - gbDataMBC5.mapperROMHighAddress = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - } - break; - case 0x4000: // RAM bank select - if(gbDataMBC5.isRumbleCartridge) - value &= 0x07; - else - value &= 0x0f; - if(value == gbDataMBC5.mapperRAMBank) - break; - tmpAddress = value << 13; - tmpAddress &= gbRamSizeMask; - if(gbRamSize) { - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - - gbDataMBC5.mapperRAMBank = value; - gbDataMBC5.mapperRAMAddress = tmpAddress; - } - break; - } -} - -// MBC5 RAM write -void mapperMBC5RAM(u16 address, u8 value) -{ - if(gbDataMBC5.mapperRAMEnable) { - if(gbRamSize) { - gbMemoryMap[address >> 12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } -} - -// MBC5 read RAM -u8 mapperMBC5ReadRAM(u16 address) -{ - - if(gbDataMBC5.mapperRAMEnable) - return gbMemoryMap[address>>12][address & 0x0fff]; - - if (!genericflashcardEnable) - return 0xff; - else - if ((address & 0x1000) >= 0x1000) - { - // The value returned when reading RAM while it's disabled - // is constant, exept for the GBASP hardware. - // (actually, is the address that read is out of the ROM, the returned value if 0xff...) - if (PC.W>=0xff80) - return 0xff; - else - if ((gbHardware & 0x08) && (gbGBCColorType == 2)) - { - if (address & 1) - return 0xfb; - else - return 0x7a; - } - else - return 0x0a; - } - else - return gbDisabledRam[address & 7]; -} - -void memoryUpdateMapMBC5() -{ - int tmpAddress = (gbDataMBC5.mapperROMBank << 14) | - (gbDataMBC5.mapperROMHighAddress << 22) ; - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - if(gbRamSize) { - tmpAddress = gbDataMBC5.mapperRAMBank << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - } -} - -mapperMBC7 gbDataMBC7 = { - 0, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // RAM address - 0, // chip select - 0, // ?? - 0, // mapper state - 0, // buffer for receiving serial data - 0, // idle state - 0, // count of bits received - 0, // command received - 0, // address received - 0, // write enable - 0, // value to return on ram -}; - -// MBC7 ROM write registers -void mapperMBC7ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: - break; - case 0x2000: // ROM bank select - value = value & 0x7f; - if(value == 0) - value = 1; - - if(value == gbDataMBC7.mapperROMBank) - break; - - tmpAddress = (value << 14); - - tmpAddress &= gbRomSizeMask; - gbDataMBC7.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - break; - case 0x4000: // RAM bank select/enable - if(value < 8) { - tmpAddress = (value&3) << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbMemory[0xa000]; - gbMemoryMap[0x0b] = &gbMemory[0xb000]; - - gbDataMBC7.mapperRAMBank = value; - gbDataMBC7.mapperRAMAddress = tmpAddress; - gbDataMBC7.mapperRAMEnable = 0; - } else { - gbDataMBC7.mapperRAMEnable = 0; - } - break; - } -} - -// MBC7 read RAM -u8 mapperMBC7ReadRAM(u16 address) -{ - switch(address & 0xa0f0) { - case 0xa000: - case 0xa010: - case 0xa060: - case 0xa070: - return 0; - case 0xa020: - // sensor X low byte - return systemGetSensorX() & 255; - case 0xa030: - // sensor X high byte - return systemGetSensorX() >> 8; - case 0xa040: - // sensor Y low byte - return systemGetSensorY() & 255; - case 0xa050: - // sensor Y high byte - return systemGetSensorY() >> 8; - case 0xa080: - return gbDataMBC7.value; - } - - if (!genericflashcardEnable) - return 0xff; - else - if ((address & 0x1000) >= 0x1000) - { - // The value returned when reading RAM while it's disabled - // is constant, exept for the GBASP hardware. - // (actually, is the address that read is out of the ROM, the returned value if 0xff...) - if (PC.W>=0xff80) - return 0xff; - else - if ((gbHardware & 0x08) && (gbGBCColorType == 2)) - { - if (address & 1) - return 0xfb; - else - return 0x7a; - } - else - return 0x0a; - } - else - return gbDisabledRam[address & 7]; -} - -// MBC7 RAM write -void mapperMBC7RAM(u16 address, u8 value) -{ - if(address == 0xa080) { - // special processing needed - int oldCs = gbDataMBC7.cs,oldSk=gbDataMBC7.sk; - - gbDataMBC7.cs=value>>7; - gbDataMBC7.sk=(value>>6)&1; - - if(!oldCs && gbDataMBC7.cs) { - if(gbDataMBC7.state==5) { - if(gbDataMBC7.writeEnable) { - gbMemory[0xa000+gbDataMBC7.address*2]=gbDataMBC7.buffer>>8; - gbMemory[0xa000+gbDataMBC7.address*2+1]=gbDataMBC7.buffer&0xff; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - gbDataMBC7.state=0; - gbDataMBC7.value=1; - } else { - gbDataMBC7.idle=true; - gbDataMBC7.state=0; - } - } - - if(!oldSk && gbDataMBC7.sk) { - if(gbDataMBC7.idle) { - if(value & 0x02) { - gbDataMBC7.idle=false; - gbDataMBC7.count=0; - gbDataMBC7.state=1; - } - } else { - switch(gbDataMBC7.state) { - case 1: - // receiving command - gbDataMBC7.buffer <<= 1; - gbDataMBC7.buffer |= (value & 0x02)?1:0; - gbDataMBC7.count++; - if(gbDataMBC7.count==2) { - // finished receiving command - gbDataMBC7.state=2; - gbDataMBC7.count=0; - gbDataMBC7.code=gbDataMBC7.buffer & 3; - } - break; - case 2: - // receive address - gbDataMBC7.buffer <<= 1; - gbDataMBC7.buffer |= (value&0x02)?1:0; - gbDataMBC7.count++; - if(gbDataMBC7.count==8) { - // finish receiving - gbDataMBC7.state=3; - gbDataMBC7.count=0; - gbDataMBC7.address=gbDataMBC7.buffer&0xff; - if(gbDataMBC7.code==0) { - if((gbDataMBC7.address>>6)==0) { - gbDataMBC7.writeEnable=0; - gbDataMBC7.state=0; - } else if((gbDataMBC7.address>>6) == 3) { - gbDataMBC7.writeEnable=1; - gbDataMBC7.state=0; - } - } - } - break; - case 3: - gbDataMBC7.buffer <<= 1; - gbDataMBC7.buffer |= (value&0x02)?1:0; - gbDataMBC7.count++; - - switch(gbDataMBC7.code) { - case 0: - if(gbDataMBC7.count==16) { - if((gbDataMBC7.address>>6)==0) { - gbDataMBC7.writeEnable = 0; - gbDataMBC7.state=0; - } else if((gbDataMBC7.address>>6)==1) { - if (gbDataMBC7.writeEnable) { - for(int i=0;i<256;i++) { - gbMemory[0xa000+i*2] = gbDataMBC7.buffer >> 8; - gbMemory[0xa000+i*2+1] = gbDataMBC7.buffer & 0xff; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } - gbDataMBC7.state=5; - } else if((gbDataMBC7.address>>6) == 2) { - if (gbDataMBC7.writeEnable) { - for(int i=0;i<256;i++) - WRITE16LE((u16 *)&gbMemory[0xa000+i*2], 0xffff); - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - gbDataMBC7.state=5; - } else if((gbDataMBC7.address>>6)==3) { - gbDataMBC7.writeEnable = 1; - gbDataMBC7.state=0; - } - gbDataMBC7.count=0; - } - break; - case 1: - if(gbDataMBC7.count==16) { - gbDataMBC7.count=0; - gbDataMBC7.state=5; - gbDataMBC7.value=0; - } - break; - case 2: - if(gbDataMBC7.count==1) { - gbDataMBC7.state=4; - gbDataMBC7.count=0; - gbDataMBC7.buffer = (gbMemory[0xa000+gbDataMBC7.address*2]<<8)| - (gbMemory[0xa000+gbDataMBC7.address*2+1]); - } - break; - case 3: - if(gbDataMBC7.count==16) { - gbDataMBC7.count=0; - gbDataMBC7.state=5; - gbDataMBC7.value=0; - gbDataMBC7.buffer=0xffff; - } - break; - } - break; - } - } - } - - if (oldSk && !gbDataMBC7.sk) { - if (gbDataMBC7.state==4) { - gbDataMBC7.value = (gbDataMBC7.buffer & 0x8000)?1:0; - gbDataMBC7.buffer <<= 1; - gbDataMBC7.count++; - if (gbDataMBC7.count==16) { - gbDataMBC7.count=0; - gbDataMBC7.state=0; - } - } - } - } -} - -void memoryUpdateMapMBC7() -{ - int tmpAddress = (gbDataMBC7.mapperROMBank << 14); - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; -} - -mapperHuC1 gbDataHuC1 = { - 0, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // memory model - 0, // ROM high address - 0 // RAM address -}; - -// HuC1 ROM write registers -void mapperHuC1ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // RAM enable register - gbDataHuC1.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0); - break; - case 0x2000: // ROM bank select - value = value & 0x3f; - if(value == 0) - value = 1; - if(value == gbDataHuC1.mapperROMBank) - break; - - tmpAddress = value << 14; - - tmpAddress &= gbRomSizeMask; - gbDataHuC1.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - break; - case 0x4000: // RAM bank select - if(gbDataHuC1.mapperMemoryModel == 1) { - // 4/32 model, RAM bank switching provided - value = value & 0x03; - if(value == gbDataHuC1.mapperRAMBank) - break; - tmpAddress = value << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - gbDataHuC1.mapperRAMBank = value; - gbDataHuC1.mapperRAMAddress = tmpAddress; - } else { - // 16/8, set the high address - gbDataHuC1.mapperROMHighAddress = value & 0x03; - tmpAddress = gbDataHuC1.mapperROMBank << 14; - tmpAddress |= (gbDataHuC1.mapperROMHighAddress) << 19; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - } - break; - case 0x6000: // memory model select - gbDataHuC1.mapperMemoryModel = value & 1; - break; - } -} - -// HuC1 RAM write -void mapperHuC1RAM(u16 address, u8 value) -{ - if(gbDataHuC1.mapperRAMEnable) { - if(gbRamSize) { - gbMemoryMap[address >> 12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } -} - -void memoryUpdateMapHuC1() -{ - int tmpAddress = gbDataHuC1.mapperROMBank << 14; - - tmpAddress &= gbRomSizeMask; - - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - if(gbRamSize) { - tmpAddress = gbDataHuC1.mapperRAMBank << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - } -} - -mapperHuC3 gbDataHuC3 = { - 0, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // RAM address - 0, // RAM flag - 0 // RAM read value -}; - - -// HuC3 ROM write registers -void mapperHuC3ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // RAM enable register - gbDataHuC3.mapperRAMEnable = ( value == 0x0a ? 1 : 0); - gbDataHuC3.mapperRAMFlag = value; - if(gbDataHuC3.mapperRAMFlag != 0x0a) - gbDataHuC3.mapperRAMBank = -1; - break; - case 0x2000: // ROM bank select - value = value & 0x7f; - if(value == 0) - value = 1; - if(value == gbDataHuC3.mapperROMBank) - break; - - tmpAddress = value << 14; - - tmpAddress &= gbRomSizeMask; - gbDataHuC3.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - break; - case 0x4000: // RAM bank select - value = value & 0x03; - if(value == gbDataHuC3.mapperRAMBank) - break; - tmpAddress = value << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - gbDataHuC3.mapperRAMBank = value; - gbDataHuC3.mapperRAMAddress = tmpAddress; - break; - case 0x6000: // nothing to do! - break; - } -} - -// HuC3 read RAM -u8 mapperHuC3ReadRAM(u16 address) -{ - if(gbDataHuC3.mapperRAMFlag > 0x0b && - gbDataHuC3.mapperRAMFlag < 0x0e) { - if(gbDataHuC3.mapperRAMFlag != 0x0c) - return 1; - return gbDataHuC3.mapperRAMValue; - } else - return gbMemoryMap[address >> 12][address & 0x0fff]; -} - -// HuC3 RAM write -void mapperHuC3RAM(u16 address, u8 value) -{ - int *p; - - if(gbDataHuC3.mapperRAMFlag < 0x0b || - gbDataHuC3.mapperRAMFlag > 0x0e) { - if(gbDataHuC3.mapperRAMEnable) { - if(gbRamSize) { - gbMemoryMap[address >> 12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } - } else { - if(gbDataHuC3.mapperRAMFlag == 0x0b) { - if(value == 0x62) { - gbDataHuC3.mapperRAMValue = 1; - } else { - switch(value & 0xf0) { - case 0x10: - p = &gbDataHuC3.mapperRegister2; - gbDataHuC3.mapperRAMValue = *(p+gbDataHuC3.mapperRegister1++); - if(gbDataHuC3.mapperRegister1 > 6) - gbDataHuC3.mapperRegister1 = 0; - break; - case 0x30: - p = &gbDataHuC3.mapperRegister2; - *(p+gbDataHuC3.mapperRegister1++) = value & 0x0f; - if(gbDataHuC3.mapperRegister1 > 6) - gbDataHuC3.mapperRegister1 = 0; - gbDataHuC3.mapperAddress = - (gbDataHuC3.mapperRegister6 << 24) | - (gbDataHuC3.mapperRegister5 << 16) | - (gbDataHuC3.mapperRegister4 << 8) | - (gbDataHuC3.mapperRegister3 << 4) | - (gbDataHuC3.mapperRegister2); - break; - case 0x40: - gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) | - (value & 0x0f); - gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f); - gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress>>4)&0x0f); - gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress>>8)&0x0f); - gbDataHuC3.mapperRegister5 = ((gbDataHuC3.mapperAddress>>16)&0x0f); - gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress>>24)&0x0f); - gbDataHuC3.mapperRegister7 = 0; - gbDataHuC3.mapperRegister8 = 0; - gbDataHuC3.mapperRAMValue = 0; - break; - case 0x50: - gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) | - ((value << 4)&0x0f); - break; - default: - gbDataHuC3.mapperRAMValue = 1; - break; - } - } - } - } -} - -void memoryUpdateMapHuC3() -{ - int tmpAddress = gbDataHuC3.mapperROMBank << 14; - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - if(gbRamSize) { - tmpAddress = gbDataHuC3.mapperRAMBank << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - } -} - -// TAMA5 (for Tamagotchi 3 (gb)). -// Very basic (and ugly :p) support, only rom bank switching is actually working... -mapperTAMA5 gbDataTAMA5 = { - 1, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // RAM address - 0, // RAM Byte select - 0, // mapper command number - 0, // mapper last command; - 0, // commands 0x0 - 0, // commands 0x1 - 0, // commands 0x2 - 0, // commands 0x3 - 0, // commands 0x4 - 0, // commands 0x5 - 0, // commands 0x6 - 0, // commands 0x7 - 0, // commands 0x8 - 0, // commands 0x9 - 0, // commands 0xa - 0, // commands 0xb - 0, // commands 0xc - 0, // commands 0xd - 0, // commands 0xe - 0, // commands 0xf - 0, // register - 0, // timer clock latch - 0, // timer clock register - 0, // timer seconds - 0, // timer minutes - 0, // timer hours - 0, // timer days - 0, // timer months - 0, // timer years - 0, // timer control - 0, // timer latched seconds - 0, // timer latched minutes - 0, // timer latched hours - 0, // timer latched days - 0, // timer latched months - 0, // timer latched years - 0, // timer latched control - (time_t)-1 // last time -}; - - -void memoryUpdateTAMA5Clock() -{ - if ((gbDataTAMA5.mapperYears & 3) == 0) - gbDaysinMonth[1] = 29; - else - gbDaysinMonth[1] = 28; - - time_t now = time(NULL); - time_t diff = now - gbDataTAMA5.mapperLastTime; - if(diff > 0) { - // update the clock according to the last update time - gbDataTAMA5.mapperSeconds += (int)(diff % 60); - if(gbDataTAMA5.mapperSeconds > 59) { - gbDataTAMA5.mapperSeconds -= 60; - gbDataTAMA5.mapperMinutes++; - } - - diff /= 60; - - gbDataTAMA5.mapperMinutes += (int)(diff % 60); - if(gbDataTAMA5.mapperMinutes > 59) { - gbDataTAMA5.mapperMinutes -= 60; - gbDataTAMA5.mapperHours++; - } - - diff /= 60; - - gbDataTAMA5.mapperHours += (int)(diff % 24); - diff /= 24; - if(gbDataTAMA5.mapperHours > 23) { - gbDataTAMA5.mapperHours -= 24; - diff++; - - } - - time_t days = diff; - while (days) - { - gbDataTAMA5.mapperDays++; - days--; - if (gbDataTAMA5.mapperDays>gbDaysinMonth[gbDataTAMA5.mapperMonths-1]) - { - gbDataTAMA5.mapperDays = 1; - gbDataTAMA5.mapperMonths++; - if (gbDataTAMA5.mapperMonths>12) - { - gbDataTAMA5.mapperMonths = 1; - gbDataTAMA5.mapperYears++; - if ((gbDataTAMA5.mapperYears & 3) == 0) - gbDaysinMonth[1] = 29; - else - gbDaysinMonth[1] = 28; - } - } - } - } - gbDataTAMA5.mapperLastTime = now; - -} - - - -// TAMA5 RAM write -void mapperTAMA5RAM(u16 address, u8 value) -{ - if ((address & 0xffff) <= 0xa001) - { - switch (address & 1) - { - case 0: // 'Values' Register - { - value &= 0xf; - gbDataTAMA5.mapperCommands[gbDataTAMA5.mapperCommandNumber] = value; - gbMemoryMap[0xa][0] = value; - - int test = gbDataTAMA5.mapperCommands[gbDataTAMA5.mapperCommandNumber & 0x0e] | - (gbDataTAMA5.mapperCommands[(gbDataTAMA5.mapperCommandNumber & 0x0e) +1]<<4); - - if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 0) // Read Command !!! - { - gbDataTAMA5.mapperROMBank = gbDataTAMA5.mapperCommands[0] | - (gbDataTAMA5.mapperCommands[1]<<4); - - int tmpAddress = (gbDataTAMA5.mapperROMBank << 14); - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - gbDataTAMA5.mapperCommands[0x0f] = 0; - } - else if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 4) - { - gbDataTAMA5.mapperCommands[0x0f] = 1; - if (gbDataTAMA5.mapperCommandNumber == 4) - gbDataTAMA5.mapperCommands[5] =0; // correct ? - } - else if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 6) - { - gbDataTAMA5.mapperRamByteSelect = (gbDataTAMA5.mapperCommands[7]<<4) | - (gbDataTAMA5.mapperCommands[6]&0x0f); - - // Write Commands !!! - if (gbDataTAMA5.mapperCommands[0x0f] && (gbDataTAMA5.mapperCommandNumber == 7)) - { - int data = gbDataTAMA5.mapperCommands[0x04] & 0x0f | - (gbDataTAMA5.mapperCommands[0x05] <<4); - - // Not sure when the write command should reset... - // but it doesn't seem to matter. - // gbDataTAMA5.mapperCommands[0x0f] = 0; - - if (gbDataTAMA5.mapperRamByteSelect == 0x8) // Timer stuff - { - switch (data & 0xf) - { - case 0x7: - gbDataTAMA5.mapperDays = ((gbDataTAMA5.mapperDays)/10)*10 + (data >> 4); - break; - case 0x8: - gbDataTAMA5.mapperDays = (gbDataTAMA5.mapperDays%10) + (data >>4)*10; - break; - case 0x9: - gbDataTAMA5.mapperMonths = ((gbDataTAMA5.mapperMonths)/10)*10 + (data >> 4); - break; - case 0xa: - gbDataTAMA5.mapperMonths = (gbDataTAMA5.mapperMonths%10) + (data >>4)*10; - break; - case 0xb: - gbDataTAMA5.mapperYears = ((gbDataTAMA5.mapperYears)%1000) + (data >> 4)*1000; - break; - case 0xc: - gbDataTAMA5.mapperYears = (gbDataTAMA5.mapperYears%100) + (gbDataTAMA5.mapperYears/1000)*1000 + - (data >>4)*100; - break; - default : - break; - } - } - else if (gbDataTAMA5.mapperRamByteSelect == 0x18) // Timer stuff again - { - memoryUpdateTAMA5Clock(); - gbDataTAMA5.mapperLSeconds = gbDataTAMA5.mapperSeconds; - gbDataTAMA5.mapperLMinutes = gbDataTAMA5.mapperMinutes; - gbDataTAMA5.mapperLHours = gbDataTAMA5.mapperHours; - gbDataTAMA5.mapperLDays = gbDataTAMA5.mapperDays; - gbDataTAMA5.mapperLMonths = gbDataTAMA5.mapperMonths; - gbDataTAMA5.mapperLYears = gbDataTAMA5.mapperYears; - gbDataTAMA5.mapperLControl = gbDataTAMA5.mapperControl; - - int seconds = (gbDataTAMA5.mapperLSeconds / 10)*16 + gbDataTAMA5.mapperLSeconds %10; - int secondsL = (gbDataTAMA5.mapperLSeconds % 10); - int secondsH = (gbDataTAMA5.mapperLSeconds / 10); - int minutes = (gbDataTAMA5.mapperLMinutes / 10)*16 + gbDataTAMA5.mapperLMinutes %10; - int hours = (gbDataTAMA5.mapperLHours / 10)*16 + gbDataTAMA5.mapperLHours %10; - int DaysL = gbDataTAMA5.mapperLDays % 10; - int DaysH = gbDataTAMA5.mapperLDays /10; - int MonthsL = gbDataTAMA5.mapperLMonths % 10; - int MonthsH = gbDataTAMA5.mapperLMonths / 10; - int Years3 = (gbDataTAMA5.mapperLYears / 100) % 10; - int Years4 = (gbDataTAMA5.mapperLYears / 1000); - - switch (data & 0x0f) - { - // I guess cases 0 and 1 are used for secondsL and secondsH - // so the game would update the timer values on screen when - // the seconds reset to 0... ? - case 0x0: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = secondsL; - break; - case 0x1: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = secondsH; - break; - case 0x7: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = DaysL; // days low - break; - case 0x8: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = DaysH; // days high - break; - case 0x9: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = MonthsL; // month low - break; - case 0xa: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = MonthsH; // month high - break; - case 0xb: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = Years4; // years 4th digit - break; - case 0xc: - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = Years3; // years 3rd digit - break; - default : - break; - } - - gbTAMA5ram[0x54] = seconds; // incorrect ? (not used by the game) ? - gbTAMA5ram[0x64] = minutes; - gbTAMA5ram[0x74] = hours; - gbTAMA5ram[0x84] = DaysH*16+DaysL; // incorrect ? (not used by the game) ? - gbTAMA5ram[0x94] = MonthsH*16+MonthsL; // incorrect ? (not used by the game) ? - - time(&gbDataTAMA5.mapperLastTime); - - gbMemoryMap[0xa][0] = 1; - } - else if (gbDataTAMA5.mapperRamByteSelect == 0x28) // Timer stuff again - { - if ((data & 0xf) == 0xb) - gbDataTAMA5.mapperYears = ((gbDataTAMA5.mapperYears>>2)<<2) + (data & 3); - } - else if (gbDataTAMA5.mapperRamByteSelect == 0x44) - { - gbDataTAMA5.mapperMinutes = (data/16)*10 + data%16; - } - else if (gbDataTAMA5.mapperRamByteSelect == 0x54) - { - gbDataTAMA5.mapperHours = (data/16)*10 + data%16; - } - else - { - gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = data; - } - } - } - } - break; - case 1: // 'Commands' Register - { - gbMemoryMap[0xa][1] = gbDataTAMA5.mapperCommandNumber = value; - - // This should be only a 'is the flashrom ready ?' command. - // However as I couldn't find any 'copy' command - // (that seems to be needed for the saving system to work) - // I put it there... - if (value == 0x0a) - { - for (int i = 0; i<0x10; i++) - for (int j = 0; j<0x10; j++) - if (!(j&2)) - gbTAMA5ram[(i*0x10)+j | 2] = gbTAMA5ram[(i*0x10)+j]; - // Enable this to see the content of the flashrom in 0xe000 - /*for (int k = 0; k<0x100; k++) - gbMemoryMap[0xe][k] = gbTAMA5ram[k];*/ - - gbMemoryMap[0xa][0] = gbDataTAMA5.mapperRAMEnable = 1; - } - else - { - if ((value & 0x0e) == 0x0c) - { - gbDataTAMA5.mapperRamByteSelect = gbDataTAMA5.mapperCommands[6] | - (gbDataTAMA5.mapperCommands[7]<<4); - - u8 byte = gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect]; - - gbMemoryMap[0xa][0] = (value & 1) ? byte >> 4 : byte & 0x0f; - - gbDataTAMA5.mapperCommands[0x0f] = 0; - } - } - break; - } - } - } - else - { - if(gbDataTAMA5.mapperRAMEnable) { - if(gbDataTAMA5.mapperRAMBank != -1) { - if(gbRamSize) { - gbMemoryMap[address>>12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } - } - } -} - - -// TAMA5 read RAM -u8 mapperTAMA5ReadRAM(u16 address) -{ - return gbMemoryMap[address>>12][address & 0xfff]; -} - - -void memoryUpdateMapTAMA5() -{ - int tmpAddress = (gbDataTAMA5.mapperROMBank << 14); - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - if(gbRamSize) { - tmpAddress = 0 << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - } -} - -// MMM01 Used in Momotarou collection (however the rom is corrupted) -mapperMMM01 gbDataMMM01 ={ - 0, // RAM enable - 1, // ROM bank - 0, // RAM bank - 0, // memory model - 0, // ROM high address - 0, // RAM address - 0 // Rom Bank 0 remapping -}; - -// MMM01 ROM write registers -void mapperMMM01ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // RAM enable register - gbDataMMM01.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0); - break; - case 0x2000: // ROM bank select - // value = value & 0x1f; - if(value == 0) - value = 1; - if(value == gbDataMMM01.mapperROMBank) - break; - - tmpAddress = value << 14; - - // check current model - if(gbDataMMM01.mapperMemoryModel == 0) { - // model is 16/8, so we have a high address in use - tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19; - } - else - tmpAddress |= gbDataMMM01.mapperRomBank0Remapping << 18; - - tmpAddress &= gbRomSizeMask; - gbDataMMM01.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - break; - case 0x4000: // RAM bank select - if(gbDataMMM01.mapperMemoryModel == 1) { - // 4/32 model, RAM bank switching provided - value = value & 0x03; - if(value == gbDataMBC1.mapperRAMBank) - break; - tmpAddress = value << 13; - tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; - gbDataMMM01.mapperRAMBank = value; - gbDataMMM01.mapperRAMAddress = tmpAddress; - } else { - // 16/8, set the high address - gbDataMMM01.mapperROMHighAddress = value & 0x03; - tmpAddress = gbDataMMM01.mapperROMBank << 14; - tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - gbDataMMM01.mapperRomBank0Remapping = ((value<<1) | (value & 0x40 ? 1 : 0)) & 0xff; - tmpAddress = gbDataMMM01.mapperRomBank0Remapping << 18; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x00] = &gbRom[tmpAddress]; - gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; - } - break; - case 0x6000: // memory model select - gbDataMMM01.mapperMemoryModel = value & 1; - break; - } -} - -// MMM01 RAM write -void mapperMMM01RAM(u16 address, u8 value) -{ - if(gbDataMMM01.mapperRAMEnable) { - if(gbRamSize) { - gbMemoryMap[address >> 12][address & 0x0fff] = value; - systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; - } - } -} - -void memoryUpdateMapMMM01() -{ - int tmpAddress = gbDataMMM01.mapperROMBank << 14; - - // check current model - if(gbDataMMM01.mapperMemoryModel == 1) { - // model is 16/8, so we have a high address in use - tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19; - } - - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; - - tmpAddress = gbDataMMM01.mapperRomBank0Remapping << 18; - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x00] = &gbRom[tmpAddress]; - gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; - - if(gbRamSize) { - gbMemoryMap[0x0a] = &gbRam[gbDataMMM01.mapperRAMAddress]; - gbMemoryMap[0x0b] = &gbRam[gbDataMMM01.mapperRAMAddress + 0x1000]; - } -} - -// GameGenie ROM write registers -void mapperGGROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // RAM enable register - break; - case 0x2000: // GameGenie has only a half bank - break; - case 0x4000: // GameGenie has no RAM - if ((address >=0x4001) && (address <= 0x4020)) // GG Hardware Registers - gbMemoryMap[address >> 12][address & 0x0fff] = value; - break; - case 0x6000: // GameGenie has only a half bank - break; - } -} - - -// GS3 Used to emulate the GS V3.0 rom bank switching -mapperGS3 gbDataGS3 = { 1 }; // ROM bank - -void mapperGS3ROM(u16 address, u8 value) -{ - int tmpAddress = 0; - - switch(address & 0x6000) { - case 0x0000: // GS has no ram - break; - case 0x2000: // GS has no 'classic' ROM bank select - break; - case 0x4000: // GS has no ram - break; - case 0x6000: // 0x6000 area is RW, and used for GS hardware registers - - if (address == 0x7FE1) // This is the (half) ROM bank select register - { - if(value == gbDataGS3.mapperROMBank) - break; - tmpAddress = value << 13; - - tmpAddress &= gbRomSizeMask; - gbDataGS3.mapperROMBank = value; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - } - else - gbMemoryMap[address>>12][address & 0x0fff] = value; - break; - } -} - -void memoryUpdateMapGS3() -{ - int tmpAddress = gbDataGS3.mapperROMBank << 13; - - tmpAddress &= gbRomSizeMask; - // GS can only change a half ROM bank - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; -} diff --git a/src/dmg/gbMemory.h b/src/dmg/gbMemory.h deleted file mode 100644 index ef714d19..00000000 --- a/src/dmg/gbMemory.h +++ /dev/null @@ -1,206 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include - -struct mapperMBC1 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperMemoryModel; - int mapperROMHighAddress; - int mapperRAMAddress; - int mapperRomBank0Remapping; -}; - -struct mapperMBC2 { - int mapperRAMEnable; - int mapperROMBank; -}; - -struct mapperMBC3 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperRAMAddress; - int mapperClockLatch; - int mapperClockRegister; - int mapperSeconds; - int mapperMinutes; - int mapperHours; - int mapperDays; - int mapperControl; - int mapperLSeconds; - int mapperLMinutes; - int mapperLHours; - int mapperLDays; - int mapperLControl; - time_t mapperLastTime; -}; - -struct mapperMBC5 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperROMHighAddress; - int mapperRAMAddress; - int isRumbleCartridge; -}; - -struct mapperMBC7 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperRAMAddress; - int cs; - int sk; - int state; - int buffer; - int idle; - int count; - int code; - int address; - int writeEnable; - int value; -}; - -struct mapperHuC1 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperMemoryModel; - int mapperROMHighAddress; - int mapperRAMAddress; -}; - -struct mapperHuC3 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperRAMAddress; - int mapperAddress; - int mapperRAMFlag; - int mapperRAMValue; - int mapperRegister1; - int mapperRegister2; - int mapperRegister3; - int mapperRegister4; - int mapperRegister5; - int mapperRegister6; - int mapperRegister7; - int mapperRegister8; -}; - -struct mapperTAMA5 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperRAMAddress; - int mapperRamByteSelect; - int mapperCommandNumber; - int mapperLastCommandNumber; - int mapperCommands[0x10]; - int mapperRegister; - int mapperClockLatch; - int mapperClockRegister; - int mapperSeconds; - int mapperMinutes; - int mapperHours; - int mapperDays; - int mapperMonths; - int mapperYears; - int mapperControl; - int mapperLSeconds; - int mapperLMinutes; - int mapperLHours; - int mapperLDays; - int mapperLMonths; - int mapperLYears; - int mapperLControl; - time_t mapperLastTime; -}; - -struct mapperMMM01 { - int mapperRAMEnable; - int mapperROMBank; - int mapperRAMBank; - int mapperMemoryModel; - int mapperROMHighAddress; - int mapperRAMAddress; - int mapperRomBank0Remapping; -}; - -struct mapperGS3 { - int mapperROMBank; -}; - -extern mapperMBC1 gbDataMBC1; -extern mapperMBC2 gbDataMBC2; -extern mapperMBC3 gbDataMBC3; -extern mapperMBC5 gbDataMBC5; -extern mapperHuC1 gbDataHuC1; -extern mapperHuC3 gbDataHuC3; -extern mapperTAMA5 gbDataTAMA5; -extern mapperMMM01 gbDataMMM01; -extern mapperGS3 gbDataGS3; - -void mapperMBC1ROM(u16,u8); -void mapperMBC1RAM(u16,u8); -u8 mapperMBC1ReadRAM(u16); -void mapperMBC2ROM(u16,u8); -void mapperMBC2RAM(u16,u8); -void mapperMBC3ROM(u16,u8); -void mapperMBC3RAM(u16,u8); -u8 mapperMBC3ReadRAM(u16); -void mapperMBC5ROM(u16,u8); -void mapperMBC5RAM(u16,u8); -u8 mapperMBC5ReadRAM(u16); -void mapperMBC7ROM(u16,u8); -void mapperMBC7RAM(u16,u8); -u8 mapperMBC7ReadRAM(u16); -void mapperHuC1ROM(u16,u8); -void mapperHuC1RAM(u16,u8); -void mapperHuC3ROM(u16,u8); -void mapperHuC3RAM(u16,u8); -u8 mapperHuC3ReadRAM(u16); -void mapperTAMA5RAM(u16,u8); -u8 mapperTAMA5ReadRAM(u16); -void memoryUpdateTAMA5Clock(); -void mapperMMM01ROM(u16,u8); -void mapperMMM01RAM(u16,u8); -void mapperGGROM(u16,u8); -void mapperGS3ROM(u16,u8); -//extern void (*mapper)(u16,u8); -//extern void (*mapperRAM)(u16,u8); -//extern u8 (*mapperReadRAM)(u16); - -extern void memoryUpdateMapMBC1(); -extern void memoryUpdateMapMBC2(); -extern void memoryUpdateMapMBC3(); -extern void memoryUpdateMapMBC5(); -extern void memoryUpdateMapMBC7(); -extern void memoryUpdateMapHuC1(); -extern void memoryUpdateMapHuC3(); -extern void memoryUpdateMapTAMA5(); -extern void memoryUpdateMapMMM01(); -extern void memoryUpdateMapGS3(); - - - - diff --git a/src/dmg/gbPrinter.cpp b/src/dmg/gbPrinter.cpp deleted file mode 100644 index c3fda855..00000000 --- a/src/dmg/gbPrinter.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include -#include "../agb/GBA.h" - -u8 gbPrinterStatus = 0; -int gbPrinterState = 0; -u8 gbPrinterData[0x280*9]; -u8 gbPrinterPacket[0x400]; -int gbPrinterCount = 0; -int gbPrinterDataCount = 0; -int gbPrinterDataSize = 0; -int gbPrinterResult = 0; - -bool gbPrinterCheckCRC() -{ - u16 crc = 0; - - for(int i = 2; i < (6+gbPrinterDataSize); i++) { - crc += gbPrinterPacket[i]; - } - - int msgCrc = gbPrinterPacket[6+gbPrinterDataSize] + - (gbPrinterPacket[7+gbPrinterDataSize]<<8); - - return msgCrc == crc; -} - -void gbPrinterReset() -{ - gbPrinterState = 0; - gbPrinterDataSize = 0; - gbPrinterDataCount = 0; - gbPrinterCount = 0; - gbPrinterStatus = 0; - gbPrinterResult = 0; -} - -void gbPrinterShowData() -{ - systemGbPrint(gbPrinterData, - gbPrinterPacket[6], - gbPrinterPacket[7], - gbPrinterPacket[8], - gbPrinterPacket[9]); - /* - allegro_init(); - install_keyboard(); - set_gfx_mode(GFX_AUTODETECT, 160, 144, 0, 0); - PALETTE pal; - pal[0].r = 255; - pal[0].g = 255; - pal[0].b = 255; - pal[1].r = 168; - pal[1].g = 168; - pal[1].b = 168; - pal[2].r = 96; - pal[2].g = 96; - pal[2].b = 96; - pal[3].r = 0; - pal[3].g = 0; - pal[3].b = 0; - set_palette(pal); - acquire_screen(); - u8 *data = gbPrinterData; - for(int y = 0; y < 0x12; y++) { - for(int x = 0; x < 0x14; x++) { - for(int k = 0; k < 8; k++) { - int a = *data++; - int b = *data++; - for(int j = 0; j < 8; j++) { - int mask = 1 << (7-j); - int c = 0; - if(a & mask) - c++; - if(b & mask) - c+=2; - putpixel(screen, x*8+j, y*8+k, c); - } - } - } - } - release_screen(); - while(!keypressed()) { - } - */ -} - -void gbPrinterReceiveData() -{ - if(gbPrinterPacket[3]) { // compressed - u8 *data = &gbPrinterPacket[6]; - u8 *dest = &gbPrinterData[gbPrinterDataCount]; - int len = 0; - while(len < gbPrinterDataSize) { - u8 control = *data++; - if(control & 0x80) { // repeated data - control &= 0x7f; - control += 2; - memset(dest, *data++, control); - len += control; - dest += control; - } else { // raw data - control++; - memcpy(dest, data, control); - dest += control; - data += control; - len += control; - } - } - } else { - memcpy(&gbPrinterData[gbPrinterDataCount], - &gbPrinterPacket[6], - gbPrinterDataSize); - gbPrinterDataCount += gbPrinterDataSize; - } -} - -void gbPrinterCommand() -{ - switch(gbPrinterPacket[2]) { - case 0x01: - // reset/initialize packet - gbPrinterDataCount = 0; - gbPrinterStatus = 0; - break; - case 0x02: - // print packet - gbPrinterShowData(); - break; - case 0x04: - // data packet - gbPrinterReceiveData(); - break; - case 0x0f: - // NUL packet - break; - } -} - -u8 gbPrinterSend(u8 b) -{ - switch(gbPrinterState) { - case 0: - gbPrinterCount = 0; - // receiving preamble - if(b == 0x88) { - gbPrinterPacket[gbPrinterCount++] = b; - gbPrinterState++; - } else { - // todo: handle failure - gbPrinterReset(); - } - break; - case 1: - // receiving preamble - if(b == 0x33) { - gbPrinterPacket[gbPrinterCount++] = b; - gbPrinterState++; - } else { - // todo: handle failure - gbPrinterReset(); - } - break; - case 2: - // receiving header - gbPrinterPacket[gbPrinterCount++] = b; - if(gbPrinterCount == 6) { - gbPrinterState++; - gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5]<<8); - } - break; - case 3: - // receiving data - if(gbPrinterDataSize) { - gbPrinterPacket[gbPrinterCount++] = b; - if(gbPrinterCount == (6+gbPrinterDataSize)) { - gbPrinterState++; - } - break; - } - gbPrinterState++; - // intentionally move to next if no data to receive - case 4: - // receiving CRC - gbPrinterPacket[gbPrinterCount++] = b; - gbPrinterState++; - break; - case 5: - // receiving CRC-2 - gbPrinterPacket[gbPrinterCount++] = b; - if(gbPrinterCheckCRC()) { - gbPrinterCommand(); - } - gbPrinterState++; - break; - case 6: - // receiving dummy 1 - gbPrinterPacket[gbPrinterCount++] = b; - gbPrinterResult = 0x81; - gbPrinterState++; - break; - case 7: - // receiving dummy 2 - gbPrinterPacket[gbPrinterCount++] = b; - gbPrinterResult = gbPrinterStatus; - gbPrinterState = 0; - gbPrinterCount = 0; - break; - } - return gbPrinterResult; -} diff --git a/src/dmg/gbPrinter.h b/src/dmg/gbPrinter.h deleted file mode 100644 index 9bebd4e3..00000000 --- a/src/dmg/gbPrinter.h +++ /dev/null @@ -1,20 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -extern u8 gbPrinterSend(u8 b); diff --git a/src/dmg/gbSGB.cpp b/src/dmg/gbSGB.cpp deleted file mode 100644 index 677d1ad9..00000000 --- a/src/dmg/gbSGB.cpp +++ /dev/null @@ -1,917 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include - -#include "../System.h" -#include "../Port.h" -#include "../Util.h" -#include "gb.h" -#include "gbGlobals.h" - -extern u8 *pix; -extern bool speedup; -extern bool gbSgbResetFlag; - -#define GBSGB_NONE 0 -#define GBSGB_RESET 1 -#define GBSGB_PACKET_TRANSMIT 2 - -u8 *gbSgbBorderChar = NULL; -u8 *gbSgbBorder = NULL; - -int gbSgbCGBSupport = 0; -int gbSgbMask = 0; -int gbSgbMode = 0; -int gbSgbPacketState = GBSGB_NONE; -int gbSgbBit = 0; -int gbSgbPacketTimeout = 0; -int GBSGB_PACKET_TIMEOUT = 66666; -u8 gbSgbPacket[16*7]; -int gbSgbPacketNBits = 0; -int gbSgbPacketByte = 0; -int gbSgbPacketNumber = 0; -int gbSgbMultiplayer = 0; -int gbSgbFourPlayers = 0; -u8 gbSgbNextController = 0x0f; -u8 gbSgbReadingController = 0; -u16 gbSgbSCPPalette[4*512]; -u8 gbSgbATF[20 * 18]; -u8 gbSgbATFList[45 * 20 * 18]; -u8 gbSgbScreenBuffer[4160]; - -inline void gbSgbDraw24Bit(u8 *p, u16 v) -{ - *((u32*) p) = systemColorMap32[v]; -} - -inline void gbSgbDraw32Bit(u32 *p, u16 v) -{ - *p = systemColorMap32[v]; -} - -inline void gbSgbDraw16Bit(u16 *p, u16 v) -{ - *p = systemColorMap16[v]; -} - -void gbSgbReset() -{ - gbSgbPacketTimeout = 0; - gbSgbCGBSupport = 0; - gbSgbMask = 0; - gbSgbPacketState = GBSGB_NONE; - gbSgbBit = 0; - gbSgbPacketNBits = 0; - gbSgbPacketNumber = 0; - gbSgbMultiplayer = 0; - gbSgbFourPlayers = 0; - gbSgbNextController = 0x0f; - gbSgbReadingController = 0; - - memset(gbSgbSCPPalette, 0, 512*4); - memset(gbSgbATF, 0, 20*18); - memset(gbSgbATFList, 0, 45 * 20 * 18); - memset(gbSgbPacket, 0, 16 * 7); - memset(gbSgbBorderChar, 0, 32*256); - memset(gbSgbBorder, 0, 2048); - - int i; - for(i = 1; i < 2048; i+=2) { - gbSgbBorder[i] = 1 << 2; - } - - for(i = 0; i < 32; i++) { - gbPalette[i*4] = (0x1f) | (0x1f << 5) | (0x1f << 10); - gbPalette[i*4+1] = (0x15) | (0x15 << 5) | (0x15 << 10); - gbPalette[i*4+2] = (0x0c) | (0x0c << 5) | (0x0c << 10); - gbPalette[i*4+3] = 0; - } -} - -void gbSgbInit() -{ - gbSgbBorderChar = (u8 *)malloc(32 * 256); - gbSgbBorder = (u8 *)malloc(2048); - - gbSgbReset(); -} - -void gbSgbShutdown() -{ - if(gbSgbBorderChar != NULL) { - free(gbSgbBorderChar); - gbSgbBorderChar = NULL; - } - - if(gbSgbBorder != NULL) { - free(gbSgbBorder); - gbSgbBorder = NULL; - } -} - -void gbSgbFillScreen(u16 color) -{ - switch(systemColorDepth) { - case 16: - { - for(int y = 0; y < 144; y++) { - int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+2) + - gbBorderColumnSkip; - u16 *dest = (u16*)pix + yLine; - for(register int x = 0; x < 160; x++) - gbSgbDraw16Bit(dest++, color); - } - } - break; - case 24: - { - for(int y = 0; y < 144; y++) { - int yLine = (y+gbBorderRowSkip)*gbBorderLineSkip + gbBorderColumnSkip; - u8 *dest = (u8 *)pix + yLine*3; - for(register int x = 0; x < 160; x++) { - gbSgbDraw24Bit(dest, color); - dest += 3; - } - } - } - break; - case 32: - { - for(int y = 0; y < 144; y++) { - int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+1) + gbBorderColumnSkip; - u32 *dest = (u32 *)pix + yLine; - for(register int x = 0; x < 160; x++) { - gbSgbDraw32Bit(dest++, color); - } - } - } - break; - } -} - -#define getmem(x) gbMemoryMap[(x) >> 12][(x) & 0xfff] - -void gbSgbRenderScreenToBuffer() -{ - u16 mapAddress = 0x9800; - - if(register_LCDC & 0x08) - mapAddress = 0x9c00; - - u16 patternAddress = 0x8800; - - int flag = 1; - - if(register_LCDC & 0x10) { - patternAddress = 0x8000; - flag = 0; - } - - u8 *toAddress = gbSgbScreenBuffer; - - for(int i = 0; i < 13; i++) { - for(int j = 0; j < 20; j++) { - int tile = getmem(mapAddress); - mapAddress++; - - if(flag) { - if(tile > 127) - tile -= 128; - else - tile += 128; - } - for(int k = 0; k < 16; k++) - *toAddress++ = getmem(patternAddress + tile*16 + k); - } - mapAddress += 12; - } -} - -void gbSgbDrawBorderTile(int x, int y, int tile, int attr) -{ - u16 *dest = (u16*)pix + ((y+1) * (256+2)) + x; - u8 *dest8 = (u8*)pix + ((y*256)+x)*3; - u32 *dest32 = (u32*)pix + ((y+1)*257) + x; - - u8 *tileAddress = &gbSgbBorderChar[tile * 32]; - u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16]; - - u8 l = 8; - - u8 palette = ((attr >> 2 ) & 7); - - if(palette < 4) - palette += 4; - - palette *= 16; - - u8 xx = 0; - u8 yy = 0; - - int flipX = attr & 0x40; - int flipY = attr & 0x80; - - while(l > 0) { - u8 mask = 0x80; - u8 a = *tileAddress++; - u8 b = *tileAddress++; - u8 c = *tileAddress2++; - u8 d = *tileAddress2++; - - while(mask > 0) { - - u8 color = 0; - if(a & mask) - color++; - if(b & mask) - color+=2; - if(c & mask) - color+=4; - if(d & mask) - color+=8; - - u8 xxx = xx; - u8 yyy = yy; - - if(flipX) - xxx = 7 - xx; - if(flipY) - yyy = 7 - yy; - - u16 c = gbPalette[palette + color]; - - // Fix for Super Snaky ??? - // (it allows SGB borders to not redraw on the GB screen) - //if(!color) - // c = gbPalette[0]; - if(((yy < 40 || yy >= 184) || (xx < 48 || xx >= 208)) && (color || (gbSgbResetFlag == true))) { - switch(systemColorDepth) { - case 16: - gbSgbDraw16Bit(dest + yyy*(256+2) + xxx, c); - break; - case 24: - gbSgbDraw24Bit(dest8 + (yyy*256+xxx)*3, c); - break; - case 32: - gbSgbDraw32Bit(dest32 + yyy*(256+1)+xxx, c); - break; - } - } - - mask >>= 1; - - xx++; - } - yy++; - xx = 0; - l--; - mask = 0x80; - } -} - -void gbSgbRenderBorder() -{ - if(gbBorderOn) { - u8 *fromAddress = gbSgbBorder; - - for(u8 y = 0; y < 28; y++) { - for(u8 x = 0; x< 32; x++) { - u8 tile = *fromAddress++; - u8 attr = *fromAddress++; - - gbSgbDrawBorderTile(x*8,y*8,tile,attr); - } - } - } -} - -void gbSgbPicture() -{ - gbSgbRenderScreenToBuffer(); - - memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048); - - u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048]; - - for(int i = 64; i < 128; i++) { - gbPalette[i] = READ16LE(paletteAddr++); - } - - gbSgbCGBSupport |= 4; - - if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) { - gbBorderOn = 1; - systemGbBorderOn(); - } - - if(gbBorderOn && !gbSgbMask) - gbSgbRenderBorder(); - - if(gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) { - gbSgbCGBSupport = 0; - gbSgbMode = 0; - gbSgbMask = 0; - gbSgbRenderBorder(); - gbReset(); - } - - if(gbSgbCGBSupport > 4) - gbSgbCGBSupport = 0; -} - -void gbSgbSetPalette(int a,int b,u16 *p) -{ - u16 bit00 = READ16LE(p++); - int i; - - for(i = 1; i < 4; i++) { - gbPalette[a*4+i] = READ16LE(p++); - } - - for(i = 1; i < 4; i++) { - gbPalette[b*4+i] = READ16LE(p++); - } - - gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00; - if(gbBorderOn && !gbSgbMask) - gbSgbRenderBorder(); -} - -void gbSgbScpPalette() -{ - gbSgbRenderScreenToBuffer(); - - u16 *fromAddress = (u16 *)gbSgbScreenBuffer; - - for(int i = 0; i < 512*4; i++) { - gbSgbSCPPalette[i] = READ16LE(fromAddress++); - } -} - -void gbSgbSetATF(int n) -{ - if(n < 0) - n = 0; - if(n > 44) - n = 44; - memcpy(gbSgbATF,&gbSgbATFList[n * 20 * 18], 20 * 18); - - if(gbSgbPacket[1] & 0x40) { - gbSgbMask = 0; - if(gbBorderOn) - gbSgbRenderBorder(); - } -} - -void gbSgbSetPalette() -{ - u16 pal = READ16LE((((u16 *)&gbSgbPacket[1])))&511; - memcpy(&gbPalette[0], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); - - pal = READ16LE((((u16 *)&gbSgbPacket[3])))&511; - memcpy(&gbPalette[4], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); - - pal = READ16LE((((u16 *)&gbSgbPacket[5])))&511; - memcpy(&gbPalette[8], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); - - pal = READ16LE((((u16 *)&gbSgbPacket[7])))&511; - memcpy(&gbPalette[12], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); - - u8 atf = gbSgbPacket[9]; - - if(atf & 0x80) { - gbSgbSetATF(atf & 0x3f); - } - - if(atf & 0x40) { - gbSgbMask = 0; - if(gbBorderOn) - gbSgbRenderBorder(); - } -} - -void gbSgbAttributeBlock() -{ - u8 *fromAddress = &gbSgbPacket[1]; - - u8 nDataSet = *fromAddress++; - if(nDataSet > 12) - nDataSet = 12; - if(nDataSet == 0) - nDataSet = 1; - - while(nDataSet) { - u8 controlCode = (*fromAddress++) & 7; - u8 paletteDesignation = (*fromAddress++) & 0x3f; - u8 startH = (*fromAddress++) & 0x1f; - u8 startV = (*fromAddress++) & 0x1f; - u8 endH = (*fromAddress++) & 0x1f; - u8 endV = (*fromAddress++) & 0x1f; - - u8 * toAddress = gbSgbATF; - - for(u8 y = 0; y < 18; y++) { - for(u8 x = 0; x < 20; x++) { - if(x < startH || y < startV || - x > endH || y > endV) { - // outside - if(controlCode & 0x04) - *toAddress = (paletteDesignation >> 4) & 0x03; - } else if(x > startH && x < endH && - y > startV && y < endV) { - // inside - if(controlCode & 0x01) - *toAddress = paletteDesignation & 0x03; - } else { - // surrounding line - if(controlCode & 0x02) - *toAddress = (paletteDesignation>>2) & 0x03; - else if(controlCode == 0x01) - *toAddress = paletteDesignation & 0x03; - } - toAddress++; - } - } - nDataSet--; - } -} - -void gbSgbSetColumnPalette(u8 col, u8 p) -{ - // if(col < 0) - // col = 0; - if(col > 19) - col = 19; - - p &= 3; - - u8 *toAddress = &gbSgbATF[col]; - - for(u8 y = 0; y < 18; y++) { - *toAddress = p; - toAddress += 20; - } -} - -void gbSgbSetRowPalette(u8 row, u8 p) -{ - // if(row < 0) - // row = 0; - if(row > 17) - row = 17; - - p &= 3; - - u8 *toAddress = &gbSgbATF[row*20]; - - for(u8 x = 0; x < 20; x++) { - *toAddress++ = p; - } -} - -void gbSgbAttributeDivide() -{ - u8 control = gbSgbPacket[1]; - u8 coord = gbSgbPacket[2]; - u8 colorBR = control & 3; - u8 colorAL = (control >> 2) & 3; - u8 colorOL = (control >> 4) & 3; - - if(control & 0x40) { - if(coord > 17) - coord = 17; - - for(u8 i = 0; i < 18; i++) { - if(i < coord) - gbSgbSetRowPalette(i, colorAL); - else if ( i > coord) - gbSgbSetRowPalette(i, colorBR); - else - gbSgbSetRowPalette(i, colorOL); - } - } else { - if(coord > 19) - coord = 19; - - for(u8 i = 0; i < 20; i++) { - if(i < coord) - gbSgbSetColumnPalette(i, colorAL); - else if ( i > coord) - gbSgbSetColumnPalette(i, colorBR); - else - gbSgbSetColumnPalette(i, colorOL); - } - } -} - -void gbSgbAttributeLine() -{ - u8 *fromAddress = &gbSgbPacket[1]; - - u8 nDataSet = *fromAddress++; - - if(nDataSet > 0x6e) - nDataSet = 0x6e; - - while(nDataSet) { - u8 line = *fromAddress++; - u8 num = line & 0x1f; - u8 pal = (line >> 5) & 0x03; - if(line & 0x80) { - if(num > 17) - num = 17; - gbSgbSetRowPalette(num,pal); - } else { - if(num > 19) - num = 19; - gbSgbSetColumnPalette(num,pal); - } - nDataSet--; - } -} - -void gbSgbAttributeCharacter() -{ - u8 startH = gbSgbPacket[1] & 0x1f; - u8 startV = gbSgbPacket[2] & 0x1f; - int nDataSet = READ16LE(((u16 *)&gbSgbPacket[3])); - int style = gbSgbPacket[5] & 1; - if(startH > 19) - startH = 19; - if(startV > 17) - startV = 17; - - u8 s = 6; - u8 *fromAddress = &gbSgbPacket[6]; - u8 v = *fromAddress++; - - if(style) { - while(nDataSet) { - u8 p = (v >> s) & 3; - gbSgbATF[startV * 20 + startH] = p; - startV++; - if(startV == 18) { - startV = 0; - startH++; - if(startH == 20) - break; - } - - if(s) - s -= 2; - else { - s = 6; - v = *fromAddress++; - nDataSet--; - } - } - } else { - while(nDataSet) { - u8 p = (v >> s) & 3; - gbSgbATF[startV * 20 + startH] = p; - startH++; - if(startH == 20) { - startH = 0; - startV++; - if(startV == 18) - break; - } - - if(s) - s -= 2; - else { - s = 6; - v = *fromAddress++; - nDataSet--; - } - } - } -} - -void gbSgbSetATFList() -{ - gbSgbRenderScreenToBuffer(); - - u8 *fromAddress = gbSgbScreenBuffer; - u8 *toAddress = gbSgbATFList; - - for(int i = 0; i < 45; i++) { - for(int j = 0; j < 90; j++) { - u8 v = *fromAddress++; - u8 s = 6; - if(i == 2) - s = 6; - for(int k = 0; k < 4; k++) { - *toAddress++ = (v >> s) & 0x03; - s -= 2; - } - } - } -} - -void gbSgbMaskEnable() -{ - int gbSgbMaskFlag = gbSgbPacket[1] & 3; - - gbSgbMask = gbSgbMaskFlag; - - switch(gbSgbMaskFlag) { - case 1: - break; - case 2: - gbSgbFillScreen(0x0000); - // memset(&gbPalette[0], 0, 128*sizeof(u16)); - break; - case 3: - gbSgbFillScreen(gbPalette[0]); - break; - } - if(!gbSgbMask) { - if(gbBorderOn) - gbSgbRenderBorder(); - } -} - -void gbSgbChrTransfer() -{ - gbSgbRenderScreenToBuffer(); - - int address = (gbSgbPacket[1] & 1) * (128*32); - - if(gbSgbPacket[1] & 1) - gbSgbCGBSupport |= 2; - else - gbSgbCGBSupport |= 1; - - memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32); - - if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) { - gbBorderOn = 1; - systemGbBorderOn(); - } - - if(gbBorderOn && !gbSgbMask) - gbSgbRenderBorder(); - - if(gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) { - gbSgbCGBSupport = 0; - gbSgbMode = 0; - gbSgbMask = 0; - gbSgbRenderBorder(); - gbReset(); - } - - if(gbSgbCGBSupport > 4) - gbSgbCGBSupport = 0; -} - -void gbSgbMultiRequest() -{ - if(gbSgbPacket[1] & 1) { - gbSgbMultiplayer = 1; - if(gbSgbPacket[1] & 2) - gbSgbFourPlayers = 1; - else - gbSgbFourPlayers = 0; - gbSgbNextController = 0x0e; - } else { - gbSgbFourPlayers = 0; - gbSgbMultiplayer = 0; - gbSgbNextController = 0x0f; - } -} - -void gbSgbCommand() -{ - int command = gbSgbPacket[0] >> 3; - // int nPacket = gbSgbPacket[0] & 7; - - switch(command) { - case 0x00: - gbSgbSetPalette(0,1,(u16 *)&gbSgbPacket[1]); - break; - case 0x01: - gbSgbSetPalette(2,3,(u16 *)&gbSgbPacket[1]); - break; - case 0x02: - gbSgbSetPalette(0,3,(u16 *)&gbSgbPacket[1]); - break; - case 0x03: - gbSgbSetPalette(1,2,(u16 *)&gbSgbPacket[1]); - break; - case 0x04: - gbSgbAttributeBlock(); - break; - case 0x05: - gbSgbAttributeLine(); - break; - case 0x06: - gbSgbAttributeDivide(); - break; - case 0x07: - gbSgbAttributeCharacter(); - break; - case 0x0a: - gbSgbSetPalette(); - break; - case 0x0b: - gbSgbScpPalette(); - break; - case 0x11: - gbSgbMultiRequest(); - break; - case 0x13: - gbSgbChrTransfer(); - break; - case 0x14: - gbSgbPicture(); - break; - case 0x15: - gbSgbSetATFList(); - break; - case 0x16: - gbSgbSetATF(gbSgbPacket[1] & 0x3f); - break; - case 0x17: - gbSgbMaskEnable(); - break; - } -} - -void gbSgbResetPacketState() -{ - gbSgbPacketState = GBSGB_NONE; - gbSgbPacketTimeout = 0; -} - -void gbSgbDoBitTransfer(u8 value) -{ - value = value & 0x30; - switch(gbSgbPacketState) { - case GBSGB_NONE: - if(value == 0) { - gbSgbPacketState = GBSGB_RESET; - gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; - } else if (value == 0x30) { - if(gbSgbMultiplayer) { - if((gbSgbReadingController & 7) == 7) { - gbSgbReadingController = 0; - if(gbSgbMultiplayer) { - gbSgbNextController--; - if(gbSgbFourPlayers) { - if(gbSgbNextController == 0x0b) - gbSgbNextController = 0x0f; - } else { - if(gbSgbNextController == 0x0d) - gbSgbNextController = 0x0f; - } - } - } else { - gbSgbReadingController &= 3; - } - } - gbSgbPacketTimeout = 0; - } else { - if(value == 0x10) - gbSgbReadingController |= 0x2; - else if(value == 0x20) - gbSgbReadingController |= 0x01; - gbSgbPacketTimeout = 0; - } - gbSgbPacketTimeout = 0; - break; - case GBSGB_RESET: - if(value == 0x30) { - gbSgbPacketState = GBSGB_PACKET_TRANSMIT; - gbSgbPacketByte = 0; - gbSgbPacketNBits = 0; - gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; - } else if(value == 0x00) { - gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; - gbSgbPacketState = GBSGB_RESET; - } else { - gbSgbPacketState = GBSGB_NONE; - gbSgbPacketTimeout = 0; - } - break; - case GBSGB_PACKET_TRANSMIT: - if(value == 0) { - gbSgbPacketState = GBSGB_RESET; - gbSgbPacketTimeout = 0; - } else if (value == 0x30){ - if(gbSgbPacketNBits == 128) { - gbSgbPacketNBits = 0; - gbSgbPacketByte = 0; - gbSgbPacketNumber++; - gbSgbPacketTimeout = 0; - if(gbSgbPacketNumber == (gbSgbPacket[0] & 7)) { - gbSgbCommand(); - gbSgbPacketNumber = 0; - gbSgbPacketState = GBSGB_NONE; - gbSgbPacketTimeout = 0; - } - } else { - if(gbSgbPacketNBits < 128) { - gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1; - gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit; - gbSgbPacketNBits++; - if(!(gbSgbPacketNBits & 7)) { - gbSgbPacketByte++; - } - gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; - } - } - } else { - if(value == 0x20) - gbSgbBit = 0x00; - else - gbSgbBit = 0x80; - gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; - } - gbSgbReadingController = 0; - break; - default: - gbSgbPacketState = GBSGB_NONE; - gbSgbPacketTimeout = 0; - break; - } -} - -variable_desc gbSgbSaveStruct[] = { - { &gbSgbMask, sizeof(int) }, - { &gbSgbPacketState, sizeof(int) }, - { &gbSgbBit, sizeof(int) }, - { &gbSgbPacketNBits, sizeof(int) }, - { &gbSgbPacketByte, sizeof(int) }, - { &gbSgbPacketNumber, sizeof(int) }, - { &gbSgbMultiplayer, sizeof(int) }, - { &gbSgbNextController, sizeof(u8) }, - { &gbSgbReadingController, sizeof(u8) }, - { NULL, 0 } -}; - -variable_desc gbSgbSaveStructV3[] = { - { &gbSgbMask, sizeof(int) }, - { &gbSgbPacketState, sizeof(int) }, - { &gbSgbBit, sizeof(int) }, - { &gbSgbPacketNBits, sizeof(int) }, - { &gbSgbPacketByte, sizeof(int) }, - { &gbSgbPacketNumber, sizeof(int) }, - { &gbSgbMultiplayer, sizeof(int) }, - { &gbSgbNextController, sizeof(u8) }, - { &gbSgbReadingController, sizeof(u8) }, - { &gbSgbFourPlayers, sizeof(int) }, - { NULL, 0 } -}; - -void gbSgbSaveGame(gzFile gzFile) -{ - utilWriteData(gzFile, gbSgbSaveStructV3); - - utilGzWrite(gzFile, gbSgbBorder, 2048); - utilGzWrite(gzFile, gbSgbBorderChar, 32*256); - - utilGzWrite(gzFile, gbSgbPacket, 16*7); - - utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); - utilGzWrite(gzFile, gbSgbATF, 20 * 18); - utilGzWrite(gzFile, gbSgbATFList, 45 * 20 * 18); -} - -void gbSgbReadGame(gzFile gzFile, int version) -{ - if(version >= 3) - utilReadData(gzFile, gbSgbSaveStructV3); - else { - utilReadData(gzFile, gbSgbSaveStruct); - gbSgbFourPlayers = 0; - } - - if(version >= 8) { - utilGzRead(gzFile, gbSgbBorder, 2048); - utilGzRead(gzFile, gbSgbBorderChar, 32*256); - } - - utilGzRead(gzFile, gbSgbPacket, 16*7); - - utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); - utilGzRead(gzFile, gbSgbATF, 20 * 18); - utilGzRead(gzFile, gbSgbATFList, 45 * 20 * 18); -} diff --git a/src/dmg/gbSGB.h b/src/dmg/gbSGB.h deleted file mode 100644 index 95afb2c1..00000000 --- a/src/dmg/gbSGB.h +++ /dev/null @@ -1,39 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -void gbSgbInit(); -void gbSgbShutdown(); -void gbSgbCommand(); -void gbSgbResetPacketState(); -void gbSgbReset(); -void gbSgbDoBitTransfer(u8); -void gbSgbSaveGame(gzFile); -void gbSgbReadGame(gzFile, int version); -void gbSgbRenderBorder(); - -extern u8 gbSgbATF[20*18]; -extern int gbSgbMode; -extern int gbSgbMask; -extern int gbSgbMultiplayer; -extern u8 gbSgbNextController; -extern int gbSgbPacketTimeout; -extern u8 gbSgbReadingController; -extern int gbSgbFourPlayers; - - diff --git a/src/dmg/gbSound.cpp b/src/dmg/gbSound.cpp deleted file mode 100644 index da1bcc58..00000000 --- a/src/dmg/gbSound.cpp +++ /dev/null @@ -1,412 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005-2006 Forgotten and the VBA development team -// Copyright (C) 2007-2008 VBA-M development team -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include - -#include "../System.h" -#include "../Util.h" -#include "gbGlobals.h" -#include "gbSound.h" - -#include "gb_apu/Gb_Apu.h" -#include "gb_apu/Effects_Buffer.h" - -static Gb_Apu* gb_apu; -static Simple_Effects_Buffer* stereo_buffer; - -extern u16 soundFinalWave[1470]; -extern int soundVolume; - -extern int gbHardware; - -extern void soundResume(); - -extern int soundBufferLen; -extern int soundQuality; -extern bool soundPaused; -extern int soundTicks; -extern int SOUND_CLOCK_TICKS; -extern u32 soundNextPosition; - -extern int soundDebug; - -extern bool soundEcho; -extern bool soundLowPass; -extern bool soundReverse; -extern bool soundOffFlag; - -int const ticks_to_time = 2 * GB_APU_OVERCLOCK; - -static inline blip_time_t blip_time() -{ - return (SOUND_CLOCK_TICKS - soundTicks) * ticks_to_time; -} - -u8 gbSoundRead( u16 address ) -{ - if ( gb_apu && address >= NR10 && address <= 0xFF3F ) - return gb_apu->read_register( blip_time(), address ); - - return gbMemory[address]; -} - -void gbSoundEvent(register u16 address, register int data) -{ - int freq = 0; - - gbMemory[address] = data; - -#ifndef FINAL_VERSION - if(soundDebug) { - // don't translate. debug only - log("Sound event: %08lx %02x\n", address, data); - } -#endif - - if ( gb_apu && address >= NR10 && address <= 0xFF3F ) - gb_apu->write_register( blip_time(), address, data ); -} - -static void end_frame( blip_time_t time ) -{ - gb_apu ->end_frame( time ); - stereo_buffer->end_frame( time ); -} - -static void flush_samples() -{ - // number of samples in output buffer - int const out_buf_size = soundBufferLen / sizeof *soundFinalWave; - - // Keep filling and writing soundFinalWave until it can't be fully filled - while ( stereo_buffer->samples_avail() >= out_buf_size ) - { - stereo_buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size ); - if(systemSoundOn) - { - if(soundPaused) - soundResume(); - - systemWriteDataToSoundBuffer(); - } - } -} - -int const chan_count = 4; - -gb_effects_config_t gb_effects_config; -static gb_effects_config_t gb_effects_config_current; - -static void apply_effects() -{ - gb_effects_config_current = gb_effects_config; - - stereo_buffer->config().enabled = gb_effects_config_current.enabled; - stereo_buffer->config().echo = gb_effects_config_current.echo; - stereo_buffer->config().stereo = gb_effects_config_current.stereo; - stereo_buffer->config().surround = gb_effects_config_current.surround; - stereo_buffer->apply_config(); - - for ( int i = 0; i < chan_count; i++ ) - { - Multi_Buffer::channel_t ch = stereo_buffer->channel( i ); - gb_apu->set_output( ch.center, ch.left, ch.right, i ); - } -} - -void gbSoundTick() -{ - if ( systemSoundOn && gb_apu && stereo_buffer ) - { - // Run sound hardware to present - end_frame( SOUND_CLOCK_TICKS * ticks_to_time ); - - flush_samples(); - - gb_effects_config.enabled = soundEcho; - - // Update effects config if it was changed - if ( memcmp( &gb_effects_config_current, &gb_effects_config, - sizeof gb_effects_config ) ) - apply_effects(); - } -} - -static void reset_apu() -{ - // Use DMG or CGB sound differences based on type of game - gb_apu->reset( gbHardware & 1 ? gb_apu->mode_dmg : gb_apu->mode_cgb ); - - if ( stereo_buffer ) - stereo_buffer->clear(); - - soundTicks = SOUND_CLOCK_TICKS; -} - -static void remake_stereo_buffer() -{ - // Stereo_Buffer - delete stereo_buffer; - stereo_buffer = 0; - - stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory - stereo_buffer->set_sample_rate( 44100 / soundQuality ); // TODO: handle out of memory - stereo_buffer->clock_rate( gb_apu->clock_rate ); - - // APU - static int const chan_types [chan_count] = { - Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2, - Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1 - }; - stereo_buffer->set_channel_count( chan_count, chan_types ); - - if ( !gb_apu ) - { - gb_apu = new Gb_Apu; - reset_apu(); - } - - apply_effects(); -} - -void gbSoundReset() -{ - gb_effects_config.echo = 0.20f; - gb_effects_config.stereo = 0.15f; - gb_effects_config.surround = false; - - SOUND_CLOCK_TICKS = 20000; - - remake_stereo_buffer(); - reset_apu(); - - soundPaused = 1; - soundNextPosition = 0; - - // don't translate -#ifndef FINAL_VERSION - if(soundDebug) { - log("*** Sound Init ***\n"); - } -#endif - gbSoundEvent(0xff10, 0x80); - gbSoundEvent(0xff11, 0xbf); - gbSoundEvent(0xff12, 0xf3); - gbSoundEvent(0xff14, 0xbf); - gbSoundEvent(0xff16, 0x3f); - gbSoundEvent(0xff17, 0x00); - gbSoundEvent(0xff19, 0xbf); - - gbSoundEvent(0xff1a, 0x7f); - gbSoundEvent(0xff1b, 0xff); - gbSoundEvent(0xff1c, 0xbf); - gbSoundEvent(0xff1e, 0xbf); - - gbSoundEvent(0xff20, 0xff); - gbSoundEvent(0xff21, 0x00); - gbSoundEvent(0xff22, 0x00); - gbSoundEvent(0xff23, 0xbf); - gbSoundEvent(0xff24, 0x77); - gbSoundEvent(0xff25, 0xf3); - - if (gbHardware & 0x4) - gbSoundEvent(0xff26, 0xf0); - else - gbSoundEvent(0xff26, 0xf1); - - // don't translate -#ifndef FINAL_VERSION - if(soundDebug) { - log("*** Sound Init Complete ***\n"); - } -#endif - int addr = 0xff30; - - while(addr < 0xff40) { - gbMemory[addr++] = 0x00; - gbMemory[addr++] = 0xff; - } -} - -extern bool soundInit(); -extern void soundShutdown(); - -void gbSoundSetQuality(int quality) -{ - if ( soundQuality != quality ) - { - if ( systemCanChangeSoundQuality() ) - { - if ( !soundOffFlag ) - soundShutdown(); - - soundQuality = quality; - soundNextPosition = 0; - - if ( !soundOffFlag ) - soundInit(); - } - else - { - soundQuality = quality; - soundNextPosition = 0; - } - - remake_stereo_buffer(); - } -} - -static char dummy_buf [735 * 2]; - -#define SKIP( type, name ) { dummy_buf, sizeof (type) } - -// funny expr at end ensures that type matches type of variable -#define LOAD( type, name ) { &name, sizeof (name) + (&name - (type*) &name) } - -static variable_desc gbsound_format [] = -{ - SKIP( int, soundPaused ), - SKIP( int, soundPlay ), - SKIP( int, soundTicks ), - SKIP( int, SOUND_CLOCK_TICKS ), - SKIP( int, soundLevel1 ), - SKIP( int, soundLevel2 ), - SKIP( int, soundBalance ), - SKIP( int, soundMasterOn ), - SKIP( int, soundIndex ), - SKIP( int, soundVIN ), - SKIP( int, soundOn [0] ), - SKIP( int, soundATL [0] ), - SKIP( int, sound1Skip ), - SKIP( int, soundIndex [0] ), - SKIP( int, sound1Continue ), - SKIP( int, soundEnvelopeVolume [0] ), - SKIP( int, soundEnvelopeATL [0] ), - SKIP( int, sound1EnvelopeATLReload ), - SKIP( int, sound1EnvelopeUpDown ), - SKIP( int, sound1SweepATL ), - SKIP( int, sound1SweepATLReload ), - SKIP( int, sound1SweepSteps ), - SKIP( int, sound1SweepUpDown ), - SKIP( int, sound1SweepStep ), - SKIP( int, soundOn [1] ), - SKIP( int, soundATL [1] ), - SKIP( int, sound2Skip ), - SKIP( int, soundIndex [1] ), - SKIP( int, sound2Continue ), - SKIP( int, soundEnvelopeVolume [1] ), - SKIP( int, soundEnvelopeATL [1] ), - SKIP( int, sound2EnvelopeATLReload ), - SKIP( int, sound2EnvelopeUpDown ), - SKIP( int, soundOn [2] ), - SKIP( int, soundATL [2] ), - SKIP( int, sound3Skip ), - SKIP( int, soundIndex [2] ), - SKIP( int, sound3Continue ), - SKIP( int, sound3OutputLevel ), - SKIP( int, soundOn [3] ), - SKIP( int, soundATL [3] ), - SKIP( int, sound4Skip ), - SKIP( int, soundIndex [3] ), - SKIP( int, sound4Clock ), - SKIP( int, sound4ShiftRight ), - SKIP( int, sound4ShiftSkip ), - SKIP( int, sound4ShiftIndex ), - SKIP( int, sound4NSteps ), - SKIP( int, sound4CountDown ), - SKIP( int, sound4Continue ), - SKIP( int, soundEnvelopeVolume [2] ), - SKIP( int, soundEnvelopeATL [2] ), - SKIP( int, sound4EnvelopeATLReload ), - SKIP( int, sound4EnvelopeUpDown ), - SKIP( int, soundEnableFlag ), - { NULL, 0 } -}; - -static variable_desc gbsound_format2 [] = -{ - SKIP( int, sound1ATLreload ), - SKIP( int, freq1low ), - SKIP( int, freq1high ), - SKIP( int, sound2ATLreload ), - SKIP( int, freq2low ), - SKIP( int, freq2high ), - SKIP( int, sound3ATLreload ), - SKIP( int, freq3low ), - SKIP( int, freq3high ), - SKIP( int, sound4ATLreload ), - SKIP( int, freq4 ), - { NULL, 0 } -}; - -static variable_desc gbsound_format3 [] = -{ - SKIP( u8[2*735], soundBuffer ), - SKIP( u8[2*735], soundBuffer ), - SKIP( u16[735], soundFinalWave ), - { NULL, 0 } -}; - -void gbSoundSaveGame(gzFile gzFile) -{ - // TODO: implement -} - -enum { - nr10 = 0, - nr11, nr12, nr13, nr14, - nr20, nr21, nr22, nr23, nr24, - nr30, nr31, nr32, nr33, nr34, - nr40, nr41, nr42, nr43, nr44, - nr50, nr51, nr52 -}; - -void gbSoundReadGame(int version,gzFile gzFile) -{ - return; // TODO: apparently GB save states don't work in the main emulator - - // Load state - utilReadData( gzFile, gbsound_format ); - - if ( version >= 11 ) - utilReadData( gzFile, gbsound_format2 ); - - utilReadData( gzFile, gbsound_format3 ); - - int quality = 1; - if ( version >= 7 ) - quality = utilReadInt( gzFile ); - - gbSoundSetQuality( quality ); - - // Convert to format Gb_Apu uses - reset_apu(); - gb_apu_state_t s; - gb_apu->save_state( &s ); // use fresh values for anything not restored - - // Only some registers are properly preserved - static int const regs_to_copy [] = { - nr10, nr11, nr12, nr21, nr22, nr30, nr32, nr42, nr43, nr50, nr51, nr52, -1 - }; - for ( int i = 0; regs_to_copy [i] >= 0; i++ ) - s.regs [regs_to_copy [i]] = gbMemory [0xFF10 + regs_to_copy [i]]; - - memcpy( &s.regs [0x20], &gbMemory [0xFF30], 0x10 ); // wave - - gb_apu->load_state( s ); -} diff --git a/src/dmg/gbSound.h b/src/dmg/gbSound.h deleted file mode 100644 index 2dc8e79a..00000000 --- a/src/dmg/gbSound.h +++ /dev/null @@ -1,74 +0,0 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#define NR10 0xff10 -#define NR11 0xff11 -#define NR12 0xff12 -#define NR13 0xff13 -#define NR14 0xff14 -#define NR21 0xff16 -#define NR22 0xff17 -#define NR23 0xff18 -#define NR24 0xff19 -#define NR30 0xff1a -#define NR31 0xff1b -#define NR32 0xff1c -#define NR33 0xff1d -#define NR34 0xff1e -#define NR41 0xff20 -#define NR42 0xff21 -#define NR43 0xff22 -#define NR44 0xff23 -#define NR50 0xff24 -#define NR51 0xff25 -#define NR52 0xff26 - -#define SOUND_EVENT(address,value) \ - gbSoundEvent(address,value) - -extern void gbSoundTick(); -extern void gbSoundPause(); -extern void gbSoundResume(); -extern void gbSoundEnable(int); -extern void gbSoundDisable(int); -extern int gbSoundGetEnable(); -extern void gbSoundReset(); -extern void gbSoundSaveGame(gzFile); -extern void gbSoundReadGame(int,gzFile); -extern void gbSoundEvent(register u16, register int); -extern void gbSoundSetQuality(int); - -extern u8 gbSoundRead(u16 address); - -extern int soundTicks; -extern int soundQuality; -extern int SOUND_CLOCK_TICKS; - -struct gb_effects_config_t -{ - bool enabled; // false = disable all effects - - float echo; // 0.0 = none, 1.0 = lots - float stereo; // 0.0 = channels in center, 1.0 = channels on left/right - bool surround; // true = put some channels in back -}; - -// Can be changed at any time, probably from another thread too. -// Sound will notice changes during next 1/100 second. -extern gb_effects_config_t gb_effects_config; diff --git a/src/dmg/gb_apu/Blip_Buffer.cpp b/src/dmg/gb_apu/Blip_Buffer.cpp deleted file mode 100644 index 3b2dda93..00000000 --- a/src/dmg/gb_apu/Blip_Buffer.cpp +++ /dev/null @@ -1,465 +0,0 @@ -// Blip_Buffer 0.4.1. http://www.slack.net/~ant/ - -#include "Blip_Buffer.h" - -#include -#include -#include -#include -#include - -/* Copyright (C) 2003-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module 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 Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -// TODO: use scoped for variables in treble_eq() - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -int const silent_buf_size = 1; // size used for Silent_Blip_Buffer - -Blip_Buffer::Blip_Buffer() -{ - factor_ = LONG_MAX; - buffer_ = 0; - buffer_size_ = 0; - sample_rate_ = 0; - bass_shift_ = 0; - clock_rate_ = 0; - bass_freq_ = 16; - length_ = 0; - - // assumptions code makes about implementation-defined features - #ifndef NDEBUG - // right shift of negative value preserves sign - buf_t_ i = -0x7FFFFFFE; - assert( (i >> 1) == -0x3FFFFFFF ); - - // casting to short truncates to 16 bits and sign-extends - i = 0x18000; - assert( (short) i == -0x8000 ); - #endif - - clear(); -} - -Blip_Buffer::~Blip_Buffer() -{ - if ( buffer_size_ != silent_buf_size ) - free( buffer_ ); -} - -Silent_Blip_Buffer::Silent_Blip_Buffer() -{ - factor_ = 0; - buffer_ = buf; - buffer_size_ = silent_buf_size; - clear(); -} - -void Blip_Buffer::clear( int entire_buffer ) -{ - offset_ = 0; - reader_accum_ = 0; - modified_ = 0; - if ( buffer_ ) - { - long count = (entire_buffer ? buffer_size_ : samples_avail()); - memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) ); - } -} - -Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec ) -{ - if ( buffer_size_ == silent_buf_size ) - { - assert( 0 ); - return "Internal (tried to resize Silent_Blip_Buffer)"; - } - - // start with maximum length that resampled time can represent - long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64; - if ( msec != blip_max_length ) - { - long s = (new_rate * (msec + 1) + 999) / 1000; - if ( s < new_size ) - new_size = s; - else - assert( 0 ); // fails if requested buffer length exceeds limit - } - - if ( buffer_size_ != new_size ) - { - void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ ); - if ( !p ) - return "Out of memory"; - buffer_ = (buf_t_*) p; - } - - buffer_size_ = new_size; - assert( buffer_size_ != silent_buf_size ); // size should never happen to match this - - // update things based on the sample rate - sample_rate_ = new_rate; - length_ = new_size * 1000 / new_rate - 1; - if ( msec ) - assert( length_ == msec ); // ensure length is same as that passed in - - // update these since they depend on sample rate - if ( clock_rate_ ) - clock_rate( clock_rate_ ); - bass_freq( bass_freq_ ); - - clear(); - - return 0; // success -} - -blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const -{ - double ratio = (double) sample_rate_ / rate; - blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 ); - assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large - return (blip_resampled_time_t) factor; -} - -void Blip_Buffer::bass_freq( int freq ) -{ - bass_freq_ = freq; - int shift = 31; - if ( freq > 0 ) - { - shift = 13; - long f = (freq << 16) / sample_rate_; - while ( (f >>= 1) && --shift ) { } - } - bass_shift_ = shift; -} - -void Blip_Buffer::end_frame( blip_time_t t ) -{ - offset_ += t * factor_; - assert( samples_avail() <= (long) buffer_size_ ); // fails if time is past end of buffer -} - -long Blip_Buffer::count_samples( blip_time_t t ) const -{ - blip_resampled_time_t last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY; - blip_resampled_time_t first_sample = offset_ >> BLIP_BUFFER_ACCURACY; - return long (last_sample - first_sample); -} - -blip_time_t Blip_Buffer::count_clocks( long count ) const -{ - if ( !factor_ ) - { - assert( 0 ); // sample rate and clock rates must be set first - return 0; - } - - if ( count > buffer_size_ ) - count = buffer_size_; - blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; - return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_); -} - -void Blip_Buffer::remove_samples( long count ) -{ - if ( count ) - { - remove_silence( count ); - - // copy remaining samples to beginning and clear old samples - long remain = samples_avail() + blip_buffer_extra_; - memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ ); - memset( buffer_ + remain, 0, count * sizeof *buffer_ ); - } -} - -// Blip_Synth_ - -Blip_Synth_Fast_::Blip_Synth_Fast_() -{ - buf = 0; - last_amp = 0; - delta_factor = 0; -} - -void Blip_Synth_Fast_::volume_unit( double new_unit ) -{ - delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5); -} - -#if !BLIP_BUFFER_FAST - -Blip_Synth_::Blip_Synth_( short* p, int w ) : - impulses( p ), - width( w ) -{ - volume_unit_ = 0.0; - kernel_unit = 0; - buf = 0; - last_amp = 0; - delta_factor = 0; -} - -#undef PI -#define PI 3.1415926535897932384626433832795029 - -static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff ) -{ - if ( cutoff >= 0.999 ) - cutoff = 0.999; - - if ( treble < -300.0 ) - treble = -300.0; - if ( treble > 5.0 ) - treble = 5.0; - - double const maxh = 4096.0; - double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) ); - double const pow_a_n = pow( rolloff, maxh - maxh * cutoff ); - double const to_angle = PI / 2 / maxh / oversample; - for ( int i = 0; i < count; i++ ) - { - double angle = ((i - count) * 2 + 1) * to_angle; - double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle ); - double cos_nc_angle = cos( maxh * cutoff * angle ); - double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle ); - double cos_angle = cos( angle ); - - c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle; - double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle); - double b = 2.0 - cos_angle - cos_angle; - double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle; - - out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d - } -} - -void blip_eq_t::generate( float* out, int count ) const -{ - // lower cutoff freq for narrow kernels with their wider transition band - // (8 points->1.49, 16 points->1.15) - double oversample = blip_res * 2.25 / count + 0.85; - double half_rate = sample_rate * 0.5; - if ( cutoff_freq ) - oversample = half_rate / cutoff_freq; - double cutoff = rolloff_freq * oversample / half_rate; - - gen_sinc( out, count, blip_res * oversample, treble, cutoff ); - - // apply (half of) hamming window - double to_fraction = PI / (count - 1); - for ( int i = count; i--; ) - out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction ); -} - -void Blip_Synth_::adjust_impulse() -{ - // sum pairs for each phase and add error correction to end of first half - int const size = impulses_size(); - for ( int p = blip_res; p-- >= blip_res / 2; ) - { - int p2 = blip_res - 2 - p; - long error = kernel_unit; - for ( int i = 1; i < size; i += blip_res ) - { - error -= impulses [i + p ]; - error -= impulses [i + p2]; - } - if ( p == p2 ) - error /= 2; // phase = 0.5 impulse uses same half for both sides - impulses [size - blip_res + p] += (short) error; - //printf( "error: %ld\n", error ); - } - - //for ( int i = blip_res; i--; printf( "\n" ) ) - // for ( int j = 0; j < width / 2; j++ ) - // printf( "%5ld,", impulses [j * blip_res + i + 1] ); -} - -void Blip_Synth_::treble_eq( blip_eq_t const& eq ) -{ - float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2]; - - int const half_size = blip_res / 2 * (width - 1); - eq.generate( &fimpulse [blip_res], half_size ); - - int i; - - // need mirror slightly past center for calculation - for ( i = blip_res; i--; ) - fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i]; - - // starts at 0 - for ( i = 0; i < blip_res; i++ ) - fimpulse [i] = 0.0f; - - // find rescale factor - double total = 0.0; - for ( i = 0; i < half_size; i++ ) - total += fimpulse [blip_res + i]; - - //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB - //double const base_unit = 37888.0; // allows treble to +5 dB - double const base_unit = 32768.0; // necessary for blip_unscaled to work - double rescale = base_unit / 2 / total; - kernel_unit = (long) base_unit; - - // integrate, first difference, rescale, convert to int - double sum = 0.0; - double next = 0.0; - int const size = this->impulses_size(); - for ( i = 0; i < size; i++ ) - { - impulses [i] = (short) (int) floor( (next - sum) * rescale + 0.5 ); - sum += fimpulse [i]; - next += fimpulse [i + blip_res]; - } - adjust_impulse(); - - // volume might require rescaling - double vol = volume_unit_; - if ( vol ) - { - volume_unit_ = 0.0; - volume_unit( vol ); - } -} - -void Blip_Synth_::volume_unit( double new_unit ) -{ - if ( new_unit != volume_unit_ ) - { - // use default eq if it hasn't been set yet - if ( !kernel_unit ) - treble_eq( -8.0 ); - - volume_unit_ = new_unit; - double factor = new_unit * (1L << blip_sample_bits) / kernel_unit; - - if ( factor > 0.0 ) - { - int shift = 0; - - // if unit is really small, might need to attenuate kernel - while ( factor < 2.0 ) - { - shift++; - factor *= 2.0; - } - - if ( shift ) - { - kernel_unit >>= shift; - assert( kernel_unit > 0 ); // fails if volume unit is too low - - // keep values positive to avoid round-towards-zero of sign-preserving - // right shift for negative values - long offset = 0x8000 + (1 << (shift - 1)); - long offset2 = 0x8000 >> shift; - for ( int i = impulses_size(); i--; ) - impulses [i] = (short) (int) (((impulses [i] + offset) >> shift) - offset2); - adjust_impulse(); - } - } - delta_factor = (int) floor( factor + 0.5 ); - //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit ); - } -} -#endif - -long Blip_Buffer::read_samples( blip_sample_t* out_, long max_samples, int stereo ) -{ - long count = samples_avail(); - if ( count > max_samples ) - count = max_samples; - - if ( count ) - { - int const bass = BLIP_READER_BASS( *this ); - BLIP_READER_BEGIN( reader, *this ); - BLIP_READER_ADJ_( reader, count ); - blip_sample_t* BLIP_RESTRICT out = out_ + count; - blip_long offset = (blip_long) -count; - - if ( !stereo ) - { - do - { - blip_long s = BLIP_READER_READ( reader ); - BLIP_READER_NEXT_IDX_( reader, bass, offset ); - BLIP_CLAMP( s, s ); - out [offset] = (blip_sample_t) s; - } - while ( ++offset ); - } - else - { - do - { - blip_long s = BLIP_READER_READ( reader ); - BLIP_READER_NEXT_IDX_( reader, bass, offset ); - BLIP_CLAMP( s, s ); - out [offset * 2] = (blip_sample_t) s; - } - while ( ++offset ); - } - - BLIP_READER_END( reader, *this ); - - remove_samples( count ); - } - return count; -} - -void Blip_Buffer::mix_samples( blip_sample_t const* in, long count ) -{ - if ( buffer_size_ == silent_buf_size ) - { - assert( 0 ); - return; - } - - buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2; - - int const sample_shift = blip_sample_bits - 16; - int prev = 0; - while ( count-- ) - { - blip_long s = (blip_long) *in++ << sample_shift; - *out += s - prev; - prev = s; - ++out; - } - *out -= prev; -} - -blip_ulong const subsample_mask = (1L << BLIP_BUFFER_ACCURACY) - 1; - -void Blip_Buffer::save_state( blip_buffer_state_t* out ) -{ - assert( samples_avail() == 0 ); - out->offset_ = offset_; - out->reader_accum_ = reader_accum_; - memcpy( out->buf, &buffer_ [offset_ >> BLIP_BUFFER_ACCURACY], sizeof out->buf ); -} - -void Blip_Buffer::load_state( blip_buffer_state_t const& in ) -{ - clear( false ); - - offset_ = in.offset_; - reader_accum_ = in.reader_accum_; - memcpy( buffer_, in.buf, sizeof in.buf ); -} diff --git a/src/dmg/gb_apu/Blip_Buffer.h b/src/dmg/gb_apu/Blip_Buffer.h deleted file mode 100644 index 850f0957..00000000 --- a/src/dmg/gb_apu/Blip_Buffer.h +++ /dev/null @@ -1,556 +0,0 @@ -// Band-limited sound synthesis buffer - -// Blip_Buffer 0.4.1 -#ifndef BLIP_BUFFER_H -#define BLIP_BUFFER_H - - // internal - #include - #if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF - typedef long blip_long; - typedef unsigned long blip_ulong; - #else - typedef int blip_long; - typedef unsigned blip_ulong; - #endif - -// Time unit at source clock rate -typedef blip_long blip_time_t; - -// Output samples are 16-bit signed, with a range of -32768 to 32767 -typedef short blip_sample_t; -enum { blip_sample_max = 32767 }; - -struct blip_buffer_state_t; - -class Blip_Buffer { -public: - typedef const char* blargg_err_t; - - // Sets output sample rate and buffer length in milliseconds (1/1000 sec, defaults - // to 1/4 second) and clears buffer. If there isn't enough memory, leaves buffer - // untouched and returns "Out of memory", otherwise returns NULL. - blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 ); - - // Sets number of source time units per second - void clock_rate( long clocks_per_sec ); - - // Ends current time frame of specified duration and makes its samples available - // (along with any still-unread samples) for reading with read_samples(). Begins - // a new time frame at the end of the current frame. - void end_frame( blip_time_t time ); - - // Reads at most 'max_samples' out of buffer into 'dest', removing them from from - // the buffer. Returns number of samples actually read and removed. If stereo is - // true, increments 'dest' one extra time after writing each sample, to allow - // easy interleving of two channels into a stereo output buffer. - long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 ); - -// Additional features - - // Removes all available samples and clear buffer to silence. If 'entire_buffer' is - // false, just clears out any samples waiting rather than the entire buffer. - void clear( int entire_buffer = 1 ); - - // Number of samples available for reading with read_samples() - long samples_avail() const; - - // Removes 'count' samples from those waiting to be read - void remove_samples( long count ); - - // Sets frequency high-pass filter frequency, where higher values reduce bass more - void bass_freq( int frequency ); - - // Current output sample rate - long sample_rate() const; - - // Length of buffer in milliseconds - int length() const; - - // Number of source time units per second - long clock_rate() const; - -// Experimental features - - // Saves state, including high-pass filter and tails of last deltas. - // All samples must have been read from buffer before calling this. - void save_state( blip_buffer_state_t* out ); - - // Loads state. State must have been saved from Blip_Buffer with same - // settings during same run of program. States can NOT be stored on disk. - // Clears buffer before loading state. - void load_state( blip_buffer_state_t const& in ); - - // Number of samples delay from synthesis to samples read out - int output_latency() const; - - // Counts number of clocks needed until 'count' samples will be available. - // If buffer can't even hold 'count' samples, returns number of clocks until - // buffer becomes full. - blip_time_t count_clocks( long count ) const; - - // Number of raw samples that can be mixed within frame of specified duration. - long count_samples( blip_time_t duration ) const; - - // Mixes in 'count' samples from 'buf_in' - void mix_samples( blip_sample_t const* buf_in, long count ); - - - // Signals that sound has been added to buffer. Could be done automatically in - // Blip_Synth, but that would affect performance more, as you can arrange that - // this is called only once per time frame rather than for every delta. - void set_modified() { modified_ = this; } - - // not documented yet - blip_ulong unsettled() const; - Blip_Buffer* clear_modified() { Blip_Buffer* b = modified_; modified_ = 0; return b; } - void remove_silence( long count ); - typedef blip_ulong blip_resampled_time_t; - blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; } - blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; } - blip_resampled_time_t clock_rate_factor( long clock_rate ) const; -public: - Blip_Buffer(); - ~Blip_Buffer(); - - // Deprecated - typedef blip_resampled_time_t resampled_time_t; - blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); } - blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); } -private: - // noncopyable - Blip_Buffer( const Blip_Buffer& ); - Blip_Buffer& operator = ( const Blip_Buffer& ); -public: - typedef blip_long buf_t_; - blip_ulong factor_; - blip_resampled_time_t offset_; - buf_t_* buffer_; - blip_long buffer_size_; - blip_long reader_accum_; - int bass_shift_; -private: - long sample_rate_; - long clock_rate_; - int bass_freq_; - int length_; - Blip_Buffer* modified_; // non-zero = true (more optimal than using bool, heh) - friend class Blip_Reader; -}; - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -// Number of bits in resample ratio fraction. Higher values give a more accurate ratio -// but reduce maximum buffer size. -#ifndef BLIP_BUFFER_ACCURACY - #define BLIP_BUFFER_ACCURACY 16 -#endif - -// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in -// noticeable broadband noise when synthesizing high frequency square waves. -// Affects size of Blip_Synth objects since they store the waveform directly. -#ifndef BLIP_PHASE_BITS - #if BLIP_BUFFER_FAST - #define BLIP_PHASE_BITS 8 - #else - #define BLIP_PHASE_BITS 6 - #endif -#endif - - // Internal - typedef blip_ulong blip_resampled_time_t; - int const blip_widest_impulse_ = 16; - int const blip_buffer_extra_ = blip_widest_impulse_ + 2; - int const blip_res = 1 << BLIP_PHASE_BITS; - class blip_eq_t; - - class Blip_Synth_Fast_ { - public: - Blip_Buffer* buf; - int last_amp; - int delta_factor; - - void volume_unit( double ); - Blip_Synth_Fast_(); - void treble_eq( blip_eq_t const& ) { } - }; - - class Blip_Synth_ { - public: - Blip_Buffer* buf; - int last_amp; - int delta_factor; - - void volume_unit( double ); - Blip_Synth_( short* impulses, int width ); - void treble_eq( blip_eq_t const& ); - private: - double volume_unit_; - short* const impulses; - int const width; - blip_long kernel_unit; - int impulses_size() const { return blip_res / 2 * width + 1; } - void adjust_impulse(); - }; - -// Quality level, better = slower. In general, use blip_good_quality. -const int blip_med_quality = 8; -const int blip_good_quality = 12; -const int blip_high_quality = 16; - -// Range specifies the greatest expected change in amplitude. Calculate it -// by finding the difference between the maximum and minimum expected -// amplitudes (max - min). -template -class Blip_Synth { -public: - // Sets overall volume of waveform - void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); } - - // Configures low-pass filter (see blip_buffer.txt) - void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); } - - // Gets/sets Blip_Buffer used for output - Blip_Buffer* output() const { return impl.buf; } - void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; } - - // Updates amplitude of waveform at given time. Using this requires a separate - // Blip_Synth for each waveform. - void update( blip_time_t time, int amplitude ); - -// Low-level interface - - // Adds an amplitude transition of specified delta, optionally into specified buffer - // rather than the one set with output(). Delta can be positive or negative. - // The actual change in amplitude is delta * (volume / range) - void offset( blip_time_t, int delta, Blip_Buffer* ) const; - void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); } - - // Works directly in terms of fractional output samples. Contact author for more info. - void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const; - - // Same as offset(), except code is inlined for higher performance - void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const { - offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); - } - void offset_inline( blip_time_t t, int delta ) const { - offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); - } - -private: -#if BLIP_BUFFER_FAST - Blip_Synth_Fast_ impl; -#else - Blip_Synth_ impl; - typedef short imp_t; - imp_t impulses [blip_res * (quality / 2) + 1]; -public: - Blip_Synth() : impl( impulses, quality ) { } -#endif -}; - -// Low-pass equalization parameters -class blip_eq_t { -public: - // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce - // treble, small positive values (0 to 5.0) increase treble. - blip_eq_t( double treble_db = 0 ); - - // See blip_buffer.txt - blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 ); - -private: - double treble; - long rolloff_freq; - long sample_rate; - long cutoff_freq; - void generate( float* out, int count ) const; - friend class Blip_Synth_; -}; - -int const blip_sample_bits = 30; - -// Dummy Blip_Buffer to direct sound output to, for easy muting without -// having to stop sound code. -class Silent_Blip_Buffer : public Blip_Buffer { - buf_t_ buf [blip_buffer_extra_ + 1]; -public: - // The following cannot be used (an assertion will fail if attempted): - blargg_err_t set_sample_rate( long samples_per_sec, int msec_length ); - blip_time_t count_clocks( long count ) const; - void mix_samples( blip_sample_t const* buf, long count ); - - Silent_Blip_Buffer(); -}; - - #if __GNUC__ >= 3 || _MSC_VER >= 1100 - #define BLIP_RESTRICT __restrict - #else - #define BLIP_RESTRICT - #endif - -// Optimized reading from Blip_Buffer, for use in custom sample output - -// Begins reading from buffer. Name should be unique to the current block. -#define BLIP_READER_BEGIN( name, blip_buffer ) \ - const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\ - blip_long name##_reader_accum = (blip_buffer).reader_accum_ - -// Gets value to pass to BLIP_READER_NEXT() -#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_) - -// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal -// code at the cost of having no bass control -int const blip_reader_default_bass = 9; - -// Current sample -#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16)) - -// Current raw sample in full internal resolution -#define BLIP_READER_READ_RAW( name ) (name##_reader_accum) - -// Advances to next sample -#define BLIP_READER_NEXT( name, bass ) \ - (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass))) - -// Ends reading samples from buffer. The number of samples read must now be removed -// using Blip_Buffer::remove_samples(). -#define BLIP_READER_END( name, blip_buffer ) \ - (void) ((blip_buffer).reader_accum_ = name##_reader_accum) - - -// experimental -#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset) - -blip_long const blip_reader_idx_factor = sizeof (Blip_Buffer::buf_t_); - -#define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\ - name##_reader_accum -= name##_reader_accum >> (bass);\ - name##_reader_accum += name##_reader_buf [(idx)];\ -} - -#define BLIP_READER_NEXT_RAW_IDX_( name, bass, idx ) {\ - name##_reader_accum -= name##_reader_accum >> (bass);\ - name##_reader_accum +=\ - *(Blip_Buffer::buf_t_ const*) ((char const*) name##_reader_buf + (idx));\ -} - -// Compatibility with older version -const long blip_unscaled = 65535; -const int blip_low_quality = blip_med_quality; -const int blip_best_quality = blip_high_quality; - -// Deprecated; use BLIP_READER macros as follows: -// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf ); -// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf ); -// r.read() -> BLIP_READER_READ( r ) -// r.read_raw() -> BLIP_READER_READ_RAW( r ) -// r.next( bass ) -> BLIP_READER_NEXT( r, bass ) -// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass ) -// r.end( buf ) -> BLIP_READER_END( r, buf ) -class Blip_Reader { -public: - int begin( Blip_Buffer& ); - blip_long read() const { return accum >> (blip_sample_bits - 16); } - blip_long read_raw() const { return accum; } - void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); } - void end( Blip_Buffer& b ) { b.reader_accum_ = accum; } -private: - const Blip_Buffer::buf_t_* buf; - blip_long accum; -}; - -#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in -#else - #define BLIP_CLAMP_( in ) (blip_sample_t) in != in -#endif - -// Clamp sample to blip_sample_t range -#define BLIP_CLAMP( sample, out )\ - { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 24) ^ 0x7FFF; } - -struct blip_buffer_state_t -{ - blip_resampled_time_t offset_; - blip_long reader_accum_; - blip_long buf [blip_buffer_extra_]; -}; - -// End of public interface - -#ifndef assert - #include -#endif - -template -inline void Blip_Synth::offset_resampled( blip_resampled_time_t time, - int delta, Blip_Buffer* blip_buf ) const -{ - // If this assertion fails, it means that an attempt was made to add a delta - // at a negative time or past the end of the buffer. - assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ ); - - delta *= impl.delta_factor; - blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY); - int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1)); - -#if BLIP_BUFFER_FAST - blip_long left = buf [0] + delta; - - // Kind of crappy, but doing shift after multiply results in overflow. - // Alternate way of delaying multiply by delta_factor results in worse - // sub-sample resolution. - blip_long right = (delta >> BLIP_PHASE_BITS) * phase; - left -= right; - right += buf [1]; - - buf [0] = left; - buf [1] = right; -#else - - int const fwd = (blip_widest_impulse_ - quality) / 2; - int const rev = fwd + quality - 2; - int const mid = quality / 2 - 1; - - imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase; - - #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - - // this straight forward version gave in better code on GCC for x86 - - #define ADD_IMP( out, in ) \ - buf [out] += (blip_long) imp [blip_res * (in)] * delta - - #define BLIP_FWD( i ) {\ - ADD_IMP( fwd + i, i );\ - ADD_IMP( fwd + 1 + i, i + 1 );\ - } - #define BLIP_REV( r ) {\ - ADD_IMP( rev - r, r + 1 );\ - ADD_IMP( rev + 1 - r, r );\ - } - - BLIP_FWD( 0 ) - if ( quality > 8 ) BLIP_FWD( 2 ) - if ( quality > 12 ) BLIP_FWD( 4 ) - { - ADD_IMP( fwd + mid - 1, mid - 1 ); - ADD_IMP( fwd + mid , mid ); - imp = impulses + phase; - } - if ( quality > 12 ) BLIP_REV( 6 ) - if ( quality > 8 ) BLIP_REV( 4 ) - BLIP_REV( 2 ) - - ADD_IMP( rev , 1 ); - ADD_IMP( rev + 1, 0 ); - - #undef ADD_IMP - - #else - - // for RISC processors, help compiler by reading ahead of writes - - #define BLIP_FWD( i ) {\ - blip_long t0 = i0 * delta + buf [fwd + i];\ - blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\ - i0 = imp [blip_res * (i + 2)];\ - buf [fwd + i] = t0;\ - buf [fwd + 1 + i] = t1;\ - } - #define BLIP_REV( r ) {\ - blip_long t0 = i0 * delta + buf [rev - r];\ - blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\ - i0 = imp [blip_res * (r - 1)];\ - buf [rev - r] = t0;\ - buf [rev + 1 - r] = t1;\ - } - - blip_long i0 = *imp; - BLIP_FWD( 0 ) - if ( quality > 8 ) BLIP_FWD( 2 ) - if ( quality > 12 ) BLIP_FWD( 4 ) - { - blip_long t0 = i0 * delta + buf [fwd + mid - 1]; - blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ]; - imp = impulses + phase; - i0 = imp [blip_res * mid]; - buf [fwd + mid - 1] = t0; - buf [fwd + mid ] = t1; - } - if ( quality > 12 ) BLIP_REV( 6 ) - if ( quality > 8 ) BLIP_REV( 4 ) - BLIP_REV( 2 ) - - blip_long t0 = i0 * delta + buf [rev ]; - blip_long t1 = *imp * delta + buf [rev + 1]; - buf [rev ] = t0; - buf [rev + 1] = t1; - #endif - -#endif -} - -#undef BLIP_FWD -#undef BLIP_REV - -template -#if BLIP_BUFFER_FAST - inline -#endif -void Blip_Synth::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const -{ - offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); -} - -template -#if BLIP_BUFFER_FAST - inline -#endif -void Blip_Synth::update( blip_time_t t, int amp ) -{ - int delta = amp - impl.last_amp; - impl.last_amp = amp; - offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); -} - -inline blip_eq_t::blip_eq_t( double t ) : - treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { } -inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) : - treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { } - -inline int Blip_Buffer::length() const { return length_; } -inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); } -inline long Blip_Buffer::sample_rate() const { return sample_rate_; } -inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; } -inline long Blip_Buffer::clock_rate() const { return clock_rate_; } -inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); } - -inline int Blip_Reader::begin( Blip_Buffer& blip_buf ) -{ - buf = blip_buf.buffer_; - accum = blip_buf.reader_accum_; - return blip_buf.bass_shift_; -} - -inline void Blip_Buffer::remove_silence( long count ) -{ - // fails if you try to remove more samples than available - assert( count <= samples_avail() ); - offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; -} - -inline blip_ulong Blip_Buffer::unsettled() const -{ - return reader_accum_ >> (blip_sample_bits - 16); -} - -int const blip_max_length = 0; -int const blip_default_length = 250; // 1/4 second - -#endif diff --git a/src/dmg/gb_apu/Effects_Buffer.cpp b/src/dmg/gb_apu/Effects_Buffer.cpp deleted file mode 100644 index c418bad5..00000000 --- a/src/dmg/gb_apu/Effects_Buffer.cpp +++ /dev/null @@ -1,638 +0,0 @@ -// Game_Music_Emu $vers. http://www.slack.net/~ant/ - -#include "Effects_Buffer.h" - -#include - -/* Copyright (C) 2006-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module 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 Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -int const fixed_shift = 12; -#define TO_FIXED( f ) fixed_t ((f) * ((fixed_t) 1 << fixed_shift)) -#define FROM_FIXED( f ) ((f) >> fixed_shift) - -int const max_read = 2560; // determines minimum delay - -Effects_Buffer::Effects_Buffer( int max_bufs, long echo_size_ ) : Multi_Buffer( stereo ) -{ - echo_size = max( max_read * (long) stereo, echo_size_ & ~1 ); - clock_rate_ = 0; - bass_freq_ = 90; - bufs = 0; - bufs_size = 0; - bufs_max = max( max_bufs, (int) extra_chans ); - no_echo = true; - no_effects = true; - - // defaults - config_.enabled = false; - config_.delay [0] = 120; - config_.delay [1] = 122; - config_.feedback = 0.2f; - config_.treble = 0.4f; - - static float const sep = 0.8f; - config_.side_chans [0].pan = -sep; - config_.side_chans [1].pan = +sep; - config_.side_chans [0].vol = 1.0f; - config_.side_chans [1].vol = 1.0f; - - memset( &s, 0, sizeof s ); - clear(); -} - -Effects_Buffer::~Effects_Buffer() -{ - delete_bufs(); -} - -// avoid using new [] -blargg_err_t Effects_Buffer::new_bufs( int size ) -{ - bufs = (buf_t*) malloc( size * sizeof *bufs ); - CHECK_ALLOC( bufs ); - for ( int i = 0; i < size; i++ ) - new (bufs + i) buf_t; - bufs_size = size; - return 0; -} - -void Effects_Buffer::delete_bufs() -{ - if ( bufs ) - { - for ( int i = bufs_size; --i >= 0; ) - bufs [i].~buf_t(); - free( bufs ); - bufs = 0; - } - bufs_size = 0; -} - -blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec ) -{ - // extra to allow farther past-the-end pointers - mixer.samples_read = 0; - RETURN_ERR( echo.resize( echo_size + stereo ) ); - return Multi_Buffer::set_sample_rate( rate, msec ); -} - -void Effects_Buffer::clock_rate( long rate ) -{ - clock_rate_ = rate; - for ( int i = bufs_size; --i >= 0; ) - bufs [i].clock_rate( clock_rate_ ); -} - -void Effects_Buffer::bass_freq( int freq ) -{ - bass_freq_ = freq; - for ( int i = bufs_size; --i >= 0; ) - bufs [i].bass_freq( bass_freq_ ); -} - -blargg_err_t Effects_Buffer::set_channel_count( int count, int const* types ) -{ - RETURN_ERR( Multi_Buffer::set_channel_count( count, types ) ); - - delete_bufs(); - - mixer.samples_read = 0; - - RETURN_ERR( chans.resize( count + extra_chans ) ); - - RETURN_ERR( new_bufs( min( bufs_max, count + extra_chans ) ) ); - - for ( int i = bufs_size; --i >= 0; ) - RETURN_ERR( bufs [i].set_sample_rate( sample_rate(), length() ) ); - - for ( int i = chans.size(); --i >= 0; ) - { - chan_t& ch = chans [i]; - ch.cfg.vol = 1.0f; - ch.cfg.pan = 0.0f; - ch.cfg.surround = false; - ch.cfg.echo = false; - } - // side channels with echo - chans [2].cfg.echo = true; - chans [3].cfg.echo = true; - - clock_rate( clock_rate_ ); - bass_freq( bass_freq_ ); - apply_config(); - clear(); - - return 0; -} - -void Effects_Buffer::clear_echo() -{ - if ( echo.size() ) - memset( echo.begin(), 0, echo.size() * sizeof echo [0] ); -} - -void Effects_Buffer::clear() -{ - echo_pos = 0; - s.low_pass [0] = 0; - s.low_pass [1] = 0; - mixer.samples_read = 0; - - for ( int i = bufs_size; --i >= 0; ) - bufs [i].clear(); - clear_echo(); -} - -Effects_Buffer::channel_t Effects_Buffer::channel( int i ) -{ - i += extra_chans; - require( extra_chans <= i && i < (int) chans.size() ); - return chans [i].channel; -} - - -// Configuration - -// 3 wave positions with/without surround, 2 multi (one with same config as wave) -int const simple_bufs = 3 * 2 + 2 - 1; - -Simple_Effects_Buffer::Simple_Effects_Buffer() : - Effects_Buffer( extra_chans + simple_bufs, 18 * 1024L ) -{ - config_.echo = 0.20f; - config_.stereo = 0.20f; - config_.surround = true; - config_.enabled = false; -} - -void Simple_Effects_Buffer::apply_config() -{ - Effects_Buffer::config_t& c = Effects_Buffer::config(); - - c.enabled = config_.enabled; - if ( c.enabled ) - { - c.delay [0] = 120; - c.delay [1] = 122; - c.feedback = config_.echo * 0.7f; - c.treble = 0.6f - 0.3f * config_.echo; - - float sep = config_.stereo + 0.80f; - if ( sep > 1.0f ) - sep = 1.0f; - - c.side_chans [0].pan = -sep; - c.side_chans [1].pan = +sep; - - for ( int i = channel_count(); --i >= 0; ) - { - chan_config_t& ch = Effects_Buffer::chan_config( i ); - - ch.pan = 0.0f; - ch.surround = config_.surround; - ch.echo = false; - - int const type = (channel_types() ? channel_types() [i] : 0); - if ( !(type & noise_type) ) - { - int index = (type & type_index_mask) % 6 - 3; - if ( index < 0 ) - { - index += 3; - ch.surround = false; - ch.echo = true; - } - if ( index >= 1 ) - { - ch.pan = config_.stereo; - if ( index == 1 ) - ch.pan = -ch.pan; - } - } - else if ( type & 1 ) - { - ch.surround = false; - } - } - } - - Effects_Buffer::apply_config(); -} - -int Effects_Buffer::min_delay() const -{ - require( sample_rate() ); - return max_read * 1000L / sample_rate(); -} - -int Effects_Buffer::max_delay() const -{ - require( sample_rate() ); - return (echo_size / stereo - max_read) * 1000L / sample_rate(); -} - -void Effects_Buffer::apply_config() -{ - int i; - - if ( !bufs_size ) - return; - - s.treble = TO_FIXED( config_.treble ); - - bool echo_dirty = false; - - fixed_t old_feedback = s.feedback; - s.feedback = TO_FIXED( config_.feedback ); - if ( !old_feedback && s.feedback ) - echo_dirty = true; - - // delays - for ( i = stereo; --i >= 0; ) - { - long delay = config_.delay [i] * sample_rate() / 1000 * stereo; - delay = max( delay, long (max_read * stereo) ); - delay = min( delay, long (echo_size - max_read * stereo) ); - if ( s.delay [i] != delay ) - { - s.delay [i] = delay; - echo_dirty = true; - } - } - - // side channels - for ( i = 2; --i >= 0; ) - { - chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f; - chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan; - } - - // convert volumes - for ( i = chans.size(); --i >= 0; ) - { - chan_t& ch = chans [i]; - ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan ); - ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan ); - if ( ch.cfg.surround ) - ch.vol [0] = -ch.vol [0]; - } - - assign_buffers(); - - // set side channels - for ( i = chans.size(); --i >= 0; ) - { - chan_t& ch = chans [i]; - ch.channel.left = chans [ch.cfg.echo*2 ].channel.center; - ch.channel.right = chans [ch.cfg.echo*2+1].channel.center; - } - - bool old_echo = !no_echo && !no_effects; - - // determine whether effects and echo are needed at all - no_effects = true; - no_echo = true; - for ( i = chans.size(); --i >= extra_chans; ) - { - chan_t& ch = chans [i]; - if ( ch.cfg.echo && s.feedback ) - no_echo = false; - - if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) ) - no_effects = false; - } - if ( !no_echo ) - no_effects = false; - - if ( chans [0].vol [0] != TO_FIXED( 1 ) || - chans [0].vol [1] != TO_FIXED( 0 ) || - chans [1].vol [0] != TO_FIXED( 0 ) || - chans [1].vol [1] != TO_FIXED( 1 ) ) - no_effects = false; - - if ( !config_.enabled ) - no_effects = true; - - if ( no_effects ) - { - for ( i = chans.size(); --i >= 0; ) - { - chan_t& ch = chans [i]; - ch.channel.center = &bufs [2]; - ch.channel.left = &bufs [0]; - ch.channel.right = &bufs [1]; - } - } - - mixer.bufs [0] = &bufs [0]; - mixer.bufs [1] = &bufs [1]; - mixer.bufs [2] = &bufs [2]; - - if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) ) - clear_echo(); - - channels_changed(); -} - -void Effects_Buffer::assign_buffers() -{ - // assign channels to buffers - int buf_count = 0; - for ( int i = 0; i < (int) chans.size(); i++ ) - { - // put second two side channels at end to give priority to main channels - // in case closest matching is necessary - int x = i; - if ( i > 1 ) - x += 2; - if ( x >= (int) chans.size() ) - x -= (chans.size() - 2); - chan_t& ch = chans [x]; - - int b = 0; - for ( ; b < buf_count; b++ ) - { - if ( ch.vol [0] == bufs [b].vol [0] && - ch.vol [1] == bufs [b].vol [1] && - (ch.cfg.echo == bufs [b].echo || !s.feedback) ) - break; - } - - if ( b >= buf_count ) - { - if ( buf_count < bufs_max ) - { - bufs [b].vol [0] = ch.vol [0]; - bufs [b].vol [1] = ch.vol [1]; - bufs [b].echo = ch.cfg.echo; - buf_count++; - } - else - { - // TODO: this is a mess, needs refinement - dprintf( "Effects_Buffer ran out of buffers; using closest match\n" ); - b = 0; - fixed_t best_dist = TO_FIXED( 8 ); - for ( int h = buf_count; --h >= 0; ) - { - #define CALC_LEVELS( vols, sum, diff, surround ) \ - fixed_t sum, diff;\ - bool surround = false;\ - {\ - fixed_t vol_0 = vols [0];\ - if ( vol_0 < 0 ) vol_0 = -vol_0, surround = true;\ - fixed_t vol_1 = vols [1];\ - if ( vol_1 < 0 ) vol_1 = -vol_1, surround = true;\ - sum = vol_0 + vol_1;\ - diff = vol_0 - vol_1;\ - } - CALC_LEVELS( ch.vol, ch_sum, ch_diff, ch_surround ); - CALC_LEVELS( bufs [h].vol, buf_sum, buf_diff, buf_surround ); - - fixed_t dist = abs( ch_sum - buf_sum ) + abs( ch_diff - buf_diff ); - - if ( ch_surround != buf_surround ) - dist += TO_FIXED( 1 ) / 2; - - if ( s.feedback && ch.cfg.echo != bufs [h].echo ) - dist += TO_FIXED( 1 ) / 2; - - if ( best_dist > dist ) - { - best_dist = dist; - b = h; - } - } - } - } - - //dprintf( "ch %d->buf %d\n", x, b ); - ch.channel.center = &bufs [b]; - } -} - - -// Mixing - -void Effects_Buffer::end_frame( blip_time_t time ) -{ - for ( int i = bufs_size; --i >= 0; ) - bufs [i].end_frame( time ); -} - -long Effects_Buffer::read_samples( blip_sample_t* out, long out_size ) -{ - out_size = min( out_size, samples_avail() ); - - int pair_count = int (out_size >> 1); - require( pair_count * stereo == out_size ); // must read an even number of samples - if ( pair_count ) - { - if ( no_effects ) - { - mixer.read_pairs( out, pair_count ); - } - else - { - int pairs_remain = pair_count; - do - { - // mix at most max_read pairs at a time - int count = max_read; - if ( count > pairs_remain ) - count = pairs_remain; - - if ( no_echo ) - { - // optimization: clear echo here to keep mix_effects() a leaf function - echo_pos = 0; - memset( echo.begin(), 0, count * stereo * sizeof echo [0] ); - } - mix_effects( out, count ); - - blargg_long new_echo_pos = echo_pos + count * stereo; - if ( new_echo_pos >= echo_size ) - new_echo_pos -= echo_size; - echo_pos = new_echo_pos; - assert( echo_pos < echo_size ); - - out += count * stereo; - mixer.samples_read += count; - pairs_remain -= count; - } - while ( pairs_remain ); - } - - if ( samples_avail() <= 0 || immediate_removal() ) - { - for ( int i = bufs_size; --i >= 0; ) - { - buf_t& b = bufs [i]; - // TODO: might miss non-silence settling since it checks END of last read - if ( b.non_silent() ) - b.remove_samples( mixer.samples_read ); - else - b.remove_silence( mixer.samples_read ); - } - mixer.samples_read = 0; - } - } - return out_size; -} - -void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count ) -{ - typedef fixed_t stereo_fixed_t [stereo]; - - // add channels with echo, do echo, add channels without echo, then convert to 16-bit and output - int echo_phase = 1; - do - { - // mix any modified buffers - { - buf_t* buf = bufs; - int bufs_remain = bufs_size; - do - { - if ( buf->non_silent() && ( buf->echo == (bool)echo_phase ) ) - { - stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos]; - int const bass = BLIP_READER_BASS( *buf ); - BLIP_READER_BEGIN( in, *buf ); - BLIP_READER_ADJ_( in, mixer.samples_read ); - fixed_t const vol_0 = buf->vol [0]; - fixed_t const vol_1 = buf->vol [1]; - - int count = unsigned (echo_size - echo_pos) / stereo; - int remain = pair_count; - if ( count > remain ) - count = remain; - do - { - remain -= count; - BLIP_READER_ADJ_( in, count ); - - out += count; - int offset = -count; - do - { - fixed_t s = BLIP_READER_READ( in ); - BLIP_READER_NEXT_IDX_( in, bass, offset ); - - out [offset] [0] += s * vol_0; - out [offset] [1] += s * vol_1; - } - while ( ++offset ); - - out = (stereo_fixed_t*) echo.begin(); - count = remain; - } - while ( remain ); - - BLIP_READER_END( in, *buf ); - } - buf++; - } - while ( --bufs_remain ); - } - - // add echo - if ( echo_phase && !no_echo ) - { - fixed_t const feedback = s.feedback; - fixed_t const treble = s.treble; - - int i = 1; - do - { - fixed_t low_pass = s.low_pass [i]; - - fixed_t* echo_end = &echo [echo_size + i]; - fixed_t const* BLIP_RESTRICT in_pos = &echo [echo_pos + i]; - blargg_long out_offset = echo_pos + i + s.delay [i]; - if ( out_offset >= echo_size ) - out_offset -= echo_size; - assert( out_offset < echo_size ); - fixed_t* BLIP_RESTRICT out_pos = &echo [out_offset]; - - // break into up to three chunks to avoid having to handle wrap-around - // in middle of core loop - int remain = pair_count; - do - { - fixed_t const* pos = in_pos; - if ( pos < out_pos ) - pos = out_pos; - int count = blargg_ulong ((char*) echo_end - (char const*) pos) / - unsigned (stereo * sizeof (fixed_t)); - if ( count > remain ) - count = remain; - remain -= count; - - in_pos += count * stereo; - out_pos += count * stereo; - int offset = -count; - do - { - low_pass += FROM_FIXED( in_pos [offset * stereo] - low_pass ) * treble; - out_pos [offset * stereo] = FROM_FIXED( low_pass ) * feedback; - } - while ( ++offset ); - - if ( in_pos >= echo_end ) in_pos -= echo_size; - if ( out_pos >= echo_end ) out_pos -= echo_size; - } - while ( remain ); - - s.low_pass [i] = low_pass; - } - while ( --i >= 0 ); - } - } - while ( --echo_phase >= 0 ); - - // clamp to 16 bits - { - stereo_fixed_t const* BLIP_RESTRICT in = (stereo_fixed_t*) &echo [echo_pos]; - typedef blip_sample_t stereo_blip_sample_t [stereo]; - stereo_blip_sample_t* BLIP_RESTRICT out = (stereo_blip_sample_t*) out_; - int count = unsigned (echo_size - echo_pos) / (unsigned) stereo; - int remain = pair_count; - if ( count > remain ) - count = remain; - do - { - remain -= count; - in += count; - out += count; - int offset = -count; - do - { - fixed_t in_0 = FROM_FIXED( in [offset] [0] ); - fixed_t in_1 = FROM_FIXED( in [offset] [1] ); - - BLIP_CLAMP( in_0, in_0 ); - out [offset] [0] = (blip_sample_t) in_0; - - BLIP_CLAMP( in_1, in_1 ); - out [offset] [1] = (blip_sample_t) in_1; - } - while ( ++offset ); - - in = (stereo_fixed_t*) echo.begin(); - count = remain; - } - while ( remain ); - } -} diff --git a/src/dmg/gb_apu/Effects_Buffer.h b/src/dmg/gb_apu/Effects_Buffer.h deleted file mode 100644 index 790325d9..00000000 --- a/src/dmg/gb_apu/Effects_Buffer.h +++ /dev/null @@ -1,143 +0,0 @@ -// Multi-channel effects buffer with echo and individual panning for each channel - -// Game_Music_Emu $vers -#ifndef EFFECTS_BUFFER_H -#define EFFECTS_BUFFER_H - -#include "Multi_Buffer.h" - -// See Simple_Effects_Buffer (below) for a simpler interface - -class Effects_Buffer : public Multi_Buffer { -public: - // To reduce memory usage, fewer buffers can be used (with a best-fit - // approach if there are too few), and maximum echo delay can be reduced - Effects_Buffer( int max_bufs = 32, long echo_size = 24 * 1024L ); - - struct pan_vol_t - { - float vol; // 0.0 = silent, 0.5 = half volume, 1.0 = normal - float pan; // -1.0 = left, 0.0 = center, +1.0 = right - }; - - // Global configuration - struct config_t - { - bool enabled; // false = disable all effects - - // Current sound is echoed at adjustable left/right delay, - // with reduced treble and volume (feedback). - float treble; // 1.0 = full treble, 0.1 = very little, 0.0 = silent - int delay [2]; // left, right delays (msec) - float feedback; // 0.0 = no echo, 0.5 = each echo half previous, 1.0 = cacophony - pan_vol_t side_chans [2]; // left and right side channel volume and pan - }; - config_t& config() { return config_; } - - // Limits of delay (msec) - int min_delay() const; - int max_delay() const; - - // Per-channel configuration. Two or more channels with matching parameters are - // optimized to internally use the same buffer. - struct chan_config_t : pan_vol_t - { - // (inherited from pan_vol_t) - //float vol; // these only affect center channel - //float pan; - bool surround; // if true, negates left volume to put sound in back - bool echo; // false = channel doesn't have any echo - }; - chan_config_t& chan_config( int i ) { return chans [i + extra_chans].cfg; } - - // Apply any changes made to config() and chan_config() - virtual void apply_config(); - -public: - ~Effects_Buffer(); - blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length ); - blargg_err_t set_channel_count( int, int const* = 0 ); - void clock_rate( long ); - void bass_freq( int ); - void clear(); - channel_t channel( int ); - void end_frame( blip_time_t ); - long read_samples( blip_sample_t*, long ); - long samples_avail() const { return (bufs [0].samples_avail() - mixer.samples_read) * 2; } - enum { stereo = 2 }; - typedef blargg_long fixed_t; -protected: - enum { extra_chans = stereo * stereo }; -private: - config_t config_; - long clock_rate_; - int bass_freq_; - - blargg_long echo_size; - - struct chan_t - { - fixed_t vol [stereo]; - chan_config_t cfg; - channel_t channel; - }; - blargg_vector chans; - - struct buf_t : Tracked_Blip_Buffer - { - fixed_t vol [stereo]; - bool echo; - - void* operator new ( size_t, void* p ) { return p; } - void operator delete ( void* ) { } - - ~buf_t() { } - }; - buf_t* bufs; - int bufs_size; - int bufs_max; // bufs_size <= bufs_max, to limit memory usage - Stereo_Mixer mixer; - - struct { - long delay [stereo]; - fixed_t treble; - fixed_t feedback; - fixed_t low_pass [stereo]; - } s; - - blargg_vector echo; - blargg_long echo_pos; - - bool no_effects; - bool no_echo; - - void assign_buffers(); - void clear_echo(); - void mix_effects( blip_sample_t* out, int pair_count ); - blargg_err_t new_bufs( int size ); - void delete_bufs(); -}; - -// Simpler interface and lower memory usage -class Simple_Effects_Buffer : public Effects_Buffer { -public: - struct config_t - { - bool enabled; // false = disable all effects - float echo; // 0.0 = none, 1.0 = lots - float stereo; // 0.0 = channels in center, 1.0 = channels on left/right - bool surround; // true = put some channels in back - }; - config_t& config() { return config_; } - - // Apply any changes made to config() - void apply_config(); - -public: - Simple_Effects_Buffer(); -private: - config_t config_; - void chan_config(); // hide -}; - -#endif diff --git a/src/dmg/gb_apu/Gb_Apu.cpp b/src/dmg/gb_apu/Gb_Apu.cpp deleted file mode 100644 index 14004d59..00000000 --- a/src/dmg/gb_apu/Gb_Apu.cpp +++ /dev/null @@ -1,394 +0,0 @@ -// Gb_Snd_Emu 0.2.0. http://www.slack.net/~ant/ - -#include "Gb_Apu.h" - -/* Copyright (C) 2003-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module 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 Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -unsigned const vol_reg = 0xFF24; -unsigned const stereo_reg = 0xFF25; -unsigned const status_reg = 0xFF26; -unsigned const wave_ram = 0xFF30; - -int const power_mask = 0x80; - -void Gb_Apu::treble_eq( blip_eq_t const& eq ) -{ - good_synth.treble_eq( eq ); - med_synth .treble_eq( eq ); -} - -inline int Gb_Apu::calc_output( int osc ) const -{ - int bits = regs [stereo_reg - start_addr] >> osc; - return (bits >> 3 & 2) | (bits & 1); -} - -void Gb_Apu::set_output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right, int osc ) -{ - // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL) - require( !center || (center && !left && !right) || (center && left && right) ); - require( (unsigned) osc <= osc_count ); // fails if you pass invalid osc index - - if ( !center || !left || !right ) - { - left = center; - right = center; - } - - int i = (unsigned) osc % osc_count; - do - { - Gb_Osc& o = *oscs [i]; - o.outputs [1] = right; - o.outputs [2] = left; - o.outputs [3] = center; - o.output = o.outputs [calc_output( i )]; - } - while ( ++i < osc ); -} - -void Gb_Apu::synth_volume( int iv ) -{ - double v = volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv; - good_synth.volume( v ); - med_synth .volume( v ); -} - -void Gb_Apu::apply_volume() -{ - // TODO: Doesn't handle differing left and right volumes (panning). - // Not worth the complexity. - int data = regs [vol_reg - start_addr]; - int left = data >> 4 & 7; - int right = data & 7; - //if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 ); - //if ( left != right ) dprintf( "l: %d r: %d\n", left, right ); - synth_volume( max( left, right ) + 1 ); -} - -void Gb_Apu::volume( double v ) -{ - if ( volume_ != v ) - { - volume_ = v; - apply_volume(); - } -} - -void Gb_Apu::reset_regs() -{ - for ( int i = 0; i < 0x20; i++ ) - regs [i] = 0; - - square1.reset(); - square2.reset(); - wave .reset(); - noise .reset(); - - apply_volume(); -} - -void Gb_Apu::reset_lengths() -{ - square1.length_ctr = 64; - square2.length_ctr = 64; - wave .length_ctr = 256; - noise .length_ctr = 64; -} - -void Gb_Apu::reduce_clicks( bool reduce ) -{ - reduce_clicks_ = reduce; - - // Click reduction makes DAC off generate same output as volume 0 - int dac_off_amp = 0; - if ( reduce && wave.mode != mode_agb ) // AGB already eliminates clicks - dac_off_amp = -Gb_Osc::dac_bias; - - for ( int i = 0; i < osc_count; i++ ) - oscs [i]->dac_off_amp = dac_off_amp; - - // AGB always eliminates clicks on wave channel using same method - if ( wave.mode == mode_agb ) - wave.dac_off_amp = -Gb_Osc::dac_bias; -} - -void Gb_Apu::reset( mode_t mode, bool agb_wave ) -{ - // Hardware mode - if ( agb_wave ) - mode = mode_agb; // using AGB wave features implies AGB hardware - wave.agb_mask = agb_wave ? 0xFF : 0; - for ( int i = 0; i < osc_count; i++ ) - oscs [i]->mode = mode; - reduce_clicks( reduce_clicks_ ); - - // Reset state - frame_time = 0; - last_time = 0; - frame_phase = 0; - - reset_regs(); - reset_lengths(); - - // Load initial wave RAM - static byte const initial_wave [2] [16] = { - {0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA}, - {0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF}, - }; - for ( int b = 2; --b >= 0; ) - { - // Init both banks (does nothing if not in AGB mode) - // TODO: verify that this works - write_register( 0, 0xFF1A, b * 0x40 ); - for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ ) - write_register( 0, i + wave_ram, initial_wave [(mode != mode_dmg)] [i] ); - } -} - -void Gb_Apu::set_tempo( double t ) -{ - frame_period = 4194304 / 512; // 512 Hz - if ( t != 1.0 ) - frame_period = blip_time_t (frame_period / t); -} - -Gb_Apu::Gb_Apu() -{ - wave.wave_ram = ®s [wave_ram - start_addr]; - - oscs [0] = &square1; - oscs [1] = &square2; - oscs [2] = &wave; - oscs [3] = &noise; - - for ( int i = osc_count; --i >= 0; ) - { - Gb_Osc& o = *oscs [i]; - o.regs = ®s [i * 5]; - o.output = 0; - o.outputs [0] = 0; - o.outputs [1] = 0; - o.outputs [2] = 0; - o.outputs [3] = 0; - o.good_synth = &good_synth; - o.med_synth = &med_synth; - } - - reduce_clicks_ = false; - set_tempo( 1.0 ); - volume_ = 1.0; - reset(); -} - -void Gb_Apu::run_until_( blip_time_t end_time ) -{ - while ( true ) - { - // run oscillators - blip_time_t time = end_time; - if ( time > frame_time ) - time = frame_time; - - square1.run( last_time, time ); - square2.run( last_time, time ); - wave .run( last_time, time ); - noise .run( last_time, time ); - last_time = time; - - if ( time == end_time ) - break; - - // run frame sequencer - frame_time += frame_period * Gb_Osc::clk_mul; - switch ( frame_phase++ ) - { - case 2: - case 6: - // 128 Hz - square1.clock_sweep(); - case 0: - case 4: - // 256 Hz - square1.clock_length(); - square2.clock_length(); - wave .clock_length(); - noise .clock_length(); - break; - - case 7: - // 64 Hz - frame_phase = 0; - square1.clock_envelope(); - square2.clock_envelope(); - noise .clock_envelope(); - } - } -} - -inline void Gb_Apu::run_until( blip_time_t time ) -{ - require( time >= last_time ); // end_time must not be before previous time - if ( time > last_time ) - run_until_( time ); -} - -void Gb_Apu::end_frame( blip_time_t end_time ) -{ - if ( end_time > last_time ) - run_until( end_time ); - - frame_time -= end_time; - assert( frame_time >= 0 ); - - last_time -= end_time; - assert( last_time >= 0 ); -} - -void Gb_Apu::silence_osc( Gb_Osc& o ) -{ - int delta = -o.last_amp; - if ( delta ) - { - o.last_amp = 0; - if ( o.output ) - { - o.output->set_modified(); - med_synth.offset( last_time, delta, o.output ); - } - } -} - -void Gb_Apu::apply_stereo() -{ - for ( int i = osc_count; --i >= 0; ) - { - Gb_Osc& o = *oscs [i]; - Blip_Buffer* out = o.outputs [calc_output( i )]; - if ( o.output != out ) - { - silence_osc( o ); - o.output = out; - } - } -} - -void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data ) -{ - require( (unsigned) data < 0x100 ); - - int reg = addr - start_addr; - if ( (unsigned) reg >= register_count ) - { - require( false ); - return; - } - - if ( addr < status_reg && !(regs [status_reg - start_addr] & power_mask) ) - { - // Power is off - - // length counters can only be written in DMG mode - if ( wave.mode != mode_dmg || (reg != 1 && reg != 5+1 && reg != 10+1 && reg != 15+1) ) - return; - - if ( reg < 10 ) - data &= 0x3F; // clear square duty - } - - run_until( time ); - - if ( addr >= wave_ram ) - { - wave.write( addr, data ); - } - else - { - int old_data = regs [reg]; - regs [reg] = data; - - if ( addr < vol_reg ) - { - // Oscillator - write_osc( reg / 5, reg, old_data, data ); - } - else if ( addr == vol_reg && data != old_data ) - { - // Master volume - for ( int i = osc_count; --i >= 0; ) - silence_osc( *oscs [i] ); - - apply_volume(); - } - else if ( addr == stereo_reg ) - { - // Stereo panning - apply_stereo(); - } - else if ( addr == status_reg && (data ^ old_data) & power_mask ) - { - // Power control - frame_phase = 0; - for ( int i = osc_count; --i >= 0; ) - silence_osc( *oscs [i] ); - - reset_regs(); - if ( wave.mode != mode_dmg ) - reset_lengths(); - - regs [status_reg - start_addr] = data; - } - } -} - -int Gb_Apu::read_register( blip_time_t time, unsigned addr ) -{ - run_until( time ); - - int reg = addr - start_addr; - if ( (unsigned) reg >= register_count ) - { - require( false ); - return 0; - } - - if ( addr >= wave_ram ) - return wave.read( addr ); - - // Value read back has some bits always set - static byte const masks [] = { - 0x80,0x3F,0x00,0xFF,0xBF, - 0xFF,0x3F,0x00,0xFF,0xBF, - 0x7F,0xFF,0x9F,0xFF,0xBF, - 0xFF,0xFF,0x00,0x00,0xBF, - 0x00,0x00,0x70, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF - }; - int mask = masks [reg]; - if ( wave.agb_mask && (reg == 10 || reg == 12) ) - mask = 0x1F; // extra implemented bits in wave regs on AGB - int data = regs [reg] | mask; - - // Status register - if ( addr == status_reg ) - { - data &= 0xF0; - data |= (int) square1.enabled << 0; - data |= (int) square2.enabled << 1; - data |= (int) wave .enabled << 2; - data |= (int) noise .enabled << 3; - } - - return data; -} diff --git a/src/dmg/gb_apu/Gb_Apu.h b/src/dmg/gb_apu/Gb_Apu.h deleted file mode 100644 index 3f132096..00000000 --- a/src/dmg/gb_apu/Gb_Apu.h +++ /dev/null @@ -1,182 +0,0 @@ -// Nintendo Game Boy sound hardware emulator with save state support - -// Gb_Snd_Emu 0.2.0 -#ifndef GB_APU_H -#define GB_APU_H - -#include "Gb_Oscs.h" - -struct gb_apu_state_t; - -class Gb_Apu { -public: -// Basics - - // Clock rate that sound hardware runs at. - enum { clock_rate = 4194304 * GB_APU_OVERCLOCK }; - - // Sets buffer(s) to generate sound into. If left and right are NULL, output is mono. - // If all are NULL, no output is generated but other emulation still runs. - // If chan is specified, only that channel's output is changed, otherwise all are. - enum { osc_count = 4 }; // 0: Square 1, 1: Square 2, 2: Wave, 3: Noise - void set_output( Blip_Buffer* center, Blip_Buffer* left = NULL, Blip_Buffer* right = NULL, - int chan = osc_count ); - - // Resets hardware to initial power on state BEFORE boot ROM runs. Mode selects - // sound hardware. Additional AGB wave features are enabled separately. - enum mode_t { - mode_dmg, // Game Boy monochrome - mode_cgb, // Game Boy Color - mode_agb // Game Boy Advance - }; - void reset( mode_t mode = mode_cgb, bool agb_wave = false ); - - // Reads and writes must be within the start_addr to end_addr range, inclusive. - // Addresses outside this range are not mapped to the sound hardware. - enum { start_addr = 0xFF10 }; - enum { end_addr = 0xFF3F }; - enum { register_count = end_addr - start_addr + 1 }; - - // Times are specified as the number of clocks since the beginning of the - // current time frame. - - // Emulates CPU write of data to addr at specified time. - void write_register( blip_time_t time, unsigned addr, int data ); - - // Emulates CPU read from addr at specified time. - int read_register( blip_time_t time, unsigned addr ); - - // Emulates sound hardware up to specified time, ends current time frame, then - // starts a new frame at time 0. - void end_frame( blip_time_t frame_length ); - -// Sound adjustments - - // Sets overall volume, where 1.0 is normal. - void volume( double ); - - // If true, reduces clicking by disabling DAC biasing. Note that this reduces - // emulation accuracy, since the clicks are authentic. - void reduce_clicks( bool reduce = true ); - - // Sets treble equalization. - void treble_eq( blip_eq_t const& ); - - // Treble and bass values for various hardware. - enum { - speaker_treble = -47, // speaker on system - speaker_bass = 2000, - dmg_treble = 0, // headphones on each system - dmg_bass = 30, - cgb_treble = 0, - cgb_bass = 300, // CGB has much less bass - agb_treble = 0, - agb_bass = 30 - }; - - // Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the - // tempo in a game music player. - void set_tempo( double ); - -// Save states - - // Saves full emulation state to state_out. Data format is portable and - // includes some extra space to avoid expansion in case more state needs - // to be stored in the future. - void save_state( gb_apu_state_t* state_out ); - - // Loads state. You should call reset() BEFORE this. - blargg_err_t load_state( gb_apu_state_t const& in ); - -public: - Gb_Apu(); - - // Use set_output() in place of these - BLARGG_DEPRECATED void output ( Blip_Buffer* c ) { set_output( c, c, c ); } - BLARGG_DEPRECATED void output ( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r ); } - BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c ) { set_output( c, c, c, i ); } - BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r, i ); } - -private: - // noncopyable - Gb_Apu( const Gb_Apu& ); - Gb_Apu& operator = ( const Gb_Apu& ); - - Gb_Osc* oscs [osc_count]; - blip_time_t last_time; // time sound emulator has been run to - blip_time_t frame_period; // clocks between each frame sequencer step - double volume_; - bool reduce_clicks_; - - Gb_Sweep_Square square1; - Gb_Square square2; - Gb_Wave wave; - Gb_Noise noise; - blip_time_t frame_time; // time of next frame sequencer action - int frame_phase; // phase of next frame sequencer step - enum { regs_size = register_count + 0x10 }; - BOOST::uint8_t regs [regs_size];// last values written to registers - - // large objects after everything else - Gb_Osc::Good_Synth good_synth; - Gb_Osc::Med_Synth med_synth; - - void reset_lengths(); - void reset_regs(); - int calc_output( int osc ) const; - void apply_stereo(); - void apply_volume(); - void synth_volume( int ); - void run_until_( blip_time_t ); - void run_until( blip_time_t ); - void silence_osc( Gb_Osc& ); - void write_osc( int index, int reg, int old_data, int data ); - const char* save_load( gb_apu_state_t*, bool save ); - void save_load2( gb_apu_state_t*, bool save ); - friend class Gb_Apu_Tester; -}; - -// Format of save state. Should be stable across versions of the library, -// with earlier versions properly opening later save states. Includes some -// room for expansion so the state size shouldn't increase. -struct gb_apu_state_t -{ -#if GB_APU_CUSTOM_STATE - // Values stored as plain int so your code can read/write them easily. - // Structure can NOT be written to disk, since format is not portable. - typedef int val_t; -#else - // Values written in portable little-endian format, allowing structure - // to be written directly to disk. - typedef unsigned char val_t [4]; -#endif - - enum { format0 = 0x50414247 }; - - val_t format; // format of all following data - val_t version; // later versions just add fields to end - - unsigned char regs [0x40]; - val_t frame_time; - val_t frame_phase; - - val_t sweep_freq; - val_t sweep_delay; - val_t sweep_enabled; - val_t sweep_neg; - val_t noise_divider; - val_t wave_buf; - - val_t delay [4]; - val_t length_ctr [4]; - val_t phase [4]; - val_t enabled [4]; - - val_t env_delay [3]; - val_t env_volume [3]; - val_t env_enabled [3]; - - val_t unused [13]; // for future expansion -}; - -#endif diff --git a/src/dmg/gb_apu/Gb_Apu_State.cpp b/src/dmg/gb_apu/Gb_Apu_State.cpp deleted file mode 100644 index f726ccbd..00000000 --- a/src/dmg/gb_apu/Gb_Apu_State.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Gb_Snd_Emu $vers. http://www.slack.net/~ant/ - -#include "Gb_Apu.h" - -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module 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 Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#if GB_APU_CUSTOM_STATE - #define REFLECT( x, y ) (save ? (io->y) = (x) : (x) = (io->y) ) -#else - #define REFLECT( x, y ) (save ? set_val( io->y, x ) : (void) ((x) = get_val( io->y ))) - - static blargg_ulong get_val( byte const* p ) - { - return p [3] * 0x1000000 + p [2] * 0x10000 + p [1] * 0x100 + p [0]; - } - - static void set_val( byte* p, blargg_ulong n ) - { - p [0] = (byte) (n ); - p [1] = (byte) (n >> 8); - p [2] = (byte) (n >> 16); - p [3] = (byte) (n >> 24); - } -#endif - -inline const char* Gb_Apu::save_load( gb_apu_state_t* io, bool save ) -{ - #if !GB_APU_CUSTOM_STATE - assert( sizeof (gb_apu_state_t) == 256 ); - #endif - - int format = io->format0; - REFLECT( format, format ); - if ( format != io->format0 ) - return "Unsupported sound save state format"; - - int version = 0; - REFLECT( version, version ); - - // Registers and wave RAM - assert( regs_size == sizeof io->regs ); - if ( save ) - memcpy( io->regs, regs, sizeof io->regs ); - else - memcpy( regs, io->regs, sizeof regs ); - - // Frame sequencer - REFLECT( frame_time, frame_time ); - REFLECT( frame_phase, frame_phase ); - - REFLECT( square1.sweep_freq, sweep_freq ); - REFLECT( square1.sweep_delay, sweep_delay ); - REFLECT( square1.sweep_enabled, sweep_enabled ); - REFLECT( square1.sweep_neg, sweep_neg ); - - REFLECT( noise.divider, noise_divider ); - REFLECT( wave.sample_buf, wave_buf ); - - return 0; -} - -// second function to avoid inline limits of some compilers -inline void Gb_Apu::save_load2( gb_apu_state_t* io, bool save ) -{ - for ( int i = osc_count; --i >= 0; ) - { - Gb_Osc& osc = *oscs [i]; - REFLECT( osc.delay, delay [i] ); - REFLECT( osc.length_ctr, length_ctr [i] ); - REFLECT( osc.phase, phase [i] ); - REFLECT( osc.enabled, enabled [i] ); - - if ( i != 2 ) - { - int j = min( i, 2 ); - Gb_Env& env = STATIC_CAST(Gb_Env&,osc); - REFLECT( env.env_delay, env_delay [j] ); - REFLECT( env.volume, env_volume [j] ); - REFLECT( env.env_enabled, env_enabled [j] ); - } - } -} - -void Gb_Apu::save_state( gb_apu_state_t* out ) -{ - (void) save_load( out, true ); - save_load2( out, true ); - - #if !GB_APU_CUSTOM_STATE - memset( out->unused, 0, sizeof out->unused ); - #endif -} - -blargg_err_t Gb_Apu::load_state( gb_apu_state_t const& in ) -{ - RETURN_ERR( save_load( CONST_CAST(gb_apu_state_t*,&in), false ) ); - save_load2( CONST_CAST(gb_apu_state_t*,&in), false ); - - apply_stereo(); - synth_volume( 0 ); // suppress output for the moment - run_until_( last_time ); // get last_amp updated - apply_volume(); // now use correct volume - - return 0; -} diff --git a/src/dmg/gb_apu/Gb_Oscs.cpp b/src/dmg/gb_apu/Gb_Oscs.cpp deleted file mode 100644 index 644f6ddd..00000000 --- a/src/dmg/gb_apu/Gb_Oscs.cpp +++ /dev/null @@ -1,665 +0,0 @@ -// Gb_Snd_Emu 0.2.0. http://www.slack.net/~ant/ - -#include "Gb_Apu.h" - -/* Copyright (C) 2003-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module 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 Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -bool const cgb_02 = false; // enables bug in early CGB units that causes problems in some games -bool const cgb_05 = false; // enables CGB-05 zombie behavior - -int const trigger_mask = 0x80; -int const length_enabled = 0x40; - -void Gb_Osc::reset() -{ - output = 0; - last_amp = 0; - delay = 0; - phase = 0; - enabled = false; -} - -inline void Gb_Osc::update_amp( blip_time_t time, int new_amp ) -{ - output->set_modified(); - int delta = new_amp - last_amp; - if ( delta ) - { - last_amp = new_amp; - med_synth->offset( time, delta, output ); - } -} - -// Units - -void Gb_Osc::clock_length() -{ - if ( (regs [4] & length_enabled) && length_ctr ) - { - if ( --length_ctr <= 0 ) - enabled = false; - } -} - -inline int Gb_Env::reload_env_timer() -{ - int raw = regs [2] & 7; - env_delay = (raw ? raw : 8); - return raw; -} - -void Gb_Env::clock_envelope() -{ - if ( env_enabled && --env_delay <= 0 && reload_env_timer() ) - { - int v = volume + (regs [2] & 0x08 ? +1 : -1); - if ( 0 <= v && v <= 15 ) - volume = v; - else - env_enabled = false; - } -} - -inline void Gb_Sweep_Square::reload_sweep_timer() -{ - sweep_delay = (regs [0] & period_mask) >> 4; - if ( !sweep_delay ) - sweep_delay = 8; -} - -void Gb_Sweep_Square::calc_sweep( bool update ) -{ - int const shift = regs [0] & shift_mask; - int const delta = sweep_freq >> shift; - sweep_neg = (regs [0] & 0x08) != 0; - int const freq = sweep_freq + (sweep_neg ? -delta : delta); - - if ( freq > 0x7FF ) - { - enabled = false; - } - else if ( shift && update ) - { - sweep_freq = freq; - - regs [3] = freq & 0xFF; - regs [4] = (regs [4] & ~0x07) | (freq >> 8 & 0x07); - } -} - -void Gb_Sweep_Square::clock_sweep() -{ - if ( --sweep_delay <= 0 ) - { - reload_sweep_timer(); - if ( sweep_enabled && (regs [0] & period_mask) ) - { - calc_sweep( true ); - calc_sweep( false ); - } - } -} - -int Gb_Wave::access( unsigned addr ) const -{ - if ( enabled ) - { - addr = phase & (bank_size - 1); - if ( mode == Gb_Apu::mode_dmg ) - { - addr++; - if ( delay > clk_mul ) - return -1; // can only access within narrow time window while playing - } - addr >>= 1; - } - return addr & 0x0F; -} - -// write_register - -int Gb_Osc::write_trig( int frame_phase, int max_len, int old_data ) -{ - int data = regs [4]; - - if ( (frame_phase & 1) && !(old_data & length_enabled) && length_ctr ) - { - if ( (data & length_enabled) || cgb_02 ) - length_ctr--; - } - - if ( data & trigger_mask ) - { - enabled = true; - if ( !length_ctr ) - { - length_ctr = max_len; - if ( (frame_phase & 1) && (data & length_enabled) ) - length_ctr--; - } - } - - if ( !length_ctr ) - enabled = false; - - return data & trigger_mask; -} - -inline void Gb_Env::zombie_volume( int old, int data ) -{ - int v = volume; - if ( mode == Gb_Apu::mode_agb || cgb_05 ) - { - // CGB-05 behavior, very close to AGB behavior as well - if ( (old ^ data) & 8 ) - { - if ( !(old & 8) ) - { - v++; - if ( old & 7 ) - v++; - } - - v = 16 - v; - } - else if ( (old & 0x0F) == 8 ) - { - v++; - } - } - else - { - // CGB-04&02 behavior, very close to MGB behavior as well - if ( !(old & 7) && env_enabled ) - v++; - else if ( !(old & 8) ) - v += 2; - - if ( (old ^ data) & 8 ) - v = 16 - v; - } - volume = v & 0x0F; -} - -bool Gb_Env::write_register( int frame_phase, int reg, int old, int data ) -{ - int const max_len = 64; - - switch ( reg ) - { - case 1: - length_ctr = max_len - (data & (max_len - 1)); - break; - - case 2: - if ( !dac_enabled() ) - enabled = false; - - zombie_volume( old, data ); - - if ( (data & 7) && env_delay == 8 ) - { - env_delay = 1; - clock_envelope(); // TODO: really happens at next length clock - } - break; - - case 4: - if ( write_trig( frame_phase, max_len, old ) ) - { - volume = regs [2] >> 4; - reload_env_timer(); - env_enabled = true; - if ( frame_phase == 7 ) - env_delay++; - if ( !dac_enabled() ) - enabled = false; - return true; - } - } - return false; -} - -bool Gb_Square::write_register( int frame_phase, int reg, int old_data, int data ) -{ - bool result = Gb_Env::write_register( frame_phase, reg, old_data, data ); - if ( result ) - delay = (delay & (4 * clk_mul - 1)) + period(); - return result; -} - -inline void Gb_Noise::write_register( int frame_phase, int reg, int old_data, int data ) -{ - if ( Gb_Env::write_register( frame_phase, reg, old_data, data ) ) - { - phase = 0x7FFF; - delay += 8 * clk_mul; - } -} - -inline void Gb_Sweep_Square::write_register( int frame_phase, int reg, int old_data, int data ) -{ - if ( reg == 0 && sweep_enabled && sweep_neg && !(data & 0x08) ) - enabled = false; // sweep negate disabled after used - - if ( Gb_Square::write_register( frame_phase, reg, old_data, data ) ) - { - sweep_freq = frequency(); - sweep_neg = false; - reload_sweep_timer(); - sweep_enabled = (regs [0] & (period_mask | shift_mask)) != 0; - if ( regs [0] & shift_mask ) - calc_sweep( false ); - } -} - -void Gb_Wave::corrupt_wave() -{ - int pos = ((phase + 1) & (bank_size - 1)) >> 1; - if ( pos < 4 ) - wave_ram [0] = wave_ram [pos]; - else - for ( int i = 4; --i >= 0; ) - wave_ram [i] = wave_ram [(pos & ~3) + i]; -} - -inline void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int data ) -{ - int const max_len = 256; - - switch ( reg ) - { - case 0: - if ( !dac_enabled() ) - enabled = false; - break; - - case 1: - length_ctr = max_len - data; - break; - - case 4: - bool was_enabled = enabled; - if ( write_trig( frame_phase, max_len, old_data ) ) - { - if ( !dac_enabled() ) - enabled = false; - else if ( mode == Gb_Apu::mode_dmg && was_enabled && - (unsigned) (delay - 2 * clk_mul) < 2 * clk_mul ) - corrupt_wave(); - - phase = 0; - delay = period() + 6 * clk_mul; - } - } -} - -void Gb_Apu::write_osc( int index, int reg, int old_data, int data ) -{ - reg -= index * 5; - switch ( index ) - { - case 0: square1.write_register( frame_phase, reg, old_data, data ); break; - case 1: square2.write_register( frame_phase, reg, old_data, data ); break; - case 2: wave .write_register( frame_phase, reg, old_data, data ); break; - case 3: noise .write_register( frame_phase, reg, old_data, data ); break; - } -} - -// Synthesis - -void Gb_Square::run( blip_time_t time, blip_time_t end_time ) -{ - // Calc duty and phase - static byte const duty_offsets [4] = { 1, 1, 3, 7 }; - static byte const duties [4] = { 1, 2, 4, 6 }; - int const duty_code = regs [1] >> 6; - int duty_offset = duty_offsets [duty_code]; - int duty = duties [duty_code]; - if ( mode == Gb_Apu::mode_agb ) - { - // AGB uses inverted duty - duty_offset -= duty; - duty = 8 - duty; - } - int ph = (this->phase + duty_offset) & 7; - - // Determine what will be generated - int vol = 0; - Blip_Buffer* const out = this->output; - if ( out ) - { - int amp = dac_off_amp; - if ( dac_enabled() ) - { - if ( enabled ) - vol = this->volume; - - amp = -dac_bias; - if ( mode == Gb_Apu::mode_agb ) - amp = -(vol >> 1); - - // Play inaudible frequencies as constant amplitude - if ( frequency() >= 0x7FA && delay < 32 * clk_mul ) - { - amp += (vol * duty) >> 3; - vol = 0; - } - - if ( ph < duty ) - { - amp += vol; - vol = -vol; - } - } - update_amp( time, amp ); - } - - // Generate wave - time += delay; - if ( time < end_time ) - { - int const per = this->period(); - if ( !vol ) - { - // Maintain phase when not playing - int count = (end_time - time + per - 1) / per; - ph += count; // will be masked below - time += (blip_time_t) count * per; - } - else - { - // Output amplitude transitions - int delta = vol; - do - { - ph = (ph + 1) & 7; - if ( ph == 0 || ph == duty ) - { - good_synth->offset_inline( time, delta, out ); - delta = -delta; - } - time += per; - } - while ( time < end_time ); - - if ( delta != vol ) - last_amp -= delta; - } - this->phase = (ph - duty_offset) & 7; - } - delay = time - end_time; -} - -// Quickly runs LFSR for a large number of clocks. For use when noise is generating -// no sound. -static unsigned run_lfsr( unsigned s, unsigned mask, int count ) -{ - bool const optimized = true; // set to false to use only unoptimized loop in middle - - // optimization used in several places: - // ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n) - - if ( mask == 0x4000 && optimized ) - { - if ( count >= 32767 ) - count %= 32767; - - // Convert from Fibonacci to Galois configuration, - // shifted left 1 bit - s ^= (s & 1) * 0x8000; - - // Each iteration is equivalent to clocking LFSR 255 times - while ( (count -= 255) > 0 ) - s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3); - count += 255; - - // Each iteration is equivalent to clocking LFSR 15 times - // (interesting similarity to single clocking below) - while ( (count -= 15) > 0 ) - s ^= ((s & 2) * (3 << 13)) ^ (s >> 1); - count += 15; - - // Remaining singles - while ( --count >= 0 ) - s = ((s & 2) * (3 << 13)) ^ (s >> 1); - - // Convert back to Fibonacci configuration - s &= 0x7FFF; - } - else if ( count < 8 || !optimized ) - { - // won't fully replace upper 8 bits, so have to do the unoptimized way - while ( --count >= 0 ) - s = (s >> 1 | mask) ^ (mask & -((s - 1) & 2)); - } - else - { - if ( count > 127 ) - { - count %= 127; - if ( !count ) - count = 127; // must run at least once - } - - // Need to keep one extra bit of history - s = s << 1 & 0xFF; - - // Convert from Fibonacci to Galois configuration, - // shifted left 2 bits - s ^= (s & 2) * 0x80; - - // Each iteration is equivalent to clocking LFSR 7 times - // (interesting similarity to single clocking below) - while ( (count -= 7) > 0 ) - s ^= ((s & 4) * (3 << 5)) ^ (s >> 1); - count += 7; - - // Remaining singles - while ( --count >= 0 ) - s = ((s & 4) * (3 << 5)) ^ (s >> 1); - - // Convert back to Fibonacci configuration and - // repeat last 8 bits above significant 7 - s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F); - } - - return s; -} - -void Gb_Noise::run( blip_time_t time, blip_time_t end_time ) -{ - // Determine what will be generated - int vol = 0; - Blip_Buffer* const out = this->output; - if ( out ) - { - int amp = dac_off_amp; - if ( dac_enabled() ) - { - if ( enabled ) - vol = this->volume; - - amp = -dac_bias; - if ( mode == Gb_Apu::mode_agb ) - amp = -(vol >> 1); - - if ( !(phase & 1) ) - { - amp += vol; - vol = -vol; - } - } - - // AGB negates final output - if ( mode == Gb_Apu::mode_agb ) - { - vol = -vol; - amp = -amp; - } - - update_amp( time, amp ); - } - - // Run timer and calculate time of next LFSR clock - static byte const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 }; - int const period1 = period1s [regs [3] & 7] * clk_mul; - { - int extra = (end_time - time) - delay; - int const per2 = this->period2(); - time += delay + ((divider ^ (per2 >> 1)) & (per2 - 1)) * period1; - - int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1); - divider = (divider - count) & period2_mask; - delay = count * period1 - extra; - } - - // Generate wave - if ( time < end_time ) - { - unsigned const mask = this->lfsr_mask(); - unsigned bits = this->phase; - - int per = period2( period1 * 8 ); - if ( period2_index() >= 0xE ) - { - time = end_time; - } - else if ( !vol ) - { - // Maintain phase when not playing - int count = (end_time - time + per - 1) / per; - time += (blip_time_t) count * per; - bits = run_lfsr( bits, ~mask, count ); - } - else - { - // Output amplitude transitions - int delta = -vol; - do - { - unsigned changed = bits + 1; - bits = bits >> 1 & mask; - if ( changed & 2 ) - { - bits |= ~mask; - delta = -delta; - med_synth->offset_inline( time, delta, out ); - } - time += per; - } - while ( time < end_time ); - - if ( delta == vol ) - last_amp += delta; - } - this->phase = bits; - } -} - -void Gb_Wave::run( blip_time_t time, blip_time_t end_time ) -{ - // Calc volume - static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 }; - int const volume_shift = 2; - int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB - int const volume_mul = volumes [volume_idx]; - - // Determine what will be generated - int playing = false; - Blip_Buffer* const out = this->output; - if ( out ) - { - int amp = dac_off_amp; - if ( dac_enabled() ) - { - // Play inaudible frequencies as constant amplitude - amp = 8 << 4; // really depends on average of all samples in wave - - // if delay is larger, constant amplitude won't start yet - if ( frequency() <= 0x7FB || delay > 15 * clk_mul ) - { - if ( volume_mul ) - playing = (int) enabled; - - amp = (sample_buf << (phase << 2 & 4) & 0xF0) * playing; - } - - amp = ((amp * volume_mul) >> (volume_shift + 4)) - dac_bias; - } - update_amp( time, amp ); - } - - // Generate wave - time += delay; - if ( time < end_time ) - { - byte const* wave = this->wave_ram; - - // wave size and bank - int const size20_mask = 0x20; - int const flags = regs [0] & agb_mask; - int const wave_mask = (flags & size20_mask) | 0x1F; - int swap_banks = 0; - if ( flags & bank40_mask ) - { - swap_banks = flags & size20_mask; - wave += bank_size/2 - (swap_banks >> 1); - } - - int ph = this->phase ^ swap_banks; - ph = (ph + 1) & wave_mask; // pre-advance - - int const per = this->period(); - if ( !playing ) - { - // Maintain phase when not playing - int count = (end_time - time + per - 1) / per; - ph += count; // will be masked below - time += (blip_time_t) count * per; - } - else - { - // Output amplitude transitions - int lamp = this->last_amp + dac_bias; - do - { - // Extract nybble - int nybble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0; - ph = (ph + 1) & wave_mask; - - // Scale by volume - int amp = (nybble * volume_mul) >> (volume_shift + 4); - - int delta = amp - lamp; - if ( delta ) - { - lamp = amp; - med_synth->offset_inline( time, delta, out ); - } - time += per; - } - while ( time < end_time ); - this->last_amp = lamp - dac_bias; - } - ph = (ph - 1) & wave_mask; // undo pre-advance and mask position - - // Keep track of last byte read - if ( enabled ) - sample_buf = wave [ph >> 1]; - - this->phase = ph ^ swap_banks; // undo swapped banks - } - delay = time - end_time; -} diff --git a/src/dmg/gb_apu/Gb_Oscs.h b/src/dmg/gb_apu/Gb_Oscs.h deleted file mode 100644 index 175127b9..00000000 --- a/src/dmg/gb_apu/Gb_Oscs.h +++ /dev/null @@ -1,190 +0,0 @@ -// Private oscillators used by Gb_Apu - -// Gb_Snd_Emu 0.2.0 -#ifndef GB_OSCS_H -#define GB_OSCS_H - -#include "blargg_common.h" -#include "Blip_Buffer.h" - -#ifndef GB_APU_OVERCLOCK - #define GB_APU_OVERCLOCK 1 -#endif - -#if GB_APU_OVERCLOCK & (GB_APU_OVERCLOCK - 1) - #error "GB_APU_OVERCLOCK must be a power of 2" -#endif - -class Gb_Osc { -protected: - - // 11-bit frequency in NRx3 and NRx4 - int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; } - - void update_amp( blip_time_t, int new_amp ); - int write_trig( int frame_phase, int max_len, int old_data ); -public: - - enum { clk_mul = GB_APU_OVERCLOCK }; - enum { dac_bias = 7 }; - - Blip_Buffer* outputs [4];// NULL, right, left, center - Blip_Buffer* output; // where to output sound - BOOST::uint8_t* regs; // osc's 5 registers - int mode; // mode_dmg, mode_cgb, mode_agb - int dac_off_amp;// amplitude when DAC is off - int last_amp; // current amplitude in Blip_Buffer - typedef Blip_Synth Good_Synth; - typedef Blip_Synth Med_Synth; - Good_Synth const* good_synth; - Med_Synth const* med_synth; - - int delay; // clocks until frequency timer expires - int length_ctr; // length counter - unsigned phase; // waveform phase (or equivalent) - bool enabled; // internal enabled flag - - void clock_length(); - void reset(); -}; - -class Gb_Env : public Gb_Osc { -public: - int env_delay; - int volume; - bool env_enabled; - - void clock_envelope(); - bool write_register( int frame_phase, int reg, int old_data, int data ); - - void reset() - { - env_delay = 0; - volume = 0; - Gb_Osc::reset(); - } -protected: - // Non-zero if DAC is enabled - int dac_enabled() const { return regs [2] & 0xF8; } -private: - void zombie_volume( int old, int data ); - int reload_env_timer(); -}; - -class Gb_Square : public Gb_Env { -public: - bool write_register( int frame_phase, int reg, int old_data, int data ); - void run( blip_time_t, blip_time_t ); - - void reset() - { - Gb_Env::reset(); - delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger) - } -private: - // Frequency timer period - int period() const { return (2048 - frequency()) * (4 * clk_mul); } -}; - -class Gb_Sweep_Square : public Gb_Square { -public: - int sweep_freq; - int sweep_delay; - bool sweep_enabled; - bool sweep_neg; - - void clock_sweep(); - void write_register( int frame_phase, int reg, int old_data, int data ); - - void reset() - { - sweep_freq = 0; - sweep_delay = 0; - sweep_enabled = false; - sweep_neg = false; - Gb_Square::reset(); - } -private: - enum { period_mask = 0x70 }; - enum { shift_mask = 0x07 }; - - void calc_sweep( bool update ); - void reload_sweep_timer(); -}; - -class Gb_Noise : public Gb_Env { -public: - - int divider; // noise has more complex frequency divider setup - - void run( blip_time_t, blip_time_t ); - void write_register( int frame_phase, int reg, int old_data, int data ); - - void reset() - { - divider = 0; - Gb_Env::reset(); - delay = 4 * clk_mul; // TODO: remove? - } -private: - enum { period2_mask = 0x1FFFF }; - - int period2_index() const { return regs [3] >> 4; } - int period2( int base = 8 ) const { return base << period2_index(); } - unsigned lfsr_mask() const { return (regs [3] & 0x08) ? ~0x4040 : ~0x4000; } -}; - -class Gb_Wave : public Gb_Osc { -public: - int sample_buf; // last wave RAM byte read (hardware has this as well) - - void write_register( int frame_phase, int reg, int old_data, int data ); - void run( blip_time_t, blip_time_t ); - - // Reads/writes wave RAM - int read( unsigned addr ) const; - void write( unsigned addr, int data ); - - void reset() - { - sample_buf = 0; - Gb_Osc::reset(); - } - -private: - enum { bank40_mask = 0x40 }; - enum { bank_size = 32 }; - - int agb_mask; // 0xFF if AGB features enabled, 0 otherwise - BOOST::uint8_t* wave_ram; // 32 bytes (64 nybbles), stored in APU - - friend class Gb_Apu; - - // Frequency timer period - int period() const { return (2048 - frequency()) * (2 * clk_mul); } - - // Non-zero if DAC is enabled - int dac_enabled() const { return regs [0] & 0x80; } - - void corrupt_wave(); - - BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; } - - // Wave index that would be accessed, or -1 if no access would occur - int access( unsigned addr ) const; -}; - -inline int Gb_Wave::read( unsigned addr ) const -{ - int index = access( addr ); - return (index < 0 ? 0xFF : wave_bank() [index]); -} - -inline void Gb_Wave::write( unsigned addr, int data ) -{ - int index = access( addr ); - if ( index >= 0 ) - wave_bank() [index] = data;; -} - -#endif diff --git a/src/dmg/gb_apu/Multi_Buffer.cpp b/src/dmg/gb_apu/Multi_Buffer.cpp deleted file mode 100644 index 0923766a..00000000 --- a/src/dmg/gb_apu/Multi_Buffer.cpp +++ /dev/null @@ -1,281 +0,0 @@ -// Blip_Buffer 0.4.1. http://www.slack.net/~ant/ - -#include "Multi_Buffer.h" - -/* Copyright (C) 2003-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module 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 Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf ) -{ - length_ = 0; - sample_rate_ = 0; - channels_changed_count_ = 1; - channel_types_ = 0; - channel_count_ = 0; - immediate_removal_ = true; -} - -Multi_Buffer::channel_t Multi_Buffer::channel( int /*index*/ ) -{ - static channel_t const ch = { 0, 0, 0 }; - return ch; -} - -// Silent_Buffer - -Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse -{ - // TODO: better to use empty Blip_Buffer so caller never has to check for NULL? - chan.left = 0; - chan.center = 0; - chan.right = 0; -} - -// Mono_Buffer - -Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 ) -{ - chan.center = &buf; - chan.left = &buf; - chan.right = &buf; -} - -Mono_Buffer::~Mono_Buffer() { } - -blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec ) -{ - RETURN_ERR( buf.set_sample_rate( rate, msec ) ); - return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() ); -} - - -// Tracked_Blip_Buffer - -Tracked_Blip_Buffer::Tracked_Blip_Buffer() -{ - last_non_silence = 0; -} - -void Tracked_Blip_Buffer::clear() -{ - last_non_silence = 0; - Blip_Buffer::clear(); -} - -void Tracked_Blip_Buffer::end_frame( blip_time_t t ) -{ - Blip_Buffer::end_frame( t ); - if ( clear_modified() ) - last_non_silence = samples_avail() + blip_buffer_extra_; -} - -blip_ulong Tracked_Blip_Buffer::non_silent() const -{ - return last_non_silence | unsettled(); -} - -inline void Tracked_Blip_Buffer::remove_( long n ) -{ - if ( (last_non_silence -= n) < 0 ) - last_non_silence = 0; -} - -void Tracked_Blip_Buffer::remove_silence( long n ) -{ - remove_( n ); - Blip_Buffer::remove_silence( n ); -} - -void Tracked_Blip_Buffer::remove_samples( long n ) -{ - remove_( n ); - Blip_Buffer::remove_samples( n ); -} - -void Tracked_Blip_Buffer::remove_all_samples() -{ - long avail = samples_avail(); - if ( !non_silent() ) - remove_silence( avail ); - else - remove_samples( avail ); -} - -long Tracked_Blip_Buffer::read_samples( blip_sample_t* out, long count ) -{ - count = Blip_Buffer::read_samples( out, count ); - remove_( count ); - return count; -} - -// Stereo_Buffer - -int const stereo = 2; - -Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 ) -{ - chan.center = mixer.bufs [2] = &bufs [2]; - chan.left = mixer.bufs [0] = &bufs [0]; - chan.right = mixer.bufs [1] = &bufs [1]; - mixer.samples_read = 0; -} - -Stereo_Buffer::~Stereo_Buffer() { } - -blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec ) -{ - mixer.samples_read = 0; - for ( int i = bufs_size; --i >= 0; ) - RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) ); - return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() ); -} - -void Stereo_Buffer::clock_rate( long rate ) -{ - for ( int i = bufs_size; --i >= 0; ) - bufs [i].clock_rate( rate ); -} - -void Stereo_Buffer::bass_freq( int bass ) -{ - for ( int i = bufs_size; --i >= 0; ) - bufs [i].bass_freq( bass ); -} - -void Stereo_Buffer::clear() -{ - mixer.samples_read = 0; - for ( int i = bufs_size; --i >= 0; ) - bufs [i].clear(); -} - -void Stereo_Buffer::end_frame( blip_time_t time ) -{ - for ( int i = bufs_size; --i >= 0; ) - bufs [i].end_frame( time ); -} - -long Stereo_Buffer::read_samples( blip_sample_t* out, long out_size ) -{ - require( (out_size & 1) == 0 ); // must read an even number of samples - out_size = min( out_size, samples_avail() ); - - int pair_count = int (out_size >> 1); - if ( pair_count ) - { - mixer.read_pairs( out, pair_count ); - - if ( samples_avail() <= 0 || immediate_removal() ) - { - for ( int i = bufs_size; --i >= 0; ) - { - buf_t& b = bufs [i]; - // TODO: might miss non-silence settling since it checks END of last read - if ( !b.non_silent() ) - b.remove_silence( mixer.samples_read ); - else - b.remove_samples( mixer.samples_read ); - } - mixer.samples_read = 0; - } - } - return out_size; -} - - -// Stereo_Mixer - -// mixers use a single index value to improve performance on register-challenged processors -// offset goes from negative to zero - -void Stereo_Mixer::read_pairs( blip_sample_t* out, int count ) -{ - // TODO: if caller never marks buffers as modified, uses mono - // except that buffer isn't cleared, so caller can encounter - // subtle problems and not realize the cause. - samples_read += count; - if ( bufs [0]->non_silent() | bufs [1]->non_silent() ) - mix_stereo( out, count ); - else - mix_mono( out, count ); -} - -void Stereo_Mixer::mix_mono( blip_sample_t* out_, int count ) -{ - int const bass = BLIP_READER_BASS( *bufs [2] ); - BLIP_READER_BEGIN( center, *bufs [2] ); - BLIP_READER_ADJ_( center, samples_read ); - - typedef blip_sample_t stereo_blip_sample_t [stereo]; - stereo_blip_sample_t* BLIP_RESTRICT out = (stereo_blip_sample_t*) out_ + count; - int offset = -count; - do - { - blargg_long s = BLIP_READER_READ( center ); - BLIP_READER_NEXT_IDX_( center, bass, offset ); - BLIP_CLAMP( s, s ); - - out [offset] [0] = (blip_sample_t) s; - out [offset] [1] = (blip_sample_t) s; - } - while ( ++offset ); - - BLIP_READER_END( center, *bufs [2] ); -} - -void Stereo_Mixer::mix_stereo( blip_sample_t* out_, int count ) -{ - blip_sample_t* BLIP_RESTRICT out = out_ + count * stereo; - - // do left + center and right + center separately to reduce register load - Tracked_Blip_Buffer* const* buf = &bufs [2]; - while ( true ) // loop runs twice - { - --buf; - --out; - - int const bass = BLIP_READER_BASS( *bufs [2] ); - BLIP_READER_BEGIN( side, **buf ); - BLIP_READER_BEGIN( center, *bufs [2] ); - - BLIP_READER_ADJ_( side, samples_read ); - BLIP_READER_ADJ_( center, samples_read ); - - int offset = -count; - do - { - blargg_long s = BLIP_READER_READ_RAW( center ) + BLIP_READER_READ_RAW( side ); - s >>= blip_sample_bits - 16; - BLIP_READER_NEXT_IDX_( side, bass, offset ); - BLIP_READER_NEXT_IDX_( center, bass, offset ); - BLIP_CLAMP( s, s ); - - ++offset; // before write since out is decremented to slightly before end - out [offset * stereo] = (blip_sample_t) s; - } - while ( offset ); - - BLIP_READER_END( side, **buf ); - - if ( buf != bufs ) - continue; - - // only end center once - BLIP_READER_END( center, *bufs [2] ); - break; - } -} diff --git a/src/dmg/gb_apu/Multi_Buffer.h b/src/dmg/gb_apu/Multi_Buffer.h deleted file mode 100644 index d22075d0..00000000 --- a/src/dmg/gb_apu/Multi_Buffer.h +++ /dev/null @@ -1,205 +0,0 @@ -// Multi-channel sound buffer interface, and basic mono and stereo buffers - -// Blip_Buffer 0.4.1 -#ifndef MULTI_BUFFER_H -#define MULTI_BUFFER_H - -#include "blargg_common.h" -#include "Blip_Buffer.h" - -// Interface to one or more Blip_Buffers mapped to one or more channels -// consisting of left, center, and right buffers. -class Multi_Buffer { -public: - Multi_Buffer( int samples_per_frame ); - virtual ~Multi_Buffer() { } - - // Sets the number of channels available and optionally their types - // (type information used by Effects_Buffer) - enum { type_index_mask = 0xFF }; - enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type }; - virtual blargg_err_t set_channel_count( int, int const* types = 0 ); - int channel_count() const { return channel_count_; } - - // Gets indexed channel, from 0 to channel count - 1 - struct channel_t { - Blip_Buffer* center; - Blip_Buffer* left; - Blip_Buffer* right; - }; - virtual channel_t channel( int index ) BLARGG_PURE( ; ) - - // See Blip_Buffer.h - virtual blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ) BLARGG_PURE( ; ) - virtual void clock_rate( long ) BLARGG_PURE( { } ) - virtual void bass_freq( int ) BLARGG_PURE( { } ) - virtual void clear() BLARGG_PURE( { } ) - long sample_rate() const; - - // Length of buffer, in milliseconds - int length() const; - - // See Blip_Buffer.h - virtual void end_frame( blip_time_t ) BLARGG_PURE( { } ) - - // Number of samples per output frame (1 = mono, 2 = stereo) - int samples_per_frame() const; - - // Count of changes to channel configuration. Incremented whenever - // a change is made to any of the Blip_Buffers for any channel. - unsigned channels_changed_count() { return channels_changed_count_; } - - // See Blip_Buffer.h - virtual long read_samples( blip_sample_t*, long ) BLARGG_PURE( { return 0; } ) - virtual long samples_avail() const BLARGG_PURE( { return 0; } ) - -public: - BLARGG_DISABLE_NOTHROW - void disable_immediate_removal() { immediate_removal_ = false; } -protected: - bool immediate_removal() const { return immediate_removal_; } - int const* channel_types() const { return channel_types_; } - void channels_changed() { channels_changed_count_++; } -private: - // noncopyable - Multi_Buffer( const Multi_Buffer& ); - Multi_Buffer& operator = ( const Multi_Buffer& ); - - unsigned channels_changed_count_; - long sample_rate_; - int length_; - int channel_count_; - int const samples_per_frame_; - int const* channel_types_; - bool immediate_removal_; -}; - -// Uses a single buffer and outputs mono samples. -class Mono_Buffer : public Multi_Buffer { - Blip_Buffer buf; - channel_t chan; -public: - // Buffer used for all channels - Blip_Buffer* center() { return &buf; } - -public: - Mono_Buffer(); - ~Mono_Buffer(); - blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ); - void clock_rate( long rate ) { buf.clock_rate( rate ); } - void bass_freq( int freq ) { buf.bass_freq( freq ); } - void clear() { buf.clear(); } - long samples_avail() const { return buf.samples_avail(); } - long read_samples( blip_sample_t* p, long s ) { return buf.read_samples( p, s ); } - channel_t channel( int ) { return chan; } - void end_frame( blip_time_t t ) { buf.end_frame( t ); } -}; - - class Tracked_Blip_Buffer : public Blip_Buffer { - public: - // Non-zero if buffer still has non-silent samples in it. Requires that you call - // set_modified() appropriately. - blip_ulong non_silent() const; - - // remove_samples( samples_avail() ) - void remove_all_samples(); - - public: - BLARGG_DISABLE_NOTHROW - - long read_samples( blip_sample_t*, long ); - void remove_silence( long ); - void remove_samples( long ); - Tracked_Blip_Buffer(); - void clear(); - void end_frame( blip_time_t ); - private: - blip_long last_non_silence; - void remove_( long ); - }; - - class Stereo_Mixer { - public: - Tracked_Blip_Buffer* bufs [3]; - blargg_long samples_read; - - Stereo_Mixer() : samples_read( 0 ) { } - void read_pairs( blip_sample_t* out, int count ); - private: - void mix_mono ( blip_sample_t* out, int pair_count ); - void mix_stereo( blip_sample_t* out, int pair_count ); - }; - -// Uses three buffers (one for center) and outputs stereo sample pairs. -class Stereo_Buffer : public Multi_Buffer { -public: - - // Buffers used for all channels - Blip_Buffer* center() { return &bufs [2]; } - Blip_Buffer* left() { return &bufs [0]; } - Blip_Buffer* right() { return &bufs [1]; } - -public: - Stereo_Buffer(); - ~Stereo_Buffer(); - blargg_err_t set_sample_rate( long, int msec = blip_default_length ); - void clock_rate( long ); - void bass_freq( int ); - void clear(); - channel_t channel( int ) { return chan; } - void end_frame( blip_time_t ); - - long samples_avail() const { return (bufs [0].samples_avail() - mixer.samples_read) * 2; } - long read_samples( blip_sample_t*, long ); - -private: - enum { bufs_size = 3 }; - typedef Tracked_Blip_Buffer buf_t; - buf_t bufs [bufs_size]; - Stereo_Mixer mixer; - channel_t chan; - long samples_avail_; -}; - -// Silent_Buffer generates no samples, useful where no sound is wanted -class Silent_Buffer : public Multi_Buffer { - channel_t chan; -public: - Silent_Buffer(); - blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ); - void clock_rate( long ) { } - void bass_freq( int ) { } - void clear() { } - channel_t channel( int ) { return chan; } - void end_frame( blip_time_t ) { } - long samples_avail() const { return 0; } - long read_samples( blip_sample_t*, long ) { return 0; } -}; - - -inline blargg_err_t Multi_Buffer::set_sample_rate( long rate, int msec ) -{ - sample_rate_ = rate; - length_ = msec; - return 0; -} - -inline blargg_err_t Silent_Buffer::set_sample_rate( long rate, int msec ) -{ - return Multi_Buffer::set_sample_rate( rate, msec ); -} - -inline int Multi_Buffer::samples_per_frame() const { return samples_per_frame_; } - -inline long Multi_Buffer::sample_rate() const { return sample_rate_; } - -inline int Multi_Buffer::length() const { return length_; } - -inline blargg_err_t Multi_Buffer::set_channel_count( int n, int const* types ) -{ - channel_count_ = n; - channel_types_ = types; - return 0; -} - -#endif diff --git a/src/dmg/gb_apu/blargg_common.h b/src/dmg/gb_apu/blargg_common.h deleted file mode 100644 index 1203d387..00000000 --- a/src/dmg/gb_apu/blargg_common.h +++ /dev/null @@ -1,206 +0,0 @@ -// Sets up common environment for Shay Green's libraries. -// To change configuration options, modify blargg_config.h, not this file. - -// Gb_Snd_Emu 0.2.0 -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -#include -#include -#include -#include - -#undef BLARGG_COMMON_H -// allow blargg_config.h to #include blargg_common.h -#include "blargg_config.h" -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -// BLARGG_RESTRICT: equivalent to restrict, where supported -#if __GNUC__ >= 3 || _MSC_VER >= 1100 - #define BLARGG_RESTRICT __restrict -#else - #define BLARGG_RESTRICT -#endif - -// STATIC_CAST(T,expr): Used in place of static_cast (expr) -// CONST_CAST( T,expr): Used in place of const_cast (expr) -#ifndef STATIC_CAST - #if __GNUC__ >= 4 - #define STATIC_CAST(T,expr) static_cast (expr) - #define CONST_CAST( T,expr) const_cast (expr) - #else - #define STATIC_CAST(T,expr) ((T) (expr)) - #define CONST_CAST( T,expr) ((T) (expr)) - #endif -#endif - -// blargg_err_t (0 on success, otherwise error string) -#ifndef blargg_err_t - typedef const char* blargg_err_t; -#endif - -// blargg_vector - very lightweight vector of POD types (no constructor/destructor) -template -class blargg_vector { - T* begin_; - size_t size_; -public: - blargg_vector() : begin_( 0 ), size_( 0 ) { } - ~blargg_vector() { free( begin_ ); } - size_t size() const { return size_; } - T* begin() const { return begin_; } - T* end() const { return begin_ + size_; } - blargg_err_t resize( size_t n ) - { - // TODO: blargg_common.cpp to hold this as an outline function, ugh - void* p = realloc( begin_, n * sizeof (T) ); - if ( p ) - begin_ = (T*) p; - else if ( n > size_ ) // realloc failure only a problem if expanding - return "Out of memory"; - size_ = n; - return 0; - } - void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } - T& operator [] ( size_t n ) const - { - assert( n <= size_ ); // <= to allow past-the-end value - return begin_ [n]; - } -}; - -#ifndef BLARGG_DISABLE_NOTHROW - // throw spec mandatory in ISO C++ if operator new can return NULL - #if __cplusplus >= 199711 || __GNUC__ >= 3 - #define BLARGG_THROWS( spec ) throw spec - #else - #define BLARGG_THROWS( spec ) - #endif - #define BLARGG_DISABLE_NOTHROW \ - void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ - void operator delete ( void* p ) { free( p ); } - #define BLARGG_NEW new -#else - #include - #define BLARGG_NEW new (std::nothrow) -#endif - -// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) -#define BLARGG_4CHAR( a, b, c, d ) \ - ((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF)) - -// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. -#ifndef BOOST_STATIC_ASSERT - #ifdef _MSC_VER - // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) - #else - // Some other compilers fail when declaring same function multiple times in class, - // so differentiate them by line - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) - #endif -#endif - -// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, -// compiler is assumed to support bool. If undefined, availability is determined. -#ifndef BLARGG_COMPILER_HAS_BOOL - #if defined (__MWERKS__) - #if !__option(bool) - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (_MSC_VER) - #if _MSC_VER < 1100 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (__GNUC__) - // supports bool - #elif __cplusplus < 199711 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif -#endif -#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL - // If you get errors here, modify your blargg_config.h file - typedef int bool; - const bool true = 1; - const bool false = 0; -#endif - -// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough - -#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF - typedef long blargg_long; -#else - typedef int blargg_long; -#endif - -#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF - typedef unsigned long blargg_ulong; -#else - typedef unsigned blargg_ulong; -#endif - -// BOOST::int8_t etc. - -// HAVE_STDINT_H: If defined, use for int8_t etc. -#if defined (HAVE_STDINT_H) - #include - #define BOOST - -// HAVE_INTTYPES_H: If defined, use for int8_t etc. -#elif defined (HAVE_INTTYPES_H) - #include - #define BOOST - -#else - struct BOOST - { - #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F - typedef signed char int8_t; - typedef unsigned char uint8_t; - #else - // No suitable 8-bit type available - typedef struct see_blargg_common_h int8_t; - typedef struct see_blargg_common_h uint8_t; - #endif - - #if USHRT_MAX == 0xFFFF - typedef short int16_t; - typedef unsigned short uint16_t; - #else - // No suitable 16-bit type available - typedef struct see_blargg_common_h int16_t; - typedef struct see_blargg_common_h uint16_t; - #endif - - #if ULONG_MAX == 0xFFFFFFFF - typedef long int32_t; - typedef unsigned long uint32_t; - #elif UINT_MAX == 0xFFFFFFFF - typedef int int32_t; - typedef unsigned int uint32_t; - #else - // No suitable 32-bit type available - typedef struct see_blargg_common_h int32_t; - typedef struct see_blargg_common_h uint32_t; - #endif - }; -#endif - -#if __GNUC__ >= 3 - #define BLARGG_DEPRECATED __attribute__ ((deprecated)) -#else - #define BLARGG_DEPRECATED -#endif - -// Use in place of "= 0;" for a pure virtual, since these cause calls to std C++ lib. -// During development, BLARGG_PURE( x ) expands to = 0; -// virtual int func() BLARGG_PURE( { return 0; } ) -#ifndef BLARGG_PURE - #define BLARGG_PURE( def ) def -#endif - -#endif -#endif diff --git a/src/dmg/gb_apu/blargg_config.h b/src/dmg/gb_apu/blargg_config.h deleted file mode 100644 index 961e0453..00000000 --- a/src/dmg/gb_apu/blargg_config.h +++ /dev/null @@ -1,33 +0,0 @@ -// $package user configuration file. Don't replace when updating library. - -#ifndef BLARGG_CONFIG_H -#define BLARGG_CONFIG_H - -// Uncomment to have Gb_Apu run at 4x normal clock rate (16777216 Hz), useful in -// a Game Boy Advance emulator. -#define GB_APU_OVERCLOCK 4 - -#define GB_APU_CUSTOM_STATE 1 - -// Uncomment to enable platform-specific (and possibly non-portable) optimizations. -//#define BLARGG_NONPORTABLE 1 - -// Uncomment if automatic byte-order determination doesn't work -//#define BLARGG_BIG_ENDIAN 1 - -// Uncomment to use zlib for transparent decompression of gzipped files -//#define HAVE_ZLIB_H - -// Uncomment if you get errors in the bool section of blargg_common.h -//#define BLARGG_COMPILER_HAS_BOOL 1 - -// Uncomment to disable out-of-memory exceptions -//#include -//#define BLARGG_NEW new (std::nothrow) - -// Use standard config.h if present -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#endif diff --git a/src/dmg/gb_apu/blargg_source.h b/src/dmg/gb_apu/blargg_source.h deleted file mode 100644 index ddef37d6..00000000 --- a/src/dmg/gb_apu/blargg_source.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Included at the beginning of library source files, AFTER all other #include lines. -Sets up helpful macros and services used in my source code. Since this is only "active" -in my source code, I don't have to worry about polluting the global namespace with -unprefixed names. */ - -// Gb_Snd_Emu 0.2.0 -#ifndef BLARGG_SOURCE_H -#define BLARGG_SOURCE_H - -// The following four macros are for debugging only. Some or all might be defined -// to do nothing, depending on the circumstances. Described is what happens when -// a particular macro is defined to do something. When defined to do nothing, the -// macros do NOT evaluate their argument(s). - -// If expr is false, prints file and line number, then aborts program. Meant for -// checking internal state and consistency. A failed assertion indicates a bug -// in MY code. -// -// void assert( bool expr ); -#include - -// If expr is false, prints file and line number, then aborts program. Meant for -// checking caller-supplied parameters and operations that are outside the control -// of the module. A failed requirement probably indicates a bug in YOUR code. -// -// void require( bool expr ); -#undef require -#define require( expr ) assert( expr ) - -// Like printf() except output goes to debugging console/file. -// -// void dprintf( const char* format, ... ); -static inline void blargg_dprintf_( const char*, ... ) { } -#undef dprintf -#define dprintf (1) ? (void) 0 : blargg_dprintf_ - -// If expr is false, prints file and line number to debug console/log, then -// continues execution normally. Meant for flagging potential problems or things -// that should be looked into, but that aren't serious problems. -// -// void check( bool expr ); -#undef check -#define check( expr ) ((void) 0) - -// If expr yields non-NULL error string, returns it from current function, -// otherwise continues normally. -#undef RETURN_ERR -#define RETURN_ERR( expr ) do { \ - blargg_err_t blargg_return_err_ = (expr); \ - if ( blargg_return_err_ ) return blargg_return_err_; \ - } while ( 0 ) - -// If ptr is NULL, returns "Out of memory" error string, otherwise continues normally. -#undef CHECK_ALLOC -#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) - -// The usual min/max functions for built-in types. -// -// template T min( T x, T y ) { return x < y ? x : y; } -// template T max( T x, T y ) { return x > y ? x : y; } -#define BLARGG_DEF_MIN_MAX( type ) \ - static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\ - static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; } - -BLARGG_DEF_MIN_MAX( int ) -BLARGG_DEF_MIN_MAX( unsigned ) -BLARGG_DEF_MIN_MAX( long ) -BLARGG_DEF_MIN_MAX( unsigned long ) -BLARGG_DEF_MIN_MAX( float ) -BLARGG_DEF_MIN_MAX( double ) - -#undef min -#define min blargg_min - -#undef max -#define max blargg_max - -// typedef unsigned char byte; -typedef unsigned char blargg_byte; -#undef byte -#define byte blargg_byte - -// deprecated -#define BLARGG_CHECK_ALLOC CHECK_ALLOC -#define BLARGG_RETURN_ERR RETURN_ERR - -// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check -#ifdef BLARGG_SOURCE_BEGIN - #include BLARGG_SOURCE_BEGIN -#endif - -#endif