all repos — mgba @ cfb0115c0efe5e328ad880ec6e090829f9615be7

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