all repos — mgba @ a71007267d684ff85249be0b6947d6a3e7ce9678

mGBA Game Boy Advance Emulator

src/gb/mbc.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 "mbc.h"
  7
  8#include "gb/gb.h"
  9#include "gb/memory.h"
 10#include "gb/memory.h"
 11#include "util/vfs.h"
 12
 13#include <time.h>
 14
 15mLOG_DEFINE_CATEGORY(GB_MBC, "GB MBC");
 16
 17static void _GBMBCNone(struct GB* gb, uint16_t address, uint8_t value) {
 18	UNUSED(gb);
 19	UNUSED(address);
 20	UNUSED(value);
 21
 22	mLOG(GB_MBC, GAME_ERROR, "Wrote to invalid MBC");
 23}
 24
 25static void _GBMBC1(struct GB*, uint16_t address, uint8_t value);
 26static void _GBMBC2(struct GB*, uint16_t address, uint8_t value);
 27static void _GBMBC3(struct GB*, uint16_t address, uint8_t value);
 28static void _GBMBC5(struct GB*, uint16_t address, uint8_t value);
 29static void _GBMBC6(struct GB*, uint16_t address, uint8_t value);
 30static void _GBMBC7(struct GB*, uint16_t address, uint8_t value);
 31static void _GBHuC3(struct GB*, uint16_t address, uint8_t value);
 32
 33void GBMBCSwitchBank(struct GBMemory* memory, int bank) {
 34	size_t bankStart = bank * GB_SIZE_CART_BANK0;
 35	if (bankStart + GB_SIZE_CART_BANK0 > memory->romSize) {
 36		mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
 37		bankStart &= (memory->romSize - 1);
 38		bank = bankStart / GB_SIZE_CART_BANK0;
 39	}
 40	memory->romBank = &memory->rom[bankStart];
 41	memory->currentBank = bank;
 42}
 43
 44void GBMBCSwitchSramBank(struct GB* gb, int bank) {
 45	size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM;
 46	GBResizeSram(gb, (bank + 1) * GB_SIZE_EXTERNAL_RAM);
 47	gb->memory.sramBank = &gb->memory.sram[bankStart];
 48	gb->memory.sramCurrentBank = bank;
 49}
 50
 51void GBMBCInit(struct GB* gb) {
 52	const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
 53	switch (cart->ramSize) {
 54	case 0:
 55		gb->sramSize = 0;
 56		break;
 57	case 1:
 58		gb->sramSize = 0x800;
 59		break;
 60	default:
 61	case 2:
 62		gb->sramSize = 0x2000;
 63		break;
 64	case 3:
 65		gb->sramSize = 0x8000;
 66		break;
 67	}
 68
 69	if (gb->memory.mbcType == GB_MBC_AUTODETECT) {
 70		const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
 71		switch (cart->type) {
 72		case 0:
 73		case 8:
 74		case 9:
 75			gb->memory.mbcType = GB_MBC_NONE;
 76			break;
 77		case 1:
 78		case 2:
 79		case 3:
 80			gb->memory.mbcType = GB_MBC1;
 81			break;
 82		case 5:
 83		case 6:
 84			gb->memory.mbcType = GB_MBC2;
 85			break;
 86		case 0x0F:
 87		case 0x10:
 88			gb->memory.mbcType = GB_MBC3_RTC;
 89			break;
 90		case 0x11:
 91		case 0x12:
 92		case 0x13:
 93			gb->memory.mbcType = GB_MBC3;
 94			break;
 95		default:
 96			mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
 97			// Fall through
 98		case 0x19:
 99		case 0x1A:
100		case 0x1B:
101			gb->memory.mbcType = GB_MBC5;
102			break;
103		case 0x1C:
104		case 0x1D:
105		case 0x1E:
106			gb->memory.mbcType = GB_MBC5_RUMBLE;
107			break;
108		case 0x20:
109			gb->memory.mbcType = GB_MBC6;
110			break;
111		case 0x22:
112			gb->memory.mbcType = GB_MBC7;
113			break;
114		case 0xFE:
115			gb->memory.mbcType = GB_HuC3;
116			break;
117		}
118	}
119	switch (gb->memory.mbcType) {
120	case GB_MBC_NONE:
121		gb->memory.mbc = _GBMBCNone;
122		break;
123	case GB_MBC1:
124		gb->memory.mbc = _GBMBC1;
125		break;
126	case GB_MBC2:
127		gb->memory.mbc = _GBMBC2;
128		gb->sramSize = 0x200;
129		break;
130	case GB_MBC3:
131		gb->memory.mbc = _GBMBC3;
132		default:
133		mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
134		// Fall through
135	case GB_MBC5:
136		gb->memory.mbc = _GBMBC5;
137		break;
138	case GB_MBC6:
139		mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6");
140		gb->memory.mbc = _GBMBC6;
141		break;
142	case GB_MBC7:
143		gb->memory.mbc = _GBMBC7;
144		break;
145	case GB_MMM01:
146		mLOG(GB_MBC, WARN, "unimplemented MBC: MMM01");
147		gb->memory.mbc = _GBMBC1;
148		break;
149	case GB_HuC1:
150		mLOG(GB_MBC, WARN, "unimplemented MBC: HuC-1");
151		gb->memory.mbc = _GBMBC1;
152		break;
153	case GB_HuC3:
154		gb->memory.mbc = _GBHuC3;
155		break;
156	case GB_MBC3_RTC:
157		memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
158		gb->memory.mbc = _GBMBC3;
159		break;
160	case GB_MBC5_RUMBLE:
161		gb->memory.mbc = _GBMBC5;
162		break;
163	}
164
165	GBResizeSram(gb, gb->sramSize);
166
167	if (gb->memory.mbcType == GB_MBC3_RTC) {
168		GBMBCRTCRead(gb);
169	}
170}
171
172static void _latchRtc(struct mRTCSource* rtc, uint8_t* rtcRegs, time_t* rtcLastLatch) {
173	time_t t;
174	if (rtc) {
175		if (rtc->sample) {
176			rtc->sample(rtc);
177		}
178		t = rtc->unixTime(rtc);
179	} else {
180		t = time(0);
181	}
182	time_t currentLatch = t;
183	t -= *rtcLastLatch;
184	*rtcLastLatch = currentLatch;
185
186	unsigned diff;
187	diff = rtcRegs[0] + t % 60;
188	rtcRegs[0] = diff % 60;
189	t = t / 60 + diff / 60;
190
191	diff = rtcRegs[1] + t % 60;
192	rtcRegs[1] = diff % 60;
193	t = t / 60 + diff / 60;
194
195	diff = rtcRegs[2] + t % 24;
196	rtcRegs[2] = diff % 24;
197	t = t / 24 + diff / 24;
198
199	diff = rtcRegs[3] + ((rtcRegs[4] & 1) << 8) + (t & 0x1FF);
200	rtcRegs[3] = diff;
201	rtcRegs[4] &= 0xFE;
202	rtcRegs[4] |= (diff >> 8) & 1;
203	if (diff & 0x200) {
204		rtcRegs[4] |= 0x80;
205	}
206}
207
208void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
209	struct GBMemory* memory = &gb->memory;
210	int bank = value & 0x1F;
211	switch (address >> 13) {
212	case 0x0:
213		switch (value) {
214		case 0:
215			memory->sramAccess = false;
216			break;
217		case 0xA:
218			memory->sramAccess = true;
219			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
220			break;
221		default:
222			// TODO
223			mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
224			break;
225		}
226		break;
227	case 0x1:
228		if (!bank) {
229			++bank;
230		}
231		GBMBCSwitchBank(memory, bank | (memory->currentBank & 0x60));
232		break;
233	case 0x2:
234		bank &= 3;
235		if (!memory->mbcState.mbc1.mode) {
236			GBMBCSwitchBank(memory, (bank << 5) | (memory->currentBank & 0x1F));
237		} else {
238			GBMBCSwitchSramBank(gb, bank);
239		}
240		break;
241	case 0x3:
242		memory->mbcState.mbc1.mode = value & 1;
243		if (memory->mbcState.mbc1.mode) {
244			GBMBCSwitchBank(memory, memory->currentBank & 0x1F);
245		} else {
246			GBMBCSwitchSramBank(gb, 0);
247		}
248		break;
249	default:
250		// TODO
251		mLOG(GB_MBC, STUB, "MBC1 unknown address: %04X:%02X", address, value);
252		break;
253	}
254}
255
256void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
257	struct GBMemory* memory = &gb->memory;
258	int bank = value & 0xF;
259	switch (address >> 13) {
260	case 0x0:
261		switch (value) {
262		case 0:
263			memory->sramAccess = false;
264			break;
265		case 0xA:
266			memory->sramAccess = true;
267			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
268			break;
269		default:
270			// TODO
271			mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
272			break;
273		}
274		break;
275	case 0x1:
276		if (!bank) {
277			++bank;
278		}
279		GBMBCSwitchBank(memory, bank);
280		break;
281	default:
282		// TODO
283		mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
284		break;
285	}}
286
287void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
288	struct GBMemory* memory = &gb->memory;
289	int bank = value & 0x7F;
290	switch (address >> 13) {
291	case 0x0:
292		switch (value) {
293		case 0:
294			memory->sramAccess = false;
295			break;
296		case 0xA:
297			memory->sramAccess = true;
298			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
299			break;
300		default:
301			// TODO
302			mLOG(GB_MBC, STUB, "MBC3 unknown value %02X", value);
303			break;
304		}
305		break;
306	case 0x1:
307		if (!bank) {
308			++bank;
309		}
310		GBMBCSwitchBank(memory, bank);
311		break;
312	case 0x2:
313		if (value < 4) {
314			GBMBCSwitchSramBank(gb, value);
315			memory->rtcAccess = false;
316		} else if (value >= 8 && value <= 0xC) {
317			memory->activeRtcReg = value - 8;
318			memory->rtcAccess = true;
319		}
320		break;
321	case 0x3:
322		if (memory->rtcLatched && value == 0) {
323			memory->rtcLatched = false;
324		} else if (!memory->rtcLatched && value == 1) {
325			_latchRtc(gb->memory.rtc, gb->memory.rtcRegs, &gb->memory.rtcLastLatch);
326			memory->rtcLatched = true;
327		}
328		break;
329	}
330}
331
332void _GBMBC5(struct GB* gb, uint16_t address, uint8_t value) {
333	struct GBMemory* memory = &gb->memory;
334	int bank;
335	switch (address >> 12) {
336	case 0x0:
337	case 0x1:
338		switch (value) {
339		case 0:
340			memory->sramAccess = false;
341			break;
342		case 0xA:
343			memory->sramAccess = true;
344			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
345			break;
346		default:
347			// TODO
348			mLOG(GB_MBC, STUB, "MBC5 unknown value %02X", value);
349			break;
350		}
351		break;
352	case 0x2:
353		bank = (memory->currentBank & 0x100) | value;
354		GBMBCSwitchBank(memory, bank);
355		break;
356	case 0x3:
357		bank = (memory->currentBank & 0xFF) | ((value & 1) << 8);
358		GBMBCSwitchBank(memory, bank);
359		break;
360	case 0x4:
361	case 0x5:
362		if (memory->mbcType == GB_MBC5_RUMBLE && memory->rumble) {
363			memory->rumble->setRumble(memory->rumble, (value >> 3) & 1);
364			value &= ~8;
365		}
366		GBMBCSwitchSramBank(gb, value & 0xF);
367		break;
368	default:
369		// TODO
370		mLOG(GB_MBC, STUB, "MBC5 unknown address: %04X:%02X", address, value);
371		break;
372	}
373}
374
375void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) {
376	// TODO
377	mLOG(GB_MBC, STUB, "MBC6 unimplemented");
378	UNUSED(gb);
379	UNUSED(address);
380	UNUSED(value);
381}
382
383void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
384	struct GBMemory* memory = &gb->memory;
385	int bank = value & 0x7F;
386	switch (address >> 13) {
387	case 0x1:
388		GBMBCSwitchBank(memory, bank);
389		break;
390	case 0x2:
391		if (value < 0x10) {
392			GBMBCSwitchSramBank(gb, value);
393		}
394		break;
395	default:
396		// TODO
397		mLOG(GB_MBC, STUB, "MBC7 unknown address: %04X:%02X", address, value);
398		break;
399	}
400}
401
402uint8_t GBMBC7Read(struct GBMemory* memory, uint16_t address) {
403	struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
404	switch (address & 0xF0) {
405	case 0x00:
406	case 0x10:
407	case 0x60:
408	case 0x70:
409		return 0;
410	case 0x20:
411		if (memory->rotation && memory->rotation->readTiltX) {
412			int32_t x = -memory->rotation->readTiltX(memory->rotation);
413			x >>= 21;
414			x += 2047;
415			return x;
416		}
417		return 0xFF;
418	case 0x30:
419		if (memory->rotation && memory->rotation->readTiltX) {
420			int32_t x = -memory->rotation->readTiltX(memory->rotation);
421			x >>= 21;
422			x += 2047;
423			return x >> 8;
424		}
425		return 7;
426	case 0x40:
427		if (memory->rotation && memory->rotation->readTiltY) {
428			int32_t y = -memory->rotation->readTiltY(memory->rotation);
429			y >>= 21;
430			y += 2047;
431			return y;
432		}
433		return 0xFF;
434	case 0x50:
435		if (memory->rotation && memory->rotation->readTiltY) {
436			int32_t y = -memory->rotation->readTiltY(memory->rotation);
437			y >>= 21;
438			y += 2047;
439			return y >> 8;
440		}
441		return 7;
442	case 0x80:
443		return (mbc7->sr >> 16) & 1;
444	default:
445		return 0xFF;
446	}
447}
448
449void GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) {
450	if ((address & 0xF0) != 0x80) {
451		return;
452	}
453	struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
454	GBMBC7Field old = memory->mbcState.mbc7.field;
455	mbc7->field = GBMBC7FieldClearIO(value);
456	if (!GBMBC7FieldIsCS(old) && GBMBC7FieldIsCS(value)) {
457		if (mbc7->state == GBMBC7_STATE_WRITE) {
458			if (mbc7->writable) {
459				memory->sramBank[mbc7->address * 2] = mbc7->sr >> 8;
460				memory->sramBank[mbc7->address * 2 + 1] = mbc7->sr;
461			}
462			mbc7->sr = 0x1FFFF;
463			mbc7->state = GBMBC7_STATE_NULL;
464		} else {
465			mbc7->state = GBMBC7_STATE_IDLE;
466		}
467	}
468	if (!GBMBC7FieldIsSK(old) && GBMBC7FieldIsSK(value)) {
469		if (mbc7->state > GBMBC7_STATE_IDLE && mbc7->state != GBMBC7_STATE_READ) {
470			mbc7->sr <<= 1;
471			mbc7->sr |= GBMBC7FieldGetIO(value);
472			++mbc7->srBits;
473		}
474		switch (mbc7->state) {
475		case GBMBC7_STATE_IDLE:
476			if (GBMBC7FieldIsIO(value)) {
477				mbc7->state = GBMBC7_STATE_READ_COMMAND;
478				mbc7->srBits = 0;
479				mbc7->sr = 0;
480			}
481			break;
482		case GBMBC7_STATE_READ_COMMAND:
483			if (mbc7->srBits == 2) {
484				mbc7->state = GBMBC7_STATE_READ_ADDRESS;
485				mbc7->srBits = 0;
486				mbc7->command = mbc7->sr;
487			}
488			break;
489		case GBMBC7_STATE_READ_ADDRESS:
490			if (mbc7->srBits == 8) {
491				mbc7->state = GBMBC7_STATE_COMMAND_0 + mbc7->command;
492				mbc7->srBits = 0;
493				mbc7->address = mbc7->sr;
494				if (mbc7->state == GBMBC7_STATE_COMMAND_0) {
495					switch (mbc7->address >> 6) {
496					case 0:
497						mbc7->writable = false;
498						mbc7->state = GBMBC7_STATE_NULL;
499						break;
500					case 3:
501						mbc7->writable = true;
502						mbc7->state = GBMBC7_STATE_NULL;
503						break;
504					}
505				}
506			}
507			break;
508		case GBMBC7_STATE_COMMAND_0:
509			if (mbc7->srBits == 16) {
510				switch (mbc7->address >> 6) {
511				case 0:
512					mbc7->writable = false;
513					mbc7->state = GBMBC7_STATE_NULL;
514					break;
515				case 1:
516					mbc7->state = GBMBC7_STATE_WRITE;
517					if (mbc7->writable) {
518						int i;
519						for (i = 0; i < 256; ++i) {
520							memory->sramBank[i * 2] = mbc7->sr >> 8;
521							memory->sramBank[i * 2 + 1] = mbc7->sr;
522						}
523					}
524					break;
525				case 2:
526					mbc7->state = GBMBC7_STATE_WRITE;
527					if (mbc7->writable) {
528						int i;
529						for (i = 0; i < 256; ++i) {
530							memory->sramBank[i * 2] = 0xFF;
531							memory->sramBank[i * 2 + 1] = 0xFF;
532						}
533					}
534					break;
535				case 3:
536					mbc7->writable = true;
537					mbc7->state = GBMBC7_STATE_NULL;
538					break;
539				}
540			}
541			break;
542		case GBMBC7_STATE_COMMAND_SR_WRITE:
543			if (mbc7->srBits == 16) {
544				mbc7->srBits = 0;
545				mbc7->state = GBMBC7_STATE_WRITE;
546			}
547			break;
548		case GBMBC7_STATE_COMMAND_SR_READ:
549			if (mbc7->srBits == 1) {
550				mbc7->sr = memory->sramBank[mbc7->address * 2] << 8;
551				mbc7->sr |= memory->sramBank[mbc7->address * 2 + 1];
552				mbc7->srBits = 0;
553				mbc7->state = GBMBC7_STATE_READ;
554			}
555			break;
556		case GBMBC7_STATE_COMMAND_SR_FILL:
557			if (mbc7->srBits == 16) {
558				mbc7->sr = 0xFFFF;
559				mbc7->srBits = 0;
560				mbc7->state = GBMBC7_STATE_WRITE;
561			}
562			break;
563		default:
564			break;
565		}
566	} else if (GBMBC7FieldIsSK(old) && !GBMBC7FieldIsSK(value)) {
567		if (mbc7->state == GBMBC7_STATE_READ) {
568			mbc7->sr <<= 1;
569			++mbc7->srBits;
570			if (mbc7->srBits == 16) {
571				mbc7->srBits = 0;
572				mbc7->state = GBMBC7_STATE_NULL;
573			}
574		}
575	}
576}
577
578void _GBHuC3(struct GB* gb, uint16_t address, uint8_t value) {
579	struct GBMemory* memory = &gb->memory;
580	int bank = value & 0x3F;
581	if (address & 0x1FFF) {
582		mLOG(GB_MBC, STUB, "HuC-3 unknown value %04X:%02X", address, value);
583	}
584
585	switch (address >> 13) {
586	case 0x0:
587		switch (value) {
588		case 0xA:
589			memory->sramAccess = true;
590			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
591			break;
592		default:
593			memory->sramAccess = false;
594			break;
595		}
596		break;
597	case 0x1:
598		GBMBCSwitchBank(memory, bank);
599		break;
600	case 0x2:
601		GBMBCSwitchSramBank(gb, bank);
602		break;
603	default:
604		// TODO
605		mLOG(GB_MBC, STUB, "HuC-3 unknown address: %04X:%02X", address, value);
606		break;
607	}
608}
609
610void GBMBCRTCRead(struct GB* gb) {
611	struct GBMBCRTCSaveBuffer rtcBuffer;
612	struct VFile* vf = gb->sramVf;
613	ssize_t end = vf->seek(vf, -sizeof(rtcBuffer), SEEK_END);
614	switch (end & 0x1FFF) {
615	case 0:
616		break;
617	case 0x1FFC:
618		vf->seek(vf, -sizeof(rtcBuffer) - 4, SEEK_END);
619		break;
620	default:
621		return;
622	}
623	vf->read(vf, &rtcBuffer, sizeof(rtcBuffer));
624
625	LOAD_32LE(gb->memory.rtcRegs[0], 0, &rtcBuffer.latchedSec);
626	LOAD_32LE(gb->memory.rtcRegs[1], 0, &rtcBuffer.latchedMin);
627	LOAD_32LE(gb->memory.rtcRegs[2], 0, &rtcBuffer.latchedHour);
628	LOAD_32LE(gb->memory.rtcRegs[3], 0, &rtcBuffer.latchedDays);
629	LOAD_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
630	LOAD_64LE(gb->memory.rtcLastLatch, 0, &rtcBuffer.unixTime);
631}
632
633void GBMBCRTCWrite(struct GB* gb) {
634	uint8_t rtcRegs[5];
635	memcpy(rtcRegs, gb->memory.rtcRegs, sizeof(rtcRegs));
636	time_t rtcLastLatch = gb->memory.rtcLastLatch;
637	_latchRtc(gb->memory.rtc, rtcRegs, &rtcLastLatch);
638
639	struct GBMBCRTCSaveBuffer rtcBuffer;
640	STORE_32LE(rtcRegs[0], 0, &rtcBuffer.sec);
641	STORE_32LE(rtcRegs[1], 0, &rtcBuffer.min);
642	STORE_32LE(rtcRegs[2], 0, &rtcBuffer.hour);
643	STORE_32LE(rtcRegs[3], 0, &rtcBuffer.days);
644	STORE_32LE(rtcRegs[4], 0, &rtcBuffer.daysHi);
645	STORE_32LE(gb->memory.rtcRegs[0], 0, &rtcBuffer.latchedSec);
646	STORE_32LE(gb->memory.rtcRegs[1], 0, &rtcBuffer.latchedMin);
647	STORE_32LE(gb->memory.rtcRegs[2], 0, &rtcBuffer.latchedHour);
648	STORE_32LE(gb->memory.rtcRegs[3], 0, &rtcBuffer.latchedDays);
649	STORE_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
650	STORE_64LE(rtcLastLatch, 0, &rtcBuffer.unixTime);
651
652	struct VFile* vf = gb->sramVf;
653	vf->seek(vf, gb->sramSize, SEEK_SET);
654	vf->write(vf, &rtcBuffer, sizeof(rtcBuffer));
655}