From 2199c147aedecd0ce97e03afba386575a1da96e2 Mon Sep 17 00:00:00 2001 From: lifehackerhansol Date: Fri, 1 Nov 2024 02:28:48 -0700 Subject: [PATCH] TopToyLauncher: Add support for dual SD/SDHC support for DSTT Works by reinitializing the SD card to retrieve the HCS bit --- arm9/Makefile | 2 +- arm9/source/launcher/TopToyLauncher.cpp | 14 +- arm9/source/launcher/ttio/libtwl_card.c | 82 ++++++++ arm9/source/launcher/ttio/libtwl_card.h | 134 ++++++++++++ arm9/source/launcher/ttio/scdssdhc.c | 262 ++++++++++++++++++++++++ arm9/source/launcher/ttio/scdssdhc.h | 168 +++++++++++++++ arm9/source/launcher/ttio/waitByLoop.s | 18 ++ arm9_ak2/Makefile | 2 +- arm9_dsi/Makefile | 2 +- arm9_tt/Makefile | 6 +- 10 files changed, 682 insertions(+), 8 deletions(-) create mode 100644 arm9/source/launcher/ttio/libtwl_card.c create mode 100644 arm9/source/launcher/ttio/libtwl_card.h create mode 100644 arm9/source/launcher/ttio/scdssdhc.c create mode 100644 arm9/source/launcher/ttio/scdssdhc.h create mode 100644 arm9/source/launcher/ttio/waitByLoop.s diff --git a/arm9/Makefile b/arm9/Makefile index 494b496..027add4 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -32,7 +32,7 @@ CFLAGS := -g -Wall -O3\ CFLAGS += -D_NO_BOOTSTUB_ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -ASFLAGS := -g $(ARCH) +ASFLAGS := -g $(ARCH) $(INCLUDE) LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #--------------------------------------------------------------------------------- diff --git a/arm9/source/launcher/TopToyLauncher.cpp b/arm9/source/launcher/TopToyLauncher.cpp index 54d1d0a..3871971 100644 --- a/arm9/source/launcher/TopToyLauncher.cpp +++ b/arm9/source/launcher/TopToyLauncher.cpp @@ -22,6 +22,11 @@ #include "TopToyLauncher.h" #include "libfat_ext/fat_ext.h" +#ifdef __TTLAUNCHER_DSTT__ +#include "ttio/scdssdhc.h" +extern u32 SCDS_isSDHC; +#endif + static void resetAndLoop() { DC_FlushAll(); DC_InvalidateAll(); @@ -213,8 +218,13 @@ bool TopToyLauncher::launchRom(std::string romPath, std::string savePath, u32 fl // ttpatch checks this for some reason *((vu32*)0x02FFFC20) = 0x5555AAAA; - // set SD/SDHC flag to SDHC, right now our DLDI only does SDHC - *((vu32*)0x02FFFC24) = ~0; +#ifdef __TTLAUNCHER_DSTT__ + // set SD/SDHC flag + // Needs a SDIO reinitialization to retrieve HCS bit + if (!SCDS_SDInitialize()) return false; + + *((vu32*)0x02FFFC24) = SCDS_isSDHC ? ~0 : 0; +#endif // this int seems to be a flag to reinitialize the SD card in ttpatch // if this is *not* -1, ttpatch sends an SDIO CMD12 (STOP_TRANSMISSION) diff --git a/arm9/source/launcher/ttio/libtwl_card.c b/arm9/source/launcher/ttio/libtwl_card.c new file mode 100644 index 0000000..2945aa3 --- /dev/null +++ b/arm9/source/launcher/ttio/libtwl_card.c @@ -0,0 +1,82 @@ +// clang-format off + +/* + This file is a part of libtwl (card.c) + + Copyright (C) 2023 Gericom + + SPDX-License-Identifier: Zlib +*/ + +#include +#include "libtwl_card.h" + +void card_romCpuRead(u32* dst, u32 words) +{ + u32* target = dst + words; + do + { + // Read data if available + if (card_romIsDataReady()) + { + u32 data = card_romGetData(); + if (dst < target) + *dst++ = data; + } + } while (card_romIsBusy()); +} + +void card_romCpuReadUnaligned(u8* dst, u32 words) +{ + u8* target = dst + (words << 2); + do + { + // Read data if available + if (card_romIsDataReady()) + { + u32 data = card_romGetData(); + if (dst < target) + { + *dst++ = data & 0xFF; + *dst++ = (data >> 8) & 0xFF; + *dst++ = (data >> 16) & 0xFF; + *dst++ = (data >> 24) & 0xFF; + } + } + } while (card_romIsBusy()); +} + +void card_romCpuWrite(const u32* src, u32 words) +{ + u32 data = 0; + const u32* target = src + words; + do + { + // Write data if ready + if (card_romIsDataReady()) + { + if (src < target) + data = *src++; + card_romSetData(data); + } + } while (card_romIsBusy()); +} + +void card_romCpuWriteUnaligned(const u8* src, u32 words) +{ + u32 data = 0; + const u8* target = src + (words << 2); + do + { + // Write data if ready + if (card_romIsDataReady()) + { + if (src < target) + { + data = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); + src += 4; + } + card_romSetData(data); + } + } while (card_romIsBusy()); +} diff --git a/arm9/source/launcher/ttio/libtwl_card.h b/arm9/source/launcher/ttio/libtwl_card.h new file mode 100644 index 0000000..cf9ca69 --- /dev/null +++ b/arm9/source/launcher/ttio/libtwl_card.h @@ -0,0 +1,134 @@ +// clang-format off + +/* + This file is a part of libtwl (card.h) + + Copyright (C) 2023 Gericom + + SPDX-License-Identifier: Zlib +*/ + +#pragma once + +#define REG_MCCNT0 (*(vu16*)0x040001A0) +#define REG_MCD0 (*(vu16*)0x040001A2) +#define REG_MCCNT1 (*(vu32*)0x040001A4) +#define REG_MCCMD0 (*(vu32*)0x040001A8) +#define REG_MCCMD1 (*(vu32*)0x040001AC) +#define REG_MCSCR0 (*(vu32*)0x040001B0) +#define REG_MCSCR1 (*(vu32*)0x040001B4) +#define REG_MCSCR2 (*(vu32*)0x040001B8) +#define REG_MCD1 (*(vu32*)0x04100010) + +// REG_MCCNT0 + +#define MCCNT0_SPI_RATE_4_19_MHZ 0 +#define MCCNT0_SPI_RATE_2_09_MHZ 1 +#define MCCNT0_SPI_RATE_1_05_MHZ 2 +#define MCCNT0_SPI_RATE_524_KHZ 3 + +#define MCCNT0_SPI_HOLD_CS (1 << 6) +#define MCCNT0_SPI_BUSY (1 << 7) + +#define MCCNT0_MODE_MASK (1 << 13) +#define MCCNT0_MODE_ROM (0 << 13) +#define MCCNT0_MODE_SPI (1 << 13) + +#define MCCNT0_ROM_XFER_IRQ (1 << 14) +#define MCCNT0_ENABLE (1 << 15) + +// REG_MCCNT1 + +#define MCCNT1_LATENCY1_SHIFT 0 +#define MCCNT1_LATENCY1_MASK 0x1FFF +#define MCCNT1_LATENCY1(x) (x) + +#define MCCNT1_READ_DATA_DESCRAMBLE (1 << 13) +#define MCCNT1_CLOCK_SCRAMBLER (1 << 14) +#define MCCNT1_APPLY_SCRAMBLE_SEED (1 << 15) + +#define MCCNT1_LATENCY2_SHIFT 16 +#define MCCNT1_LATENCY2_MASK 0x3F0000 +#define MCCNT1_LATENCY2(x) (((x) << MCCNT1_LATENCY2_SHIFT) & MCCNT1_LATENCY2_MASK) + +#define MCCNT1_CMD_SCRAMBLE (1 << 22) + +#define MCCNT1_DATA_READY (1 << 23) + +#define MCCNT1_LEN_0 (0 << 24) +#define MCCNT1_LEN_512 (1 << 24) +#define MCCNT1_LEN_1024 (2 << 24) +#define MCCNT1_LEN_2048 (3 << 24) +#define MCCNT1_LEN_4096 (4 << 24) +#define MCCNT1_LEN_8192 (5 << 24) +#define MCCNT1_LEN_16384 (6 << 24) +#define MCCNT1_LEN_4 (7 << 24) + +#define MCCNT1_CLK_6_7_MHZ (0 << 27) +#define MCCNT1_CLK_4_2_MHZ (1 << 27) + +#define MCCNT1_LATENCY_CLK (1 << 28) + +#define MCCNT1_RESET_ON (0 << 29) +#define MCCNT1_RESET_OFF (1 << 29) + +#define MCCNT1_DIR_READ (0 << 30) +#define MCCNT1_DIR_WRITE (1 << 30) + +#define MCCNT1_ENABLE (1 << 31) + +#ifdef __cplusplus +extern "C" +{ +#endif + + static inline void card_romSetCmd(u64 cmd) + { + *(vu64*)®_MCCMD0 = __builtin_bswap64(cmd); + } + + static inline bool card_romIsDataReady(void) + { + return REG_MCCNT1 & MCCNT1_DATA_READY; + } + + static inline void card_romWaitDataReady(void) + { + while(!card_romIsDataReady()); + } + + static inline u32 card_romGetData(void) + { + return REG_MCD1; + } + + static inline void card_romSetData(u32 data) + { + REG_MCD1 = data; + } + + static inline bool card_romIsBusy(void) + { + return REG_MCCNT1 & MCCNT1_ENABLE; + } + + static inline void card_romWaitBusy(void) + { + while(card_romIsBusy()); + } + + static inline void card_romStartXfer(u32 settings, bool irq) + { + REG_MCCNT0 = (REG_MCCNT0 & ~(MCCNT0_MODE_MASK | MCCNT0_ROM_XFER_IRQ)) | MCCNT0_MODE_ROM | (irq ? MCCNT0_ROM_XFER_IRQ : 0) | MCCNT0_ENABLE; + REG_MCCNT1 = MCCNT1_ENABLE | settings; + } + + void card_romCpuRead(u32* dst, u32 len); + void card_romCpuReadUnaligned(u8* dst, u32 words); + + void card_romCpuWrite(const u32* src, u32 words); + void card_romCpuWriteUnaligned(const u8* src, u32 words); + +#ifdef __cplusplus +} +#endif diff --git a/arm9/source/launcher/ttio/scdssdhc.c b/arm9/source/launcher/ttio/scdssdhc.c new file mode 100644 index 0000000..160c888 --- /dev/null +++ b/arm9/source/launcher/ttio/scdssdhc.c @@ -0,0 +1,262 @@ +// clang-format off + +/* + SuperCard DSONE + Card IO routines + + Copyright (C) 2023 lifehackerhansol + + SPDX-License-Identifier: Zlib +*/ + +#include +#include "scdssdhc.h" +#include "libtwl_card.h" + +u32 SCDS_isSDHC = 0; + +static void SCDS_ReadCardData(u64 command, u32 flags, void *buffer, u32 length) +{ + card_romSetCmd(command); + card_romStartXfer(flags, false); + if ((u32)buffer & 3) + card_romCpuReadUnaligned((u8 *)buffer, length); + else + card_romCpuRead(buffer, length); +} + +static void SCDS_WriteCardData(u64 command, u32 flags, const void *buffer, u32 length) +{ + card_romSetCmd(command); + card_romStartXfer(flags, false); + if ((u32)buffer & 3) + card_romCpuWriteUnaligned((u8 *)buffer, length); + else + card_romCpuWrite(buffer, length); +} + +static u32 SCDS_IsSDHostBusy(void) +{ + return SCDS_SendCommand(SCDS_CMD_SD_HOST_BUSY, 0); +} + +static void SCDS_SDSendR0Command(u8 sdio, u32 parameter, u32 latency) +{ + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(sdio, parameter, SCDS_SD_HOST_NORESPONSE), latency); + while(SCDS_IsSDHostBusy()); +} + +static u32 SCDS_SDSendR1Command(u8 sdio, u32 parameter, u32 latency) +{ + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(sdio, parameter, SCDS_SD_HOST_READ_4B), latency); + while(SCDS_IsSDHostBusy()); + return __builtin_bswap32(SCDS_SendCommand(SCDS_CMD_SD_HOST_RESPONSE, 0)); +} + +// TODO: save the response to a buffer (also figure out in which order they're sent) +static void SCDS_SDSendR2Command(u8 sdio, u32 parameter, u32 latency) +{ + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(sdio, parameter, SCDS_SD_HOST_READ_4B_MULTI), latency); + while(SCDS_IsSDHostBusy()); + + // TODO: parse this response + SCDS_SendCommand(SCDS_CMD_SD_HOST_RESPONSE, 0); + + for(int i=0; i < 4; i++) + { + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(sdio, parameter, SCDS_SD_HOST_NEXT_4B), latency); + while(SCDS_IsSDHostBusy()); + // TODO: parse this response + SCDS_SendCommand(SCDS_CMD_SD_HOST_RESPONSE, 0); + } + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(sdio, parameter, SCDS_SD_HOST_SEND_STOP_CLK), 0); + while(SCDS_IsSDHostBusy()); +} + +void waitByLoop(u32 count); + +static void SCDS_SDSetHostRegister(u8 bits) +{ + SCDS_SendCommand(SCDS_CMD_SD_HOST_SET_REGISTER(bits), 0); + waitByLoop(0x300); +} + +void SCDS_SDGetSDHCStatusFromSRAM(void) +{ + SCDS_isSDHC = SCDS_SendCommand(SCDS_CMD_SRAM_READ_DATA(0x7F9E0), 0) != 0 ? 1 : 0; +} + +u32 SCDS_SendCommand(const u64 command, u32 latency) +{ + card_romSetCmd(command); + card_romStartXfer(SCDS_CTRL_READ_4B | MCCNT1_LATENCY1(latency), false); + card_romWaitDataReady(); + return card_romGetData(); +} + +bool SCDS_SDInitialize(void) +{ + u32 isSD20 = 0; + u32 response = 0; + + SCDS_isSDHC = 0; + + // TODO: What is this command doing? + SCDS_ReadCardData(0x6600000000000000ull, 0xA7586000, &response, 1); + + // Reset SD host + SCDS_SDSetHostRegister(0); + + // Init + SCDS_SDSetHostRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_400KHZ_CLK | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(0, 0, SCDS_SD_HOST_SEND_CLK), SCDS_CTRL_SD_LOW_CLK_LATENCY); + waitByLoop(0x1000); + + // CMD0 + SCDS_SDSendR0Command(0, 0, SCDS_CTRL_SD_LOW_CLK_LATENCY); + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(0, 0, SCDS_SD_HOST_SEND_STOP_CLK), SCDS_CTRL_SD_LOW_CLK_LATENCY); + + // CMD8 + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(8, 0x1AA, SCDS_SD_HOST_READ_4B), SCDS_CTRL_SD_LOW_CLK_LATENCY); + + u32 retryCount = 9999; + while(1) + { + if(!SCDS_IsSDHostBusy()) + { + response = __builtin_bswap32(SCDS_SendCommand(SCDS_CMD_SD_HOST_RESPONSE, 0)); + break; + } + if (--retryCount == 0) + { + SCDS_SDSetHostRegister(0); + SCDS_SDSetHostRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_400KHZ_CLK | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); + response = 0; + break; + } + } + + if(response == 0x1AA) + isSD20 = 1; + + do + { + // CMD55 + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(55, 0, SCDS_SD_HOST_READ_4B), SCDS_CTRL_SD_LOW_CLK_LATENCY); + retryCount = 9999; + while(SCDS_IsSDHostBusy()) + { + if (--retryCount == 0) + { + SCDS_SDSetHostRegister(0); + SCDS_SDSetHostRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_400KHZ_CLK | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); + return false; + } + } + SCDS_SendCommand(SCDS_CMD_SD_HOST_RESPONSE, 0); + + // ACMD41 + u32 parameter = 0x00FC0000; + if(isSD20) + parameter |= BIT(30); + response = SCDS_SDSendR1Command(41, parameter, SCDS_CTRL_SD_LOW_CLK_LATENCY); + } while(!(response & BIT(31))); + + SCDS_isSDHC = response & BIT(30) ? 1 : 0; + + // CMD2 + SCDS_SDSendR2Command(2, 0, SCDS_CTRL_SD_LOW_CLK_LATENCY); + + // CMD3 + response = SCDS_SDSendR1Command(3, 0, SCDS_CTRL_SD_LOW_CLK_LATENCY); + u32 sdio_rca = response & 0xFFFF0000; + + // CMD7 + SCDS_SDSendR1Command(7, sdio_rca, SCDS_CTRL_SD_LOW_CLK_LATENCY); + + // ACMD6 + SCDS_SDSendR1Command(55, sdio_rca, SCDS_CTRL_SD_LOW_CLK_LATENCY); + SCDS_SDSendR1Command(6, 2, SCDS_CTRL_SD_LOW_CLK_LATENCY); + + // CMD16 + SCDS_SDSendR1Command(16, 512, SCDS_CTRL_SD_LOW_CLK_LATENCY); + + SCDS_SDSetHostRegister(0); + SCDS_SDSetHostRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); + if(SCDS_isSDHC ) + SCDS_SDSetHostRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_CLEAN_ROM_MODE | SCDS_SD_HOST_REG_SDHC); + + return true; +} + +void SCDS_SDReadSingleSector(u32 sector, void *buffer) +{ + // instruct cart what to read + SCDS_SendCommand(SCDS_CMD_SD_READ_SINGLE_BLOCK(SCDS_isSDHC ? sector : sector << 9), 0); + + // wait until data ready + while(SCDS_SendCommand(SCDS_CMD_FIFO_BUSY, 0)); + + // retrieve data + SCDS_ReadCardData(SCDS_CMD_FIFO_READ_DATA, SCDS_CTRL_READ_512B, buffer, 128); +} + +void SCDS_SDReadMultiSector(u32 sector, void *buffer, u32 num_sectors) +{ + // instruct cart what to read + SCDS_SendCommand(SCDS_CMD_SD_READ_MULTI_BLOCK(SCDS_isSDHC ? sector : sector << 9), 0); + + while(1) + { + // wait until data ready + while(SCDS_SendCommand(SCDS_CMD_FIFO_BUSY, 0)); + + // retrieve data + SCDS_ReadCardData(SCDS_CMD_FIFO_READ_DATA, SCDS_CTRL_READ_512B, buffer, 128); + buffer = (u8 *)buffer + 0x200; + num_sectors--; + if(num_sectors == 0) + break; + SCDS_SendCommand(SCDS_CMD_SD_HOST_PARAM(0, 0, SCDS_SD_HOST_NEXT_DATABLOCK), 0); + }; + + // end read + SCDS_SDSendR1Command(12, 0, 0); +} + +void SCDS_SDWriteSingleSector(u32 sector, const void *buffer) +{ + // instruct cart where to write + SCDS_SDSendR1Command(24, SCDS_isSDHC ? sector : sector << 9, 0); + + // write + SCDS_WriteCardData(SCDS_CMD_FIFO_WRITE_DATA, SCDS_CTRL_WRITE_512B, buffer, 128); + while(SCDS_IsSDHostBusy()); + + // end write + SCDS_SendCommand(SCDS_CMD_SD_WRITE_END, 0); + while(SCDS_IsSDHostBusy()); +} + +void SCDS_SDWriteMultiSector(u32 sector, const void *buffer, u32 num_sectors) +{ + // instruct cart where to write + SCDS_SDSendR1Command(25, SCDS_isSDHC ? sector : sector << 9, 0); + + while (num_sectors--) { + // end write + // well, it's supposed to be end write. But doing it first is a no-op, and it's also + // a little simpler to write this way + SCDS_SendCommand(SCDS_CMD_SD_WRITE_END, 0); + while(SCDS_IsSDHostBusy()); + // write + SCDS_WriteCardData(SCDS_CMD_FIFO_WRITE_DATA, SCDS_CTRL_WRITE_512B, buffer, 128); + while(SCDS_IsSDHostBusy()); + buffer = (u8 *)buffer + 0x200; + } + + // *really* end write + SCDS_SDSendR1Command(12, 0, 0); + SCDS_SendCommand(SCDS_CMD_SD_WRITE_END, 0); + while(SCDS_IsSDHostBusy()); +} diff --git a/arm9/source/launcher/ttio/scdssdhc.h b/arm9/source/launcher/ttio/scdssdhc.h new file mode 100644 index 0000000..9fad624 --- /dev/null +++ b/arm9/source/launcher/ttio/scdssdhc.h @@ -0,0 +1,168 @@ +// clang-format off + +/* + SuperCard DSONE + Card IO routines + + Copyright (C) 2006 SuperCard + Copyright (C) 2023 lifehackerhansol + + SPDX-License-Identifier: Zlib +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef NULL + #define NULL 0 +#endif + +// SCDS defines +// SCDS ROMCTRL flags +#define SCDS_CTRL_BASE (MCCNT1_ENABLE | MCCNT1_RESET_OFF | MCCNT1_LATENCY2(24) | MCCNT1_LATENCY1(0)) +#define SCDS_CTRL_READ_4B (SCDS_CTRL_BASE | MCCNT1_LEN_4) +#define SCDS_CTRL_READ_512B (SCDS_CTRL_BASE | MCCNT1_LEN_512) +#define SCDS_CTRL_WRITE_4B (SCDS_CTRL_BASE | MCCNT1_DIR_WRITE | MCCNT1_LEN_4) +#define SCDS_CTRL_WRITE_512B (SCDS_CTRL_BASE | MCCNT1_DIR_WRITE | MCCNT1_LEN_512) + +#define SCDS_CTRL_SD_LOW_CLK_LATENCY 0x1000 + +// SCDS CARD_COMMANDs + +/* + SRAM commands + + Command structure: + AA BB BB BB BB 00 00 00 + AA = command + BBBBBBBB = address +*/ + +static inline u64 SCDS_CMD_SRAM_READ_DATA(u32 address) +{ + return (0x70ull << 56) | ((u64)address << 24); +} + +static inline u64 SCDS_CMD_SRAM_WRITE_DATA(u32 address) +{ + return (0x71ull << 56) | ((u64)address << 24); +} + +/* + This address in SRAM *usually* contains a bool for SD or SDHC + While not exactly reliable, the original driver did it, so here goes + + return 0 == SD + return non-0 == SDHC +*/ +static inline u64 SCDS_CMD_SD_IS_SDHC(void) +{ + return SCDS_CMD_SRAM_READ_DATA(0x7F9E0); +} + +// FIFO commands +#define SCDS_CMD_FIFO_BUSY (0x80ull << 56) +#define SCDS_CMD_FIFO_READ_DATA (0x81ull << 56) +#define SCDS_CMD_FIFO_WRITE_DATA (0x82ull << 56) + +/* + SD host modes + Used with 0x51 command, see below +*/ +enum SCDS_SD_HOST_MODES { + SCDS_SD_HOST_NORESPONSE = 0ull, + SCDS_SD_HOST_READ_4B = 1ull, + SCDS_SD_HOST_READ_4B_MULTI = 2ull, // use mode 3 to continue this read + SCDS_SD_HOST_NEXT_4B = 3ull, + SCDS_SD_HOST_SEND_CLK = 4ull, + SCDS_SD_HOST_SEND_STOP_CLK = 5ull, + SCDS_SD_HOST_READ_DATABLOCK = 6ull, + SCDS_SD_HOST_NEXT_DATABLOCK = 7ull, + SCDS_SD_HOST_CMD17_READ_DATA = 8ull, // Send SDIO CMD17 & read data + SCDS_SD_HOST_CMD18_READ_DATA = 9ull, // Send SDIO CMD18 & read data until stop + SCDS_SD_HOST_COMMIT_FIFO_DATA = 0xAull, // commit data in FIFO to SD card + SCDS_SD_HOST_CMD24_WRITE_DATA = 0xBull, // Send SDIO CMD24 & send data in SRAM buffer + SCDS_SD_HOST_WAIT_BUSY = 0xCull // wait until data transfer ends +}; + +/* + SD host related commands + + Note: + While this is where the SDIO happens, it isn't always SDIO + Thus, it can sometimes be 0 + + Command structure: + 51 AA AA AA AA BB CC 00 + AAAAAAAA = SDIO parameter + BB = SDIO command + CC = SD host mode, see SCDS_SD_HOST_MODES enum +*/ +static inline u64 SCDS_CMD_SD_HOST_PARAM(u8 sdio, u32 parameter, u8 mode) +{ + return (0x51ull << 56) | ((u64)parameter << 24) | ((u64)sdio << 16) | ((u64)mode << 8); +} + +// SD host misc commands +// return 0 == idle +// return non-0 == not idle +#define SCDS_CMD_SD_HOST_BUSY (0x50ull << 56) + +// Gets response of SD_HOST commands, if the sent mode is 1 or 2 +#define SCDS_CMD_SD_HOST_RESPONSE (0x52ull << 56) +// Stops SD host data transfer +#define SCDS_CMD_SD_WRITE_END (0x56ull << 56) + +// Sends CMD17 +// This is effectively 0x51/0x50/0x52 rolled into one command +static inline u64 SCDS_CMD_SD_READ_SINGLE_BLOCK(u32 sector) +{ + return (0x53ull << 56) | ((u64)sector << 24); +} + +// Sends CMD18 +// This is effectively 0x51/0x50/0x52 rolled into one command +static inline u64 SCDS_CMD_SD_READ_MULTI_BLOCK(u32 sector) +{ + return (0x54ull << 56) | ((u64)sector << 24); +} + +/* + SD host control registers + The 0x5F sets raw registers related to the SD host, which is a single u8. + Bits: + 0: Reset + 1: Set 400k low clk + 2: Use 0xB7 as alternative of 0x5B for ROM reads + 3: Set SDHC mode + 4-5: 1 + 6-7: 0 +*/ +#define SCDS_SD_HOST_REG_RESET BIT(0) +#define SCDS_SD_HOST_REG_400KHZ_CLK BIT(1) +#define SCDS_SD_HOST_REG_CLEAN_ROM_MODE BIT(2) +#define SCDS_SD_HOST_REG_SDHC BIT(3) + +// This function will always set bits 4-5 to 1 and bits 6-7 to 0 for convenience +static inline u64 SCDS_CMD_SD_HOST_SET_REGISTER(u8 bits) +{ + return (0x5F30ull << 48) | ((u64)bits << 48); +} + +// user API +u32 SCDS_SendCommand(const u64 command, u32 latency); +void SCDS_SDGetSDHCStatusFromSRAM(void); +bool SCDS_SDInitialize(void); +void SCDS_SDReadSingleSector(u32 sector, void *buffer); +void SCDS_SDReadMultiSector(u32 sector, void *buffer, u32 num_sectors); +void SCDS_SDWriteSingleSector(u32 sector, const void *buffer); +void SCDS_SDWriteMultiSector(u32 sector, const void *buffer, u32 num_sectors); + +#ifdef __cplusplus +} +#endif diff --git a/arm9/source/launcher/ttio/waitByLoop.s b/arm9/source/launcher/ttio/waitByLoop.s new file mode 100644 index 0000000..e457b97 --- /dev/null +++ b/arm9/source/launcher/ttio/waitByLoop.s @@ -0,0 +1,18 @@ +@ +@ Copyright (C) 2024 lifehackerhansol +@ +@ SPDX-License-Identifier: zlib +@ + +#include + + .syntax unified + .arm + +@ void waitByLoop(u32 count) +@ because we can't use swi 0x3 in DLDI + +BEGIN_ASM_FUNC waitByLoop + subs r0, r0, #1 + bgt waitByLoop + bx lr diff --git a/arm9_ak2/Makefile b/arm9_ak2/Makefile index ac620fd..ab91788 100644 --- a/arm9_ak2/Makefile +++ b/arm9_ak2/Makefile @@ -33,7 +33,7 @@ CFLAGS := -g -Wall -O3\ CFLAGS += -D_NO_BOOTSTUB_ -D__KERNEL_LAUNCHER_SUPPORT__ -D__AKLOADER_AK2__ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -ASFLAGS := -g $(ARCH) +ASFLAGS := -g $(ARCH) $(INCLUDE) LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #--------------------------------------------------------------------------------- diff --git a/arm9_dsi/Makefile b/arm9_dsi/Makefile index 837aa5f..98b4f58 100644 --- a/arm9_dsi/Makefile +++ b/arm9_dsi/Makefile @@ -33,7 +33,7 @@ CFLAGS := -g -Wall -O3\ CFLAGS += -D_NO_BOOTSTUB_ -D__DSIMODE__ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -ASFLAGS := -g $(ARCH) +ASFLAGS := -g $(ARCH) $(INCLUDE) LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #--------------------------------------------------------------------------------- diff --git a/arm9_tt/Makefile b/arm9_tt/Makefile index 9a837cf..b7a9493 100644 --- a/arm9_tt/Makefile +++ b/arm9_tt/Makefile @@ -17,7 +17,7 @@ SOURCE_PATH := ../arm9 # all directories are relative to this makefile #--------------------------------------------------------------------------------- BUILD := build -SOURCES := $(SOURCE_PATH)/source $(SOURCE_PATH)/source/ui $(SOURCE_PATH)/source/font $(SOURCE_PATH)/source/launcher $(SOURCE_PATH)/source/launcher/libfat_ext $(SOURCE_PATH)/source/saves +SOURCES := $(SOURCE_PATH)/source $(SOURCE_PATH)/source/ui $(SOURCE_PATH)/source/font $(SOURCE_PATH)/source/launcher $(SOURCE_PATH)/source/launcher/libfat_ext $(SOURCE_PATH)/source/launcher/ttio $(SOURCE_PATH)/source/saves INCLUDES := $(SOURCE_PATH)/include ../share $(SOURCES) DATA := $(SOURCE_PATH)/data ../data GRAPHICS := @@ -30,10 +30,10 @@ ARCH := -marm -mthumb-interwork -march=armv5te -mtune=arm946e-s CFLAGS := -g -Wall -O3\ $(ARCH) $(INCLUDE) -DARM9 -CFLAGS += -D_NO_BOOTSTUB_ -D__KERNEL_LAUNCHER_SUPPORT__ -D__TTLAUNCHER__ +CFLAGS += -D_NO_BOOTSTUB_ -D__KERNEL_LAUNCHER_SUPPORT__ -D__TTLAUNCHER__ -D__TTLAUNCHER_DSTT__ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -ASFLAGS := -g $(ARCH) +ASFLAGS := -g $(ARCH) $(INCLUDE) LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #---------------------------------------------------------------------------------