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}