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 case 0xB8:
54 memcpy(ds->memory.slot1.readBuffer, DS_CHIP_ID, 4);
55 ds->memory.slot1.transferRemaining = 0;
56 break;
57 default:
58 mLOG(DS_SLOT1, STUB, "Unimplemented card command: %02X%02X%02X%02X%02X%02X%02X%02X",
59 ds->memory.slot1.command[0], ds->memory.slot1.command[1],
60 ds->memory.slot1.command[2], ds->memory.slot1.command[3],
61 ds->memory.slot1.command[4], ds->memory.slot1.command[5],
62 ds->memory.slot1.command[6], ds->memory.slot1.command[7]);
63 break;
64 }
65}
66
67DSSlot1AUXSPICNT DSSlot1Configure(struct DS* ds, DSSlot1AUXSPICNT config) {
68 mLOG(DS_SLOT1, STUB, "Unimplemented SPI AUX config: %04X", config);
69 return config;
70}
71
72DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control) {
73 ds->memory.slot1.transferSize = DSSlot1ROMCNTGetBlockSize(control);
74 if (ds->memory.slot1.transferSize != 0 && ds->memory.slot1.transferSize != 7) {
75 ds->memory.slot1.transferSize = 0x100 << ds->memory.slot1.transferSize;
76 }
77 if (DSSlot1ROMCNTIsBlockBusy(control)) {
78 DSSlot1StartTransfer(ds);
79 // TODO timing
80 control = DSSlot1ROMCNTFillWordReady(control);
81 }
82 return control;
83}
84
85uint32_t DSSlot1Read(struct DS* ds) {
86 uint32_t result;
87 LOAD_32(result, 0, ds->memory.slot1.readBuffer);
88 DSSlot1StepTransfer(ds);
89 return result;
90}