mirror of https://github.com/mgba-emu/mgba.git
Redo component model/type punning
This commit is contained in:
parent
c0eb7c81f7
commit
0f68dbc832
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue