Skip to content

Commit 27b6e44

Browse files
committed
A9LH support, clarity fixes
1 parent 25edca0 commit 27b6e44

5 files changed

Lines changed: 138 additions & 13 deletions

File tree

agb_inject/gen_rom.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
print("Use Python3.")
1515
savename = input("Type in the save's name: ")
1616
outname = input("Type in the output cia's name: ")
17-
savetype = int(input("Type in the save type: "))
17+
savetype = int(input("Type in the save type (0: SRAM, 1: Flash, 2: EEPROM): "))
1818
titleid = input("Type in the title id of the game you wish to inject: ")
1919
os.mkdir(ScriptPath + "tmp")
2020
try:

source/decryptor/nand.c

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "hid.h"
44
#include "platform.h"
55
#include "decryptor/aes.h"
6+
#include "decryptor/sha.h"
67
#include "decryptor/decryptor.h"
78
#include "decryptor/nand.h"
89
#include "fatfs/sdmmc.h"
@@ -105,6 +106,86 @@ static inline int WriteNandSectors(u32 sector_no, u32 numsectors, u8 *in)
105106
} else return sdmmc_nand_writesectors(sector_no, numsectors, in);
106107
}
107108

109+
u32 SetupNandCrypto(u8* ctr, u32 offset)
110+
{
111+
static bool initial_setup_done = false;
112+
static u8 CtrNandCtr[16];
113+
//static u8 TwlNandCtr[16];
114+
115+
if (!initial_setup_done) {
116+
// CTRNAND
117+
u8 NandCid[16];
118+
u8 shasum[32];
119+
120+
sdmmc_get_cid( 1, (uint32_t*) NandCid);
121+
sha_init(SHA256_MODE);
122+
sha_update(NandCid, 16);
123+
sha_get(shasum);
124+
memcpy(CtrNandCtr, shasum, 16);
125+
126+
/*sha_init(SHA1_MODE);
127+
sha_update(NandCid, 16);
128+
sha_get(shasum);
129+
for(u32 i = 0; i < 16; i++) // little endian and reversed order
130+
TwlNandCtr[i] = shasum[15-i];
131+
132+
Debug("NAND CID: %08X%08X%08X%08X", getbe32(NandCid), getbe32(NandCid+4), getbe32(NandCid+8), getbe32(NandCid+12));
133+
134+
// part #2: TWL KEY
135+
// see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM
136+
u32* TwlCustId = (u32*) (0x01FFB808+8);
137+
u8 TwlKeyX[16];
138+
u8 TwlKeyY[16];
139+
140+
Debug("TWL Customer ID: %08X%08X", TwlCustId[0], TwlCustId[1]);
141+
142+
// see source from https://gbatemp.net/threads/release-twltool-dsi-downgrading-save-injection-etc-multitool.393488/
143+
const char* nintendo = "NINTENDO";
144+
u32* TwlKeyXW = (u32*) TwlKeyX;
145+
TwlKeyXW[0] = (TwlCustId[0] ^ 0xB358A6AF) | 0x80000000;
146+
TwlKeyXW[3] = TwlCustId[1] ^ 0x08C267B7;
147+
memcpy(TwlKeyX + 4, nintendo, 8);
148+
149+
// see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM
150+
u32 TwlKeyYW3 = 0xE1A00005;
151+
memcpy(TwlKeyY, (u8*) 0x01FFD3C8, 12);
152+
memcpy(TwlKeyY + 12, &TwlKeyYW3, 4);
153+
154+
setup_aeskeyX(0x03, TwlKeyX);
155+
setup_aeskeyY(0x03, TwlKeyY);
156+
Debug("0x03 KeyX: %08X%08X%08X%08X", getbe32(TwlKeyX), getbe32(TwlKeyX+4), getbe32(TwlKeyX+8), getbe32(TwlKeyX+12));
157+
Debug("0x03 KeyY: %08X%08X%08X%08X", getbe32(TwlKeyY), getbe32(TwlKeyY+4), getbe32(TwlKeyY+8), getbe32(TwlKeyY+12));
158+
159+
// part #3: CTRNAND N3DS KEY
160+
while (GetUnitPlatform() == PLATFORM_N3DS) {
161+
u8 CtrNandKeyY[16];
162+
163+
if (!FileOpen("slot0x05KeyY.bin")) {
164+
Debug("0x05 KeyY: not set, slot0x05KeyY.bin not found");
165+
break;
166+
}
167+
if (FileRead(CtrNandKeyY, 16, 0) != 16) {
168+
Debug("0x05 KeyY: not set, bad file");
169+
FileClose();
170+
break;
171+
}
172+
FileClose();
173+
174+
setup_aeskeyY(0x05, CtrNandKeyY);
175+
Debug("0x05 KeyY: %08X%08X%08X%08X", getbe32(CtrNandKeyY), getbe32(CtrNandKeyY+4), getbe32(CtrNandKeyY+8), getbe32(CtrNandKeyY+12));
176+
break;
177+
}*/
178+
179+
initial_setup_done = true;
180+
}
181+
182+
// get the correct CTR and increment counter
183+
memcpy(ctr, CtrNandCtr, 16);
184+
add_ctr(ctr, offset / 0x10);
185+
186+
return 0;
187+
}
188+
108189
u32 OutputFileNameSelector(char* filename, const char* basename, char* extension, bool emuname) {
109190
char bases[3][64] = { 0 };
110191
char* dotpos = NULL;
@@ -404,7 +485,7 @@ u32 GetNandCtr(u8* ctr, u32 offset)
404485
u32 DecryptNandToMem(u8* buffer, u32 offset, u32 size, PartitionInfo* partition)
405486
{
406487
CryptBufferInfo info = {.keyslot = partition->keyslot, .setKeyY = 0, .size = size, .buffer = buffer, .mode = partition->mode};
407-
if(GetNandCtr(info.ctr, offset) != 0)
488+
if(SetupNandCrypto(info.ctr, offset) != 0)
408489
return 1;
409490

410491
u32 n_sectors = (size + NAND_SECTOR_SIZE - 1) / NAND_SECTOR_SIZE;
@@ -668,23 +749,23 @@ u32 DumpAgbSave(u32 parm)
668749
memcpy(&Saveadder, Header + (sizeof(u8) * 0x50), sizeof(u32));
669750
char *Magic = ".SAV";
670751
if (Saveadder != 0x200 || memcmp(Magic, Header, 4)) {
671-
Debug("The Agb_save partiton is corrupted.");
672-
Debug("Did you run an Agb_firm game?");
752+
Debug("The AGBSAVE partition is corrupted.");
753+
Debug("Did you run a GBA VC game?");
673754
return 1;
674755
}
675756
u32 Savesize;
676757
memcpy(&Savesize, Header + (sizeof(u8) * 0x54), sizeof(u32));
677758
u32 Titleid;
678759
memcpy(&Titleid, Header + 0x38, 4);
679-
Debug("Title id %08x", Titleid);
760+
Debug("Title ID: %08x", Titleid);
680761
if (Savesize == 32768) {
681-
Debug("Use save type 0");
762+
Debug("Use save type 0: SRAM");
682763
} else if (Savesize == 65536) {
683-
Debug("Use save type 1");
764+
Debug("Use save type 1: Flash");
684765
} else if (Savesize == 0x2000) {
685-
Debug("Use save type 2");
766+
Debug("Use save type 2: EEPROM");
686767
} else {
687-
Debug("Injecton support for this game is not yet ready");
768+
Debug("Injection support for this game is not yet ready");
688769
}
689770
if (Savesize == 0x2000) {
690771
u8* buffer = BUFFER_ADDRESS;

source/draw.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
#define TOP_SCREEN1 TOP_SCREEN0
4141
#define BOT_SCREEN1 BOT_SCREEN0
4242
#elif defined(EXEC_BOOTSTRAP)
43-
#define TOP_SCREEN0 (u8*)(0x20000000)
44-
#define TOP_SCREEN1 (u8*)(0x20046500)
45-
#define BOT_SCREEN0 (u8*)(0x2008CA00)
46-
#define BOT_SCREEN1 (u8*)(0x200C4E00)
43+
#define TOP_SCREEN0 (u8*)(*(u32*)0x23FFFE00)
44+
#define TOP_SCREEN1 (u8*)(*(u32*)0x23FFFE00)
45+
#define BOT_SCREEN0 (u8*)(*(u32*)0x23FFFE08)
46+
#define BOT_SCREEN1 (u8*)(*(u32*)0x23FFFE08)
4747
#else
4848
#error "Unknown execution method"
4949
#endif

source/fatfs/sdmmc.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,3 +618,45 @@ void sdmmc_sdcard_init()
618618
SD_Init();
619619
DEBUGPRINT(topScreen, "sd_res ", sd_res, 10, 20 + 4*8, RGB(40, 40, 40), RGB(208, 208, 208));
620620
}
621+
622+
int sdmmc_get_cid( int isNand, uint32_t *info)
623+
{
624+
struct mmcdevice *device;
625+
if(isNand)
626+
device = &handelNAND;
627+
else
628+
device = &handelSD;
629+
630+
inittarget(device);
631+
// use cmd7 to put sd card in standby mode
632+
// CMD7
633+
{
634+
sdmmc_send_command(device,0x10507,0);
635+
//if((device->error & 0x4)) return -1;
636+
}
637+
638+
// get sd card info
639+
// use cmd10 to read CID
640+
{
641+
sdmmc_send_command(device,0x1060A,device->initarg << 0x10);
642+
//if((device->error & 0x4)) return -2;
643+
644+
for( int i = 0; i < 4; ++i ) {
645+
info[i] = device->ret[i];
646+
}
647+
}
648+
649+
// put sd card back to transfer mode
650+
// CMD7
651+
{
652+
sdmmc_send_command(device,0x10507,device->initarg << 0x10);
653+
//if((device->error & 0x4)) return -3;
654+
}
655+
656+
if(isNand)
657+
{
658+
inittarget(&handelSD);
659+
}
660+
661+
return 0;
662+
}

source/fatfs/sdmmc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ extern "C" {
130130

131131
int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
132132
int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
133+
134+
int sdmmc_get_cid( int isNand, uint32_t *info);
133135

134136
mmcdevice *getMMCDevice(int drive);
135137

0 commit comments

Comments
 (0)