all repos — mgba @ c037dada3e13727bb41ce807fe9a6caa8fd4cf95

mGBA Game Boy Advance Emulator

DS: Share code between cores
Jeffrey Pfau jeffrey@endrift.com
Tue, 03 Jan 2017 13:58:54 -0800
commit

c037dada3e13727bb41ce807fe9a6caa8fd4cf95

parent

2359a4e88689fd23f5cf2ef57f7aa38055158b52

M include/mgba/internal/ds/ds.hinclude/mgba/internal/ds/ds.h

@@ -54,21 +54,27 @@ struct mDebugger;

mLOG_DECLARE_CATEGORY(DS); +struct DSCommon { + struct DS* p; + + struct ARMCore* cpu; + struct GBATimer timers[4]; + struct mTiming timing; + int springIRQ; + + struct DSCoreMemory memory; + struct DSCommon* ipc; +}; + struct DS { struct mCPUComponent d; - struct ARMCore* arm7; - struct ARMCore* arm9; + struct DSCommon ds7; + struct DSCommon ds9; struct DSMemory memory; struct DSVideo video; - int timersEnabled7; - int timersEnabled9; - struct GBATimer timers7[4]; - struct GBATimer timers9[4]; struct mCoreSync* sync; - struct mTiming timing7; - struct mTiming timing9; struct mTimingEvent slice; struct ARMCore* activeCpu; uint32_t sliceStart;

@@ -76,8 +82,6 @@ int32_t cycleDrift;

struct ARMDebugger* debugger; - int springIRQ7; - int springIRQ9; bool cpuBlocked; bool earlyExit;
M include/mgba/internal/ds/io.hinclude/mgba/internal/ds/io.h

@@ -12,61 +12,70 @@ CXX_GUARD_START

#include <mgba/core/log.h> +enum DSIORegisters { + // DMA + DS_REG_DMA0SAD_LO = 0x0B0, + DS_REG_DMA0SAD_HI = 0x0B2, + DS_REG_DMA0DAD_LO = 0x0B4, + DS_REG_DMA0DAD_HI = 0x0B6, + DS_REG_DMA0CNT_LO = 0x0B8, + DS_REG_DMA0CNT_HI = 0x0BA, + DS_REG_DMA1SAD_LO = 0x0BC, + DS_REG_DMA1SAD_HI = 0x0BE, + DS_REG_DMA1DAD_LO = 0x0C0, + DS_REG_DMA1DAD_HI = 0x0C2, + DS_REG_DMA1CNT_LO = 0x0C4, + DS_REG_DMA1CNT_HI = 0x0C6, + DS_REG_DMA2SAD_LO = 0x0C8, + DS_REG_DMA2SAD_HI = 0x0CA, + DS_REG_DMA2DAD_LO = 0x0CC, + DS_REG_DMA2DAD_HI = 0x0CE, + DS_REG_DMA2CNT_LO = 0x0D0, + DS_REG_DMA2CNT_HI = 0x0D2, + DS_REG_DMA3SAD_LO = 0x0D4, + DS_REG_DMA3SAD_HI = 0x0D6, + DS_REG_DMA3DAD_LO = 0x0D8, + DS_REG_DMA3DAD_HI = 0x0DA, + DS_REG_DMA3CNT_LO = 0x0DC, + DS_REG_DMA3CNT_HI = 0x0DE, + + // Timers + DS_REG_TM0CNT_LO = 0x100, + DS_REG_TM0CNT_HI = 0x102, + DS_REG_TM1CNT_LO = 0x104, + DS_REG_TM1CNT_HI = 0x106, + DS_REG_TM2CNT_LO = 0x108, + DS_REG_TM2CNT_HI = 0x10A, + DS_REG_TM3CNT_LO = 0x10C, + DS_REG_TM3CNT_HI = 0x10E, + + // IPC + DS_REG_IPCSYNC = 0x180, + DS_REG_IPCFIFOCNT = 0x182, + DS_REG_IPCFIFOSEND_LO = 0x184, + DS_REG_IPCFIFOSEND_HI = 0x186, + DS_REG_IPCFIFORECV_LO = 0x100000, + DS_REG_IPCFIFORECV_HI = 0x100002, + + // Interrupts + DS_REG_IME = 0x208, + DS_REG_IE_LO = 0x210, + DS_REG_IE_HI = 0x212, + DS_REG_IF_LO = 0x214, + DS_REG_IF_HI = 0x216, +}; + enum DS7IORegisters { // Video DS7_REG_DISPSTAT = 0x004, DS7_REG_VCOUNT = 0x006, - // DMA - DS7_REG_DISPSTAT_REG_DMA0SAD_LO = 0x0B0, - DS7_REG_DISPSTAT_REG_DMA0SAD_HI = 0x0B2, - DS7_REG_DISPSTAT_REG_DMA0DAD_LO = 0x0B4, - DS7_REG_DISPSTAT_REG_DMA0DAD_HI = 0x0B6, - DS7_REG_DISPSTAT_REG_DMA0CNT_LO = 0x0B8, - DS7_REG_DISPSTAT_REG_DMA0CNT_HI = 0x0BA, - DS7_REG_DISPSTAT_REG_DMA1SAD_LO = 0x0BC, - DS7_REG_DISPSTAT_REG_DMA1SAD_HI = 0x0BE, - DS7_REG_DISPSTAT_REG_DMA1DAD_LO = 0x0C0, - DS7_REG_DISPSTAT_REG_DMA1DAD_HI = 0x0C2, - DS7_REG_DISPSTAT_REG_DMA1CNT_LO = 0x0C4, - DS7_REG_DISPSTAT_REG_DMA1CNT_HI = 0x0C6, - DS7_REG_DISPSTAT_REG_DMA2SAD_LO = 0x0C8, - DS7_REG_DISPSTAT_REG_DMA2SAD_HI = 0x0CA, - DS7_REG_DISPSTAT_REG_DMA2DAD_LO = 0x0CC, - DS7_REG_DISPSTAT_REG_DMA2DAD_HI = 0x0CE, - DS7_REG_DISPSTAT_REG_DMA2CNT_LO = 0x0D0, - DS7_REG_DISPSTAT_REG_DMA2CNT_HI = 0x0D2, - DS7_REG_DISPSTAT_REG_DMA3SAD_LO = 0x0D4, - DS7_REG_DISPSTAT_REG_DMA3SAD_HI = 0x0D6, - DS7_REG_DISPSTAT_REG_DMA3DAD_LO = 0x0D8, - DS7_REG_DISPSTAT_REG_DMA3DAD_HI = 0x0DA, - DS7_REG_DISPSTAT_REG_DMA3CNT_LO = 0x0DC, - DS7_REG_DISPSTAT_REG_DMA3CNT_HI = 0x0DE, - - // Timers - DS7_REG_TM0CNT_LO = 0x100, - DS7_REG_TM0CNT_HI = 0x102, - DS7_REG_TM1CNT_LO = 0x104, - DS7_REG_TM1CNT_HI = 0x106, - DS7_REG_TM2CNT_LO = 0x108, - DS7_REG_TM2CNT_HI = 0x10A, - DS7_REG_TM3CNT_LO = 0x10C, - DS7_REG_TM3CNT_HI = 0x10E, - // Keypad DS7_REG_KEYINPUT = 0x130, DS7_REG_KEYCNT = 0x132, DS7_REG_EXTKEYIN = 0x136, DS7_REG_RTC = 0x138, - // IPC - DS7_REG_IPCSYNC = 0x180, - DS7_REG_IPCFIFOCNT = 0x182, - DS7_REG_IPCFIFOSEND_LO = 0x184, - DS7_REG_IPCFIFOSEND_HI = 0x186, - DS7_REG_IPCFIFORECV_LO = 0x100000, - DS7_REG_IPCFIFORECV_HI = 0x100002, - // Game card DS7_REG_AUXSPICNT = 0x1A0, DS7_REG_AUXSPIDATA = 0x1A2,

@@ -85,13 +94,8 @@ DS7_REG_SLOT1DATA_1 = 0x100011,

DS7_REG_SLOT1DATA_2 = 0x100012, DS7_REG_SLOT1DATA_3 = 0x100013, - // Interrupts, etc + // Etc DS7_REG_EXMEMSTAT = 0x204, - DS7_REG_IME = 0x208, - DS7_REG_IE_LO = 0x210, - DS7_REG_IE_HI = 0x212, - DS7_REG_IF_LO = 0x214, - DS7_REG_IF_HI = 0x216, // Memory control DS7_REG_VRAMSTAT = 0x240,

@@ -198,62 +202,10 @@ DS9_REG_B_BLDALPHA = 0x1052,

DS9_REG_B_BLDY = 0x1054, DS9_REG_B_MASTER_BRIGHT = 0x106C, - // DMA - DS9_REG_DMA0SAD_LO = 0x0B0, - DS9_REG_DMA0SAD_HI = 0x0B2, - DS9_REG_DMA0DAD_LO = 0x0B4, - DS9_REG_DMA0DAD_HI = 0x0B6, - DS9_REG_DMA0CNT_LO = 0x0B8, - DS9_REG_DMA0CNT_HI = 0x0BA, - DS9_REG_DMA1SAD_LO = 0x0BC, - DS9_REG_DMA1SAD_HI = 0x0BE, - DS9_REG_DMA1DAD_LO = 0x0C0, - DS9_REG_DMA1DAD_HI = 0x0C2, - DS9_REG_DMA1CNT_LO = 0x0C4, - DS9_REG_DMA1CNT_HI = 0x0C6, - DS9_REG_DMA2SAD_LO = 0x0C8, - DS9_REG_DMA2SAD_HI = 0x0CA, - DS9_REG_DMA2DAD_LO = 0x0CC, - DS9_REG_DMA2DAD_HI = 0x0CE, - DS9_REG_DMA2CNT_LO = 0x0D0, - DS9_REG_DMA2CNT_HI = 0x0D2, - DS9_REG_DMA3SAD_LO = 0x0D4, - DS9_REG_DMA3SAD_HI = 0x0D6, - DS9_REG_DMA3DAD_LO = 0x0D8, - DS9_REG_DMA3DAD_HI = 0x0DA, - DS9_REG_DMA3CNT_LO = 0x0DC, - DS9_REG_DMA3CNT_HI = 0x0DE, - DS9_REG_DMA0FILL_LO = 0x0E0, - DS9_REG_DMA0FILL_HI = 0x0E2, - DS9_REG_DMA1FILL_LO = 0x0E4, - DS9_REG_DMA1FILL_HI = 0x0E6, - DS9_REG_DMA2FILL_LO = 0x0E8, - DS9_REG_DMA2FILL_HI = 0x0EA, - DS9_REG_DMA3FILL_LO = 0x0EC, - DS9_REG_DMA3FILL_HI = 0x0EE, - - // Timers - DS9_REG_TM0CNT_LO = 0x100, - DS9_REG_TM0CNT_HI = 0x102, - DS9_REG_TM1CNT_LO = 0x104, - DS9_REG_TM1CNT_HI = 0x106, - DS9_REG_TM2CNT_LO = 0x108, - DS9_REG_TM2CNT_HI = 0x10A, - DS9_REG_TM3CNT_LO = 0x10C, - DS9_REG_TM3CNT_HI = 0x10E, - // Keypad DS9_REG_KEYINPUT = 0x130, DS9_REG_KEYCNT = 0x132, - // IPC - DS9_REG_IPCSYNC = 0x180, - DS9_REG_IPCFIFOCNT = 0x182, - DS9_REG_IPCFIFOSEND_LO = 0x184, - DS9_REG_IPCFIFOSEND_HI = 0x186, - DS9_REG_IPCFIFORECV_LO = 0x100000, - DS9_REG_IPCFIFORECV_HI = 0x100002, - // Game card DS9_REG_AUXSPICNT = 0x1A0, DS9_REG_AUXSPIDATA = 0x1A2,

@@ -272,13 +224,8 @@ DS9_REG_SLOT1DATA_1 = 0x100011,

DS9_REG_SLOT1DATA_2 = 0x100012, DS9_REG_SLOT1DATA_3 = 0x100013, - // Interrupts, etc + // Etc DS9_REG_EXMEMCNT = 0x204, - DS9_REG_IME = 0x208, - DS9_REG_IE_LO = 0x210, - DS9_REG_IE_HI = 0x212, - DS9_REG_IF_LO = 0x214, - DS9_REG_IF_HI = 0x216, // Memory control DS9_REG_VRAMCNT_A = 0x240,
M include/mgba/internal/ds/memory.hinclude/mgba/internal/ds/memory.h

@@ -133,15 +133,14 @@ char waitstatesPrefetchSeq32[16];

char waitstatesPrefetchSeq16[16]; char waitstatesPrefetchNonseq32[16]; char waitstatesPrefetchNonseq16[16]; - int activeRegion7; - int activeRegion9; +}; - struct DSDMA dma7[4]; - struct DSDMA dma9[4]; - int activeDMA7; - int activeDMA9; - int32_t nextDMA; - int32_t eventDiff; +struct DSCoreMemory { + uint16_t* io; + int activeRegion; + + struct DSDMA dma[4]; + int activeDMA; }; struct DS;
M src/ds/core.csrc/ds/core.c

@@ -159,8 +159,8 @@

static void _DSCoreReset(struct mCore* core) { struct DSCore* dscore = (struct DSCore*) core; struct DS* ds = (struct DS*) core->board; - ARMReset(ds->arm7); - ARMReset(ds->arm9); + ARMReset(ds->ds7.cpu); + ARMReset(ds->ds9.cpu); } static void _DSCoreRunFrame(struct mCore* core) {
M src/ds/ds.csrc/ds/ds.c

@@ -49,7 +49,7 @@ static void DS9WriteCP15(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2, uint32_t value);

static void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh); static void DS9ProcessEvents(struct ARMCore* cpu); -static void DSProcessEvents(struct DS* ds, struct mTiming* timing); +static void DSProcessEvents(struct DSCommon* dscore); static void DSHitStub(struct ARMCore* cpu, uint32_t opcode); static void DSIllegal(struct ARMCore* cpu, uint32_t opcode); static void DSBreakpoint(struct ARMCore* cpu, int immediate);

@@ -58,16 +58,16 @@ static void _slice(struct mTiming* timing, void* context, uint32_t cyclesLate) {

UNUSED(cyclesLate); struct DS* ds = context; uint32_t cycles = mTimingCurrentTime(timing) - ds->sliceStart; - if (ds->activeCpu == ds->arm9) { - ds->activeCpu = ds->arm7; + if (ds->activeCpu == ds->ds9.cpu) { + ds->activeCpu = ds->ds7.cpu; ds->cycleDrift += cycles; cycles = ds->cycleDrift >> 1; - timing = &ds->timing7; + timing = &ds->ds7.timing; } else { - ds->activeCpu = ds->arm9; + ds->activeCpu = ds->ds9.cpu; ds->cycleDrift -= cycles << 1; cycles = ds->cycleDrift + SLICE_CYCLES; - timing = &ds->timing9; + timing = &ds->ds9.timing; } mTimingSchedule(timing, &ds->slice, cycles); ds->sliceStart = mTimingCurrentTime(timing);

@@ -77,38 +77,42 @@ void DSCreate(struct DS* ds) {

ds->d.id = DS_COMPONENT_MAGIC; ds->d.init = DSInit; ds->d.deinit = NULL; - ds->arm7 = NULL; - ds->arm9 = NULL; + ds->ds7.p = ds; + ds->ds9.p = ds; + ds->ds7.cpu = NULL; + ds->ds9.cpu = NULL; + ds->ds7.ipc = &ds->ds9; + ds->ds9.ipc = &ds->ds7; } static void DSInit(void* cpu, struct mCPUComponent* component) { struct DS* ds = (struct DS*) component; struct ARMCore* core = cpu; - if (!ds->arm7) { + if (!ds->ds7.cpu) { // The ARM7 must get initialized first - ds->arm7 = core; + ds->ds7.cpu = core; ds->debugger = 0; ds->sync = 0; return; } - ds->arm9 = cpu; + ds->ds9.cpu = cpu; ds->activeCpu = NULL; - ds->arm9->cp15.r1.c0 = ARMControlRegFillVE(0); + ds->ds9.cpu->cp15.r1.c0 = ARMControlRegFillVE(0); ds->slice.name = "DS CPU Time Slicing"; ds->slice.callback = _slice; ds->slice.context = ds; ds->slice.priority = UINT_MAX; - DS7InterruptHandlerInit(&ds->arm7->irqh); - DS9InterruptHandlerInit(&ds->arm9->irqh); + DS7InterruptHandlerInit(&ds->ds7.cpu->irqh); + DS9InterruptHandlerInit(&ds->ds9.cpu->irqh); DSMemoryInit(ds); ds->video.p = ds; - ds->springIRQ7 = 0; - ds->springIRQ9 = 0; + ds->ds7.springIRQ = 0; + ds->ds9.springIRQ = 0; DSTimerInit(ds); ds->keySource = NULL; ds->rtcSource = NULL;

@@ -118,8 +122,8 @@ ds->romVf = NULL;

ds->keyCallback = NULL; - mTimingInit(&ds->timing7, &ds->arm7->cycles, &ds->arm7->nextEvent); - mTimingInit(&ds->timing9, &ds->arm9->cycles, &ds->arm9->nextEvent); + mTimingInit(&ds->ds7.timing, &ds->ds7.cpu->cycles, &ds->ds7.cpu->nextEvent); + mTimingInit(&ds->ds9.timing, &ds->ds9.cpu->cycles, &ds->ds9.cpu->nextEvent); } void DSUnloadROM(struct DS* ds) {

@@ -132,8 +136,8 @@

void DSDestroy(struct DS* ds) { DSUnloadROM(ds); DSMemoryDeinit(ds); - mTimingDeinit(&ds->timing7); - mTimingDeinit(&ds->timing9); + mTimingDeinit(&ds->ds7.timing); + mTimingDeinit(&ds->ds9.timing); } void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh) {

@@ -171,7 +175,7 @@ ARMSetPrivilegeMode(cpu, MODE_SYSTEM);

cpu->gprs[ARM_SP] = DS7_SP_BASE; struct DS* ds = (struct DS*) cpu->master; - mTimingClear(&ds->timing7); + mTimingClear(&ds->ds7.timing); DSMemoryReset(ds); DS7IOInit(ds);

@@ -203,13 +207,13 @@ ARMSetPrivilegeMode(cpu, MODE_SYSTEM);

cpu->gprs[ARM_SP] = DS9_SP_BASE; struct DS* ds = (struct DS*) cpu->master; - mTimingClear(&ds->timing9); + mTimingClear(&ds->ds9.timing); DS9IOInit(ds); ds->activeCpu = cpu; - mTimingSchedule(&ds->timing9, &ds->slice, SLICE_CYCLES); + mTimingSchedule(&ds->ds9.timing, &ds->slice, SLICE_CYCLES); ds->cycleDrift = 0; - ds->sliceStart = mTimingCurrentTime(&ds->timing9); + ds->sliceStart = mTimingCurrentTime(&ds->ds9.timing); struct DSCartridge* header = ds->romVf->map(ds->romVf, sizeof(*header), MAP_READ); if (header) {

@@ -232,26 +236,22 @@ }

static void DS7ProcessEvents(struct ARMCore* cpu) { struct DS* ds = (struct DS*) cpu->master; - - if (ds->springIRQ7 && !cpu->cpsr.i) { - ARMRaiseIRQ(cpu); - ds->springIRQ7 = 0; - } - DSProcessEvents(ds, &ds->timing7); + DSProcessEvents(&ds->ds7); } static void DS9ProcessEvents(struct ARMCore* cpu) { struct DS* ds = (struct DS*) cpu->master; + DSProcessEvents(&ds->ds9); +} - if (ds->springIRQ9 && !cpu->cpsr.i) { +static void DSProcessEvents(struct DSCommon* dscore) { + struct ARMCore* cpu = dscore->cpu; + struct DS* ds = dscore->p; + if (dscore->springIRQ && !cpu->cpsr.i) { ARMRaiseIRQ(cpu); - ds->springIRQ9 = 0; + dscore->springIRQ = 0; } - DSProcessEvents(ds, &ds->timing9); -} -static void DSProcessEvents(struct DS* ds, struct mTiming* timing) { - struct ARMCore* cpu = ds->activeCpu; int32_t nextEvent = cpu->nextEvent; while (cpu->cycles >= nextEvent) { int32_t cycles = cpu->cycles;

@@ -266,7 +266,7 @@ }

#endif nextEvent = cycles; do { - nextEvent = mTimingTick(timing, nextEvent); + nextEvent = mTimingTick(&dscore->timing, nextEvent); } while (ds->cpuBlocked); cpu->nextEvent = nextEvent;

@@ -287,41 +287,41 @@ }

} void DSRunLoop(struct DS* ds) { - if (ds->activeCpu == ds->arm9) { - ARMv5RunLoop(ds->arm9); + if (ds->activeCpu == ds->ds9.cpu) { + ARMv5RunLoop(ds->ds9.cpu); } else { - ARMv4RunLoop(ds->arm7); + ARMv4RunLoop(ds->ds7.cpu); } } void DS7Step(struct DS* ds) { - while (ds->activeCpu == ds->arm9) { - ARMv5RunLoop(ds->arm9); + while (ds->activeCpu == ds->ds9.cpu) { + ARMv5RunLoop(ds->ds9.cpu); } - ARMv4Run(ds->arm7); + ARMv4Run(ds->ds7.cpu); } void DS9Step(struct DS* ds) { - while (ds->activeCpu == ds->arm7) { - ARMv4RunLoop(ds->arm7); + while (ds->activeCpu == ds->ds7.cpu) { + ARMv4RunLoop(ds->ds7.cpu); } - ARMv5Run(ds->arm9); + ARMv5Run(ds->ds9.cpu); } void DSAttachDebugger(struct DS* ds, struct mDebugger* debugger) { ds->debugger = (struct ARMDebugger*) debugger->platform; - ds->arm7->components[CPU_COMPONENT_DEBUGGER] = &debugger->d; - ds->arm9->components[CPU_COMPONENT_DEBUGGER] = &debugger->d; - ARMHotplugAttach(ds->arm7, CPU_COMPONENT_DEBUGGER); - ARMHotplugAttach(ds->arm9, CPU_COMPONENT_DEBUGGER); + ds->ds7.cpu->components[CPU_COMPONENT_DEBUGGER] = &debugger->d; + ds->ds9.cpu->components[CPU_COMPONENT_DEBUGGER] = &debugger->d; + ARMHotplugAttach(ds->ds7.cpu, CPU_COMPONENT_DEBUGGER); + ARMHotplugAttach(ds->ds9.cpu, CPU_COMPONENT_DEBUGGER); } void DSDetachDebugger(struct DS* ds) { ds->debugger = NULL; - ARMHotplugDetach(ds->arm7, CPU_COMPONENT_DEBUGGER); - ARMHotplugDetach(ds->arm9, CPU_COMPONENT_DEBUGGER); - ds->arm7->components[CPU_COMPONENT_DEBUGGER] = NULL; - ds->arm9->components[CPU_COMPONENT_DEBUGGER] = NULL; + ARMHotplugDetach(ds->ds7.cpu, CPU_COMPONENT_DEBUGGER); + ARMHotplugDetach(ds->ds9.cpu, CPU_COMPONENT_DEBUGGER); + ds->ds7.cpu->components[CPU_COMPONENT_DEBUGGER] = NULL; + ds->ds9.cpu->components[CPU_COMPONENT_DEBUGGER] = NULL; } bool DSLoadROM(struct DS* ds, struct VFile* vf) {

@@ -442,7 +442,7 @@

void DS7TestIRQ(struct ARMCore* cpu) { struct DS* ds = (struct DS*) cpu->master; if (0) { - ds->springIRQ7 = 1; + ds->ds7.springIRQ = 1; cpu->nextEvent = cpu->cycles; } }

@@ -450,7 +450,7 @@

void DS9TestIRQ(struct ARMCore* cpu) { struct DS* ds = (struct DS*) cpu->master; if (0) { - ds->springIRQ9 = 1; + ds->ds9.springIRQ = 1; cpu->nextEvent = cpu->cycles; } }

@@ -552,30 +552,27 @@ }

} void DSWriteIE(struct ARMCore* cpu, uint16_t* io, uint32_t value) { - if (io[DS7_REG_IME >> 1] && (value & io[DS7_REG_IF_LO >> 1] || (value >> 16) & io[DS7_REG_IF_HI >> 1])) { + if (io[DS_REG_IME >> 1] && (value & io[DS_REG_IF_LO >> 1] || (value >> 16) & io[DS_REG_IF_HI >> 1])) { ARMRaiseIRQ(cpu); } } void DSWriteIME(struct ARMCore* cpu, uint16_t* io, uint16_t value) { - if (value && (io[DS7_REG_IE_LO >> 1] & io[DS7_REG_IF_LO >> 1] || io[DS7_REG_IE_HI >> 1] & io[DS7_REG_IF_HI >> 1])) { + if (value && (io[DS_REG_IE_LO >> 1] & io[DS_REG_IF_LO >> 1] || io[DS_REG_IE_HI >> 1] & io[DS_REG_IF_HI >> 1])) { ARMRaiseIRQ(cpu); } } void DSRaiseIRQ(struct ARMCore* cpu, uint16_t* io, enum DSIRQ irq) { if (irq < 16) { - io[DS7_REG_IF_LO >> 1] |= 1 << irq; + io[DS_REG_IF_LO >> 1] |= 1 << irq; } else { - io[DS7_REG_IF_HI >> 1] |= 1 << (irq - 16); + io[DS_REG_IF_HI >> 1] |= 1 << (irq - 16); } - cpu->halted = 0; - if (!io[DS7_REG_IME >> 1]) { - return; - } - if (irq < 16 && (io[DS7_REG_IE_LO >> 1] & 1 << irq)) { - ARMRaiseIRQ(cpu); - } else if (io[DS7_REG_IE_HI >> 1] & 1 << (irq - 16)) { - ARMRaiseIRQ(cpu); + if ((irq < 16 && (io[DS_REG_IE_LO >> 1] & 1 << irq)) || (io[DS_REG_IE_HI >> 1] & 1 << (irq - 16))) { + cpu->halted = 0; + if (io[DS_REG_IME >> 1]) { + ARMRaiseIRQ(cpu); + } } }
M src/ds/extra/cli.csrc/ds/extra/cli.c

@@ -69,10 +69,10 @@ struct DSCLIDebugger* dsDebugger = (struct DSCLIDebugger*) debugger->system;

struct mCore* core = dsDebugger->core; struct DS* ds = core->board; debugger->d.platform->deinit(debugger->d.platform); - if (core->cpu == ds->arm9) { - core->cpu = ds->arm7; + if (core->cpu == ds->ds9.cpu) { + core->cpu = ds->ds7.cpu; } else { - core->cpu = ds->arm9; + core->cpu = ds->ds9.cpu; } debugger->d.platform->init(core->cpu, debugger->d.platform); debugger->system->printStatus(debugger->system);
M src/ds/io.csrc/ds/io.c

@@ -10,64 +10,92 @@

mLOG_DEFINE_CATEGORY(DS_IO, "DS I/O"); static void _writeIPCSync(struct ARMCore* remoteCpu, uint16_t* remoteIo, int16_t value) { - remoteIo[DS7_REG_IPCSYNC >> 1] &= 0xFFF0; - remoteIo[DS7_REG_IPCSYNC >> 1] |= (value >> 8) & 0x0F; - if (value & 0x2000 && remoteIo[DS7_REG_IPCSYNC >> 1] & 0x4000) { + remoteIo[DS_REG_IPCSYNC >> 1] &= 0xFFF0; + remoteIo[DS_REG_IPCSYNC >> 1] |= (value >> 8) & 0x0F; + if (value & 0x2000 && remoteIo[DS_REG_IPCSYNC >> 1] & 0x4000) { mLOG(DS_IO, STUB, "Unimplemented IPC IRQ"); UNUSED(remoteCpu); } } -void DS7IOInit(struct DS* ds) { - memset(ds->memory.io7, 0, sizeof(ds->memory.io7)); -} - -void DS7IOWrite(struct DS* ds, uint32_t address, uint16_t value) { +static bool DSIOWrite(struct DSCommon* dscore, uint32_t address, uint16_t value) { switch (address) { // Timers - case DS7_REG_TM0CNT_LO: - GBATimerWriteTMCNT_LO(&ds->timers7[0], value); - return; - case DS7_REG_TM1CNT_LO: - GBATimerWriteTMCNT_LO(&ds->timers7[1], value); - return; - case DS7_REG_TM2CNT_LO: - GBATimerWriteTMCNT_LO(&ds->timers7[2], value); - return; - case DS7_REG_TM3CNT_LO: - GBATimerWriteTMCNT_LO(&ds->timers7[3], value); - return; + case DS_REG_TM0CNT_LO: + GBATimerWriteTMCNT_LO(&dscore->timers[0], value); + return true; + case DS_REG_TM1CNT_LO: + GBATimerWriteTMCNT_LO(&dscore->timers[1], value); + return true; + case DS_REG_TM2CNT_LO: + GBATimerWriteTMCNT_LO(&dscore->timers[2], value); + return true; + case DS_REG_TM3CNT_LO: + GBATimerWriteTMCNT_LO(&dscore->timers[3], value); + return true; - case DS7_REG_TM0CNT_HI: + case DS_REG_TM0CNT_HI: value &= 0x00C7; - DSTimerWriteTMCNT_HI(&ds->timers7[0], &ds->timing7, ds->arm7, &ds->memory.io7[DS7_REG_TM0CNT_LO >> 1], value); + DSTimerWriteTMCNT_HI(&dscore->timers[0], &dscore->timing, dscore->cpu, &dscore->memory.io[DS_REG_TM0CNT_LO >> 1], value); break; - case DS7_REG_TM1CNT_HI: + case DS_REG_TM1CNT_HI: value &= 0x00C7; - DSTimerWriteTMCNT_HI(&ds->timers7[1], &ds->timing7, ds->arm7, &ds->memory.io7[DS7_REG_TM1CNT_LO >> 1], value); + DSTimerWriteTMCNT_HI(&dscore->timers[1], &dscore->timing, dscore->cpu, &dscore->memory.io[DS_REG_TM1CNT_LO >> 1], value); break; - case DS7_REG_TM2CNT_HI: + case DS_REG_TM2CNT_HI: value &= 0x00C7; - DSTimerWriteTMCNT_HI(&ds->timers7[2], &ds->timing7, ds->arm7, &ds->memory.io7[DS7_REG_TM2CNT_LO >> 1], value); + DSTimerWriteTMCNT_HI(&dscore->timers[2], &dscore->timing, dscore->cpu, &dscore->memory.io[DS_REG_TM2CNT_LO >> 1], value); break; - case DS7_REG_TM3CNT_HI: + case DS_REG_TM3CNT_HI: value &= 0x00C7; - DSTimerWriteTMCNT_HI(&ds->timers7[3], &ds->timing7, ds->arm7, &ds->memory.io7[DS7_REG_TM3CNT_LO >> 1], value); + DSTimerWriteTMCNT_HI(&dscore->timers[3], &dscore->timing, dscore->cpu, &dscore->memory.io[DS_REG_TM3CNT_LO >> 1], value); break; - case DS7_REG_IPCSYNC: + case DS_REG_IPCSYNC: value &= 0x6F00; - value |= ds->memory.io7[address >> 1] & 0x000F; - _writeIPCSync(ds->arm9, ds->memory.io9, value); + value |= dscore->memory.io[address >> 1] & 0x000F; + _writeIPCSync(dscore->ipc->cpu, dscore->ipc->memory.io, value); break; - case DS7_REG_IME: - DSWriteIME(ds->arm7, ds->memory.io7, value); + case DS_REG_IME: + DSWriteIME(dscore->cpu, dscore->memory.io, value); break; - case DS7_REG_IF_LO: - case DS7_REG_IF_HI: - value = ds->memory.io7[address >> 1] & ~value; + case DS_REG_IF_LO: + case DS_REG_IF_HI: + value = dscore->memory.io[address >> 1] & ~value; break; default: + return false; + } + return true; +} + +static void DSIOUpdateTimer(struct DSCommon* dscore, uint32_t address) { + switch (address) { + case DS_REG_TM0CNT_LO: + GBATimerUpdateRegisterInternal(&dscore->timers[0], &dscore->timing, dscore->cpu, &dscore->memory.io[address >> 1], 0); + break; + case DS_REG_TM1CNT_LO: + GBATimerUpdateRegisterInternal(&dscore->timers[1], &dscore->timing, dscore->cpu, &dscore->memory.io[address >> 1], 0); + break; + case DS_REG_TM2CNT_LO: + GBATimerUpdateRegisterInternal(&dscore->timers[2], &dscore->timing, dscore->cpu, &dscore->memory.io[address >> 1], 0); + break; + case DS_REG_TM3CNT_LO: + GBATimerUpdateRegisterInternal(&dscore->timers[3], &dscore->timing, dscore->cpu, &dscore->memory.io[address >> 1], 0); + break; + } +} + +void DS7IOInit(struct DS* ds) { + memset(ds->memory.io7, 0, sizeof(ds->memory.io7)); +} + +void DS7IOWrite(struct DS* ds, uint32_t address, uint16_t value) { + switch (address) { + default: + if (DSIOWrite(&ds->ds7, address, value)) { + break; + } mLOG(DS_IO, STUB, "Stub DS7 I/O register write: %06X:%04X", address, value); if (address >= DS7_REG_MAX) { mLOG(DS_IO, GAME_ERROR, "Write to unused DS7 I/O register: %06X:%04X", address, value);

@@ -81,7 +109,7 @@

void DS7IOWrite8(struct DS* ds, uint32_t address, uint8_t value) { if (address < DS7_REG_MAX) { uint16_t value16 = value << (8 * (address & 1)); - value16 |= (ds->memory.io7[(address & 0xFFF) >> 1]) & ~(0xFF << (8 * (address & 1))); + value16 |= (ds->ds7.memory.io[(address & 0xFFF) >> 1]) & ~(0xFF << (8 * (address & 1))); DS7IOWrite(ds, address & 0xFFFFFFFE, value16); } else { mLOG(DS, STUB, "Writing to unknown DS7 register: %08X:%02X", address, value);

@@ -90,43 +118,36 @@ }

void DS7IOWrite32(struct DS* ds, uint32_t address, uint32_t value) { switch (address) { - case DS7_REG_IE_LO: - DSWriteIE(ds->arm7, ds->memory.io7, value); + case DS_REG_IE_LO: + DSWriteIE(ds->ds7.cpu, ds->ds7.memory.io, value); break; default: DS7IOWrite(ds, address, value & 0xFFFF); DS7IOWrite(ds, address | 2, value >> 16); return; } - ds->memory.io7[address >> 1] = value; - ds->memory.io7[(address >> 1) + 1] = value >> 16; + ds->ds7.memory.io[address >> 1] = value; + ds->ds7.memory.io[(address >> 1) + 1] = value >> 16; } uint16_t DS7IORead(struct DS* ds, uint32_t address) { switch (address) { - case DS7_REG_TM0CNT_LO: - GBATimerUpdateRegisterInternal(&ds->timers7[0], &ds->timing7, ds->arm7, &ds->memory.io7[address >> 1], 0); - break; - case DS7_REG_TM1CNT_LO: - GBATimerUpdateRegisterInternal(&ds->timers7[1], &ds->timing7, ds->arm7, &ds->memory.io7[address >> 1], 0); - break; - case DS7_REG_TM2CNT_LO: - GBATimerUpdateRegisterInternal(&ds->timers7[2], &ds->timing7, ds->arm7, &ds->memory.io7[address >> 1], 0); + case DS_REG_TM0CNT_LO: + case DS_REG_TM1CNT_LO: + case DS_REG_TM2CNT_LO: + case DS_REG_TM3CNT_LO: + DSIOUpdateTimer(&ds->ds7, address); break; - case DS7_REG_TM3CNT_LO: - GBATimerUpdateRegisterInternal(&ds->timers7[3], &ds->timing7, ds->arm7, &ds->memory.io7[address >> 1], 0); - break; - - case DS7_REG_TM0CNT_HI: - case DS7_REG_TM1CNT_HI: - case DS7_REG_TM2CNT_HI: - case DS7_REG_TM3CNT_HI: - case DS7_REG_IPCSYNC: - case DS7_REG_IME: - case DS7_REG_IE_LO: - case DS7_REG_IE_HI: - case DS7_REG_IF_LO: - case DS7_REG_IF_HI: + case DS_REG_TM0CNT_HI: + case DS_REG_TM1CNT_HI: + case DS_REG_TM2CNT_HI: + case DS_REG_TM3CNT_HI: + case DS_REG_IPCSYNC: + case DS_REG_IME: + case DS_REG_IE_LO: + case DS_REG_IE_HI: + case DS_REG_IF_LO: + case DS_REG_IF_HI: // Handled transparently by the registers break; default:

@@ -144,12 +165,10 @@ }

void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) { switch (address) { - case DS9_REG_IPCSYNC: - value &= 0x6F00; - value |= ds->memory.io9[address >> 1] & 0x000F; - _writeIPCSync(ds->arm7, ds->memory.io7, value); - break; default: + if (DSIOWrite(&ds->ds9, address, value)) { + break; + } mLOG(DS_IO, STUB, "Stub DS9 I/O register write: %06X:%04X", address, value); if (address >= DS7_REG_MAX) { mLOG(DS_IO, GAME_ERROR, "Write to unused DS9 I/O register: %06X:%04X", address, value);

@@ -177,20 +196,35 @@ DS9IOWrite(ds, address, value & 0xFFFF);

DS9IOWrite(ds, address | 2, value >> 16); return; } - ds->memory.io9[address >> 1] = value; - ds->memory.io9[(address >> 1) + 1] = value >> 16; + ds->ds9.memory.io[address >> 1] = value; + ds->ds9.memory.io[(address >> 1) + 1] = value >> 16; } uint16_t DS9IORead(struct DS* ds, uint32_t address) { switch (address) { - case DS9_REG_IPCSYNC: + case DS_REG_TM0CNT_LO: + case DS_REG_TM1CNT_LO: + case DS_REG_TM2CNT_LO: + case DS_REG_TM3CNT_LO: + DSIOUpdateTimer(&ds->ds9, address); + break; + case DS_REG_TM0CNT_HI: + case DS_REG_TM1CNT_HI: + case DS_REG_TM2CNT_HI: + case DS_REG_TM3CNT_HI: + case DS_REG_IPCSYNC: + case DS_REG_IME: + case DS_REG_IE_LO: + case DS_REG_IE_HI: + case DS_REG_IF_LO: + case DS_REG_IF_HI: // Handled transparently by the registers break; default: mLOG(DS_IO, STUB, "Stub DS9 I/O register read: %06X", address); } if (address < DS9_REG_MAX) { - return ds->memory.io9[address >> 1]; + return ds->ds9.memory.io[address >> 1]; } return 0; }
M src/ds/memory.csrc/ds/memory.c

@@ -80,7 +80,7 @@

static const int DMA_OFFSET[] = { 1, -1, 0, 1 }; void DSMemoryInit(struct DS* ds) { - struct ARMCore* arm7 = ds->arm7; + struct ARMCore* arm7 = ds->ds7.cpu; arm7->memory.load32 = DS7Load32; arm7->memory.load16 = DS7Load16; arm7->memory.load8 = DS7Load8;

@@ -91,7 +91,7 @@ arm7->memory.store8 = DS7Store8;

arm7->memory.storeMultiple = DS7StoreMultiple; arm7->memory.stall = DSMemoryStall; - struct ARMCore* arm9 = ds->arm9; + struct ARMCore* arm9 = ds->ds9.cpu; arm9->memory.load32 = DS9Load32; arm9->memory.load16 = DS9Load16; arm9->memory.load8 = DS9Load8;

@@ -111,8 +111,10 @@ ds->memory.itcm = NULL;

ds->memory.dtcm = NULL; ds->memory.rom = NULL; - ds->memory.activeRegion7 = -1; - ds->memory.activeRegion9 = -1; + ds->ds7.memory.activeRegion = -1; + ds->ds9.memory.activeRegion = -1; + ds->ds7.memory.io = ds->memory.io7; + ds->ds9.memory.io = ds->memory.io9; arm7->memory.activeRegion = 0; arm7->memory.activeMask = 0;

@@ -165,12 +167,10 @@ mappedMemoryFree(ds->memory.dtcm, DS9_SIZE_DTCM);

} ds->memory.dtcm = anonymousMemoryMap(DS9_SIZE_DTCM); - memset(ds->memory.dma7, 0, sizeof(ds->memory.dma7)); - memset(ds->memory.dma9, 0, sizeof(ds->memory.dma9)); - ds->memory.activeDMA7 = -1; - ds->memory.activeDMA9 = -1; - ds->memory.nextDMA = INT_MAX; - ds->memory.eventDiff = 0; + memset(ds->ds7.memory.dma, 0, sizeof(ds->ds7.memory.dma)); + memset(ds->ds9.memory.dma, 0, sizeof(ds->ds9.memory.dma)); + ds->ds7.memory.activeDMA = -1; + ds->ds9.memory.activeDMA = -1; // TODO: Correct size ds->memory.wramSize7 = 0x8000;

@@ -188,7 +188,7 @@ struct DSMemory* memory = &ds->memory;

int newRegion = address >> DS_BASE_OFFSET; - memory->activeRegion7 = newRegion; + ds->ds7.memory.activeRegion = newRegion; switch (newRegion) { case DS_REGION_WORKING_RAM: if (address >= DS7_BASE_WORKING_RAM || !memory->wramSize7) {

@@ -550,7 +550,7 @@ struct DSMemory* memory = &ds->memory;

int newRegion = address >> DS_BASE_OFFSET; - memory->activeRegion9 = newRegion; + ds->ds9.memory.activeRegion = newRegion; switch (newRegion) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR:
M src/ds/timer.csrc/ds/timer.c

@@ -8,81 +8,81 @@

#include <mgba/internal/arm/arm.h> #include <mgba/internal/ds/ds.h> -static void DS7TimerUpdate0(struct mTiming* timing, void* context, uint32_t cyclesLate) { - struct DS* ds = context; - struct GBATimer* timer = &ds->timers7[0]; +static void DSTimerUpdate0(struct mTiming* timing, void* context, uint32_t cyclesLate) { + struct DSCommon* dscore = context; + struct GBATimer* timer = &dscore->timers[0]; if (GBATimerFlagsIsDoIrq(timer->flags)) { - DSRaiseIRQ(ds->arm7, ds->memory.io7, DS_IRQ_TIMER0); + DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_TIMER0); } - GBATimerUpdate(timing, &ds->timers7[0], &ds->memory.io7[DS7_REG_TM0CNT_LO >> 1], cyclesLate); - GBATimerUpdateCountUp(timing, &ds->timers7[1], &ds->memory.io7[DS7_REG_TM1CNT_LO >> 1], cyclesLate); + GBATimerUpdate(timing, &dscore->timers[0], &dscore->memory.io[DS_REG_TM0CNT_LO >> 1], cyclesLate); + GBATimerUpdateCountUp(timing, &dscore->timers[1], &dscore->memory.io[DS_REG_TM1CNT_LO >> 1], cyclesLate); } -static void DS7TimerUpdate1(struct mTiming* timing, void* context, uint32_t cyclesLate) { - struct DS* ds = context; - struct GBATimer* timer = &ds->timers7[1]; +static void DSTimerUpdate1(struct mTiming* timing, void* context, uint32_t cyclesLate) { + struct DSCommon* dscore = context; + struct GBATimer* timer = &dscore->timers[1]; if (GBATimerFlagsIsDoIrq(timer->flags)) { - DSRaiseIRQ(ds->arm7, ds->memory.io7, DS_IRQ_TIMER1); + DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_TIMER1); } - GBATimerUpdate(timing, &ds->timers7[1], &ds->memory.io7[DS7_REG_TM1CNT_LO >> 1], cyclesLate); - GBATimerUpdateCountUp(timing, &ds->timers7[2], &ds->memory.io7[DS7_REG_TM2CNT_LO >> 1], cyclesLate); + GBATimerUpdate(timing, &dscore->timers[1], &dscore->memory.io[DS_REG_TM1CNT_LO >> 1], cyclesLate); + GBATimerUpdateCountUp(timing, &dscore->timers[2], &dscore->memory.io[DS_REG_TM2CNT_LO >> 1], cyclesLate); } -static void DS7TimerUpdate2(struct mTiming* timing, void* context, uint32_t cyclesLate) { - struct DS* ds = context; - struct GBATimer* timer = &ds->timers7[2]; +static void DSTimerUpdate2(struct mTiming* timing, void* context, uint32_t cyclesLate) { + struct DSCommon* dscore = context; + struct GBATimer* timer = &dscore->timers[2]; if (GBATimerFlagsIsDoIrq(timer->flags)) { - DSRaiseIRQ(ds->arm7, ds->memory.io7, DS_IRQ_TIMER2); + DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_TIMER2); } - GBATimerUpdate(timing, &ds->timers7[2], &ds->memory.io7[DS7_REG_TM2CNT_LO >> 1], cyclesLate); - GBATimerUpdateCountUp(timing, &ds->timers7[3], &ds->memory.io7[DS7_REG_TM3CNT_LO >> 1], cyclesLate); + GBATimerUpdate(timing, &dscore->timers[2], &dscore->memory.io[DS_REG_TM2CNT_LO >> 1], cyclesLate); + GBATimerUpdateCountUp(timing, &dscore->timers[3], &dscore->memory.io[DS_REG_TM3CNT_LO >> 1], cyclesLate); } -static void DS7TimerUpdate3(struct mTiming* timing, void* context, uint32_t cyclesLate) { - struct DS* ds = context; - struct GBATimer* timer = &ds->timers7[3]; +static void DSTimerUpdate3(struct mTiming* timing, void* context, uint32_t cyclesLate) { + struct DSCommon* dscore = context; + struct GBATimer* timer = &dscore->timers[3]; if (GBATimerFlagsIsDoIrq(timer->flags)) { - DSRaiseIRQ(ds->arm7, ds->memory.io7, DS_IRQ_TIMER3); + DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_TIMER3); } - GBATimerUpdate(timing, &ds->timers7[3], &ds->memory.io7[DS7_REG_TM3CNT_LO >> 1], cyclesLate); + GBATimerUpdate(timing, &dscore->timers[3], &dscore->memory.io[DS_REG_TM3CNT_LO >> 1], cyclesLate); } void DSTimerInit(struct DS* ds) { - memset(ds->timers7, 0, sizeof(ds->timers7)); - ds->timers7[0].event.name = "DS7 Timer 0"; - ds->timers7[0].event.callback = DS7TimerUpdate0; - ds->timers7[0].event.context = ds; - ds->timers7[0].event.priority = 0x20; - ds->timers7[1].event.name = "DS7 Timer 1"; - ds->timers7[1].event.callback = DS7TimerUpdate1; - ds->timers7[1].event.context = ds; - ds->timers7[1].event.priority = 0x21; - ds->timers7[2].event.name = "DS7 Timer 2"; - ds->timers7[2].event.callback = DS7TimerUpdate2; - ds->timers7[2].event.context = ds; - ds->timers7[2].event.priority = 0x22; - ds->timers7[3].event.name = "DS7 Timer 3"; - ds->timers7[3].event.callback = DS7TimerUpdate3; - ds->timers7[3].event.context = ds; - ds->timers7[3].event.priority = 0x23; + memset(ds->ds7.timers, 0, sizeof(ds->ds7.timers)); + ds->ds7.timers[0].event.name = "DS7 Timer 0"; + ds->ds7.timers[0].event.callback = DSTimerUpdate0; + ds->ds7.timers[0].event.context = &ds->ds7; + ds->ds7.timers[0].event.priority = 0x20; + ds->ds7.timers[1].event.name = "DS7 Timer 1"; + ds->ds7.timers[0].event.callback = DSTimerUpdate1; + ds->ds7.timers[0].event.context = &ds->ds7; + ds->ds7.timers[1].event.priority = 0x21; + ds->ds7.timers[2].event.name = "DS7 Timer 2"; + ds->ds7.timers[0].event.callback = DSTimerUpdate2; + ds->ds7.timers[0].event.context = &ds->ds7; + ds->ds7.timers[2].event.priority = 0x22; + ds->ds7.timers[3].event.name = "DS7 Timer 3"; + ds->ds7.timers[0].event.callback = DSTimerUpdate3; + ds->ds7.timers[0].event.context = &ds->ds7; + ds->ds7.timers[3].event.priority = 0x23; - memset(ds->timers9, 0, sizeof(ds->timers9)); - ds->timers9[0].event.name = "DS9 Timer 0"; - ds->timers9[0].event.callback = NULL; - ds->timers9[0].event.context = ds; - ds->timers9[0].event.priority = 0x20; - ds->timers9[1].event.name = "DS9 Timer 1"; - ds->timers9[1].event.callback = NULL; - ds->timers9[1].event.context = ds; - ds->timers9[1].event.priority = 0x21; - ds->timers9[2].event.name = "DS9 Timer 2"; - ds->timers9[2].event.callback = NULL; - ds->timers9[2].event.context = ds; - ds->timers9[2].event.priority = 0x22; - ds->timers9[3].event.name = "DS9 Timer 3"; - ds->timers9[3].event.callback = NULL; - ds->timers9[3].event.context = ds; - ds->timers9[3].event.priority = 0x23; + memset(ds->ds9.timers, 0, sizeof(ds->ds9.timers)); + ds->ds9.timers[0].event.name = "DS9 Timer 0"; + ds->ds9.timers[0].event.callback = DSTimerUpdate0; + ds->ds9.timers[0].event.context = ds; + ds->ds9.timers[0].event.priority = 0x20; + ds->ds9.timers[1].event.name = "DS9 Timer 1"; + ds->ds9.timers[1].event.callback = DSTimerUpdate1; + ds->ds9.timers[1].event.context = ds; + ds->ds9.timers[1].event.priority = 0x21; + ds->ds9.timers[2].event.name = "DS9 Timer 2"; + ds->ds9.timers[2].event.callback = DSTimerUpdate2; + ds->ds9.timers[2].event.context = ds; + ds->ds9.timers[2].event.priority = 0x22; + ds->ds9.timers[3].event.name = "DS9 Timer 3"; + ds->ds9.timers[3].event.callback = DSTimerUpdate3; + ds->ds9.timers[3].event.context = ds; + ds->ds9.timers[3].event.priority = 0x23; } void DSTimerWriteTMCNT_HI(struct GBATimer* timer, struct mTiming* timing, struct ARMCore* cpu, uint16_t* io, uint16_t value) {