diff --git a/README.md b/README.md index 72cedb9..8da9039 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,6 @@ If you find this software useful, please consider supporting it: ![screenshot](https://raw.githubusercontent.com/Luca1991/NDSFactory/master/screenshot.png) -**!!!ROMS WITH OVERLAY ARE CURRENTLY NOT SUPPORTED!!!** - # Description NDSFactory helps you easily unpack and repack Nintendo DS ROMs, but **some technical knowledge is required.** @@ -19,11 +17,13 @@ NDSFactory helps you easily unpack and repack Nintendo DS ROMs, but **some techn A typical NDS ROM consists of the following sections: * Header * ARM9 Binary +* ARM9 Overlay (Optional) +* ARM9 Overlay Files (Optional) * ARM7 Binary +* ARM7 Overlay (Optional) +* ARM7 Overlay Files (Optional) * FNT (Filename Table) * FAT (File Allocation Table) -* ARM9/ARM7 Overlay (Optional) -* ARM9/ARM7 Overlay Files (Optional) * Icon/Title Logo * FAT Files (The actual files used by the software, like Graphics, Music etc.) @@ -48,7 +48,6 @@ In this tab, you can: # Known Limitations/Possible Future Features/Bugs -* Add support for ROMs with overlays. * Add support to rebuild a new fat_data.bin and fat.bin from a set of files inside a directory. If you find a bug, feel free to open an issue or submit a pull request :) diff --git a/ui/dialogs/about/revision.h b/ui/dialogs/about/revision.h index 4888de2..a06ace5 100644 --- a/ui/dialogs/about/revision.h +++ b/ui/dialogs/about/revision.h @@ -1,6 +1,6 @@ #ifndef REVISION_H #define REVISION_H -#define GIT_COMMIT_HASH "d69e4e1" +#define GIT_COMMIT_HASH "921eef8" #endif diff --git a/ui/mainwindow.h b/ui/mainwindow.h index 6bf915e..47bac5c 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -103,13 +103,8 @@ private: bool writeArm7BinPadding(char paddingByte, const std::string& savePath); bool writeFntPadding(char paddingByte, const std::string& savePath); bool writeFatPadding(char paddingByte, const std::string& savePath); - bool writeArm9OverlayPadding(char paddingByte, const std::string& savePath); - bool writeArm9OverlayFilesPadding(char paddingByte, const std::string& savePath); - bool writeArm7OverlayPadding(char paddingByte, const std::string& savePath); - bool writeArm7OverlayFilesPadding(char paddingByte, const std::string& savePath); bool writeRomPadding(const std::string& savePath); - //QString extractUnpackerHeaderTableData(int index); QString extractPackerHeaderTableData(int index); bool extractFatData(const std::string& fatDataSectionPath, const std::string& fatSectionPath, diff --git a/ui/tabs/packer/packertabfunctions.cpp b/ui/tabs/packer/packertabfunctions.cpp index 2099d68..9ff9202 100644 --- a/ui/tabs/packer/packertabfunctions.cpp +++ b/ui/tabs/packer/packertabfunctions.cpp @@ -91,6 +91,16 @@ void MainWindow::generateHeader(NDSHeader* pRomHeader) std::fill(std::begin(pRomHeader->Reserved4), std::end(pRomHeader->Reserved4), 0); } +void MainWindow::calcHeaderCrc16() +{ + std::vector romHeaderBuffer(sizeof(NDSHeader)); + NDSHeader* pRomHeader = reinterpret_cast(romHeaderBuffer.data()); + + generateHeader(pRomHeader); + + QModelIndex headerCrcIndex = ui->packerHeaderDataTable->model()->index(NDSHeaderNames::HeaderCRC, 1); + ui->packerHeaderDataTable->model()->setData(headerCrcIndex, QString::number(ndsFactory.calcHeaderCrc16(romHeaderBuffer), 16), Qt::EditRole); +} bool MainWindow::writeHeader(const std::string& savePath) { @@ -102,15 +112,16 @@ bool MainWindow::writeHeader(const std::string& savePath) return ndsFactory.writeBytesToFile(romHeaderBuffer, savePath, 0, sizeof(NDSHeader));; } -void MainWindow::calcHeaderCrc16() +bool MainWindow::writeHeaderPadding(char paddingType, const std::string& savePath) { - std::vector romHeaderBuffer(sizeof(NDSHeader)); - NDSHeader* pRomHeader = reinterpret_cast(romHeaderBuffer.data()); + uint32_t startAddr = sizeof(NDSHeader); + uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::ARM9RomAddress).toUInt(nullptr, 16) - startAddr; - generateHeader(pRomHeader); - - QModelIndex headerCrcIndex = ui->packerHeaderDataTable->model()->index(NDSHeaderNames::HeaderCRC, 1); - ui->packerHeaderDataTable->model()->setData(headerCrcIndex, QString::number(ndsFactory.calcHeaderCrc16(romHeaderBuffer), 16), Qt::EditRole); + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); } bool MainWindow::writeArm9Bin(const std::string& savePath, bool isArm9FooterPresent) @@ -125,6 +136,48 @@ bool MainWindow::writeArm9Bin(const std::string& savePath, bool isArm9FooterPres size); } + +bool MainWindow::writeArm9BinPadding(char paddingType, const std::string& savePath, bool isFooterPresent) +{ + uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9RomAddress).toUInt(nullptr, 16) + + extractPackerHeaderTableData(NDSHeaderNames::ARM9Size).toUInt(nullptr, 16); + uint32_t size; + if (extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16) != 0) + size = extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16) - startAddr; + else + size = extractPackerHeaderTableData(NDSHeaderNames::ARM7RomAddress).toUInt(nullptr, 16) - startAddr; + + if (isFooterPresent) + size -= Arm9FooterSize; + + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); +} + +bool MainWindow::writeArm9Overlay(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedArm9OverlayPathEdt->text().toStdString(), + savePath, + extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16), + extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlaySize).toUInt(nullptr, 16)); +} + +bool MainWindow::writeArm9OverlayFiles(const std::string& savePath) +{ + uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16) + + extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlaySize).toUInt(nullptr, 16); + uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::ARM7RomAddress).toUInt(nullptr, 16) - startAddr; + return ndsFactory.writeSectionToFile( + ui->loadedArm9OverlayFilesPathEdt->text().toStdString(), + savePath, + startAddr, + size); +} + bool MainWindow::writeArm7Bin(const std::string& savePath) { return ndsFactory.writeSectionToFile( @@ -134,6 +187,44 @@ bool MainWindow::writeArm7Bin(const std::string& savePath) extractPackerHeaderTableData(NDSHeaderNames::ARM7Size).toUInt(nullptr, 16)); } +bool MainWindow::writeArm7BinPadding(char paddingType, const std::string& savePath) +{ + uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7RomAddress).toUInt(nullptr, 16) + + extractPackerHeaderTableData(NDSHeaderNames::ARM7Size).toUInt(nullptr, 16); + uint32_t size; + if (extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlayAddress).toUInt(nullptr, 16) != 0) + size = extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlayAddress).toUInt(nullptr, 16) - startAddr; + else + size = extractPackerHeaderTableData(NDSHeaderNames::FilenameTableAddress).toUInt(nullptr, 16) - startAddr; + + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); +} + +bool MainWindow::writeArm7Overlay(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedArm7OverlayPathEdt->text().toStdString(), + savePath, + extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlayAddress).toUInt(nullptr, 16), + extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlaySize).toUInt(nullptr, 16)); +} + +bool MainWindow::writeArm7OverlayFiles(const std::string& savePath) +{ + uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlayAddress).toUInt(nullptr, 16) + + extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlaySize).toUInt(nullptr, 16); + uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::FilenameTableAddress).toUInt(nullptr, 16) - startAddr; + return ndsFactory.writeSectionToFile( + ui->loadedArm7OverlayFilesPathEdt->text().toStdString(), + savePath, + startAddr, + size); +} + bool MainWindow::writeFnt(const std::string& savePath) { return ndsFactory.writeSectionToFile( @@ -143,6 +234,19 @@ bool MainWindow::writeFnt(const std::string& savePath) extractPackerHeaderTableData(NDSHeaderNames::FilenameTableSize).toUInt(nullptr, 16)); } +bool MainWindow::writeFntPadding(char paddingType, const std::string& savePath) +{ + uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::FilenameTableAddress).toUInt(nullptr, 16) + + extractPackerHeaderTableData(NDSHeaderNames::FilenameTableSize).toUInt(nullptr, 16); + uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::FATAddress).toUInt(nullptr, 16) - startAddr; + + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); +} + bool MainWindow::writeFat(const std::string& savePath) { return ndsFactory.writeSectionToFile( @@ -152,32 +256,17 @@ bool MainWindow::writeFat(const std::string& savePath) extractPackerHeaderTableData(NDSHeaderNames::FATSize).toUInt(nullptr, 16)); } -bool MainWindow::writeArm9Overlay(const std::string& savePath) +bool MainWindow::writeFatPadding(char paddingType, const std::string& savePath) { - return ndsFactory.writeSectionToFile( - ui->loadedArm9OverlayPathEdt->text().toStdString(), - savePath, - extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16), - extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlaySize).toUInt(nullptr, 16)); -} + uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::FATAddress).toUInt(nullptr, 16) + + extractPackerHeaderTableData(NDSHeaderNames::FATSize).toUInt(nullptr, 16); + uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::IconTitleAddress).toUInt(nullptr, 16) - startAddr; -bool MainWindow::writeArm9OverlayFiles([[maybe_unused]] const std::string& savePath) -{ - return false; // TODO: implement me! -} - -bool MainWindow::writeArm7Overlay(const std::string& savePath) -{ - return ndsFactory.writeSectionToFile( - ui->loadedArm7OverlayPathEdt->text().toStdString(), - savePath, - extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16), - extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlaySize).toUInt(nullptr, 16)); -} - -bool MainWindow::writeArm7OverlayFiles([[maybe_unused]] const std::string& savePath) -{ - return false; // TODO: implement me! + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); } bool MainWindow::writeIconTitle(const std::string& savePath) @@ -201,94 +290,6 @@ bool MainWindow::writeFatFiles(const std::string& savePath) size); } -bool MainWindow::writeHeaderPadding(char paddingType, const std::string& savePath) -{ - uint32_t startAddr = sizeof(NDSHeader); - uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::ARM9RomAddress).toUInt(nullptr, 16) - startAddr; - - return ndsFactory.writePaddingToFile( - paddingType, - savePath, - startAddr, - size); -} - -bool MainWindow::writeArm9BinPadding(char paddingType, const std::string& savePath, bool isFooterPresent) -{ // FIXME check ARM9 Overlay - uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9RomAddress).toUInt(nullptr, 16) + - extractPackerHeaderTableData(NDSHeaderNames::ARM9Size).toUInt(nullptr, 16); - uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::ARM7RomAddress).toUInt(nullptr, 16) - startAddr; - - if (isFooterPresent) - size -= Arm9FooterSize; - - return ndsFactory.writePaddingToFile( - paddingType, - savePath, - startAddr, - size); -} - -bool MainWindow::writeArm7BinPadding(char paddingType, const std::string& savePath) -{ // FIXME check ARM7 Overlay - uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7RomAddress).toUInt(nullptr, 16) + - extractPackerHeaderTableData(NDSHeaderNames::ARM7Size).toUInt(nullptr, 16); - uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::FilenameTableAddress).toUInt(nullptr, 16) - startAddr; - - return ndsFactory.writePaddingToFile( - paddingType, - savePath, - startAddr, - size); -} - -bool MainWindow::writeFntPadding(char paddingType, const std::string& savePath) -{ - uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::FilenameTableAddress).toUInt(nullptr, 16) + - extractPackerHeaderTableData(NDSHeaderNames::FilenameTableSize).toUInt(nullptr, 16); - uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::FATAddress).toUInt(nullptr, 16) - startAddr; - - return ndsFactory.writePaddingToFile( - paddingType, - savePath, - startAddr, - size); -} - -bool MainWindow::writeFatPadding(char paddingType, const std::string& savePath) -{ - uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::FATAddress).toUInt(nullptr, 16) + - extractPackerHeaderTableData(NDSHeaderNames::FATSize).toUInt(nullptr, 16); - uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::IconTitleAddress).toUInt(nullptr, 16) - startAddr; - - return ndsFactory.writePaddingToFile( - paddingType, - savePath, - startAddr, - size); -} - -bool MainWindow::writeArm9OverlayPadding([[maybe_unused]] char paddingType, [[maybe_unused]] const std::string& savePath) -{ // FIXME TODO - return true; -} - -bool MainWindow::writeArm9OverlayFilesPadding([[maybe_unused]] char paddingType, [[maybe_unused]] const std::string& savePath) -{ // FIXME TODO - return true; -} - -bool MainWindow::writeArm7OverlayPadding([[maybe_unused]] char paddingType, [[maybe_unused]] const std::string& savePath) -{ // FIXME TODO - return true; -} - - -bool MainWindow::writeArm7OverlayFilesPadding([[maybe_unused]] char paddingType, [[maybe_unused]] const std::string& savePath) -{ // FIXME TODO - return true; -} - bool MainWindow::writeRomPadding(const std::string& savePath) { uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::UsedRomSize).toUInt(nullptr, 16); @@ -306,7 +307,7 @@ bool MainWindow::writeEverything(const std::string& savePath) bool res = true; char paddingType; bool isArm9FooterPresent = ndsFactory.checkArm9FooterPresence(ui->loadedArm9BinPathEdt->text().toStdString(), - extractPackerHeaderTableData(NDSHeaderNames::ARM9Size).toUInt(nullptr, 16)); + extractPackerHeaderTableData(NDSHeaderNames::ARM9Size).toUInt(nullptr, 16)); if (ui->packerPadType00RdBtn->isChecked()) paddingType = static_cast('\x00'); else @@ -318,24 +319,21 @@ bool MainWindow::writeEverything(const std::string& savePath) res &= writeHeaderPadding(paddingType, savePath); res &= writeArm9Bin(savePath, isArm9FooterPresent); res &= writeArm9BinPadding(paddingType, savePath, isArm9FooterPresent); + if (extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16) != 0) + { + res &= writeArm9Overlay(savePath); + res &= writeArm9OverlayFiles(savePath); + } res &= writeArm7Bin(savePath); res &= writeArm7BinPadding(paddingType, savePath); + if (extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlayAddress).toUInt(nullptr, 16) != 0) { + res &= writeArm7Overlay(savePath); + res &= writeArm7OverlayFiles(savePath); + } res &= writeFnt(savePath); res &= writeFntPadding(paddingType, savePath); res &= writeFat(savePath); res &= writeFatPadding(paddingType, savePath); - if(extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16) != 0) { - res &= writeArm9Overlay(savePath); - res &= writeArm9OverlayPadding(paddingType, savePath); - res &= writeArm9OverlayFiles(savePath); - res &= writeArm9OverlayFilesPadding(paddingType, savePath); - } - if(extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16) != 0) { - res &= writeArm7Overlay(savePath); - res &= writeArm7OverlayPadding(paddingType, savePath); - res &= writeArm7OverlayFiles(savePath); - res &= writeArm7OverlayFilesPadding(paddingType, savePath); - } res &= writeIconTitle(savePath); res &= writeFatFiles(savePath); if(!ui->packerTrimRomsCbx->isChecked()) diff --git a/ui/tabs/unpacker/unpackertabfunctions.cpp b/ui/tabs/unpacker/unpackertabfunctions.cpp index b16c85e..c5f1c96 100644 --- a/ui/tabs/unpacker/unpackertabfunctions.cpp +++ b/ui/tabs/unpacker/unpackertabfunctions.cpp @@ -96,9 +96,17 @@ bool MainWindow::dumpArm9Overlay(const std::string& dirPath) ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9OverlaySize, 1).data().toString().toUInt(nullptr,16)); } -bool MainWindow::dumpArm9OverlayFiles([[maybe_unused]] const std::string& dirPath) +bool MainWindow::dumpArm9OverlayFiles(const std::string& dirPath) { - return false; // TODO: implement me! + uint32_t startAddr = ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9OverlayAddress, 1).data().toString().toUInt(nullptr, 16) + + ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9OverlaySize, 1).data().toString().toUInt(nullptr, 16); + uint32_t size = ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7RomAddress, 1).data().toString().toUInt(nullptr, 16) - startAddr; + + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + startAddr, + size); } bool MainWindow::dumpArm7Overlay(const std::string& dirPath) @@ -110,9 +118,17 @@ bool MainWindow::dumpArm7Overlay(const std::string& dirPath) ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7OverlaySize, 1).data().toString().toUInt(nullptr,16)); } -bool MainWindow::dumpArm7OverlayFiles([[maybe_unused]] const std::string& dirPath) +bool MainWindow::dumpArm7OverlayFiles(const std::string& dirPath) { - return false; // TODO: implement me! + uint32_t startAddr = ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7OverlayAddress, 1).data().toString().toUInt(nullptr, 16) + + ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7OverlaySize, 1).data().toString().toUInt(nullptr, 16); + uint32_t size = ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::FilenameTableAddress, 1).data().toString().toUInt(nullptr, 16) - startAddr; + + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + startAddr, + size); } bool MainWindow::dumpIconTitle(const std::string& dirPath)