all repos — mgba @ ea41ef7ae6c57c9b604e61ad6251935aef0b00e9

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_RCNT >> 1] = 0x8000;
  8	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
  9}
 10
 11void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
 12	if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
 13		value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
 14	} else {
 15		switch (address) {
 16		// Video
 17		case REG_DISPSTAT:
 18			value &= 0xFFF8;
 19			GBAVideoWriteDISPSTAT(&gba->video, value);
 20			break;
 21
 22		// Audio
 23		case REG_SOUND1CNT_LO:
 24			GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
 25			break;
 26		case REG_SOUND1CNT_HI:
 27			GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
 28			break;
 29		case REG_SOUND1CNT_X:
 30			GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
 31			break;
 32		case REG_SOUND2CNT_LO:
 33			GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
 34			break;
 35		case REG_SOUND2CNT_HI:
 36			GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
 37			break;
 38		case REG_SOUND3CNT_LO:
 39			GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
 40			break;
 41		case REG_SOUND3CNT_HI:
 42			GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
 43			break;
 44		case REG_SOUND3CNT_X:
 45			GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
 46			break;
 47		case REG_SOUND4CNT_LO:
 48			GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
 49			break;
 50		case REG_SOUND4CNT_HI:
 51			GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
 52			break;
 53		case REG_SOUNDCNT_LO:
 54			GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
 55			break;
 56		case REG_SOUNDCNT_HI:
 57			GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
 58			break;
 59		case REG_SOUNDCNT_X:
 60			GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
 61			break;
 62
 63		case REG_WAVE_RAM0_LO:
 64		case REG_WAVE_RAM1_LO:
 65		case REG_WAVE_RAM2_LO:
 66		case REG_WAVE_RAM3_LO:
 67		case REG_FIFO_A_LO:
 68		case REG_FIFO_B_LO:
 69			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
 70			break;
 71
 72		case REG_WAVE_RAM0_HI:
 73		case REG_WAVE_RAM1_HI:
 74		case REG_WAVE_RAM2_HI:
 75		case REG_WAVE_RAM3_HI:
 76		case REG_FIFO_A_HI:
 77		case REG_FIFO_B_HI:
 78			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
 79			break;
 80
 81		// DMA
 82		case REG_DMA0SAD_LO:
 83		case REG_DMA0DAD_LO:
 84		case REG_DMA1SAD_LO:
 85		case REG_DMA1DAD_LO:
 86		case REG_DMA2SAD_LO:
 87		case REG_DMA2DAD_LO:
 88		case REG_DMA3SAD_LO:
 89		case REG_DMA3DAD_LO:
 90			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
 91			break;
 92
 93		case REG_DMA0SAD_HI:
 94		case REG_DMA0DAD_HI:
 95		case REG_DMA1SAD_HI:
 96		case REG_DMA1DAD_HI:
 97		case REG_DMA2SAD_HI:
 98		case REG_DMA2DAD_HI:
 99		case REG_DMA3SAD_HI:
100		case REG_DMA3DAD_HI:
101			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
102			break;
103
104		case REG_DMA0CNT_LO:
105			GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
106			break;
107		case REG_DMA0CNT_HI:
108			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
109			break;
110		case REG_DMA1CNT_LO:
111			GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
112			break;
113		case REG_DMA1CNT_HI:
114			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
115			break;
116		case REG_DMA2CNT_LO:
117			GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
118			break;
119		case REG_DMA2CNT_HI:
120			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
121			break;
122		case REG_DMA3CNT_LO:
123			GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
124			break;
125		case REG_DMA3CNT_HI:
126			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
127			break;
128
129		// Timers
130		case REG_TM0CNT_LO:
131			GBATimerWriteTMCNT_LO(gba, 0, value);
132			return;
133		case REG_TM1CNT_LO:
134			GBATimerWriteTMCNT_LO(gba, 1, value);
135			return;
136		case REG_TM2CNT_LO:
137			GBATimerWriteTMCNT_LO(gba, 2, value);
138			return;
139		case REG_TM3CNT_LO:
140			GBATimerWriteTMCNT_LO(gba, 3, value);
141			return;
142
143		case REG_TM0CNT_HI:
144			value &= 0x00C7;
145			GBATimerWriteTMCNT_HI(gba, 0, value);
146			break;
147		case REG_TM1CNT_HI:
148			value &= 0x00C7;
149			GBATimerWriteTMCNT_HI(gba, 1, value);
150			break;
151		case REG_TM2CNT_HI:
152			value &= 0x00C7;
153			GBATimerWriteTMCNT_HI(gba, 2, value);
154			break;
155		case REG_TM3CNT_HI:
156			value &= 0x00C7;
157			GBATimerWriteTMCNT_HI(gba, 3, value);
158			break;
159
160		// Interrupts and misc
161		case REG_WAITCNT:
162			GBAAdjustWaitstates(&gba->memory, value);
163			break;
164		case REG_IE:
165			GBAWriteIE(gba, value);
166			break;
167		case REG_IF:
168			value = gba->memory.io[REG_IF >> 1] & ~value;
169			break;
170		case REG_IME:
171			GBAWriteIME(gba, value);
172			break;
173		case 0x20A:
174			// Some bad interrupt libraries will write to this
175			break;
176		default:
177			GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
178			break;
179		}
180	}
181	gba->memory.io[address >> 1] = value;
182}
183
184void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
185	if (address == REG_HALTCNT) {
186		value &= 0x80;
187		if (!value) {
188			GBAHalt(gba);
189		} else {
190			GBALog(gba, GBA_LOG_STUB, "Stop unimplemented");
191		}
192		return;
193	}
194	uint16_t value16 = value << (8 * (address & 1));
195	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
196	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
197}
198
199void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
200	switch (address) {
201	case REG_WAVE_RAM0_LO:
202		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
203		break;
204	case REG_WAVE_RAM1_LO:
205		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
206		break;
207	case REG_WAVE_RAM2_LO:
208		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
209		break;
210	case REG_WAVE_RAM3_LO:
211		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
212		break;
213	case REG_FIFO_A_LO:
214	case REG_FIFO_B_LO:
215		GBAAudioWriteFIFO(&gba->audio, address, 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_DISPCNT:
282	case REG_VCOUNT:
283	case REG_BG0CNT:
284	case REG_BG1CNT:
285	case REG_BG2CNT:
286	case REG_BG3CNT:
287	case REG_DMA0CNT_HI:
288	case REG_DMA1CNT_HI:
289	case REG_DMA2CNT_HI:
290	case REG_DMA3CNT_HI:
291	case REG_IE:
292	case REG_IF:
293	case REG_WAITCNT:
294	case REG_IME:
295		// Handled transparently by registers
296		break;
297	case 0x20A:
298		// Some bad interrupt libraries will read from this
299		break;
300	default:
301		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
302		break;
303	}
304	return gba->memory.io[address >> 1];
305}