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,8 +65,20 @@ 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;
@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

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->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);
}

View File

@ -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);

View File

@ -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;

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 _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;
}
}

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 };
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) {

View File

@ -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);

View File

@ -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);

View File

@ -37,6 +37,7 @@ struct GBAThread {
// Output
enum ThreadState state;
struct GBA* gba;
struct ARMCore* cpu;
// Input
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);
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];

View File

@ -7,11 +7,10 @@
#include "util/memory.h"
#include "debugger/debugger.h"
#include <sys/stat.h>
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);

View File

@ -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);