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