all repos — mgba @ eac9dfb325b1fcbef9b69c87aed70094ef381e3b

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