src/gba/gba.c (view raw)
1#include "gba.h"
2
3#include "gba-bios.h"
4#include "gba-io.h"
5#include "gba-thread.h"
6#include "memory.h"
7
8#include "debugger.h"
9
10#include <limits.h>
11#include <stdarg.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/stat.h>
16
17const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
18
19enum {
20 SP_BASE_SYSTEM = 0x03FFFF00,
21 SP_BASE_IRQ = 0x03FFFFA0,
22 SP_BASE_SUPERVISOR = 0x03FFFFE0
23};
24
25struct GBACartridgeOverride {
26 uint32_t id;
27 enum SavedataType type;
28 int gpio;
29};
30
31static const struct GBACartridgeOverride _overrides[] = {
32 // Boktai: The Sun is in Your Hand
33 { 'EI3U', SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR },
34 { 'PI3U', SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR },
35
36 // Boktai 2: Solar Boy Django
37 { 'E23U', SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR },
38 { 'P23U', SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR },
39
40 // Drill Dozer
41 { 'J94V', SAVEDATA_SRAM, GPIO_RUMBLE },
42 { 'E94V', SAVEDATA_SRAM, GPIO_RUMBLE },
43
44 // Pokemon Ruby
45 { 'JVXA', SAVEDATA_FLASH1M, GPIO_RTC },
46 { 'EVXA', SAVEDATA_FLASH1M, GPIO_RTC },
47 { 'PVXA', SAVEDATA_FLASH1M, GPIO_RTC },
48 { 'IVXA', SAVEDATA_FLASH1M, GPIO_RTC },
49 { 'SVXA', SAVEDATA_FLASH1M, GPIO_RTC },
50 { 'DVXA', SAVEDATA_FLASH1M, GPIO_RTC },
51 { 'FVXA', SAVEDATA_FLASH1M, GPIO_RTC },
52
53 // Pokemon Sapphire
54 { 'JPXA', SAVEDATA_FLASH1M, GPIO_RTC },
55 { 'EPXA', SAVEDATA_FLASH1M, GPIO_RTC },
56 { 'PPXA', SAVEDATA_FLASH1M, GPIO_RTC },
57 { 'IPXA', SAVEDATA_FLASH1M, GPIO_RTC },
58 { 'SPXA', SAVEDATA_FLASH1M, GPIO_RTC },
59 { 'DPXA', SAVEDATA_FLASH1M, GPIO_RTC },
60 { 'FPXA', SAVEDATA_FLASH1M, GPIO_RTC },
61
62 // Pokemon Emerald
63 { 'JEPB', SAVEDATA_FLASH1M, GPIO_RTC },
64 { 'EEPB', SAVEDATA_FLASH1M, GPIO_RTC },
65 { 'PEPB', SAVEDATA_FLASH1M, GPIO_RTC },
66 { 'IEPB', SAVEDATA_FLASH1M, GPIO_RTC },
67 { 'SEPB', SAVEDATA_FLASH1M, GPIO_RTC },
68 { 'DEPB', SAVEDATA_FLASH1M, GPIO_RTC },
69 { 'FEPB', SAVEDATA_FLASH1M, GPIO_RTC },
70
71 // Pokemon FireRed
72 { 'JRPB', SAVEDATA_FLASH1M, GPIO_NONE },
73 { 'ERPB', SAVEDATA_FLASH1M, GPIO_NONE },
74 { 'PRPB', SAVEDATA_FLASH1M, GPIO_NONE },
75
76 // Pokemon LeafGreen
77 { 'JGPB', SAVEDATA_FLASH1M, GPIO_NONE },
78 { 'EGPB', SAVEDATA_FLASH1M, GPIO_NONE },
79 { 'PGPB', SAVEDATA_FLASH1M, GPIO_NONE },
80
81 // RockMan EXE 4.5 - Real Operation
82 { 'J4RB', SAVEDATA_FLASH512, GPIO_RTC },
83
84 // Super Mario Advance 4
85 { 'J4XA', SAVEDATA_FLASH1M, GPIO_NONE },
86 { 'E4XA', SAVEDATA_FLASH1M, GPIO_NONE },
87 { 'P4XA', SAVEDATA_FLASH1M, GPIO_NONE },
88
89 // Wario Ware Twisted
90 { 'JWZR', SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO },
91 { 'EWZR', SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO },
92 { 'PWZR', SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO },
93
94 { 0, 0, 0 }
95};
96
97static void GBAProcessEvents(struct ARMBoard* board);
98static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles);
99static void GBAHitStub(struct ARMBoard* board, uint32_t opcode);
100static void GBAIllegal(struct ARMBoard* board, uint32_t opcode);
101
102static void _checkOverrides(struct GBA* gba, uint32_t code);
103
104void GBAInit(struct GBA* gba) {
105 gba->debugger = 0;
106 gba->savefile = 0;
107
108 ARMInit(&gba->cpu);
109
110 gba->memory.p = gba;
111 GBAMemoryInit(&gba->memory);
112 ARMAssociateMemory(&gba->cpu, &gba->memory.d);
113
114 gba->board.p = gba;
115 GBABoardInit(&gba->board);
116 ARMAssociateBoard(&gba->cpu, &gba->board.d);
117
118 gba->video.p = gba;
119 GBAVideoInit(&gba->video);
120
121 gba->audio.p = gba;
122 GBAAudioInit(&gba->audio);
123
124 GBAIOInit(gba);
125
126 gba->timersEnabled = 0;
127 memset(gba->timers, 0, sizeof(gba->timers));
128
129 gba->springIRQ = 0;
130 gba->keySource = 0;
131 gba->rotationSource = 0;
132 gba->rumble = 0;
133
134 gba->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR;
135
136 ARMReset(&gba->cpu);
137}
138
139void GBADeinit(struct GBA* gba) {
140 GBAMemoryDeinit(&gba->memory);
141 GBAVideoDeinit(&gba->video);
142 GBAAudioDeinit(&gba->audio);
143}
144
145void GBABoardInit(struct GBABoard* board) {
146 board->d.reset = GBABoardReset;
147 board->d.processEvents = GBAProcessEvents;
148 board->d.swi16 = GBASwi16;
149 board->d.swi32 = GBASwi32;
150 board->d.hitIllegal = GBAIllegal;
151 board->d.readCPSR = GBATestIRQ;
152 board->d.hitStub = GBAHitStub;
153}
154
155void GBABoardReset(struct ARMBoard* board) {
156 struct ARMCore* cpu = board->cpu;
157 ARMSetPrivilegeMode(cpu, MODE_IRQ);
158 cpu->gprs[ARM_SP] = SP_BASE_IRQ;
159 ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
160 cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
161 ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
162 cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
163}
164
165static void GBAProcessEvents(struct ARMBoard* board) {
166 struct GBABoard* gbaBoard = (struct GBABoard*) board;
167 int32_t cycles = board->cpu->cycles;
168 int32_t nextEvent = INT_MAX;
169 int32_t testEvent;
170
171 if (gbaBoard->p->springIRQ) {
172 ARMRaiseIRQ(&gbaBoard->p->cpu);
173 gbaBoard->p->springIRQ = 0;
174 }
175
176 testEvent = GBAVideoProcessEvents(&gbaBoard->p->video, cycles);
177 if (testEvent < nextEvent) {
178 nextEvent = testEvent;
179 }
180
181 testEvent = GBAAudioProcessEvents(&gbaBoard->p->audio, cycles);
182 if (testEvent < nextEvent) {
183 nextEvent = testEvent;
184 }
185
186 testEvent = GBAMemoryProcessEvents(&gbaBoard->p->memory, cycles);
187 if (testEvent < nextEvent) {
188 nextEvent = testEvent;
189 }
190
191 testEvent = GBATimersProcessEvents(gbaBoard->p, cycles);
192 if (testEvent < nextEvent) {
193 nextEvent = testEvent;
194 }
195
196 board->cpu->cycles = 0;
197 board->cpu->nextEvent = nextEvent;
198}
199
200static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
201 int32_t nextEvent = INT_MAX;
202 if (gba->timersEnabled) {
203 struct GBATimer* timer;
204 struct GBATimer* nextTimer;
205
206 timer = &gba->timers[0];
207 if (timer->enable) {
208 timer->nextEvent -= cycles;
209 timer->lastEvent -= cycles;
210 if (timer->nextEvent <= 0) {
211 timer->lastEvent = timer->nextEvent;
212 timer->nextEvent += timer->overflowInterval;
213 gba->memory.io[REG_TM0CNT_LO >> 1] = timer->reload;
214 timer->oldReload = timer->reload;
215
216 if (timer->doIrq) {
217 GBARaiseIRQ(gba, IRQ_TIMER0);
218 }
219
220 if (gba->audio.enable) {
221 if ((gba->audio.chALeft || gba->audio.chARight) && gba->audio.chATimer == 0) {
222 GBAAudioSampleFIFO(&gba->audio, 0);
223 }
224
225 if ((gba->audio.chBLeft || gba->audio.chBRight) && gba->audio.chBTimer == 0) {
226 GBAAudioSampleFIFO(&gba->audio, 1);
227 }
228 }
229
230 nextTimer = &gba->timers[1];
231 if (nextTimer->countUp) {
232 ++gba->memory.io[REG_TM1CNT_LO >> 1];
233 if (!gba->memory.io[REG_TM1CNT_LO >> 1]) {
234 nextTimer->nextEvent = 0;
235 }
236 }
237 }
238 nextEvent = timer->nextEvent;
239 }
240
241 timer = &gba->timers[1];
242 if (timer->enable) {
243 timer->nextEvent -= cycles;
244 timer->lastEvent -= cycles;
245 if (timer->nextEvent <= 0) {
246 timer->lastEvent = timer->nextEvent;
247 timer->nextEvent += timer->overflowInterval;
248 gba->memory.io[REG_TM1CNT_LO >> 1] = timer->reload;
249 timer->oldReload = timer->reload;
250
251 if (timer->doIrq) {
252 GBARaiseIRQ(gba, IRQ_TIMER1);
253 }
254
255 if (gba->audio.enable) {
256 if ((gba->audio.chALeft || gba->audio.chARight) && gba->audio.chATimer == 1) {
257 GBAAudioSampleFIFO(&gba->audio, 0);
258 }
259
260 if ((gba->audio.chBLeft || gba->audio.chBRight) && gba->audio.chBTimer == 1) {
261 GBAAudioSampleFIFO(&gba->audio, 1);
262 }
263 }
264
265 if (timer->countUp) {
266 timer->nextEvent = INT_MAX;
267 }
268
269 nextTimer = &gba->timers[2];
270 if (nextTimer->countUp) {
271 ++gba->memory.io[REG_TM2CNT_LO >> 1];
272 if (!gba->memory.io[REG_TM2CNT_LO >> 1]) {
273 nextTimer->nextEvent = 0;
274 }
275 }
276 }
277 if (timer->nextEvent < nextEvent) {
278 nextEvent = timer->nextEvent;
279 }
280 }
281
282 timer = &gba->timers[2];
283 if (timer->enable) {
284 timer->nextEvent -= cycles;
285 timer->lastEvent -= cycles;
286 nextEvent = timer->nextEvent;
287 if (timer->nextEvent <= 0) {
288 timer->lastEvent = timer->nextEvent;
289 timer->nextEvent += timer->overflowInterval;
290 gba->memory.io[REG_TM2CNT_LO >> 1] = timer->reload;
291 timer->oldReload = timer->reload;
292
293 if (timer->doIrq) {
294 GBARaiseIRQ(gba, IRQ_TIMER2);
295 }
296
297 if (timer->countUp) {
298 timer->nextEvent = INT_MAX;
299 }
300
301 nextTimer = &gba->timers[3];
302 if (nextTimer->countUp) {
303 ++gba->memory.io[REG_TM3CNT_LO >> 1];
304 if (!gba->memory.io[REG_TM3CNT_LO >> 1]) {
305 nextTimer->nextEvent = 0;
306 }
307 }
308 }
309 if (timer->nextEvent < nextEvent) {
310 nextEvent = timer->nextEvent;
311 }
312 }
313
314 timer = &gba->timers[3];
315 if (timer->enable) {
316 timer->nextEvent -= cycles;
317 timer->lastEvent -= cycles;
318 nextEvent = timer->nextEvent;
319 if (timer->nextEvent <= 0) {
320 timer->lastEvent = timer->nextEvent;
321 timer->nextEvent += timer->overflowInterval;
322 gba->memory.io[REG_TM3CNT_LO >> 1] = timer->reload;
323 timer->oldReload = timer->reload;
324
325 if (timer->doIrq) {
326 GBARaiseIRQ(gba, IRQ_TIMER3);
327 }
328
329 if (timer->countUp) {
330 timer->nextEvent = INT_MAX;
331 }
332 }
333 if (timer->nextEvent < nextEvent) {
334 nextEvent = timer->nextEvent;
335 }
336 }
337 }
338 return nextEvent;
339}
340
341#ifdef USE_DEBUGGER
342void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) {
343 ARMDebuggerInit(debugger, &gba->cpu);
344 gba->debugger = debugger;
345}
346#endif
347
348void GBALoadROM(struct GBA* gba, int fd, const char* fname) {
349 struct stat info;
350 gba->memory.rom = fileMemoryMap(fd, SIZE_CART0, MEMORY_READ);
351 gba->activeFile = fname;
352 fstat(fd, &info);
353 gba->memory.romSize = info.st_size;
354 if (gba->savefile) {
355 GBASavedataInit(&gba->memory.savedata, gba->savefile);
356 }
357 GBAGPIOInit(&gba->memory.gpio, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]);
358 _checkOverrides(gba, ((struct GBACartridge*) gba->memory.rom)->id);
359 // TODO: error check
360}
361
362void GBALoadBIOS(struct GBA* gba, int fd) {
363 gba->memory.bios = fileMemoryMap(fd, SIZE_BIOS, MEMORY_READ);
364 gba->memory.fullBios = 1;
365 uint32_t checksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
366 GBALog(gba, GBA_LOG_DEBUG, "BIOS Checksum: 0x%X", checksum);
367 if (checksum == GBA_BIOS_CHECKSUM) {
368 GBALog(gba, GBA_LOG_INFO, "Official GBA BIOS detected");
369 } else if (checksum == GBA_DS_BIOS_CHECKSUM) {
370 GBALog(gba, GBA_LOG_INFO, "Official GBA (DS) BIOS detected");
371 } else {
372 GBALog(gba, GBA_LOG_WARN, "BIOS checksum incorrect");
373 }
374 if ((gba->cpu.gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) {
375 gba->memory.d.setActiveRegion(&gba->memory.d, gba->cpu.gprs[ARM_PC]);
376 }
377 // TODO: error check
378}
379
380void GBATimerUpdateRegister(struct GBA* gba, int timer) {
381 struct GBATimer* currentTimer = &gba->timers[timer];
382 if (currentTimer->enable && !currentTimer->countUp) {
383 gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu.cycles - currentTimer->lastEvent) >> currentTimer->prescaleBits);
384 }
385}
386
387void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t reload) {
388 gba->timers[timer].reload = reload;
389}
390
391void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
392 struct GBATimer* currentTimer = &gba->timers[timer];
393 GBATimerUpdateRegister(gba, timer);
394
395 int oldPrescale = currentTimer->prescaleBits;
396 switch (control & 0x0003) {
397 case 0x0000:
398 currentTimer->prescaleBits = 0;
399 break;
400 case 0x0001:
401 currentTimer->prescaleBits = 6;
402 break;
403 case 0x0002:
404 currentTimer->prescaleBits = 8;
405 break;
406 case 0x0003:
407 currentTimer->prescaleBits = 10;
408 break;
409 }
410 currentTimer->countUp = !!(control & 0x0004);
411 currentTimer->doIrq = !!(control & 0x0040);
412 currentTimer->overflowInterval = (0x10000 - currentTimer->reload) << currentTimer->prescaleBits;
413 int wasEnabled = currentTimer->enable;
414 currentTimer->enable = !!(control & 0x0080);
415 if (!wasEnabled && currentTimer->enable) {
416 if (!currentTimer->countUp) {
417 currentTimer->nextEvent = gba->cpu.cycles + currentTimer->overflowInterval;
418 } else {
419 currentTimer->nextEvent = INT_MAX;
420 }
421 gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->reload;
422 currentTimer->oldReload = currentTimer->reload;
423 gba->timersEnabled |= 1 << timer;
424 } else if (wasEnabled && !currentTimer->enable) {
425 if (!currentTimer->countUp) {
426 gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu.cycles - currentTimer->lastEvent) >> oldPrescale);
427 }
428 gba->timersEnabled &= ~(1 << timer);
429 } else if (currentTimer->prescaleBits != oldPrescale && !currentTimer->countUp) {
430 // FIXME: this might be before present
431 currentTimer->nextEvent = currentTimer->lastEvent + currentTimer->overflowInterval;
432 }
433
434 if (currentTimer->nextEvent < gba->cpu.nextEvent) {
435 gba->cpu.nextEvent = currentTimer->nextEvent;
436 }
437};
438
439void GBAWriteIE(struct GBA* gba, uint16_t value) {
440 if (value & (1 << IRQ_SIO)) {
441 GBALog(gba, GBA_LOG_STUB, "SIO interrupts not implemented");
442 }
443
444 if (value & (1 << IRQ_KEYPAD)) {
445 GBALog(gba, GBA_LOG_STUB, "Keypad interrupts not implemented");
446 }
447
448 if (value & (1 << IRQ_GAMEPAK)) {
449 GBALog(gba, GBA_LOG_STUB, "Gamepak interrupts not implemented");
450 }
451
452 if (gba->memory.io[REG_IME >> 1] && value & gba->memory.io[REG_IF >> 1]) {
453 ARMRaiseIRQ(&gba->cpu);
454 }
455}
456
457void GBAWriteIME(struct GBA* gba, uint16_t value) {
458 if (value && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) {
459 ARMRaiseIRQ(&gba->cpu);
460 }
461}
462
463void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) {
464 gba->memory.io[REG_IF >> 1] |= 1 << irq;
465
466 if (gba->memory.io[REG_IME >> 1] && (gba->memory.io[REG_IE >> 1] & 1 << irq)) {
467 ARMRaiseIRQ(&gba->cpu);
468 }
469}
470
471void GBATestIRQ(struct ARMBoard* board) {
472 struct GBABoard* gbaBoard = (struct GBABoard*) board;
473 struct GBA* gba = gbaBoard->p;
474 if (gba->memory.io[REG_IME >> 1] && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) {
475 gba->springIRQ = 1;
476 gba->cpu.nextEvent = 0;
477 }
478}
479
480int GBAWaitForIRQ(struct GBA* gba) {
481 int irqs = gba->memory.io[REG_IF >> 1];
482 int newIRQs = 0;
483 gba->memory.io[REG_IF >> 1] = 0;
484 while (1) {
485 if (gba->cpu.nextEvent == INT_MAX) {
486 break;
487 } else {
488 gba->cpu.cycles = gba->cpu.nextEvent;
489 GBAProcessEvents(&gba->board.d);
490 if (gba->memory.io[REG_IF >> 1]) {
491 newIRQs = gba->memory.io[REG_IF >> 1];
492 break;
493 }
494 }
495 }
496 gba->memory.io[REG_IF >> 1] = newIRQs | irqs;
497 return newIRQs;
498}
499
500int GBAHalt(struct GBA* gba) {
501 return GBAWaitForIRQ(gba);
502}
503
504void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
505 if (!gba) {
506 struct GBAThread* threadContext = GBAThreadGetContext();
507 if (threadContext) {
508 gba = threadContext->gba;
509 }
510 }
511 if (gba && !(level & gba->logLevel)) {
512 return;
513 }
514 va_list args;
515 va_start(args, format);
516 vprintf(format, args);
517 va_end(args);
518 printf("\n");
519}
520
521void GBAHitStub(struct ARMBoard* board, uint32_t opcode) {
522 struct GBABoard* gbaBoard = (struct GBABoard*) board;
523 GBALog(gbaBoard->p, GBA_LOG_STUB, "Stub opcode: %08x", opcode);
524#ifdef USE_DEBUGGER
525 if (!gbaBoard->p->debugger) {
526 abort();
527 } else {
528 ARMDebuggerEnter(gbaBoard->p->debugger);
529 }
530#else
531 abort();
532#endif
533}
534
535void GBAIllegal(struct ARMBoard* board, uint32_t opcode) {
536 struct GBABoard* gbaBoard = (struct GBABoard*) board;
537 GBALog(gbaBoard->p, GBA_LOG_WARN, "Illegal opcode: %08x", opcode);
538#ifdef USE_DEBUGGER
539 if (gbaBoard->p->debugger) {
540 ARMDebuggerEnter(gbaBoard->p->debugger);
541 }
542#endif
543}
544
545void _checkOverrides(struct GBA* gba, uint32_t id) {
546 int i;
547 for (i = 0; _overrides[i].id; ++i) {
548 if (_overrides[i].id == id) {
549 switch (_overrides[i].type) {
550 case SAVEDATA_FLASH512:
551 case SAVEDATA_FLASH1M:
552 gba->memory.savedata.type = _overrides[i].type;
553 GBASavedataInitFlash(&gba->memory.savedata);
554 break;
555 case SAVEDATA_EEPROM:
556 GBASavedataInitEEPROM(&gba->memory.savedata);
557 break;
558 case SAVEDATA_SRAM:
559 GBASavedataInitSRAM(&gba->memory.savedata);
560 break;
561 case SAVEDATA_NONE:
562 break;
563 }
564
565 if (_overrides[i].gpio & GPIO_RTC) {
566 GBAGPIOInitRTC(&gba->memory.gpio);
567 }
568
569 if (_overrides[i].gpio & GPIO_GYRO) {
570 GBAGPIOInitGyro(&gba->memory.gpio);
571 }
572
573 if (_overrides[i].gpio & GPIO_RUMBLE) {
574 GBAGPIOInitRumble(&gba->memory.gpio);
575 }
576 return;
577 }
578 }
579}