all repos — mgba @ 0053f85922a69fade4c543e53d8ef6e90c6e0a6b

mGBA Game Boy Advance Emulator

src/ds/ipc.c (view raw)

 1/* Copyright (c) 2013-2017 Jeffrey Pfau
 2 *
 3 * This Source Code Form is subject to the terms of the Mozilla Public
 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 6#include <mgba/internal/ds/ipc.h>
 7
 8#include <mgba/internal/ds/ds.h>
 9#include <mgba/internal/ds/io.h>
10
11void DSIPCWriteSYNC(struct ARMCore* remoteCpu, uint16_t* remoteIo, int16_t value) {
12	remoteIo[DS_REG_IPCSYNC >> 1] &= 0xFFF0;
13	remoteIo[DS_REG_IPCSYNC >> 1] |= (value >> 8) & 0x0F;
14	if (value & 0x2000 && remoteIo[DS_REG_IPCSYNC >> 1] & 0x4000) {
15		mLOG(DS_IO, STUB, "Unimplemented IPC IRQ");
16		UNUSED(remoteCpu);
17	}
18}
19
20int16_t DSIPCWriteFIFOCNT(struct DSCommon* dscore, int16_t value) {
21	value &= 0xC40C;
22	int16_t oldValue = dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] & 0x4303;
23	int16_t newValue = value | oldValue;
24	if (DSIPCFIFOCNTIsError(value)) {
25		newValue = DSIPCFIFOCNTClearError(0x8FFF);
26	}
27	if (DSIPCFIFOCNTIsSendClear(newValue)) {
28		CircleBufferClear(&dscore->ipc->fifo);
29	}
30	return newValue;
31}
32
33void DSIPCWriteFIFO(struct DSCommon* dscore, int32_t value) {
34	if (!DSIPCFIFOCNTIsEnable(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1])) {
35		return;
36	}
37	CircleBufferWrite32(&dscore->ipc->fifo, value);
38	size_t fullness = CircleBufferSize(&dscore->ipc->fifo);
39	if (fullness == 4) {
40		dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearSendEmpty(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]);
41		dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearRecvEmpty(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]);
42		if (DSIPCFIFOCNTIsRecvIRQ(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1])) {
43			// TODO: Adaptive time slicing?
44			DSRaiseIRQ(dscore->ipc->cpu, dscore->ipc->memory.io, DS_IRQ_IPC_NOT_EMPTY);
45		}
46	} else if (fullness == 64) {
47		dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillSendFull(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]);
48		dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillRecvFull(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]);
49	}
50}