mirror of https://github.com/mgba-emu/mgba.git
DS Slot-1: Initial Slot-1 implementation
This commit is contained in:
parent
035998e3f0
commit
7389176033
|
@ -76,20 +76,20 @@ enum DSIORegisters {
|
||||||
// Game card
|
// Game card
|
||||||
DS_REG_AUXSPICNT = 0x1A0,
|
DS_REG_AUXSPICNT = 0x1A0,
|
||||||
DS_REG_AUXSPIDATA = 0x1A2,
|
DS_REG_AUXSPIDATA = 0x1A2,
|
||||||
DS_REG_SLOT1CNT_LO = 0x1A4,
|
DS_REG_ROMCNT_LO = 0x1A4,
|
||||||
DS_REG_SLOT1CNT_HI = 0x1A6,
|
DS_REG_ROMCNT_HI = 0x1A6,
|
||||||
DS_REG_SLOT1CMD_0 = 0x1A8,
|
DS_REG_ROMCMD_0 = 0x1A8,
|
||||||
DS_REG_SLOT1CMD_1 = 0x1A9,
|
DS_REG_ROMCMD_1 = 0x1A9,
|
||||||
DS_REG_SLOT1CMD_2 = 0x1AA,
|
DS_REG_ROMCMD_2 = 0x1AA,
|
||||||
DS_REG_SLOT1CMD_3 = 0x1AB,
|
DS_REG_ROMCMD_3 = 0x1AB,
|
||||||
DS_REG_SLOT1CMD_4 = 0x1AC,
|
DS_REG_ROMCMD_4 = 0x1AC,
|
||||||
DS_REG_SLOT1CMD_5 = 0x1AD,
|
DS_REG_ROMCMD_5 = 0x1AD,
|
||||||
DS_REG_SLOT1CMD_6 = 0x1AE,
|
DS_REG_ROMCMD_6 = 0x1AE,
|
||||||
DS_REG_SLOT1CMD_7 = 0x1AF,
|
DS_REG_ROMCMD_7 = 0x1AF,
|
||||||
DS_REG_SLOT1DATA_0 = 0x100010,
|
DS_REG_ROMDATA_0 = 0x100010,
|
||||||
DS_REG_SLOT1DATA_1 = 0x100011,
|
DS_REG_ROMDATA_1 = 0x100011,
|
||||||
DS_REG_SLOT1DATA_2 = 0x100012,
|
DS_REG_ROMDATA_2 = 0x100012,
|
||||||
DS_REG_SLOT1DATA_3 = 0x100013,
|
DS_REG_ROMDATA_3 = 0x100013,
|
||||||
|
|
||||||
// Interrupts
|
// Interrupts
|
||||||
DS_REG_IME = 0x208,
|
DS_REG_IME = 0x208,
|
||||||
|
|
|
@ -15,6 +15,7 @@ CXX_GUARD_START
|
||||||
#include <mgba/internal/arm/arm.h>
|
#include <mgba/internal/arm/arm.h>
|
||||||
#include <mgba/internal/ds/dma.h>
|
#include <mgba/internal/ds/dma.h>
|
||||||
#include <mgba/internal/ds/io.h>
|
#include <mgba/internal/ds/io.h>
|
||||||
|
#include <mgba/internal/ds/slot1.h>
|
||||||
|
|
||||||
enum DSMemoryRegion {
|
enum DSMemoryRegion {
|
||||||
DS7_REGION_BIOS = 0x0,
|
DS7_REGION_BIOS = 0x0,
|
||||||
|
@ -84,6 +85,7 @@ struct DSMemory {
|
||||||
uint32_t* rom;
|
uint32_t* rom;
|
||||||
uint16_t io7[DS7_REG_MAX >> 1];
|
uint16_t io7[DS7_REG_MAX >> 1];
|
||||||
uint16_t io9[DS9_REG_MAX >> 1];
|
uint16_t io9[DS9_REG_MAX >> 1];
|
||||||
|
struct DSSlot1 slot1;
|
||||||
|
|
||||||
uint16_t vramMirror[9][0x40];
|
uint16_t vramMirror[9][0x40];
|
||||||
uint16_t vramMode[9][8];
|
uint16_t vramMode[9][8];
|
||||||
|
@ -96,6 +98,9 @@ struct DSMemory {
|
||||||
uint32_t dtcmBase;
|
uint32_t dtcmBase;
|
||||||
uint32_t dtcmSize;
|
uint32_t dtcmSize;
|
||||||
uint32_t itcmSize;
|
uint32_t itcmSize;
|
||||||
|
|
||||||
|
bool slot1Owner;
|
||||||
|
bool slot2Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DSCoreMemory {
|
struct DSCoreMemory {
|
||||||
|
@ -114,6 +119,8 @@ struct DSCoreMemory {
|
||||||
struct GBADMA dma[4];
|
struct GBADMA dma[4];
|
||||||
struct mTimingEvent dmaEvent;
|
struct mTimingEvent dmaEvent;
|
||||||
int activeDMA;
|
int activeDMA;
|
||||||
|
bool slot1Access;
|
||||||
|
bool slot2Access;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DS;
|
struct DS;
|
||||||
|
@ -149,5 +156,6 @@ uint32_t DS9StoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum
|
||||||
int* cycleCounter);
|
int* cycleCounter);
|
||||||
|
|
||||||
void DSConfigureWRAM(struct DSMemory*, uint8_t config);
|
void DSConfigureWRAM(struct DSMemory*, uint8_t config);
|
||||||
|
void DSConfigureExternalMemory(struct DS*, uint16_t config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#ifndef DS_SLOT1_H
|
||||||
|
#define DS_SLOT1_H
|
||||||
|
|
||||||
|
#include <mgba-util/common.h>
|
||||||
|
|
||||||
|
CXX_GUARD_START
|
||||||
|
|
||||||
|
#include <mgba/core/log.h>
|
||||||
|
|
||||||
|
mLOG_DECLARE_CATEGORY(DS_SLOT1);
|
||||||
|
|
||||||
|
DECL_BITFIELD(DSSlot1AUXSPICNT, uint16_t);
|
||||||
|
|
||||||
|
DECL_BITFIELD(DSSlot1ROMCNT, uint32_t);
|
||||||
|
DECL_BIT(DSSlot1ROMCNT, WordReady, 23);
|
||||||
|
DECL_BITS(DSSlot1ROMCNT, BlockSize, 24, 3);
|
||||||
|
DECL_BIT(DSSlot1ROMCNT, BlockBusy, 31);
|
||||||
|
|
||||||
|
struct DSSlot1 {
|
||||||
|
uint8_t command[8];
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t transferSize;
|
||||||
|
uint32_t transferRemaining;
|
||||||
|
uint8_t readBuffer[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DS;
|
||||||
|
DSSlot1AUXSPICNT DSSlot1Configure(struct DS* ds, DSSlot1AUXSPICNT config);
|
||||||
|
DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control);
|
||||||
|
uint32_t DSSlot1Read(struct DS* ds);
|
||||||
|
|
||||||
|
CXX_GUARD_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -279,6 +279,7 @@ void DS7Reset(struct ARMCore* cpu) {
|
||||||
struct DSCartridge* header = ds->romVf->map(ds->romVf, sizeof(*header), MAP_READ);
|
struct DSCartridge* header = ds->romVf->map(ds->romVf, sizeof(*header), MAP_READ);
|
||||||
if (header) {
|
if (header) {
|
||||||
memcpy(&ds->memory.ram[0x3FFE00 >> 2], header, 0x170);
|
memcpy(&ds->memory.ram[0x3FFE00 >> 2], header, 0x170);
|
||||||
|
DS7IOWrite32(ds, DS_REG_ROMCNT_LO, header->busTiming | 0x2700000);
|
||||||
// TODO: Error check
|
// TODO: Error check
|
||||||
ds->romVf->seek(ds->romVf, header->arm7Offset, SEEK_SET);
|
ds->romVf->seek(ds->romVf, header->arm7Offset, SEEK_SET);
|
||||||
uint32_t base = header->arm7Base - DS_BASE_RAM;
|
uint32_t base = header->arm7Base - DS_BASE_RAM;
|
||||||
|
|
61
src/ds/io.c
61
src/ds/io.c
|
@ -8,6 +8,7 @@
|
||||||
#include <mgba/core/interface.h>
|
#include <mgba/core/interface.h>
|
||||||
#include <mgba/internal/ds/ds.h>
|
#include <mgba/internal/ds/ds.h>
|
||||||
#include <mgba/internal/ds/ipc.h>
|
#include <mgba/internal/ds/ipc.h>
|
||||||
|
#include <mgba/internal/ds/slot1.h>
|
||||||
#include <mgba/internal/ds/spi.h>
|
#include <mgba/internal/ds/spi.h>
|
||||||
|
|
||||||
mLOG_DEFINE_CATEGORY(DS_IO, "DS I/O");
|
mLOG_DEFINE_CATEGORY(DS_IO, "DS I/O");
|
||||||
|
@ -101,9 +102,38 @@ static uint32_t DSIOWrite(struct DSCommon* dscore, uint32_t address, uint16_t va
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Cart bus
|
// Cart bus
|
||||||
case DS_REG_SLOT1CNT_LO:
|
case DS_REG_AUXSPICNT:
|
||||||
mLOG(DS_IO, STUB, "ROM control not implemented");
|
if (dscore->memory.slot1Access) {
|
||||||
value &= 0x7FFF;
|
value = DSSlot1Configure(dscore->p, value);
|
||||||
|
dscore->ipc->memory.io[address >> 1] = value;
|
||||||
|
} else {
|
||||||
|
mLOG(DS_IO, GAME_ERROR, "Invalid cart access");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DS_REG_ROMCNT_HI:
|
||||||
|
if (dscore->memory.slot1Access) {
|
||||||
|
DSSlot1ROMCNT cnt = value << 16;
|
||||||
|
cnt |= dscore->memory.io[(address - 2) >> 1];
|
||||||
|
cnt = DSSlot1Control(dscore->p, cnt);
|
||||||
|
value = cnt >> 16;
|
||||||
|
dscore->ipc->memory.io[address >> 1] = value;
|
||||||
|
} else {
|
||||||
|
mLOG(DS_IO, GAME_ERROR, "Invalid cart access");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DS_REG_ROMCNT_LO:
|
||||||
|
case DS_REG_ROMCMD_0:
|
||||||
|
case DS_REG_ROMCMD_2:
|
||||||
|
case DS_REG_ROMCMD_4:
|
||||||
|
case DS_REG_ROMCMD_6:
|
||||||
|
if (dscore->memory.slot1Access) {
|
||||||
|
dscore->ipc->memory.io[address >> 1] = value;
|
||||||
|
} else {
|
||||||
|
mLOG(DS_IO, GAME_ERROR, "Invalid cart access");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Interrupts
|
// Interrupts
|
||||||
|
@ -313,6 +343,8 @@ uint16_t DS7IORead(struct DS* ds, uint32_t address) {
|
||||||
case DS7_REG_SPIDATA:
|
case DS7_REG_SPIDATA:
|
||||||
case DS_REG_IPCSYNC:
|
case DS_REG_IPCSYNC:
|
||||||
case DS_REG_IPCFIFOCNT:
|
case DS_REG_IPCFIFOCNT:
|
||||||
|
case DS_REG_ROMCNT_LO:
|
||||||
|
case DS_REG_ROMCNT_HI:
|
||||||
case DS_REG_IME:
|
case DS_REG_IME:
|
||||||
case 0x20A:
|
case 0x20A:
|
||||||
case DS_REG_IE_LO:
|
case DS_REG_IE_LO:
|
||||||
|
@ -334,6 +366,13 @@ uint32_t DS7IORead32(struct DS* ds, uint32_t address) {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case DS_REG_IPCFIFORECV_LO:
|
case DS_REG_IPCFIFORECV_LO:
|
||||||
return DSIPCReadFIFO(&ds->ds7);
|
return DSIPCReadFIFO(&ds->ds7);
|
||||||
|
case DS_REG_ROMDATA_0:
|
||||||
|
if (ds->ds7.memory.slot1Access) {
|
||||||
|
return DSSlot1Read(ds);
|
||||||
|
} else {
|
||||||
|
mLOG(DS_IO, GAME_ERROR, "Invalid cart access");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return DS7IORead(ds, address & 0x00FFFFFC) | (DS7IORead(ds, (address & 0x00FFFFFC) | 2) << 16);
|
return DS7IORead(ds, address & 0x00FFFFFC) | (DS7IORead(ds, (address & 0x00FFFFFC) | 2) << 16);
|
||||||
}
|
}
|
||||||
|
@ -343,7 +382,7 @@ void DS9IOInit(struct DS* ds) {
|
||||||
memset(ds->memory.io9, 0, sizeof(ds->memory.io9));
|
memset(ds->memory.io9, 0, sizeof(ds->memory.io9));
|
||||||
ds->memory.io9[DS_REG_IPCFIFOCNT >> 1] = 0x0101;
|
ds->memory.io9[DS_REG_IPCFIFOCNT >> 1] = 0x0101;
|
||||||
ds->memory.io9[DS_REG_POSTFLG >> 1] = 0x0001;
|
ds->memory.io9[DS_REG_POSTFLG >> 1] = 0x0001;
|
||||||
ds->memory.io9[DS9_REG_VRAMCNT_G >> 1] = 0x0300;
|
DS9IOWrite(ds, DS9_REG_VRAMCNT_G, 0x0300);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
|
void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
|
||||||
|
@ -367,6 +406,11 @@ void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
|
||||||
DSVideoConfigureVRAM(&ds->memory, 8, value >> 8);
|
DSVideoConfigureVRAM(&ds->memory, 8, value >> 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DS9_REG_EXMEMCNT:
|
||||||
|
value &= 0xE8FF;
|
||||||
|
DSConfigureExternalMemory(ds, value);
|
||||||
|
break;
|
||||||
|
|
||||||
// Math
|
// Math
|
||||||
case DS9_REG_DIVCNT:
|
case DS9_REG_DIVCNT:
|
||||||
value = _scheduleDiv(ds, value);
|
value = _scheduleDiv(ds, value);
|
||||||
|
@ -482,6 +526,8 @@ uint16_t DS9IORead(struct DS* ds, uint32_t address) {
|
||||||
case DS_REG_TM3CNT_HI:
|
case DS_REG_TM3CNT_HI:
|
||||||
case DS_REG_IPCSYNC:
|
case DS_REG_IPCSYNC:
|
||||||
case DS_REG_IPCFIFOCNT:
|
case DS_REG_IPCFIFOCNT:
|
||||||
|
case DS_REG_ROMCNT_LO:
|
||||||
|
case DS_REG_ROMCNT_HI:
|
||||||
case DS_REG_IME:
|
case DS_REG_IME:
|
||||||
case 0x20A:
|
case 0x20A:
|
||||||
case DS_REG_IE_LO:
|
case DS_REG_IE_LO:
|
||||||
|
@ -527,6 +573,13 @@ uint32_t DS9IORead32(struct DS* ds, uint32_t address) {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case DS_REG_IPCFIFORECV_LO:
|
case DS_REG_IPCFIFORECV_LO:
|
||||||
return DSIPCReadFIFO(&ds->ds9);
|
return DSIPCReadFIFO(&ds->ds9);
|
||||||
|
case DS_REG_ROMDATA_0:
|
||||||
|
if (ds->ds9.memory.slot1Access) {
|
||||||
|
return DSSlot1Read(ds);
|
||||||
|
} else {
|
||||||
|
mLOG(DS_IO, GAME_ERROR, "Invalid cart access");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return DS9IORead(ds, address & 0x00FFFFFC) | (DS9IORead(ds, (address & 0x00FFFFFC) | 2) << 16);
|
return DS9IORead(ds, address & 0x00FFFFFC) | (DS9IORead(ds, (address & 0x00FFFFFC) | 2) << 16);
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,11 @@ void DSMemoryReset(struct DS* ds) {
|
||||||
ds->memory.wramSize9 = 0;
|
ds->memory.wramSize9 = 0;
|
||||||
ds->memory.wramBase9 = NULL;
|
ds->memory.wramBase9 = NULL;
|
||||||
|
|
||||||
|
ds->memory.slot1Owner = true;
|
||||||
|
ds->memory.slot2Owner = true;
|
||||||
|
ds->ds7.memory.slot1Access = true;
|
||||||
|
ds->ds9.memory.slot1Access = false;
|
||||||
|
|
||||||
DSVideoConfigureVRAM(&ds->memory, 0, 0);
|
DSVideoConfigureVRAM(&ds->memory, 0, 0);
|
||||||
DSVideoConfigureVRAM(&ds->memory, 1, 0);
|
DSVideoConfigureVRAM(&ds->memory, 1, 0);
|
||||||
DSVideoConfigureVRAM(&ds->memory, 2, 0);
|
DSVideoConfigureVRAM(&ds->memory, 2, 0);
|
||||||
|
@ -1261,6 +1266,16 @@ void DSConfigureWRAM(struct DSMemory* memory, uint8_t config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DSConfigureExternalMemory(struct DS* ds, uint16_t config) {
|
||||||
|
// TODO: GBA params
|
||||||
|
ds->memory.slot1Owner = config & 0x0800;
|
||||||
|
ds->memory.slot2Owner = config & 0x0080;
|
||||||
|
ds->memory.io7[DS7_REG_EXMEMSTAT >> 1] = config;
|
||||||
|
|
||||||
|
ds->ds7.memory.slot1Access = ds->memory.slot1Owner;
|
||||||
|
ds->ds9.memory.slot1Access = !ds->memory.slot1Owner;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned _selectVRAM(struct DSMemory* memory, uint32_t offset) {
|
static unsigned _selectVRAM(struct DSMemory* memory, uint32_t offset) {
|
||||||
unsigned mask = 0;
|
unsigned mask = 0;
|
||||||
offset &= 0x3FF;
|
offset &= 0x3FF;
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#include <mgba/internal/ds/slot1.h>
|
||||||
|
|
||||||
|
#include <mgba/internal/arm/macros.h>
|
||||||
|
#include <mgba/internal/ds/ds.h>
|
||||||
|
#include <mgba-util/vfs.h>
|
||||||
|
|
||||||
|
mLOG_DEFINE_CATEGORY(DS_SLOT1, "DS Slot-1");
|
||||||
|
|
||||||
|
static void DSSlot1StepTransfer(struct DS* ds) {
|
||||||
|
DSSlot1ROMCNT romcnt;
|
||||||
|
LOAD_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io7);
|
||||||
|
if (ds->memory.slot1.transferRemaining) {
|
||||||
|
ds->romVf->read(ds->romVf, ds->memory.slot1.readBuffer, 4);
|
||||||
|
// TODO: Error check
|
||||||
|
ds->memory.slot1.address += 4;
|
||||||
|
ds->memory.slot1.transferRemaining -= 4;
|
||||||
|
romcnt = DSSlot1ROMCNTFillWordReady(romcnt);
|
||||||
|
} else {
|
||||||
|
memset(ds->memory.slot1.readBuffer, 0, 4);
|
||||||
|
romcnt = DSSlot1ROMCNTClearWordReady(romcnt);
|
||||||
|
// TODO: IRQ
|
||||||
|
romcnt = DSSlot1ROMCNTClearBlockBusy(romcnt);
|
||||||
|
}
|
||||||
|
STORE_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io7);
|
||||||
|
STORE_32(romcnt, DS_REG_ROMCNT_LO, ds->memory.io9);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DSSlot1StartTransfer(struct DS* ds) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < 8; i += 2) {
|
||||||
|
uint16_t bytes;
|
||||||
|
LOAD_16(bytes, DS_REG_ROMCMD_0 + i, ds->memory.io7);
|
||||||
|
ds->memory.slot1.command[i] = bytes & 0xFF;
|
||||||
|
ds->memory.slot1.command[i + 1] = bytes >> 8;
|
||||||
|
}
|
||||||
|
switch (ds->memory.slot1.command[0]) {
|
||||||
|
case 0xB7:
|
||||||
|
ds->memory.slot1.address = ds->memory.slot1.command[1] << 24;
|
||||||
|
ds->memory.slot1.address |= ds->memory.slot1.command[2] << 16;
|
||||||
|
ds->memory.slot1.address |= ds->memory.slot1.command[3] << 8;
|
||||||
|
ds->memory.slot1.address |= ds->memory.slot1.command[4];
|
||||||
|
if (ds->romVf) {
|
||||||
|
ds->romVf->seek(ds->romVf, ds->memory.slot1.address, SEEK_SET);
|
||||||
|
}
|
||||||
|
ds->memory.slot1.transferRemaining = ds->memory.slot1.transferSize;
|
||||||
|
DSSlot1StepTransfer(ds);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mLOG(DS_SLOT1, STUB, "Unimplemented card command: %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
|
ds->memory.slot1.command[0], ds->memory.slot1.command[1],
|
||||||
|
ds->memory.slot1.command[2], ds->memory.slot1.command[3],
|
||||||
|
ds->memory.slot1.command[4], ds->memory.slot1.command[5],
|
||||||
|
ds->memory.slot1.command[6], ds->memory.slot1.command[7]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DSSlot1AUXSPICNT DSSlot1Configure(struct DS* ds, DSSlot1AUXSPICNT config) {
|
||||||
|
mLOG(DS_SLOT1, STUB, "Unimplemented SPI AUX config: %04X", config);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control) {
|
||||||
|
ds->memory.slot1.transferSize = DSSlot1ROMCNTGetBlockSize(control);
|
||||||
|
if (ds->memory.slot1.transferSize != 0 && ds->memory.slot1.transferSize != 7) {
|
||||||
|
ds->memory.slot1.transferSize = 0x100 << ds->memory.slot1.transferSize;
|
||||||
|
}
|
||||||
|
if (DSSlot1ROMCNTIsBlockBusy(control)) {
|
||||||
|
DSSlot1StartTransfer(ds);
|
||||||
|
// TODO timing
|
||||||
|
control = DSSlot1ROMCNTFillWordReady(control);
|
||||||
|
}
|
||||||
|
return control;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DSSlot1Read(struct DS* ds) {
|
||||||
|
uint32_t result;
|
||||||
|
LOAD_32(result, 0, ds->memory.slot1.readBuffer);
|
||||||
|
DSSlot1StepTransfer(ds);
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue