all repos — mgba @ 71ec6162f11ab51bb159af78a9a3a84538189cb6

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		// Audio
 21		case REG_SOUND1CNT_LO:
 22			GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
 23			break;
 24		case REG_SOUND1CNT_HI:
 25			GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
 26			break;
 27		case REG_SOUND1CNT_X:
 28			GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
 29			break;
 30		case REG_SOUND2CNT_LO:
 31			GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
 32			break;
 33		case REG_SOUND2CNT_HI:
 34			GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
 35			break;
 36		case REG_SOUND3CNT_LO:
 37			GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
 38			break;
 39		case REG_SOUND3CNT_HI:
 40			GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
 41			break;
 42		case REG_SOUND3CNT_X:
 43			GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
 44			break;
 45		case REG_SOUND4CNT_LO:
 46			GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
 47			break;
 48		case REG_SOUND4CNT_HI:
 49			GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
 50			break;
 51		case REG_SOUNDCNT_LO:
 52			GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
 53			break;
 54		case REG_SOUNDCNT_HI:
 55			GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
 56			break;
 57		case REG_SOUNDCNT_X:
 58			GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
 59			break;
 60
 61		case REG_WAVE_RAM0_LO:
 62		case REG_WAVE_RAM1_LO:
 63		case REG_WAVE_RAM2_LO:
 64		case REG_WAVE_RAM3_LO:
 65		case REG_FIFO_A_LO:
 66		case REG_FIFO_B_LO:
 67			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
 68			break;
 69
 70		case REG_WAVE_RAM0_HI:
 71		case REG_WAVE_RAM1_HI:
 72		case REG_WAVE_RAM2_HI:
 73		case REG_WAVE_RAM3_HI:
 74		case REG_FIFO_A_HI:
 75		case REG_FIFO_B_HI:
 76			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
 77			break;
 78
 79		// DMA
 80		case REG_DMA0SAD_LO:
 81		case REG_DMA0DAD_LO:
 82		case REG_DMA1SAD_LO:
 83		case REG_DMA1DAD_LO:
 84		case REG_DMA2SAD_LO:
 85		case REG_DMA2DAD_LO:
 86		case REG_DMA3SAD_LO:
 87		case REG_DMA3DAD_LO:
 88			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
 89			break;
 90
 91		case REG_DMA0SAD_HI:
 92		case REG_DMA0DAD_HI:
 93		case REG_DMA1SAD_HI:
 94		case REG_DMA1DAD_HI:
 95		case REG_DMA2SAD_HI:
 96		case REG_DMA2DAD_HI:
 97		case REG_DMA3SAD_HI:
 98		case REG_DMA3DAD_HI:
 99			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
100			break;
101
102		case REG_DMA0CNT_LO:
103			GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
104			break;
105		case REG_DMA0CNT_HI:
106			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
107			break;
108		case REG_DMA1CNT_LO:
109			GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
110			break;
111		case REG_DMA1CNT_HI:
112			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
113			break;
114		case REG_DMA2CNT_LO:
115			GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
116			break;
117		case REG_DMA2CNT_HI:
118			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
119			break;
120		case REG_DMA3CNT_LO:
121			GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
122			break;
123		case REG_DMA3CNT_HI:
124			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
125			break;
126
127		// Timers
128		case REG_TM0CNT_LO:
129			GBATimerWriteTMCNT_LO(gba, 0, value);
130			return;
131		case REG_TM1CNT_LO:
132			GBATimerWriteTMCNT_LO(gba, 1, value);
133			return;
134		case REG_TM2CNT_LO:
135			GBATimerWriteTMCNT_LO(gba, 2, value);
136			return;
137		case REG_TM3CNT_LO:
138			GBATimerWriteTMCNT_LO(gba, 3, value);
139			return;
140
141		case REG_TM0CNT_HI:
142			value &= 0x00C7;
143			GBATimerWriteTMCNT_HI(gba, 0, value);
144			break;
145		case REG_TM1CNT_HI:
146			value &= 0x00C7;
147			GBATimerWriteTMCNT_HI(gba, 1, value);
148			break;
149		case REG_TM2CNT_HI:
150			value &= 0x00C7;
151			GBATimerWriteTMCNT_HI(gba, 2, value);
152			break;
153		case REG_TM3CNT_HI:
154			value &= 0x00C7;
155			GBATimerWriteTMCNT_HI(gba, 3, value);
156			break;
157
158		// Interrupts and misc
159		case REG_WAITCNT:
160			GBAAdjustWaitstates(&gba->memory, value);
161			break;
162		case REG_IE:
163			GBAWriteIE(gba, value);
164			break;
165		case REG_IF:
166			value = gba->memory.io[REG_IF >> 1] & ~value;
167			break;
168		case REG_IME:
169			GBAWriteIME(gba, value);
170			break;
171		case 0x20A:
172			// Some bad interrupt libraries will write to this
173			break;
174		default:
175			GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
176			break;
177		}
178	}
179	gba->memory.io[address >> 1] = value;
180}
181
182void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
183	if (address == REG_HALTCNT) {
184		value &= 0x80;
185		if (!value) {
186			GBAHalt(gba);
187		} else {
188			GBALog(gba, GBA_LOG_STUB, "Stop unimplemented");
189		}
190		return;
191	}
192	uint16_t value16 = value << (8 * (address & 1));
193	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
194	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
195}
196
197void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
198	switch (address) {
199	case REG_WAVE_RAM0_LO:
200		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
201		break;
202	case REG_WAVE_RAM1_LO:
203		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
204		break;
205	case REG_WAVE_RAM2_LO:
206		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
207		break;
208	case REG_WAVE_RAM3_LO:
209		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
210		break;
211	case REG_FIFO_A_LO:
212		GBAAudioWriteFIFO(&gba->audio, 0, value);
213		break;
214	case REG_FIFO_B_LO:
215		GBAAudioWriteFIFO(&gba->audio, 1, value);
216		break;
217	case REG_DMA0SAD_LO:
218		GBAMemoryWriteDMASAD(&gba->memory, 0, value);
219		break;
220	case REG_DMA0DAD_LO:
221		GBAMemoryWriteDMADAD(&gba->memory, 0, value);
222		break;
223	case REG_DMA1SAD_LO:
224		GBAMemoryWriteDMASAD(&gba->memory, 1, value);
225		break;
226	case REG_DMA1DAD_LO:
227		GBAMemoryWriteDMADAD(&gba->memory, 1, value);
228		break;
229	case REG_DMA2SAD_LO:
230		GBAMemoryWriteDMASAD(&gba->memory, 2, value);
231		break;
232	case REG_DMA2DAD_LO:
233		GBAMemoryWriteDMADAD(&gba->memory, 2, value);
234		break;
235	case REG_DMA3SAD_LO:
236		GBAMemoryWriteDMASAD(&gba->memory, 3, value);
237		break;
238	case REG_DMA3DAD_LO:
239		GBAMemoryWriteDMADAD(&gba->memory, 3, value);
240		break;
241	default:
242		GBAIOWrite(gba, address, value & 0xFFFF);
243		GBAIOWrite(gba, address | 2, value >> 16);
244		return;
245	}
246	gba->memory.io[address >> 1] = value;
247	gba->memory.io[(address >> 1) + 1] = value >> 16;
248}
249
250uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
251	switch (address) {
252	case REG_DISPSTAT:
253		return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
254		break;
255
256	case REG_TM0CNT_LO:
257		GBATimerUpdateRegister(gba, 0);
258		break;
259	case REG_TM1CNT_LO:
260		GBATimerUpdateRegister(gba, 1);
261		break;
262	case REG_TM2CNT_LO:
263		GBATimerUpdateRegister(gba, 2);
264		break;
265	case REG_TM3CNT_LO:
266		GBATimerUpdateRegister(gba, 3);
267		break;
268
269	case REG_KEYINPUT:
270		if (gba->keySource) {
271			return 0x3FF ^ *gba->keySource;
272		}
273		break;
274
275	case REG_DMA0CNT_LO:
276	case REG_DMA1CNT_LO:
277	case REG_DMA2CNT_LO:
278	case REG_DMA3CNT_LO:
279		// Write-only register
280		return 0;
281	case REG_VCOUNT:
282	case REG_DMA0CNT_HI:
283	case REG_DMA1CNT_HI:
284	case REG_DMA2CNT_HI:
285	case REG_DMA3CNT_HI:
286	case REG_IE:
287	case REG_IF:
288	case REG_WAITCNT:
289	case REG_IME:
290		// Handled transparently by registers
291		break;
292	case 0x20A:
293		// Some bad interrupt libraries will read from this
294		break;
295	default:
296		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
297		break;
298	}
299	return gba->memory.io[address >> 1];
300}