From 3679e1e8d6049a150b7f55a71808df7b2aba4bd7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 Jan 2017 15:02:19 -0800 Subject: [PATCH] DS IPC: Implement IPC read --- include/mgba/internal/ds/io.h | 2 ++ src/ds/io.c | 20 ++++++++++++++++++++ src/ds/ipc.c | 20 ++++++++++++++++++++ src/ds/memory.c | 4 ++-- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/mgba/internal/ds/io.h b/include/mgba/internal/ds/io.h index 047cfb603..c2be86de0 100644 --- a/include/mgba/internal/ds/io.h +++ b/include/mgba/internal/ds/io.h @@ -282,12 +282,14 @@ void DS7IOWrite(struct DS* ds, uint32_t address, uint16_t value); void DS7IOWrite8(struct DS* ds, uint32_t address, uint8_t value); void DS7IOWrite32(struct DS* ds, uint32_t address, uint32_t value); uint16_t DS7IORead(struct DS* ds, uint32_t address); +uint32_t DS7IORead32(struct DS* ds, uint32_t address); void DS9IOInit(struct DS* ds); void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value); void DS9IOWrite8(struct DS* ds, uint32_t address, uint8_t value); void DS9IOWrite32(struct DS* ds, uint32_t address, uint32_t value); uint16_t DS9IORead(struct DS* ds, uint32_t address); +uint32_t DS9IORead32(struct DS* ds, uint32_t address); CXX_GUARD_END diff --git a/src/ds/io.c b/src/ds/io.c index dc7c26933..4d75ae2b0 100644 --- a/src/ds/io.c +++ b/src/ds/io.c @@ -207,6 +207,7 @@ uint16_t DS7IORead(struct DS* ds, uint32_t address) { case DS_REG_TM2CNT_HI: case DS_REG_TM3CNT_HI: case DS_REG_IPCSYNC: + case DS_REG_IPCFIFOCNT: case DS_REG_IME: case DS_REG_IE_LO: case DS_REG_IE_HI: @@ -223,6 +224,15 @@ uint16_t DS7IORead(struct DS* ds, uint32_t address) { return 0; } +uint32_t DS7IORead32(struct DS* ds, uint32_t address) { + switch (address) { + case DS_REG_IPCFIFORECV_LO: + return DSIPCReadFIFO(&ds->ds7); + default: + return DS7IORead(ds, address & 0x00FFFFFC) | (DS7IORead(ds, (address & 0x00FFFFFC) | 2) << 16); + } +} + void DS9IOInit(struct DS* ds) { memset(ds->memory.io9, 0, sizeof(ds->memory.io9)); } @@ -328,6 +338,7 @@ uint16_t DS9IORead(struct DS* ds, uint32_t address) { case DS_REG_TM2CNT_HI: case DS_REG_TM3CNT_HI: case DS_REG_IPCSYNC: + case DS_REG_IPCFIFOCNT: case DS_REG_IME: case DS_REG_IE_LO: case DS_REG_IE_HI: @@ -343,3 +354,12 @@ uint16_t DS9IORead(struct DS* ds, uint32_t address) { } return 0; } + +uint32_t DS9IORead32(struct DS* ds, uint32_t address) { + switch (address) { + case DS_REG_IPCFIFORECV_LO: + return DSIPCReadFIFO(&ds->ds9); + default: + return DS9IORead(ds, address & 0x00FFFFFC) | (DS9IORead(ds, (address & 0x00FFFFFC) | 2) << 16); + } +} diff --git a/src/ds/ipc.c b/src/ds/ipc.c index 570fd4dc3..2ba387dda 100644 --- a/src/ds/ipc.c +++ b/src/ds/ipc.c @@ -48,3 +48,23 @@ void DSIPCWriteFIFO(struct DSCommon* dscore, int32_t value) { dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillRecvFull(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]); } } + +int32_t DSIPCReadFIFO(struct DSCommon* dscore) { + if (!DSIPCFIFOCNTIsEnable(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1])) { + return 0; + } + int32_t value = ((int32_t*) dscore->ipc->memory.io)[DS_REG_IPCFIFOSEND_LO >> 2]; // TODO: actual last value + CircleBufferRead32(&dscore->fifo, &value); + size_t fullness = CircleBufferSize(&dscore->fifo); + dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearRecvFull(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]); + dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearSendFull(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]); + if (fullness == 0) { + dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillRecvEmpty(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]); + dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillSendEmpty(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]); + if (DSIPCFIFOCNTIsSendIRQ(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1])) { + // TODO: Adaptive time slicing? + DSRaiseIRQ(dscore->ipc->cpu, dscore->ipc->memory.io, DS_IRQ_IPC_NOT_EMPTY); + } + } + return value; +} diff --git a/src/ds/memory.c b/src/ds/memory.c index c778391a3..df5e0b246 100644 --- a/src/ds/memory.c +++ b/src/ds/memory.c @@ -237,7 +237,7 @@ uint32_t DS7Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { mLOG(DS_MEM, STUB, "Unimplemented DS7 Load32: %08X", address); break; case DS_REGION_IO: - value = DS7IORead(ds, address & 0x00FFFFFC) | (DS7IORead(ds, (address & 0x00FFFFFC) | 2) << 16); + value = DS7IORead32(ds, address & 0x00FFFFFC); break; default: mLOG(DS_MEM, STUB, "Unimplemented DS7 Load32: %08X", address); @@ -681,7 +681,7 @@ uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { mLOG(DS_MEM, STUB, "Unimplemented DS9 Load32: %08X", address); break; case DS_REGION_IO: - value = DS9IORead(ds, address & 0x00FFFFFC) | (DS9IORead(ds, (address & 0x00FFFFFC) | 2) << 16); + value = DS9IORead32(ds, address & 0x00FFFFFC); break; case DS9_REGION_BIOS: // TODO: Fix undersized BIOS