all repos — mgba @ 76ccf41c25d89de5448883d77b95ef69a341ae78

mGBA Game Boy Advance Emulator

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 <mgba/internal/gba/gba.h>
  7
  8#include <mgba/internal/arm/isa-inlines.h>
  9#include <mgba/internal/arm/debugger/debugger.h>
 10#include <mgba/internal/arm/decoder.h>
 11
 12#include <mgba/internal/gba/bios.h>
 13#include <mgba/internal/gba/cheats.h>
 14#include <mgba/internal/gba/io.h>
 15#include <mgba/internal/gba/overrides.h>
 16#include <mgba/internal/gba/rr/rr.h>
 17
 18#include <mgba-util/patch.h>
 19#include <mgba-util/crc32.h>
 20#include <mgba-util/math.h>
 21#include <mgba-util/memory.h>
 22#include <mgba-util/vfs.h>
 23
 24#ifdef USE_ELF
 25#include <mgba-util/elf-read.h>
 26#endif
 27
 28#define GBA_IRQ_DELAY 7
 29
 30mLOG_DEFINE_CATEGORY(GBA, "GBA", "gba");
 31mLOG_DEFINE_CATEGORY(GBA_DEBUG, "GBA Debug", "gba.debug");
 32
 33const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
 34
 35static const size_t GBA_ROM_MAGIC_OFFSET = 3;
 36static const uint8_t GBA_ROM_MAGIC[] = { 0xEA };
 37
 38static const size_t GBA_ROM_MAGIC_OFFSET2 = 0xB2;
 39static const uint8_t GBA_ROM_MAGIC2[] = { 0x96 };
 40
 41static const size_t GBA_MB_MAGIC_OFFSET = 0xC0;
 42
 43static void GBAInit(void* cpu, struct mCPUComponent* component);
 44static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh);
 45static void GBAProcessEvents(struct ARMCore* cpu);
 46static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode);
 47static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode);
 48static void GBABreakpoint(struct ARMCore* cpu, int immediate);
 49
 50static void _triggerIRQ(struct mTiming*, void* user, uint32_t cyclesLate);
 51
 52#ifdef USE_DEBUGGERS
 53static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
 54static bool _clearSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
 55#endif
 56
 57#ifdef FIXED_ROM_BUFFER
 58extern uint32_t* romBuffer;
 59extern size_t romBufferSize;
 60#endif
 61
 62void GBACreate(struct GBA* gba) {
 63	gba->d.id = GBA_COMPONENT_MAGIC;
 64	gba->d.init = GBAInit;
 65	gba->d.deinit = 0;
 66}
 67
 68static void GBAInit(void* cpu, struct mCPUComponent* component) {
 69	struct GBA* gba = (struct GBA*) component;
 70	gba->cpu = cpu;
 71	gba->debugger = 0;
 72	gba->sync = 0;
 73
 74	GBAInterruptHandlerInit(&gba->cpu->irqh);
 75	GBAMemoryInit(gba);
 76
 77	gba->memory.savedata.timing = &gba->timing;
 78	GBASavedataInit(&gba->memory.savedata, NULL);
 79
 80	gba->video.p = gba;
 81	GBAVideoInit(&gba->video);
 82
 83	gba->audio.p = gba;
 84	GBAAudioInit(&gba->audio, GBA_AUDIO_SAMPLES);
 85
 86	GBAIOInit(gba);
 87
 88	gba->sio.p = gba;
 89	GBASIOInit(&gba->sio);
 90
 91	GBAHardwareInit(&gba->memory.hw, NULL);
 92
 93	gba->keySource = 0;
 94	gba->rotationSource = 0;
 95	gba->luminanceSource = 0;
 96	gba->rtcSource = 0;
 97	gba->rumble = 0;
 98	gba->rr = 0;
 99
100	gba->romVf = 0;
101	gba->biosVf = 0;
102
103	gba->stream = NULL;
104	gba->keyCallback = NULL;
105	mCoreCallbacksListInit(&gba->coreCallbacks, 0);
106
107	gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
108
109	gba->idleOptimization = IDLE_LOOP_REMOVE;
110	gba->idleLoop = IDLE_LOOP_NONE;
111
112	gba->hardCrash = true;
113	gba->allowOpposingDirections = true;
114
115	gba->performingDMA = false;
116
117	gba->isPristine = false;
118	gba->pristineRomSize = 0;
119	gba->yankedRomSize = 0;
120
121	mTimingInit(&gba->timing, &gba->cpu->cycles, &gba->cpu->nextEvent);
122
123	gba->irqEvent.name = "GBA IRQ Event";
124	gba->irqEvent.callback = _triggerIRQ;
125	gba->irqEvent.context = gba;
126	gba->irqEvent.priority = 0;
127}
128
129void GBAUnloadROM(struct GBA* gba) {
130	if (gba->memory.rom && !gba->isPristine) {
131		if (gba->yankedRomSize) {
132			gba->yankedRomSize = 0;
133		}
134		mappedMemoryFree(gba->memory.rom, SIZE_CART0);
135	}
136
137	if (gba->romVf) {
138#ifndef FIXED_ROM_BUFFER
139		if (gba->isPristine) {
140			gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize);
141		}
142#endif
143		gba->romVf->close(gba->romVf);
144		gba->romVf = NULL;
145	}
146	gba->memory.rom = NULL;
147	gba->isPristine = false;
148
149	gba->memory.savedata.maskWriteback = false;
150	GBASavedataUnmask(&gba->memory.savedata);
151	GBASavedataDeinit(&gba->memory.savedata);
152	if (gba->memory.savedata.realVf) {
153		gba->memory.savedata.realVf->close(gba->memory.savedata.realVf);
154		gba->memory.savedata.realVf = 0;
155	}
156	gba->idleLoop = IDLE_LOOP_NONE;
157}
158
159void GBADestroy(struct GBA* gba) {
160	GBAUnloadROM(gba);
161
162	if (gba->biosVf) {
163		gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
164		gba->biosVf->close(gba->biosVf);
165		gba->biosVf = 0;
166	}
167
168	GBAMemoryDeinit(gba);
169	GBAVideoDeinit(&gba->video);
170	GBAAudioDeinit(&gba->audio);
171	GBASIODeinit(&gba->sio);
172	gba->rr = 0;
173	mTimingDeinit(&gba->timing);
174	mCoreCallbacksListDeinit(&gba->coreCallbacks);
175}
176
177void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) {
178	irqh->reset = GBAReset;
179	irqh->processEvents = GBAProcessEvents;
180	irqh->swi16 = GBASwi16;
181	irqh->swi32 = GBASwi32;
182	irqh->hitIllegal = GBAIllegal;
183	irqh->readCPSR = GBATestIRQ;
184	irqh->hitStub = GBAHitStub;
185	irqh->bkpt16 = GBABreakpoint;
186	irqh->bkpt32 = GBABreakpoint;
187}
188
189void GBAReset(struct ARMCore* cpu) {
190	ARMSetPrivilegeMode(cpu, MODE_IRQ);
191	cpu->gprs[ARM_SP] = SP_BASE_IRQ;
192	ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
193	cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
194	ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
195	cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
196
197	struct GBA* gba = (struct GBA*) cpu->master;
198	if (!gba->rr || (!gba->rr->isPlaying(gba->rr) && !gba->rr->isRecording(gba->rr))) {
199		gba->memory.savedata.maskWriteback = false;
200		GBASavedataUnmask(&gba->memory.savedata);
201	}
202
203	gba->cpuBlocked = false;
204	gba->earlyExit = false;
205	if (gba->yankedRomSize) {
206		gba->memory.romSize = gba->yankedRomSize;
207		gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
208		gba->yankedRomSize = 0;
209	}
210	mTimingClear(&gba->timing);
211	GBAMemoryReset(gba);
212	GBAVideoReset(&gba->video);
213	GBAAudioReset(&gba->audio);
214	GBAIOInit(gba);
215	GBATimerInit(gba);
216
217	GBASIOReset(&gba->sio);
218
219	gba->lastJump = 0;
220	gba->haltPending = false;
221	gba->idleDetectionStep = 0;
222	gba->idleDetectionFailures = 0;
223
224	gba->debug = false;
225	memset(gba->debugString, 0, sizeof(gba->debugString));
226	if (gba->pristineRomSize > SIZE_CART0) {
227		GBAMatrixReset(gba);
228	}
229
230	if (!gba->romVf && gba->memory.rom) {
231		GBASkipBIOS(gba);
232	}
233}
234
235void GBASkipBIOS(struct GBA* gba) {
236	struct ARMCore* cpu = gba->cpu;
237	if (cpu->gprs[ARM_PC] == BASE_RESET + WORD_SIZE_ARM) {
238		if (gba->memory.rom) {
239			cpu->gprs[ARM_PC] = BASE_CART0;
240		} else {
241			cpu->gprs[ARM_PC] = BASE_WORKING_RAM;
242		}
243		gba->memory.io[REG_VCOUNT >> 1] = 0x7E;
244		gba->memory.io[REG_POSTFLG >> 1] = 1;
245		int currentCycles = 0;
246		ARM_WRITE_PC;
247	}
248}
249
250static void GBAProcessEvents(struct ARMCore* cpu) {
251	struct GBA* gba = (struct GBA*) cpu->master;
252
253	gba->bus = cpu->prefetch[1];
254	if (cpu->executionMode == MODE_THUMB) {
255		gba->bus |= cpu->prefetch[1] << 16;
256	}
257
258	int32_t nextEvent = cpu->nextEvent;
259	while (cpu->cycles >= nextEvent) {
260		cpu->nextEvent = INT_MAX;
261		nextEvent = 0;
262		do {
263			int32_t cycles = cpu->cycles;
264			cpu->cycles = 0;
265#ifndef NDEBUG
266			if (cycles < 0) {
267				mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles);
268			}
269#endif
270			nextEvent = mTimingTick(&gba->timing, nextEvent + cycles);
271		} while (gba->cpuBlocked);
272
273		cpu->nextEvent = nextEvent;
274		if (cpu->halted) {
275			cpu->cycles = nextEvent;
276			if (!gba->memory.io[REG_IME >> 1] || !gba->memory.io[REG_IE >> 1]) {
277				break;
278			}
279		}
280#ifndef NDEBUG
281		else if (nextEvent < 0) {
282			mLOG(GBA, FATAL, "Negative cycles will pass: %i", nextEvent);
283		}
284#endif
285		if (gba->earlyExit) {
286			break;
287		}
288	}
289	gba->earlyExit = false;
290#ifndef NDEBUG
291	if (gba->cpuBlocked) {
292		mLOG(GBA, FATAL, "CPU is blocked!");
293	}
294#endif
295}
296
297#ifdef USE_DEBUGGERS
298void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger) {
299	gba->debugger = (struct ARMDebugger*) debugger->platform;
300	gba->debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint;
301	gba->debugger->clearSoftwareBreakpoint = _clearSoftwareBreakpoint;
302	gba->cpu->components[CPU_COMPONENT_DEBUGGER] = &debugger->d;
303	ARMHotplugAttach(gba->cpu, CPU_COMPONENT_DEBUGGER);
304}
305
306void GBADetachDebugger(struct GBA* gba) {
307	if (gba->debugger) {
308		ARMHotplugDetach(gba->cpu, CPU_COMPONENT_DEBUGGER);
309	}
310	gba->cpu->components[CPU_COMPONENT_DEBUGGER] = NULL;
311	gba->debugger = NULL;
312}
313#endif
314
315bool GBALoadNull(struct GBA* gba) {
316	GBAUnloadROM(gba);
317	gba->romVf = NULL;
318	gba->pristineRomSize = 0;
319#ifndef FIXED_ROM_BUFFER
320	gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
321#else
322	gba->memory.rom = romBuffer;
323#endif
324	gba->isPristine = false;
325	gba->yankedRomSize = 0;
326	gba->memory.romSize = SIZE_CART0;
327	gba->memory.romMask = SIZE_CART0 - 1;
328	gba->memory.mirroring = false;
329	gba->romCrc32 = 0;
330
331	if (gba->cpu) {
332		gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
333	}
334	return true;
335}
336
337bool GBALoadMB(struct GBA* gba, struct VFile* vf) {
338	GBAUnloadROM(gba);
339	gba->romVf = vf;
340	gba->pristineRomSize = vf->size(vf);
341	vf->seek(vf, 0, SEEK_SET);
342	if (gba->pristineRomSize > SIZE_WORKING_RAM) {
343		gba->pristineRomSize = SIZE_WORKING_RAM;
344	}
345	gba->isPristine = true;
346	memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
347	vf->read(vf, gba->memory.wram, gba->pristineRomSize);
348	if (!gba->memory.wram) {
349		mLOG(GBA, WARN, "Couldn't map ROM");
350		return false;
351	}
352	gba->yankedRomSize = 0;
353	gba->memory.romSize = 0;
354	gba->memory.romMask = 0;
355	gba->romCrc32 = doCrc32(gba->memory.wram, gba->pristineRomSize);
356	if (gba->cpu && gba->memory.activeRegion == REGION_WORKING_RAM) {
357		gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
358	}
359	return true;
360}
361
362bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
363	if (!vf) {
364		return false;
365	}
366	GBAUnloadROM(gba);
367	gba->romVf = vf;
368	gba->pristineRomSize = vf->size(vf);
369	vf->seek(vf, 0, SEEK_SET);
370	if (gba->pristineRomSize > SIZE_CART0) {
371		gba->isPristine = false;
372		gba->memory.romSize = 0x01000000;
373#ifdef FIXED_ROM_BUFFER
374		gba->memory.rom = romBuffer;
375#else
376		gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
377#endif
378	} else {
379		gba->isPristine = true;
380#ifdef FIXED_ROM_BUFFER
381		if (gba->pristineRomSize <= romBufferSize) {
382			gba->memory.rom = romBuffer;
383			vf->read(vf, romBuffer, gba->pristineRomSize);
384		}
385#else
386		gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ);
387#endif
388		gba->memory.romSize = gba->pristineRomSize;
389	}
390	if (!gba->memory.rom) {
391		mLOG(GBA, WARN, "Couldn't map ROM");
392		return false;
393	}
394	gba->yankedRomSize = 0;
395	gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
396	gba->memory.mirroring = false;
397	gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
398	GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]);
399	GBAVFameDetect(&gba->memory.vfame, gba->memory.rom, gba->memory.romSize);
400	if (popcount32(gba->memory.romSize) != 1) {
401		// This ROM is either a bad dump or homebrew. Emulate flash cart behavior.
402#ifndef FIXED_ROM_BUFFER
403		void* newRom = anonymousMemoryMap(SIZE_CART0);
404		memcpy(newRom, gba->memory.rom, gba->pristineRomSize);
405		gba->memory.rom = newRom;
406#endif
407		gba->memory.romSize = SIZE_CART0;
408		gba->memory.romMask = SIZE_CART0 - 1;
409		gba->isPristine = false;
410	}
411	if (gba->cpu && gba->memory.activeRegion >= REGION_CART0) {
412		gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
413	}
414	// TODO: error check
415	return true;
416}
417
418bool GBALoadSave(struct GBA* gba, struct VFile* sav) {
419	GBASavedataInit(&gba->memory.savedata, sav);
420	return true;
421}
422
423void GBAYankROM(struct GBA* gba) {
424	gba->yankedRomSize = gba->memory.romSize;
425	gba->memory.romSize = 0;
426	gba->memory.romMask = 0;
427	GBARaiseIRQ(gba, IRQ_GAMEPAK);
428}
429
430void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
431	gba->biosVf = vf;
432	uint32_t* bios = vf->map(vf, SIZE_BIOS, MAP_READ);
433	if (!bios) {
434		mLOG(GBA, WARN, "Couldn't map BIOS");
435		return;
436	}
437	gba->memory.bios = bios;
438	gba->memory.fullBios = 1;
439	uint32_t checksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
440	mLOG(GBA, DEBUG, "BIOS Checksum: 0x%X", checksum);
441	if (checksum == GBA_BIOS_CHECKSUM) {
442		mLOG(GBA, INFO, "Official GBA BIOS detected");
443	} else if (checksum == GBA_DS_BIOS_CHECKSUM) {
444		mLOG(GBA, INFO, "Official GBA (DS) BIOS detected");
445	} else {
446		mLOG(GBA, WARN, "BIOS checksum incorrect");
447	}
448	gba->biosChecksum = checksum;
449	if (gba->memory.activeRegion == REGION_BIOS) {
450		gba->cpu->memory.activeRegion = gba->memory.bios;
451	}
452	// TODO: error check
453}
454
455void GBAApplyPatch(struct GBA* gba, struct Patch* patch) {
456	size_t patchedSize = patch->outputSize(patch, gba->memory.romSize);
457	if (!patchedSize || patchedSize > SIZE_CART0) {
458		return;
459	}
460	void* newRom = anonymousMemoryMap(SIZE_CART0);
461	if (!patch->applyPatch(patch, gba->memory.rom, gba->pristineRomSize, newRom, patchedSize)) {
462		mappedMemoryFree(newRom, SIZE_CART0);
463		return;
464	}
465	if (gba->romVf) {
466#ifndef FIXED_ROM_BUFFER
467		gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize);
468#endif
469		gba->romVf->close(gba->romVf);
470		gba->romVf = NULL;
471	}
472	gba->isPristine = false;
473	gba->memory.rom = newRom;
474	gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1];
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 GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) {
481	gba->memory.io[REG_IF >> 1] |= 1 << irq;
482	GBATestIRQ(gba->cpu);
483}
484
485void GBATestIRQ(struct ARMCore* cpu) {
486	struct GBA* gba = (struct GBA*) cpu->master;
487	if (gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) {
488		if (!mTimingIsScheduled(&gba->timing, &gba->irqEvent)) {
489			mTimingSchedule(&gba->timing, &gba->irqEvent, GBA_IRQ_DELAY);
490		}
491	}
492}
493
494void GBAHalt(struct GBA* gba) {
495	gba->cpu->nextEvent = gba->cpu->cycles;
496	gba->cpu->halted = 1;
497}
498
499void GBAStop(struct GBA* gba) {
500	size_t c;
501	for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
502		struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
503		if (callbacks->sleep) {
504			callbacks->sleep(callbacks->context);
505		}
506	}
507	gba->cpu->nextEvent = gba->cpu->cycles;
508}
509
510void GBADebug(struct GBA* gba, uint16_t flags) {
511	gba->debugFlags = flags;
512	if (GBADebugFlagsIsSend(gba->debugFlags)) {
513		int level = 1 << GBADebugFlagsGetLevel(gba->debugFlags);
514		level &= 0x1F;
515		char oolBuf[0x101];
516		strncpy(oolBuf, gba->debugString, sizeof(gba->debugString));
517		memset(gba->debugString, 0, sizeof(gba->debugString));
518		oolBuf[0x100] = '\0';
519		mLog(_mLOG_CAT_GBA_DEBUG(), level, "%s", oolBuf);
520	}
521	gba->debugFlags = GBADebugFlagsClearSend(gba->debugFlags);
522}
523
524bool GBAIsROM(struct VFile* vf) {
525#ifdef USE_ELF
526	struct ELF* elf = ELFOpen(vf);
527	if (elf) {
528		uint32_t entry = ELFEntry(elf);
529		bool isGBA = true;
530		isGBA = isGBA && ELFMachine(elf) == EM_ARM;
531		isGBA = isGBA && (entry == BASE_CART0 || entry == BASE_WORKING_RAM);
532		ELFClose(elf);
533		return isGBA;
534	}
535#endif
536	if (!vf) {
537		return false;
538	}
539
540	uint8_t signature[sizeof(GBA_ROM_MAGIC) + sizeof(GBA_ROM_MAGIC2)];
541	if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
542		return false;
543	}
544	if (vf->read(vf, &signature, sizeof(GBA_ROM_MAGIC)) != sizeof(GBA_ROM_MAGIC)) {
545		return false;
546	}
547	if (memcmp(signature, GBA_ROM_MAGIC, sizeof(GBA_ROM_MAGIC)) != 0) {
548		return false;
549	}
550
551	if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET2, SEEK_SET) < 0) {
552		return false;
553	}
554	if (vf->read(vf, &signature, sizeof(GBA_ROM_MAGIC2)) != sizeof(GBA_ROM_MAGIC2)) {
555		return false;
556	}
557	if (memcmp(signature, GBA_ROM_MAGIC2, sizeof(GBA_ROM_MAGIC2)) != 0) {
558		// If the signature byte is missing then we must be using an unfixed ROM
559		uint32_t buffer[0x9C / sizeof(uint32_t)];
560		if (vf->seek(vf, 0x4, SEEK_SET) < 0) {
561			return false;
562		}
563		if (vf->read(vf, &buffer, sizeof(buffer)) != sizeof(buffer)) {
564			return false;
565		}
566		uint32_t bits = 0;
567		size_t i;
568		for (i = 0; i < sizeof(buffer) / sizeof(*buffer); ++i) {
569			bits |= buffer[i];
570		}
571		if (bits) {
572			return false;
573		}
574	}
575
576
577	if (GBAIsBIOS(vf)) {
578		return false;
579	}
580	return true;
581}
582
583bool GBAIsMB(struct VFile* vf) {
584	if (!GBAIsROM(vf)) {
585		return false;
586	}
587#ifdef USE_ELF
588	struct ELF* elf = ELFOpen(vf);
589	if (elf) {
590		bool isMB = ELFEntry(elf) == BASE_WORKING_RAM;
591		ELFClose(elf);
592		return isMB;
593	}
594#endif
595	if (vf->size(vf) > SIZE_WORKING_RAM) {
596		return false;
597	}
598	if (vf->seek(vf, GBA_MB_MAGIC_OFFSET, SEEK_SET) < 0) {
599		return false;
600	}
601	uint32_t signature;
602	if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
603		return false;
604	}
605	uint32_t opcode;
606	LOAD_32(opcode, 0, &signature);
607	struct ARMInstructionInfo info;
608	ARMDecodeARM(opcode, &info);
609	if (info.branchType == ARM_BRANCH) {
610		if (info.op1.immediate <= 0) {
611			return false;
612		} else if (info.op1.immediate == 28) {
613			// Ancient toolchain that is known to throw MB detection for a loop
614			return false;
615		} else if (info.op1.immediate != 24) {
616			return true;
617		}
618	}
619
620	uint32_t pc = GBA_MB_MAGIC_OFFSET;
621	int i;
622	for (i = 0; i < 80; ++i) {
623		if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
624			break;
625		}
626		pc += 4;
627		LOAD_32(opcode, 0, &signature);
628		ARMDecodeARM(opcode, &info);
629		if (info.mnemonic != ARM_MN_LDR) {
630			continue;
631		}
632		if ((info.operandFormat & ARM_OPERAND_MEMORY) && info.memory.baseReg == ARM_PC && info.memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
633			uint32_t immediate = info.memory.offset.immediate;
634			if (info.memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
635				immediate = -immediate;
636			}
637			immediate += pc + 8;
638			if (vf->seek(vf, immediate, SEEK_SET) < 0) {
639				break;
640			}
641			if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
642				break;
643			}
644			LOAD_32(immediate, 0, &signature);
645			if (vf->seek(vf, pc, SEEK_SET) < 0) {
646				break;
647			}
648			if ((immediate & ~0x7FF) == BASE_WORKING_RAM) {
649				return true;
650			}
651		}
652	}
653	// Found a libgba-linked cart...these are a bit harder to detect.
654	return false;
655}
656
657bool GBAIsBIOS(struct VFile* vf) {
658	if (vf->seek(vf, 0, SEEK_SET) < 0) {
659		return false;
660	}
661	uint8_t interruptTable[7 * 4];
662	if (vf->read(vf, &interruptTable, sizeof(interruptTable)) != sizeof(interruptTable)) {
663		return false;
664	}
665	int i;
666	for (i = 0; i < 7; ++i) {
667		if (interruptTable[4 * i + 3] != 0xEA || interruptTable[4 * i + 2]) {
668			return false;
669		}
670	}
671	return true;
672}
673
674void GBAGetGameCode(const struct GBA* gba, char* out) {
675	memset(out, 0, 8);
676	if (!gba->memory.rom) {
677		return;
678	}
679
680	memcpy(out, "AGB-", 4);
681	memcpy(&out[4], &((struct GBACartridge*) gba->memory.rom)->id, 4);
682}
683
684void GBAGetGameTitle(const struct GBA* gba, char* out) {
685	if (gba->memory.rom) {
686		memcpy(out, &((struct GBACartridge*) gba->memory.rom)->title, 12);
687		return;
688	}
689	if (gba->isPristine && gba->memory.wram) {
690		memcpy(out, &((struct GBACartridge*) gba->memory.wram)->title, 12);
691		return;
692	}
693	strncpy(out, "(BIOS)", 12);
694}
695
696void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) {
697	struct GBA* gba = (struct GBA*) cpu->master;
698	UNUSED(gba);
699#ifdef USE_DEBUGGERS
700	if (gba->debugger) {
701		struct mDebuggerEntryInfo info = {
702			.address = _ARMPCAddress(cpu),
703			.type.bp.opcode = opcode
704		};
705		mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info);
706	}
707#endif
708	// TODO: More sensible category?
709	mLOG(GBA, ERROR, "Stub opcode: %08x", opcode);
710}
711
712void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) {
713	struct GBA* gba = (struct GBA*) cpu->master;
714	if (!gba->yankedRomSize) {
715		// TODO: More sensible category?
716		mLOG(GBA, WARN, "Illegal opcode: %08x", opcode);
717	}
718	if (cpu->executionMode == MODE_THUMB && (opcode & 0xFFC0) == 0xE800) {
719		mLOG(GBA, DEBUG, "Hit Wii U VC opcode: %08x", opcode);
720		return;
721	}
722#ifdef USE_DEBUGGERS
723	if (gba->debugger) {
724		struct mDebuggerEntryInfo info = {
725			.address = _ARMPCAddress(cpu),
726			.type.bp.opcode = opcode
727		};
728		mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info);
729	} else
730#endif
731	{
732		ARMRaiseUndefined(cpu);
733	}
734}
735
736void GBABreakpoint(struct ARMCore* cpu, int immediate) {
737	struct GBA* gba = (struct GBA*) cpu->master;
738	if (immediate >= CPU_COMPONENT_MAX) {
739		return;
740	}
741	switch (immediate) {
742#ifdef USE_DEBUGGERS
743	case CPU_COMPONENT_DEBUGGER:
744		if (gba->debugger) {
745			struct mDebuggerEntryInfo info = {
746				.address = _ARMPCAddress(cpu),
747				.type.bp.breakType = BREAKPOINT_SOFTWARE
748			};
749			mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_BREAKPOINT, &info);
750		}
751		break;
752#endif
753	case CPU_COMPONENT_CHEAT_DEVICE:
754		if (gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) {
755			struct mCheatDevice* device = (struct mCheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE];
756			struct GBACheatHook* hook = 0;
757			size_t i;
758			for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) {
759				struct GBACheatSet* cheats = (struct GBACheatSet*) *mCheatSetsGetPointer(&device->cheats, i);
760				if (cheats->hook && cheats->hook->address == _ARMPCAddress(cpu)) {
761					mCheatRefresh(device, &cheats->d);
762					hook = cheats->hook;
763				}
764			}
765			if (hook) {
766				ARMRunFake(cpu, hook->patchedOpcode);
767			}
768		}
769		break;
770	default:
771		break;
772	}
773}
774
775void GBAFrameStarted(struct GBA* gba) {
776	GBATestKeypadIRQ(gba);
777
778	size_t c;
779	for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
780		struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
781		if (callbacks->videoFrameStarted) {
782			callbacks->videoFrameStarted(callbacks->context);
783		}
784	}
785}
786
787void GBAFrameEnded(struct GBA* gba) {
788	GBASavedataClean(&gba->memory.savedata, gba->video.frameCounter);
789
790	if (gba->rr) {
791		gba->rr->nextFrame(gba->rr);
792	}
793
794	if (gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) {
795		struct mCheatDevice* device = (struct mCheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE];
796		size_t i;
797		for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) {
798			struct GBACheatSet* cheats = (struct GBACheatSet*) *mCheatSetsGetPointer(&device->cheats, i);
799			if (!cheats->hook) {
800				mCheatRefresh(device, &cheats->d);
801			}
802		}
803	}
804
805	if (gba->stream && gba->stream->postVideoFrame) {
806		const color_t* pixels;
807		size_t stride;
808		gba->video.renderer->getPixels(gba->video.renderer, &stride, (const void**) &pixels);
809		gba->stream->postVideoFrame(gba->stream, pixels, stride);
810	}
811
812	if (gba->memory.hw.devices & (HW_GB_PLAYER | HW_GB_PLAYER_DETECTION)) {
813		GBAHardwarePlayerUpdate(gba);
814	}
815
816	size_t c;
817	for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
818		struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
819		if (callbacks->videoFrameEnded) {
820			callbacks->videoFrameEnded(callbacks->context);
821		}
822	}
823}
824
825void GBATestKeypadIRQ(struct GBA* gba) {
826	uint16_t keycnt = gba->memory.io[REG_KEYCNT >> 1];
827	if (!(keycnt & 0x4000)) {
828		return;
829	}
830	int isAnd = keycnt & 0x8000;
831	if (!gba->keySource) {
832		// TODO?
833		return;
834	}
835
836	keycnt &= 0x3FF;
837	uint16_t keyInput = *gba->keySource & keycnt;
838
839	if (isAnd && keycnt == keyInput) {
840		GBARaiseIRQ(gba, IRQ_KEYPAD);
841	} else if (!isAnd && keyInput) {
842		GBARaiseIRQ(gba, IRQ_KEYPAD);
843	}
844}
845
846static void _triggerIRQ(struct mTiming* timing, void* user, uint32_t cyclesLate) {
847	UNUSED(timing);
848	UNUSED(cyclesLate);
849	struct GBA* gba = user;
850	gba->cpu->halted = 0;
851	if (!(gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1])) {
852		return;
853	}
854
855	if (gba->memory.io[REG_IME >> 1] && !gba->cpu->cpsr.i) {
856		ARMRaiseIRQ(gba->cpu);
857	}
858}
859
860void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
861	size_t immediate;
862	for (immediate = 0; immediate < gba->cpu->numComponents; ++immediate) {
863		if (gba->cpu->components[immediate] == component) {
864			break;
865		}
866	}
867	if (immediate == gba->cpu->numComponents) {
868		return;
869	}
870	if (mode == MODE_ARM) {
871		int32_t value;
872		int32_t old;
873		value = 0xE1200070;
874		value |= immediate & 0xF;
875		value |= (immediate & 0xFFF0) << 4;
876		GBAPatch32(gba->cpu, address, value, &old);
877		*opcode = old;
878	} else {
879		int16_t value;
880		int16_t old;
881		value = 0xBE00;
882		value |= immediate & 0xFF;
883		GBAPatch16(gba->cpu, address, value, &old);
884		*opcode = (uint16_t) old;
885	}
886}
887
888void GBAClearBreakpoint(struct GBA* gba, uint32_t address, enum ExecutionMode mode, uint32_t opcode) {
889	if (mode == MODE_ARM) {
890		GBAPatch32(gba->cpu, address, opcode, 0);
891	} else {
892		GBAPatch16(gba->cpu, address, opcode, 0);
893	}
894}
895
896#ifdef USE_DEBUGGERS
897static bool _setSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
898	GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d.p->d, address, mode, opcode);
899	return true;
900}
901
902static bool _clearSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t opcode) {
903	GBAClearBreakpoint((struct GBA*) debugger->cpu->master, address, mode, opcode);
904	return true;
905}
906#endif