Redo component model/type punning

This commit is contained in:
Jeffrey Pfau 2014-04-20 00:19:55 -07:00
parent c0eb7c81f7
commit 0f68dbc832
17 changed files with 308 additions and 249 deletions

View File

@ -65,9 +65,21 @@ static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode mode) {
} }
void ARMInit(struct ARMCore* cpu) { 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) { void ARMReset(struct ARMCore* cpu) {
int i; int i;
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
@ -101,7 +113,7 @@ void ARMReset(struct ARMCore* cpu) {
cpu->cycles = 0; cpu->cycles = 0;
cpu->nextEvent = 0; cpu->nextEvent = 0;
cpu->board.reset(cpu); cpu->irqh.reset(cpu);
} }
void ARMRaiseIRQ(struct ARMCore* cpu) { void ARMRaiseIRQ(struct ARMCore* cpu) {
@ -264,6 +276,6 @@ void ARMRun(struct ARMCore* cpu) {
ARMStep(cpu); ARMStep(cpu);
} }
if (cpu->cycles >= cpu->nextEvent) { if (cpu->cycles >= cpu->nextEvent) {
cpu->board.processEvents(cpu); cpu->irqh.processEvents(cpu);
} }
} }

View File

@ -99,15 +99,21 @@ struct ARMMemory {
int (*waitMultiple)(struct ARMCore*, uint32_t startAddress, int count); int (*waitMultiple)(struct ARMCore*, uint32_t startAddress, int count);
}; };
struct ARMBoard { struct ARMInterruptHandler {
void (*reset)(struct ARMCore* board); void (*reset)(struct ARMCore* cpu);
void (*processEvents)(struct ARMCore* board); void (*processEvents)(struct ARMCore* cpu);
void (*swi16)(struct ARMCore* board, int immediate); void (*swi16)(struct ARMCore* cpu, int immediate);
void (*swi32)(struct ARMCore* board, int immediate); void (*swi32)(struct ARMCore* cpu, int immediate);
void (*hitIllegal)(struct ARMCore* board, uint32_t opcode); void (*hitIllegal)(struct ARMCore* cpu, uint32_t opcode);
void (*readCPSR)(struct ARMCore* board); 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 { struct ARMCore {
@ -130,15 +136,16 @@ struct ARMCore {
enum PrivilegeMode privilegeMode; enum PrivilegeMode privilegeMode;
struct ARMMemory memory; struct ARMMemory memory;
struct ARMBoard board; struct ARMInterruptHandler irqh;
int64_t absoluteCycles; struct ARMComponent* master;
int32_t lastCycles;
int numComponents;
struct ARMComponent** components;
}; };
void ARMInit(struct ARMCore* cpu); void ARMInit(struct ARMCore* cpu);
void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory); void ARMSetComponents(struct ARMCore* cpu, struct ARMComponent* master, int extra, struct ARMComponent** extras);
void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board);
void ARMReset(struct ARMCore* cpu); void ARMReset(struct ARMCore* cpu);
void ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode); void ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode);

View File

@ -702,7 +702,7 @@ DEFINE_INSTRUCTION_ARM(MSRRI,
mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK; mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK;
cpu->spsr.packed = (cpu->spsr.packed & ~mask) | (operand & 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) \ #define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \
EMITTER ## NAME EMITTER ## NAME

View File

@ -65,8 +65,8 @@
cpu->cycles += 4; \ cpu->cycles += 4; \
} }
#define ARM_STUB cpu->board.hitStub(cpu, opcode) #define ARM_STUB cpu->irqh.hitStub(cpu, opcode)
#define ARM_ILL cpu->board.hitIllegal(cpu, opcode) #define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode)
#define ARM_WRITE_PC \ #define ARM_WRITE_PC \
cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM; \ 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) { static inline void _ARMReadCPSR(struct ARMCore* cpu) {
_ARMSetMode(cpu, cpu->cpsr.t); _ARMSetMode(cpu, cpu->cpsr.t);
ARMSetPrivilegeMode(cpu, cpu->cpsr.priv); ARMSetPrivilegeMode(cpu, cpu->cpsr.priv);
cpu->board.readCPSR(cpu); cpu->irqh.readCPSR(cpu);
} }
#endif #endif

View File

@ -469,7 +469,7 @@ DEFINE_INSTRUCTION_THUMB(BX,
ARM_WRITE_PC; 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) \ #define DECLARE_INSTRUCTION_THUMB(EMITTER, NAME) \
EMITTER ## NAME EMITTER ## NAME

View File

@ -604,6 +604,7 @@ static void _cliDebuggerDeinit(struct ARMDebugger* debugger) {
} }
void CLIDebuggerCreate(struct CLIDebugger* debugger) { void CLIDebuggerCreate(struct CLIDebugger* debugger) {
ARMDebuggerCreate(&debugger->d);
debugger->d.init = _cliDebuggerInit; debugger->d.init = _cliDebuggerInit;
debugger->d.deinit = _cliDebuggerDeinit; debugger->d.deinit = _cliDebuggerDeinit;
debugger->d.paused = _commandLine; debugger->d.paused = _commandLine;

View File

@ -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->cpu = cpu;
debugger->state = DEBUGGER_RUNNING; debugger->state = DEBUGGER_RUNNING;
debugger->breakpoints = 0; debugger->breakpoints = 0;
@ -33,8 +42,8 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
} }
} }
void ARMDebuggerDeinit(struct ARMDebugger* debugger) { void ARMDebuggerDeinit(struct ARMComponent* component) {
// TODO: actually call this struct ARMDebugger* debugger = (struct ARMDebugger*) component;
debugger->deinit(debugger); debugger->deinit(debugger);
} }

View File

@ -40,6 +40,7 @@ enum DebuggerLogLevel {
}; };
struct ARMDebugger { struct ARMDebugger {
struct ARMComponent d;
enum DebuggerState state; enum DebuggerState state;
struct ARMCore* cpu; struct ARMCore* cpu;
@ -55,8 +56,7 @@ struct ARMDebugger {
void (*log)(struct ARMDebugger*, enum DebuggerLogLevel, const char* format, ...); void (*log)(struct ARMDebugger*, enum DebuggerLogLevel, const char* format, ...);
}; };
void ARMDebuggerInit(struct ARMDebugger*, struct ARMCore*); void ARMDebuggerCreate(struct ARMDebugger*);
void ARMDebuggerDeinit(struct ARMDebugger*);
void ARMDebuggerRun(struct ARMDebugger*); void ARMDebuggerRun(struct ARMDebugger*);
void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason); void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason);
void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address); void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address);

View File

@ -420,6 +420,7 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
} }
void GDBStubCreate(struct GDBStub* stub) { void GDBStubCreate(struct GDBStub* stub) {
ARMDebuggerCreate(&stub->d);
stub->socket = -1; stub->socket = -1;
stub->connection = -1; stub->connection = -1;
stub->d.init = 0; stub->d.init = 0;

View File

@ -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 _unRl(struct GBA* gba, uint32_t source, uint8_t* dest);
static void _RegisterRamReset(struct GBA* gba) { static void _RegisterRamReset(struct GBA* gba) {
uint32_t registers = gba->cpu.gprs[0]; uint32_t registers = gba->cpu->gprs[0];
(void)(registers); (void)(registers);
GBALog(gba, GBA_LOG_STUB, "RegisterRamReset unimplemented"); GBALog(gba, GBA_LOG_STUB, "RegisterRamReset unimplemented");
} }
static void _CpuSet(struct GBA* gba) { static void _CpuSet(struct GBA* gba) {
uint32_t source = gba->cpu.gprs[0]; struct ARMCore* cpu = gba->cpu;
uint32_t dest = gba->cpu.gprs[1]; uint32_t source = cpu->gprs[0];
uint32_t mode = gba->cpu.gprs[2]; uint32_t dest = cpu->gprs[1];
uint32_t mode = cpu->gprs[2];
int count = mode & 0x000FFFFF; int count = mode & 0x000FFFFF;
int fill = mode & 0x01000000; int fill = mode & 0x01000000;
int wordsize = (mode & 0x04000000) ? 4 : 2; int wordsize = (mode & 0x04000000) ? 4 : 2;
@ -29,18 +30,18 @@ static void _CpuSet(struct GBA* gba) {
if (wordsize == 4) { if (wordsize == 4) {
source &= 0xFFFFFFFC; source &= 0xFFFFFFFC;
dest &= 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) { for (i = 0; i < count; ++i) {
gba->cpu.memory.store32(&gba->cpu, dest + (i << 2), word, &gba->cpu.cycles); cpu->memory.store32(cpu, dest + (i << 2), word, &cpu->cycles);
gba->cpu.board.processEvents(&gba->cpu); cpu->irqh.processEvents(cpu);
} }
} else { } else {
source &= 0xFFFFFFFE; source &= 0xFFFFFFFE;
dest &= 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) { for (i = 0; i < count; ++i) {
gba->cpu.memory.store16(&gba->cpu, dest + (i << 1), word, &gba->cpu.cycles); cpu->memory.store16(cpu, dest + (i << 1), word, &cpu->cycles);
gba->cpu.board.processEvents(&gba->cpu); cpu->irqh.processEvents(cpu);
} }
} }
} else { } else {
@ -48,68 +49,70 @@ static void _CpuSet(struct GBA* gba) {
source &= 0xFFFFFFFC; source &= 0xFFFFFFFC;
dest &= 0xFFFFFFFC; dest &= 0xFFFFFFFC;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
int32_t word = gba->cpu.memory.load32(&gba->cpu, source + (i << 2), &gba->cpu.cycles); int32_t word = cpu->memory.load32(cpu, source + (i << 2), &cpu->cycles);
gba->cpu.memory.store32(&gba->cpu, dest + (i << 2), word, &gba->cpu.cycles); cpu->memory.store32(cpu, dest + (i << 2), word, &cpu->cycles);
gba->cpu.board.processEvents(&gba->cpu); cpu->irqh.processEvents(cpu);
} }
} else { } else {
source &= 0xFFFFFFFE; source &= 0xFFFFFFFE;
dest &= 0xFFFFFFFE; dest &= 0xFFFFFFFE;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
uint16_t word = gba->cpu.memory.load16(&gba->cpu, source + (i << 1), &gba->cpu.cycles); uint16_t word = cpu->memory.load16(cpu, source + (i << 1), &cpu->cycles);
gba->cpu.memory.store16(&gba->cpu, dest + (i << 1), word, &gba->cpu.cycles); cpu->memory.store16(cpu, dest + (i << 1), word, &cpu->cycles);
gba->cpu.board.processEvents(&gba->cpu); cpu->irqh.processEvents(cpu);
} }
} }
} }
} }
static void _FastCpuSet(struct GBA* gba) { static void _FastCpuSet(struct GBA* gba) {
uint32_t source = gba->cpu.gprs[0] & 0xFFFFFFFC; struct ARMCore* cpu = gba->cpu;
uint32_t dest = gba->cpu.gprs[1] & 0xFFFFFFFC; uint32_t source = cpu->gprs[0] & 0xFFFFFFFC;
uint32_t mode = gba->cpu.gprs[2]; uint32_t dest = cpu->gprs[1] & 0xFFFFFFFC;
uint32_t mode = cpu->gprs[2];
int count = mode & 0x000FFFFF; 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; count = ((count + 7) >> 3) << 3;
int i; int i;
if (mode & 0x01000000) { 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) { for (i = 0; i < count; i += 4) {
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 0) << 2), word, 0); cpu->memory.store32(cpu, dest + ((i + 0) << 2), word, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 1) << 2), word, 0); cpu->memory.store32(cpu, dest + ((i + 1) << 2), word, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 2) << 2), word, 0); cpu->memory.store32(cpu, dest + ((i + 2) << 2), word, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 3) << 2), word, 0); cpu->memory.store32(cpu, dest + ((i + 3) << 2), word, 0);
gba->cpu.cycles += storeCycles; cpu->cycles += storeCycles;
gba->cpu.board.processEvents(&gba->cpu); cpu->irqh.processEvents(cpu);
} }
} else { } 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) { for (i = 0; i < count; i += 4) {
int32_t word0 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 0) << 2), 0); int32_t word0 = cpu->memory.load32(cpu, source + ((i + 0) << 2), 0);
int32_t word1 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 1) << 2), 0); int32_t word1 = cpu->memory.load32(cpu, source + ((i + 1) << 2), 0);
int32_t word2 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 2) << 2), 0); int32_t word2 = cpu->memory.load32(cpu, source + ((i + 2) << 2), 0);
int32_t word3 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 3) << 2), 0); int32_t word3 = cpu->memory.load32(cpu, source + ((i + 3) << 2), 0);
gba->cpu.cycles += loadCycles; cpu->cycles += loadCycles;
gba->cpu.board.processEvents(&gba->cpu); cpu->irqh.processEvents(cpu);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 0) << 2), word0, 0); cpu->memory.store32(cpu, dest + ((i + 0) << 2), word0, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 1) << 2), word1, 0); cpu->memory.store32(cpu, dest + ((i + 1) << 2), word1, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 2) << 2), word2, 0); cpu->memory.store32(cpu, dest + ((i + 2) << 2), word2, 0);
gba->cpu.memory.store32(&gba->cpu, dest + ((i + 3) << 2), word3, 0); cpu->memory.store32(cpu, dest + ((i + 3) << 2), word3, 0);
gba->cpu.cycles += storeCycles; cpu->cycles += storeCycles;
gba->cpu.board.processEvents(&gba->cpu); cpu->irqh.processEvents(cpu);
} }
} }
} }
static void _BgAffineSet(struct GBA* gba) { 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 ox, oy;
float cx, cy; float cx, cy;
float sx, sy; float sx, sy;
float theta; float theta;
int offset = gba->cpu.gprs[0]; int offset = cpu->gprs[0];
int destination = gba->cpu.gprs[1]; int destination = cpu->gprs[1];
int diff = gba->cpu.gprs[3]; int diff = cpu->gprs[3];
(void)(diff); // Are we supposed to use this? (void)(diff); // Are we supposed to use this?
float a, b, c, d; float a, b, c, d;
float rx, ry; 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 ] // [ 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 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 ] // [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ]
ox = gba->cpu.memory.load32(&gba->cpu, offset, 0) / 256.f; ox = cpu->memory.load32(cpu, offset, 0) / 256.f;
oy = gba->cpu.memory.load32(&gba->cpu, offset + 4, 0) / 256.f; oy = cpu->memory.load32(cpu, offset + 4, 0) / 256.f;
cx = gba->cpu.memory.load16(&gba->cpu, offset + 8, 0); cx = cpu->memory.load16(cpu, offset + 8, 0);
cy = gba->cpu.memory.load16(&gba->cpu, offset + 10, 0); cy = cpu->memory.load16(cpu, offset + 10, 0);
sx = gba->cpu.memory.load16(&gba->cpu, offset + 12, 0) / 256.f; sx = cpu->memory.load16(cpu, offset + 12, 0) / 256.f;
sy = gba->cpu.memory.load16(&gba->cpu, offset + 14, 0) / 256.f; sy = cpu->memory.load16(cpu, offset + 14, 0) / 256.f;
theta = (gba->cpu.memory.loadU16(&gba->cpu, offset + 16, 0) >> 8) / 128.f * M_PI; theta = (cpu->memory.loadU16(cpu, offset + 16, 0) >> 8) / 128.f * M_PI;
offset += 20; offset += 20;
// Rotation // Rotation
a = d = cosf(theta); a = d = cosf(theta);
@ -136,30 +139,31 @@ static void _BgAffineSet(struct GBA* gba) {
// Translate // Translate
rx = ox - (a * cx + b * cy); rx = ox - (a * cx + b * cy);
ry = oy - (c * cx + d * cy); ry = oy - (c * cx + d * cy);
gba->cpu.memory.store16(&gba->cpu, destination, a * 256, 0); cpu->memory.store16(cpu, destination, a * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + 2, b * 256, 0); cpu->memory.store16(cpu, destination + 2, b * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + 4, c * 256, 0); cpu->memory.store16(cpu, destination + 4, c * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + 6, d * 256, 0); cpu->memory.store16(cpu, destination + 6, d * 256, 0);
gba->cpu.memory.store32(&gba->cpu, destination + 8, rx * 256, 0); cpu->memory.store32(cpu, destination + 8, rx * 256, 0);
gba->cpu.memory.store32(&gba->cpu, destination + 12, ry * 256, 0); cpu->memory.store32(cpu, destination + 12, ry * 256, 0);
destination += 16; destination += 16;
} }
} }
static void _ObjAffineSet(struct GBA* gba) { 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 sx, sy;
float theta; float theta;
int offset = gba->cpu.gprs[0]; int offset = cpu->gprs[0];
int destination = gba->cpu.gprs[1]; int destination = cpu->gprs[1];
int diff = gba->cpu.gprs[3]; int diff = cpu->gprs[3];
float a, b, c, d; float a, b, c, d;
while (i--) { while (i--) {
// [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ] // [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ]
// [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ] // [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ]
sx = gba->cpu.memory.load16(&gba->cpu, offset, 0) / 256.f; sx = cpu->memory.load16(cpu, offset, 0) / 256.f;
sy = gba->cpu.memory.load16(&gba->cpu, offset + 2, 0) / 256.f; sy = cpu->memory.load16(cpu, offset + 2, 0) / 256.f;
theta = (gba->cpu.memory.loadU16(&gba->cpu, offset + 4, 0) >> 8) / 128.f * M_PI; theta = (cpu->memory.loadU16(cpu, offset + 4, 0) >> 8) / 128.f * M_PI;
offset += 6; offset += 6;
// Rotation // Rotation
a = d = cosf(theta); a = d = cosf(theta);
@ -169,23 +173,24 @@ static void _ObjAffineSet(struct GBA* gba) {
b *= -sx; b *= -sx;
c *= sy; c *= sy;
d *= sy; d *= sy;
gba->cpu.memory.store16(&gba->cpu, destination, a * 256, 0); cpu->memory.store16(cpu, destination, a * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + diff, b * 256, 0); cpu->memory.store16(cpu, destination + diff, b * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + diff * 2, c * 256, 0); cpu->memory.store16(cpu, destination + diff * 2, c * 256, 0);
gba->cpu.memory.store16(&gba->cpu, destination + diff * 3, d * 256, 0); cpu->memory.store16(cpu, destination + diff * 3, d * 256, 0);
destination += diff * 4; destination += diff * 4;
} }
} }
static void _MidiKey2Freq(struct GBA* gba) { static void _MidiKey2Freq(struct GBA* gba) {
uint32_t key = gba->cpu.memory.load32(&gba->cpu, gba->cpu.gprs[0] + 4, 0); struct ARMCore* cpu = gba->cpu;
gba->cpu.gprs[0] = key / powf(2, (180.f - gba->cpu.gprs[1] - gba->cpu.gprs[2] / 256.f) / 12.f); 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) { void GBASwi16(struct ARMCore* cpu, int immediate) {
struct GBA* gba = (struct GBA*) cpu; struct GBA* gba = (struct GBA*) cpu->master;
if (gba->memory.fullBios) { if (gba->memory.fullBios) {
ARMRaiseSWI(&gba->cpu); ARMRaiseSWI(cpu);
return; return;
} }
switch (immediate) { switch (immediate) {
@ -197,39 +202,39 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
break; break;
case 0x05: case 0x05:
// VBlankIntrWait // VBlankIntrWait
gba->cpu.gprs[0] = 1; cpu->gprs[0] = 1;
gba->cpu.gprs[1] = 1; cpu->gprs[1] = 1;
// Fall through: // Fall through:
case 0x04: case 0x04:
// IntrWait // IntrWait
gba->memory.io[REG_IME >> 1] = 1; 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; break;
} }
gba->memory.io[REG_IF >> 1] = 0; gba->memory.io[REG_IF >> 1] = 0;
ARMRaiseSWI(&gba->cpu); ARMRaiseSWI(cpu);
break; break;
case 0x6: case 0x6:
{ {
div_t result = div(gba->cpu.gprs[0], gba->cpu.gprs[1]); div_t result = div(cpu->gprs[0], cpu->gprs[1]);
gba->cpu.gprs[0] = result.quot; cpu->gprs[0] = result.quot;
gba->cpu.gprs[1] = result.rem; cpu->gprs[1] = result.rem;
gba->cpu.gprs[3] = abs(result.quot); cpu->gprs[3] = abs(result.quot);
} }
break; break;
case 0x7: case 0x7:
{ {
div_t result = div(gba->cpu.gprs[1], gba->cpu.gprs[0]); div_t result = div(cpu->gprs[1], cpu->gprs[0]);
gba->cpu.gprs[0] = result.quot; cpu->gprs[0] = result.quot;
gba->cpu.gprs[1] = result.rem; cpu->gprs[1] = result.rem;
gba->cpu.gprs[3] = abs(result.quot); cpu->gprs[3] = abs(result.quot);
} }
break; break;
case 0x8: case 0x8:
gba->cpu.gprs[0] = sqrt(gba->cpu.gprs[0]); cpu->gprs[0] = sqrt(cpu->gprs[0]);
break; break;
case 0xA: 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; break;
case 0xB: case 0xB:
_CpuSet(gba); _CpuSet(gba);
@ -238,7 +243,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
_FastCpuSet(gba); _FastCpuSet(gba);
break; break;
case 0xD: case 0xD:
gba->cpu.gprs[0] = GBAChecksum(gba->memory.bios, SIZE_BIOS); cpu->gprs[0] = GBAChecksum(gba->memory.bios, SIZE_BIOS);
case 0xE: case 0xE:
_BgAffineSet(gba); _BgAffineSet(gba);
break; break;
@ -247,19 +252,19 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
break; break;
case 0x11: case 0x11:
case 0x12: 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"); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 source");
break; break;
} }
switch (gba->cpu.gprs[1] >> BASE_OFFSET) { switch (cpu->gprs[1] >> BASE_OFFSET) {
case REGION_WORKING_RAM: 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; break;
case REGION_WORKING_IRAM: 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; break;
case REGION_VRAM: 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; break;
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 destination"); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 destination");
@ -267,19 +272,19 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
} }
break; break;
case 0x13: 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"); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman source");
break; break;
} }
switch (gba->cpu.gprs[1] >> BASE_OFFSET) { switch (cpu->gprs[1] >> BASE_OFFSET) {
case REGION_WORKING_RAM: 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; break;
case REGION_WORKING_IRAM: 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; break;
case REGION_VRAM: 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; break;
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman destination"); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman destination");
@ -288,19 +293,19 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
break; break;
case 0x14: case 0x14:
case 0x15: 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"); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad RL source");
break; break;
} }
switch (gba->cpu.gprs[1] >> BASE_OFFSET) { switch (cpu->gprs[1] >> BASE_OFFSET) {
case REGION_WORKING_RAM: 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; break;
case REGION_WORKING_IRAM: 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; break;
case REGION_VRAM: 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; break;
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad RL destination"); 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) { 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 // We assume the signature byte (0x10) is correct
int blockheader; int blockheader;
uint32_t sPointer = source + 4; uint32_t sPointer = source + 4;
@ -342,7 +348,7 @@ static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest) {
if (blocksRemaining) { if (blocksRemaining) {
if (blockheader & 0x80) { if (blockheader & 0x80) {
// Compressed // 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; sPointer += 2;
disp = dPointer - (((block & 0x000F) << 8) | ((block & 0xFF00) >> 8)) - 1; disp = dPointer - (((block & 0x000F) << 8) | ((block & 0xFF00) >> 8)) - 1;
bytes = ((block & 0x00F0) >> 4) + 3; bytes = ((block & 0x00F0) >> 4) + 3;
@ -354,22 +360,23 @@ static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest) {
} }
} else { } else {
// Uncompressed // Uncompressed
*dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); *dPointer = cpu->memory.loadU8(cpu, sPointer++, 0);
++dPointer; ++dPointer;
--remaining; --remaining;
} }
blockheader <<= 1; blockheader <<= 1;
--blocksRemaining; --blocksRemaining;
} else { } else {
blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); blockheader = cpu->memory.loadU8(cpu, sPointer++, 0);
blocksRemaining = 8; blocksRemaining = 8;
} }
} }
} }
static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) { static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) {
struct ARMCore* cpu = gba->cpu;
source = source & 0xFFFFFFFC; 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 remaining = header >> 8;
int bits = header & 0xF; int bits = header & 0xF;
if (32 % bits) { if (32 % bits) {
@ -380,7 +387,7 @@ static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) {
remaining &= 0xFFFFFFFC; remaining &= 0xFFFFFFFC;
// We assume the signature byte (0x20) is correct // We assume the signature byte (0x20) is correct
//var tree = []; //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; int block = 0;
uint32_t treeBase = source + 5; uint32_t treeBase = source + 5;
uint32_t sPointer = source + 5 + treesize; 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 bitsRemaining;
int readBits; int readBits;
int bitsSeen = 0; int bitsSeen = 0;
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); node.packed = cpu->memory.load8(cpu, nPointer, 0);
while (remaining > 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; sPointer += 4;
for (bitsRemaining = 32; bitsRemaining > 0; --bitsRemaining, bitstream <<= 1) { for (bitsRemaining = 32; bitsRemaining > 0; --bitsRemaining, bitstream <<= 1) {
uint32_t next = (nPointer & ~1) + node.offset * 2 + 2; uint32_t next = (nPointer & ~1) + node.offset * 2 + 2;
if (bitstream & 0x80000000) { if (bitstream & 0x80000000) {
// Go right // Go right
if (node.rTerm) { if (node.rTerm) {
readBits = gba->cpu.memory.load8(&gba->cpu, next + 1, 0); readBits = cpu->memory.load8(cpu, next + 1, 0);
} else { } else {
nPointer = next + 1; nPointer = next + 1;
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); node.packed = cpu->memory.load8(cpu, nPointer, 0);
continue; continue;
} }
} else { } else {
// Go left // Go left
if (node.lTerm) { if (node.lTerm) {
readBits = gba->cpu.memory.load8(&gba->cpu, next, 0); readBits = cpu->memory.load8(cpu, next, 0);
} else { } else {
nPointer = next; nPointer = next;
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); node.packed = cpu->memory.load8(cpu, nPointer, 0);
continue; continue;
} }
} }
@ -426,7 +433,7 @@ static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) {
block |= (readBits & ((1 << bits) - 1)) << bitsSeen; block |= (readBits & ((1 << bits) - 1)) << bitsSeen;
bitsSeen += bits; bitsSeen += bits;
nPointer = treeBase; nPointer = treeBase;
node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); node.packed = cpu->memory.load8(cpu, nPointer, 0);
if (bitsSeen == 32) { if (bitsSeen == 32) {
bitsSeen = 0; bitsSeen = 0;
*dPointer = block; *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) { static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) {
struct ARMCore* cpu = gba->cpu;
source = source & 0xFFFFFFFC; 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; int padding = (4 - remaining) & 0x3;
// We assume the signature byte (0x30) is correct // We assume the signature byte (0x30) is correct
int blockheader; int blockheader;
@ -452,12 +460,12 @@ static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) {
uint32_t sPointer = source + 4; uint32_t sPointer = source + 4;
uint8_t* dPointer = dest; uint8_t* dPointer = dest;
while (remaining > 0) { while (remaining > 0) {
blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); blockheader = cpu->memory.loadU8(cpu, sPointer++, 0);
if (blockheader & 0x80) { if (blockheader & 0x80) {
// Compressed // Compressed
blockheader &= 0x7F; blockheader &= 0x7F;
blockheader += 3; blockheader += 3;
block = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); block = cpu->memory.loadU8(cpu, sPointer++, 0);
while (blockheader-- && remaining) { while (blockheader-- && remaining) {
--remaining; --remaining;
*dPointer = block; *dPointer = block;
@ -468,7 +476,7 @@ static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) {
blockheader++; blockheader++;
while (blockheader-- && remaining) { while (blockheader-- && remaining) {
--remaining; --remaining;
*dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); *dPointer = cpu->memory.loadU8(cpu, sPointer++, 0);
++dPointer; ++dPointer;
} }
} }

View File

@ -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 }; static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
void GBAMemoryInit(struct GBA* gba) { void GBAMemoryInit(struct GBA* gba) {
gba->cpu.memory.load32 = GBALoad32; struct ARMCore* cpu = gba->cpu;
gba->cpu.memory.load16 = GBALoad16; cpu->memory.load32 = GBALoad32;
gba->cpu.memory.loadU16 = GBALoadU16; cpu->memory.load16 = GBALoad16;
gba->cpu.memory.load8 = GBALoad8; cpu->memory.loadU16 = GBALoadU16;
gba->cpu.memory.loadU8 = GBALoadU8; cpu->memory.load8 = GBALoad8;
gba->cpu.memory.store32 = GBAStore32; cpu->memory.loadU8 = GBALoadU8;
gba->cpu.memory.store16 = GBAStore16; cpu->memory.store32 = GBAStore32;
gba->cpu.memory.store8 = GBAStore8; cpu->memory.store16 = GBAStore16;
cpu->memory.store8 = GBAStore8;
gba->memory.bios = (uint32_t*) hleBios; gba->memory.bios = (uint32_t*) hleBios;
gba->memory.fullBios = 0; gba->memory.fullBios = 0;
@ -69,13 +70,13 @@ void GBAMemoryInit(struct GBA* gba) {
} }
gba->memory.activeRegion = -1; gba->memory.activeRegion = -1;
gba->cpu.memory.activeRegion = 0; cpu->memory.activeRegion = 0;
gba->cpu.memory.activeMask = 0; cpu->memory.activeMask = 0;
gba->cpu.memory.setActiveRegion = GBASetActiveRegion; cpu->memory.setActiveRegion = GBASetActiveRegion;
gba->cpu.memory.activePrefetchCycles32 = 0; cpu->memory.activePrefetchCycles32 = 0;
gba->cpu.memory.activePrefetchCycles16 = 0; cpu->memory.activePrefetchCycles16 = 0;
gba->memory.biosPrefetch = 0; gba->memory.biosPrefetch = 0;
gba->cpu.memory.waitMultiple = GBAWaitMultiple; cpu->memory.waitMultiple = GBAWaitMultiple;
} }
void GBAMemoryDeinit(struct GBA* gba) { void GBAMemoryDeinit(struct GBA* gba) {
@ -85,7 +86,7 @@ void GBAMemoryDeinit(struct GBA* gba) {
} }
static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { 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; struct GBAMemory* memory = &gba->memory;
int newRegion = address >> BASE_OFFSET; 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) { 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; struct GBAMemory* memory = &gba->memory;
uint32_t value = 0; uint32_t value = 0;
int wait = 0; int wait = 0;
@ -185,9 +186,9 @@ int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
if (cpu->executionMode == MODE_ARM) { 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 { } 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; value |= value << 16;
} }
break; 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) { 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; struct GBAMemory* memory = &gba->memory;
uint16_t value = 0; uint16_t value = 0;
int wait = 0; int wait = 0;
@ -267,7 +268,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
break; break;
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); 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; 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) { 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; struct GBAMemory* memory = &gba->memory;
int8_t value = 0; int8_t value = 0;
int wait = 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) { 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; struct GBAMemory* memory = &gba->memory;
int wait = 0; 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) { 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; struct GBAMemory* memory = &gba->memory;
int wait = 0; 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) { 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; struct GBAMemory* memory = &gba->memory;
int wait = 0; 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) { 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; struct GBAMemory* memory = &gba->memory;
int wait = 1 + memory->waitstates32[startAddress >> BASE_OFFSET]; int wait = 1 + memory->waitstates32[startAddress >> BASE_OFFSET];
wait += (1 + memory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1); 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) { void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
struct GBAMemory* memory = &gba->memory; struct GBAMemory* memory = &gba->memory;
struct ARMCore* cpu = gba->cpu;
int sram = parameters & 0x0003; int sram = parameters & 0x0003;
int ws0 = (parameters & 0x000C) >> 2; int ws0 = (parameters & 0x000C) >> 2;
int ws0seq = (parameters & 0x0010) >> 4; 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; memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = 0;
} }
gba->cpu.memory.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion]; cpu->memory.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion];
gba->cpu.memory.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion]; cpu->memory.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion];
gba->cpu.memory.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion]; cpu->memory.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion];
gba->cpu.memory.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion]; cpu->memory.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion];
} }
void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) { 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) { void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
struct ARMCore* cpu = gba->cpu;
switch (info->timing) { switch (info->timing) {
case DMA_TIMING_NOW: case DMA_TIMING_NOW:
info->nextEvent = gba->cpu.cycles; info->nextEvent = cpu->cycles;
GBAMemoryUpdateDMAs(gba, 0); GBAMemoryUpdateDMAs(gba, 0);
break; break;
case DMA_TIMING_HBLANK: 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) { void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
int i; int i;
struct GBAMemory* memory = &gba->memory; struct GBAMemory* memory = &gba->memory;
struct ARMCore* cpu = gba->cpu;
memory->activeDMA = -1; memory->activeDMA = -1;
memory->nextDMA = INT_MAX; memory->nextDMA = INT_MAX;
for (i = 3; i >= 0; --i) { for (i = 3; i >= 0; --i) {
@ -707,13 +711,14 @@ void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
} }
} }
} }
if (memory->nextDMA < gba->cpu.nextEvent) { if (memory->nextDMA < cpu->nextEvent) {
gba->cpu.nextEvent = memory->nextDMA; cpu->nextEvent = memory->nextDMA;
} }
} }
void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) { void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
struct GBAMemory* memory = &gba->memory; struct GBAMemory* memory = &gba->memory;
struct ARMCore* cpu = gba->cpu;
uint32_t width = info->width ? 4 : 2; uint32_t width = info->width ? 4 : 2;
int sourceOffset = DMA_OFFSET[info->srcControl] * width; int sourceOffset = DMA_OFFSET[info->srcControl] * width;
int destOffset = DMA_OFFSET[info->dstControl] * 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) { if (width == 4) {
int32_t word; int32_t word;
word = gba->cpu.memory.load32(&gba->cpu, source, 0); word = cpu->memory.load32(cpu, source, 0);
gba->cpu.memory.store32(&gba->cpu, dest, word, 0); cpu->memory.store32(cpu, dest, word, 0);
source += sourceOffset; source += sourceOffset;
dest += destOffset; dest += destOffset;
--wordsRemaining; --wordsRemaining;
@ -753,7 +758,7 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
uint16_t word; uint16_t word;
if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) { if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
word = GBASavedataReadEEPROM(&memory->savedata); word = GBASavedataReadEEPROM(&memory->savedata);
gba->cpu.memory.store16(&gba->cpu, dest, word, 0); cpu->memory.store16(cpu, dest, word, 0);
source += sourceOffset; source += sourceOffset;
dest += destOffset; dest += destOffset;
--wordsRemaining; --wordsRemaining;
@ -761,14 +766,14 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
if (memory->savedata.type == SAVEDATA_NONE) { if (memory->savedata.type == SAVEDATA_NONE) {
GBASavedataInitEEPROM(&memory->savedata); GBASavedataInitEEPROM(&memory->savedata);
} }
word = gba->cpu.memory.load16(&gba->cpu, source, 0); word = cpu->memory.load16(cpu, source, 0);
GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining); GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
source += sourceOffset; source += sourceOffset;
dest += destOffset; dest += destOffset;
--wordsRemaining; --wordsRemaining;
} else { } else {
word = gba->cpu.memory.load16(&gba->cpu, source, 0); word = cpu->memory.load16(cpu, source, 0);
gba->cpu.memory.store16(&gba->cpu, dest, word, 0); cpu->memory.store16(cpu, dest, word, 0);
source += sourceOffset; source += sourceOffset;
dest += destOffset; dest += destOffset;
--wordsRemaining; --wordsRemaining;
@ -804,7 +809,7 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
memory->dma[i].nextEvent += cycles; memory->dma[i].nextEvent += cycles;
} }
} }
gba->cpu.cycles += cycles; cpu->cycles += cycles;
} }
void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) { void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {

View File

@ -16,13 +16,13 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {
state->id = ((struct GBACartridge*) gba->memory.rom)->id; state->id = ((struct GBACartridge*) gba->memory.rom)->id;
memcpy(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title)); memcpy(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title));
memcpy(state->cpu.gprs, gba->cpu.gprs, sizeof(state->cpu.gprs)); memcpy(state->cpu.gprs, gba->cpu->gprs, sizeof(state->cpu.gprs));
state->cpu.cpsr = gba->cpu.cpsr; state->cpu.cpsr = gba->cpu->cpsr;
state->cpu.spsr = gba->cpu.spsr; state->cpu.spsr = gba->cpu->spsr;
state->cpu.cycles = gba->cpu.cycles; state->cpu.cycles = gba->cpu->cycles;
state->cpu.nextEvent = gba->cpu.nextEvent; state->cpu.nextEvent = gba->cpu->nextEvent;
memcpy(state->cpu.bankedRegisters, gba->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); 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.bankedSPSRs, gba->cpu->bankedSPSRs, 6 * sizeof(int32_t));
GBAMemorySerialize(&gba->memory, state); GBAMemorySerialize(&gba->memory, state);
GBAIOSerialize(gba, 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"); GBALog(gba, GBA_LOG_WARN, "Savestate is for a different game");
return; return;
} }
memcpy(gba->cpu.gprs, state->cpu.gprs, sizeof(gba->cpu.gprs)); memcpy(gba->cpu->gprs, state->cpu.gprs, sizeof(gba->cpu->gprs));
gba->cpu.cpsr = state->cpu.cpsr; gba->cpu->cpsr = state->cpu.cpsr;
gba->cpu.spsr = state->cpu.spsr; gba->cpu->spsr = state->cpu.spsr;
gba->cpu.cycles = state->cpu.cycles; gba->cpu->cycles = state->cpu.cycles;
gba->cpu.nextEvent = state->cpu.nextEvent; gba->cpu->nextEvent = state->cpu.nextEvent;
memcpy(gba->cpu.bankedRegisters, state->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); memcpy(gba->cpu->bankedRegisters, state->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t));
memcpy(gba->cpu.bankedSPSRs, state->cpu.bankedSPSRs, 6 * 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->executionMode = gba->cpu->cpsr.t ? MODE_THUMB : MODE_ARM;
gba->cpu.privilegeMode = gba->cpu.cpsr.priv; gba->cpu->privilegeMode = gba->cpu->cpsr.priv;
gba->cpu.memory.setActiveRegion(&gba->cpu, gba->cpu.gprs[ARM_PC]); gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
GBAMemoryDeserialize(&gba->memory, state); GBAMemoryDeserialize(&gba->memory, state);
GBAIODeserialize(gba, state); GBAIODeserialize(gba, state);

View File

@ -51,9 +51,17 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
#endif #endif
struct GBA gba; struct GBA gba;
struct ARMCore cpu;
struct GBAThread* threadContext = context; struct GBAThread* threadContext = context;
struct ARMComponent* components[1] = {};
int numComponents = 0;
char* savedata = 0; char* savedata = 0;
if (threadContext->debugger) {
components[numComponents] = &threadContext->debugger->d;
++numComponents;
}
#if !defined(_WIN32) && defined(USE_PTHREADS) #if !defined(_WIN32) && defined(USE_PTHREADS)
sigset_t signals; sigset_t signals;
sigemptyset(&signals); sigemptyset(&signals);
@ -61,7 +69,10 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
#endif #endif
gba.logHandler = threadContext->logHandler; gba.logHandler = threadContext->logHandler;
GBAInit(&gba); GBACreate(&gba);
ARMSetComponents(&cpu, &gba.d, numComponents, components);
ARMInit(&cpu);
ARMReset(&cpu);
threadContext->gba = &gba; threadContext->gba = &gba;
gba.sync = &threadContext->sync; gba.sync = &threadContext->sync;
#ifdef USE_PTHREADS #ifdef USE_PTHREADS
@ -124,7 +135,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
} }
} else { } else {
while (threadContext->state == THREAD_RUNNING) { while (threadContext->state == THREAD_RUNNING) {
ARMRun(&gba.cpu); ARMRun(&cpu);
} }
} }
MutexLock(&threadContext->stateMutex); MutexLock(&threadContext->stateMutex);
@ -143,7 +154,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
} }
threadContext->gba = 0; threadContext->gba = 0;
GBADeinit(&gba); GBADestroy(&gba);
ConditionWake(&threadContext->sync.videoFrameAvailableCond); ConditionWake(&threadContext->sync.videoFrameAvailableCond);
ConditionWake(&threadContext->sync.audioRequiredCond); ConditionWake(&threadContext->sync.audioRequiredCond);

View File

@ -37,6 +37,7 @@ struct GBAThread {
// Output // Output
enum ThreadState state; enum ThreadState state;
struct GBA* gba; struct GBA* gba;
struct ARMCore* cpu;
// Input // Input
struct GBAVideoRenderer* renderer; struct GBAVideoRenderer* renderer;

View File

@ -207,10 +207,10 @@ void GBAVideoDeserialize(struct GBAVideo* video, struct GBASerializedState* stat
memcpy(video->renderer->vram, state->vram, SIZE_VRAM); memcpy(video->renderer->vram, state->vram, SIZE_VRAM);
int i; int i;
for (i = 0; i < SIZE_OAM; i += 2) { 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) { 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; union GBARegisterDISPSTAT dispstat;
dispstat.packed = state->io[REG_DISPSTAT >> 1]; dispstat.packed = state->io[REG_DISPSTAT >> 1];

View File

@ -7,11 +7,10 @@
#include "util/memory.h" #include "util/memory.h"
#include "debugger/debugger.h"
#include <sys/stat.h> #include <sys/stat.h>
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000; const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
enum { enum {
SP_BASE_SYSTEM = 0x03FFFF00, SP_BASE_SYSTEM = 0x03FFFF00,
@ -91,6 +90,8 @@ static const struct GBACartridgeOverride _overrides[] = {
{ { 0, 0, 0, 0 }, 0, 0 } { { 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 void GBAProcessEvents(struct ARMCore* cpu);
static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles); static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles);
static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode); 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); 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->debugger = 0;
gba->savefile = 0; gba->savefile = 0;
ARMInit(&gba->cpu); GBAInterruptHandlerInit(&cpu->irqh);
GBAMemoryInit(gba); GBAMemoryInit(gba);
GBABoardInit(&gba->cpu.board);
gba->video.p = gba; gba->video.p = gba;
GBAVideoInit(&gba->video); 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->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL;
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS); gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
ARMReset(&gba->cpu);
} }
void GBADeinit(struct GBA* gba) { void GBADestroy(struct GBA* gba) {
GBAMemoryDeinit(gba); GBAMemoryDeinit(gba);
GBAVideoDeinit(&gba->video); GBAVideoDeinit(&gba->video);
GBAAudioDeinit(&gba->audio); GBAAudioDeinit(&gba->audio);
} }
void GBABoardInit(struct ARMBoard* board) { void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) {
board->reset = GBABoardReset; irqh->reset = GBAReset;
board->processEvents = GBAProcessEvents; irqh->processEvents = GBAProcessEvents;
board->swi16 = GBASwi16; irqh->swi16 = GBASwi16;
board->swi32 = GBASwi32; irqh->swi32 = GBASwi32;
board->hitIllegal = GBAIllegal; irqh->hitIllegal = GBAIllegal;
board->readCPSR = GBATestIRQ; irqh->readCPSR = GBATestIRQ;
board->hitStub = GBAHitStub; irqh->hitStub = GBAHitStub;
} }
void GBABoardReset(struct ARMCore* cpu) { void GBAReset(struct ARMCore* cpu) {
ARMSetPrivilegeMode(cpu, MODE_IRQ); ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->gprs[ARM_SP] = SP_BASE_IRQ; cpu->gprs[ARM_SP] = SP_BASE_IRQ;
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR); ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
@ -160,7 +164,7 @@ void GBABoardReset(struct ARMCore* cpu) {
static void GBAProcessEvents(struct ARMCore* cpu) { static void GBAProcessEvents(struct ARMCore* cpu) {
do { do {
struct GBA* gba = (struct GBA*) cpu; struct GBA* gba = (struct GBA*) cpu->master;
int32_t cycles = cpu->cycles; int32_t cycles = cpu->cycles;
int32_t nextEvent = INT_MAX; int32_t nextEvent = INT_MAX;
int32_t testEvent; 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) { void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) {
ARMDebuggerInit(debugger, &gba->cpu);
gba->debugger = debugger; gba->debugger = debugger;
} }
void GBADetachDebugger(struct GBA* gba) { void GBADetachDebugger(struct GBA* gba) {
ARMDebuggerDeinit(gba->debugger);
gba->debugger = 0; gba->debugger = 0;
} }
@ -382,8 +384,8 @@ void GBALoadBIOS(struct GBA* gba, int fd) {
GBALog(gba, GBA_LOG_WARN, "BIOS checksum incorrect"); GBALog(gba, GBA_LOG_WARN, "BIOS checksum incorrect");
} }
gba->biosChecksum = checksum; gba->biosChecksum = checksum;
if ((gba->cpu.gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) { if ((gba->cpu->gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) {
gba->cpu.memory.setActiveRegion(&gba->cpu, gba->cpu.gprs[ARM_PC]); gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
} }
// TODO: error check // TODO: error check
} }
@ -391,7 +393,7 @@ void GBALoadBIOS(struct GBA* gba, int fd) {
void GBATimerUpdateRegister(struct GBA* gba, int timer) { void GBATimerUpdateRegister(struct GBA* gba, int timer) {
struct GBATimer* currentTimer = &gba->timers[timer]; struct GBATimer* currentTimer = &gba->timers[timer];
if (currentTimer->enable && !currentTimer->countUp) { 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); currentTimer->enable = !!(control & 0x0080);
if (!wasEnabled && currentTimer->enable) { if (!wasEnabled && currentTimer->enable) {
if (!currentTimer->countUp) { if (!currentTimer->countUp) {
currentTimer->nextEvent = gba->cpu.cycles + currentTimer->overflowInterval; currentTimer->nextEvent = gba->cpu->cycles + currentTimer->overflowInterval;
} else { } else {
currentTimer->nextEvent = INT_MAX; currentTimer->nextEvent = INT_MAX;
} }
@ -434,7 +436,7 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
gba->timersEnabled |= 1 << timer; gba->timersEnabled |= 1 << timer;
} else if (wasEnabled && !currentTimer->enable) { } else if (wasEnabled && !currentTimer->enable) {
if (!currentTimer->countUp) { 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); gba->timersEnabled &= ~(1 << timer);
} else if (currentTimer->prescaleBits != oldPrescale && !currentTimer->countUp) { } 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; currentTimer->nextEvent = currentTimer->lastEvent + currentTimer->overflowInterval;
} }
if (currentTimer->nextEvent < gba->cpu.nextEvent) { if (currentTimer->nextEvent < gba->cpu->nextEvent) {
gba->cpu.nextEvent = currentTimer->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]) { 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) { void GBAWriteIME(struct GBA* gba, uint16_t value) {
if (value && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { 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) { void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) {
gba->memory.io[REG_IF >> 1] |= 1 << 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)) { 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) { 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]) { if (gba->memory.io[REG_IME >> 1] && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) {
gba->springIRQ = 1; gba->springIRQ = 1;
gba->cpu.nextEvent = 0; gba->cpu->nextEvent = 0;
} }
} }
void GBAHalt(struct GBA* gba) { void GBAHalt(struct GBA* gba) {
gba->cpu.nextEvent = 0; gba->cpu->nextEvent = 0;
gba->cpu.halted = 1; gba->cpu->halted = 1;
} }
static void _GBAVLog(struct GBA* gba, enum GBALogLevel level, const char* format, va_list args) { 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, ...) { void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...) {
struct GBA* gba = 0; struct GBA* gba = 0;
if (debugger->cpu) { if (debugger->cpu) {
gba = (struct GBA*) debugger->cpu; gba = (struct GBA*) debugger->cpu->master;
} }
enum GBALogLevel gbaLevel; enum GBALogLevel gbaLevel;
@ -560,7 +562,7 @@ void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) {
} }
void GBAIllegal(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); GBALog(gba, GBA_LOG_WARN, "Illegal opcode: %08x", opcode);
if (gba->debugger) { if (gba->debugger) {
ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP); ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP);

View File

@ -65,7 +65,9 @@ struct GBA;
typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args); typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args);
struct GBA { struct GBA {
struct ARMCore cpu; struct ARMComponent d;
struct ARMCore* cpu;
struct GBAMemory memory; struct GBAMemory memory;
struct GBAVideo video; struct GBAVideo video;
struct GBAAudio audio; struct GBAAudio audio;
@ -116,11 +118,11 @@ struct GBACartridge {
// And ROM data... // And ROM data...
}; };
void GBAInit(struct GBA* gba); void GBACreate(struct GBA* gba);
void GBADeinit(struct GBA* gba); void GBADestroy(struct GBA* gba);
void GBABoardInit(struct ARMBoard* board); void GBABInterruptHandlerInit(struct ARMInterruptHandler* board);
void GBABoardReset(struct ARMCore* cpu); void GBAReset(struct ARMCore* cpu);
void GBATimerUpdateRegister(struct GBA* gba, int timer); void GBATimerUpdateRegister(struct GBA* gba, int timer);
void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t value); void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t value);