all repos — mgba @ 495ca50dc00b580f37d576d084ace2a05ec2812d

mGBA Game Boy Advance Emulator

src/ds/slot1.c (view raw)

 1/* Copyright (c) 2013-2017 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/ds/slot1.h>
 7
 8#include <mgba/internal/arm/macros.h>
 9#include <mgba/internal/ds/ds.h>
10#include <mgba-util/vfs.h>
11
12mLOG_DEFINE_CATEGORY(DS_SLOT1, "DS Slot-1");
13
14static void DSSlot1StepTransfer(struct DS* ds) {
15	DSSlot1ROMCNT romcnt;
16	LOAD_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io7);
17	if (ds->memory.slot1.transferRemaining) {
18		ds->romVf->read(ds->romVf, ds->memory.slot1.readBuffer, 4);
19		// TODO: Error check
20		ds->memory.slot1.address += 4;
21		ds->memory.slot1.transferRemaining -= 4;
22		romcnt = DSSlot1ROMCNTFillWordReady(romcnt);
23	} else {
24		memset(ds->memory.slot1.readBuffer, 0, 4);
25		romcnt = DSSlot1ROMCNTClearWordReady(romcnt);
26		// TODO: IRQ
27		romcnt = DSSlot1ROMCNTClearBlockBusy(romcnt);
28	}
29	STORE_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io7);
30	STORE_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io9);
31}
32
33static void DSSlot1StartTransfer(struct DS* ds) {
34	size_t i;
35	for (i = 0; i < 8; i += 2) {
36		uint16_t bytes;
37		LOAD_16(bytes, DS_REG_ROMCMD_0 + i, ds->memory.io7);
38		ds->memory.slot1.command[i] = bytes & 0xFF;
39		ds->memory.slot1.command[i + 1] = bytes >> 8;
40	}
41	switch (ds->memory.slot1.command[0]) {
42	case 0xB7:
43		ds->memory.slot1.address = ds->memory.slot1.command[1] << 24;
44		ds->memory.slot1.address |= ds->memory.slot1.command[2] << 16;
45		ds->memory.slot1.address |= ds->memory.slot1.command[3] << 8;
46		ds->memory.slot1.address |= ds->memory.slot1.command[4];
47		if (ds->romVf) {
48			ds->romVf->seek(ds->romVf, ds->memory.slot1.address, SEEK_SET);
49		}
50		ds->memory.slot1.transferRemaining = ds->memory.slot1.transferSize;
51		DSSlot1StepTransfer(ds);
52		break;
53	default:
54		mLOG(DS_SLOT1, STUB, "Unimplemented card command: %02X%02X%02X%02X%02X%02X%02X%02X",
55		     ds->memory.slot1.command[0], ds->memory.slot1.command[1],
56		     ds->memory.slot1.command[2], ds->memory.slot1.command[3],
57		     ds->memory.slot1.command[4], ds->memory.slot1.command[5],
58		     ds->memory.slot1.command[6], ds->memory.slot1.command[7]);
59		break;
60	}
61}
62
63DSSlot1AUXSPICNT DSSlot1Configure(struct DS* ds, DSSlot1AUXSPICNT config) {
64	mLOG(DS_SLOT1, STUB, "Unimplemented SPI AUX config: %04X", config);
65	return config;
66}
67
68DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control) {
69	ds->memory.slot1.transferSize = DSSlot1ROMCNTGetBlockSize(control);
70	if (ds->memory.slot1.transferSize != 0 && ds->memory.slot1.transferSize != 7) {
71		ds->memory.slot1.transferSize = 0x100 << ds->memory.slot1.transferSize;
72	}
73	if (DSSlot1ROMCNTIsBlockBusy(control)) {
74		DSSlot1StartTransfer(ds);
75		// TODO timing
76		control = DSSlot1ROMCNTFillWordReady(control);
77	}
78	return control;
79}
80
81uint32_t DSSlot1Read(struct DS* ds) {
82	uint32_t result;
83	LOAD_32(result, 0, ds->memory.slot1.readBuffer);
84	DSSlot1StepTransfer(ds);
85	return result;
86}