mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 16:59:04 +00:00
225 lines
6.2 KiB
C
225 lines
6.2 KiB
C
#include "lib.h"
|
|
#include "ncch_read.h"
|
|
#include "ncsd_build.h"
|
|
#include "cardinfo.h"
|
|
|
|
void InitCardInfoHdr(cardinfo_hdr **cihdr, devcardinfo_hdr **dcihdr, cci_settings *set);
|
|
int SetWriteableAddress(cardinfo_hdr *hdr, cci_settings *set);
|
|
int SetCardInfoBitmask(cardinfo_hdr *hdr, cci_settings *set);
|
|
int SetCardInfoNotes(cardinfo_hdr *hdr, cci_settings *set);
|
|
void SetNcchHeader(cardinfo_hdr *hdr, cci_settings *set);
|
|
void SetCardSeedData(cardinfo_hdr *hdr, cci_settings *set);
|
|
void SetDevCardInfo(devcardinfo_hdr *hdr, cci_settings *set);
|
|
|
|
|
|
int GenCardInfoHdr(cci_settings *set)
|
|
{
|
|
cardinfo_hdr *cihdr;
|
|
devcardinfo_hdr *dcihdr;
|
|
|
|
InitCardInfoHdr(&cihdr,&dcihdr,set);
|
|
|
|
if(SetWriteableAddress(cihdr,set))
|
|
return GEN_HDR_FAIL;
|
|
if(SetCardInfoBitmask(cihdr,set))
|
|
return GEN_HDR_FAIL;
|
|
if(SetCardInfoNotes(cihdr,set))
|
|
return GEN_HDR_FAIL;
|
|
SetNcchHeader(cihdr,set);
|
|
SetCardSeedData(cihdr,set);
|
|
|
|
if(dcihdr)
|
|
SetDevCardInfo(dcihdr,set);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void InitCardInfoHdr(cardinfo_hdr **cihdr, devcardinfo_hdr **dcihdr, cci_settings *set)
|
|
{
|
|
set->headers.cardinfohdr.size = sizeof(cardinfo_hdr);
|
|
if(set->options.useExternalSdkCardInfo)
|
|
set->headers.cardinfohdr.size += sizeof(devcardinfo_hdr);
|
|
|
|
set->headers.cardinfohdr.buffer = calloc(1,set->headers.cardinfohdr.size);
|
|
|
|
*cihdr = (cardinfo_hdr*)set->headers.cardinfohdr.buffer;
|
|
|
|
if(set->headers.cardinfohdr.size > sizeof(cardinfo_hdr))
|
|
*dcihdr = (devcardinfo_hdr*)(set->headers.cardinfohdr.buffer+sizeof(cardinfo_hdr));
|
|
else
|
|
*dcihdr = NULL;
|
|
|
|
//clrmem(set->headers.cardinfohdr.buffer, set->headers.cardinfohdr.size);
|
|
|
|
return;
|
|
}
|
|
|
|
u64 GetCciUnusedSize(u64 mediaSize, u8 cardType)
|
|
{
|
|
if(cardType == mediatype_CARD1){
|
|
switch(mediaSize){
|
|
case (u64)MB*128: return (u64)2621440;
|
|
case (u64)MB*256: return (u64)5242880;
|
|
case (u64)MB*512: return (u64)10485760;
|
|
case (u64)GB*1: return (u64)73924608;
|
|
case (u64)GB*2: return (u64)147324928;
|
|
case (u64)GB*4: return (u64)294649856;
|
|
case (u64)GB*8: return (u64)587202560;
|
|
default: return 0;
|
|
}
|
|
}
|
|
else if(cardType == mediatype_CARD2){
|
|
switch(mediaSize){
|
|
case (u64)MB*512: return (u64)37224448;
|
|
case (u64)GB*1: return (u64)73924608;
|
|
case (u64)GB*2: return (u64)147324928;
|
|
case (u64)GB*4: return (u64)294649856;
|
|
case (u64)GB*8: return (u64)587202560;
|
|
default: return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int SetWriteableAddress(cardinfo_hdr *hdr, cci_settings *set)
|
|
{
|
|
if(set->romInfo.mediaType != mediatype_CARD2){ // Can only be set for Card2 Media
|
|
u32_to_u8(hdr->writableAddress,(u32)-1,LE);
|
|
return 0;
|
|
}
|
|
|
|
char *str = set->rsf->CardInfo.WritableAddress;
|
|
set->romInfo.card2SaveOffset = -1;
|
|
|
|
if(str){
|
|
if(strncmp(str,"0x",2) != 0){
|
|
fprintf(stderr,"[CCI ERROR] WritableAddress requires a Hexadecimal value\n");
|
|
return INVALID_RSF_OPT;
|
|
}
|
|
set->romInfo.card2SaveOffset = strtoull(str,NULL,16);
|
|
}
|
|
else{
|
|
if ((set->romInfo.mediaSize / 2) < set->romInfo.saveSize || set->romInfo.saveSize > (u64)(2047*MB)){
|
|
u64 saveDataSize = set->romInfo.saveSize / KB;
|
|
fprintf(stderr,"[CCI ERROR] Too large SavedataSize %"PRIu64"K\n",saveDataSize);
|
|
return SAVE_DATA_TOO_LARGE;
|
|
}
|
|
if(set->options.closeAlignWR)
|
|
set->romInfo.card2SaveOffset = align(set->romInfo.usedSize, set->romInfo.blockSize); // invalid for "real" chips
|
|
else{
|
|
u64 unusedSize = GetCciUnusedSize(set->romInfo.mediaSize,set->romInfo.mediaType); // Some value related to the physical implementation of gamecards
|
|
if(unusedSize > 0)
|
|
set->romInfo.card2SaveOffset = set->romInfo.mediaSize - unusedSize - set->romInfo.saveSize; // Nintendo's method for calculating writable region offset
|
|
else{
|
|
fprintf(stderr,"[CCI WARNING] Nintendo does not support CARD2 for the current MediaSize, aligning save offset after last NCCH\n");
|
|
set->romInfo.card2SaveOffset = align(set->romInfo.usedSize, set->romInfo.blockSize); // invalid for "real" chips
|
|
}
|
|
}
|
|
}
|
|
|
|
u32_to_u8(hdr->writableAddress,(u32)(set->romInfo.card2SaveOffset/set->romInfo.blockSize),LE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SetCardInfoBitmask(cardinfo_hdr *hdr, cci_settings *set)
|
|
{
|
|
u32 bitmask = 0;
|
|
|
|
char *str = set->rsf->CardInfo.CardType;
|
|
if(!str)
|
|
bitmask |= 0;
|
|
else{
|
|
if(strcasecmp(str,"s1") == 0)
|
|
bitmask |= 0;
|
|
else if(strcasecmp(str,"s2") == 0)
|
|
bitmask |= 0x20;
|
|
else {
|
|
fprintf(stderr,"[CCI ERROR] Invalid CardType: %s\n",str);
|
|
return INVALID_RSF_OPT;
|
|
}
|
|
}
|
|
|
|
str = set->rsf->CardInfo.CryptoType;
|
|
if(!str) {
|
|
if(set->options.useExternalSdkCardInfo)
|
|
bitmask |= (3*0x40);
|
|
else
|
|
bitmask |= 0;
|
|
}
|
|
else{
|
|
int val = strtol(str,NULL,10);
|
|
if(val < 0 || val > 3) {
|
|
fprintf(stderr,"[CCI ERROR] Invalid CryptoType: %s\n",str);
|
|
return INVALID_RSF_OPT;
|
|
}
|
|
if(val != 3)
|
|
fprintf(stderr,"[CCI WARNING] Card crypto type = '%d'\n",val);
|
|
bitmask |= val * 0x40;
|
|
}
|
|
|
|
u32_to_u8(hdr->cardInfoBitmask,bitmask,BE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SetCardInfoNotes(cardinfo_hdr *hdr, cci_settings *set)
|
|
{
|
|
u64_to_u8(hdr->notes.mediaSizeUsed,set->romInfo.usedSize,LE);
|
|
u32_to_u8(hdr->notes.unknown,0,LE);
|
|
|
|
if(set->options.tmdHdr){
|
|
u64_to_u8(hdr->notes.cverTitleId,GetTmdTitleId(set->options.tmdHdr),LE);
|
|
u16_to_u8(hdr->notes.cverTitleId,GetTmdVersion(set->options.tmdHdr),LE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SetNcchHeader(cardinfo_hdr *hdr, cci_settings *set)
|
|
{
|
|
u8 *ncch;
|
|
ncch_hdr *ncchHdr;
|
|
|
|
ncch = set->content.data + set->content.dOffset[0];
|
|
ncchHdr = (ncch_hdr*)ncch;
|
|
|
|
memcpy(hdr->ncch0Hdr,GetNcchHdrData(ncchHdr),GetNcchHdrDataLen(ncchHdr));
|
|
|
|
return;
|
|
}
|
|
|
|
void SetCardSeedData(cardinfo_hdr *hdr, cci_settings *set)
|
|
{
|
|
u8 *ncch;
|
|
ncch_hdr *ncchHdr;
|
|
|
|
ncch = set->content.data + set->content.dOffset[0];
|
|
ncchHdr = (ncch_hdr*)ncch;
|
|
|
|
if (set->options.useExternalSdkCardInfo) {
|
|
memcpy(hdr->cardSeedKeyY, ncchHdr->titleId, 8);
|
|
clrmem(hdr->encCardSeed, 0x10);
|
|
memcpy(hdr->cardSeedMac, stock_card_seed_mac, 0x10);
|
|
clrmem(hdr->cardSeedNonce, 0xC);
|
|
}
|
|
else {
|
|
memcpy(hdr->cardSeedKeyY, ncchHdr->titleId, 8);
|
|
rndset(hdr->encCardSeed, 0x10);
|
|
rndset(hdr->cardSeedMac, 0x10);
|
|
rndset(hdr->cardSeedNonce, 0xC);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void SetDevCardInfo(devcardinfo_hdr *hdr, cci_settings *set)
|
|
{
|
|
clrmem(hdr,sizeof(devcardinfo_hdr));
|
|
if(set->options.useExternalSdkCardInfo)
|
|
memcpy(hdr->titleKey,(u8*)stock_title_key,0x10);
|
|
else
|
|
rndset(hdr->titleKey,0x10);
|
|
|
|
return;
|
|
} |