all repos — mgba @ 9c91235a34e5ecbb4512c56284265f2f5c0a06c0

mGBA Game Boy Advance Emulator

src/ds/io.c (view raw)

  1/* Copyright (c) 2013-2016 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 "io.h"
  7
  8#include "ds/ds.h"
  9
 10mLOG_DEFINE_CATEGORY(DS_IO, "DS I/O");
 11
 12static void _writeIPCSync(struct ARMCore* remoteCpu, uint16_t* remoteIo, int16_t value) {
 13	remoteIo[DS7_REG_IPCSYNC >> 1] &= 0xFFF0;
 14	remoteIo[DS7_REG_IPCSYNC >> 1] |= (value >> 8) & 0x0F;
 15	if (value & 0x2000 && remoteIo[DS7_REG_IPCSYNC >> 1] & 0x4000) {
 16		mLOG(DS_IO, STUB, "Unimplemented IPC IRQ");
 17		UNUSED(remoteCpu);
 18	}
 19}
 20
 21void DS7IOInit(struct DS* ds) {
 22	memset(ds->memory.io7, 0, sizeof(ds->memory.io7));
 23}
 24
 25void DS7IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
 26	switch (address) {
 27	case DS9_REG_IPCSYNC:
 28		value &= 0x6F00;
 29		value |= ds->memory.io7[address >> 1] & 0x000F;
 30		_writeIPCSync(ds->arm9, ds->memory.io9, value);
 31		break;
 32	default:
 33		mLOG(DS_IO, STUB, "Stub DS7 I/O register write: %06X:%04X", address, value);
 34		if (address >= DS7_REG_MAX) {
 35			mLOG(DS_IO, GAME_ERROR, "Write to unused DS7 I/O register: %06X:%04X", address, value);
 36			return;
 37		}
 38		break;
 39	}
 40	ds->memory.io7[address >> 1] = value;
 41}
 42
 43void DS7IOWrite8(struct DS* ds, uint32_t address, uint8_t value) {
 44	if (address < DS7_REG_MAX) {
 45		uint16_t value16 = value << (8 * (address & 1));
 46		value16 |= (ds->memory.io7[(address & 0xFFF) >> 1]) & ~(0xFF << (8 * (address & 1)));
 47		DS7IOWrite(ds, address & 0xFFFFFFFE, value16);
 48	} else {
 49		mLOG(DS, STUB, "Writing to unknown DS7 register: %08X:%02X", address, value);
 50	}
 51}
 52
 53void DS7IOWrite32(struct DS* ds, uint32_t address, uint32_t value);
 54
 55uint16_t DS7IORead(struct DS* ds, uint32_t address) {
 56	switch (address) {
 57	case DS7_REG_IPCSYNC:
 58		// Handled transparently by the registers
 59		break;
 60	default:
 61		mLOG(DS_IO, STUB, "Stub DS7 I/O register read: %06X", address);
 62	}
 63	if (address < DS7_REG_MAX) {
 64		return ds->memory.io7[address >> 1];
 65	}
 66	return 0;
 67}
 68
 69void DS9IOInit(struct DS* ds) {
 70	memset(ds->memory.io9, 0, sizeof(ds->memory.io9));
 71}
 72
 73void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
 74	switch (address) {
 75	case DS9_REG_IPCSYNC:
 76		value &= 0x6F00;
 77		value |= ds->memory.io9[address >> 1] & 0x000F;
 78		_writeIPCSync(ds->arm7, ds->memory.io7, value);
 79		break;
 80	default:
 81		mLOG(DS_IO, STUB, "Stub DS9 I/O register write: %06X:%04X", address, value);
 82		if (address >= DS7_REG_MAX) {
 83			mLOG(DS_IO, GAME_ERROR, "Write to unused DS9 I/O register: %06X:%04X", address, value);
 84			return;
 85		}
 86		break;
 87	}
 88	ds->memory.io9[address >> 1] = value;
 89}
 90
 91void DS9IOWrite8(struct DS* ds, uint32_t address, uint8_t value) {
 92	if (address < DS9_REG_MAX) {
 93		uint16_t value16 = value << (8 * (address & 1));
 94		value16 |= (ds->memory.io9[(address & 0x1FFF) >> 1]) & ~(0xFF << (8 * (address & 1)));
 95		DS9IOWrite(ds, address & 0xFFFFFFFE, value16);
 96	} else {
 97		mLOG(DS, STUB, "Writing to unknown DS9 register: %08X:%02X", address, value);
 98	}
 99}
100
101void DS9IOWrite32(struct DS* ds, uint32_t address, uint32_t value);
102
103uint16_t DS9IORead(struct DS* ds, uint32_t address) {
104	switch (address) {
105	case DS9_REG_IPCSYNC:
106		// Handled transparently by the registers
107		break;
108	default:
109		mLOG(DS_IO, STUB, "Stub DS9 I/O register read: %06X", address);
110	}
111	if (address < DS9_REG_MAX) {
112		return ds->memory.io9[address >> 1];
113	}
114	return 0;
115}