src/gba/gba.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "gba.h"
7
8#include "gba/bios.h"
9#include "gba/cheats.h"
10#include "gba/io.h"
11#include "gba/supervisor/rr.h"
12#include "gba/supervisor/thread.h"
13#include "gba/serialize.h"
14#include "gba/sio.h"
15
16#include "isa-inlines.h"
17
18#include "util/crc32.h"
19#include "util/memory.h"
20#include "util/math.h"
21#include "util/patch.h"
22#include "util/vfs.h"
23
24const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
25const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
26
27static const size_t GBA_ROM_MAGIC_OFFSET = 3;
28static const uint8_t GBA_ROM_MAGIC[] = { 0xEA };
29
30static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component);
31static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh);
32static void GBAProcessEvents(struct ARMCore* cpu);
33static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles);
34static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode);
35static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode);
36static void GBABreakpoint(struct ARMCore* cpu, int immediate);
37
38static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
39static bool _clearSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
40
41
42#ifdef _3DS
43extern uint32_t* romBuffer;
44extern size_t romBufferSize;
45#endif
46
47void GBACreate(struct GBA* gba) {
48 gba->d.id = GBA_COMPONENT_MAGIC;
49 gba->d.init = GBAInit;
50 gba->d.deinit = 0;
51}
52
53static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component) {
54 struct GBA* gba = (struct GBA*) component;
55 gba->cpu = cpu;
56 gba->debugger = 0;
57 gba->sync = 0;
58
59 GBAInterruptHandlerInit(&cpu->irqh);
60 GBAMemoryInit(gba);
61 GBASavedataInit(&gba->memory.savedata, 0);
62
63 gba->video.p = gba;
64 GBAVideoInit(&gba->video);
65
66 gba->audio.p = gba;
67 GBAAudioInit(&gba->audio, GBA_AUDIO_SAMPLES);
68
69 GBAIOInit(gba);
70
71 gba->sio.p = gba;
72 GBASIOInit(&gba->sio);
73
74 gba->timersEnabled = 0;
75 memset(gba->timers, 0, sizeof(gba->timers));
76
77 gba->springIRQ = 0;
78 gba->keySource = 0;
79 gba->rotationSource = 0;
80 gba->luminanceSource = 0;
81 gba->rtcSource = 0;
82 gba->rumble = 0;
83 gba->rr = 0;
84
85 gba->romVf = 0;
86 gba->biosVf = 0;
87
88 gba->logHandler = 0;
89 gba->logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL;
90 gba->stream = 0;
91 gba->keyCallback = 0;
92 gba->stopCallback = 0;
93
94 gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
95
96 gba->idleOptimization = IDLE_LOOP_REMOVE;
97 gba->idleLoop = IDLE_LOOP_NONE;
98 gba->lastJump = 0;
99 gba->haltPending = false;
100 gba->idleDetectionStep = 0;
101 gba->idleDetectionFailures = 0;
102
103 gba->realisticTiming = true;
104 gba->hardCrash = true;
105
106 gba->performingDMA = false;
107}
108
109void GBAUnloadROM(struct GBA* gba) {
110 if (gba->memory.rom && gba->pristineRom != gba->memory.rom) {
111 if (gba->yankedRomSize) {
112 gba->yankedRomSize = 0;
113 }
114 mappedMemoryFree(gba->memory.rom, SIZE_CART0);
115 }
116 gba->memory.rom = 0;
117
118 if (gba->romVf) {
119#ifndef _3DS
120 gba->romVf->unmap(gba->romVf, gba->pristineRom, gba->pristineRomSize);
121#endif
122 gba->pristineRom = 0;
123 gba->romVf = 0;
124 }
125}
126
127void GBADestroy(struct GBA* gba) {
128 GBAUnloadROM(gba);
129
130 if (gba->biosVf) {
131 gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
132 }
133
134 GBAMemoryDeinit(gba);
135 GBAVideoDeinit(&gba->video);
136 GBAAudioDeinit(&gba->audio);
137 GBASIODeinit(&gba->sio);
138 gba->rr = 0;
139}
140
141void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) {
142 irqh->reset = GBAReset;
143 irqh->processEvents = GBAProcessEvents;
144 irqh->swi16 = GBASwi16;
145 irqh->swi32 = GBASwi32;
146 irqh->hitIllegal = GBAIllegal;
147 irqh->readCPSR = GBATestIRQ;
148 irqh->hitStub = GBAHitStub;
149 irqh->bkpt16 = GBABreakpoint;
150 irqh->bkpt32 = GBABreakpoint;
151}
152
153void GBAReset(struct ARMCore* cpu) {
154 ARMSetPrivilegeMode(cpu, MODE_IRQ);
155 cpu->gprs[ARM_SP] = SP_BASE_IRQ;
156 ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
157 cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
158 ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
159 cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
160
161 struct GBA* gba = (struct GBA*) cpu->master;
162 if (!gba->rr || (!gba->rr->isPlaying(gba->rr) && !gba->rr->isRecording(gba->rr))) {
163 GBASavedataUnmask(&gba->memory.savedata);
164 }
165
166 if (gba->yankedRomSize) {
167 gba->memory.romSize = gba->yankedRomSize;
168 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
169 gba->yankedRomSize = 0;
170 }
171 GBAMemoryReset(gba);
172 GBAVideoReset(&gba->video);
173 GBAAudioReset(&gba->audio);
174 GBAIOInit(gba);
175
176 GBASIOReset(&gba->sio);
177
178 gba->timersEnabled = 0;
179 memset(gba->timers, 0, sizeof(gba->timers));
180}
181
182void GBASkipBIOS(struct ARMCore* cpu) {
183 if (cpu->gprs[ARM_PC] == BASE_RESET + WORD_SIZE_ARM) {
184 cpu->gprs[ARM_PC] = BASE_CART0;
185 int currentCycles = 0;
186 ARM_WRITE_PC;
187 }
188}
189
190static void GBAProcessEvents(struct ARMCore* cpu) {
191 do {
192 struct GBA* gba = (struct GBA*) cpu->master;
193 int32_t cycles = cpu->nextEvent;
194 int32_t nextEvent = INT_MAX;
195 int32_t testEvent;
196#ifndef NDEBUG
197 if (cycles < 0) {
198 GBALog(gba, GBA_LOG_FATAL, "Negative cycles passed: %i", cycles);
199 }
200#endif
201
202 gba->bus = cpu->prefetch[1];
203 if (cpu->executionMode == MODE_THUMB) {
204 gba->bus |= cpu->prefetch[1] << 16;
205 }
206
207 if (gba->springIRQ) {
208 ARMRaiseIRQ(cpu);
209 gba->springIRQ = 0;
210 }
211
212 testEvent = GBAVideoProcessEvents(&gba->video, cycles);
213 if (testEvent < nextEvent) {
214 nextEvent = testEvent;
215 }
216
217 testEvent = GBAAudioProcessEvents(&gba->audio, cycles);
218 if (testEvent < nextEvent) {
219 nextEvent = testEvent;
220 }
221
222 testEvent = GBATimersProcessEvents(gba, cycles);
223 if (testEvent < nextEvent) {
224 nextEvent = testEvent;
225 }
226
227 testEvent = GBAMemoryRunDMAs(gba, cycles);
228 if (testEvent < nextEvent) {
229 nextEvent = testEvent;
230 }
231
232 testEvent = GBASIOProcessEvents(&gba->sio, cycles);
233 if (testEvent < nextEvent) {
234 nextEvent = testEvent;
235 }
236
237 cpu->cycles -= cycles;
238 cpu->nextEvent = nextEvent;
239
240 if (cpu->halted) {
241 cpu->cycles = cpu->nextEvent;
242 }
243 } while (cpu->cycles >= cpu->nextEvent);
244}
245
246static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
247 int32_t nextEvent = INT_MAX;
248 if (gba->timersEnabled) {
249 struct GBATimer* timer;
250 struct GBATimer* nextTimer;
251
252 timer = &gba->timers[0];
253 if (timer->enable) {
254 timer->nextEvent -= cycles;
255 timer->lastEvent -= cycles;
256 while (timer->nextEvent <= 0) {
257 timer->lastEvent = timer->nextEvent;
258 timer->nextEvent += timer->overflowInterval;
259 gba->memory.io[REG_TM0CNT_LO >> 1] = timer->reload;
260 timer->oldReload = timer->reload;
261
262 if (timer->doIrq) {
263 GBARaiseIRQ(gba, IRQ_TIMER0);
264 }
265
266 if (gba->audio.enable) {
267 if ((gba->audio.chALeft || gba->audio.chARight) && gba->audio.chATimer == 0) {
268 GBAAudioSampleFIFO(&gba->audio, 0, timer->lastEvent);
269 }
270
271 if ((gba->audio.chBLeft || gba->audio.chBRight) && gba->audio.chBTimer == 0) {
272 GBAAudioSampleFIFO(&gba->audio, 1, timer->lastEvent);
273 }
274 }
275
276 nextTimer = &gba->timers[1];
277 if (nextTimer->countUp) {
278 ++gba->memory.io[REG_TM1CNT_LO >> 1];
279 if (!gba->memory.io[REG_TM1CNT_LO >> 1]) {
280 nextTimer->nextEvent = 0;
281 }
282 }
283 }
284 nextEvent = timer->nextEvent;
285 }
286
287 timer = &gba->timers[1];
288 if (timer->enable) {
289 timer->nextEvent -= cycles;
290 timer->lastEvent -= cycles;
291 if (timer->nextEvent <= 0) {
292 timer->lastEvent = timer->nextEvent;
293 timer->nextEvent += timer->overflowInterval;
294 gba->memory.io[REG_TM1CNT_LO >> 1] = timer->reload;
295 timer->oldReload = timer->reload;
296
297 if (timer->doIrq) {
298 GBARaiseIRQ(gba, IRQ_TIMER1);
299 }
300
301 if (gba->audio.enable) {
302 if ((gba->audio.chALeft || gba->audio.chARight) && gba->audio.chATimer == 1) {
303 GBAAudioSampleFIFO(&gba->audio, 0, timer->lastEvent);
304 }
305
306 if ((gba->audio.chBLeft || gba->audio.chBRight) && gba->audio.chBTimer == 1) {
307 GBAAudioSampleFIFO(&gba->audio, 1, timer->lastEvent);
308 }
309 }
310
311 if (timer->countUp) {
312 timer->nextEvent = INT_MAX;
313 }
314
315 nextTimer = &gba->timers[2];
316 if (nextTimer->countUp) {
317 ++gba->memory.io[REG_TM2CNT_LO >> 1];
318 if (!gba->memory.io[REG_TM2CNT_LO >> 1]) {
319 nextTimer->nextEvent = 0;
320 }
321 }
322 }
323 if (timer->nextEvent < nextEvent) {
324 nextEvent = timer->nextEvent;
325 }
326 }
327
328 timer = &gba->timers[2];
329 if (timer->enable) {
330 timer->nextEvent -= cycles;
331 timer->lastEvent -= cycles;
332 if (timer->nextEvent <= 0) {
333 timer->lastEvent = timer->nextEvent;
334 timer->nextEvent += timer->overflowInterval;
335 gba->memory.io[REG_TM2CNT_LO >> 1] = timer->reload;
336 timer->oldReload = timer->reload;
337
338 if (timer->doIrq) {
339 GBARaiseIRQ(gba, IRQ_TIMER2);
340 }
341
342 if (timer->countUp) {
343 timer->nextEvent = INT_MAX;
344 }
345
346 nextTimer = &gba->timers[3];
347 if (nextTimer->countUp) {
348 ++gba->memory.io[REG_TM3CNT_LO >> 1];
349 if (!gba->memory.io[REG_TM3CNT_LO >> 1]) {
350 nextTimer->nextEvent = 0;
351 }
352 }
353 }
354 if (timer->nextEvent < nextEvent) {
355 nextEvent = timer->nextEvent;
356 }
357 }
358
359 timer = &gba->timers[3];
360 if (timer->enable) {
361 timer->nextEvent -= cycles;
362 timer->lastEvent -= cycles;
363 if (timer->nextEvent <= 0) {
364 timer->lastEvent = timer->nextEvent;
365 timer->nextEvent += timer->overflowInterval;
366 gba->memory.io[REG_TM3CNT_LO >> 1] = timer->reload;
367 timer->oldReload = timer->reload;
368
369 if (timer->doIrq) {
370 GBARaiseIRQ(gba, IRQ_TIMER3);
371 }
372
373 if (timer->countUp) {
374 timer->nextEvent = INT_MAX;
375 }
376 }
377 if (timer->nextEvent < nextEvent) {
378 nextEvent = timer->nextEvent;
379 }
380 }
381 }
382 return nextEvent;
383}
384
385void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) {
386 debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint;
387 debugger->clearSoftwareBreakpoint = _clearSoftwareBreakpoint;
388 gba->debugger = debugger;
389 gba->cpu->components[GBA_COMPONENT_DEBUGGER] = &debugger->d;
390 ARMHotplugAttach(gba->cpu, GBA_COMPONENT_DEBUGGER);
391}
392
393void GBADetachDebugger(struct GBA* gba) {
394 gba->debugger = 0;
395 ARMHotplugDetach(gba->cpu, GBA_COMPONENT_DEBUGGER);
396 gba->cpu->components[GBA_COMPONENT_DEBUGGER] = 0;
397}
398
399bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname) {
400 GBAUnloadROM(gba);
401 gba->romVf = vf;
402 gba->pristineRomSize = vf->size(vf);
403 vf->seek(vf, 0, SEEK_SET);
404 if (gba->pristineRomSize > SIZE_CART0) {
405 gba->pristineRomSize = SIZE_CART0;
406 }
407#ifdef _3DS
408 gba->pristineRom = 0;
409 if (gba->pristineRomSize <= romBufferSize) {
410 gba->pristineRom = romBuffer;
411 vf->read(vf, romBuffer, gba->pristineRomSize);
412 }
413#else
414 gba->pristineRom = vf->map(vf, gba->pristineRomSize, MAP_READ);
415#endif
416 if (!gba->pristineRom) {
417 GBALog(gba, GBA_LOG_WARN, "Couldn't map ROM");
418 return false;
419 }
420 gba->yankedRomSize = 0;
421 gba->memory.rom = gba->pristineRom;
422 gba->activeFile = fname;
423 gba->memory.romSize = gba->pristineRomSize;
424 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
425 gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
426 GBASavedataInit(&gba->memory.savedata, sav);
427 GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]);
428 return true;
429 // TODO: error check
430}
431
432void GBAYankROM(struct GBA* gba) {
433 gba->yankedRomSize = gba->memory.romSize;
434 gba->memory.romSize = 0;
435 gba->memory.romMask = 0;
436 GBARaiseIRQ(gba, IRQ_GAMEPAK);
437}
438
439void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
440 gba->biosVf = vf;
441 uint32_t* bios = vf->map(vf, SIZE_BIOS, MAP_READ);
442 if (!bios) {
443 GBALog(gba, GBA_LOG_WARN, "Couldn't map BIOS");
444 return;
445 }
446 gba->memory.bios = bios;
447 gba->memory.fullBios = 1;
448 uint32_t checksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
449 GBALog(gba, GBA_LOG_DEBUG, "BIOS Checksum: 0x%X", checksum);
450 if (checksum == GBA_BIOS_CHECKSUM) {
451 GBALog(gba, GBA_LOG_INFO, "Official GBA BIOS detected");
452 } else if (checksum == GBA_DS_BIOS_CHECKSUM) {
453 GBALog(gba, GBA_LOG_INFO, "Official GBA (DS) BIOS detected");
454 } else {
455 GBALog(gba, GBA_LOG_WARN, "BIOS checksum incorrect");
456 }
457 gba->biosChecksum = checksum;
458 if (gba->memory.activeRegion == REGION_BIOS) {
459 gba->cpu->memory.activeRegion = gba->memory.bios;
460 }
461 // TODO: error check
462}
463
464void GBAApplyPatch(struct GBA* gba, struct Patch* patch) {
465 size_t patchedSize = patch->outputSize(patch, gba->memory.romSize);
466 if (!patchedSize || patchedSize > SIZE_CART0) {
467 return;
468 }
469 gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
470 if (!patch->applyPatch(patch, gba->pristineRom, gba->pristineRomSize, gba->memory.rom, patchedSize)) {
471 mappedMemoryFree(gba->memory.rom, patchedSize);
472 gba->memory.rom = gba->pristineRom;
473 return;
474 }
475 gba->memory.romSize = patchedSize;
476 gba->memory.romMask = SIZE_CART0 - 1;
477 gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
478}
479
480void GBATimerUpdateRegister(struct GBA* gba, int timer) {
481 struct GBATimer* currentTimer = &gba->timers[timer];
482 if (currentTimer->enable && !currentTimer->countUp) {
483 int32_t prefetchSkew = 0;
484 if (gba->memory.lastPrefetchedPc - gba->memory.lastPrefetchedLoads * WORD_SIZE_THUMB >= (uint32_t) gba->cpu->gprs[ARM_PC]) {
485 prefetchSkew = (gba->memory.lastPrefetchedPc - gba->cpu->gprs[ARM_PC]) * (gba->cpu->memory.activeSeqCycles16 + 1) / WORD_SIZE_THUMB;
486 }
487 // Reading this takes two cycles (1N+1I), so let's remove them preemptively
488 gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu->cycles - currentTimer->lastEvent - 2 + prefetchSkew) >> currentTimer->prescaleBits);
489 }
490}
491
492void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t reload) {
493 gba->timers[timer].reload = reload;
494 gba->timers[timer].overflowInterval = (0x10000 - gba->timers[timer].reload) << gba->timers[timer].prescaleBits;
495}
496
497void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
498 struct GBATimer* currentTimer = &gba->timers[timer];
499 GBATimerUpdateRegister(gba, timer);
500
501 int oldPrescale = currentTimer->prescaleBits;
502 switch (control & 0x0003) {
503 case 0x0000:
504 currentTimer->prescaleBits = 0;
505 break;
506 case 0x0001:
507 currentTimer->prescaleBits = 6;
508 break;
509 case 0x0002:
510 currentTimer->prescaleBits = 8;
511 break;
512 case 0x0003:
513 currentTimer->prescaleBits = 10;
514 break;
515 }
516 currentTimer->countUp = !!(control & 0x0004);
517 currentTimer->doIrq = !!(control & 0x0040);
518 currentTimer->overflowInterval = (0x10000 - currentTimer->reload) << currentTimer->prescaleBits;
519 int wasEnabled = currentTimer->enable;
520 currentTimer->enable = !!(control & 0x0080);
521 if (!wasEnabled && currentTimer->enable) {
522 if (!currentTimer->countUp) {
523 currentTimer->nextEvent = gba->cpu->cycles + currentTimer->overflowInterval;
524 } else {
525 currentTimer->nextEvent = INT_MAX;
526 }
527 gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->reload;
528 currentTimer->oldReload = currentTimer->reload;
529 currentTimer->lastEvent = gba->cpu->cycles;
530 gba->timersEnabled |= 1 << timer;
531 } else if (wasEnabled && !currentTimer->enable) {
532 if (!currentTimer->countUp) {
533 gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu->cycles - currentTimer->lastEvent) >> oldPrescale);
534 }
535 gba->timersEnabled &= ~(1 << timer);
536 } else if (currentTimer->prescaleBits != oldPrescale && !currentTimer->countUp) {
537 // FIXME: this might be before present
538 currentTimer->nextEvent = currentTimer->lastEvent + currentTimer->overflowInterval;
539 }
540
541 if (currentTimer->nextEvent < gba->cpu->nextEvent) {
542 gba->cpu->nextEvent = currentTimer->nextEvent;
543 }
544};
545
546void GBAWriteIE(struct GBA* gba, uint16_t value) {
547 if (value & (1 << IRQ_KEYPAD)) {
548 GBALog(gba, GBA_LOG_STUB, "Keypad interrupts not implemented");
549 }
550
551 if (gba->memory.io[REG_IME >> 1] && value & gba->memory.io[REG_IF >> 1]) {
552 ARMRaiseIRQ(gba->cpu);
553 }
554}
555
556void GBAWriteIME(struct GBA* gba, uint16_t value) {
557 if (value && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) {
558 ARMRaiseIRQ(gba->cpu);
559 }
560}
561
562void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) {
563 gba->memory.io[REG_IF >> 1] |= 1 << irq;
564 gba->cpu->halted = 0;
565
566 if (gba->memory.io[REG_IME >> 1] && (gba->memory.io[REG_IE >> 1] & 1 << irq)) {
567 ARMRaiseIRQ(gba->cpu);
568 }
569}
570
571void GBATestIRQ(struct ARMCore* cpu) {
572 struct GBA* gba = (struct GBA*) cpu->master;
573 if (gba->memory.io[REG_IME >> 1] && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) {
574 gba->springIRQ = 1;
575 gba->cpu->nextEvent = 0;
576 }
577}
578
579void GBAHalt(struct GBA* gba) {
580 gba->cpu->nextEvent = 0;
581 gba->cpu->halted = 1;
582}
583
584void GBAStop(struct GBA* gba) {
585 if (!gba->stopCallback) {
586 return;
587 }
588 gba->cpu->nextEvent = 0;
589 gba->stopCallback->stop(gba->stopCallback);
590}
591
592static void _GBAVLog(struct GBA* gba, enum GBALogLevel level, const char* format, va_list args) {
593 struct GBAThread* threadContext = GBAThreadGetContext();
594 enum GBALogLevel logLevel = GBA_LOG_ALL;
595
596 if (gba) {
597 logLevel = gba->logLevel;
598 }
599
600 if (threadContext) {
601 logLevel = threadContext->logLevel;
602 gba = threadContext->gba;
603 }
604
605 if (!(level & logLevel) && level != GBA_LOG_FATAL) {
606 return;
607 }
608
609 if (level == GBA_LOG_FATAL && gba) {
610 gba->cpu->nextEvent = 0;
611 }
612
613 if (threadContext) {
614 if (level == GBA_LOG_FATAL) {
615 MutexLock(&threadContext->stateMutex);
616 threadContext->state = THREAD_CRASHED;
617 MutexUnlock(&threadContext->stateMutex);
618 }
619 }
620 if (gba && gba->logHandler) {
621 gba->logHandler(threadContext, level, format, args);
622 return;
623 }
624
625 vprintf(format, args);
626 printf("\n");
627
628 if (level == GBA_LOG_FATAL && !threadContext) {
629 abort();
630 }
631}
632
633void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
634 va_list args;
635 va_start(args, format);
636 _GBAVLog(gba, level, format, args);
637 va_end(args);
638}
639
640void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...) {
641 struct GBA* gba = 0;
642 if (debugger->cpu) {
643 gba = (struct GBA*) debugger->cpu->master;
644 }
645
646 enum GBALogLevel gbaLevel;
647 switch (level) {
648 default: // Avoids compiler warning
649 case DEBUGGER_LOG_DEBUG:
650 gbaLevel = GBA_LOG_DEBUG;
651 break;
652 case DEBUGGER_LOG_INFO:
653 gbaLevel = GBA_LOG_INFO;
654 break;
655 case DEBUGGER_LOG_WARN:
656 gbaLevel = GBA_LOG_WARN;
657 break;
658 case DEBUGGER_LOG_ERROR:
659 gbaLevel = GBA_LOG_ERROR;
660 break;
661 }
662 va_list args;
663 va_start(args, format);
664 _GBAVLog(gba, gbaLevel, format, args);
665 va_end(args);
666}
667
668bool GBAIsROM(struct VFile* vf) {
669 if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
670 return false;
671 }
672 uint8_t signature[sizeof(GBA_ROM_MAGIC)];
673 if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
674 return false;
675 }
676 return memcmp(signature, GBA_ROM_MAGIC, sizeof(signature)) == 0;
677}
678
679bool GBAIsBIOS(struct VFile* vf) {
680 if (vf->seek(vf, 0, SEEK_SET) < 0) {
681 return false;
682 }
683 uint32_t interruptTable[7];
684 if (vf->read(vf, &interruptTable, sizeof(interruptTable)) != sizeof(interruptTable)) {
685 return false;
686 }
687 int i;
688 for (i = 0; i < 7; ++i) {
689 if ((interruptTable[i] & 0xFFFF0000) != 0xEA000000) {
690 return false;
691 }
692 }
693 return true;
694}
695
696void GBAGetGameCode(struct GBA* gba, char* out) {
697 if (!gba->memory.rom) {
698 out[0] = '\0';
699 return;
700 }
701 memcpy(out, &((struct GBACartridge*) gba->memory.rom)->id, 4);
702}
703
704void GBAGetGameTitle(struct GBA* gba, char* out) {
705 if (!gba->memory.rom) {
706 strncpy(out, "(BIOS)", 12);
707 return;
708 }
709 memcpy(out, &((struct GBACartridge*) gba->memory.rom)->title, 12);
710}
711
712void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) {
713 struct GBA* gba = (struct GBA*) cpu->master;
714 enum GBALogLevel level = GBA_LOG_ERROR;
715 if (gba->debugger) {
716 level = GBA_LOG_STUB;
717 struct DebuggerEntryInfo info = {
718 .address = _ARMPCAddress(cpu),
719 .opcode = opcode
720 };
721 ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info);
722 }
723 GBALog(gba, level, "Stub opcode: %08x", opcode);
724}
725
726void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) {
727 struct GBA* gba = (struct GBA*) cpu->master;
728 if (!gba->yankedRomSize) {
729 GBALog(gba, GBA_LOG_WARN, "Illegal opcode: %08x", opcode);
730 }
731 if (gba->debugger) {
732 struct DebuggerEntryInfo info = {
733 .address = _ARMPCAddress(cpu),
734 .opcode = opcode
735 };
736 ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info);
737 } else {
738 ARMRaiseUndefined(cpu);
739 }
740}
741
742void GBABreakpoint(struct ARMCore* cpu, int immediate) {
743 struct GBA* gba = (struct GBA*) cpu->master;
744 if (immediate >= GBA_COMPONENT_MAX) {
745 return;
746 }
747 switch (immediate) {
748 case GBA_COMPONENT_DEBUGGER:
749 if (gba->debugger) {
750 struct DebuggerEntryInfo info = {
751 .address = _ARMPCAddress(cpu)
752 };
753 ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_BREAKPOINT, &info);
754 }
755 break;
756 case GBA_COMPONENT_CHEAT_DEVICE:
757 if (gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) {
758 struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE];
759 struct GBACheatHook* hook = 0;
760 size_t i;
761 for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) {
762 struct GBACheatSet* cheats = *GBACheatSetsGetPointer(&device->cheats, i);
763 if (cheats->hook && cheats->hook->address == _ARMPCAddress(cpu)) {
764 GBACheatRefresh(device, cheats);
765 hook = cheats->hook;
766 }
767 }
768 if (hook) {
769 ARMRunFake(cpu, hook->patchedOpcode);
770 }
771 }
772 break;
773 default:
774 break;
775 }
776}
777
778void GBAFrameStarted(struct GBA* gba) {
779 UNUSED(gba);
780
781 struct GBAThread* thread = GBAThreadGetContext();
782 if (!thread) {
783 return;
784 }
785
786 if (thread->rewindBuffer) {
787 --thread->rewindBufferNext;
788 if (thread->rewindBufferNext <= 0) {
789 thread->rewindBufferNext = thread->rewindBufferInterval;
790 GBARecordFrame(thread);
791 }
792 }
793}
794
795void GBAFrameEnded(struct GBA* gba) {
796 GBASavedataClean(&gba->memory.savedata, gba->video.frameCounter);
797
798 if (gba->rr) {
799 gba->rr->nextFrame(gba->rr);
800 }
801
802 if (gba->cpu->components && gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) {
803 struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE];
804 size_t i;
805 for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) {
806 struct GBACheatSet* cheats = *GBACheatSetsGetPointer(&device->cheats, i);
807 if (!cheats->hook) {
808 GBACheatRefresh(device, cheats);
809 }
810 }
811 }
812
813 if (gba->stream) {
814 gba->stream->postVideoFrame(gba->stream, gba->video.renderer);
815 }
816
817 if (gba->memory.hw.devices & (HW_GB_PLAYER | HW_GB_PLAYER_DETECTION)) {
818 GBAHardwarePlayerUpdate(gba);
819 }
820
821 struct GBAThread* thread = GBAThreadGetContext();
822 if (!thread) {
823 return;
824 }
825
826 if (thread->frameCallback) {
827 thread->frameCallback(thread);
828 }
829}
830
831void GBASetBreakpoint(struct GBA* gba, struct ARMComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
832 size_t immediate;
833 for (immediate = 0; immediate < gba->cpu->numComponents; ++immediate) {
834 if (gba->cpu->components[immediate] == component) {
835 break;
836 }
837 }
838 if (immediate == gba->cpu->numComponents) {
839 return;
840 }
841 if (mode == MODE_ARM) {
842 int32_t value;
843 int32_t old;
844 value = 0xE1200070;
845 value |= immediate & 0xF;
846 value |= (immediate & 0xFFF0) << 4;
847 GBAPatch32(gba->cpu, address, value, &old);
848 *opcode = old;
849 } else {
850 int16_t value;
851 int16_t old;
852 value = 0xBE00;
853 value |= immediate & 0xFF;
854 GBAPatch16(gba->cpu, address, value, &old);
855 *opcode = (uint16_t) old;
856 }
857}
858
859void GBAClearBreakpoint(struct GBA* gba, uint32_t address, enum ExecutionMode mode, uint32_t opcode) {
860 if (mode == MODE_ARM) {
861 GBAPatch32(gba->cpu, address, opcode, 0);
862 } else {
863 GBAPatch16(gba->cpu, address, opcode, 0);
864 }
865}
866
867static bool _setSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
868 GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d, address, mode, opcode);
869 return true;
870}
871
872static bool _clearSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t opcode) {
873 GBAClearBreakpoint((struct GBA*) debugger->cpu->master, address, mode, opcode);
874 return true;
875}