From 0f68dbc832db31915d31a6e13438e566083dfb42 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 20 Apr 2014 00:19:55 -0700 Subject: [PATCH] Redo component model/type punning --- src/arm/arm.c | 18 ++- src/arm/arm.h | 33 +++-- src/arm/isa-arm.c | 2 +- src/arm/isa-inlines.h | 6 +- src/arm/isa-thumb.c | 2 +- src/debugger/cli-debugger.c | 1 + src/debugger/debugger.c | 15 ++- src/debugger/debugger.h | 4 +- src/debugger/gdb-stub.c | 1 + src/gba/gba-bios.c | 246 +++++++++++++++++++----------------- src/gba/gba-memory.c | 83 ++++++------ src/gba/gba-serialize.c | 34 ++--- src/gba/gba-thread.c | 17 ++- src/gba/gba-thread.h | 1 + src/gba/gba-video.c | 4 +- src/gba/gba.c | 78 ++++++------ src/gba/gba.h | 12 +- 17 files changed, 308 insertions(+), 249 deletions(-) diff --git a/src/arm/arm.c b/src/arm/arm.c index c39391a50..ccd46cb95 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -65,9 +65,21 @@ static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode mode) { } void ARMInit(struct ARMCore* cpu) { - // TODO: Remove + cpu->master->init(cpu, cpu->master); + int i; + for (i = 0; i < cpu->numComponents; ++i) { + cpu->components[i]->init(cpu, cpu->components[i]); + } } +void ARMSetComponents(struct ARMCore* cpu, struct ARMComponent* master, int extra, struct ARMComponent** extras) { + // TODO: Call init/deinit + cpu->master = master; + cpu->numComponents = extra; + cpu->components = extras; +} + + void ARMReset(struct ARMCore* cpu) { int i; for (i = 0; i < 16; ++i) { @@ -101,7 +113,7 @@ void ARMReset(struct ARMCore* cpu) { cpu->cycles = 0; cpu->nextEvent = 0; - cpu->board.reset(cpu); + cpu->irqh.reset(cpu); } void ARMRaiseIRQ(struct ARMCore* cpu) { @@ -264,6 +276,6 @@ void ARMRun(struct ARMCore* cpu) { ARMStep(cpu); } if (cpu->cycles >= cpu->nextEvent) { - cpu->board.processEvents(cpu); + cpu->irqh.processEvents(cpu); } } diff --git a/src/arm/arm.h b/src/arm/arm.h index 522508f82..b7a2b787a 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -99,15 +99,21 @@ struct ARMMemory { int (*waitMultiple)(struct ARMCore*, uint32_t startAddress, int count); }; -struct ARMBoard { - 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); +struct ARMInterruptHandler { + void (*reset)(struct ARMCore* cpu); + void (*processEvents)(struct ARMCore* cpu); + void (*swi16)(struct ARMCore* cpu, int immediate); + void (*swi32)(struct ARMCore* cpu, int immediate); + void (*hitIllegal)(struct ARMCore* cpu, uint32_t opcode); + void (*readCPSR)(struct ARMCore* cpu); - void (*hitStub)(struct ARMCore* board, uint32_t opcode); + void (*hitStub)(struct ARMCore* cpu, uint32_t opcode); +}; + +struct ARMComponent { + long id; + void (*init)(struct ARMCore* cpu, struct ARMComponent* component); + void (*deinit)(struct ARMComponent* component); }; struct ARMCore { @@ -130,15 +136,16 @@ struct ARMCore { enum PrivilegeMode privilegeMode; struct ARMMemory memory; - struct ARMBoard board; + struct ARMInterruptHandler irqh; - int64_t absoluteCycles; - int32_t lastCycles; + struct ARMComponent* master; + + int numComponents; + struct ARMComponent** components; }; void ARMInit(struct ARMCore* cpu); -void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory); -void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board); +void ARMSetComponents(struct ARMCore* cpu, struct ARMComponent* master, int extra, struct ARMComponent** extras); void ARMReset(struct ARMCore* cpu); void ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode); diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index bdeaab590..01fe3579b 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -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, opcode & 0xFFFFFF)) +DEFINE_INSTRUCTION_ARM(SWI, cpu->irqh.swi32(cpu, opcode & 0xFFFFFF)) #define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \ EMITTER ## NAME diff --git a/src/arm/isa-inlines.h b/src/arm/isa-inlines.h index c7c80570b..6d28d789c 100644 --- a/src/arm/isa-inlines.h +++ b/src/arm/isa-inlines.h @@ -65,8 +65,8 @@ cpu->cycles += 4; \ } -#define ARM_STUB cpu->board.hitStub(cpu, opcode) -#define ARM_ILL cpu->board.hitIllegal(cpu, opcode) +#define ARM_STUB cpu->irqh.hitStub(cpu, opcode) +#define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode) #define ARM_WRITE_PC \ cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM; \ @@ -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); + cpu->irqh.readCPSR(cpu); } #endif diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index 6ded2969a..282a2c772 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -469,7 +469,7 @@ DEFINE_INSTRUCTION_THUMB(BX, ARM_WRITE_PC; }) -DEFINE_INSTRUCTION_THUMB(SWI, cpu->board.swi16(cpu, opcode & 0xFF)) +DEFINE_INSTRUCTION_THUMB(SWI, cpu->irqh.swi16(cpu, opcode & 0xFF)) #define DECLARE_INSTRUCTION_THUMB(EMITTER, NAME) \ EMITTER ## NAME diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index 42f5c7e73..6accda46b 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -604,6 +604,7 @@ static void _cliDebuggerDeinit(struct ARMDebugger* debugger) { } void CLIDebuggerCreate(struct CLIDebugger* debugger) { + ARMDebuggerCreate(&debugger->d); debugger->d.init = _cliDebuggerInit; debugger->d.deinit = _cliDebuggerDeinit; debugger->d.paused = _commandLine; diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 68c56f261..e412f3f50 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -21,7 +21,16 @@ static void _checkBreakpoints(struct ARMDebugger* debugger) { } } -void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) { +static void ARMDebuggerInit(struct ARMCore*, struct ARMComponent*); +static void ARMDebuggerDeinit(struct ARMComponent*); + +void ARMDebuggerCreate(struct ARMDebugger* debugger) { + debugger->d.init = ARMDebuggerInit; + debugger->d.deinit = ARMDebuggerDeinit; +} + +void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) { + struct ARMDebugger* debugger = (struct ARMDebugger*) component; debugger->cpu = cpu; debugger->state = DEBUGGER_RUNNING; debugger->breakpoints = 0; @@ -33,8 +42,8 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) { } } -void ARMDebuggerDeinit(struct ARMDebugger* debugger) { - // TODO: actually call this +void ARMDebuggerDeinit(struct ARMComponent* component) { + struct ARMDebugger* debugger = (struct ARMDebugger*) component; debugger->deinit(debugger); } diff --git a/src/debugger/debugger.h b/src/debugger/debugger.h index 68801df63..15d62683c 100644 --- a/src/debugger/debugger.h +++ b/src/debugger/debugger.h @@ -40,6 +40,7 @@ enum DebuggerLogLevel { }; struct ARMDebugger { + struct ARMComponent d; enum DebuggerState state; struct ARMCore* cpu; @@ -55,8 +56,7 @@ struct ARMDebugger { void (*log)(struct ARMDebugger*, enum DebuggerLogLevel, const char* format, ...); }; -void ARMDebuggerInit(struct ARMDebugger*, struct ARMCore*); -void ARMDebuggerDeinit(struct ARMDebugger*); +void ARMDebuggerCreate(struct ARMDebugger*); void ARMDebuggerRun(struct ARMDebugger*); void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason); void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address); diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index 6b85837f9..5688086ac 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -420,6 +420,7 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) { } void GDBStubCreate(struct GDBStub* stub) { + ARMDebuggerCreate(&stub->d); stub->socket = -1; stub->connection = -1; stub->d.init = 0; diff --git a/src/gba/gba-bios.c b/src/gba/gba-bios.c index 58d706415..934abe746 100644 --- a/src/gba/gba-bios.c +++ b/src/gba/gba-bios.c @@ -12,15 +12,16 @@ 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]; + uint32_t registers = gba->cpu->gprs[0]; (void)(registers); GBALog(gba, GBA_LOG_STUB, "RegisterRamReset unimplemented"); } static void _CpuSet(struct GBA* gba) { - uint32_t source = gba->cpu.gprs[0]; - uint32_t dest = gba->cpu.gprs[1]; - uint32_t mode = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + uint32_t source = cpu->gprs[0]; + uint32_t dest = cpu->gprs[1]; + uint32_t mode = cpu->gprs[2]; int count = mode & 0x000FFFFF; int fill = mode & 0x01000000; int wordsize = (mode & 0x04000000) ? 4 : 2; @@ -29,18 +30,18 @@ static void _CpuSet(struct GBA* gba) { if (wordsize == 4) { source &= 0xFFFFFFFC; dest &= 0xFFFFFFFC; - int32_t word = gba->cpu.memory.load32(&gba->cpu, source, &gba->cpu.cycles); + int32_t word = cpu->memory.load32(cpu, source, &cpu->cycles); for (i = 0; i < count; ++i) { - gba->cpu.memory.store32(&gba->cpu, dest + (i << 2), word, &gba->cpu.cycles); - gba->cpu.board.processEvents(&gba->cpu); + cpu->memory.store32(cpu, dest + (i << 2), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } else { source &= 0xFFFFFFFE; dest &= 0xFFFFFFFE; - uint16_t word = gba->cpu.memory.load16(&gba->cpu, source, &gba->cpu.cycles); + uint16_t word = cpu->memory.load16(cpu, source, &cpu->cycles); for (i = 0; i < count; ++i) { - gba->cpu.memory.store16(&gba->cpu, dest + (i << 1), word, &gba->cpu.cycles); - gba->cpu.board.processEvents(&gba->cpu); + cpu->memory.store16(cpu, dest + (i << 1), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } } else { @@ -48,68 +49,70 @@ static void _CpuSet(struct GBA* gba) { source &= 0xFFFFFFFC; dest &= 0xFFFFFFFC; for (i = 0; i < count; ++i) { - 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); + int32_t word = cpu->memory.load32(cpu, source + (i << 2), &cpu->cycles); + cpu->memory.store32(cpu, dest + (i << 2), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } else { source &= 0xFFFFFFFE; dest &= 0xFFFFFFFE; for (i = 0; i < count; ++i) { - 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); + uint16_t word = cpu->memory.load16(cpu, source + (i << 1), &cpu->cycles); + cpu->memory.store16(cpu, dest + (i << 1), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } } } static void _FastCpuSet(struct GBA* gba) { - uint32_t source = gba->cpu.gprs[0] & 0xFFFFFFFC; - uint32_t dest = gba->cpu.gprs[1] & 0xFFFFFFFC; - uint32_t mode = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + uint32_t source = cpu->gprs[0] & 0xFFFFFFFC; + uint32_t dest = cpu->gprs[1] & 0xFFFFFFFC; + uint32_t mode = cpu->gprs[2]; int count = mode & 0x000FFFFF; - int storeCycles = gba->cpu.memory.waitMultiple(&gba->cpu, dest, 4); + int storeCycles = cpu->memory.waitMultiple(cpu, dest, 4); count = ((count + 7) >> 3) << 3; int i; if (mode & 0x01000000) { - int32_t word = gba->cpu.memory.load32(&gba->cpu, source, &gba->cpu.cycles); + int32_t word = cpu->memory.load32(cpu, source, &cpu->cycles); for (i = 0; i < count; i += 4) { - 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->cpu.board.processEvents(&gba->cpu); + cpu->memory.store32(cpu, dest + ((i + 0) << 2), word, 0); + cpu->memory.store32(cpu, dest + ((i + 1) << 2), word, 0); + cpu->memory.store32(cpu, dest + ((i + 2) << 2), word, 0); + cpu->memory.store32(cpu, dest + ((i + 3) << 2), word, 0); + cpu->cycles += storeCycles; + cpu->irqh.processEvents(cpu); } } else { - int loadCycles = gba->cpu.memory.waitMultiple(&gba->cpu, source, 4); + int loadCycles = cpu->memory.waitMultiple(cpu, source, 4); for (i = 0; i < count; i += 4) { - 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->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->cpu.board.processEvents(&gba->cpu); + int32_t word0 = cpu->memory.load32(cpu, source + ((i + 0) << 2), 0); + int32_t word1 = cpu->memory.load32(cpu, source + ((i + 1) << 2), 0); + int32_t word2 = cpu->memory.load32(cpu, source + ((i + 2) << 2), 0); + int32_t word3 = cpu->memory.load32(cpu, source + ((i + 3) << 2), 0); + cpu->cycles += loadCycles; + cpu->irqh.processEvents(cpu); + cpu->memory.store32(cpu, dest + ((i + 0) << 2), word0, 0); + cpu->memory.store32(cpu, dest + ((i + 1) << 2), word1, 0); + cpu->memory.store32(cpu, dest + ((i + 2) << 2), word2, 0); + cpu->memory.store32(cpu, dest + ((i + 3) << 2), word3, 0); + cpu->cycles += storeCycles; + cpu->irqh.processEvents(cpu); } } } static void _BgAffineSet(struct GBA* gba) { - int i = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + int i = cpu->gprs[2]; float ox, oy; float cx, cy; float sx, sy; float theta; - int offset = gba->cpu.gprs[0]; - int destination = gba->cpu.gprs[1]; - int diff = gba->cpu.gprs[3]; + int offset = cpu->gprs[0]; + int destination = cpu->gprs[1]; + int diff = cpu->gprs[3]; (void)(diff); // Are we supposed to use this? float a, b, c, d; float rx, ry; @@ -117,13 +120,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->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; + ox = cpu->memory.load32(cpu, offset, 0) / 256.f; + oy = cpu->memory.load32(cpu, offset + 4, 0) / 256.f; + cx = cpu->memory.load16(cpu, offset + 8, 0); + cy = cpu->memory.load16(cpu, offset + 10, 0); + sx = cpu->memory.load16(cpu, offset + 12, 0) / 256.f; + sy = cpu->memory.load16(cpu, offset + 14, 0) / 256.f; + theta = (cpu->memory.loadU16(cpu, offset + 16, 0) >> 8) / 128.f * M_PI; offset += 20; // Rotation a = d = cosf(theta); @@ -136,30 +139,31 @@ static void _BgAffineSet(struct GBA* gba) { // Translate rx = ox - (a * cx + b * cy); ry = oy - (c * cx + d * cy); - 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); + cpu->memory.store16(cpu, destination, a * 256, 0); + cpu->memory.store16(cpu, destination + 2, b * 256, 0); + cpu->memory.store16(cpu, destination + 4, c * 256, 0); + cpu->memory.store16(cpu, destination + 6, d * 256, 0); + cpu->memory.store32(cpu, destination + 8, rx * 256, 0); + cpu->memory.store32(cpu, destination + 12, ry * 256, 0); destination += 16; } } static void _ObjAffineSet(struct GBA* gba) { - int i = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + int i = cpu->gprs[2]; float sx, sy; float theta; - int offset = gba->cpu.gprs[0]; - int destination = gba->cpu.gprs[1]; - int diff = gba->cpu.gprs[3]; + int offset = cpu->gprs[0]; + int destination = cpu->gprs[1]; + int diff = cpu->gprs[3]; float a, b, c, d; while (i--) { // [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ] // [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ] - 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; + sx = cpu->memory.load16(cpu, offset, 0) / 256.f; + sy = cpu->memory.load16(cpu, offset + 2, 0) / 256.f; + theta = (cpu->memory.loadU16(cpu, offset + 4, 0) >> 8) / 128.f * M_PI; offset += 6; // Rotation a = d = cosf(theta); @@ -169,23 +173,24 @@ static void _ObjAffineSet(struct GBA* gba) { b *= -sx; c *= sy; d *= sy; - 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); + cpu->memory.store16(cpu, destination, a * 256, 0); + cpu->memory.store16(cpu, destination + diff, b * 256, 0); + cpu->memory.store16(cpu, destination + diff * 2, c * 256, 0); + cpu->memory.store16(cpu, destination + diff * 3, d * 256, 0); destination += diff * 4; } } static void _MidiKey2Freq(struct GBA* gba) { - 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); + struct ARMCore* cpu = gba->cpu; + uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0); + cpu->gprs[0] = key / powf(2, (180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); } void GBASwi16(struct ARMCore* cpu, int immediate) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; if (gba->memory.fullBios) { - ARMRaiseSWI(&gba->cpu); + ARMRaiseSWI(cpu); return; } switch (immediate) { @@ -197,39 +202,39 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { break; case 0x05: // VBlankIntrWait - gba->cpu.gprs[0] = 1; - gba->cpu.gprs[1] = 1; + cpu->gprs[0] = 1; + cpu->gprs[1] = 1; // Fall through: case 0x04: // IntrWait gba->memory.io[REG_IME >> 1] = 1; - if (!gba->cpu.gprs[0] && gba->memory.io[REG_IF >> 1] & gba->cpu.gprs[1]) { + if (!cpu->gprs[0] && gba->memory.io[REG_IF >> 1] & cpu->gprs[1]) { break; } gba->memory.io[REG_IF >> 1] = 0; - ARMRaiseSWI(&gba->cpu); + ARMRaiseSWI(cpu); break; case 0x6: { - div_t result = div(gba->cpu.gprs[0], gba->cpu.gprs[1]); - gba->cpu.gprs[0] = result.quot; - gba->cpu.gprs[1] = result.rem; - gba->cpu.gprs[3] = abs(result.quot); + div_t result = div(cpu->gprs[0], cpu->gprs[1]); + cpu->gprs[0] = result.quot; + cpu->gprs[1] = result.rem; + cpu->gprs[3] = abs(result.quot); } break; case 0x7: { - div_t result = div(gba->cpu.gprs[1], gba->cpu.gprs[0]); - gba->cpu.gprs[0] = result.quot; - gba->cpu.gprs[1] = result.rem; - gba->cpu.gprs[3] = abs(result.quot); + div_t result = div(cpu->gprs[1], cpu->gprs[0]); + cpu->gprs[0] = result.quot; + cpu->gprs[1] = result.rem; + cpu->gprs[3] = abs(result.quot); } break; case 0x8: - gba->cpu.gprs[0] = sqrt(gba->cpu.gprs[0]); + cpu->gprs[0] = sqrt(cpu->gprs[0]); break; case 0xA: - gba->cpu.gprs[0] = atan2f(gba->cpu.gprs[1] / 16384.f, gba->cpu.gprs[0] / 16384.f) / (2 * M_PI) * 0x10000; + cpu->gprs[0] = atan2f(cpu->gprs[1] / 16384.f, cpu->gprs[0] / 16384.f) / (2 * M_PI) * 0x10000; break; case 0xB: _CpuSet(gba); @@ -238,7 +243,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { _FastCpuSet(gba); break; case 0xD: - gba->cpu.gprs[0] = GBAChecksum(gba->memory.bios, SIZE_BIOS); + cpu->gprs[0] = GBAChecksum(gba->memory.bios, SIZE_BIOS); case 0xE: _BgAffineSet(gba); break; @@ -247,19 +252,19 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { break; case 0x11: case 0x12: - if (gba->cpu.gprs[0] < BASE_WORKING_RAM) { + if (cpu->gprs[0] < BASE_WORKING_RAM) { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 source"); break; } - switch (gba->cpu.gprs[1] >> BASE_OFFSET) { + switch (cpu->gprs[1] >> BASE_OFFSET) { case REGION_WORKING_RAM: - _unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]); + _unLz77(gba, cpu->gprs[0], &((uint8_t*) gba->memory.wram)[(cpu->gprs[1] & (SIZE_WORKING_RAM - 1))]); break; case REGION_WORKING_IRAM: - _unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]); + _unLz77(gba, cpu->gprs[0], &((uint8_t*) gba->memory.iwram)[(cpu->gprs[1] & (SIZE_WORKING_IRAM - 1))]); break; case REGION_VRAM: - _unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]); + _unLz77(gba, cpu->gprs[0], &((uint8_t*) gba->video.renderer->vram)[(cpu->gprs[1] & 0x0001FFFF)]); break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 destination"); @@ -267,19 +272,19 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { } break; case 0x13: - if (gba->cpu.gprs[0] < BASE_WORKING_RAM) { + if (cpu->gprs[0] < BASE_WORKING_RAM) { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman source"); break; } - switch (gba->cpu.gprs[1] >> BASE_OFFSET) { + switch (cpu->gprs[1] >> BASE_OFFSET) { case REGION_WORKING_RAM: - _unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 3)) >> 2]); + _unHuffman(gba, cpu->gprs[0], &((uint32_t*) gba->memory.wram)[(cpu->gprs[1] & (SIZE_WORKING_RAM - 3)) >> 2]); break; case REGION_WORKING_IRAM: - _unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 3)) >> 2]); + _unHuffman(gba, cpu->gprs[0], &((uint32_t*) gba->memory.iwram)[(cpu->gprs[1] & (SIZE_WORKING_IRAM - 3)) >> 2]); break; case REGION_VRAM: - _unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFC) >> 2]); + _unHuffman(gba, cpu->gprs[0], &((uint32_t*) gba->video.renderer->vram)[(cpu->gprs[1] & 0x0001FFFC) >> 2]); break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman destination"); @@ -288,19 +293,19 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { break; case 0x14: case 0x15: - if (gba->cpu.gprs[0] < BASE_WORKING_RAM) { + if (cpu->gprs[0] < BASE_WORKING_RAM) { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad RL source"); break; } - switch (gba->cpu.gprs[1] >> BASE_OFFSET) { + switch (cpu->gprs[1] >> BASE_OFFSET) { case REGION_WORKING_RAM: - _unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]); + _unRl(gba, cpu->gprs[0], &((uint8_t*) gba->memory.wram)[(cpu->gprs[1] & (SIZE_WORKING_RAM - 1))]); break; case REGION_WORKING_IRAM: - _unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]); + _unRl(gba, cpu->gprs[0], &((uint8_t*) gba->memory.iwram)[(cpu->gprs[1] & (SIZE_WORKING_IRAM - 1))]); break; case REGION_VRAM: - _unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]); + _unRl(gba, cpu->gprs[0], &((uint8_t*) gba->video.renderer->vram)[(cpu->gprs[1] & 0x0001FFFF)]); break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad RL destination"); @@ -329,7 +334,8 @@ uint32_t GBAChecksum(uint32_t* memory, size_t size) { } static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest) { - int remaining = (gba->cpu.memory.load32(&gba->cpu, source, 0) & 0xFFFFFF00) >> 8; + struct ARMCore* cpu = gba->cpu; + int remaining = (cpu->memory.load32(cpu, source, 0) & 0xFFFFFF00) >> 8; // We assume the signature byte (0x10) is correct int blockheader; uint32_t sPointer = source + 4; @@ -342,7 +348,7 @@ static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest) { if (blocksRemaining) { if (blockheader & 0x80) { // Compressed - block = gba->cpu.memory.loadU8(&gba->cpu, sPointer, 0) | (gba->cpu.memory.loadU8(&gba->cpu, sPointer + 1, 0) << 8); + block = cpu->memory.loadU8(cpu, sPointer, 0) | (cpu->memory.loadU8(cpu, sPointer + 1, 0) << 8); sPointer += 2; disp = dPointer - (((block & 0x000F) << 8) | ((block & 0xFF00) >> 8)) - 1; bytes = ((block & 0x00F0) >> 4) + 3; @@ -354,22 +360,23 @@ static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest) { } } else { // Uncompressed - *dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + *dPointer = cpu->memory.loadU8(cpu, sPointer++, 0); ++dPointer; --remaining; } blockheader <<= 1; --blocksRemaining; } else { - blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + blockheader = cpu->memory.loadU8(cpu, sPointer++, 0); blocksRemaining = 8; } } } static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) { + struct ARMCore* cpu = gba->cpu; source = source & 0xFFFFFFFC; - uint32_t header = gba->cpu.memory.load32(&gba->cpu, source, 0); + uint32_t header = cpu->memory.load32(cpu, source, 0); int remaining = header >> 8; int bits = header & 0xF; if (32 % bits) { @@ -380,7 +387,7 @@ static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) { remaining &= 0xFFFFFFFC; // We assume the signature byte (0x20) is correct //var tree = []; - int treesize = (gba->cpu.memory.loadU8(&gba->cpu, source + 4, 0) << 1) + 1; + int treesize = (cpu->memory.loadU8(cpu, source + 4, 0) << 1) + 1; int block = 0; uint32_t treeBase = source + 5; uint32_t sPointer = source + 5 + treesize; @@ -397,28 +404,28 @@ static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) { int bitsRemaining; int readBits; int bitsSeen = 0; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); while (remaining > 0) { - uint32_t bitstream = gba->cpu.memory.load32(&gba->cpu, sPointer, 0); + uint32_t bitstream = cpu->memory.load32(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 = gba->cpu.memory.load8(&gba->cpu, next + 1, 0); + readBits = cpu->memory.load8(cpu, next + 1, 0); } else { nPointer = next + 1; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); continue; } } else { // Go left if (node.lTerm) { - readBits = gba->cpu.memory.load8(&gba->cpu, next, 0); + readBits = cpu->memory.load8(cpu, next, 0); } else { nPointer = next; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); continue; } } @@ -426,7 +433,7 @@ static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) { block |= (readBits & ((1 << bits) - 1)) << bitsSeen; bitsSeen += bits; nPointer = treeBase; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); if (bitsSeen == 32) { bitsSeen = 0; *dPointer = block; @@ -443,8 +450,9 @@ static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) { } static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) { + struct ARMCore* cpu = gba->cpu; source = source & 0xFFFFFFFC; - int remaining = (gba->cpu.memory.load32(&gba->cpu, source, 0) & 0xFFFFFF00) >> 8; + int remaining = (cpu->memory.load32(cpu, source, 0) & 0xFFFFFF00) >> 8; int padding = (4 - remaining) & 0x3; // We assume the signature byte (0x30) is correct int blockheader; @@ -452,12 +460,12 @@ static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) { uint32_t sPointer = source + 4; uint8_t* dPointer = dest; while (remaining > 0) { - blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + blockheader = cpu->memory.loadU8(cpu, sPointer++, 0); if (blockheader & 0x80) { // Compressed blockheader &= 0x7F; blockheader += 3; - block = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + block = cpu->memory.loadU8(cpu, sPointer++, 0); while (blockheader-- && remaining) { --remaining; *dPointer = block; @@ -468,7 +476,7 @@ static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) { blockheader++; while (blockheader-- && remaining) { --remaining; - *dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + *dPointer = cpu->memory.loadU8(cpu, sPointer++, 0); ++dPointer; } } diff --git a/src/gba/gba-memory.c b/src/gba/gba-memory.c index aa5349a27..ed6784ba4 100644 --- a/src/gba/gba-memory.c +++ b/src/gba/gba-memory.c @@ -19,14 +19,15 @@ 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 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; + struct ARMCore* cpu = gba->cpu; + cpu->memory.load32 = GBALoad32; + cpu->memory.load16 = GBALoad16; + cpu->memory.loadU16 = GBALoadU16; + cpu->memory.load8 = GBALoad8; + cpu->memory.loadU8 = GBALoadU8; + cpu->memory.store32 = GBAStore32; + cpu->memory.store16 = GBAStore16; + cpu->memory.store8 = GBAStore8; gba->memory.bios = (uint32_t*) hleBios; gba->memory.fullBios = 0; @@ -69,13 +70,13 @@ void GBAMemoryInit(struct GBA* gba) { } 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; + cpu->memory.activeRegion = 0; + cpu->memory.activeMask = 0; + cpu->memory.setActiveRegion = GBASetActiveRegion; + cpu->memory.activePrefetchCycles32 = 0; + cpu->memory.activePrefetchCycles16 = 0; gba->memory.biosPrefetch = 0; - gba->cpu.memory.waitMultiple = GBAWaitMultiple; + cpu->memory.waitMultiple = GBAWaitMultiple; } void GBAMemoryDeinit(struct GBA* gba) { @@ -85,7 +86,7 @@ void GBAMemoryDeinit(struct GBA* gba) { } static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int newRegion = address >> BASE_OFFSET; @@ -131,7 +132,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { } int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; uint32_t value = 0; int wait = 0; @@ -185,9 +186,9 @@ int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { default: 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); + value = cpu->memory.load32(cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0); } else { - value = cpu->memory.load16(&gba->cpu, cpu->currentPC + WORD_SIZE_THUMB * 2, 0); + value = cpu->memory.load16(cpu, cpu->currentPC + WORD_SIZE_THUMB * 2, 0); value |= value << 16; } break; @@ -207,7 +208,7 @@ uint16_t GBALoadU16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; uint16_t value = 0; int wait = 0; @@ -267,7 +268,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; default: 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); + value = cpu->memory.load16(cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0); break; } @@ -284,7 +285,7 @@ uint8_t GBALoadU8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int8_t value = 0; int wait = 0; @@ -356,7 +357,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 0; @@ -404,7 +405,7 @@ void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle } void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 0; @@ -461,7 +462,7 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle } void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 0; @@ -521,7 +522,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo } static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 1 + memory->waitstates32[startAddress >> BASE_OFFSET]; wait += (1 + memory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1); @@ -530,6 +531,7 @@ static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) { struct GBAMemory* memory = &gba->memory; + struct ARMCore* cpu = gba->cpu; int sram = parameters & 0x0003; int ws0 = (parameters & 0x000C) >> 2; int ws0seq = (parameters & 0x0010) >> 4; @@ -578,10 +580,10 @@ void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) { memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = 0; } - 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]; + 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]; } void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) { @@ -620,9 +622,10 @@ uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) { }; void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) { + struct ARMCore* cpu = gba->cpu; switch (info->timing) { case DMA_TIMING_NOW: - info->nextEvent = gba->cpu.cycles; + info->nextEvent = cpu->cycles; GBAMemoryUpdateDMAs(gba, 0); break; case DMA_TIMING_HBLANK: @@ -695,6 +698,7 @@ int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) { void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) { int i; struct GBAMemory* memory = &gba->memory; + struct ARMCore* cpu = gba->cpu; memory->activeDMA = -1; memory->nextDMA = INT_MAX; for (i = 3; i >= 0; --i) { @@ -707,13 +711,14 @@ void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) { } } } - if (memory->nextDMA < gba->cpu.nextEvent) { - gba->cpu.nextEvent = memory->nextDMA; + if (memory->nextDMA < cpu->nextEvent) { + cpu->nextEvent = memory->nextDMA; } } void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) { struct GBAMemory* memory = &gba->memory; + struct ARMCore* cpu = gba->cpu; uint32_t width = info->width ? 4 : 2; int sourceOffset = DMA_OFFSET[info->srcControl] * width; int destOffset = DMA_OFFSET[info->dstControl] * width; @@ -744,8 +749,8 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) { if (width == 4) { int32_t word; - word = gba->cpu.memory.load32(&gba->cpu, source, 0); - gba->cpu.memory.store32(&gba->cpu, dest, word, 0); + word = cpu->memory.load32(cpu, source, 0); + cpu->memory.store32(cpu, dest, word, 0); source += sourceOffset; dest += destOffset; --wordsRemaining; @@ -753,7 +758,7 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) { uint16_t word; if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) { word = GBASavedataReadEEPROM(&memory->savedata); - gba->cpu.memory.store16(&gba->cpu, dest, word, 0); + cpu->memory.store16(cpu, dest, word, 0); source += sourceOffset; dest += destOffset; --wordsRemaining; @@ -761,14 +766,14 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) { if (memory->savedata.type == SAVEDATA_NONE) { GBASavedataInitEEPROM(&memory->savedata); } - word = gba->cpu.memory.load16(&gba->cpu, source, 0); + word = cpu->memory.load16(cpu, source, 0); GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining); source += sourceOffset; dest += destOffset; --wordsRemaining; } else { - word = gba->cpu.memory.load16(&gba->cpu, source, 0); - gba->cpu.memory.store16(&gba->cpu, dest, word, 0); + word = cpu->memory.load16(cpu, source, 0); + cpu->memory.store16(cpu, dest, word, 0); source += sourceOffset; dest += destOffset; --wordsRemaining; @@ -804,7 +809,7 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) { memory->dma[i].nextEvent += cycles; } } - gba->cpu.cycles += cycles; + cpu->cycles += cycles; } void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) { diff --git a/src/gba/gba-serialize.c b/src/gba/gba-serialize.c index 91bab32e0..e2f8124ac 100644 --- a/src/gba/gba-serialize.c +++ b/src/gba/gba-serialize.c @@ -16,13 +16,13 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) { state->id = ((struct GBACartridge*) gba->memory.rom)->id; memcpy(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title)); - memcpy(state->cpu.gprs, gba->cpu.gprs, sizeof(state->cpu.gprs)); - state->cpu.cpsr = gba->cpu.cpsr; - state->cpu.spsr = gba->cpu.spsr; - state->cpu.cycles = gba->cpu.cycles; - state->cpu.nextEvent = gba->cpu.nextEvent; - memcpy(state->cpu.bankedRegisters, gba->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); - memcpy(state->cpu.bankedSPSRs, gba->cpu.bankedSPSRs, 6 * sizeof(int32_t)); + memcpy(state->cpu.gprs, gba->cpu->gprs, sizeof(state->cpu.gprs)); + state->cpu.cpsr = gba->cpu->cpsr; + state->cpu.spsr = gba->cpu->spsr; + state->cpu.cycles = gba->cpu->cycles; + state->cpu.nextEvent = gba->cpu->nextEvent; + memcpy(state->cpu.bankedRegisters, gba->cpu->bankedRegisters, 6 * 7 * sizeof(int32_t)); + memcpy(state->cpu.bankedSPSRs, gba->cpu->bankedSPSRs, 6 * sizeof(int32_t)); GBAMemorySerialize(&gba->memory, state); GBAIOSerialize(gba, state); @@ -43,16 +43,16 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) { GBALog(gba, GBA_LOG_WARN, "Savestate is for a different game"); return; } - memcpy(gba->cpu.gprs, state->cpu.gprs, sizeof(gba->cpu.gprs)); - gba->cpu.cpsr = state->cpu.cpsr; - gba->cpu.spsr = state->cpu.spsr; - gba->cpu.cycles = state->cpu.cycles; - gba->cpu.nextEvent = state->cpu.nextEvent; - memcpy(gba->cpu.bankedRegisters, state->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); - 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, gba->cpu.gprs[ARM_PC]); + memcpy(gba->cpu->gprs, state->cpu.gprs, sizeof(gba->cpu->gprs)); + gba->cpu->cpsr = state->cpu.cpsr; + gba->cpu->spsr = state->cpu.spsr; + gba->cpu->cycles = state->cpu.cycles; + gba->cpu->nextEvent = state->cpu.nextEvent; + memcpy(gba->cpu->bankedRegisters, state->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); + 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, gba->cpu->gprs[ARM_PC]); GBAMemoryDeserialize(&gba->memory, state); GBAIODeserialize(gba, state); diff --git a/src/gba/gba-thread.c b/src/gba/gba-thread.c index d5f7fb098..ab109b879 100644 --- a/src/gba/gba-thread.c +++ b/src/gba/gba-thread.c @@ -51,9 +51,17 @@ static THREAD_ENTRY _GBAThreadRun(void* context) { #endif struct GBA gba; + struct ARMCore cpu; struct GBAThread* threadContext = context; + struct ARMComponent* components[1] = {}; + int numComponents = 0; char* savedata = 0; + if (threadContext->debugger) { + components[numComponents] = &threadContext->debugger->d; + ++numComponents; + } + #if !defined(_WIN32) && defined(USE_PTHREADS) sigset_t signals; sigemptyset(&signals); @@ -61,7 +69,10 @@ static THREAD_ENTRY _GBAThreadRun(void* context) { #endif gba.logHandler = threadContext->logHandler; - GBAInit(&gba); + GBACreate(&gba); + ARMSetComponents(&cpu, &gba.d, numComponents, components); + ARMInit(&cpu); + ARMReset(&cpu); threadContext->gba = &gba; gba.sync = &threadContext->sync; #ifdef USE_PTHREADS @@ -124,7 +135,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) { } } else { while (threadContext->state == THREAD_RUNNING) { - ARMRun(&gba.cpu); + ARMRun(&cpu); } } MutexLock(&threadContext->stateMutex); @@ -143,7 +154,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) { } threadContext->gba = 0; - GBADeinit(&gba); + GBADestroy(&gba); ConditionWake(&threadContext->sync.videoFrameAvailableCond); ConditionWake(&threadContext->sync.audioRequiredCond); diff --git a/src/gba/gba-thread.h b/src/gba/gba-thread.h index d772aae55..5d630e5fd 100644 --- a/src/gba/gba-thread.h +++ b/src/gba/gba-thread.h @@ -37,6 +37,7 @@ struct GBAThread { // Output enum ThreadState state; struct GBA* gba; + struct ARMCore* cpu; // Input struct GBAVideoRenderer* renderer; diff --git a/src/gba/gba-video.c b/src/gba/gba-video.c index e0f676efc..ba018225a 100644 --- a/src/gba/gba-video.c +++ b/src/gba/gba-video.c @@ -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->cpu, 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->cpu, 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]; diff --git a/src/gba/gba.c b/src/gba/gba.c index 446f3f9aa..51d6417f2 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -7,11 +7,10 @@ #include "util/memory.h" -#include "debugger/debugger.h" - #include const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000; +const uint32_t GBA_COMPONENT_MAGIC = 0x1000000; enum { SP_BASE_SYSTEM = 0x03FFFF00, @@ -91,6 +90,8 @@ static const struct GBACartridgeOverride _overrides[] = { { { 0, 0, 0, 0 }, 0, 0 } }; +static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component); +static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh); static void GBAProcessEvents(struct ARMCore* cpu); static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles); static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode); @@ -98,14 +99,19 @@ static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode); static void _checkOverrides(struct GBA* gba, uint32_t code); -void GBAInit(struct GBA* gba) { +void GBACreate(struct GBA* gba) { + gba->d.id = GBA_COMPONENT_MAGIC; + gba->d.init = GBAInit; +} + +static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component) { + struct GBA* gba = (struct GBA*) component; + gba->cpu = cpu; gba->debugger = 0; gba->savefile = 0; - ARMInit(&gba->cpu); - + GBAInterruptHandlerInit(&cpu->irqh); GBAMemoryInit(gba); - GBABoardInit(&gba->cpu.board); gba->video.p = gba; GBAVideoInit(&gba->video); @@ -129,27 +135,25 @@ void GBAInit(struct GBA* gba) { gba->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL; gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS); - - ARMReset(&gba->cpu); } -void GBADeinit(struct GBA* gba) { +void GBADestroy(struct GBA* gba) { GBAMemoryDeinit(gba); GBAVideoDeinit(&gba->video); GBAAudioDeinit(&gba->audio); } -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 GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) { + irqh->reset = GBAReset; + irqh->processEvents = GBAProcessEvents; + irqh->swi16 = GBASwi16; + irqh->swi32 = GBASwi32; + irqh->hitIllegal = GBAIllegal; + irqh->readCPSR = GBATestIRQ; + irqh->hitStub = GBAHitStub; } -void GBABoardReset(struct ARMCore* cpu) { +void GBAReset(struct ARMCore* cpu) { ARMSetPrivilegeMode(cpu, MODE_IRQ); cpu->gprs[ARM_SP] = SP_BASE_IRQ; ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR); @@ -160,7 +164,7 @@ void GBABoardReset(struct ARMCore* cpu) { static void GBAProcessEvents(struct ARMCore* cpu) { do { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; int32_t cycles = cpu->cycles; int32_t nextEvent = INT_MAX; int32_t testEvent; @@ -346,12 +350,10 @@ static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) { } void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) { - ARMDebuggerInit(debugger, &gba->cpu); gba->debugger = debugger; } void GBADetachDebugger(struct GBA* gba) { - ARMDebuggerDeinit(gba->debugger); gba->debugger = 0; } @@ -382,8 +384,8 @@ void GBALoadBIOS(struct GBA* gba, int fd) { GBALog(gba, GBA_LOG_WARN, "BIOS checksum incorrect"); } gba->biosChecksum = checksum; - if ((gba->cpu.gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) { - gba->cpu.memory.setActiveRegion(&gba->cpu, gba->cpu.gprs[ARM_PC]); + if ((gba->cpu->gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) { + gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); } // TODO: error check } @@ -391,7 +393,7 @@ void GBALoadBIOS(struct GBA* gba, int fd) { void GBATimerUpdateRegister(struct GBA* gba, int timer) { struct GBATimer* currentTimer = &gba->timers[timer]; if (currentTimer->enable && !currentTimer->countUp) { - gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu.cycles - currentTimer->lastEvent) >> currentTimer->prescaleBits); + gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu->cycles - currentTimer->lastEvent) >> currentTimer->prescaleBits); } } @@ -425,7 +427,7 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) { currentTimer->enable = !!(control & 0x0080); if (!wasEnabled && currentTimer->enable) { if (!currentTimer->countUp) { - currentTimer->nextEvent = gba->cpu.cycles + currentTimer->overflowInterval; + currentTimer->nextEvent = gba->cpu->cycles + currentTimer->overflowInterval; } else { currentTimer->nextEvent = INT_MAX; } @@ -434,7 +436,7 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) { gba->timersEnabled |= 1 << timer; } else if (wasEnabled && !currentTimer->enable) { if (!currentTimer->countUp) { - gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu.cycles - currentTimer->lastEvent) >> oldPrescale); + gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu->cycles - currentTimer->lastEvent) >> oldPrescale); } gba->timersEnabled &= ~(1 << timer); } else if (currentTimer->prescaleBits != oldPrescale && !currentTimer->countUp) { @@ -442,8 +444,8 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) { currentTimer->nextEvent = currentTimer->lastEvent + currentTimer->overflowInterval; } - if (currentTimer->nextEvent < gba->cpu.nextEvent) { - gba->cpu.nextEvent = currentTimer->nextEvent; + if (currentTimer->nextEvent < gba->cpu->nextEvent) { + gba->cpu->nextEvent = currentTimer->nextEvent; } }; @@ -457,36 +459,36 @@ void GBAWriteIE(struct GBA* gba, uint16_t value) { } if (gba->memory.io[REG_IME >> 1] && value & gba->memory.io[REG_IF >> 1]) { - ARMRaiseIRQ(&gba->cpu); + ARMRaiseIRQ(gba->cpu); } } void GBAWriteIME(struct GBA* gba, uint16_t value) { if (value && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { - ARMRaiseIRQ(&gba->cpu); + ARMRaiseIRQ(gba->cpu); } } void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) { gba->memory.io[REG_IF >> 1] |= 1 << irq; - gba->cpu.halted = 0; + gba->cpu->halted = 0; if (gba->memory.io[REG_IME >> 1] && (gba->memory.io[REG_IE >> 1] & 1 << irq)) { - ARMRaiseIRQ(&gba->cpu); + ARMRaiseIRQ(gba->cpu); } } void GBATestIRQ(struct ARMCore* cpu) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; 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; + gba->cpu->nextEvent = 0; } } void GBAHalt(struct GBA* gba) { - gba->cpu.nextEvent = 0; - gba->cpu.halted = 1; + gba->cpu->nextEvent = 0; + gba->cpu->halted = 1; } static void _GBAVLog(struct GBA* gba, enum GBALogLevel level, const char* format, va_list args) { @@ -524,7 +526,7 @@ void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) { void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...) { struct GBA* gba = 0; if (debugger->cpu) { - gba = (struct GBA*) debugger->cpu; + gba = (struct GBA*) debugger->cpu->master; } enum GBALogLevel gbaLevel; @@ -560,7 +562,7 @@ void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) { } void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; GBALog(gba, GBA_LOG_WARN, "Illegal opcode: %08x", opcode); if (gba->debugger) { ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP); diff --git a/src/gba/gba.h b/src/gba/gba.h index ec403c54d..fb346cca0 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -65,7 +65,9 @@ struct GBA; typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args); struct GBA { - struct ARMCore cpu; + struct ARMComponent d; + + struct ARMCore* cpu; struct GBAMemory memory; struct GBAVideo video; struct GBAAudio audio; @@ -116,11 +118,11 @@ struct GBACartridge { // And ROM data... }; -void GBAInit(struct GBA* gba); -void GBADeinit(struct GBA* gba); +void GBACreate(struct GBA* gba); +void GBADestroy(struct GBA* gba); -void GBABoardInit(struct ARMBoard* board); -void GBABoardReset(struct ARMCore* cpu); +void GBABInterruptHandlerInit(struct ARMInterruptHandler* board); +void GBAReset(struct ARMCore* cpu); void GBATimerUpdateRegister(struct GBA* gba, int timer); void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t value);