mirror of https://github.com/mgba-emu/mgba.git
DS: Port over DMAs
This commit is contained in:
parent
66db559f5b
commit
5a55b53983
|
@ -0,0 +1,46 @@
|
|||
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef DS_DMA_H
|
||||
#define DS_DMA_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/internal/gba/dma.h>
|
||||
|
||||
enum DSDMATiming {
|
||||
DS_DMA_TIMING_NOW = 0,
|
||||
DS_DMA_TIMING_VBLANK = 1,
|
||||
DS_DMA_TIMING_HBLANK = 2,
|
||||
DS7_DMA_TIMING_SLOT1 = 2,
|
||||
DS_DMA_TIMING_DISPLAY_START = 3,
|
||||
DS7_DMA_TIMING_CUSTOM = 3,
|
||||
DS_DMA_TIMING_MEMORY_DISPLAY = 4,
|
||||
DS9_DMA_TIMING_SLOT1 = 5,
|
||||
DS_DMA_TIMING_SLOT2 = 6,
|
||||
DS_DMA_TIMING_GEOM_FIFO = 7,
|
||||
};
|
||||
|
||||
DECL_BITS(GBADMARegister, Timing9, 11, 3);
|
||||
|
||||
struct DS;
|
||||
struct DSCommon;
|
||||
void DSDMAInit(struct DS* ds);
|
||||
void DSDMAReset(struct DSCommon* dscore);
|
||||
|
||||
uint32_t DSDMAWriteSAD(struct DSCommon* dscore, int dma, uint32_t address);
|
||||
uint32_t DSDMAWriteDAD(struct DSCommon* dscore, int dma, uint32_t address);
|
||||
void DS7DMAWriteCNT(struct DSCommon* dscore, int dma, uint32_t value);
|
||||
void DS9DMAWriteCNT(struct DSCommon* dscore, int dma, uint32_t value);
|
||||
|
||||
struct DSDMA;
|
||||
void DSDMASchedule(struct DSCommon* dscore, int number, struct GBADMA* info);
|
||||
void DSDMAUpdate(struct DSCommon* dscore);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -10,8 +10,10 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/internal/arm/arm.h>
|
||||
#include <mgba/core/log.h>
|
||||
#include <mgba/core/timing.h>
|
||||
#include <mgba/internal/arm/arm.h>
|
||||
#include <mgba/internal/ds/dma.h>
|
||||
#include <mgba/internal/ds/io.h>
|
||||
|
||||
enum DSMemoryRegion {
|
||||
|
@ -65,50 +67,8 @@ enum {
|
|||
DS_BASE_OFFSET = 24
|
||||
};
|
||||
|
||||
enum DSDMAControl {
|
||||
DS_DMA_INCREMENT = 0,
|
||||
DS_DMA_DECREMENT = 1,
|
||||
DS_DMA_FIXED = 2,
|
||||
DS_DMA_INCREMENT_RELOAD = 3
|
||||
};
|
||||
|
||||
enum DSDMATiming {
|
||||
DS_DMA_TIMING_NOW = 0,
|
||||
DS_DMA_TIMING_VBLANK = 1,
|
||||
DS_DMA_TIMING_HBLANK = 2,
|
||||
DS7_DMA_TIMING_SLOT1 = 2,
|
||||
DS_DMA_TIMING_DISPLAY_START = 3,
|
||||
DS7_DMA_TIMING_CUSTOM = 3,
|
||||
DS_DMA_TIMING_MEMORY_DISPLAY = 4,
|
||||
DS9_DMA_TIMING_SLOT1 = 5,
|
||||
DS_DMA_TIMING_SLOT2 = 6,
|
||||
DS_DMA_TIMING_GEOM_FIFO = 7,
|
||||
};
|
||||
|
||||
mLOG_DECLARE_CATEGORY(DS_MEM);
|
||||
|
||||
DECL_BITFIELD(DSDMARegister, uint16_t);
|
||||
DECL_BITS(DSDMARegister, DestControl, 5, 2);
|
||||
DECL_BITS(DSDMARegister, SrcControl, 7, 2);
|
||||
DECL_BIT(DSDMARegister, Repeat, 9);
|
||||
DECL_BIT(DSDMARegister, Width, 10);
|
||||
DECL_BITS(DSDMARegister, Timing7, 12, 2);
|
||||
DECL_BITS(DSDMARegister, Timing9, 11, 3);
|
||||
DECL_BIT(DSDMARegister, DoIRQ, 14);
|
||||
DECL_BIT(DSDMARegister, Enable, 15);
|
||||
|
||||
struct DSDMA {
|
||||
DSDMARegister reg;
|
||||
|
||||
uint32_t source;
|
||||
uint32_t dest;
|
||||
int32_t count;
|
||||
uint32_t nextSource;
|
||||
uint32_t nextDest;
|
||||
int32_t nextCount;
|
||||
int32_t nextEvent;
|
||||
};
|
||||
|
||||
struct DSMemory {
|
||||
uint32_t* bios7;
|
||||
uint32_t* bios9;
|
||||
|
@ -139,7 +99,8 @@ struct DSCoreMemory {
|
|||
uint16_t* io;
|
||||
int activeRegion;
|
||||
|
||||
struct DSDMA dma[4];
|
||||
struct GBADMA dma[4];
|
||||
struct mTimingEvent dmaEvent;
|
||||
int activeDMA;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,6 +10,42 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
enum DMAControl {
|
||||
DMA_INCREMENT = 0,
|
||||
DMA_DECREMENT = 1,
|
||||
DMA_FIXED = 2,
|
||||
DMA_INCREMENT_RELOAD = 3
|
||||
};
|
||||
|
||||
enum DMATiming {
|
||||
DMA_TIMING_NOW = 0,
|
||||
DMA_TIMING_VBLANK = 1,
|
||||
DMA_TIMING_HBLANK = 2,
|
||||
DMA_TIMING_CUSTOM = 3
|
||||
};
|
||||
|
||||
DECL_BITFIELD(GBADMARegister, uint16_t);
|
||||
DECL_BITS(GBADMARegister, DestControl, 5, 2);
|
||||
DECL_BITS(GBADMARegister, SrcControl, 7, 2);
|
||||
DECL_BIT(GBADMARegister, Repeat, 9);
|
||||
DECL_BIT(GBADMARegister, Width, 10);
|
||||
DECL_BIT(GBADMARegister, DRQ, 11);
|
||||
DECL_BITS(GBADMARegister, Timing, 12, 2);
|
||||
DECL_BIT(GBADMARegister, DoIRQ, 14);
|
||||
DECL_BIT(GBADMARegister, Enable, 15);
|
||||
|
||||
struct GBADMA {
|
||||
GBADMARegister reg;
|
||||
|
||||
uint32_t source;
|
||||
uint32_t dest;
|
||||
int32_t count;
|
||||
uint32_t nextSource;
|
||||
uint32_t nextDest;
|
||||
int32_t nextCount;
|
||||
uint32_t when;
|
||||
};
|
||||
|
||||
struct GBA;
|
||||
void GBADMAInit(struct GBA* gba);
|
||||
void GBADMAReset(struct GBA* gba);
|
||||
|
|
|
@ -13,10 +13,13 @@ CXX_GUARD_START
|
|||
#include <mgba/core/timing.h>
|
||||
|
||||
#include <mgba/internal/arm/arm.h>
|
||||
#include <mgba/internal/gba/dma.h>
|
||||
#include <mgba/internal/gba/hardware.h>
|
||||
#include <mgba/internal/gba/savedata.h>
|
||||
#include <mgba/internal/gba/vfame.h>
|
||||
|
||||
mLOG_DECLARE_CATEGORY(GBA_MEM);
|
||||
|
||||
enum GBAMemoryRegion {
|
||||
REGION_BIOS = 0x0,
|
||||
REGION_WORKING_RAM = 0x2,
|
||||
|
@ -75,44 +78,6 @@ enum {
|
|||
BASE_OFFSET = 24
|
||||
};
|
||||
|
||||
enum DMAControl {
|
||||
DMA_INCREMENT = 0,
|
||||
DMA_DECREMENT = 1,
|
||||
DMA_FIXED = 2,
|
||||
DMA_INCREMENT_RELOAD = 3
|
||||
};
|
||||
|
||||
enum DMATiming {
|
||||
DMA_TIMING_NOW = 0,
|
||||
DMA_TIMING_VBLANK = 1,
|
||||
DMA_TIMING_HBLANK = 2,
|
||||
DMA_TIMING_CUSTOM = 3
|
||||
};
|
||||
|
||||
mLOG_DECLARE_CATEGORY(GBA_MEM);
|
||||
|
||||
DECL_BITFIELD(GBADMARegister, uint16_t);
|
||||
DECL_BITS(GBADMARegister, DestControl, 5, 2);
|
||||
DECL_BITS(GBADMARegister, SrcControl, 7, 2);
|
||||
DECL_BIT(GBADMARegister, Repeat, 9);
|
||||
DECL_BIT(GBADMARegister, Width, 10);
|
||||
DECL_BIT(GBADMARegister, DRQ, 11);
|
||||
DECL_BITS(GBADMARegister, Timing, 12, 2);
|
||||
DECL_BIT(GBADMARegister, DoIRQ, 14);
|
||||
DECL_BIT(GBADMARegister, Enable, 15);
|
||||
|
||||
struct GBADMA {
|
||||
GBADMARegister reg;
|
||||
|
||||
uint32_t source;
|
||||
uint32_t dest;
|
||||
int32_t count;
|
||||
uint32_t nextSource;
|
||||
uint32_t nextDest;
|
||||
int32_t nextCount;
|
||||
uint32_t when;
|
||||
};
|
||||
|
||||
struct GBAMemory {
|
||||
uint32_t* bios;
|
||||
uint32_t* wram;
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/ds/dma.h>
|
||||
|
||||
#include <mgba/internal/ds/ds.h>
|
||||
#include <mgba/internal/ds/io.h>
|
||||
#include <mgba/internal/ds/memory.h>
|
||||
|
||||
static void _dmaEvent(struct mTiming* timing, void* context, uint32_t cyclesLate);
|
||||
|
||||
static void DSDMAService(struct DSCommon* dscore, int number, struct GBADMA* info);
|
||||
|
||||
static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
|
||||
|
||||
void DSDMAInit(struct DS* ds) {
|
||||
ds->ds7.memory.dmaEvent.name = "DS7 DMA";
|
||||
ds->ds7.memory.dmaEvent.callback = _dmaEvent;
|
||||
ds->ds7.memory.dmaEvent.context = &ds->ds7;
|
||||
ds->ds7.memory.dmaEvent.priority = 0x40;
|
||||
ds->ds9.memory.dmaEvent.name = "DS9 DMA";
|
||||
ds->ds9.memory.dmaEvent.callback = _dmaEvent;
|
||||
ds->ds9.memory.dmaEvent.context = &ds->ds9;
|
||||
ds->ds9.memory.dmaEvent.priority = 0x40;
|
||||
}
|
||||
|
||||
void DSDMAReset(struct DSCommon* dscore) {
|
||||
memset(dscore->memory.dma, 0, sizeof(dscore->memory.dma));
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
// TODO: This is wrong for DS7
|
||||
dscore->memory.dma[i].count = 0x200000;
|
||||
}
|
||||
dscore->memory.activeDMA = -1;
|
||||
}
|
||||
|
||||
uint32_t DSDMAWriteSAD(struct DSCommon* dscore, int dma, uint32_t address) {
|
||||
address &= 0x0FFFFFFE;
|
||||
dscore->memory.dma[dma].source = address;
|
||||
return dscore->memory.dma[dma].source;
|
||||
}
|
||||
|
||||
uint32_t DSDMAWriteDAD(struct DSCommon* dscore, int dma, uint32_t address) {
|
||||
address &= 0x0FFFFFFE;
|
||||
dscore->memory.dma[dma].dest = address;
|
||||
return dscore->memory.dma[dma].dest;
|
||||
}
|
||||
|
||||
void DS7DMAWriteCNT(struct DSCommon* dscore, int dma, uint32_t value) {
|
||||
struct DSCoreMemory* memory = &dscore->memory;
|
||||
struct GBADMA* currentDma = &memory->dma[dma];
|
||||
uint32_t count = value & 0xFFFF;
|
||||
currentDma->count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
|
||||
int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
|
||||
unsigned control = (value >> 16) & 0xF7E0;
|
||||
currentDma->reg = control;
|
||||
|
||||
if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
|
||||
currentDma->nextSource = currentDma->source;
|
||||
currentDma->nextDest = currentDma->dest;
|
||||
DSDMASchedule(dscore, dma, currentDma);
|
||||
}
|
||||
}
|
||||
|
||||
void DS9DMAWriteCNT(struct DSCommon* dscore, int dma, uint32_t value) {
|
||||
struct DSCoreMemory* memory = &dscore->memory;
|
||||
struct GBADMA* currentDma = &memory->dma[dma];
|
||||
uint32_t count = value & 0x1FFFFF;
|
||||
currentDma->count = count ? count : 0x200000;
|
||||
int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
|
||||
unsigned control = (value >> 16) & 0xFFE0;
|
||||
currentDma->reg = control;
|
||||
|
||||
if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
|
||||
currentDma->nextSource = currentDma->source;
|
||||
currentDma->nextDest = currentDma->dest;
|
||||
DSDMASchedule(dscore, dma, currentDma);
|
||||
}
|
||||
}
|
||||
|
||||
void DSDMASchedule(struct DSCommon* dscore, int number, struct GBADMA* info) {
|
||||
switch (GBADMARegisterGetTiming(info->reg)) {
|
||||
case DS_DMA_TIMING_NOW:
|
||||
info->when = mTimingCurrentTime(&dscore->timing) + 3; // DMAs take 3 cycles to start
|
||||
info->nextCount = info->count;
|
||||
break;
|
||||
case DS_DMA_TIMING_HBLANK:
|
||||
case DS_DMA_TIMING_VBLANK:
|
||||
// Handled implicitly
|
||||
return;
|
||||
default:
|
||||
mLOG(DS_MEM, STUB, "Unimplemented DMA");
|
||||
}
|
||||
DSDMAUpdate(dscore);
|
||||
}
|
||||
|
||||
void _dmaEvent(struct mTiming* timing, void* context, uint32_t cyclesLate) {
|
||||
UNUSED(timing);
|
||||
UNUSED(cyclesLate);
|
||||
struct DSCommon* dscore = context;
|
||||
struct DSCoreMemory* memory = &dscore->memory;
|
||||
struct GBADMA* dma = &memory->dma[memory->activeDMA];
|
||||
if (dma->nextCount == dma->count) {
|
||||
dma->when = mTimingCurrentTime(&dscore->timing);
|
||||
}
|
||||
if (dma->nextCount & 0xFFFFF) {
|
||||
dscore->p->cpuBlocked = true; // TODO: Fix for ITCM
|
||||
DSDMAService(dscore, memory->activeDMA, dma);
|
||||
} else {
|
||||
dma->nextCount = 0;
|
||||
if (!GBADMARegisterIsRepeat(dma->reg) || GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_NOW) {
|
||||
dma->reg = GBADMARegisterClearEnable(dma->reg);
|
||||
|
||||
// Clear the enable bit in memory
|
||||
memory->io[(DS_REG_DMA0CNT_HI + memory->activeDMA * (DS_REG_DMA1CNT_HI - DS_REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
|
||||
}
|
||||
if (GBADMARegisterGetDestControl(dma->reg) == DMA_INCREMENT_RELOAD) {
|
||||
dma->nextDest = dma->dest;
|
||||
}
|
||||
if (GBADMARegisterIsDoIRQ(dma->reg)) {
|
||||
DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_DMA0 + memory->activeDMA);
|
||||
}
|
||||
DSDMAUpdate(dscore);
|
||||
}
|
||||
}
|
||||
|
||||
void DSDMAUpdate(struct DSCommon* dscore) {
|
||||
int i;
|
||||
struct DSCoreMemory* memory = &dscore->memory;
|
||||
memory->activeDMA = -1;
|
||||
uint32_t currentTime = mTimingCurrentTime(&dscore->timing);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
struct GBADMA* dma = &memory->dma[i];
|
||||
if (GBADMARegisterIsEnable(dma->reg) && dma->nextCount) {
|
||||
memory->activeDMA = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (memory->activeDMA >= 0) {
|
||||
mTimingDeschedule(&dscore->timing, &memory->dmaEvent);
|
||||
mTimingSchedule(&dscore->timing, &memory->dmaEvent, memory->dma[memory->activeDMA].when - currentTime);
|
||||
} else {
|
||||
dscore->p->cpuBlocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DSDMAService(struct DSCommon* dscore, int number, struct GBADMA* info) {
|
||||
struct DSCoreMemory* memory = &dscore->memory;
|
||||
struct ARMCore* cpu = dscore->cpu;
|
||||
uint32_t width = 2 << GBADMARegisterGetWidth(info->reg);
|
||||
int32_t wordsRemaining = info->nextCount;
|
||||
uint32_t source = info->nextSource;
|
||||
uint32_t dest = info->nextDest;
|
||||
uint32_t sourceRegion = source >> DS_BASE_OFFSET;
|
||||
uint32_t destRegion = dest >> DS_BASE_OFFSET;
|
||||
int32_t cycles = 2;
|
||||
|
||||
if (info->count == info->nextCount) {
|
||||
if (width == 4) {
|
||||
cycles += dscore->p->memory.waitstatesNonseq32[sourceRegion] + dscore->p->memory.waitstatesNonseq32[destRegion];
|
||||
} else {
|
||||
cycles += dscore->p->memory.waitstatesNonseq16[sourceRegion] + dscore->p->memory.waitstatesNonseq16[destRegion];
|
||||
}
|
||||
source &= -width;
|
||||
dest &= -width;
|
||||
} else {
|
||||
if (width == 4) {
|
||||
cycles += dscore->p->memory.waitstatesSeq32[sourceRegion] + dscore->p->memory.waitstatesSeq32[destRegion];
|
||||
} else {
|
||||
cycles += dscore->p->memory.waitstatesSeq16[sourceRegion] + dscore->p->memory.waitstatesSeq16[destRegion];
|
||||
}
|
||||
}
|
||||
info->when += cycles;
|
||||
|
||||
uint32_t word;
|
||||
if (width == 4) {
|
||||
word = cpu->memory.load32(cpu, source, 0);
|
||||
cpu->memory.store32(cpu, dest, word, 0);
|
||||
} else {
|
||||
word = cpu->memory.load16(cpu, source, 0);
|
||||
cpu->memory.store16(cpu, dest, word, 0);
|
||||
}
|
||||
int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
|
||||
int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
|
||||
source += sourceOffset;
|
||||
dest += destOffset;
|
||||
--wordsRemaining;
|
||||
|
||||
info->nextCount = wordsRemaining;
|
||||
info->nextSource = source;
|
||||
info->nextDest = dest;
|
||||
if (!wordsRemaining) {
|
||||
info->nextCount |= 0x80000000;
|
||||
}
|
||||
DSDMAUpdate(dscore);
|
||||
}
|
|
@ -111,6 +111,7 @@ static void DSInit(void* cpu, struct mCPUComponent* component) {
|
|||
DS7InterruptHandlerInit(&ds->ds7.cpu->irqh);
|
||||
DS9InterruptHandlerInit(&ds->ds9.cpu->irqh);
|
||||
DSMemoryInit(ds);
|
||||
DSDMAInit(ds);
|
||||
|
||||
ds->video.p = ds;
|
||||
|
||||
|
@ -183,6 +184,7 @@ void DS7Reset(struct ARMCore* cpu) {
|
|||
mTimingClear(&ds->ds7.timing);
|
||||
CircleBufferInit(&ds->ds7.fifo, 64);
|
||||
DSMemoryReset(ds);
|
||||
DSDMAReset(&ds->ds7);
|
||||
DS7IOInit(ds);
|
||||
|
||||
struct DSCartridge* header = ds->romVf->map(ds->romVf, sizeof(*header), MAP_READ);
|
||||
|
@ -215,6 +217,7 @@ void DS9Reset(struct ARMCore* cpu) {
|
|||
struct DS* ds = (struct DS*) cpu->master;
|
||||
mTimingClear(&ds->ds9.timing);
|
||||
CircleBufferInit(&ds->ds9.fifo, 64);
|
||||
DSDMAReset(&ds->ds9);
|
||||
DS9IOInit(ds);
|
||||
|
||||
ds->activeCpu = cpu;
|
||||
|
|
80
src/ds/io.c
80
src/ds/io.c
|
@ -113,8 +113,47 @@ void DS7IOWrite8(struct DS* ds, uint32_t address, uint8_t value) {
|
|||
|
||||
void DS7IOWrite32(struct DS* ds, uint32_t address, uint32_t value) {
|
||||
switch (address) {
|
||||
case DS_REG_DMA0SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds7, 0, value);
|
||||
break;
|
||||
case DS_REG_DMA1SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds7, 1, value);
|
||||
break;
|
||||
case DS_REG_DMA2SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds7, 2, value);
|
||||
break;
|
||||
case DS_REG_DMA3SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds7, 3, value);
|
||||
break;
|
||||
|
||||
case DS_REG_DMA0DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds7, 0, value);
|
||||
break;
|
||||
case DS_REG_DMA1DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds7, 1, value);
|
||||
break;
|
||||
case DS_REG_DMA2DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds7, 2, value);
|
||||
break;
|
||||
case DS_REG_DMA3DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds7, 3, value);
|
||||
break;
|
||||
|
||||
case DS_REG_DMA0CNT_LO:
|
||||
DS7DMAWriteCNT(&ds->ds7, 0, value);
|
||||
break;
|
||||
case DS_REG_DMA1CNT_LO:
|
||||
DS7DMAWriteCNT(&ds->ds7, 1, value);
|
||||
break;
|
||||
case DS_REG_DMA2CNT_LO:
|
||||
DS7DMAWriteCNT(&ds->ds7, 2, value);
|
||||
break;
|
||||
case DS_REG_DMA3CNT_LO:
|
||||
DS7DMAWriteCNT(&ds->ds7, 3, value);
|
||||
break;
|
||||
|
||||
case DS_REG_IPCFIFOSEND_LO:
|
||||
DSIPCWriteFIFO(&ds->ds9, value);
|
||||
DSIPCWriteFIFO(&ds->ds7, value);
|
||||
break;
|
||||
case DS_REG_IE_LO:
|
||||
DSWriteIE(ds->ds7.cpu, ds->ds7.memory.io, value);
|
||||
|
@ -189,6 +228,45 @@ void DS9IOWrite8(struct DS* ds, uint32_t address, uint8_t value) {
|
|||
|
||||
void DS9IOWrite32(struct DS* ds, uint32_t address, uint32_t value) {
|
||||
switch (address) {
|
||||
case DS_REG_DMA0SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds9, 0, value);
|
||||
break;
|
||||
case DS_REG_DMA1SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds9, 1, value);
|
||||
break;
|
||||
case DS_REG_DMA2SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds9, 2, value);
|
||||
break;
|
||||
case DS_REG_DMA3SAD_LO:
|
||||
value = DSDMAWriteSAD(&ds->ds9, 3, value);
|
||||
break;
|
||||
|
||||
case DS_REG_DMA0DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds9, 0, value);
|
||||
break;
|
||||
case DS_REG_DMA1DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds9, 1, value);
|
||||
break;
|
||||
case DS_REG_DMA2DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds9, 2, value);
|
||||
break;
|
||||
case DS_REG_DMA3DAD_LO:
|
||||
value = DSDMAWriteDAD(&ds->ds9, 3, value);
|
||||
break;
|
||||
|
||||
case DS_REG_DMA0CNT_LO:
|
||||
DS9DMAWriteCNT(&ds->ds9, 0, value);
|
||||
break;
|
||||
case DS_REG_DMA1CNT_LO:
|
||||
DS9DMAWriteCNT(&ds->ds9, 1, value);
|
||||
break;
|
||||
case DS_REG_DMA2CNT_LO:
|
||||
DS9DMAWriteCNT(&ds->ds9, 2, value);
|
||||
break;
|
||||
case DS_REG_DMA3CNT_LO:
|
||||
DS9DMAWriteCNT(&ds->ds9, 3, value);
|
||||
break;
|
||||
|
||||
case DS_REG_IPCFIFOSEND_LO:
|
||||
DSIPCWriteFIFO(&ds->ds9, value);
|
||||
break;
|
||||
|
|
|
@ -77,8 +77,6 @@ static void DS7SetActiveRegion(struct ARMCore* cpu, uint32_t region);
|
|||
static void DS9SetActiveRegion(struct ARMCore* cpu, uint32_t region);
|
||||
static int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait);
|
||||
|
||||
static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
|
||||
|
||||
void DSMemoryInit(struct DS* ds) {
|
||||
struct ARMCore* arm7 = ds->ds7.cpu;
|
||||
arm7->memory.load32 = DS7Load32;
|
||||
|
|
Loading…
Reference in New Issue