all repos — mgba @ 8215afcee6baaad0f05926a46702a27ce631e33d

mGBA Game Boy Advance Emulator

src/gba/gba-io.c (view raw)

  1#include "gba-io.h"
  2
  3#include "gba-video.h"
  4
  5void GBAIOInit(struct GBA* gba) {
  6	gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
  7	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
  8}
  9
 10void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
 11	if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
 12		gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
 13	} else {
 14		switch (address) {
 15		// Video
 16		case REG_DISPSTAT:
 17			GBAVideoWriteDISPSTAT(&gba->video, value);
 18			break;
 19
 20		// DMA
 21		case REG_DMA0SAD_LO:
 22		case REG_DMA0DAD_LO:
 23		case REG_DMA1SAD_LO:
 24		case REG_DMA1DAD_LO:
 25		case REG_DMA2SAD_LO:
 26		case REG_DMA2DAD_LO:
 27		case REG_DMA3SAD_LO:
 28		case REG_DMA3DAD_LO:
 29			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
 30			break;
 31
 32		case REG_DMA0SAD_HI:
 33		case REG_DMA0DAD_HI:
 34		case REG_DMA1SAD_HI:
 35		case REG_DMA1DAD_HI:
 36		case REG_DMA2SAD_HI:
 37		case REG_DMA2DAD_HI:
 38		case REG_DMA3SAD_HI:
 39		case REG_DMA3DAD_HI:
 40			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
 41			break;
 42
 43		case REG_DMA0CNT_LO:
 44			GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
 45			break;
 46		case REG_DMA0CNT_HI:
 47			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
 48			break;
 49		case REG_DMA1CNT_LO:
 50			GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
 51			break;
 52		case REG_DMA1CNT_HI:
 53			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
 54			break;
 55		case REG_DMA2CNT_LO:
 56			GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
 57			break;
 58		case REG_DMA2CNT_HI:
 59			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
 60			break;
 61		case REG_DMA3CNT_LO:
 62			GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
 63			break;
 64		case REG_DMA3CNT_HI:
 65			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
 66			break;
 67
 68		// Timers
 69		case REG_TM0CNT_LO:
 70			GBATimerWriteTMCNT_LO(gba, 0, value);
 71			return;
 72		case REG_TM1CNT_LO:
 73			GBATimerWriteTMCNT_LO(gba, 1, value);
 74			return;
 75		case REG_TM2CNT_LO:
 76			GBATimerWriteTMCNT_LO(gba, 2, value);
 77			return;
 78		case REG_TM3CNT_LO:
 79			GBATimerWriteTMCNT_LO(gba, 3, value);
 80			return;
 81
 82		case REG_TM0CNT_HI:
 83			value &= 0x00C7;
 84			GBATimerWriteTMCNT_HI(gba, 0, value);
 85			break;
 86		case REG_TM1CNT_HI:
 87			value &= 0x00C7;
 88			GBATimerWriteTMCNT_HI(gba, 1, value);
 89			break;
 90		case REG_TM2CNT_HI:
 91			value &= 0x00C7;
 92			GBATimerWriteTMCNT_HI(gba, 2, value);
 93			break;
 94		case REG_TM3CNT_HI:
 95			value &= 0x00C7;
 96			GBATimerWriteTMCNT_HI(gba, 3, value);
 97			break;
 98
 99		// Interrupts and misc
100		case REG_WAITCNT:
101			GBAAdjustWaitstates(&gba->memory, value);
102			break;
103		case REG_IE:
104			GBAWriteIE(gba, value);
105			break;
106		case REG_IF:
107			value = gba->memory.io[REG_IF >> 1] & ~value;
108			break;
109		case REG_IME:
110			GBAWriteIME(gba, value);
111			break;
112		case REG_HALTCNT:
113			value &= 0x80;
114			if (!value) {
115				GBAHalt(gba);
116			} else {
117				GBALog(GBA_LOG_STUB, "Stop unimplemented");
118			}
119			return;
120		default:
121			GBALog(GBA_LOG_STUB, "Stub I/O register write: %03x", address);
122			break;
123		}
124	}
125	gba->memory.io[address >> 1] = value;
126}
127
128void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
129	switch (address) {
130	case REG_DMA0SAD_LO:
131		GBAMemoryWriteDMASAD(&gba->memory, 0, value);
132		break;
133	case REG_DMA0DAD_LO:
134		GBAMemoryWriteDMADAD(&gba->memory, 0, value);
135		break;
136	case REG_DMA1SAD_LO:
137		GBAMemoryWriteDMASAD(&gba->memory, 1, value);
138		break;
139	case REG_DMA1DAD_LO:
140		GBAMemoryWriteDMADAD(&gba->memory, 1, value);
141		break;
142	case REG_DMA2SAD_LO:
143		GBAMemoryWriteDMASAD(&gba->memory, 2, value);
144		break;
145	case REG_DMA2DAD_LO:
146		GBAMemoryWriteDMADAD(&gba->memory, 2, value);
147		break;
148	case REG_DMA3SAD_LO:
149		GBAMemoryWriteDMASAD(&gba->memory, 3, value);
150		break;
151	case REG_DMA3DAD_LO:
152		GBAMemoryWriteDMADAD(&gba->memory, 3, value);
153		break;
154	default:
155		GBAIOWrite(gba, address, value & 0xFFFF);
156		GBAIOWrite(gba, address | 2, value >> 16);
157		return;
158	}
159	gba->memory.io[address >> 1] = value;
160	gba->memory.io[(address >> 1) + 1] = value >> 16;
161}
162
163uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
164	switch (address) {
165	case REG_DISPSTAT:
166		return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
167		break;
168
169	case REG_TM0CNT_LO:
170		GBATimerUpdateRegister(gba, 0);
171		break;
172	case REG_TM1CNT_LO:
173		GBATimerUpdateRegister(gba, 1);
174		break;
175	case REG_TM2CNT_LO:
176		GBATimerUpdateRegister(gba, 2);
177		break;
178	case REG_TM3CNT_LO:
179		GBATimerUpdateRegister(gba, 3);
180		break;
181
182	case REG_KEYINPUT:
183		if (gba->keySource) {
184			return 0x3FF ^ *gba->keySource;
185		}
186		break;
187
188	case REG_DMA0CNT_LO:
189	case REG_DMA1CNT_LO:
190	case REG_DMA2CNT_LO:
191	case REG_DMA3CNT_LO:
192		// Write-only register
193		return 0;
194	case REG_VCOUNT:
195	case REG_DMA0CNT_HI:
196	case REG_DMA1CNT_HI:
197	case REG_DMA2CNT_HI:
198	case REG_DMA3CNT_HI:
199	case REG_IE:
200	case REG_IF:
201	case REG_WAITCNT:
202	case REG_IME:
203		// Handled transparently by registers
204		break;
205	default:
206		GBALog(GBA_LOG_STUB, "Stub I/O register read: %03x", address);
207		break;
208	}
209	return gba->memory.io[address >> 1];
210}