Remove ARMMemory and ARMBoard shims

This commit is contained in:
Jeffrey Pfau 2014-04-19 18:14:17 -07:00
parent 775e417cc6
commit c0eb7c81f7
22 changed files with 541 additions and 551 deletions

View File

@ -36,7 +36,7 @@ if(BUILD_BBB OR BUILD_RASPI)
endif()
endif()
set(DEBUGGER_SRC "${CMAKE_SOURCE_DIR}/src/debugger/debugger.c;${CMAKE_SOURCE_DIR}/src/debugger/memory-debugger.c")
set(DEBUGGER_SRC "${CMAKE_SOURCE_DIR}/src/debugger/debugger.c")
if(USE_CLI_DEBUGGER)
set(DEBUGGER_SRC "${DEBUGGER_SRC};${CMAKE_SOURCE_DIR}/src/debugger/cli-debugger.c")

View File

@ -65,17 +65,7 @@ static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode mode) {
}
void ARMInit(struct ARMCore* cpu) {
cpu->memory = 0;
cpu->board = 0;
}
void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory) {
cpu->memory = memory;
}
void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board) {
cpu->board = board;
board->cpu = cpu;
// TODO: Remove
}
void ARMReset(struct ARMCore* cpu) {
@ -111,7 +101,7 @@ void ARMReset(struct ARMCore* cpu) {
cpu->cycles = 0;
cpu->nextEvent = 0;
cpu->board->reset(cpu->board);
cpu->board.reset(cpu);
}
void ARMRaiseIRQ(struct ARMCore* cpu) {
@ -129,7 +119,7 @@ void ARMRaiseIRQ(struct ARMCore* cpu) {
cpu->cpsr.priv = MODE_IRQ;
cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth + WORD_SIZE_ARM;
cpu->gprs[ARM_PC] = BASE_IRQ + WORD_SIZE_ARM;
cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC]);
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]);
_ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr;
cpu->cpsr.i = 1;
@ -147,7 +137,7 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
cpu->cpsr.priv = MODE_SUPERVISOR;
cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth;
cpu->gprs[ARM_PC] = BASE_SWI + WORD_SIZE_ARM;
cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC]);
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]);
_ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr;
cpu->cpsr.i = 1;
@ -156,7 +146,7 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
static inline void ARMStep(struct ARMCore* cpu) {
uint32_t opcode;
cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_ARM;
LOAD_32(opcode, cpu->currentPC & cpu->memory->activeMask, cpu->memory->activeRegion);
LOAD_32(opcode, cpu->currentPC & cpu->memory.activeMask, cpu->memory.activeRegion);
cpu->gprs[ARM_PC] += WORD_SIZE_ARM;
int condition = opcode >> 28;
@ -262,7 +252,7 @@ static inline void ThumbStep(struct ARMCore* cpu) {
cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_THUMB;
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
uint16_t opcode;
LOAD_16(opcode, cpu->currentPC & cpu->memory->activeMask, cpu->memory->activeRegion);
LOAD_16(opcode, cpu->currentPC & cpu->memory.activeMask, cpu->memory.activeRegion);
ThumbInstruction instruction = _thumbTable[opcode >> 6];
instruction(cpu, opcode);
}
@ -274,6 +264,6 @@ void ARMRun(struct ARMCore* cpu) {
ARMStep(cpu);
}
if (cpu->cycles >= cpu->nextEvent) {
cpu->board->processEvents(cpu->board);
cpu->board.processEvents(cpu);
}
}

View File

@ -79,15 +79,15 @@ union PSR {
};
struct ARMMemory {
int32_t (*load32)(struct ARMMemory*, uint32_t address, int* cycleCounter);
int16_t (*load16)(struct ARMMemory*, uint32_t address, int* cycleCounter);
uint16_t (*loadU16)(struct ARMMemory*, uint32_t address, int* cycleCounter);
int8_t (*load8)(struct ARMMemory*, uint32_t address, int* cycleCounter);
uint8_t (*loadU8)(struct ARMMemory*, uint32_t address, int* cycleCounter);
int32_t (*load32)(struct ARMCore*, uint32_t address, int* cycleCounter);
int16_t (*load16)(struct ARMCore*, uint32_t address, int* cycleCounter);
uint16_t (*loadU16)(struct ARMCore*, uint32_t address, int* cycleCounter);
int8_t (*load8)(struct ARMCore*, uint32_t address, int* cycleCounter);
uint8_t (*loadU8)(struct ARMCore*, uint32_t address, int* cycleCounter);
void (*store32)(struct ARMMemory*, uint32_t address, int32_t value, int* cycleCounter);
void (*store16)(struct ARMMemory*, uint32_t address, int16_t value, int* cycleCounter);
void (*store8)(struct ARMMemory*, uint32_t address, int8_t value, int* cycleCounter);
void (*store32)(struct ARMCore*, uint32_t address, int32_t value, int* cycleCounter);
void (*store16)(struct ARMCore*, uint32_t address, int16_t value, int* cycleCounter);
void (*store8)(struct ARMCore*, uint32_t address, int8_t value, int* cycleCounter);
uint32_t* activeRegion;
uint32_t activeMask;
@ -95,20 +95,19 @@ struct ARMMemory {
uint32_t activePrefetchCycles16;
uint32_t activeNonseqCycles32;
uint32_t activeNonseqCycles16;
void (*setActiveRegion)(struct ARMMemory*, uint32_t address);
int (*waitMultiple)(struct ARMMemory*, uint32_t startAddress, int count);
void (*setActiveRegion)(struct ARMCore*, uint32_t address);
int (*waitMultiple)(struct ARMCore*, uint32_t startAddress, int count);
};
struct ARMBoard {
struct ARMCore* cpu;
void (*reset)(struct ARMBoard* board);
void (*processEvents)(struct ARMBoard* board);
void (*swi16)(struct ARMBoard* board, int immediate);
void (*swi32)(struct ARMBoard* board, int immediate);
void (*hitIllegal)(struct ARMBoard* board, uint32_t opcode);
void (*readCPSR)(struct ARMBoard* board);
void (*reset)(struct ARMCore* board);
void (*processEvents)(struct ARMCore* board);
void (*swi16)(struct ARMCore* board, int immediate);
void (*swi32)(struct ARMCore* board, int immediate);
void (*hitIllegal)(struct ARMCore* board, uint32_t opcode);
void (*readCPSR)(struct ARMCore* board);
void (*hitStub)(struct ARMBoard* board, uint32_t opcode);
void (*hitStub)(struct ARMCore* board, uint32_t opcode);
};
struct ARMCore {
@ -130,8 +129,8 @@ struct ARMCore {
enum ExecutionMode executionMode;
enum PrivilegeMode privilegeMode;
struct ARMMemory* memory;
struct ARMBoard* board;
struct ARMMemory memory;
struct ARMBoard board;
int64_t absoluteCycles;
int32_t lastCycles;

View File

@ -249,7 +249,7 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
#define ARM_STORE_POST_BODY \
currentCycles -= ARM_PREFETCH_CYCLES; \
currentCycles += 1 + cpu->memory->activeNonseqCycles32;
currentCycles += 1 + cpu->memory.activeNonseqCycles32;
#define DEFINE_INSTRUCTION_ARM(NAME, BODY) \
static void _ARMInstruction ## NAME (struct ARMCore* cpu, uint32_t opcode) { \
@ -424,7 +424,7 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
S_PRE; \
LOOP(BODY); \
S_POST; \
currentCycles += cpu->memory->waitMultiple(cpu->memory, addr, total); \
currentCycles += cpu->memory.waitMultiple(cpu, addr, total); \
POST_BODY; \
WRITEBACK;)
@ -543,68 +543,68 @@ DEFINE_MULTIPLY_INSTRUCTION_ARM(UMULL,
// Begin load/store definitions
DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDR, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRB, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRH, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(STR, cpu->memory->store32(cpu->memory, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRB, cpu->memory->store8(cpu->memory, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(STRH, cpu->memory->store16(cpu->memory, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDR, cpu->gprs[rd] = cpu->memory.load32(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRB, cpu->gprs[rd] = cpu->memory.loadU8(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRH, cpu->gprs[rd] = cpu->memory.loadU16(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSB, cpu->gprs[rd] = cpu->memory.load8(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSH, cpu->gprs[rd] = cpu->memory.load16(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(STR, cpu->memory.store32(cpu, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRB, cpu->memory.store8(cpu, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(STRH, cpu->memory.store16(cpu, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(LDRBT,
enum PrivilegeMode priv = cpu->privilegeMode;
ARMSetPrivilegeMode(cpu, MODE_USER);
cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address, &currentCycles);
cpu->gprs[rd] = cpu->memory.loadU8(cpu, address, &currentCycles);
ARMSetPrivilegeMode(cpu, priv);
ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(LDRT,
enum PrivilegeMode priv = cpu->privilegeMode;
ARMSetPrivilegeMode(cpu, MODE_USER);
cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address, &currentCycles);
cpu->gprs[rd] = cpu->memory.load32(cpu, address, &currentCycles);
ARMSetPrivilegeMode(cpu, priv);
ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(STRBT,
enum PrivilegeMode priv = cpu->privilegeMode;
ARMSetPrivilegeMode(cpu, MODE_USER);
cpu->memory->store32(cpu->memory, address, cpu->gprs[rd], &currentCycles);
cpu->memory.store32(cpu, address, cpu->gprs[rd], &currentCycles);
ARMSetPrivilegeMode(cpu, priv);
ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(STRT,
enum PrivilegeMode priv = cpu->privilegeMode;
ARMSetPrivilegeMode(cpu, MODE_USER);
cpu->memory->store8(cpu->memory, address, cpu->gprs[rd], &currentCycles);
cpu->memory.store8(cpu, address, cpu->gprs[rd], &currentCycles);
ARMSetPrivilegeMode(cpu, priv);
ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM,
cpu->gprs[i] = cpu->memory->load32(cpu->memory, addr & 0xFFFFFFFC, 0);,
cpu->gprs[i] = cpu->memory.load32(cpu, addr & 0xFFFFFFFC, 0);,
++currentCycles;
if (rs & 0x8000) {
ARM_WRITE_PC;
})
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM,
cpu->memory->store32(cpu->memory, addr, cpu->gprs[i], 0);,
currentCycles += cpu->memory->activeNonseqCycles32 - cpu->memory->activePrefetchCycles32)
cpu->memory.store32(cpu, addr, cpu->gprs[i], 0);,
currentCycles += cpu->memory.activeNonseqCycles32 - cpu->memory.activePrefetchCycles32)
DEFINE_INSTRUCTION_ARM(SWP,
int rm = opcode & 0xF;
int rd = (opcode >> 12) & 0xF;
int rn = (opcode >> 16) & 0xF;
int32_t d = cpu->memory->load32(cpu->memory, cpu->gprs[rn], &currentCycles);
cpu->memory->store32(cpu->memory, cpu->gprs[rn], cpu->gprs[rm], &currentCycles);
int32_t d = cpu->memory.load32(cpu, cpu->gprs[rn], &currentCycles);
cpu->memory.store32(cpu, cpu->gprs[rn], cpu->gprs[rm], &currentCycles);
cpu->gprs[rd] = d;)
DEFINE_INSTRUCTION_ARM(SWPB,
int rm = opcode & 0xF;
int rd = (opcode >> 12) & 0xF;
int rn = (opcode >> 16) & 0xF;
int32_t d = cpu->memory->loadU8(cpu->memory, cpu->gprs[rn], &currentCycles);
cpu->memory->store8(cpu->memory, cpu->gprs[rn], cpu->gprs[rm], &currentCycles);
int32_t d = cpu->memory.loadU8(cpu, cpu->gprs[rn], &currentCycles);
cpu->memory.store8(cpu, cpu->gprs[rn], cpu->gprs[rm], &currentCycles);
cpu->gprs[rd] = d;)
// End load/store definitions
@ -702,7 +702,7 @@ DEFINE_INSTRUCTION_ARM(MSRRI,
mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK;
cpu->spsr.packed = (cpu->spsr.packed & ~mask) | (operand & mask);)
DEFINE_INSTRUCTION_ARM(SWI, cpu->board->swi32(cpu->board, opcode & 0xFFFFFF))
DEFINE_INSTRUCTION_ARM(SWI, cpu->board.swi32(cpu, opcode & 0xFFFFFF))
#define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \
EMITTER ## NAME

View File

@ -3,7 +3,7 @@
#include "common.h"
#define ARM_PREFETCH_CYCLES (1 + cpu->memory->activePrefetchCycles32)
#define ARM_PREFETCH_CYCLES (1 + cpu->memory.activePrefetchCycles32)
struct ARMCore;

View File

@ -65,18 +65,18 @@
cpu->cycles += 4; \
}
#define ARM_STUB cpu->board->hitStub(cpu->board, opcode)
#define ARM_ILL cpu->board->hitIllegal(cpu->board, opcode)
#define ARM_STUB cpu->board.hitStub(cpu, opcode)
#define ARM_ILL cpu->board.hitIllegal(cpu, opcode)
#define ARM_WRITE_PC \
cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM; \
cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC] - WORD_SIZE_ARM); \
currentCycles += 2 + cpu->memory->activeNonseqCycles32 + cpu->memory->activePrefetchCycles32;
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC] - WORD_SIZE_ARM); \
currentCycles += 2 + cpu->memory.activeNonseqCycles32 + cpu->memory.activePrefetchCycles32;
#define THUMB_WRITE_PC \
cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB) + WORD_SIZE_THUMB; \
cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC] - WORD_SIZE_THUMB); \
currentCycles += 2 + cpu->memory->activeNonseqCycles16 + cpu->memory->activePrefetchCycles16;
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC] - WORD_SIZE_THUMB); \
currentCycles += 2 + cpu->memory.activeNonseqCycles16 + cpu->memory.activePrefetchCycles16;
static inline int _ARMModeHasSPSR(enum PrivilegeMode mode) {
return mode != MODE_SYSTEM && mode != MODE_USER;
@ -100,7 +100,7 @@ static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode execution
static inline void _ARMReadCPSR(struct ARMCore* cpu) {
_ARMSetMode(cpu, cpu->cpsr.t);
ARMSetPrivilegeMode(cpu, cpu->cpsr.priv);
cpu->board->readCPSR(cpu->board);
cpu->board.readCPSR(cpu);
}
#endif

View File

@ -33,10 +33,10 @@
D = M - N; \
THUMB_SUBTRACTION_S(m, n, D)
#define THUMB_PREFETCH_CYCLES (1 + cpu->memory->activePrefetchCycles16)
#define THUMB_PREFETCH_CYCLES (1 + cpu->memory.activePrefetchCycles16)
#define THUMB_STORE_POST_BODY \
currentCycles += cpu->memory->activeNonseqCycles16 - cpu->memory->activePrefetchCycles16;
currentCycles += cpu->memory.activeNonseqCycles16 - cpu->memory.activePrefetchCycles16;
#define APPLY(F, ...) F(__VA_ARGS__)
@ -136,12 +136,12 @@ DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(ASR1,
}
THUMB_NEUTRAL_S( , , cpu->gprs[rd]);)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDR1, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[rm] + immediate * 4, &currentCycles))
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRB1, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, cpu->gprs[rm] + immediate, &currentCycles))
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRH1, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, cpu->gprs[rm] + immediate * 2, &currentCycles))
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STR1, cpu->memory->store32(cpu->memory, cpu->gprs[rm] + immediate * 4, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRB1, cpu->memory->store8(cpu->memory, cpu->gprs[rm] + immediate, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRH1, cpu->memory->store16(cpu->memory, cpu->gprs[rm] + immediate * 2, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDR1, cpu->gprs[rd] = cpu->memory.load32(cpu, cpu->gprs[rm] + immediate * 4, &currentCycles))
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRB1, cpu->gprs[rd] = cpu->memory.loadU8(cpu, cpu->gprs[rm] + immediate, &currentCycles))
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRH1, cpu->gprs[rd] = cpu->memory.loadU16(cpu, cpu->gprs[rm] + immediate * 2, &currentCycles))
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STR1, cpu->memory.store32(cpu, cpu->gprs[rm] + immediate * 4, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRB1, cpu->memory.store8(cpu, cpu->gprs[rm] + immediate, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRH1, cpu->memory.store16(cpu, cpu->gprs[rm] + immediate * 2, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
#define DEFINE_DATA_FORM_1_INSTRUCTION_EX_THUMB(NAME, RM, BODY) \
DEFINE_INSTRUCTION_THUMB(NAME, \
@ -308,9 +308,9 @@ DEFINE_INSTRUCTION_WITH_HIGH_THUMB(MOV3,
#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, BODY) \
COUNT_3(DEFINE_IMMEDIATE_WITH_REGISTER_EX_THUMB, NAME ## _R, BODY)
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, (cpu->gprs[ARM_PC] & 0xFFFFFFFC) + immediate, &currentCycles))
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[ARM_SP] + immediate, &currentCycles))
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, cpu->memory->store32(cpu->memory, cpu->gprs[ARM_SP] + immediate, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, cpu->gprs[rd] = cpu->memory.load32(cpu, (cpu->gprs[ARM_PC] & 0xFFFFFFFC) + immediate, &currentCycles))
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, cpu->gprs[rd] = cpu->memory.load32(cpu, cpu->gprs[ARM_SP] + immediate, &currentCycles))
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, cpu->memory.store32(cpu, cpu->gprs[ARM_SP] + immediate, cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, cpu->gprs[rd] = (cpu->gprs[ARM_PC] & 0xFFFFFFFC) + immediate)
DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, cpu->gprs[rd] = cpu->gprs[ARM_SP] + immediate)
@ -325,14 +325,14 @@ DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, cpu->gprs[rd] = cpu->gprs[ARM_SP] + i
#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, BODY) \
COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, BODY)
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, cpu->memory->store32(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, cpu->memory->store8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory->store16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, cpu->gprs[rd] = cpu->memory.load32(cpu, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, cpu->gprs[rd] = cpu->memory.loadU8(cpu, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, cpu->gprs[rd] = cpu->memory.loadU16(cpu, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, cpu->gprs[rd] = cpu->memory.load8(cpu, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, cpu->gprs[rd] = cpu->memory.load16(cpu, cpu->gprs[rn] + cpu->gprs[rm], &currentCycles))
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, cpu->memory.store32(cpu, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, cpu->memory.store8(cpu, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory.store16(cpu, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &currentCycles); THUMB_STORE_POST_BODY;)
#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, ADDRESS, LOOP, BODY, OP, PRE_BODY, POST_BODY, WRITEBACK) \
DEFINE_INSTRUCTION_THUMB(NAME, \
@ -352,20 +352,20 @@ DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory->store16(cpu->memory, c
} \
} \
POST_BODY; \
currentCycles += cpu->memory->waitMultiple(cpu->memory, address, total); \
currentCycles += cpu->memory.waitMultiple(cpu, address, total); \
WRITEBACK;)
#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME, BODY, WRITEBACK) \
COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## _R, cpu->gprs[rn], (m = 0x01, i = 0; i < 8; m <<= 1, ++i), BODY, +=, , , WRITEBACK)
DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDMIA,
cpu->gprs[i] = cpu->memory->load32(cpu->memory, address, 0),
cpu->gprs[i] = cpu->memory.load32(cpu, address, 0),
if (!((1 << rn) & rs)) {
cpu->gprs[rn] = address;
})
DEFINE_LOAD_STORE_MULTIPLE_THUMB(STMIA,
cpu->memory->store32(cpu->memory, address, cpu->gprs[i], 0),
cpu->memory.store32(cpu, address, cpu->gprs[i], 0),
THUMB_STORE_POST_BODY;
cpu->gprs[rn] = address;)
@ -399,7 +399,7 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP,
opcode & 0x00FF,
cpu->gprs[ARM_SP],
(m = 0x01, i = 0; i < 8; m <<= 1, ++i),
cpu->gprs[i] = cpu->memory->load32(cpu->memory, address, 0),
cpu->gprs[i] = cpu->memory.load32(cpu, address, 0),
+=,
, ,
cpu->gprs[ARM_SP] = address)
@ -408,10 +408,10 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR,
opcode & 0x00FF,
cpu->gprs[ARM_SP],
(m = 0x01, i = 0; i < 8; m <<= 1, ++i),
cpu->gprs[i] = cpu->memory->load32(cpu->memory, address, 0),
cpu->gprs[i] = cpu->memory.load32(cpu, address, 0),
+=,
,
cpu->gprs[ARM_PC] = cpu->memory->load32(cpu->memory, address, 0) & 0xFFFFFFFE;
cpu->gprs[ARM_PC] = cpu->memory.load32(cpu, address, 0) & 0xFFFFFFFE;
address += 4;,
cpu->gprs[ARM_SP] = address;
THUMB_WRITE_PC;)
@ -420,7 +420,7 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH,
opcode & 0x00FF,
cpu->gprs[ARM_SP] - 4,
(m = 0x80, i = 7; m; m >>= 1, --i),
cpu->memory->store32(cpu->memory, address, cpu->gprs[i], 0),
cpu->memory.store32(cpu, address, cpu->gprs[i], 0),
-=,
,
THUMB_STORE_POST_BODY,
@ -430,9 +430,9 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR,
opcode & 0x00FF,
cpu->gprs[ARM_SP] - 4,
(m = 0x80, i = 7; m; m >>= 1, --i),
cpu->memory->store32(cpu->memory, address, cpu->gprs[i], 0),
cpu->memory.store32(cpu, address, cpu->gprs[i], 0),
-=,
cpu->memory->store32(cpu->memory, address, cpu->gprs[ARM_LR], 0);
cpu->memory.store32(cpu, address, cpu->gprs[ARM_LR], 0);
address -= 4;,
THUMB_STORE_POST_BODY,
cpu->gprs[ARM_SP] = address + 4)
@ -469,7 +469,7 @@ DEFINE_INSTRUCTION_THUMB(BX,
ARM_WRITE_PC;
})
DEFINE_INSTRUCTION_THUMB(SWI, cpu->board->swi16(cpu->board, opcode & 0xFF))
DEFINE_INSTRUCTION_THUMB(SWI, cpu->board.swi16(cpu, opcode & 0xFF))
#define DECLARE_INSTRUCTION_THUMB(EMITTER, NAME) \
EMITTER ## NAME

View File

@ -134,10 +134,10 @@ static void _printHex(struct CLIDebugger* debugger, struct DebugVector* dv) {
static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
// TODO: write a disassembler
if (mode == MODE_ARM) {
uint32_t instruction = debugger->d.cpu->memory->load32(debugger->d.cpu->memory, address, 0);
uint32_t instruction = debugger->d.cpu->memory.load32(debugger->d.cpu, address, 0);
printf("%08X\n", instruction);
} else {
uint16_t instruction = debugger->d.cpu->memory->loadU16(debugger->d.cpu->memory, address, 0);
uint16_t instruction = debugger->d.cpu->memory.loadU16(debugger->d.cpu, address, 0);
printf("%04X\n", instruction);
}
}
@ -174,7 +174,7 @@ static void _readByte(struct CLIDebugger* debugger, struct DebugVector* dv) {
return;
}
uint32_t address = dv->intValue;
uint8_t value = debugger->d.cpu->memory->loadU8(debugger->d.cpu->memory, address, 0);
uint8_t value = debugger->d.cpu->memory.loadU8(debugger->d.cpu, address, 0);
printf(" 0x%02X\n", value);
}
@ -184,7 +184,7 @@ static void _readHalfword(struct CLIDebugger* debugger, struct DebugVector* dv)
return;
}
uint32_t address = dv->intValue;
uint16_t value = debugger->d.cpu->memory->loadU16(debugger->d.cpu->memory, address, 0);
uint16_t value = debugger->d.cpu->memory.loadU16(debugger->d.cpu, address, 0);
printf(" 0x%04X\n", value);
}
@ -194,7 +194,7 @@ static void _readWord(struct CLIDebugger* debugger, struct DebugVector* dv) {
return;
}
uint32_t address = dv->intValue;
uint32_t value = debugger->d.cpu->memory->load32(debugger->d.cpu->memory, address, 0);
uint32_t value = debugger->d.cpu->memory.load32(debugger->d.cpu, address, 0);
printf(" 0x%08X\n", value);
}
@ -221,8 +221,8 @@ static void _setWatchpoint(struct CLIDebugger* debugger, struct DebugVector* dv)
printf("%s\n", ERROR_MISSING_ARGS);
return;
}
uint32_t address = dv->intValue;
ARMDebuggerSetWatchpoint(&debugger->d, address);
// TODO: Redo watchpoints
(void) (debugger);
}
static void _breakIntoDefault(int signal) {

View File

@ -96,9 +96,7 @@ void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address)
}
void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
if (debugger->cpu->memory != &debugger->memoryShim.d) {
ARMDebuggerInstallMemoryShim(debugger);
}
// FIXME: Make watchpoints work again
struct DebugBreakpoint* watchpoint = malloc(sizeof(struct DebugBreakpoint));
watchpoint->address = address;
watchpoint->next = debugger->memoryShim.watchpoints;

View File

@ -18,8 +18,7 @@ struct DebugBreakpoint {
};
struct DebugMemoryShim {
struct ARMMemory d;
struct ARMMemory* original;
struct ARMMemory original;
struct ARMDebugger* p;
struct DebugBreakpoint* watchpoints;

View File

@ -189,10 +189,10 @@ static void _readMemory(struct GDBStub* stub, const char* message) {
_error(stub, GDB_BAD_ARGUMENTS);
return;
}
struct ARMMemory* memory = stub->d.memoryShim.original;
struct ARMCore* cpu = stub->d.cpu;
int writeAddress = 0;
for (i = 0; i < size; ++i, writeAddress += 2) {
uint8_t byte = memory->load8(memory, address + i, 0);
uint8_t byte = cpu->memory.load8(cpu, address + i, 0);
_int2hex8(byte, &stub->outgoing[writeAddress]);
}
stub->outgoing[writeAddress] = 0;

View File

@ -2,6 +2,8 @@
#include "debugger.h"
#include <string.h>
static void ARMDebuggerShim_store32(struct ARMMemory*, uint32_t address, int32_t value, int* cycleCounter);
static void ARMDebuggerShim_store16(struct ARMMemory*, uint32_t address, int16_t value, int* cycleCounter);
static void ARMDebuggerShim_store8(struct ARMMemory*, uint32_t address, int8_t value, int* cycleCounter);

View File

@ -397,7 +397,7 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
dma->nextCount = 4;
dma->nextEvent = 0;
GBAMemoryUpdateDMAs(&audio->p->memory, -cycles);
GBAMemoryUpdateDMAs(audio->p, -cycles);
}
CircleBufferRead8(&channel->fifo, &channel->sample);
}

View File

@ -7,9 +7,9 @@
const uint32_t GBA_BIOS_CHECKSUM = 0xBAAE187F;
const uint32_t GBA_DS_BIOS_CHECKSUM = 0xBAAE1880;
static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest);
static void _unHuffman(struct GBAMemory* memory, uint32_t source, uint32_t* dest);
static void _unRl(struct GBAMemory* memory, uint32_t source, uint8_t* dest);
static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest);
static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest);
static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest);
static void _RegisterRamReset(struct GBA* gba) {
uint32_t registers = gba->cpu.gprs[0];
@ -29,18 +29,18 @@ static void _CpuSet(struct GBA* gba) {
if (wordsize == 4) {
source &= 0xFFFFFFFC;
dest &= 0xFFFFFFFC;
int32_t word = gba->memory.d.load32(&gba->memory.d, source, &gba->cpu.cycles);
int32_t word = gba->cpu.memory.load32(&gba->cpu, source, &gba->cpu.cycles);
for (i = 0; i < count; ++i) {
gba->memory.d.store32(&gba->memory.d, dest + (i << 2), word, &gba->cpu.cycles);
gba->board.d.processEvents(&gba->board.d);
gba->cpu.memory.store32(&gba->cpu, dest + (i << 2), word, &gba->cpu.cycles);
gba->cpu.board.processEvents(&gba->cpu);
}
} else {
source &= 0xFFFFFFFE;
dest &= 0xFFFFFFFE;
uint16_t word = gba->memory.d.load16(&gba->memory.d, source, &gba->cpu.cycles);
uint16_t word = gba->cpu.memory.load16(&gba->cpu, source, &gba->cpu.cycles);
for (i = 0; i < count; ++i) {
gba->memory.d.store16(&gba->memory.d, dest + (i << 1), word, &gba->cpu.cycles);
gba->board.d.processEvents(&gba->board.d);
gba->cpu.memory.store16(&gba->cpu, dest + (i << 1), word, &gba->cpu.cycles);
gba->cpu.board.processEvents(&gba->cpu);
}
}
} else {
@ -48,17 +48,17 @@ static void _CpuSet(struct GBA* gba) {
source &= 0xFFFFFFFC;
dest &= 0xFFFFFFFC;
for (i = 0; i < count; ++i) {
int32_t word = gba->memory.d.load32(&gba->memory.d, source + (i << 2), &gba->cpu.cycles);
gba->memory.d.store32(&gba->memory.d, dest + (i << 2), word, &gba->cpu.cycles);
gba->board.d.processEvents(&gba->board.d);
int32_t word = gba->cpu.memory.load32(&gba->cpu, source + (i << 2), &gba->cpu.cycles);
gba->cpu.memory.store32(&gba->cpu, dest + (i << 2), word, &gba->cpu.cycles);
gba->cpu.board.processEvents(&gba->cpu);
}
} else {
source &= 0xFFFFFFFE;
dest &= 0xFFFFFFFE;
for (i = 0; i < count; ++i) {
uint16_t word = gba->memory.d.load16(&gba->memory.d, source + (i << 1), &gba->cpu.cycles);
gba->memory.d.store16(&gba->memory.d, dest + (i << 1), word, &gba->cpu.cycles);
gba->board.d.processEvents(&gba->board.d);
uint16_t word = gba->cpu.memory.load16(&gba->cpu, source + (i << 1), &gba->cpu.cycles);
gba->cpu.memory.store16(&gba->cpu, dest + (i << 1), word, &gba->cpu.cycles);
gba->cpu.board.processEvents(&gba->cpu);
}
}
}
@ -69,34 +69,34 @@ static void _FastCpuSet(struct GBA* gba) {
uint32_t dest = gba->cpu.gprs[1] & 0xFFFFFFFC;
uint32_t mode = gba->cpu.gprs[2];
int count = mode & 0x000FFFFF;
int storeCycles = gba->memory.d.waitMultiple(&gba->memory.d, dest, 4);
int storeCycles = gba->cpu.memory.waitMultiple(&gba->cpu, dest, 4);
count = ((count + 7) >> 3) << 3;
int i;
if (mode & 0x01000000) {
int32_t word = gba->memory.d.load32(&gba->memory.d, source, &gba->cpu.cycles);
int32_t word = gba->cpu.memory.load32(&gba->cpu, source, &gba->cpu.cycles);
for (i = 0; i < count; i += 4) {
gba->memory.d.store32(&gba->memory.d, dest + ((i + 0) << 2), word, 0);
gba->memory.d.store32(&gba->memory.d, dest + ((i + 1) << 2), word, 0);
gba->memory.d.store32(&gba->memory.d, dest + ((i + 2) << 2), word, 0);
gba->memory.d.store32(&gba->memory.d, dest + ((i + 3) << 2), word, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 0) << 2), word, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 1) << 2), word, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 2) << 2), word, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 3) << 2), word, 0);
gba->cpu.cycles += storeCycles;
gba->board.d.processEvents(&gba->board.d);
gba->cpu.board.processEvents(&gba->cpu);
}
} else {
int loadCycles = gba->memory.d.waitMultiple(&gba->memory.d, source, 4);
int loadCycles = gba->cpu.memory.waitMultiple(&gba->cpu, source, 4);
for (i = 0; i < count; i += 4) {
int32_t word0 = gba->memory.d.load32(&gba->memory.d, source + ((i + 0) << 2), 0);
int32_t word1 = gba->memory.d.load32(&gba->memory.d, source + ((i + 1) << 2), 0);
int32_t word2 = gba->memory.d.load32(&gba->memory.d, source + ((i + 2) << 2), 0);
int32_t word3 = gba->memory.d.load32(&gba->memory.d, source + ((i + 3) << 2), 0);
int32_t word0 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 0) << 2), 0);
int32_t word1 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 1) << 2), 0);
int32_t word2 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 2) << 2), 0);
int32_t word3 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 3) << 2), 0);
gba->cpu.cycles += loadCycles;
gba->board.d.processEvents(&gba->board.d);
gba->memory.d.store32(&gba->memory.d, dest + ((i + 0) << 2), word0, 0);
gba->memory.d.store32(&gba->memory.d, dest + ((i + 1) << 2), word1, 0);
gba->memory.d.store32(&gba->memory.d, dest + ((i + 2) << 2), word2, 0);
gba->memory.d.store32(&gba->memory.d, dest + ((i + 3) << 2), word3, 0);
gba->cpu.board.processEvents(&gba->cpu);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 0) << 2), word0, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 1) << 2), word1, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 2) << 2), word2, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 3) << 2), word3, 0);
gba->cpu.cycles += storeCycles;
gba->board.d.processEvents(&gba->board.d);
gba->cpu.board.processEvents(&gba->cpu);
}
}
}
@ -117,13 +117,13 @@ static void _BgAffineSet(struct GBA* gba) {
// [ sx 0 0 ] [ cos(theta) -sin(theta) 0 ] [ 1 0 cx - ox ] [ A B rx ]
// [ 0 sy 0 ] * [ sin(theta) cos(theta) 0 ] * [ 0 1 cy - oy ] = [ C D ry ]
// [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ]
ox = gba->memory.d.load32(&gba->memory.d, offset, 0) / 256.f;
oy = gba->memory.d.load32(&gba->memory.d, offset + 4, 0) / 256.f;
cx = gba->memory.d.load16(&gba->memory.d, offset + 8, 0);
cy = gba->memory.d.load16(&gba->memory.d, offset + 10, 0);
sx = gba->memory.d.load16(&gba->memory.d, offset + 12, 0) / 256.f;
sy = gba->memory.d.load16(&gba->memory.d, offset + 14, 0) / 256.f;
theta = (gba->memory.d.loadU16(&gba->memory.d, offset + 16, 0) >> 8) / 128.f * M_PI;
ox = gba->cpu.memory.load32(&gba->cpu, offset, 0) / 256.f;
oy = gba->cpu.memory.load32(&gba->cpu, offset + 4, 0) / 256.f;
cx = gba->cpu.memory.load16(&gba->cpu, offset + 8, 0);
cy = gba->cpu.memory.load16(&gba->cpu, offset + 10, 0);
sx = gba->cpu.memory.load16(&gba->cpu, offset + 12, 0) / 256.f;
sy = gba->cpu.memory.load16(&gba->cpu, offset + 14, 0) / 256.f;
theta = (gba->cpu.memory.loadU16(&gba->cpu, offset + 16, 0) >> 8) / 128.f * M_PI;
offset += 20;
// Rotation
a = d = cosf(theta);
@ -136,12 +136,12 @@ static void _BgAffineSet(struct GBA* gba) {
// Translate
rx = ox - (a * cx + b * cy);
ry = oy - (c * cx + d * cy);
gba->memory.d.store16(&gba->memory.d, destination, a * 256, 0);
gba->memory.d.store16(&gba->memory.d, destination + 2, b * 256, 0);
gba->memory.d.store16(&gba->memory.d, destination + 4, c * 256, 0);
gba->memory.d.store16(&gba->memory.d, destination + 6, d * 256, 0);
gba->memory.d.store32(&gba->memory.d, destination + 8, rx * 256, 0);
gba->memory.d.store32(&gba->memory.d, destination + 12, ry * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination, a * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + 2, b * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + 4, c * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + 6, d * 256, 0);
gba->cpu.memory.store32(&gba->cpu, destination + 8, rx * 256, 0);
gba->cpu.memory.store32(&gba->cpu, destination + 12, ry * 256, 0);
destination += 16;
}
}
@ -157,9 +157,9 @@ static void _ObjAffineSet(struct GBA* gba) {
while (i--) {
// [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ]
// [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ]
sx = gba->memory.d.load16(&gba->memory.d, offset, 0) / 256.f;
sy = gba->memory.d.load16(&gba->memory.d, offset + 2, 0) / 256.f;
theta = (gba->memory.d.loadU16(&gba->memory.d, offset + 4, 0) >> 8) / 128.f * M_PI;
sx = gba->cpu.memory.load16(&gba->cpu, offset, 0) / 256.f;
sy = gba->cpu.memory.load16(&gba->cpu, offset + 2, 0) / 256.f;
theta = (gba->cpu.memory.loadU16(&gba->cpu, offset + 4, 0) >> 8) / 128.f * M_PI;
offset += 6;
// Rotation
a = d = cosf(theta);
@ -169,21 +169,21 @@ static void _ObjAffineSet(struct GBA* gba) {
b *= -sx;
c *= sy;
d *= sy;
gba->memory.d.store16(&gba->memory.d, destination, a * 256, 0);
gba->memory.d.store16(&gba->memory.d, destination + diff, b * 256, 0);
gba->memory.d.store16(&gba->memory.d, destination + diff * 2, c * 256, 0);
gba->memory.d.store16(&gba->memory.d, destination + diff * 3, d * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination, a * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + diff, b * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + diff * 2, c * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + diff * 3, d * 256, 0);
destination += diff * 4;
}
}
static void _MidiKey2Freq(struct GBA* gba) {
uint32_t key = gba->memory.d.load32(&gba->memory.d, gba->cpu.gprs[0] + 4, 0);
uint32_t key = gba->cpu.memory.load32(&gba->cpu, gba->cpu.gprs[0] + 4, 0);
gba->cpu.gprs[0] = key / powf(2, (180.f - gba->cpu.gprs[1] - gba->cpu.gprs[2] / 256.f) / 12.f);
}
void GBASwi16(struct ARMBoard* board, int immediate) {
struct GBA* gba = ((struct GBABoard*) board)->p;
void GBASwi16(struct ARMCore* cpu, int immediate) {
struct GBA* gba = (struct GBA*) cpu;
if (gba->memory.fullBios) {
ARMRaiseSWI(&gba->cpu);
return;
@ -253,13 +253,13 @@ void GBASwi16(struct ARMBoard* board, int immediate) {
}
switch (gba->cpu.gprs[1] >> BASE_OFFSET) {
case REGION_WORKING_RAM:
_unLz77(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]);
_unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]);
break;
case REGION_WORKING_IRAM:
_unLz77(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]);
_unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]);
break;
case REGION_VRAM:
_unLz77(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]);
_unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]);
break;
default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 destination");
@ -273,13 +273,13 @@ void GBASwi16(struct ARMBoard* board, int immediate) {
}
switch (gba->cpu.gprs[1] >> BASE_OFFSET) {
case REGION_WORKING_RAM:
_unHuffman(&gba->memory, gba->cpu.gprs[0], &((uint32_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 3)) >> 2]);
_unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 3)) >> 2]);
break;
case REGION_WORKING_IRAM:
_unHuffman(&gba->memory, gba->cpu.gprs[0], &((uint32_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 3)) >> 2]);
_unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 3)) >> 2]);
break;
case REGION_VRAM:
_unHuffman(&gba->memory, gba->cpu.gprs[0], &((uint32_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFC) >> 2]);
_unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFC) >> 2]);
break;
default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman destination");
@ -294,13 +294,13 @@ void GBASwi16(struct ARMBoard* board, int immediate) {
}
switch (gba->cpu.gprs[1] >> BASE_OFFSET) {
case REGION_WORKING_RAM:
_unRl(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]);
_unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]);
break;
case REGION_WORKING_IRAM:
_unRl(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]);
_unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]);
break;
case REGION_VRAM:
_unRl(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]);
_unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]);
break;
default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad RL destination");
@ -315,8 +315,8 @@ void GBASwi16(struct ARMBoard* board, int immediate) {
}
}
void GBASwi32(struct ARMBoard* board, int immediate) {
GBASwi16(board, immediate >> 16);
void GBASwi32(struct ARMCore* cpu, int immediate) {
GBASwi16(cpu, immediate >> 16);
}
uint32_t GBAChecksum(uint32_t* memory, size_t size) {
@ -328,8 +328,8 @@ uint32_t GBAChecksum(uint32_t* memory, size_t size) {
return sum;
}
static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
int remaining = (memory->d.load32(&memory->d, source, 0) & 0xFFFFFF00) >> 8;
static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest) {
int remaining = (gba->cpu.memory.load32(&gba->cpu, source, 0) & 0xFFFFFF00) >> 8;
// We assume the signature byte (0x10) is correct
int blockheader;
uint32_t sPointer = source + 4;
@ -342,7 +342,7 @@ static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
if (blocksRemaining) {
if (blockheader & 0x80) {
// Compressed
block = memory->d.loadU8(&memory->d, sPointer, 0) | (memory->d.loadU8(&memory->d, sPointer + 1, 0) << 8);
block = gba->cpu.memory.loadU8(&gba->cpu, sPointer, 0) | (gba->cpu.memory.loadU8(&gba->cpu, sPointer + 1, 0) << 8);
sPointer += 2;
disp = dPointer - (((block & 0x000F) << 8) | ((block & 0xFF00) >> 8)) - 1;
bytes = ((block & 0x00F0) >> 4) + 3;
@ -354,33 +354,33 @@ static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
}
} else {
// Uncompressed
*dPointer = memory->d.loadU8(&memory->d, sPointer++, 0);
*dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0);
++dPointer;
--remaining;
}
blockheader <<= 1;
--blocksRemaining;
} else {
blockheader = memory->d.loadU8(&memory->d, sPointer++, 0);
blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0);
blocksRemaining = 8;
}
}
}
static void _unHuffman(struct GBAMemory* memory, uint32_t source, uint32_t* dest) {
static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) {
source = source & 0xFFFFFFFC;
uint32_t header = memory->d.load32(&memory->d, source, 0);
uint32_t header = gba->cpu.memory.load32(&gba->cpu, source, 0);
int remaining = header >> 8;
int bits = header & 0xF;
if (32 % bits) {
GBALog(memory->p, GBA_LOG_STUB, "Unimplemented unaligned Huffman");
GBALog(gba, GBA_LOG_STUB, "Unimplemented unaligned Huffman");
return;
}
int padding = (4 - remaining) & 0x3;
remaining &= 0xFFFFFFFC;
// We assume the signature byte (0x20) is correct
//var tree = [];
int treesize = (memory->d.loadU8(&memory->d, source + 4, 0) << 1) + 1;
int treesize = (gba->cpu.memory.loadU8(&gba->cpu, source + 4, 0) << 1) + 1;
int block = 0;
uint32_t treeBase = source + 5;
uint32_t sPointer = source + 5 + treesize;
@ -397,28 +397,28 @@ static void _unHuffman(struct GBAMemory* memory, uint32_t source, uint32_t* dest
int bitsRemaining;
int readBits;
int bitsSeen = 0;
node.packed = memory->d.load8(&memory->d, nPointer, 0);
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0);
while (remaining > 0) {
uint32_t bitstream = memory->d.load32(&memory->d, sPointer, 0);
uint32_t bitstream = gba->cpu.memory.load32(&gba->cpu, sPointer, 0);
sPointer += 4;
for (bitsRemaining = 32; bitsRemaining > 0; --bitsRemaining, bitstream <<= 1) {
uint32_t next = (nPointer & ~1) + node.offset * 2 + 2;
if (bitstream & 0x80000000) {
// Go right
if (node.rTerm) {
readBits = memory->d.load8(&memory->d, next + 1, 0);
readBits = gba->cpu.memory.load8(&gba->cpu, next + 1, 0);
} else {
nPointer = next + 1;
node.packed = memory->d.load8(&memory->d, nPointer, 0);
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0);
continue;
}
} else {
// Go left
if (node.lTerm) {
readBits = memory->d.load8(&memory->d, next, 0);
readBits = gba->cpu.memory.load8(&gba->cpu, next, 0);
} else {
nPointer = next;
node.packed = memory->d.load8(&memory->d, nPointer, 0);
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0);
continue;
}
}
@ -426,7 +426,7 @@ static void _unHuffman(struct GBAMemory* memory, uint32_t source, uint32_t* dest
block |= (readBits & ((1 << bits) - 1)) << bitsSeen;
bitsSeen += bits;
nPointer = treeBase;
node.packed = memory->d.load8(&memory->d, nPointer, 0);
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0);
if (bitsSeen == 32) {
bitsSeen = 0;
*dPointer = block;
@ -442,9 +442,9 @@ static void _unHuffman(struct GBAMemory* memory, uint32_t source, uint32_t* dest
}
}
static void _unRl(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) {
source = source & 0xFFFFFFFC;
int remaining = (memory->d.load32(&memory->d, source, 0) & 0xFFFFFF00) >> 8;
int remaining = (gba->cpu.memory.load32(&gba->cpu, source, 0) & 0xFFFFFF00) >> 8;
int padding = (4 - remaining) & 0x3;
// We assume the signature byte (0x30) is correct
int blockheader;
@ -452,12 +452,12 @@ static void _unRl(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
uint32_t sPointer = source + 4;
uint8_t* dPointer = dest;
while (remaining > 0) {
blockheader = memory->d.loadU8(&memory->d, sPointer++, 0);
blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0);
if (blockheader & 0x80) {
// Compressed
blockheader &= 0x7F;
blockheader += 3;
block = memory->d.loadU8(&memory->d, sPointer++, 0);
block = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0);
while (blockheader-- && remaining) {
--remaining;
*dPointer = block;
@ -468,7 +468,7 @@ static void _unRl(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
blockheader++;
while (blockheader-- && remaining) {
--remaining;
*dPointer = memory->d.loadU8(&memory->d, sPointer++, 0);
*dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0);
++dPointer;
}
}

View File

@ -5,8 +5,8 @@
#include "arm.h"
void GBASwi16(struct ARMBoard* board, int immediate);
void GBASwi32(struct ARMBoard* board, int immediate);
void GBASwi16(struct ARMCore* cpu, int immediate);
void GBASwi32(struct ARMCore* cpu, int immediate);
uint32_t GBAChecksum(uint32_t* memory, size_t size);
const uint32_t GBA_BIOS_CHECKSUM;

View File

@ -200,28 +200,28 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
break;
case REG_DMA0CNT_LO:
GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
GBAMemoryWriteDMACNT_LO(gba, 0, value);
break;
case REG_DMA0CNT_HI:
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
value = GBAMemoryWriteDMACNT_HI(gba, 0, value);
break;
case REG_DMA1CNT_LO:
GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
GBAMemoryWriteDMACNT_LO(gba, 1, value);
break;
case REG_DMA1CNT_HI:
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
value = GBAMemoryWriteDMACNT_HI(gba, 1, value);
break;
case REG_DMA2CNT_LO:
GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
GBAMemoryWriteDMACNT_LO(gba, 2, value);
break;
case REG_DMA2CNT_HI:
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
value = GBAMemoryWriteDMACNT_HI(gba, 2, value);
break;
case REG_DMA3CNT_LO:
GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
GBAMemoryWriteDMACNT_LO(gba, 3, value);
break;
case REG_DMA3CNT_HI:
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
value = GBAMemoryWriteDMACNT_HI(gba, 3, value);
break;
// Timers
@ -269,7 +269,7 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
// Interrupts and misc
case REG_WAITCNT:
GBAAdjustWaitstates(&gba->memory, value);
GBAAdjustWaitstates(gba, value);
break;
case REG_IE:
GBAWriteIE(gba, value);
@ -325,28 +325,28 @@ void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
GBAAudioWriteFIFO(&gba->audio, address, value);
break;
case REG_DMA0SAD_LO:
GBAMemoryWriteDMASAD(&gba->memory, 0, value);
GBAMemoryWriteDMASAD(gba, 0, value);
break;
case REG_DMA0DAD_LO:
GBAMemoryWriteDMADAD(&gba->memory, 0, value);
GBAMemoryWriteDMADAD(gba, 0, value);
break;
case REG_DMA1SAD_LO:
GBAMemoryWriteDMASAD(&gba->memory, 1, value);
GBAMemoryWriteDMASAD(gba, 1, value);
break;
case REG_DMA1DAD_LO:
GBAMemoryWriteDMADAD(&gba->memory, 1, value);
GBAMemoryWriteDMADAD(gba, 1, value);
break;
case REG_DMA2SAD_LO:
GBAMemoryWriteDMASAD(&gba->memory, 2, value);
GBAMemoryWriteDMASAD(gba, 2, value);
break;
case REG_DMA2DAD_LO:
GBAMemoryWriteDMADAD(&gba->memory, 2, value);
GBAMemoryWriteDMADAD(gba, 2, value);
break;
case REG_DMA3SAD_LO:
GBAMemoryWriteDMASAD(&gba->memory, 3, value);
GBAMemoryWriteDMASAD(gba, 3, value);
break;
case REG_DMA3DAD_LO:
GBAMemoryWriteDMADAD(&gba->memory, 3, value);
GBAMemoryWriteDMADAD(gba, 3, value);
break;
default:
GBAIOWrite(gba, address, value & 0xFFFF);

View File

@ -6,9 +6,9 @@
#include "hle-bios.h"
#include "util/memory.h"
static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region);
static int GBAWaitMultiple(struct ARMMemory* memory, uint32_t startAddress, int count);
static void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* info);
static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count);
static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 9, 9, 13, 13, 9 };
@ -18,99 +18,100 @@ static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
void GBAMemoryInit(struct GBAMemory* memory) {
memory->d.load32 = GBALoad32;
memory->d.load16 = GBALoad16;
memory->d.loadU16 = GBALoadU16;
memory->d.load8 = GBALoad8;
memory->d.loadU8 = GBALoadU8;
memory->d.store32 = GBAStore32;
memory->d.store16 = GBAStore16;
memory->d.store8 = GBAStore8;
void GBAMemoryInit(struct GBA* gba) {
gba->cpu.memory.load32 = GBALoad32;
gba->cpu.memory.load16 = GBALoad16;
gba->cpu.memory.loadU16 = GBALoadU16;
gba->cpu.memory.load8 = GBALoad8;
gba->cpu.memory.loadU8 = GBALoadU8;
gba->cpu.memory.store32 = GBAStore32;
gba->cpu.memory.store16 = GBAStore16;
gba->cpu.memory.store8 = GBAStore8;
memory->bios = (uint32_t*) hleBios;
memory->fullBios = 0;
memory->wram = anonymousMemoryMap(SIZE_WORKING_RAM);
memory->iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
memory->rom = 0;
memory->gpio.p = memory->p;
memset(memory->io, 0, sizeof(memory->io));
memset(memory->dma, 0, sizeof(memory->dma));
gba->memory.bios = (uint32_t*) hleBios;
gba->memory.fullBios = 0;
gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
gba->memory.rom = 0;
gba->memory.gpio.p = gba;
memset(gba->memory.io, 0, sizeof(gba->memory.io));
memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
int i;
for (i = 0; i < 4; ++i) {
memory->dma[i].count = 0x10000;
memory->dma[i].nextEvent = INT_MAX;
gba->memory.dma[i].count = 0x10000;
gba->memory.dma[i].nextEvent = INT_MAX;
}
memory->activeDMA = -1;
memory->nextDMA = INT_MAX;
memory->eventDiff = 0;
gba->memory.activeDMA = -1;
gba->memory.nextDMA = INT_MAX;
gba->memory.eventDiff = 0;
if (!memory->wram || !memory->iwram) {
GBAMemoryDeinit(memory);
GBALog(memory->p, GBA_LOG_FATAL, "Could not map memory");
if (!gba->memory.wram || !gba->memory.iwram) {
GBAMemoryDeinit(gba);
GBALog(gba, GBA_LOG_FATAL, "Could not map memory");
return;
}
for (i = 0; i < 16; ++i) {
memory->waitstates16[i] = GBA_BASE_WAITSTATES[i];
memory->waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
memory->waitstatesPrefetch16[i] = GBA_BASE_WAITSTATES_SEQ[i];
memory->waitstates32[i] = GBA_BASE_WAITSTATES_32[i];
memory->waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
memory->waitstatesPrefetch32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
gba->memory.waitstates16[i] = GBA_BASE_WAITSTATES[i];
gba->memory.waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
gba->memory.waitstatesPrefetch16[i] = GBA_BASE_WAITSTATES_SEQ[i];
gba->memory.waitstates32[i] = GBA_BASE_WAITSTATES_32[i];
gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
gba->memory.waitstatesPrefetch32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
}
for (; i < 256; ++i) {
memory->waitstates16[i] = 0;
memory->waitstatesSeq16[i] = 0;
memory->waitstatesPrefetch16[i] = 0;
memory->waitstates32[i] = 0;
memory->waitstatesSeq32[i] = 0;
memory->waitstatesPrefetch32[i] = 0;
gba->memory.waitstates16[i] = 0;
gba->memory.waitstatesSeq16[i] = 0;
gba->memory.waitstatesPrefetch16[i] = 0;
gba->memory.waitstates32[i] = 0;
gba->memory.waitstatesSeq32[i] = 0;
gba->memory.waitstatesPrefetch32[i] = 0;
}
memory->activeRegion = -1;
memory->d.activeRegion = 0;
memory->d.activeMask = 0;
memory->d.setActiveRegion = GBASetActiveRegion;
memory->d.activePrefetchCycles32 = 0;
memory->d.activePrefetchCycles16 = 0;
memory->biosPrefetch = 0;
memory->d.waitMultiple = GBAWaitMultiple;
gba->memory.activeRegion = -1;
gba->cpu.memory.activeRegion = 0;
gba->cpu.memory.activeMask = 0;
gba->cpu.memory.setActiveRegion = GBASetActiveRegion;
gba->cpu.memory.activePrefetchCycles32 = 0;
gba->cpu.memory.activePrefetchCycles16 = 0;
gba->memory.biosPrefetch = 0;
gba->cpu.memory.waitMultiple = GBAWaitMultiple;
}
void GBAMemoryDeinit(struct GBAMemory* memory) {
mappedMemoryFree(memory->wram, SIZE_WORKING_RAM);
mappedMemoryFree(memory->iwram, SIZE_WORKING_IRAM);
GBASavedataDeinit(&memory->savedata);
void GBAMemoryDeinit(struct GBA* gba) {
mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
GBASavedataDeinit(&gba->memory.savedata);
}
static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
int newRegion = address >> BASE_OFFSET;
if (newRegion == gbaMemory->activeRegion) {
if (newRegion == memory->activeRegion) {
return;
}
if (gbaMemory->activeRegion == REGION_BIOS) {
gbaMemory->biosPrefetch = memory->load32(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_ARM * 2, 0);
if (memory->activeRegion == REGION_BIOS) {
memory->biosPrefetch = cpu->memory.load32(cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0);
}
gbaMemory->activeRegion = newRegion;
memory->activePrefetchCycles32 = gbaMemory->waitstatesPrefetch32[gbaMemory->activeRegion];
memory->activePrefetchCycles16 = gbaMemory->waitstatesPrefetch16[gbaMemory->activeRegion];
memory->activeNonseqCycles32 = gbaMemory->waitstates32[gbaMemory->activeRegion];
memory->activeNonseqCycles16 = gbaMemory->waitstates16[gbaMemory->activeRegion];
memory->activeRegion = newRegion;
cpu->memory.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion];
cpu->memory.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion];
cpu->memory.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion];
cpu->memory.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion];
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
memory->activeRegion = gbaMemory->bios;
memory->activeMask = SIZE_BIOS - 1;
cpu->memory.activeRegion = memory->bios;
cpu->memory.activeMask = SIZE_BIOS - 1;
break;
case BASE_WORKING_RAM:
memory->activeRegion = gbaMemory->wram;
memory->activeMask = SIZE_WORKING_RAM - 1;
cpu->memory.activeRegion = memory->wram;
cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
break;
case BASE_WORKING_IRAM:
memory->activeRegion = gbaMemory->iwram;
memory->activeMask = SIZE_WORKING_IRAM - 1;
cpu->memory.activeRegion = memory->iwram;
cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
break;
case BASE_CART0:
case BASE_CART0_EX:
@ -118,52 +119,53 @@ static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
case BASE_CART1_EX:
case BASE_CART2:
case BASE_CART2_EX:
memory->activeRegion = gbaMemory->rom;
memory->activeMask = SIZE_CART0 - 1;
cpu->memory.activeRegion = memory->rom;
cpu->memory.activeMask = SIZE_CART0 - 1;
break;
default:
memory->activeRegion = 0;
memory->activeMask = 0;
GBALog(gbaMemory->p, GBA_LOG_FATAL, "Jumped to invalid address");
cpu->memory.activeRegion = 0;
cpu->memory.activeMask = 0;
GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address");
break;
}
}
int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
uint32_t value = 0;
int wait = 0;
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) {
if (address < SIZE_BIOS) {
LOAD_32(value, address, gbaMemory->bios);
LOAD_32(value, address, memory->bios);
} else {
value = 0;
}
} else {
value = gbaMemory->biosPrefetch;
value = memory->biosPrefetch;
}
break;
case BASE_WORKING_RAM:
LOAD_32(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
wait = gbaMemory->waitstates32[REGION_WORKING_RAM];
LOAD_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
wait = memory->waitstates32[REGION_WORKING_RAM];
break;
case BASE_WORKING_IRAM:
LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
break;
case BASE_IO:
value = GBAIORead(gbaMemory->p, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gbaMemory->p, (address & (SIZE_IO - 1)) | 2) << 16);
value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16);
break;
case BASE_PALETTE_RAM:
LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
break;
case BASE_VRAM:
LOAD_32(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
break;
case BASE_OAM:
LOAD_32(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
break;
case BASE_CART0:
case BASE_CART0_EX:
@ -171,21 +173,21 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
case BASE_CART1_EX:
case BASE_CART2:
case BASE_CART2_EX:
wait = gbaMemory->waitstates32[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
LOAD_32(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
wait = memory->waitstates32[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
LOAD_32(value, address & (SIZE_CART0 - 1), memory->rom);
}
break;
case BASE_CART_SRAM:
case BASE_CART_SRAM_MIRROR:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address);
break;
default:
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
if (gbaMemory->p->cpu.executionMode == MODE_ARM) {
value = memory->load32(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_ARM * 2, 0);
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
if (cpu->executionMode == MODE_ARM) {
value = cpu->memory.load32(&gba->cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0);
} else {
value = memory->load16(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_THUMB * 2, 0);
value = cpu->memory.load16(&gba->cpu, cpu->currentPC + WORD_SIZE_THUMB * 2, 0);
value |= value << 16;
}
break;
@ -200,71 +202,72 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
return (value >> rotate) | (value << (32 - rotate));
}
uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
return GBALoad16(memory, address, cycleCounter);
uint16_t GBALoadU16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
return GBALoad16(cpu, address, cycleCounter);
}
int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
uint16_t value = 0;
int wait = 0;
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) {
if (address < SIZE_BIOS) {
LOAD_16(value, address, gbaMemory->bios);
LOAD_16(value, address, memory->bios);
} else {
value = 0;
}
} else {
value = gbaMemory->biosPrefetch;
value = memory->biosPrefetch;
}
break;
case BASE_WORKING_RAM:
LOAD_16(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
LOAD_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
wait = memory->waitstates16[REGION_WORKING_RAM];
break;
case BASE_WORKING_IRAM:
LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
break;
case BASE_IO:
value = GBAIORead(gbaMemory->p, address & (SIZE_IO - 1));
value = GBAIORead(gba, address & (SIZE_IO - 1));
break;
case BASE_PALETTE_RAM:
LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
break;
case BASE_VRAM:
LOAD_16(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
break;
case BASE_OAM:
LOAD_16(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
break;
case BASE_CART0:
case BASE_CART0_EX:
case BASE_CART1:
case BASE_CART1_EX:
case BASE_CART2:
wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
LOAD_16(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
wait = memory->waitstates16[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
}
break;
case BASE_CART2_EX:
wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
if (gbaMemory->savedata.type == SAVEDATA_EEPROM) {
value = GBASavedataReadEEPROM(&gbaMemory->savedata);
} else if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
LOAD_16(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
wait = memory->waitstates16[address >> BASE_OFFSET];
if (memory->savedata.type == SAVEDATA_EEPROM) {
value = GBASavedataReadEEPROM(&memory->savedata);
} else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
}
break;
case BASE_CART_SRAM:
case BASE_CART_SRAM_MIRROR:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
break;
default:
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
value = memory->load16(memory, gbaMemory->p->cpu.currentPC + (gbaMemory->p->cpu.executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0);
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
value = cpu->memory.load16(&gba->cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0);
break;
}
@ -276,45 +279,46 @@ int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
return (value >> rotate) | (value << (16 - rotate));
}
uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
return GBALoad8(memory, address, cycleCounter);
uint8_t GBALoadU8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
return GBALoad8(cpu, address, cycleCounter);
}
int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
int8_t value = 0;
int wait = 0;
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) {
if (address < SIZE_BIOS) {
value = ((int8_t*) gbaMemory->bios)[address];
value = ((int8_t*) memory->bios)[address];
} else {
value = 0;
}
} else {
value = gbaMemory->biosPrefetch;
value = memory->biosPrefetch;
}
break;
case BASE_WORKING_RAM:
value = ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
value = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
wait = memory->waitstates16[REGION_WORKING_RAM];
break;
case BASE_WORKING_IRAM:
value = ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
value = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
break;
case BASE_IO:
value = (GBAIORead(gbaMemory->p, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
break;
case BASE_PALETTE_RAM:
value = ((int8_t*) gbaMemory->p->video.renderer->palette)[address & (SIZE_PALETTE_RAM - 1)];
value = ((int8_t*) gba->video.renderer->palette)[address & (SIZE_PALETTE_RAM - 1)];
break;
case BASE_VRAM:
value = ((int8_t*) gbaMemory->p->video.renderer->vram)[address & 0x0001FFFF];
value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
break;
case BASE_OAM:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
break;
case BASE_CART0:
case BASE_CART0_EX:
@ -322,26 +326,26 @@ int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
case BASE_CART1_EX:
case BASE_CART2:
case BASE_CART2_EX:
wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
value = ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
wait = memory->waitstates16[address >> BASE_OFFSET];
if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
value = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
}
break;
case BASE_CART_SRAM:
case BASE_CART_SRAM_MIRROR:
wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
GBASavedataInitSRAM(&gbaMemory->savedata);
wait = memory->waitstates16[address >> BASE_OFFSET];
if (memory->savedata.type == SAVEDATA_NONE) {
GBASavedataInitSRAM(&memory->savedata);
}
if (gbaMemory->savedata.type == SAVEDATA_SRAM) {
value = gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)];
} else if (gbaMemory->savedata.type == SAVEDATA_FLASH512 || gbaMemory->savedata.type == SAVEDATA_FLASH1M) {
value = GBASavedataReadFlash(&gbaMemory->savedata, address);
if (memory->savedata.type == SAVEDATA_SRAM) {
value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
value = GBASavedataReadFlash(&memory->savedata, address);
}
break;
default:
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
value = memory->load16(memory, gbaMemory->p->cpu.currentPC + (gbaMemory->p->cpu.executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0) >> ((address & 1) << 3);
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
value = cpu->memory.load16(cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0) >> ((address & 1) << 3);
break;
}
@ -351,45 +355,46 @@ int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
return value;
}
void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value, int* cycleCounter) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
int wait = 0;
switch (address & ~OFFSET_MASK) {
case BASE_WORKING_RAM:
STORE_32(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
wait = gbaMemory->waitstates32[REGION_WORKING_RAM];
STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
wait = memory->waitstates32[REGION_WORKING_RAM];
break;
case BASE_WORKING_IRAM:
STORE_32(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
break;
case BASE_IO:
GBAIOWrite32(gbaMemory->p, address & (SIZE_IO - 1), value);
GBAIOWrite32(gba, address & (SIZE_IO - 1), value);
break;
case BASE_PALETTE_RAM:
STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
break;
case BASE_VRAM:
if ((address & OFFSET_MASK) < SIZE_VRAM - 2) {
STORE_32(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
}
break;
case BASE_OAM:
STORE_32(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
break;
case BASE_CART0:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
break;
case BASE_CART_SRAM:
case BASE_CART_SRAM_MIRROR:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
break;
default:
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
break;
}
@ -398,54 +403,55 @@ void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value, int*
}
}
void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value, int* cycleCounter) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
int wait = 0;
switch (address & ~OFFSET_MASK) {
case BASE_WORKING_RAM:
STORE_16(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
wait = memory->waitstates16[REGION_WORKING_RAM];
break;
case BASE_WORKING_IRAM:
STORE_16(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
break;
case BASE_IO:
GBAIOWrite(gbaMemory->p, address & (SIZE_IO - 1), value);
GBAIOWrite(gba, address & (SIZE_IO - 1), value);
break;
case BASE_PALETTE_RAM:
STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
break;
case BASE_VRAM:
if ((address & OFFSET_MASK) < SIZE_VRAM) {
STORE_16(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
}
break;
case BASE_OAM:
STORE_16(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
break;
case BASE_CART0:
if (IS_GPIO_REGISTER(address & 0xFFFFFF)) {
uint32_t reg = address & 0xFFFFFF;
GBAGPIOWrite(&gbaMemory->gpio, reg, value);
GBAGPIOWrite(&memory->gpio, reg, value);
} else {
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
}
break;
case BASE_CART2_EX:
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
GBASavedataInitEEPROM(&gbaMemory->savedata);
if (memory->savedata.type == SAVEDATA_NONE) {
GBASavedataInitEEPROM(&memory->savedata);
}
GBASavedataWriteEEPROM(&gbaMemory->savedata, value, 1);
GBASavedataWriteEEPROM(&memory->savedata, value, 1);
break;
case BASE_CART_SRAM:
case BASE_CART_SRAM_MIRROR:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
break;
default:
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
break;
}
@ -454,57 +460,58 @@ void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value, int*
}
}
void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cycleCounter) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
int wait = 0;
switch (address & ~OFFSET_MASK) {
case BASE_WORKING_RAM:
((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
wait = memory->waitstates16[REGION_WORKING_RAM];
break;
case BASE_WORKING_IRAM:
((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
break;
case BASE_IO:
GBAIOWrite8(gbaMemory->p, address & (SIZE_IO - 1), value);
GBAIOWrite8(gba, address & (SIZE_IO - 1), value);
break;
case BASE_PALETTE_RAM:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
break;
case BASE_VRAM:
if (address >= 0x06018000) {
// TODO: check BG mode
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
break;
}
((int8_t*) gbaMemory->p->video.renderer->vram)[address & 0x1FFFE] = value;
((int8_t*) gbaMemory->p->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
((int8_t*) gba->video.renderer->vram)[address & 0x1FFFE] = value;
((int8_t*) gba->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
break;
case BASE_OAM:
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
break;
case BASE_CART0:
GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
break;
case BASE_CART_SRAM:
case BASE_CART_SRAM_MIRROR:
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
if (memory->savedata.type == SAVEDATA_NONE) {
if (address == SAVEDATA_FLASH_BASE) {
GBASavedataInitFlash(&gbaMemory->savedata);
GBASavedataInitFlash(&memory->savedata);
} else {
GBASavedataInitSRAM(&gbaMemory->savedata);
GBASavedataInitSRAM(&memory->savedata);
}
}
if (gbaMemory->savedata.type == SAVEDATA_FLASH512 || gbaMemory->savedata.type == SAVEDATA_FLASH1M) {
GBASavedataWriteFlash(&gbaMemory->savedata, address, value);
} else if (gbaMemory->savedata.type == SAVEDATA_SRAM) {
gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
GBASavedataWriteFlash(&memory->savedata, address, value);
} else if (memory->savedata.type == SAVEDATA_SRAM) {
memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
}
wait = gbaMemory->waitstates16[REGION_CART_SRAM];
wait = memory->waitstates16[REGION_CART_SRAM];
break;
default:
GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
break;
}
@ -513,14 +520,16 @@ void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cy
}
}
static int GBAWaitMultiple(struct ARMMemory* memory, uint32_t startAddress, int count) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
int wait = 1 + gbaMemory->waitstates32[startAddress >> BASE_OFFSET];
wait += (1 + gbaMemory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1);
static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count) {
struct GBA* gba = (struct GBA*) cpu;
struct GBAMemory* memory = &gba->memory;
int wait = 1 + memory->waitstates32[startAddress >> BASE_OFFSET];
wait += (1 + memory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1);
return wait;
}
void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {
void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
struct GBAMemory* memory = &gba->memory;
int sram = parameters & 0x0003;
int ws0 = (parameters & 0x000C) >> 2;
int ws0seq = (parameters & 0x0010) >> 4;
@ -569,48 +578,52 @@ void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {
memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = 0;
}
memory->d.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion];
memory->d.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion];
memory->d.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion];
memory->d.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion];
gba->cpu.memory.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion];
gba->cpu.memory.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion];
gba->cpu.memory.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion];
gba->cpu.memory.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion];
}
void GBAMemoryWriteDMASAD(struct GBAMemory* memory, int dma, uint32_t address) {
void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
struct GBAMemory* memory = &gba->memory;
memory->dma[dma].source = address & 0xFFFFFFFE;
}
void GBAMemoryWriteDMADAD(struct GBAMemory* memory, int dma, uint32_t address) {
void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
struct GBAMemory* memory = &gba->memory;
memory->dma[dma].dest = address & 0xFFFFFFFE;
}
void GBAMemoryWriteDMACNT_LO(struct GBAMemory* memory, int dma, uint16_t count) {
void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
struct GBAMemory* memory = &gba->memory;
memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
}
uint16_t GBAMemoryWriteDMACNT_HI(struct GBAMemory* memory, int dma, uint16_t control) {
uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
struct GBAMemory* memory = &gba->memory;
struct GBADMA* currentDma = &memory->dma[dma];
int wasEnabled = currentDma->enable;
currentDma->packed = control;
if (currentDma->drq) {
GBALog(memory->p, GBA_LOG_STUB, "DRQ not implemented");
GBALog(gba, GBA_LOG_STUB, "DRQ not implemented");
}
if (!wasEnabled && currentDma->enable) {
currentDma->nextSource = currentDma->source;
currentDma->nextDest = currentDma->dest;
currentDma->nextCount = currentDma->count;
GBAMemoryScheduleDMA(memory, dma, currentDma);
GBAMemoryScheduleDMA(gba, dma, currentDma);
}
// If the DMA has already occurred, this value might have changed since the function started
return currentDma->packed;
};
void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* info) {
void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
switch (info->timing) {
case DMA_TIMING_NOW:
info->nextEvent = memory->p->cpu.cycles;
GBAMemoryUpdateDMAs(memory, 0);
info->nextEvent = gba->cpu.cycles;
GBAMemoryUpdateDMAs(gba, 0);
break;
case DMA_TIMING_HBLANK:
// Handled implicitly
@ -624,11 +637,11 @@ void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* i
info->nextEvent = INT_MAX;
switch (number) {
case 0:
GBALog(memory->p, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
GBALog(gba, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
break;
case 1:
case 2:
GBAAudioScheduleFifoDma(&memory->p->audio, number, info);
GBAAudioScheduleFifoDma(&gba->audio, number, info);
break;
case 3:
// GBAVideoScheduleVCaptureDma(dma, info);
@ -637,7 +650,8 @@ void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* i
}
}
void GBAMemoryRunHblankDMAs(struct GBAMemory* memory, int32_t cycles) {
void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
struct GBAMemory* memory = &gba->memory;
struct GBADMA* dma;
int i;
for (i = 0; i < 4; ++i) {
@ -646,10 +660,11 @@ void GBAMemoryRunHblankDMAs(struct GBAMemory* memory, int32_t cycles) {
dma->nextEvent = cycles;
}
}
GBAMemoryUpdateDMAs(memory, 0);
GBAMemoryUpdateDMAs(gba, 0);
}
void GBAMemoryRunVblankDMAs(struct GBAMemory* memory, int32_t cycles) {
void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
struct GBAMemory* memory = &gba->memory;
struct GBADMA* dma;
int i;
for (i = 0; i < 4; ++i) {
@ -658,10 +673,11 @@ void GBAMemoryRunVblankDMAs(struct GBAMemory* memory, int32_t cycles) {
dma->nextEvent = cycles;
}
}
GBAMemoryUpdateDMAs(memory, 0);
GBAMemoryUpdateDMAs(gba, 0);
}
int32_t GBAMemoryRunDMAs(struct GBAMemory* memory, int32_t cycles) {
int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
struct GBAMemory* memory = &gba->memory;
if (memory->nextDMA == INT_MAX) {
return INT_MAX;
}
@ -669,15 +685,16 @@ int32_t GBAMemoryRunDMAs(struct GBAMemory* memory, int32_t cycles) {
memory->eventDiff += cycles;
if (memory->nextDMA <= 0) {
struct GBADMA* dma = &memory->dma[memory->activeDMA];
GBAMemoryServiceDMA(memory, memory->activeDMA, dma);
GBAMemoryUpdateDMAs(memory, memory->eventDiff);
GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
GBAMemoryUpdateDMAs(gba, memory->eventDiff);
memory->eventDiff = 0;
}
return memory->nextDMA;
}
void GBAMemoryUpdateDMAs(struct GBAMemory* memory, int32_t cycles) {
void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
int i;
struct GBAMemory* memory = &gba->memory;
memory->activeDMA = -1;
memory->nextDMA = INT_MAX;
for (i = 3; i >= 0; --i) {
@ -690,12 +707,13 @@ void GBAMemoryUpdateDMAs(struct GBAMemory* memory, int32_t cycles) {
}
}
}
if (memory->nextDMA < memory->p->cpu.nextEvent) {
memory->p->cpu.nextEvent = memory->nextDMA;
if (memory->nextDMA < gba->cpu.nextEvent) {
gba->cpu.nextEvent = memory->nextDMA;
}
}
void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* info) {
void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
struct GBAMemory* memory = &gba->memory;
uint32_t width = info->width ? 4 : 2;
int sourceOffset = DMA_OFFSET[info->srcControl] * width;
int destOffset = DMA_OFFSET[info->dstControl] * width;
@ -726,8 +744,8 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
if (width == 4) {
int32_t word;
word = memory->d.load32(&memory->d, source, 0);
memory->d.store32(&memory->d, dest, word, 0);
word = gba->cpu.memory.load32(&gba->cpu, source, 0);
gba->cpu.memory.store32(&gba->cpu, dest, word, 0);
source += sourceOffset;
dest += destOffset;
--wordsRemaining;
@ -735,7 +753,7 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
uint16_t word;
if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
word = GBASavedataReadEEPROM(&memory->savedata);
memory->d.store16(&memory->d, dest, word, 0);
gba->cpu.memory.store16(&gba->cpu, dest, word, 0);
source += sourceOffset;
dest += destOffset;
--wordsRemaining;
@ -743,14 +761,14 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
if (memory->savedata.type == SAVEDATA_NONE) {
GBASavedataInitEEPROM(&memory->savedata);
}
word = memory->d.load16(&memory->d, source, 0);
word = gba->cpu.memory.load16(&gba->cpu, source, 0);
GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
source += sourceOffset;
dest += destOffset;
--wordsRemaining;
} else {
word = memory->d.load16(&memory->d, source, 0);
memory->d.store16(&memory->d, dest, word, 0);
word = gba->cpu.memory.load16(&gba->cpu, source, 0);
gba->cpu.memory.store16(&gba->cpu, dest, word, 0);
source += sourceOffset;
dest += destOffset;
--wordsRemaining;
@ -769,10 +787,10 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
if (info->dstControl == DMA_INCREMENT_RELOAD) {
info->nextDest = info->dest;
}
GBAMemoryScheduleDMA(memory, number, info);
GBAMemoryScheduleDMA(gba, number, info);
}
if (info->doIrq) {
GBARaiseIRQ(memory->p, IRQ_DMA0 + number);
GBARaiseIRQ(gba, IRQ_DMA0 + number);
}
} else {
info->nextDest = dest;
@ -786,7 +804,7 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
memory->dma[i].nextEvent += cycles;
}
}
memory->p->cpu.cycles += cycles;
gba->cpu.cycles += cycles;
}
void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {

View File

@ -106,9 +106,6 @@ struct GBADMA {
};
struct GBAMemory {
struct ARMMemory d;
struct GBA* p;
uint32_t* bios;
uint32_t* wram;
uint32_t* iwram;
@ -136,28 +133,31 @@ struct GBAMemory {
int32_t eventDiff;
};
int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address, int* cycleCounter);
void GBAMemoryInit(struct GBA* gba);
void GBAMemoryDeinit(struct GBA* gba);
void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value, int* cycleCounter);
void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value, int* cycleCounter);
void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cycleCounter);
int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
uint16_t GBALoadU16(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
uint8_t GBALoadU8(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters);
void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter);
void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter);
void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter);
void GBAMemoryWriteDMASAD(struct GBAMemory* memory, int dma, uint32_t address);
void GBAMemoryWriteDMADAD(struct GBAMemory* memory, int dma, uint32_t address);
void GBAMemoryWriteDMACNT_LO(struct GBAMemory* memory, int dma, uint16_t count);
uint16_t GBAMemoryWriteDMACNT_HI(struct GBAMemory* memory, int dma, uint16_t control);
void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters);
void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* info);
void GBAMemoryRunHblankDMAs(struct GBAMemory* memory, int32_t cycles);
void GBAMemoryRunVblankDMAs(struct GBAMemory* memory, int32_t cycles);
void GBAMemoryUpdateDMAs(struct GBAMemory* memory, int32_t cycles);
int32_t GBAMemoryRunDMAs(struct GBAMemory* memory, int32_t cycles);
void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address);
void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address);
void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count);
uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control);
void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info);
void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles);
void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles);
void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles);
int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles);
struct GBASerializedState;
void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state);

View File

@ -52,7 +52,7 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) {
memcpy(gba->cpu.bankedSPSRs, state->cpu.bankedSPSRs, 6 * sizeof(int32_t));
gba->cpu.executionMode = gba->cpu.cpsr.t ? MODE_THUMB : MODE_ARM;
gba->cpu.privilegeMode = gba->cpu.cpsr.priv;
gba->cpu.memory->setActiveRegion(gba->cpu.memory, gba->cpu.gprs[ARM_PC]);
gba->cpu.memory.setActiveRegion(&gba->cpu, gba->cpu.gprs[ARM_PC]);
GBAMemoryDeserialize(&gba->memory, state);
GBAIODeserialize(gba, state);

View File

@ -90,7 +90,7 @@ int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles) {
video->renderer->finishFrame(video->renderer);
}
video->nextVblankIRQ = video->nextEvent + VIDEO_TOTAL_LENGTH;
GBAMemoryRunVblankDMAs(&video->p->memory, lastEvent);
GBAMemoryRunVblankDMAs(video->p, lastEvent);
if (video->vblankIRQ) {
GBARaiseIRQ(video->p, IRQ_VBLANK);
}
@ -123,7 +123,7 @@ int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles) {
video->nextHblankIRQ = video->nextHblank;
if (video->vcount < VIDEO_VERTICAL_PIXELS) {
GBAMemoryRunHblankDMAs(&video->p->memory, lastEvent);
GBAMemoryRunHblankDMAs(video->p, lastEvent);
}
if (video->hblankIRQ) {
GBARaiseIRQ(video->p, IRQ_HBLANK);
@ -207,10 +207,10 @@ void GBAVideoDeserialize(struct GBAVideo* video, struct GBASerializedState* stat
memcpy(video->renderer->vram, state->vram, SIZE_VRAM);
int i;
for (i = 0; i < SIZE_OAM; i += 2) {
GBAStore16(&video->p->memory.d, BASE_OAM | i, state->oam[i >> 1], 0);
GBAStore16(&video->p->cpu, BASE_OAM | i, state->oam[i >> 1], 0);
}
for (i = 0; i < SIZE_PALETTE_RAM; i += 2) {
GBAStore16(&video->p->memory.d, BASE_PALETTE_RAM | i, state->pram[i >> 1], 0);
GBAStore16(&video->p->cpu, BASE_PALETTE_RAM | i, state->pram[i >> 1], 0);
}
union GBARegisterDISPSTAT dispstat;
dispstat.packed = state->io[REG_DISPSTAT >> 1];

View File

@ -91,10 +91,10 @@ static const struct GBACartridgeOverride _overrides[] = {
{ { 0, 0, 0, 0 }, 0, 0 }
};
static void GBAProcessEvents(struct ARMBoard* board);
static void GBAProcessEvents(struct ARMCore* cpu);
static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles);
static void GBAHitStub(struct ARMBoard* board, uint32_t opcode);
static void GBAIllegal(struct ARMBoard* board, uint32_t opcode);
static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode);
static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode);
static void _checkOverrides(struct GBA* gba, uint32_t code);
@ -104,13 +104,8 @@ void GBAInit(struct GBA* gba) {
ARMInit(&gba->cpu);
gba->memory.p = gba;
GBAMemoryInit(&gba->memory);
ARMAssociateMemory(&gba->cpu, &gba->memory.d);
gba->board.p = gba;
GBABoardInit(&gba->board);
ARMAssociateBoard(&gba->cpu, &gba->board.d);
GBAMemoryInit(gba);
GBABoardInit(&gba->cpu.board);
gba->video.p = gba;
GBAVideoInit(&gba->video);
@ -139,23 +134,22 @@ void GBAInit(struct GBA* gba) {
}
void GBADeinit(struct GBA* gba) {
GBAMemoryDeinit(&gba->memory);
GBAMemoryDeinit(gba);
GBAVideoDeinit(&gba->video);
GBAAudioDeinit(&gba->audio);
}
void GBABoardInit(struct GBABoard* board) {
board->d.reset = GBABoardReset;
board->d.processEvents = GBAProcessEvents;
board->d.swi16 = GBASwi16;
board->d.swi32 = GBASwi32;
board->d.hitIllegal = GBAIllegal;
board->d.readCPSR = GBATestIRQ;
board->d.hitStub = GBAHitStub;
void GBABoardInit(struct ARMBoard* board) {
board->reset = GBABoardReset;
board->processEvents = GBAProcessEvents;
board->swi16 = GBASwi16;
board->swi32 = GBASwi32;
board->hitIllegal = GBAIllegal;
board->readCPSR = GBATestIRQ;
board->hitStub = GBAHitStub;
}
void GBABoardReset(struct ARMBoard* board) {
struct ARMCore* cpu = board->cpu;
void GBABoardReset(struct ARMCore* cpu) {
ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->gprs[ARM_SP] = SP_BASE_IRQ;
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
@ -164,50 +158,50 @@ void GBABoardReset(struct ARMBoard* board) {
cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
}
static void GBAProcessEvents(struct ARMBoard* board) {
static void GBAProcessEvents(struct ARMCore* cpu) {
do {
struct GBABoard* gbaBoard = (struct GBABoard*) board;
int32_t cycles = board->cpu->cycles;
struct GBA* gba = (struct GBA*) cpu;
int32_t cycles = cpu->cycles;
int32_t nextEvent = INT_MAX;
int32_t testEvent;
if (gbaBoard->p->springIRQ) {
ARMRaiseIRQ(&gbaBoard->p->cpu);
gbaBoard->p->springIRQ = 0;
if (gba->springIRQ) {
ARMRaiseIRQ(cpu);
gba->springIRQ = 0;
}
testEvent = GBAVideoProcessEvents(&gbaBoard->p->video, cycles);
testEvent = GBAVideoProcessEvents(&gba->video, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;
}
testEvent = GBAAudioProcessEvents(&gbaBoard->p->audio, cycles);
testEvent = GBAAudioProcessEvents(&gba->audio, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;
}
testEvent = GBATimersProcessEvents(gbaBoard->p, cycles);
testEvent = GBATimersProcessEvents(gba, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;
}
testEvent = GBAMemoryRunDMAs(&gbaBoard->p->memory, cycles);
testEvent = GBAMemoryRunDMAs(gba, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;
}
testEvent = GBASIOProcessEvents(&gbaBoard->p->sio, cycles);
testEvent = GBASIOProcessEvents(&gba->sio, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;
}
board->cpu->cycles -= cycles;
board->cpu->nextEvent = nextEvent;
cpu->cycles -= cycles;
cpu->nextEvent = nextEvent;
if (board->cpu->halted) {
board->cpu->cycles = board->cpu->nextEvent;
if (cpu->halted) {
cpu->cycles = cpu->nextEvent;
}
} while (board->cpu->cycles >= board->cpu->nextEvent);
} while (cpu->cycles >= cpu->nextEvent);
}
static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
@ -389,7 +383,7 @@ void GBALoadBIOS(struct GBA* gba, int fd) {
}
gba->biosChecksum = checksum;
if ((gba->cpu.gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) {
gba->memory.d.setActiveRegion(&gba->memory.d, gba->cpu.gprs[ARM_PC]);
gba->cpu.memory.setActiveRegion(&gba->cpu, gba->cpu.gprs[ARM_PC]);
}
// TODO: error check
}
@ -482,9 +476,8 @@ void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) {
}
}
void GBATestIRQ(struct ARMBoard* board) {
struct GBABoard* gbaBoard = (struct GBABoard*) board;
struct GBA* gba = gbaBoard->p;
void GBATestIRQ(struct ARMCore* cpu) {
struct GBA* gba = (struct GBA*) cpu;
if (gba->memory.io[REG_IME >> 1] && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) {
gba->springIRQ = 1;
gba->cpu.nextEvent = 0;
@ -529,9 +522,9 @@ void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
}
void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...) {
struct GBABoard* gbaBoard = 0;
if (debugger->cpu && debugger->cpu->board) {
gbaBoard = (struct GBABoard*) debugger->cpu->board;
struct GBA* gba = 0;
if (debugger->cpu) {
gba = (struct GBA*) debugger->cpu;
}
enum GBALogLevel gbaLevel;
@ -551,26 +544,26 @@ void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel leve
}
va_list args;
va_start(args, format);
_GBAVLog(gbaBoard ? gbaBoard->p : 0, gbaLevel, format, args);
_GBAVLog(gba, gbaLevel, format, args);
va_end(args);
}
void GBAHitStub(struct ARMBoard* board, uint32_t opcode) {
struct GBABoard* gbaBoard = (struct GBABoard*) board;
void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) {
struct GBA* gba = (struct GBA*) cpu;
enum GBALogLevel level = GBA_LOG_FATAL;
if (gbaBoard->p->debugger) {
if (gba->debugger) {
level = GBA_LOG_STUB;
ARMDebuggerEnter(gbaBoard->p->debugger, DEBUGGER_ENTER_ILLEGAL_OP);
ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP);
}
GBALog(gbaBoard->p, level, "Stub opcode: %08x", opcode);
GBALog(gba, level, "Stub opcode: %08x", opcode);
}
void GBAIllegal(struct ARMBoard* board, uint32_t opcode) {
struct GBABoard* gbaBoard = (struct GBABoard*) board;
GBALog(gbaBoard->p, GBA_LOG_WARN, "Illegal opcode: %08x", opcode);
if (gbaBoard->p->debugger) {
ARMDebuggerEnter(gbaBoard->p->debugger, DEBUGGER_ENTER_ILLEGAL_OP);
void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) {
struct GBA* gba = (struct GBA*) cpu;
GBALog(gba, GBA_LOG_WARN, "Illegal opcode: %08x", opcode);
if (gba->debugger) {
ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP);
}
}

View File

@ -64,14 +64,8 @@ struct GBARotationSource;
struct GBA;
typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args);
struct GBABoard {
struct ARMBoard d;
struct GBA* p;
};
struct GBA {
struct ARMCore cpu;
struct GBABoard board;
struct GBAMemory memory;
struct GBAVideo video;
struct GBAAudio audio;
@ -125,11 +119,8 @@ struct GBACartridge {
void GBAInit(struct GBA* gba);
void GBADeinit(struct GBA* gba);
void GBAMemoryInit(struct GBAMemory* memory);
void GBAMemoryDeinit(struct GBAMemory* memory);
void GBABoardInit(struct GBABoard* board);
void GBABoardReset(struct ARMBoard* board);
void GBABoardInit(struct ARMBoard* board);
void GBABoardReset(struct ARMCore* cpu);
void GBATimerUpdateRegister(struct GBA* gba, int timer);
void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t value);
@ -138,7 +129,7 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t value);
void GBAWriteIE(struct GBA* gba, uint16_t value);
void GBAWriteIME(struct GBA* gba, uint16_t value);
void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq);
void GBATestIRQ(struct ARMBoard* board);
void GBATestIRQ(struct ARMCore* cpu);
void GBAHalt(struct GBA* gba);
void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger);