ROMs with Overlays are now supported!

This commit is contained in:
Luca D'Amico 2024-08-11 19:23:15 +02:00
parent 921eef86e2
commit e788d95289
5 changed files with 155 additions and 147 deletions

View File

@ -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 :)

View File

@ -1,6 +1,6 @@
#ifndef REVISION_H
#define REVISION_H
#define GIT_COMMIT_HASH "d69e4e1"
#define GIT_COMMIT_HASH "921eef8"
#endif

View File

@ -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,

View File

@ -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<char> romHeaderBuffer(sizeof(NDSHeader));
NDSHeader* pRomHeader = reinterpret_cast<NDSHeader*>(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<char> romHeaderBuffer(sizeof(NDSHeader));
NDSHeader* pRomHeader = reinterpret_cast<NDSHeader*>(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<char>('\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())

View File

@ -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)