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}