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