diff --git a/Makefile b/Makefile index 51afdda..85d0331 100644 --- a/Makefile +++ b/Makefile @@ -36,19 +36,26 @@ CFLAGS := -g -Wall -Wextra -Wpedantic -O2 -flto\ -ffast-math -std=c11\ $(ARCH) -CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration -Wcast-align\ - -Wcast-qual -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op \ - -Wmissing-declarations -Wmissing-include-dirs -Wredundant-decls -Wshadow \ - -Wsign-conversion -Wstrict-overflow=5 -Wswitch-default -Wundef -Wno-unused +CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration -Wcast-align \ + -Wcast-qual -Wdisabled-optimization -Wformat=2 -Winit-self \ + -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs \ + -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow=5 \ + -Wswitch-default -Wundef -Wno-unused CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions ASFLAGS := -g $(ARCH) LDFLAGS = -nostartfiles -g --specs=../stub.specs $(ARCH) -Wl,-Map,$(TARGET).map -OCFLAGS=--set-section-flags .bss=alloc,load,contents +OCFLAGS= --set-section-flags .bss=alloc,load,contents LIBS := +ifeq ($(EXEC_METHOD),BRAHMA) + CFLAGS += -DBRAHMA #can't use CPPFLAGS because 3ds_rules doesn't use them +else ifeq ($(EXEC_METHOD), A9LH) + CFLAGS += -DA9LH #can't use CPPFLAGS because 3ds_rules doesn't use them +endif + #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib @@ -97,20 +104,32 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: $(BUILD) clean all +.PHONY: common clean all brahma a9lh release #--------------------------------------------------------------------------------- -all: $(BUILD) +all: release -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile +common: + @[ -d $(BUILD) ] || mkdir -p $(BUILD) + +a9lh: common + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=A9LH cp $(OUTPUT).bin arm9loaderhax.bin +brahma: common + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=BRAHMA + cp $(OUTPUT).bin uncart_brahma.bin + +release: + @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf + @make --no-print-directory a9lh + @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf + @make --no-print-directory brahma + #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin arm9payload.bin + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin arm9payload.bin uncart_brahma.bin #--------------------------------------------------------------------------------- diff --git a/source/aes.h b/source/aes.h index 417ea38..1c951e7 100644 --- a/source/aes.h +++ b/source/aes.h @@ -1,54 +1,54 @@ -// Copyright 2014 Normmatt -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common.h" - -#define REG_AESCNT (*(vu32*)0x10009000) -#define REG_AESBLKCNT (*(vu32*)0x10009004) -#define REG_AESBLKCNTH1 (*(vu16*)0x10009004) -#define REG_AESBLKCNTH2 (*(vu16*)0x10009006) -#define REG_AESWRFIFO (*(vu32*)0x10009008) -#define REG_AESRDFIFO (*(vu32*)0x1000900C) -#define REG_AESKEYSEL (*(vu8*)0x10009010) -#define REG_AESKEYCNT (*(vu8*)0x10009011) -#define REG_AESCTR ((vu32*)0x10009020) // 16 -#define REG_AESMAC ((vu32*)0x10009030) // 16 -#define REG_AESKEY0 ((vu32*)0x10009040) // 48 -#define REG_AESKEY1 ((vu32*)0x10009070) // 48 -#define REG_AESKEY2 ((vu32*)0x100090A0) // 48 -#define REG_AESKEY3 ((vu32*)0x100090D0) // 48 -#define REG_AESKEYFIFO (*(vu32*)0x10009100) -#define REG_AESKEYXFIFO (*(vu32*)0x10009104) -#define REG_AESKEYYFIFO (*(vu32*)0x10009108) - -#define AES_WRITE_FIFO_COUNT ((REG_AESCNT>>0) & 0x1F) -#define AES_READ_FIFO_COUNT ((REG_AESCNT>>5) & 0x1F) -#define AES_BUSY (1u<<31) - -#define AES_FLUSH_READ_FIFO (1u<<10) -#define AES_FLUSH_WRITE_FIFO (1u<<11) -#define AES_BIT12 (1u<<12) -#define AES_BIT13 (1u<<13) -#define AES_MAC_SIZE(n) ((n&7u)<<16) -#define AES_MAC_REGISTER_SOURCE (1u<<20) -#define AES_UNKNOWN_21 (1u<<21) -#define AES_OUTPUT_BIG_ENDIAN (1u<<22) -#define AES_INPUT_BIG_ENDIAN (1u<<23) -#define AES_OUTPUT_NORMAL_ORDER (1u<<24) -#define AES_INPUT_NORMAL_ORDER (1u<<25) -#define AES_UNKNOWN_26 (1u<<26) -#define AES_MODE(n) ((n&7u)<<27) -#define AES_INTERRUPT_ENABLE (1u<<30) -#define AES_ENABLE (1u<<31) - -#define AES_MODE_CCM_DECRYPT 0u -#define AES_MODE_CCM_ENCRYPT 1u -#define AES_MODE_CTR 2u -#define AES_MODE_UNK3 3u -#define AES_MODE_CBC_DECRYPT 4u -#define AES_MODE_CBC_ENCRYPT 5u -#define AES_MODE_UNK6 6u -#define AES_MODE_UNK7 7u +// Copyright 2014 Normmatt +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common.h" + +#define REG_AESCNT (*(vu32*)0x10009000) +#define REG_AESBLKCNT (*(vu32*)0x10009004) +#define REG_AESBLKCNTH1 (*(vu16*)0x10009004) +#define REG_AESBLKCNTH2 (*(vu16*)0x10009006) +#define REG_AESWRFIFO (*(vu32*)0x10009008) +#define REG_AESRDFIFO (*(vu32*)0x1000900C) +#define REG_AESKEYSEL (*(vu8*)0x10009010) +#define REG_AESKEYCNT (*(vu8*)0x10009011) +#define REG_AESCTR ((vu32*)0x10009020) // 16 +#define REG_AESMAC ((vu32*)0x10009030) // 16 +#define REG_AESKEY0 ((vu32*)0x10009040) // 48 +#define REG_AESKEY1 ((vu32*)0x10009070) // 48 +#define REG_AESKEY2 ((vu32*)0x100090A0) // 48 +#define REG_AESKEY3 ((vu32*)0x100090D0) // 48 +#define REG_AESKEYFIFO (*(vu32*)0x10009100) +#define REG_AESKEYXFIFO (*(vu32*)0x10009104) +#define REG_AESKEYYFIFO (*(vu32*)0x10009108) + +#define AES_WRITE_FIFO_COUNT ((REG_AESCNT>>0) & 0x1F) +#define AES_READ_FIFO_COUNT ((REG_AESCNT>>5) & 0x1F) +#define AES_BUSY (1u<<31) + +#define AES_FLUSH_READ_FIFO (1u<<10) +#define AES_FLUSH_WRITE_FIFO (1u<<11) +#define AES_BIT12 (1u<<12) +#define AES_BIT13 (1u<<13) +#define AES_MAC_SIZE(n) ((n&7u)<<16) +#define AES_MAC_REGISTER_SOURCE (1u<<20) +#define AES_UNKNOWN_21 (1u<<21) +#define AES_OUTPUT_BIG_ENDIAN (1u<<22) +#define AES_INPUT_BIG_ENDIAN (1u<<23) +#define AES_OUTPUT_NORMAL_ORDER (1u<<24) +#define AES_INPUT_NORMAL_ORDER (1u<<25) +#define AES_UNKNOWN_26 (1u<<26) +#define AES_MODE(n) ((n&7u)<<27) +#define AES_INTERRUPT_ENABLE (1u<<30) +#define AES_ENABLE (1u<<31) + +#define AES_MODE_CCM_DECRYPT 0u +#define AES_MODE_CCM_ENCRYPT 1u +#define AES_MODE_CTR 2u +#define AES_MODE_UNK3 3u +#define AES_MODE_CBC_DECRYPT 4u +#define AES_MODE_CBC_ENCRYPT 5u +#define AES_MODE_UNK6 6u +#define AES_MODE_UNK7 7u diff --git a/source/draw.h b/source/draw.h index c39c6cf..99bba9c 100644 --- a/source/draw.h +++ b/source/draw.h @@ -14,15 +14,20 @@ #define RGB(r,g,b) (r<<24|b<<16|g<<8|r) -//#define TOP_SCREEN0 (u8*)(0x20000000) -//#define TOP_SCREEN1 (u8*)(0x20046500) -//#define BOT_SCREEN0 (u8*)(0x2008CA00) -//#define BOT_SCREEN1 (u8*)(0x200C4E00) +#ifdef BRAHMA + #define TOP_SCREEN0 (u8*)(0x20000000) + #define TOP_SCREEN1 (u8*)(0x20046500) + #define BOT_SCREEN0 (u8*)(0x2008CA00) + #define BOT_SCREEN1 (u8*)(0x200C4E00) +#endif + +#ifdef A9LH + #define TOP_SCREEN0 (u8*)(*(u32*)0x23FFFE00) + #define TOP_SCREEN1 (u8*)(*(u32*)0x23FFFE00) + #define BOT_SCREEN0 (u8*)(*(u32*)0x23FFFE08) + #define BOT_SCREEN1 (u8*)(*(u32*)0x23FFFE08) +#endif -#define TOP_SCREEN0 (u8*)(0x18300000) -#define TOP_SCREEN1 (u8*)(0x18300000) -#define BOT_SCREEN0 (u8*)(0x18346500) -#define BOT_SCREEN1 (u8*)(0x18346500) extern size_t current_y; void ClearScreen(unsigned char *screen, int color); diff --git a/source/gamecart/protocol.c b/source/gamecart/protocol.c index ee36292..fdfb7ec 100644 --- a/source/gamecart/protocol.c +++ b/source/gamecart/protocol.c @@ -1,226 +1,226 @@ -// Copyright 2014 Normmatt -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "protocol.h" - -#include -#include -#include - -#include "draw.h" -#include "common.h" -#include "aes.h" -#include "protocol_ctr.h" -#include "protocol_ntr.h" -#include "command_ctr.h" -#include "command_ntr.h" -#include "delay.h" - -extern u8* bottomScreen; - -u32 CartID = 0xFFFFFFFFu; -u32 CartType = 0; - -static u32 A0_Response = 0xFFFFFFFFu; -static u32 rand1 = 0; -static u32 rand2 = 0; - -u32 BSWAP32(u32 val) { - return (((val >> 24) & 0xFF)) | - (((val >> 16) & 0xFF) << 8) | - (((val >> 8) & 0xFF) << 16) | - ((val & 0xFF) << 24); -} - -// TODO: Verify -static void ResetCartSlot(void) -{ - REG_CARDCONF2 = 0x0C; - REG_CARDCONF &= ~3; - - if (REG_CARDCONF2 == 0xC) { - while (REG_CARDCONF2 != 0); - } - - if (REG_CARDCONF2 != 0) - return; - - REG_CARDCONF2 = 0x4; - while(REG_CARDCONF2 != 0x4); - - REG_CARDCONF2 = 0x8; - while(REG_CARDCONF2 != 0x8); -} - -static void SwitchToNTRCARD(void) -{ - REG_NTRCARDROMCNT = 0x20000000; - REG_CARDCONF &= ~3; - REG_CARDCONF &= ~0x100; - REG_NTRCARDMCNT = NTRCARD_CR1_ENABLE; -} - -static void SwitchToCTRCARD(void) -{ - REG_CTRCARDCNT = 0x10000000; - REG_CARDCONF = (REG_CARDCONF & ~3) | 2; -} - -int Cart_IsInserted(void) -{ - return (0x9000E2C2 == CTR_CmdGetSecureId(rand1, rand2) ); -} - -u32 Cart_GetID(void) -{ - return CartID; -} - -void Cart_Init(void) -{ - ResetCartSlot(); //Seems to reset the cart slot? - - REG_CTRCARDSECCNT &= 0xFFFFFFFB; - ioDelay(0x30000); - - SwitchToNTRCARD(); - ioDelay(0x30000); - - REG_NTRCARDROMCNT = 0; - REG_NTRCARDMCNT &= 0xFF; - ioDelay(0x40000); - - REG_NTRCARDMCNT |= (NTRCARD_CR1_ENABLE | NTRCARD_CR1_IRQ); - REG_NTRCARDROMCNT = NTRCARD_nRESET | NTRCARD_SEC_SEED; - while (REG_NTRCARDROMCNT & NTRCARD_BUSY); - - // Reset - NTR_CmdReset(); - CartID = NTR_CmdGetCartId(); - - // 3ds - if (CartID & 0x10000000) { - u32 unknowna0_cmd[2] = { 0xA0000000, 0x00000000 }; - NTR_SendCommand(unknowna0_cmd, 0x4, 0, &A0_Response); - - NTR_CmdEnter16ByteMode(); - SwitchToCTRCARD(); - ioDelay(0xF000); - - REG_CTRCARDBLKCNT = 0; - } -} - -static void AES_SetKeyControl(u32 a) { - REG_AESKEYCNT = (REG_AESKEYCNT & 0xC0) | a | 0x80; -} - -//returns 1 if MAC valid otherwise 0 -static u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignored - u8 tmp = REG_AESKEYCNT; - REG_AESCNT = 0x10C00; //flush r/w fifo macsize = 001 - - (*(vu8*)0x10000008) |= 0x0C; //??? - - REG_AESCNT |= 0x2800000; - - //const u8 is_dev_unit = *(vu8*)0x10010010; - //if(is_dev_unit) //Dev unit - const u8 is_dev_cart = (A0_Response&3)==3; - if(is_dev_cart) //Dev unit - { - AES_SetKeyControl(0x11); - REG_AESKEYFIFO = 0; - REG_AESKEYFIFO = 0; - REG_AESKEYFIFO = 0; - REG_AESKEYFIFO = 0; - REG_AESKEYSEL = 0x11; - } - else - { - AES_SetKeyControl(0x3B); - REG_AESKEYYFIFO = buff[0]; - REG_AESKEYYFIFO = buff[1]; - REG_AESKEYYFIFO = buff[2]; - REG_AESKEYYFIFO = buff[3]; - REG_AESKEYSEL = 0x3B; - } - - REG_AESCNT = 0x4000000; - REG_AESCNT &= 0xFFF7FFFF; - REG_AESCNT |= 0x2970000; - REG_AESMAC[0] = buff[11]; - REG_AESMAC[1] = buff[10]; - REG_AESMAC[2] = buff[9]; - REG_AESMAC[3] = buff[8]; - REG_AESCNT |= 0x2800000; - REG_AESCTR[0] = buff[14]; - REG_AESCTR[1] = buff[13]; - REG_AESCTR[2] = buff[12]; - REG_AESBLKCNT = 0x10000; - - u32 v11 = ((REG_AESCNT | 0x80000000) & 0xC7FFFFFF); //Start and clear mode (ccm decrypt) - u32 v12 = v11 & 0xBFFFFFFF; //Disable Interrupt - REG_AESCNT = ((((v12 | 0x3000) & 0xFD7F3FFF) | (5 << 23)) & 0xFEBFFFFF) | (5 << 22); - - //REG_AESCNT = 0x83D73C00; - REG_AESWRFIFO = buff[4]; - REG_AESWRFIFO = buff[5]; - REG_AESWRFIFO = buff[6]; - REG_AESWRFIFO = buff[7]; - while (((REG_AESCNT >> 5) & 0x1F) <= 3); - out[0] = REG_AESRDFIFO; - out[1] = REG_AESRDFIFO; - out[2] = REG_AESRDFIFO; - out[3] = REG_AESRDFIFO; - return ((REG_AESCNT >> 21) & 1); -} - -void Cart_Secure_Init(u32 *buf, u32 *out) -{ - u8 mac_valid = card_aes(out, buf, 0x200); - -// if (!mac_valid) -// ClearScreen(bottomScreen, RGB(255, 0, 0)); - - ioDelay(0xF0000); - - CTR_SetSecKey(A0_Response); - CTR_SetSecSeed(out, true); - - rand1 = 0x42434445;//*((vu32*)0x10011000); - rand2 = 0x46474849;//*((vu32*)0x10011010); - - CTR_CmdSeed(rand1, rand2); - - out[3] = BSWAP32(rand2); - out[2] = BSWAP32(rand1); - CTR_SetSecSeed(out, false); - - u32 test = 0; - const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); - - u32 test2 = 0; - const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2); - - if(test==CartID && test2==A0_Response) - { - const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(C5_cmd, 0, 1, 0x100002C, NULL); - } - - for (int i = 0; i < 5; ++i) { - CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); - ioDelay(0xF0000); - } -} - -void Cart_Dummy(void) { - // Sends a dummy command to skip encrypted responses some problematic carts send. - u32 test; - const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); -} +// Copyright 2014 Normmatt +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "protocol.h" + +#include +#include +#include + +#include "draw.h" +#include "common.h" +#include "aes.h" +#include "protocol_ctr.h" +#include "protocol_ntr.h" +#include "command_ctr.h" +#include "command_ntr.h" +#include "delay.h" + +extern u8* bottomScreen; + +u32 CartID = 0xFFFFFFFFu; +u32 CartType = 0; + +static u32 A0_Response = 0xFFFFFFFFu; +static u32 rand1 = 0; +static u32 rand2 = 0; + +u32 BSWAP32(u32 val) { + return (((val >> 24) & 0xFF)) | + (((val >> 16) & 0xFF) << 8) | + (((val >> 8) & 0xFF) << 16) | + ((val & 0xFF) << 24); +} + +// TODO: Verify +static void ResetCartSlot(void) +{ + REG_CARDCONF2 = 0x0C; + REG_CARDCONF &= ~3; + + if (REG_CARDCONF2 == 0xC) { + while (REG_CARDCONF2 != 0); + } + + if (REG_CARDCONF2 != 0) + return; + + REG_CARDCONF2 = 0x4; + while(REG_CARDCONF2 != 0x4); + + REG_CARDCONF2 = 0x8; + while(REG_CARDCONF2 != 0x8); +} + +static void SwitchToNTRCARD(void) +{ + REG_NTRCARDROMCNT = 0x20000000; + REG_CARDCONF &= ~3; + REG_CARDCONF &= ~0x100; + REG_NTRCARDMCNT = NTRCARD_CR1_ENABLE; +} + +static void SwitchToCTRCARD(void) +{ + REG_CTRCARDCNT = 0x10000000; + REG_CARDCONF = (REG_CARDCONF & ~3) | 2; +} + +int Cart_IsInserted(void) +{ + return (0x9000E2C2 == CTR_CmdGetSecureId(rand1, rand2) ); +} + +u32 Cart_GetID(void) +{ + return CartID; +} + +void Cart_Init(void) +{ + ResetCartSlot(); //Seems to reset the cart slot? + + REG_CTRCARDSECCNT &= 0xFFFFFFFB; + ioDelay(0x30000); + + SwitchToNTRCARD(); + ioDelay(0x30000); + + REG_NTRCARDROMCNT = 0; + REG_NTRCARDMCNT &= 0xFF; + ioDelay(0x40000); + + REG_NTRCARDMCNT |= (NTRCARD_CR1_ENABLE | NTRCARD_CR1_IRQ); + REG_NTRCARDROMCNT = NTRCARD_nRESET | NTRCARD_SEC_SEED; + while (REG_NTRCARDROMCNT & NTRCARD_BUSY); + + // Reset + NTR_CmdReset(); + CartID = NTR_CmdGetCartId(); + + // 3ds + if (CartID & 0x10000000) { + u32 unknowna0_cmd[2] = { 0xA0000000, 0x00000000 }; + NTR_SendCommand(unknowna0_cmd, 0x4, 0, &A0_Response); + + NTR_CmdEnter16ByteMode(); + SwitchToCTRCARD(); + ioDelay(0xF000); + + REG_CTRCARDBLKCNT = 0; + } +} + +static void AES_SetKeyControl(u32 a) { + REG_AESKEYCNT = (REG_AESKEYCNT & 0xC0) | a | 0x80; +} + +//returns 1 if MAC valid otherwise 0 +static u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignored + u8 tmp = REG_AESKEYCNT; + REG_AESCNT = 0x10C00; //flush r/w fifo macsize = 001 + + (*(vu8*)0x10000008) |= 0x0C; //??? + + REG_AESCNT |= 0x2800000; + + //const u8 is_dev_unit = *(vu8*)0x10010010; + //if(is_dev_unit) //Dev unit + const u8 is_dev_cart = (A0_Response&3)==3; + if(is_dev_cart) //Dev unit + { + AES_SetKeyControl(0x11); + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYSEL = 0x11; + } + else + { + AES_SetKeyControl(0x3B); + REG_AESKEYYFIFO = buff[0]; + REG_AESKEYYFIFO = buff[1]; + REG_AESKEYYFIFO = buff[2]; + REG_AESKEYYFIFO = buff[3]; + REG_AESKEYSEL = 0x3B; + } + + REG_AESCNT = 0x4000000; + REG_AESCNT &= 0xFFF7FFFF; + REG_AESCNT |= 0x2970000; + REG_AESMAC[0] = buff[11]; + REG_AESMAC[1] = buff[10]; + REG_AESMAC[2] = buff[9]; + REG_AESMAC[3] = buff[8]; + REG_AESCNT |= 0x2800000; + REG_AESCTR[0] = buff[14]; + REG_AESCTR[1] = buff[13]; + REG_AESCTR[2] = buff[12]; + REG_AESBLKCNT = 0x10000; + + u32 v11 = ((REG_AESCNT | 0x80000000) & 0xC7FFFFFF); //Start and clear mode (ccm decrypt) + u32 v12 = v11 & 0xBFFFFFFF; //Disable Interrupt + REG_AESCNT = ((((v12 | 0x3000) & 0xFD7F3FFF) | (5 << 23)) & 0xFEBFFFFF) | (5 << 22); + + //REG_AESCNT = 0x83D73C00; + REG_AESWRFIFO = buff[4]; + REG_AESWRFIFO = buff[5]; + REG_AESWRFIFO = buff[6]; + REG_AESWRFIFO = buff[7]; + while (((REG_AESCNT >> 5) & 0x1F) <= 3); + out[0] = REG_AESRDFIFO; + out[1] = REG_AESRDFIFO; + out[2] = REG_AESRDFIFO; + out[3] = REG_AESRDFIFO; + return ((REG_AESCNT >> 21) & 1); +} + +void Cart_Secure_Init(u32 *buf, u32 *out) +{ + u8 mac_valid = card_aes(out, buf, 0x200); + +// if (!mac_valid) +// ClearScreen(bottomScreen, RGB(255, 0, 0)); + + ioDelay(0xF0000); + + CTR_SetSecKey(A0_Response); + CTR_SetSecSeed(out, true); + + rand1 = 0x42434445;//*((vu32*)0x10011000); + rand2 = 0x46474849;//*((vu32*)0x10011010); + + CTR_CmdSeed(rand1, rand2); + + out[3] = BSWAP32(rand2); + out[2] = BSWAP32(rand1); + CTR_SetSecSeed(out, false); + + u32 test = 0; + const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); + + u32 test2 = 0; + const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2); + + if(test==CartID && test2==A0_Response) + { + const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(C5_cmd, 0, 1, 0x100002C, NULL); + } + + for (int i = 0; i < 5; ++i) { + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); + ioDelay(0xF0000); + } +} + +void Cart_Dummy(void) { + // Sends a dummy command to skip encrypted responses some problematic carts send. + u32 test; + const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); +} diff --git a/source/gamecart/protocol.h b/source/gamecart/protocol.h index 75418aa..7a12407 100644 --- a/source/gamecart/protocol.h +++ b/source/gamecart/protocol.h @@ -1,25 +1,25 @@ -// Copyright 2014 Normmatt -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once -#include "common.h" - -#define REG_CARDCONF (*(vu16*)0x1000000C) -#define REG_CARDCONF2 (*(vu8*)0x10000010) - -//REG_AUXSPICNT -#define CARD_ENABLE (1u<<15) -#define CARD_SPI_ENABLE (1u<<13) -#define CARD_SPI_BUSY (1u<<7) -#define CARD_SPI_HOLD (1u<<6) - -#define LATENCY 0x822Cu - -u32 BSWAP32(u32 val); - -void Cart_Init(void); -int Cart_IsInserted(void); -u32 Cart_GetID(void); -void Cart_Secure_Init(u32* buf, u32* out); -void Cart_Dummy(void); +// Copyright 2014 Normmatt +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include "common.h" + +#define REG_CARDCONF (*(vu16*)0x1000000C) +#define REG_CARDCONF2 (*(vu8*)0x10000010) + +//REG_AUXSPICNT +#define CARD_ENABLE (1u<<15) +#define CARD_SPI_ENABLE (1u<<13) +#define CARD_SPI_BUSY (1u<<7) +#define CARD_SPI_HOLD (1u<<6) + +#define LATENCY 0x822Cu + +u32 BSWAP32(u32 val); + +void Cart_Init(void); +int Cart_IsInserted(void); +u32 Cart_GetID(void); +void Cart_Secure_Init(u32* buf, u32* out); +void Cart_Dummy(void);