all repos — mgba @ b3dc065144f44d782d069d0d6ad34abe2332d0e5

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		value = 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	case REG_FIFO_B_LO:
213		GBAAudioWriteFIFO(&gba->audio, address, value);
214		break;
215	case REG_DMA0SAD_LO:
216		GBAMemoryWriteDMASAD(&gba->memory, 0, value);
217		break;
218	case REG_DMA0DAD_LO:
219		GBAMemoryWriteDMADAD(&gba->memory, 0, value);
220		break;
221	case REG_DMA1SAD_LO:
222		GBAMemoryWriteDMASAD(&gba->memory, 1, value);
223		break;
224	case REG_DMA1DAD_LO:
225		GBAMemoryWriteDMADAD(&gba->memory, 1, value);
226		break;
227	case REG_DMA2SAD_LO:
228		GBAMemoryWriteDMASAD(&gba->memory, 2, value);
229		break;
230	case REG_DMA2DAD_LO:
231		GBAMemoryWriteDMADAD(&gba->memory, 2, value);
232		break;
233	case REG_DMA3SAD_LO:
234		GBAMemoryWriteDMASAD(&gba->memory, 3, value);
235		break;
236	case REG_DMA3DAD_LO:
237		GBAMemoryWriteDMADAD(&gba->memory, 3, value);
238		break;
239	default:
240		GBAIOWrite(gba, address, value & 0xFFFF);
241		GBAIOWrite(gba, address | 2, value >> 16);
242		return;
243	}
244	gba->memory.io[address >> 1] = value;
245	gba->memory.io[(address >> 1) + 1] = value >> 16;
246}
247
248uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
249	switch (address) {
250	case REG_DISPSTAT:
251		return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
252		break;
253
254	case REG_TM0CNT_LO:
255		GBATimerUpdateRegister(gba, 0);
256		break;
257	case REG_TM1CNT_LO:
258		GBATimerUpdateRegister(gba, 1);
259		break;
260	case REG_TM2CNT_LO:
261		GBATimerUpdateRegister(gba, 2);
262		break;
263	case REG_TM3CNT_LO:
264		GBATimerUpdateRegister(gba, 3);
265		break;
266
267	case REG_KEYINPUT:
268		if (gba->keySource) {
269			return 0x3FF ^ *gba->keySource;
270		}
271		break;
272
273	case REG_DMA0CNT_LO:
274	case REG_DMA1CNT_LO:
275	case REG_DMA2CNT_LO:
276	case REG_DMA3CNT_LO:
277		// Write-only register
278		return 0;
279	case REG_DISPCNT:
280	case REG_VCOUNT:
281	case REG_DMA0CNT_HI:
282	case REG_DMA1CNT_HI:
283	case REG_DMA2CNT_HI:
284	case REG_DMA3CNT_HI:
285	case REG_IE:
286	case REG_IF:
287	case REG_WAITCNT:
288	case REG_IME:
289		// Handled transparently by registers
290		break;
291	case 0x20A:
292		// Some bad interrupt libraries will read from this
293		break;
294	default:
295		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
296		break;
297	}
298	return gba->memory.io[address >> 1];
299}