mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-12-23 09:02:06 +00:00
Update to v1.1.12.
This commit is contained in:
parent
4932283d81
commit
fc76571bc0
8 changed files with 58 additions and 34 deletions
2
Makefile
2
Makefile
|
@ -33,7 +33,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
|||
|
||||
VERSION_MAJOR := 1
|
||||
VERSION_MINOR := 1
|
||||
VERSION_MICRO := 11
|
||||
VERSION_MICRO := 12
|
||||
|
||||
APP_TITLE := nxdumptool
|
||||
APP_AUTHOR := DarkMatterCore
|
||||
|
|
|
@ -71,6 +71,12 @@ Thanks to
|
|||
Changelog
|
||||
--------------
|
||||
|
||||
**v1.1.12:**
|
||||
|
||||
* Fixed RomFS dumping/browsing support for games with base Program NCAs without a RomFS section (e.g. Fortnite, World of Tanks Blitz, etc.). Big thanks to [bigkahuna666](https://github.com/bigkahuna666) for reporting the issue and providing with testing.
|
||||
|
||||
This is only a bugfix release. I don't expect to release any new versions until the rewrite is finished - the only exception being fixing some kind of feature-breaking bug. Please understand.
|
||||
|
||||
**v1.1.11:**
|
||||
|
||||
* Built using libnx `f01fb21`.
|
||||
|
|
|
@ -4641,7 +4641,7 @@ bool dumpRomFsSectionData(u32 titleIndex, selectedRomFsType curRomFsType, ncaFsO
|
|||
}
|
||||
|
||||
// Retrieve RomFS from Program NCA
|
||||
if (!readNcaRomFsSection(titleIndex, curRomFsType, -1))
|
||||
if (readNcaRomFsSection(titleIndex, curRomFsType, -1) != 0)
|
||||
{
|
||||
free(dumpName);
|
||||
breaks += 2;
|
||||
|
|
47
source/nca.c
47
source/nca.c
|
@ -596,7 +596,7 @@ bool bktrSectionPhysicalRead(void *outBuf, size_t bufSize)
|
|||
|
||||
bool readBktrSectionBlock(u64 offset, void *outBuf, size_t bufSize)
|
||||
{
|
||||
if (!bktrContext.section_offset || !bktrContext.section_size || !bktrContext.relocation_block || !bktrContext.subsection_block || !romFsContext.section_offset || !romFsContext.section_size || !outBuf || !bufSize)
|
||||
if (!bktrContext.section_offset || !bktrContext.section_size || !bktrContext.relocation_block || (bktrContext.use_base_romfs && (!bktrContext.subsection_block || !romFsContext.section_offset || !romFsContext.section_size || !outBuf || !bufSize)))
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid parameters to read block from NCA BKTR section!", __func__);
|
||||
return false;
|
||||
|
@ -622,6 +622,13 @@ bool readBktrSectionBlock(u64 offset, void *outBuf, size_t bufSize)
|
|||
{
|
||||
if (!bktrSectionPhysicalRead(outBuf, bufSize)) return false;
|
||||
} else {
|
||||
if (!bktrContext.use_base_romfs)
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: BKTR references unexistant base RomFS block(s)!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nice and easy read from the base RomFS
|
||||
if (!processNcaCtrSectionBlock(&(romFsContext.ncmStorage), &(romFsContext.ncaId), &(romFsContext.aes_ctx), romFsContext.section_offset + bktrContext.base_seek, outBuf, bufSize, false)) return false;
|
||||
}
|
||||
|
@ -1686,12 +1693,12 @@ bool parseExeFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
return true;
|
||||
}
|
||||
|
||||
bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys)
|
||||
int parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys)
|
||||
{
|
||||
if (!ncmStorage || !ncaId || !dec_nca_header || !decrypted_nca_keys)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid parameters to read RomFS section from NCA!", __func__);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
u8 romfs_index;
|
||||
|
@ -1733,7 +1740,7 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
if (!found_romfs)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: NCA doesn't hold a RomFS section!", __func__);
|
||||
return false;
|
||||
return -2;
|
||||
}
|
||||
|
||||
section_offset = ((u64)dec_nca_header->section_entries[romfs_index].media_start_offset * (u64)MEDIA_UNIT_SIZE);
|
||||
|
@ -1742,7 +1749,7 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
if (!section_offset || section_offset < NCA_FULL_HEADER_LENGTH || !section_size)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid offset/size for NCA RomFS section! (#%u)", __func__, romfs_index);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Generate initial CTR
|
||||
|
@ -1763,13 +1770,13 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
if (__builtin_bswap32(dec_nca_header->fs_headers[romfs_index].romfs_superblock.ivfc_header.magic) != IVFC_MAGIC)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid IVFC magic word for NCA RomFS section! Wrong KAEK? (0x%08X)\nTry running Lockpick_RCM to generate the keys file from scratch.", __func__, __builtin_bswap32(dec_nca_header->fs_headers[romfs_index].romfs_superblock.ivfc_header.magic));
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dec_nca_header->fs_headers[romfs_index].crypt_type != NCA_FS_HEADER_CRYPT_CTR)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid AES crypt type for NCA RomFS section! (0x%02X)", __func__, dec_nca_header->fs_headers[romfs_index].crypt_type);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
romfs_offset = (section_offset + dec_nca_header->fs_headers[romfs_index].romfs_superblock.ivfc_header.level_headers[IVFC_MAX_LEVEL - 1].logical_offset);
|
||||
|
@ -1778,7 +1785,7 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
if (romfs_offset < section_offset || romfs_offset >= (section_offset + section_size) || romfs_size < ROMFS_HEADER_SIZE || (romfs_offset + romfs_size) > (section_offset + section_size))
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid offset/size for NCA RomFS section!", __func__);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// First read the RomFS header
|
||||
|
@ -1786,13 +1793,13 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read NCA RomFS section header!", __func__);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (romFsHeader.headerSize != ROMFS_HEADER_SIZE)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid header size for NCA RomFS section! (0x%016lX at 0x%016lX)", __func__, romFsHeader.headerSize, romfs_offset);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
romfs_dirtable_offset = (romfs_offset + romFsHeader.dirTableOff);
|
||||
|
@ -1804,7 +1811,7 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
if (romfs_dirtable_offset >= (section_offset + section_size) || !romfs_dirtable_size || (romfs_dirtable_offset + romfs_dirtable_size) > (section_offset + section_size) || romfs_filetable_offset >= (section_offset + section_size) || !romfs_filetable_size || (romfs_filetable_offset + romfs_filetable_size) > (section_offset + section_size))
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid directory/file table for NCA RomFS section!", __func__);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
romfs_filedata_offset = (romfs_offset + romFsHeader.fileDataOff);
|
||||
|
@ -1812,14 +1819,14 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
if (romfs_filedata_offset >= (section_offset + section_size))
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid file data block offset for NCA RomFS section!", __func__);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
romfs_dir_entries = calloc(1, romfs_dirtable_size);
|
||||
if (!romfs_dir_entries)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for NCA RomFS section directory entries!", __func__);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, romfs_dirtable_offset, romfs_dir_entries, romfs_dirtable_size, false))
|
||||
|
@ -1827,7 +1834,7 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read NCA RomFS section directory entries!", __func__);
|
||||
free(romfs_dir_entries);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
romfs_file_entries = calloc(1, romfs_filetable_size);
|
||||
|
@ -1835,7 +1842,7 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for NCA RomFS section file entries!", __func__);
|
||||
free(romfs_dir_entries);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, romfs_filetable_offset, romfs_file_entries, romfs_filetable_size, false))
|
||||
|
@ -1844,7 +1851,7 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read NCA RomFS section file entries!", __func__);
|
||||
free(romfs_file_entries);
|
||||
free(romfs_dir_entries);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Save data to output struct
|
||||
|
@ -1864,12 +1871,12 @@ bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *n
|
|||
romFsContext.romfs_file_entries = romfs_file_entries;
|
||||
romFsContext.romfs_filedata_offset = romfs_filedata_offset;
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool parseBktrEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys)
|
||||
{
|
||||
if (!ncmStorage || !ncaId || !dec_nca_header || !decrypted_nca_keys || !romFsContext.section_offset || !romFsContext.section_size || !romFsContext.romfs_dir_entries || !romFsContext.romfs_file_entries)
|
||||
if (!ncmStorage || !ncaId || !dec_nca_header || !decrypted_nca_keys || (bktrContext.use_base_romfs && (!romFsContext.section_offset || !romFsContext.section_size || !romFsContext.romfs_dir_entries || !romFsContext.romfs_file_entries)))
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid parameters to read BKTR section from NCA!", __func__);
|
||||
return false;
|
||||
|
@ -2941,7 +2948,7 @@ bool retrieveNacpDataFromNca(NcmContentStorage *ncmStorage, const NcmContentId *
|
|||
|
||||
bool availableSGC = false, availableRGC = false;
|
||||
|
||||
if (!parseRomFsEntryFromNca(ncmStorage, ncaId, dec_nca_header, decrypted_nca_keys)) return false;
|
||||
if (parseRomFsEntryFromNca(ncmStorage, ncaId, dec_nca_header, decrypted_nca_keys) != 0) return false;
|
||||
|
||||
// Look for the control.nacp file
|
||||
while(entryOffset < romFsContext.romfs_filetable_size)
|
||||
|
@ -3413,7 +3420,7 @@ bool retrieveLegalInfoXmlFromNca(NcmContentStorage *ncmStorage, const NcmContent
|
|||
u64 legalInfoXmlSize = 0;
|
||||
char *legalInfoXml = NULL;
|
||||
|
||||
if (!parseRomFsEntryFromNca(ncmStorage, ncaId, dec_nca_header, decrypted_nca_keys)) return false;
|
||||
if (parseRomFsEntryFromNca(ncmStorage, ncaId, dec_nca_header, decrypted_nca_keys) != 0) return false;
|
||||
|
||||
// Look for the legalinfo.xml file
|
||||
while(entryOffset < romFsContext.romfs_filetable_size)
|
||||
|
|
|
@ -448,6 +448,7 @@ typedef struct {
|
|||
u64 romfs_filetable_size;
|
||||
romfs_file *romfs_file_entries;
|
||||
u64 romfs_filedata_offset; // Relative to section start
|
||||
bool use_base_romfs;
|
||||
} bktr_ctx_t;
|
||||
|
||||
// Used in HFS0 / ExeFS / RomFS browsers
|
||||
|
@ -748,7 +749,7 @@ bool patchCnmtNca(u8 *ncaBuf, u64 ncaBufSize, cnmt_xml_program_info *xml_program
|
|||
|
||||
bool parseExeFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
|
||||
|
||||
bool parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
|
||||
int parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
|
||||
|
||||
bool parseBktrEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
|
||||
|
||||
|
|
|
@ -5035,7 +5035,7 @@ UIResult uiProcess()
|
|||
|
||||
bool romfs_fail = false;
|
||||
|
||||
if (readNcaRomFsSection(curIndex, curRomFsType, -1))
|
||||
if (readNcaRomFsSection(curIndex, curRomFsType, -1) == 0)
|
||||
{
|
||||
if (getRomFsFileList(0, (curRomFsType == ROMFS_TYPE_PATCH)))
|
||||
{
|
||||
|
|
|
@ -669,6 +669,8 @@ void freeBktrContext()
|
|||
free(bktrContext.romfs_file_entries);
|
||||
bktrContext.romfs_file_entries = NULL;
|
||||
}
|
||||
|
||||
bktrContext.use_base_romfs = false;
|
||||
}
|
||||
|
||||
static void freeGameCardInfo()
|
||||
|
@ -2727,7 +2729,7 @@ out:
|
|||
return success;
|
||||
}
|
||||
|
||||
bool readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int desiredIdOffset)
|
||||
int readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int desiredIdOffset)
|
||||
{
|
||||
u32 i = 0;
|
||||
Result result;
|
||||
|
@ -2755,7 +2757,7 @@ bool readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int des
|
|||
|
||||
u8 decrypted_nca_keys[NCA_KEY_AREA_SIZE];
|
||||
|
||||
bool success = false;
|
||||
int ret = -1;
|
||||
|
||||
if (curRomFsType != ROMFS_TYPE_APP && curRomFsType != ROMFS_TYPE_PATCH && curRomFsType != ROMFS_TYPE_ADDON)
|
||||
{
|
||||
|
@ -2879,8 +2881,8 @@ bool readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int des
|
|||
if (curRomFsType != ROMFS_TYPE_PATCH)
|
||||
{
|
||||
// Read directory and file tables from the RomFS section
|
||||
success = parseRomFsEntryFromNca(&ncmStorage, &ncaId, &dec_nca_header, decrypted_nca_keys);
|
||||
if (success)
|
||||
ret = parseRomFsEntryFromNca(&ncmStorage, &ncaId, &dec_nca_header, decrypted_nca_keys);
|
||||
if (ret == 0)
|
||||
{
|
||||
romFsContext.storageId = curStorageId;
|
||||
romFsContext.idOffset = titleContentInfos[contentIndex].id_offset;
|
||||
|
@ -2905,11 +2907,19 @@ bool readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int des
|
|||
}
|
||||
|
||||
// Read directory and file tables from the RomFS section in the Program NCA from the base application
|
||||
if (!readNcaRomFsSection(appIndex, ROMFS_TYPE_APP, (int)titleContentInfos[contentIndex].id_offset)) goto out;
|
||||
// We'll proceed even if the Program NCA from the base application doesn't hold a RomFS section (ret == -2)
|
||||
ret = readNcaRomFsSection(appIndex, ROMFS_TYPE_APP, (int)titleContentInfos[contentIndex].id_offset);
|
||||
if (ret == -1) goto out;
|
||||
|
||||
// Remove missing base RomFS error message if needed
|
||||
if (ret == -2) uiFill(0, STRING_Y_POS(breaks), FB_WIDTH, FB_HEIGHT - STRING_Y_POS(breaks), BG_COLOR_RGB);
|
||||
|
||||
// Update BKTR context to use the base RomFS if available
|
||||
bktrContext.use_base_romfs = (ret == 0);
|
||||
|
||||
// Read BKTR entry data in the Program NCA from the update
|
||||
success = parseBktrEntryFromNca(&ncmStorage, &ncaId, &dec_nca_header, decrypted_nca_keys);
|
||||
if (success)
|
||||
ret = (parseBktrEntryFromNca(&ncmStorage, &ncaId, &dec_nca_header, decrypted_nca_keys) ? 0 : -1);
|
||||
if (ret == 0)
|
||||
{
|
||||
bktrContext.storageId = curStorageId;
|
||||
bktrContext.idOffset = titleContentInfos[contentIndex].id_offset;
|
||||
|
@ -2917,7 +2927,7 @@ bool readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int des
|
|||
}
|
||||
|
||||
out:
|
||||
if (!success)
|
||||
if (ret != 0)
|
||||
{
|
||||
ncmContentStorageClose(&ncmStorage);
|
||||
if (curStorageId == NcmStorageId_GameCard) closeGameCardStoragePartition();
|
||||
|
@ -2925,7 +2935,7 @@ out:
|
|||
|
||||
if (titleContentInfos) free(titleContentInfos);
|
||||
|
||||
return success;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool getExeFsFileList()
|
||||
|
|
|
@ -388,7 +388,7 @@ void removeConsoleDataFromTicket(title_rights_ctx *rights_info);
|
|||
|
||||
bool readNcaExeFsSection(u32 titleIndex, bool usePatch);
|
||||
|
||||
bool readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int desiredIdOffset);
|
||||
int readNcaRomFsSection(u32 titleIndex, selectedRomFsType curRomFsType, int desiredIdOffset);
|
||||
|
||||
bool getExeFsFileList();
|
||||
|
||||
|
|
Loading…
Reference in a new issue