DS IPC: Implement IPC read
Vicki Pfau vi@endrift.com
Mon, 30 Jan 2017 15:02:19 -0800
4 files changed,
44 insertions(+),
2 deletions(-)
M
include/mgba/internal/ds/io.h
→
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
M
src/ds/io.c
→
src/ds/io.c
@@ -207,6 +207,7 @@ case DS_REG_TM1CNT_HI:
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:@@ -221,6 +222,15 @@ if (address < DS7_REG_MAX) {
return ds->memory.io7[address >> 1]; } 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) {@@ -328,6 +338,7 @@ case DS_REG_TM1CNT_HI:
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 @@ return ds->ds9.memory.io[address >> 1];
} 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); + } +}
M
src/ds/ipc.c
→
src/ds/ipc.c
@@ -48,3 +48,23 @@ dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillSendFull(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]);
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; +}
M
src/ds/memory.c
→
src/ds/memory.c
@@ -237,7 +237,7 @@ }
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 @@ }
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