all repos — mgba @ a44621e0d4e15d49864ef751c6f6f048a5df6415

mGBA Game Boy Advance Emulator

src/gb/gb.c (view raw)

  1/* Copyright (c) 2013-2016 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/gb/gb.h>
  7
  8#include <mgba/internal/gb/io.h>
  9#include <mgba/internal/gb/mbc.h>
 10#include <mgba/internal/lr35902/lr35902.h>
 11
 12#include <mgba/core/core.h>
 13#include <mgba/core/cheats.h>
 14#include <mgba-util/crc32.h>
 15#include <mgba-util/memory.h>
 16#include <mgba-util/math.h>
 17#include <mgba-util/patch.h>
 18#include <mgba-util/vfs.h>
 19
 20#define CLEANUP_THRESHOLD 15
 21
 22const uint32_t CGB_LR35902_FREQUENCY = 0x800000;
 23const uint32_t SGB_LR35902_FREQUENCY = 0x418B1E;
 24
 25const uint32_t GB_COMPONENT_MAGIC = 0x400000;
 26
 27static const uint8_t _knownHeader[4] = { 0xCE, 0xED, 0x66, 0x66};
 28
 29#define DMG_BIOS_CHECKSUM 0xC2F5CC97
 30#define DMG_2_BIOS_CHECKSUM 0x59C8598E
 31#define MGB_BIOS_CHECKSUM 0xE6920754
 32#define SGB_BIOS_CHECKSUM 0xEC8A83B9
 33#define CGB_BIOS_CHECKSUM 0x41884E46
 34
 35mLOG_DEFINE_CATEGORY(GB, "GB", "gb");
 36
 37static void GBInit(void* cpu, struct mCPUComponent* component);
 38static void GBDeinit(struct mCPUComponent* component);
 39static void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh);
 40static void GBProcessEvents(struct LR35902Core* cpu);
 41static void GBSetInterrupts(struct LR35902Core* cpu, bool enable);
 42static uint16_t GBIRQVector(struct LR35902Core* cpu);
 43static void GBIllegal(struct LR35902Core* cpu);
 44static void GBStop(struct LR35902Core* cpu);
 45
 46static void _enableInterrupts(struct mTiming* timing, void* user, uint32_t cyclesLate);
 47
 48#ifdef FIXED_ROM_BUFFER
 49extern uint32_t* romBuffer;
 50extern size_t romBufferSize;
 51#endif
 52
 53void GBCreate(struct GB* gb) {
 54	gb->d.id = GB_COMPONENT_MAGIC;
 55	gb->d.init = GBInit;
 56	gb->d.deinit = GBDeinit;
 57}
 58
 59static void GBInit(void* cpu, struct mCPUComponent* component) {
 60	struct GB* gb = (struct GB*) component;
 61	gb->cpu = cpu;
 62	gb->sync = NULL;
 63
 64	GBInterruptHandlerInit(&gb->cpu->irqh);
 65	GBMemoryInit(gb);
 66
 67	gb->video.p = gb;
 68	GBVideoInit(&gb->video);
 69
 70	gb->audio.p = gb;
 71	GBAudioInit(&gb->audio, 2048, &gb->memory.io[REG_NR52], GB_AUDIO_DMG); // TODO: Remove magic constant
 72
 73	gb->sio.p = gb;
 74	GBSIOInit(&gb->sio);
 75
 76	gb->timer.p = gb;
 77
 78	gb->model = GB_MODEL_AUTODETECT;
 79
 80	gb->biosVf = NULL;
 81	gb->romVf = NULL;
 82	gb->sramVf = NULL;
 83	gb->sramRealVf = NULL;
 84
 85	gb->isPristine = false;
 86	gb->pristineRomSize = 0;
 87	gb->yankedRomSize = 0;
 88
 89	mCoreCallbacksListInit(&gb->coreCallbacks, 0);
 90	gb->stream = NULL;
 91
 92	mTimingInit(&gb->timing, &gb->cpu->cycles, &gb->cpu->nextEvent);
 93	gb->audio.timing = &gb->timing;
 94
 95	gb->eiPending.name = "GB EI";
 96	gb->eiPending.callback = _enableInterrupts;
 97	gb->eiPending.context = gb;
 98	gb->eiPending.priority = 0;
 99}
100
101static void GBDeinit(struct mCPUComponent* component) {
102	struct GB* gb = (struct GB*) component;
103	mTimingDeinit(&gb->timing);
104}
105
106bool GBLoadROM(struct GB* gb, struct VFile* vf) {
107	if (!vf) {
108		return false;
109	}
110	GBUnloadROM(gb);
111	gb->romVf = vf;
112	gb->pristineRomSize = vf->size(vf);
113	vf->seek(vf, 0, SEEK_SET);
114	gb->isPristine = true;
115#ifdef FIXED_ROM_BUFFER
116	if (gb->pristineRomSize <= romBufferSize) {
117		gb->memory.rom = romBuffer;
118		vf->read(vf, romBuffer, gb->pristineRomSize);
119	}
120#else
121	gb->memory.rom = vf->map(vf, gb->pristineRomSize, MAP_READ);
122#endif
123	if (!gb->memory.rom) {
124		return false;
125	}
126	gb->yankedRomSize = 0;
127	gb->memory.romBase = gb->memory.rom;
128	gb->memory.romSize = gb->pristineRomSize;
129	gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize);
130	GBMBCInit(gb);
131
132	if (gb->cpu) {
133		struct LR35902Core* cpu = gb->cpu;
134		cpu->memory.setActiveRegion(cpu, cpu->pc);
135	}
136
137	// TODO: error check
138	return true;
139}
140
141static void GBSramDeinit(struct GB* gb) {
142	if (gb->sramVf) {
143		gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize);
144		if (gb->memory.mbcType == GB_MBC3_RTC && gb->sramVf == gb->sramRealVf) {
145			GBMBCRTCWrite(gb);
146		}
147		gb->sramVf = NULL;
148	} else if (gb->memory.sram) {
149		mappedMemoryFree(gb->memory.sram, gb->sramSize);
150	}
151	gb->memory.sram = 0;
152}
153
154bool GBLoadSave(struct GB* gb, struct VFile* vf) {
155	GBSramDeinit(gb);
156	gb->sramVf = vf;
157	gb->sramRealVf = vf;
158	if (gb->sramSize) {
159		GBResizeSram(gb, gb->sramSize);
160		GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank);
161	}
162	return vf;
163}
164
165void GBResizeSram(struct GB* gb, size_t size) {
166	if (gb->memory.sram && size <= gb->sramSize) {
167		return;
168	}
169	struct VFile* vf = gb->sramVf;
170	if (vf) {
171		if (vf == gb->sramRealVf) {
172			ssize_t vfSize = vf->size(vf);
173			if (vfSize >= 0 && (size_t) vfSize < size) {
174				uint8_t extdataBuffer[0x100];
175				if (vfSize & 0xFF) {
176					vf->seek(vf, -(vfSize & 0xFF), SEEK_END);
177					vf->read(vf, extdataBuffer, vfSize & 0xFF);
178				}
179				if (gb->memory.sram) {
180					vf->unmap(vf, gb->memory.sram, gb->sramSize);
181				}
182				vf->truncate(vf, size + (vfSize & 0xFF));
183				if (vfSize & 0xFF) {
184					vf->seek(vf, size, SEEK_SET);
185					vf->write(vf, extdataBuffer, vfSize & 0xFF);
186				}
187				gb->memory.sram = vf->map(vf, size, MAP_WRITE);
188				memset(&gb->memory.sram[gb->sramSize], 0xFF, size - gb->sramSize);
189			} else if (size > gb->sramSize || !gb->memory.sram) {
190				if (gb->memory.sram) {
191					vf->unmap(vf, gb->memory.sram, gb->sramSize);
192				}
193				gb->memory.sram = vf->map(vf, size, MAP_WRITE);
194			}
195		} else {
196			if (gb->memory.sram) {
197				vf->unmap(vf, gb->memory.sram, gb->sramSize);
198			}
199			gb->memory.sram = vf->map(vf, size, MAP_READ);
200		}
201		if (gb->memory.sram == (void*) -1) {
202			gb->memory.sram = NULL;
203		}
204	} else {
205		uint8_t* newSram = anonymousMemoryMap(size);
206		if (gb->memory.sram) {
207			if (size > gb->sramSize) {
208				memcpy(newSram, gb->memory.sram, gb->sramSize);
209				memset(&newSram[gb->sramSize], 0xFF, size - gb->sramSize);
210			} else {
211				memcpy(newSram, gb->memory.sram, size);
212			}
213			mappedMemoryFree(gb->memory.sram, gb->sramSize);
214		} else {
215			memset(newSram, 0xFF, size);
216		}
217		gb->memory.sram = newSram;
218	}
219	if (gb->sramSize < size) {
220		gb->sramSize = size;
221	}
222}
223
224void GBSramClean(struct GB* gb, uint32_t frameCount) {
225	// TODO: Share with GBASavedataClean
226	if (!gb->sramVf) {
227		return;
228	}
229	if (gb->sramDirty & GB_SRAM_DIRT_NEW) {
230		gb->sramDirtAge = frameCount;
231		gb->sramDirty &= ~GB_SRAM_DIRT_NEW;
232		if (!(gb->sramDirty & GB_SRAM_DIRT_SEEN)) {
233			gb->sramDirty |= GB_SRAM_DIRT_SEEN;
234		}
235	} else if ((gb->sramDirty & GB_SRAM_DIRT_SEEN) && frameCount - gb->sramDirtAge > CLEANUP_THRESHOLD) {
236		if (gb->sramMaskWriteback) {
237			GBSavedataUnmask(gb);
238		}
239		if (gb->memory.mbcType == GB_MBC3_RTC) {
240			GBMBCRTCWrite(gb);
241		}
242		gb->sramDirty = 0;
243		if (gb->memory.sram && gb->sramVf->sync(gb->sramVf, gb->memory.sram, gb->sramSize)) {
244			mLOG(GB_MEM, INFO, "Savedata synced");
245		} else {
246			mLOG(GB_MEM, INFO, "Savedata failed to sync!");
247		}
248	}
249}
250
251void GBSavedataMask(struct GB* gb, struct VFile* vf, bool writeback) {
252	struct VFile* oldVf = gb->sramVf;
253	GBSramDeinit(gb);
254	if (oldVf && oldVf != gb->sramRealVf) {
255		oldVf->close(oldVf);
256	}
257	gb->sramVf = vf;
258	gb->sramMaskWriteback = writeback;
259	gb->memory.sram = vf->map(vf, gb->sramSize, MAP_READ);
260	GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank);
261}
262
263void GBSavedataUnmask(struct GB* gb) {
264	if (!gb->sramRealVf || gb->sramVf == gb->sramRealVf) {
265		return;
266	}
267	struct VFile* vf = gb->sramVf;
268	GBSramDeinit(gb);
269	gb->sramVf = gb->sramRealVf;
270	gb->memory.sram = gb->sramVf->map(gb->sramVf, gb->sramSize, MAP_WRITE);
271	if (gb->sramMaskWriteback) {
272		vf->seek(vf, 0, SEEK_SET);
273		vf->read(vf, gb->memory.sram, gb->sramSize);
274		gb->sramMaskWriteback = false;
275	}
276	GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank);
277	vf->close(vf);
278}
279
280void GBUnloadROM(struct GB* gb) {
281	// TODO: Share with GBAUnloadROM
282	if (gb->memory.rom && gb->memory.romBase != gb->memory.rom && !gb->isPristine) {
283		free(gb->memory.romBase);
284	}
285	if (gb->memory.rom && !gb->isPristine) {
286		if (gb->yankedRomSize) {
287			gb->yankedRomSize = 0;
288		}
289		mappedMemoryFree(gb->memory.rom, GB_SIZE_CART_MAX);
290	}
291
292	if (gb->romVf) {
293#ifndef FIXED_ROM_BUFFER
294		gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize);
295#endif
296		gb->romVf->close(gb->romVf);
297		gb->romVf = NULL;
298	}
299	gb->memory.rom = NULL;
300	gb->memory.mbcType = GB_MBC_AUTODETECT;
301	gb->isPristine = false;
302
303	gb->sramMaskWriteback = false;
304	GBSramDeinit(gb);
305	if (gb->sramRealVf) {
306		gb->sramRealVf->close(gb->sramRealVf);
307	}
308	gb->sramRealVf = NULL;
309	gb->sramVf = NULL;
310	if (gb->memory.cam && gb->memory.cam->stopRequestImage) {
311		gb->memory.cam->stopRequestImage(gb->memory.cam);
312	}
313}
314
315void GBSynthesizeROM(struct VFile* vf) {
316	if (!vf) {
317		return;
318	}
319	const struct GBCartridge cart = {
320		.logo = { _knownHeader[0], _knownHeader[1], _knownHeader[2], _knownHeader[3]}
321	};
322
323	vf->seek(vf, 0x100, SEEK_SET);
324	vf->write(vf, &cart, sizeof(cart));
325}
326
327void GBLoadBIOS(struct GB* gb, struct VFile* vf) {
328	gb->biosVf = vf;
329}
330
331void GBApplyPatch(struct GB* gb, struct Patch* patch) {
332	size_t patchedSize = patch->outputSize(patch, gb->memory.romSize);
333	if (!patchedSize) {
334		return;
335	}
336	if (patchedSize > GB_SIZE_CART_MAX) {
337		patchedSize = GB_SIZE_CART_MAX;
338	}
339	void* newRom = anonymousMemoryMap(GB_SIZE_CART_MAX);
340	if (!patch->applyPatch(patch, gb->memory.rom, gb->pristineRomSize, newRom, patchedSize)) {
341		mappedMemoryFree(newRom, GB_SIZE_CART_MAX);
342		return;
343	}
344	if (gb->romVf) {
345#ifndef FIXED_ROM_BUFFER
346		gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize);
347#endif
348		gb->romVf->close(gb->romVf);
349		gb->romVf = NULL;
350	}
351	gb->isPristine = false;
352	if (gb->memory.romBase == gb->memory.rom) {
353		gb->memory.romBase = newRom;
354	}
355	gb->memory.rom = newRom;
356	gb->memory.romSize = patchedSize;
357	gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize);
358	gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
359}
360
361void GBDestroy(struct GB* gb) {
362	GBUnloadROM(gb);
363
364	if (gb->biosVf) {
365		gb->biosVf->close(gb->biosVf);
366		gb->biosVf = 0;
367	}
368
369	GBMemoryDeinit(gb);
370	GBAudioDeinit(&gb->audio);
371	GBVideoDeinit(&gb->video);
372	GBSIODeinit(&gb->sio);
373	mCoreCallbacksListDeinit(&gb->coreCallbacks);
374}
375
376void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {
377	irqh->reset = GBReset;
378	irqh->processEvents = GBProcessEvents;
379	irqh->setInterrupts = GBSetInterrupts;
380	irqh->irqVector = GBIRQVector;
381	irqh->hitIllegal = GBIllegal;
382	irqh->stop = GBStop;
383	irqh->halt = GBHalt;
384}
385
386static uint32_t _GBBiosCRC32(struct VFile* vf) {
387	ssize_t size = vf->size(vf);
388	if (size <= 0 || size > GB_SIZE_CART_BANK0) {
389		return 0;
390	}
391	void* bios = vf->map(vf, size, MAP_READ);
392	uint32_t biosCrc = doCrc32(bios, size);
393	vf->unmap(vf, bios, size);
394	return biosCrc;
395}
396
397bool GBIsBIOS(struct VFile* vf) {
398	switch (_GBBiosCRC32(vf)) {
399	case DMG_BIOS_CHECKSUM:
400	case DMG_2_BIOS_CHECKSUM:
401	case MGB_BIOS_CHECKSUM:
402	case SGB_BIOS_CHECKSUM:
403	case CGB_BIOS_CHECKSUM:
404		return true;
405	default:
406		return false;
407	}
408}
409
410void GBReset(struct LR35902Core* cpu) {
411	struct GB* gb = (struct GB*) cpu->master;
412	gb->memory.romBase = gb->memory.rom;
413	GBDetectModel(gb);
414
415	if (gb->biosVf) {
416		if (!GBIsBIOS(gb->biosVf)) {
417			gb->biosVf->close(gb->biosVf);
418			gb->biosVf = NULL;
419		} else {
420			gb->biosVf->seek(gb->biosVf, 0, SEEK_SET);
421			gb->memory.romBase = malloc(GB_SIZE_CART_BANK0);
422			ssize_t size = gb->biosVf->read(gb->biosVf, gb->memory.romBase, GB_SIZE_CART_BANK0);
423			memcpy(&gb->memory.romBase[size], &gb->memory.rom[size], GB_SIZE_CART_BANK0 - size);
424			if (size > 0x100) {
425				memcpy(&gb->memory.romBase[0x100], &gb->memory.rom[0x100], sizeof(struct GBCartridge));
426			}
427
428			cpu->a = 0;
429			cpu->f.packed = 0;
430			cpu->c = 0;
431			cpu->e = 0;
432			cpu->h = 0;
433			cpu->l = 0;
434			cpu->sp = 0;
435			cpu->pc = 0;
436		}
437	}
438
439	cpu->b = 0;
440	cpu->d = 0;
441
442	gb->timer.internalDiv = 0;
443
444	gb->cpuBlocked = false;
445	gb->earlyExit = false;
446	gb->doubleSpeed = 0;
447
448	if (gb->yankedRomSize) {
449		gb->memory.romSize = gb->yankedRomSize;
450		gb->yankedRomSize = 0;
451	}
452
453	gb->sgbBit = -1;
454	gb->sgbControllers = 0;
455	gb->sgbCurrentController = 0;
456	gb->currentSgbBits = 0;
457	memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket));
458
459	mTimingClear(&gb->timing);
460
461	GBMemoryReset(gb);
462	GBVideoReset(&gb->video);
463	GBTimerReset(&gb->timer);
464	if (!gb->biosVf) {
465		GBSkipBIOS(gb);
466	} else {
467		mTimingSchedule(&gb->timing, &gb->timer.event, 0);
468	}
469
470	GBIOReset(gb);
471	GBAudioReset(&gb->audio);
472	GBSIOReset(&gb->sio);
473
474	cpu->memory.setActiveRegion(cpu, cpu->pc);
475
476	gb->sramMaskWriteback = false;
477	GBSavedataUnmask(gb);
478}
479
480void GBSkipBIOS(struct GB* gb) {
481	struct LR35902Core* cpu = gb->cpu;
482	int nextDiv = 0;
483
484	switch (gb->model) {
485	case GB_MODEL_AUTODETECT: // Silence warnings
486		gb->model = GB_MODEL_DMG;
487		// Fall through
488	case GB_MODEL_DMG:
489		cpu->a = 1;
490		cpu->f.packed = 0xB0;
491		cpu->c = 0x13;
492		cpu->e = 0xD8;
493		cpu->h = 1;
494		cpu->l = 0x4D;
495		gb->timer.internalDiv = 0xABC;
496		nextDiv = 4;
497		break;
498	case GB_MODEL_SGB:
499		cpu->a = 1;
500		cpu->f.packed = 0x00;
501		cpu->c = 0x14;
502		cpu->e = 0x00;
503		cpu->h = 0xC0;
504		cpu->l = 0x60;
505		gb->timer.internalDiv = 0xABC;
506		nextDiv = 4;
507		break;
508	case GB_MODEL_MGB:
509		cpu->a = 0xFF;
510		cpu->f.packed = 0xB0;
511		cpu->c = 0x13;
512		cpu->e = 0xD8;
513		cpu->h = 1;
514		cpu->l = 0x4D;
515		gb->timer.internalDiv = 0xABC;
516		nextDiv = 4;
517		break;
518	case GB_MODEL_SGB2:
519		cpu->a = 0xFF;
520		cpu->f.packed = 0x00;
521		cpu->c = 0x14;
522		cpu->e = 0x00;
523		cpu->h = 0xC0;
524		cpu->l = 0x60;
525		gb->timer.internalDiv = 0xABC;
526		nextDiv = 4;
527		break;
528	case GB_MODEL_AGB:
529		cpu->a = 0x11;
530		cpu->b = 1;
531		cpu->f.packed = 0x00;
532		cpu->c = 0;
533		cpu->e = 0x08;
534		cpu->h = 0;
535		cpu->l = 0x7C;
536		gb->timer.internalDiv = 0x1EA;
537		nextDiv = 0xC;
538		break;
539	case GB_MODEL_CGB:
540		cpu->a = 0x11;
541		cpu->f.packed = 0x80;
542		cpu->c = 0;
543		cpu->e = 0x08;
544		cpu->h = 0;
545		cpu->l = 0x7C;
546		gb->timer.internalDiv = 0x1EA;
547		nextDiv = 0xC;
548		break;
549	}
550
551	cpu->sp = 0xFFFE;
552	cpu->pc = 0x100;
553
554	mTimingDeschedule(&gb->timing, &gb->timer.event);
555	mTimingSchedule(&gb->timing, &gb->timer.event, 0);
556
557	GBIOWrite(gb, REG_LCDC, 0x91);
558
559	if (gb->biosVf) {
560		GBUnmapBIOS(gb);
561	}
562}
563
564void GBUnmapBIOS(struct GB* gb) {
565	if (gb->memory.romBase < gb->memory.rom || gb->memory.romBase > &gb->memory.rom[gb->memory.romSize - 1]) {
566		free(gb->memory.romBase);
567		gb->memory.romBase = gb->memory.rom;
568	}
569	// XXX: Force AGB registers for AGB-mode
570	if (gb->model == GB_MODEL_AGB && gb->cpu->pc == 0x100) {
571		gb->cpu->b = 1;
572	}
573}
574
575void GBDetectModel(struct GB* gb) {
576	if (gb->model != GB_MODEL_AUTODETECT) {
577		return;
578	}
579	if (gb->biosVf) {
580		switch (_GBBiosCRC32(gb->biosVf)) {
581		case DMG_BIOS_CHECKSUM:
582		case DMG_2_BIOS_CHECKSUM:
583			gb->model = GB_MODEL_DMG;
584			break;
585		case MGB_BIOS_CHECKSUM:
586			gb->model = GB_MODEL_MGB;
587			break;
588		case SGB_BIOS_CHECKSUM:
589			gb->model = GB_MODEL_SGB;
590			break;
591		case CGB_BIOS_CHECKSUM:
592			gb->model = GB_MODEL_CGB;
593			break;
594		default:
595			gb->biosVf->close(gb->biosVf);
596			gb->biosVf = NULL;
597		}
598	}
599	if (gb->model == GB_MODEL_AUTODETECT && gb->memory.rom) {
600		const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
601		if (cart->cgb & 0x80) {
602			gb->model = GB_MODEL_CGB;
603		} else if (cart->sgb == 0x03 && cart->oldLicensee == 0x33) {
604			gb->model = GB_MODEL_SGB;
605		} else {
606			gb->model = GB_MODEL_DMG;
607		}
608	}
609
610	switch (gb->model) {
611	case GB_MODEL_DMG:
612	case GB_MODEL_SGB:
613	case GB_MODEL_AUTODETECT: //Silence warnings
614		gb->audio.style = GB_AUDIO_DMG;
615		break;
616	case GB_MODEL_MGB:
617	case GB_MODEL_SGB2:
618		gb->audio.style = GB_AUDIO_MGB;
619		break;
620	case GB_MODEL_AGB:
621	case GB_MODEL_CGB:
622		gb->audio.style = GB_AUDIO_CGB;
623		break;
624	}
625}
626
627void GBUpdateIRQs(struct GB* gb) {
628	int irqs = gb->memory.ie & gb->memory.io[REG_IF];
629	if (!irqs) {
630		gb->cpu->irqPending = false;
631		return;
632	}
633	gb->cpu->halted = false;
634
635	if (!gb->memory.ime) {
636		gb->cpu->irqPending = false;
637		return;
638	}
639	if (gb->cpu->irqPending) {
640		return;
641	}
642	LR35902RaiseIRQ(gb->cpu);
643}
644
645void GBProcessEvents(struct LR35902Core* cpu) {
646	struct GB* gb = (struct GB*) cpu->master;
647	do {
648		int32_t cycles = cpu->cycles;
649		int32_t nextEvent;
650
651		cpu->cycles = 0;
652		cpu->nextEvent = INT_MAX;
653
654		nextEvent = cycles;
655		do {
656			nextEvent = mTimingTick(&gb->timing, nextEvent);
657		} while (gb->cpuBlocked);
658		cpu->nextEvent = nextEvent;
659
660		if (cpu->halted) {
661			cpu->cycles = cpu->nextEvent;
662			if (!gb->memory.ie || !gb->memory.ime) {
663				break;
664			}
665		}
666		if (gb->earlyExit) {
667			break;
668		}
669	} while (cpu->cycles >= cpu->nextEvent);
670	gb->earlyExit = false;
671}
672
673void GBSetInterrupts(struct LR35902Core* cpu, bool enable) {
674	struct GB* gb = (struct GB*) cpu->master;
675	mTimingDeschedule(&gb->timing, &gb->eiPending);
676	if (!enable) {
677		gb->memory.ime = false;
678		GBUpdateIRQs(gb);
679	} else {
680		mTimingSchedule(&gb->timing, &gb->eiPending, 4);
681	}
682}
683
684uint16_t GBIRQVector(struct LR35902Core* cpu) {
685	struct GB* gb = (struct GB*) cpu->master;
686	int irqs = gb->memory.ie & gb->memory.io[REG_IF];
687
688	if (irqs & (1 << GB_IRQ_VBLANK)) {
689		gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_VBLANK);
690		return GB_VECTOR_VBLANK;
691	}
692	if (irqs & (1 << GB_IRQ_LCDSTAT)) {
693		gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_LCDSTAT);
694		return GB_VECTOR_LCDSTAT;
695	}
696	if (irqs & (1 << GB_IRQ_TIMER)) {
697		gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_TIMER);
698		return GB_VECTOR_TIMER;
699	}
700	if (irqs & (1 << GB_IRQ_SIO)) {
701		gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_SIO);
702		return GB_VECTOR_SIO;
703	}
704	if (irqs & (1 << GB_IRQ_KEYPAD)) {
705		gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_KEYPAD);
706		return GB_VECTOR_KEYPAD;
707	}
708	return 0;
709}
710
711static void _enableInterrupts(struct mTiming* timing, void* user, uint32_t cyclesLate) {
712	UNUSED(timing);
713	UNUSED(cyclesLate);
714	struct GB* gb = user;
715	gb->memory.ime = true;
716	GBUpdateIRQs(gb);
717}
718
719void GBHalt(struct LR35902Core* cpu) {
720	struct GB* gb = (struct GB*) cpu->master;
721	if (!(gb->memory.ie & gb->memory.io[REG_IF])) {
722		cpu->cycles = cpu->nextEvent;
723		cpu->halted = true;
724	} else if (gb->model < GB_MODEL_CGB) {
725		mLOG(GB, STUB, "Unimplemented HALT bug");
726	}
727}
728
729void GBStop(struct LR35902Core* cpu) {
730	struct GB* gb = (struct GB*) cpu->master;
731	if (cpu->bus) {
732		mLOG(GB, GAME_ERROR, "Hit illegal stop at address %04X:%02X", cpu->pc, cpu->bus);
733	}
734	if (gb->memory.io[REG_KEY1] & 1) {
735		gb->doubleSpeed ^= 1;
736		gb->audio.timingFactor = gb->doubleSpeed + 1;
737		gb->memory.io[REG_KEY1] = 0;
738		gb->memory.io[REG_KEY1] |= gb->doubleSpeed << 7;
739	} else if (cpu->bus) {
740#ifdef USE_DEBUGGERS
741		if (cpu->components && cpu->components[CPU_COMPONENT_DEBUGGER]) {
742			struct mDebuggerEntryInfo info = {
743				.address = cpu->pc - 1,
744				.type.bp.opcode = 0x1000 | cpu->bus
745			};
746			mDebuggerEnter((struct mDebugger*) cpu->components[CPU_COMPONENT_DEBUGGER], DEBUGGER_ENTER_ILLEGAL_OP, &info);
747		}
748#endif
749		// Hang forever
750		gb->memory.ime = 0;
751		cpu->pc -= 2;
752	}
753	// TODO: Actually stop
754}
755
756void GBIllegal(struct LR35902Core* cpu) {
757	struct GB* gb = (struct GB*) cpu->master;
758	mLOG(GB, GAME_ERROR, "Hit illegal opcode at address %04X:%02X", cpu->pc, cpu->bus);
759#ifdef USE_DEBUGGERS
760	if (cpu->components && cpu->components[CPU_COMPONENT_DEBUGGER]) {
761		struct mDebuggerEntryInfo info = {
762			.address = cpu->pc,
763			.type.bp.opcode = cpu->bus
764		};
765		mDebuggerEnter((struct mDebugger*) cpu->components[CPU_COMPONENT_DEBUGGER], DEBUGGER_ENTER_ILLEGAL_OP, &info);
766	}
767#endif
768	// Hang forever
769	gb->memory.ime = 0;
770	--cpu->pc;
771}
772
773bool GBIsROM(struct VFile* vf) {
774	if (!vf) {
775		return false;
776	}
777	vf->seek(vf, 0x104, SEEK_SET);
778	uint8_t header[4];
779
780	if (vf->read(vf, &header, sizeof(header)) < (ssize_t) sizeof(header)) {
781		return false;
782	}
783	if (memcmp(header, _knownHeader, sizeof(header))) {
784		return false;
785	}
786	return true;
787}
788
789void GBGetGameTitle(const struct GB* gb, char* out) {
790	const struct GBCartridge* cart = NULL;
791	if (gb->memory.rom) {
792		cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
793	}
794	if (!cart) {
795		return;
796	}
797	if (cart->oldLicensee != 0x33) {
798		memcpy(out, cart->titleLong, 16);
799	} else {
800		memcpy(out, cart->titleShort, 11);
801	}
802}
803
804void GBGetGameCode(const struct GB* gb, char* out) {
805	memset(out, 0, 8);
806	const struct GBCartridge* cart = NULL;
807	if (gb->memory.rom) {
808		cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
809	}
810	if (!cart) {
811		return;
812	}
813	if (cart->cgb == 0xC0) {
814		memcpy(out, "CGB-????", 8);
815	} else {
816		memcpy(out, "DMG-????", 8);
817	}
818	if (cart->oldLicensee == 0x33) {
819		memcpy(&out[4], cart->maker, 4);
820	}
821}
822
823void GBFrameStarted(struct GB* gb) {
824	GBTestKeypadIRQ(gb);
825
826	size_t c;
827	for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) {
828		struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c);
829		if (callbacks->videoFrameStarted) {
830			callbacks->videoFrameStarted(callbacks->context);
831		}
832	}
833}
834
835void GBFrameEnded(struct GB* gb) {
836	GBSramClean(gb, gb->video.frameCounter);
837
838	if (gb->cpu->components && gb->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) {
839		struct mCheatDevice* device = (struct mCheatDevice*) gb->cpu->components[CPU_COMPONENT_CHEAT_DEVICE];
840		size_t i;
841		for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) {
842			struct mCheatSet* cheats = *mCheatSetsGetPointer(&device->cheats, i);
843			mCheatRefresh(device, cheats);
844		}
845	}
846
847	// TODO: Move to common code
848	if (gb->stream && gb->stream->postVideoFrame) {
849		const color_t* pixels;
850		size_t stride;
851		gb->video.renderer->getPixels(gb->video.renderer, &stride, (const void**) &pixels);
852		gb->stream->postVideoFrame(gb->stream, pixels, stride);
853	}
854
855	size_t c;
856	for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) {
857		struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c);
858		if (callbacks->videoFrameEnded) {
859			callbacks->videoFrameEnded(callbacks->context);
860		}
861	}
862}
863
864enum GBModel GBNameToModel(const char* model) {
865	if (strcasecmp(model, "DMG") == 0) {
866		return GB_MODEL_DMG;
867	} else if (strcasecmp(model, "CGB") == 0) {
868		return GB_MODEL_CGB;
869	} else if (strcasecmp(model, "AGB") == 0) {
870		return GB_MODEL_AGB;
871	} else if (strcasecmp(model, "SGB") == 0) {
872		return GB_MODEL_SGB;
873	} else if (strcasecmp(model, "MGB") == 0) {
874		return GB_MODEL_MGB;
875	} else if (strcasecmp(model, "SGB2") == 0) {
876		return GB_MODEL_SGB2;
877	}
878	return GB_MODEL_AUTODETECT;
879}
880
881const char* GBModelToName(enum GBModel model) {
882	switch (model) {
883	case GB_MODEL_DMG:
884		return "DMG";
885	case GB_MODEL_SGB:
886		return "SGB";
887	case GB_MODEL_MGB:
888		return "MGB";
889	case GB_MODEL_SGB2:
890		return "SGB2";
891	case GB_MODEL_CGB:
892		return "CGB";
893	case GB_MODEL_AGB:
894		return "AGB";
895	default:
896	case GB_MODEL_AUTODETECT:
897		return NULL;
898	}
899}