diff --git a/NDSFactory.pro b/NDSFactory.pro new file mode 100644 index 0000000..f4196f6 --- /dev/null +++ b/NDSFactory.pro @@ -0,0 +1,53 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-08-29T12:15:45 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = NDSFactory +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +CONFIG += c++11 + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + ndsfactory.cpp \ + aboutdialog.cpp \ + unpackertabfunctions.cpp \ + unpackertabsignals.cpp \ + packertabsignals.cpp \ + packertabfunctions.cpp \ + fatpatchingtabsignals.cpp \ + fatpatchingtabfunctions.cpp + +HEADERS += \ + mainwindow.h \ + ndsheader.h \ + ndsfactory.h \ + aboutdialog.h \ + fatstruct.h + +FORMS += \ + mainwindow.ui \ + aboutdialog.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/aboutdialog.cpp b/aboutdialog.cpp new file mode 100644 index 0000000..a998580 --- /dev/null +++ b/aboutdialog.cpp @@ -0,0 +1,15 @@ +#include "aboutdialog.h" +#include "ui_aboutdialog.h" + + +AboutDialog::AboutDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AboutDialog) +{ + ui->setupUi(this); +} + +AboutDialog::~AboutDialog() +{ + delete ui; +} diff --git a/aboutdialog.h b/aboutdialog.h new file mode 100644 index 0000000..23df898 --- /dev/null +++ b/aboutdialog.h @@ -0,0 +1,22 @@ +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include + +namespace Ui { +class AboutDialog; +} + +class AboutDialog : public QDialog +{ + Q_OBJECT +public: + AboutDialog(QWidget *parent = nullptr); + ~AboutDialog(); + +private: + Ui::AboutDialog *ui; + +}; + +#endif // ABOUTDIALOG_H diff --git a/aboutdialog.ui b/aboutdialog.ui new file mode 100644 index 0000000..8c3b2d8 --- /dev/null +++ b/aboutdialog.ui @@ -0,0 +1,135 @@ + + + AboutDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 300 + 260 + 81 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + 10 + 150 + 381 + 31 + + + + false + + + NDS Factory V1.0 + + + Qt::AlignCenter + + + + + + 10 + 180 + 381 + 20 + + + + (C) 2019 - Luca D'Amico + + + Qt::AlignCenter + + + + + + 10 + 200 + 381 + 20 + + + + Special Thanks To: + + + Qt::AlignCenter + + + + + + 10 + 220 + 381 + 20 + + + + Dax89 (Davide Trogu) & Kaneb (Antonio Barba) + + + Qt::AlignCenter + + + + + + + aboutCloseBtnBx + accepted() + AboutDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + aboutCloseBtnBx + rejected() + AboutDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/fatpatchingtabfunctions.cpp b/fatpatchingtabfunctions.cpp new file mode 100644 index 0000000..33c5cfb --- /dev/null +++ b/fatpatchingtabfunctions.cpp @@ -0,0 +1,7 @@ +#include "mainwindow.h" + + +bool MainWindow::patchFat(const std::string& loadPath, uint32_t shiftSize, const std::string& savePath) +{ + return ndsFactory.patchFat(loadPath, shiftSize, savePath); +} diff --git a/fatpatchingtabsignals.cpp b/fatpatchingtabsignals.cpp new file mode 100644 index 0000000..0c9d7f7 --- /dev/null +++ b/fatpatchingtabsignals.cpp @@ -0,0 +1,49 @@ +#include +#include +#include "mainwindow.h" +#include "ui_mainwindow.h" + + +void MainWindow::on_fatPatchingLoadFatBtn_clicked() +{ + QString fatPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Fat", + QDir::currentPath(), + "NDS Fat (*.bin)"); + + if( !fatPath.isNull() ) + { + ui->fatPatchingFatPathEdt->setText(fatPath.toUtf8()); + } +} + +void MainWindow::on_fatPatchingPatchFatBtn_clicked() +{ + uint32_t positionDiff = 0; + uint32_t originalPos = ui->fatPatchingOriginalFatFilesAddrEdt->text().toUInt(nullptr, 16); + uint32_t newPos = ui->fatPatchingNewFatFilesAddrEdt->text().toUInt(nullptr, 16); + + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS FAT", + "fat.bin", + "Binary (*.bin)"); + + if(dirPath.isNull()) + { + return; + } + + if (originalPos < newPos) + { + positionDiff = newPos-originalPos; + } else { + positionDiff = originalPos-newPos; + } + + patchFat(ui->fatPatchingFatPathEdt->text().toStdString(), positionDiff, dirPath.toStdString()) + ? QMessageBox::information(this, tr("NDS Factory"), tr("FAT patching completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error patching FAT!")); + +} diff --git a/fatstruct.h b/fatstruct.h new file mode 100644 index 0000000..39c6a87 --- /dev/null +++ b/fatstruct.h @@ -0,0 +1,11 @@ +#ifndef FATSTRUCT_H +#define FATSTRUCT_H + +#include + +struct FatRange { + uint32_t startAddr; + uint32_t endAddr; +}; + +#endif // FATSTRUCT_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..b48f94e --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..8bd89cd --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,27 @@ +#include "mainwindow.h" +#include "aboutdialog.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + ndsFactory = NDSFactory(); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::on_actionExit_triggered() +{ + QApplication::quit(); +} + +void MainWindow::on_actionAbout_triggered() +{ + AboutDialog aboutDialog; + aboutDialog.exec(); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..233b8b5 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,106 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "ndsfactory.h" + + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private slots: + void on_loadRomBtn_clicked(); + void on_unpackerDumpHeaderBtn_clicked(); + void on_unpackerDumpArm9Btn_clicked(); + void on_unpackerDumpArm7Btn_clicked(); + void on_unpackerDumpFntBtn_clicked(); + void on_unpackerDumpFatBtn_clicked(); + void on_unpackerDumpArm9OverlayBtn_clicked(); + void on_unpackerDumpArm7OverlayBtn_clicked(); + void on_unpackerDumpIconTitleLogoBtn_clicked(); + void on_unpackerDumpFatFilesBtn_clicked(); + void on_unpackerDumpArm9OverlayFilesBtn_clicked(); + void on_unpackerDumpArm7OverlayFilesBtn_clicked(); + void on_unpackerDumpEverythingBtn_clicked(); + void on_unpackerDecodeFatFilesBtn_clicked(); + + void on_actionExit_triggered(); + void on_actionAbout_triggered(); + + void on_packerLoadHeaderBtn_clicked(); + void on_packerLoadArm9BinBtn_clicked(); + void on_packerLoadArm7BinBtn_clicked(); + void on_packerLoadFntBtn_clicked(); + void on_packerLoadFatBtn_clicked(); + void on_packerLoadArm9OverlayBtn_clicked(); + void on_packerLoadArm9OverlayFilesBtn_clicked(); + void on_packerLoadArm7OverlayBtn_clicked(); + void on_packerLoadArm7OverlayFilesBtn_clicked(); + void on_packerLoadIconTitleBtn_clicked(); + void on_packerLoadFatFilesBtn_clicked(); + void on_packerBuildNDSRomBtn_clicked(); + + void on_fatPatchingLoadFatBtn_clicked(); + + void on_fatPatchingPatchFatBtn_clicked(); + +private: + Ui::MainWindow *ui; + NDSFactory ndsFactory; + void populateHeader(NDSHeader* ndsHeader); + void enableExtractionButtons(); + void disableExtractionButtons(); + bool dumpHeader(const std::string& dirPath); + bool dumpArm9Bin(const std::string& dirPath, bool dumpExtraBytes); + bool dumpArm7Bin(const std::string& dirPath); + bool dumpFnt(const std::string& dirPath); + bool dumpFat(const std::string& dirPath); + bool dumpArm9Overlay(const std::string& dirPath); + bool dumpArm9OverlayFiles(const std::string& dirPath); + bool dumpArm7Overlay(const std::string& dirPath); + bool dumpArm7OverlayFiles(const std::string& dirPath); + bool dumpIconTitle(const std::string& dirPath); + bool dumpFatFiles(const std::string& dirPath); + bool dumpEverything(QString dirPath); + + void populatePackerSectionHeader(NDSHeader *ndsHeader); + bool writeHeader(const std::string& savePath); + bool writeArm9Bin(const std::string& savePath, bool isArm9FooterPresent); + bool writeArm7Bin(const std::string& savePath); + bool writeFnt(const std::string& savePath); + bool writeFat(const std::string& savePath); + bool writeArm9Overlay(const std::string& savePath); + bool writeArm9OverlayFiles(const std::string& savePath); + bool writeArm7Overlay(const std::string& savePath); + bool writeArm7OverlayFiles(const std::string& savePath); + bool writeIconTitle(const std::string& savePath); + bool writeFatFiles(const std::string& savePath); + bool writeEverything(const std::string& savePath); + + bool writeHeaderPadding(char paddingByte, const std::string& savePath); + bool writeArm9BinPadding(char paddingByte, const std::string& savePath, bool isArm9FooterPresent); + 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); + + bool decodeFatFiles(); + + bool patchFat(const std::string& loadPath, uint32_t shiftSize, const std::string& savePath); +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..e8ff17a --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,2066 @@ + + + MainWindow + + + + 0 + 0 + 772 + 805 + + + + NDS Factory + + + + + 0 + 0 + + + + + 756 + 800 + + + + + QLayout::SetMinAndMaxSize + + + + + 0 + + + + Unpacker + + + + + + Rom + + + + 4 + + + QLayout::SetMinimumSize + + + 1 + + + 1 + + + 1 + + + 1 + + + + + true + + + + + + + Load Rom + + + false + + + + + + + + + + Header + + + + + + + + Game Title: + + + + + + + true + + + + + + + Game Code: + + + + + + + true + + + + + + + Maker Code: + + + + + + + true + + + + + + + Unit Code: + + + + + + + true + + + + + + + + + + + Device Code: + + + + + + + + + + true + + + + + + + Card Size: + + + + + + + + + + true + + + + + + + Card Info: + + + + + + + + + + true + + + + + + + Flags: + + + + + + + + + + true + + + + + + + + + + + ARM9 Rom Addr: + + + + + + + true + + + + + + + ARM9 Entry Addr: + + + + + + + true + + + + + + + ARM9 Ram Addr: + + + + + + + true + + + + + + + ARM9 Size: + + + + + + + true + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ARM7 Rom Addr: + + + + + + + true + + + + + + + ARM7 Entry Addr: + + + + + + + true + + + + + + + ARM7 Ram Addr: + + + + + + + true + + + + + + + ARM7 Size: + + + + + + + true + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Filename Table Addr: + + + + + + + true + + + + + + + Filename Table Size: + + + + + + + true + + + + + + + FAT Addr: + + + + + + + true + + + + + + + FAT Size: + + + + + + + true + + + + + + + + + + + ARM9 Overlay Addr: + + + + + + + true + + + + + + + ARM9 Overlay Size: + + + + + + + true + + + + + + + ARM7 Overlay Addr: + + + + + + + true + + + + + + + ARM7 Overlay Size: + + + + + + + true + + + + + + + + + + + Port 40001A4h NC: + + + + + + + true + + + + + + + Port 40001A4h KC: + + + + + + + true + + + + + + + Icon/Title Addr: + + + + + + + true + + + + + + + Secure Area CRC16: + + + + + + + true + + + + + + + + + + + Secure Area Timeout: + + + + + + + true + + + + + + + ARM9 AL Ram Addr: + + + + + + + true + + + + + + + ARM7 AL Ram Addr: + + + + + + + true + + + + + + + Secure Area Disable: + + + + + + + true + + + + + + + + + + + Used Rom Size: + + + + + + + true + + + + + + + Header Size: + + + + + + + true + + + + + + + Nintendo Logo: + + + + + + + true + + + + + + + Nintendo Logo CRC: + + + + + + + true + + + + + + + + + + + Header CRC: + + + + + + + true + + + + + + + Debug Rom Addr: + + + + + + + true + + + + + + + Debug Size: + + + + + + + true + + + + + + + Debug Ram Addr: + + + + + + + true + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 400 + 20 + + + + + + + + FAT Files Original Address: + + + + + + + true + + + + + + + + + + + + Tools + + + + + + false + + + Extractor + + + + + + 7 + + + 7 + + + 7 + + + 7 + + + + + Header + + + + + + + ARM9 Bin + + + + + + + ARM7 Bin + + + + + + + Filename Table + + + + + + + + + 7 + + + 7 + + + 7 + + + 7 + + + + + FAT + + + + + + + FAT Files + + + + + + + ARM9 Overlay + + + + + + + ARM9 Overlay Files + + + + + + + + + 7 + + + 7 + + + 7 + + + 7 + + + + + ARM7 Overlay + + + + + + + ARM7 Overlay Files + + + + + + + Icon/Title Logo + + + + + + + + + + + + false + + + Extra + + + + + + Extract Everything + + + + + + + Decode FAT Contents + + + + + + + + + + + + + + Packer + + + + + + Header + + + + + + + + Game Title: + + + + + + + false + + + + + + + Game Code: + + + + + + + false + + + + + + + Maker Code: + + + + + + + + + + Unit Code: + + + + + + + false + + + + + + + + + + + Device Code: + + + + + + + + + + false + + + + + + + Card Size: + + + + + + + + + + false + + + + + + + Card Info: + + + + + + + + + + + + + + Flags: + + + + + + + + + + false + + + + + + + + + + + ARM9 Rom Addr: + + + + + + + false + + + + + + + ARM9 Entry Addr: + + + + + + + false + + + + + + + ARM9 Ram Addr: + + + + + + + + + + ARM9 Size: + + + + + + + false + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ARM7 Rom Addr: + + + + + + + false + + + + + + + ARM7 Entry Addr: + + + + + + + false + + + + + + + ARM7 Ram Addr: + + + + + + + + + + ARM7 Size: + + + + + + + false + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Filename Table Addr: + + + + + + + false + + + + + + + Filename Table Size: + + + + + + + false + + + + + + + FAT Addr: + + + + + + + + + + FAT Size: + + + + + + + false + + + + + + + + + + + ARM9 Overlay Addr: + + + + + + + false + + + + + + + ARM9 Overlay Size: + + + + + + + false + + + + + + + ARM7 Overlay Addr: + + + + + + + + + + ARM7 Overlay Size: + + + + + + + false + + + + + + + + + + + Port 40001A4h NC: + + + + + + + false + + + + + + + Port 40001A4h KC: + + + + + + + false + + + + + + + Icon/Title Addr: + + + + + + + + + + Secure Area CRC16: + + + + + + + false + + + + + + + + + + + Secure Area Timeout: + + + + + + + false + + + + + + + ARM9 AL Ram Addr: + + + + + + + false + + + + + + + ARM7 AL Ram Addr: + + + + + + + + + + Secure Area Disable: + + + + + + + false + + + + + + + + + + + Used Rom Size: + + + + + + + false + + + + + + + Header Size: + + + + + + + false + + + + + + + Nintendo Logo: + + + + + + + + + + Nintendo Logo CRC: + + + + + + + false + + + + + + + + + + + Header CRC: + + + + + + + false + + + + + + + Debug Rom Addr: + + + + + + + false + + + + + + + Debug Size: + + + + + + + + + + Debug Ram Addr: + + + + + + + false + + + + + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 450 + 20 + + + + + + + + Fat Files Address: + + + + + + + + + + + + QLayout::SetMinimumSize + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Import Header From File + + + + + + + + + + + + Injector + + + + + + + + + + + Load Arm9 Bin + + + + + + + + + + Load Arm7 Bin + + + + + + + + + + + + + + Load FNT + + + + + + + + + + Load FAT + + + + + + + + + + + + + + Load ARM9 Overlay + + + + + + + + + + Load ARM9 Overlay Files + + + + + + + + + + + + + + Load ARM7 Overlay + + + + + + + + + + Load ARM7 Overlay Files + + + + + + + + + + + + + + Load Icon/Title + + + + + + + + + + Load FAT Files + + + + + + + + + + + + Qt::LeftToRight + + + false + + + Builder + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + PAD Sections With 00s + + + true + + + + + + + + 0 + 0 + + + + PAD Sections With FFs + + + + + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Generate Trimmed Rom + + + true + + + + + + + + + + + Build NDS Rom + + + + + + + + + + + + + Fat Patching + + + + + + 4 + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + If you FAT Files Address (fat_data.bin) is different from the original ROM position, you have to patch the FAT (fat.bin)... + + + false + + + Qt::AlignCenter + + + + + + + + + + + FAT Patcher + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Load FAT (fat.bin) + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Original Fat Files (fat_data.bin) Addr: + + + + + + + + + + New Fat Files Addr: + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Apply Patch! + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + true + + + + 0 + 0 + 772 + 21 + + + + + File + + + + + + Help + + + + + + + + + true + + + + + About + + + + + Exit + + + + + + + diff --git a/ndsfactory.cpp b/ndsfactory.cpp new file mode 100644 index 0000000..abced80 --- /dev/null +++ b/ndsfactory.cpp @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include "ndsfactory.h" +#include "fatstruct.h" + + +NDSFactory::NDSFactory() +{ + +} + +bool NDSFactory::loadRomHeader(const std::string& romPath, std::vector& romHeader) +{ + std::streampos headerSize = sizeof(NDSHeader); + std::ifstream romFile (romPath, std::ios::in|std::ios::binary|std::ios::ate); + if (romFile.is_open()) + { + romHeader.resize(static_cast(headerSize)); + + romFile.seekg (0, std::ios::beg); + romFile.read (romHeader.data(), headerSize); + romFile.close(); + + return true; + } + return false; +} + +bool NDSFactory::dumpDataFromFile(const std::string& romPath, const std::string& savePath, uint32_t startAddr, uint32_t size) +{ + std::ifstream romFile (romPath, std::ios::in|std::ios::binary|std::ios::ate); + std::ofstream savedFile (savePath, std::ios::out|std::ios::binary|std::ios::ate); + if (romFile.is_open() && savedFile.is_open()) + { + std::vector dumpBuffer(size); + romFile.seekg (startAddr, std::ios::beg); + romFile.read (dumpBuffer.data(), size); + romFile.close(); + + savedFile.write(dumpBuffer.data(), size); + savedFile.close(); + return true; + } + return false; +} + + +bool NDSFactory::readBytesFromFile(std::vector& byteBuffer, const std::string& romPath, uint32_t startAddr, uint32_t size) +{ + std::ifstream romFile (romPath, std::ios::in|std::ios::binary|std::ios::ate); + if (romFile.is_open()) + { + romFile.seekg (startAddr, std::ios::beg); + romFile.read (byteBuffer.data(), size); + romFile.close(); + return true; + } + return false; +} + +bool NDSFactory::writeSectionToFile(const std::string& sectionPath, const std::string& savePath, uint32_t startAddr, uint32_t size) +{ + std::ifstream sectionFile (sectionPath, std::ios::in|std::ios::binary|std::ios::ate); + std::ofstream savedFile (savePath, std::ios::out|std::ios::binary|std::ios::app); + if (sectionFile.is_open() && savedFile.is_open()) + { + std::vector dumpBuffer(size); + sectionFile.seekg (0, std::ios::beg); + sectionFile.read (dumpBuffer.data(), size); + sectionFile.close(); + + savedFile.seekp(startAddr, std::ios::beg); + savedFile.write(dumpBuffer.data(), size); + savedFile.close(); + return true; + } + return false; +} + +bool NDSFactory::writeBytesToFile(std::vector& byteBuffer, const std::string& savePath, uint32_t startAddr, uint32_t size) +{ + std::ofstream savedFile (savePath, std::ios::out|std::ios::binary|std::ios::app); + if (savedFile.is_open()) + { + savedFile.seekp(startAddr, std::ios::beg); + savedFile.write(byteBuffer.data(), size); + savedFile.close(); + return true; + } + return false; +} + + +bool NDSFactory::writePaddingToFile(char paddingChar, const std::string& filePath, uint32_t startAddr, const uint32_t size) +{ + std::vector paddingBytes(size, paddingChar); + return writeBytesToFile(paddingBytes, filePath, startAddr, size); +} + +int NDSFactory::getCardSizeInBytes(int cardType) +{ + return static_cast(pow(2, 17 + cardType)); +} + +bool NDSFactory::checkArm9FooterPresence(const std::string& sectionPath, uint32_t size) +{ + std::ifstream sectionFile (sectionPath, std::ios::in|std::ios::binary|std::ios::ate); + if (sectionFile.is_open()) + { + long sectionRealSize = sectionFile.tellg(); + sectionFile.close(); + if (sectionRealSize >= size + Arm9FooterSize) + { + return true; + } + } + return false; +} + +bool NDSFactory::patchFat(const std::string& fatSectionPath, uint32_t shiftSize, const std::string& savePath) +{ + std::vector fatBytes; + + std::ifstream sectionFile (fatSectionPath, std::ios::in|std::ios::binary|std::ios::ate); + if (!sectionFile.is_open()) + return false; + + long sectionSize = sectionFile.tellg(); + fatBytes.resize(static_cast(sectionSize)); + + sectionFile.seekg (0, std::ios::beg); + + sectionFile.read (fatBytes.data(), sectionSize); + sectionFile.close(); + + + FatRange* pfatrange = reinterpret_cast(fatBytes.data()); + + for(size_t i = 0; i < fatBytes.size(); i += sizeof(FatRange), pfatrange++) { + pfatrange->startAddr += shiftSize; + pfatrange->endAddr += shiftSize; + } + + return writeBytesToFile(fatBytes, savePath, 0, static_cast(sectionSize)); +} diff --git a/ndsfactory.h b/ndsfactory.h new file mode 100644 index 0000000..ad8f8b1 --- /dev/null +++ b/ndsfactory.h @@ -0,0 +1,29 @@ +#ifndef NDSFACTORY_H +#define NDSFACTORY_H + +#include +#include +#include +#include "ndsheader.h" + + + +class NDSFactory +{ +public: + NDSFactory(); + bool loadRomHeader(const std::string& romPath, std::vector& header); + bool dumpDataFromFile(const std::string& romPath, const std::string& savePath, uint32_t startAddr, uint32_t size); + bool readBytesFromFile(std::vector& byteBuffer, const std::string& romPath, uint32_t startAddr, uint32_t size); + bool writeSectionToFile(const std::string& sectionPath, const std::string& savePath, uint32_t startAddr, uint32_t size); + bool writeBytesToFile(std::vector& byteBuffer, const std::string& savePath, uint32_t startAddr, uint32_t size); + bool writePaddingToFile(char paddingChar, const std::string& savePath, uint32_t startAddr, uint32_t size); + int getCardSizeInBytes(int cardType); + bool checkArm9FooterPresence(const std::string& sectionPath, uint32_t size); + bool patchFat(const std::string& sectionPath, uint32_t shiftSize, const std::string& savePath); + +private: + +}; + +#endif // NDSFACTORY_H diff --git a/ndsheader.h b/ndsheader.h new file mode 100644 index 0000000..1b6664e --- /dev/null +++ b/ndsheader.h @@ -0,0 +1,74 @@ +#ifndef NDSHEADER_H +#define NDSHEADER_H + +#include + +#define IconTitleSize 0xA00 +#define Arm9FooterSize 0xC + +#pragma pack(push, 1) +struct NDSHeader +{ + char GameTitle[0xC]; + char GameCode[0x4]; + unsigned char MakerCode[0x2]; + unsigned char UnitCode; + unsigned char DeviceType; + unsigned char DeviceSize; + unsigned char Reserved1[0x9]; + unsigned char RomVersion; + unsigned char Flags; + + uint32_t Arm9RomAddr; + uint32_t Arm9EntryAddr; + uint32_t Arm9RamAddr; + uint32_t Arm9Size; + + uint32_t Arm7RomAddr; + uint32_t Arm7EntryAddr; + uint32_t Arm7RamAddr; + uint32_t Arm7Size; + + uint32_t FilenameTableAddr; + uint32_t FilenameSize; + uint32_t FATAddr; + uint32_t FATSize; + + uint32_t Arm9OverlayAddr; + uint32_t Arm9OverlaySize; + uint32_t Arm7OverlayAddr; + uint32_t Arm7OverlaySize; + + uint32_t NormalCommandsSettings; + uint32_t Key1CommandsSettings; + + uint32_t IconTitleAddr; + + uint16_t SecureAreaCRC16; + uint16_t SecureAreaLoadingTimeout; + + uint32_t ARM9AutoLoadListRamAddr; + uint32_t ARM7AutoLoadListRamAddr; + + uint64_t SecureAreaDisable; + + uint32_t RomSize; + uint32_t HeaderSize; + + unsigned char Reserved2[0x38]; + + unsigned char NintendoLogo[0x9C]; + uint16_t NintendoLogoCRC; + uint16_t HeaderCRC16; + + uint32_t DebugRomAddr; + uint32_t DebugSize; + uint32_t DebugRamAddr; + + unsigned char Reserved3[0x4]; + unsigned char Reserved4[0x90]; +}; +#pragma pack(pop) + + +#endif // NDSHEADER_H diff --git a/packertabfunctions.cpp b/packertabfunctions.cpp new file mode 100644 index 0000000..9b7c00e --- /dev/null +++ b/packertabfunctions.cpp @@ -0,0 +1,353 @@ +#include +#include +#include +#include "mainwindow.h" +#include "ui_mainwindow.h" + + +void MainWindow::populatePackerSectionHeader(NDSHeader *ndsHeader) +{ + ui->packerGameTitleEdt->setText(QString::fromUtf8(ndsHeader->GameTitle, 0xC)); + ui->packerGameCodeEdt->setText(QString::fromUtf8(ndsHeader->GameCode, 0x4)); + ui->packerMakerCodeEdt->setText(QString::fromUtf8(reinterpret_cast(ndsHeader->MakerCode), 0x2)); + ui->packerUnitCodeEdt->setText(QString::number(ndsHeader->UnitCode, 16)); + + ui->packerDeviceCodeEdt->setText(QString::number(ndsHeader->DeviceType, 16)); + ui->packerCardSizeEdt->setText(QString::number(ndsHeader->DeviceSize, 16)); + ui->packerCardInfoEdt->setText(QString::number(ndsHeader->RomVersion, 16)); + ui->packerFlagsEdt->setText(QString::number(ndsHeader->Flags, 16)); + + ui->packerARM9RomAddrEdt->setText(QString::number(ndsHeader->Arm9RomAddr, 16)); + ui->packerARM9EntryAddrEdt->setText(QString::number(ndsHeader->Arm9EntryAddr, 16)); + ui->packerARM9RamAddrEdt->setText(QString::number(ndsHeader->Arm9RamAddr, 16)); + ui->packerARM9SizeEdt->setText(QString::number(ndsHeader->Arm9Size, 16)); + + ui->packerARM7RomAddrEdt->setText(QString::number(ndsHeader->Arm7RomAddr, 16)); + ui->packerARM7EntryAddrEdt->setText(QString::number(ndsHeader->Arm7EntryAddr, 16)); + ui->packerARM7RamAddrEdt->setText(QString::number(ndsHeader->Arm7RamAddr, 16)); + ui->packerARM7SizeEdt->setText(QString::number(ndsHeader->Arm7Size, 16)); + + ui->packerFilenameTableAddrEdt->setText(QString::number(ndsHeader->FilenameTableAddr, 16)); + ui->packerFilenameTableSizeEdt->setText(QString::number(ndsHeader->FilenameSize, 16)); + ui->packerFATAddrEdt->setText(QString::number(ndsHeader->FATAddr, 16)); + ui->packerFATSizeEdt->setText(QString::number(ndsHeader->FATSize, 16)); + + ui->packerARM9OverlayAddrEdt->setText(QString::number(ndsHeader->Arm9OverlayAddr, 16)); + ui->packerARM9OverlaySizeEdt->setText(QString::number(ndsHeader->Arm9OverlaySize, 16)); + ui->packerARM7OverlayAddrEdt->setText(QString::number(ndsHeader->Arm7OverlayAddr, 16)); + ui->packerARM7OverlaySizeEdt->setText(QString::number(ndsHeader->Arm7OverlaySize, 16)); + + ui->packerPortNCEdt->setText(QString::number(ndsHeader->NormalCommandsSettings, 16)); + ui->packerPortKCEdt->setText(QString::number(ndsHeader->Key1CommandsSettings, 16)); + ui->packerIconTitleEdt->setText(QString::number(ndsHeader->IconTitleAddr, 16)); + ui->packerSecureAreaCRC16Edt->setText(QString::number(ndsHeader->SecureAreaCRC16, 16)); + + ui->packerSecureAreaTimeoutEdt->setText(QString::number(ndsHeader->SecureAreaLoadingTimeout, 16)); + ui->packerARM9AURamAddrEdt->setText(QString::number(ndsHeader->ARM9AutoLoadListRamAddr, 16)); + ui->packerARM7AURamAddrEdt->setText(QString::number(ndsHeader->ARM7AutoLoadListRamAddr, 16)); + ui->packerSecureAreaDisableEdt->setText(QString::number(ndsHeader->SecureAreaDisable, 16)); + + ui->packerUsedRomSizeEdt->setText(QString::number(ndsHeader->RomSize, 16)); + ui->packerHeaderSizeEdt->setText(QString::number(ndsHeader->HeaderSize, 16)); + ui->packerNintendoLogoEdt->setText(QByteArray::fromRawData(reinterpret_cast(ndsHeader->NintendoLogo), 0x9C).toHex()); + ui->packerNintendoLogoCRCEdt->setText(QString::number(ndsHeader->NintendoLogoCRC, 16)); + + ui->packerHeaderCRCEdt->setText(QString::number(ndsHeader->HeaderCRC16, 16)); + ui->packerDebugRomAddrEdt->setText(QString::number(ndsHeader->DebugRomAddr, 16)); + ui->packerDebugSizeEdt->setText(QString::number(ndsHeader->DebugSize, 16)); + ui->packerDebugRamAddrEdt->setText(QString::number(ndsHeader->DebugRamAddr, 16)); +} + + +bool MainWindow::writeHeader(const std::string& savePath) +{ + std::vector romHeader(sizeof(NDSHeader)); + NDSHeader* pRomHeader = reinterpret_cast(romHeader.data()); + + std::copy_n(ui->packerGameTitleEdt->text().toLatin1().data(), 0xc, std::begin(pRomHeader->GameTitle)); + std::copy_n(ui->packerGameCodeEdt->text().toStdString().data(), 0x4, std::begin(pRomHeader->GameCode)); + std::copy_n(ui->packerMakerCodeEdt->text().toStdString().data(), 0x2, std::begin(pRomHeader->MakerCode)); + pRomHeader->UnitCode = static_cast(ui->packerUnitCodeEdt->text().toUInt(nullptr, 16)); + + pRomHeader->DeviceType = static_cast(ui->packerDeviceCodeEdt->text().toUInt(nullptr, 16)); + pRomHeader->DeviceSize = static_cast(ui->packerCardSizeEdt->text().toUInt(nullptr, 16)); + + std::fill(std::begin(pRomHeader->Reserved1), std::end(pRomHeader->Reserved1), 0); + + pRomHeader->RomVersion = static_cast(ui->packerCardInfoEdt->text().toUInt(nullptr, 16)); + pRomHeader->Flags = static_cast(ui->packerFlagsEdt->text().toUInt(nullptr, 16)); + + pRomHeader->Arm9RomAddr = ui->packerARM9RomAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm9EntryAddr = ui->packerARM9EntryAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm9RamAddr = ui->packerARM9RamAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm9Size = ui->packerARM9SizeEdt->text().toUInt(nullptr, 16); + + pRomHeader->Arm7RomAddr = ui->packerARM7RomAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm7EntryAddr = ui->packerARM7EntryAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm7RamAddr = ui->packerARM7RamAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm7Size = ui->packerARM7SizeEdt->text().toUInt(nullptr, 16); + + pRomHeader->FilenameTableAddr = ui->packerFilenameTableAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->FilenameSize = ui->packerFilenameTableSizeEdt->text().toUInt(nullptr, 16); + pRomHeader->FATAddr = ui->packerFATAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->FATSize = ui->packerFATSizeEdt->text().toUInt(nullptr, 16); + + pRomHeader->Arm9OverlayAddr = ui->packerARM9OverlayAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm9OverlaySize = ui->packerARM9OverlaySizeEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm7OverlayAddr = ui->packerARM7OverlayAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->Arm7OverlaySize = ui->packerARM7OverlaySizeEdt->text().toUInt(nullptr, 16); + + pRomHeader->NormalCommandsSettings = ui->packerPortNCEdt->text().toUInt(nullptr, 16); + pRomHeader->Key1CommandsSettings = ui->packerPortKCEdt->text().toUInt(nullptr, 16); + pRomHeader->IconTitleAddr = ui->packerIconTitleEdt->text().toUInt(nullptr, 16); + pRomHeader->SecureAreaCRC16 = ui->packerSecureAreaCRC16Edt->text().toUShort(nullptr, 16); + + pRomHeader->SecureAreaLoadingTimeout = ui->packerSecureAreaTimeoutEdt->text().toUShort(nullptr, 16); + pRomHeader->ARM9AutoLoadListRamAddr = ui->packerARM9AURamAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->ARM7AutoLoadListRamAddr = ui->packerARM7AURamAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->SecureAreaDisable = ui->packerSecureAreaDisableEdt->text().toULong(nullptr, 16); + + pRomHeader->RomSize = ui->packerUsedRomSizeEdt->text().toUInt(nullptr, 16); + pRomHeader->HeaderSize = ui->packerHeaderSizeEdt->text().toUInt(nullptr, 16); + + std::fill(std::begin(pRomHeader->Reserved2), std::end(pRomHeader->Reserved2), 0); + std::copy_n(std::begin(QByteArray::fromHex(ui->packerNintendoLogoEdt->text().toUtf8())), 0x9C, std::begin(pRomHeader->NintendoLogo)); + pRomHeader->NintendoLogoCRC = ui->packerNintendoLogoCRCEdt->text().toUShort(nullptr, 16); + + pRomHeader->HeaderCRC16 = ui->packerHeaderCRCEdt->text().toUShort(nullptr, 16); + pRomHeader->DebugRomAddr = ui->packerDebugRomAddrEdt->text().toUInt(nullptr, 16); + pRomHeader->DebugSize = ui->packerDebugSizeEdt->text().toUInt(nullptr, 16); + pRomHeader->DebugRamAddr = ui->packerDebugRamAddrEdt->text().toUInt(nullptr, 16); + + std::fill(std::begin(pRomHeader->Reserved3), std::end(pRomHeader->Reserved3), 0); + std::fill(std::begin(pRomHeader->Reserved4), std::end(pRomHeader->Reserved4), 0); + + return ndsFactory.writeBytesToFile(romHeader, savePath, 0, sizeof(NDSHeader));; +} + +bool MainWindow::writeArm9Bin(const std::string& savePath, bool isArm9FooterPresent) +{ + uint32_t size = ui->packerARM9SizeEdt->text().toUInt(nullptr, 16); + if (isArm9FooterPresent) + size += Arm9FooterSize; + return ndsFactory.writeSectionToFile( + ui->loadedArm9BinPathEdt->text().toStdString(), + savePath, + ui->packerARM9RomAddrEdt->text().toUInt(nullptr, 16), + size); +} + +bool MainWindow::writeArm7Bin(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedArm7BinPathEdt->text().toStdString(), + savePath, + ui->packerARM7RomAddrEdt->text().toUInt(nullptr, 16), + ui->packerARM7SizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::writeFnt(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedFntPathEdt->text().toStdString(), + savePath, + ui->packerFilenameTableAddrEdt->text().toUInt(nullptr, 16), + ui->packerFilenameTableSizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::writeFat(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedFatPathEdt->text().toStdString(), + savePath, + ui->packerFATAddrEdt->text().toUInt(nullptr, 16), + ui->packerFATSizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::writeArm9Overlay(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedArm9OverlayPathEdt->text().toStdString(), + savePath, + ui->packerARM9OverlayAddrEdt->text().toUInt(nullptr, 16), + ui->packerARM9OverlaySizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::writeArm9OverlayFiles(const std::string& savePath) +{ + return false; // TODO: implement me! +} + +bool MainWindow::writeArm7Overlay(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedArm7OverlayPathEdt->text().toStdString(), + savePath, + ui->packerARM7OverlayAddrEdt->text().toUInt(nullptr, 16), + ui->packerARM7OverlaySizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::writeArm7OverlayFiles(const std::string& savePath) +{ + return false; // TODO: implement me! +} + +bool MainWindow::writeIconTitle(const std::string& savePath) +{ + return ndsFactory.writeSectionToFile( + ui->loadedIconTitlePathEdt->text().toStdString(), + savePath, + ui->packerIconTitleEdt->text().toUInt(nullptr, 16), + IconTitleSize); +} + +bool MainWindow::writeFatFiles(const std::string& savePath) +{ + uint32_t startAddr = ui->packerIconTitleEdt->text().toUInt(nullptr, 16) + IconTitleSize; + uint32_t size = ui->packerUsedRomSizeEdt->text().toUInt(nullptr, 16) - startAddr; + + return ndsFactory.writeSectionToFile( + ui->loadedFatFilesPathEdt->text().toStdString(), + savePath, + startAddr, + size); +} + +bool MainWindow::writeHeaderPadding(char paddingType, const std::string& savePath) +{ + uint32_t startAddr = sizeof(NDSHeader); + uint32_t size = ui->packerARM9RomAddrEdt->text().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 = ui->packerARM9RomAddrEdt->text().toUInt(nullptr, 16) + ui->packerARM9SizeEdt->text().toUInt(nullptr, 16); + uint32_t size = ui->packerARM7RomAddrEdt->text().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 = ui->packerARM7RomAddrEdt->text().toUInt(nullptr, 16) + ui->packerARM7SizeEdt->text().toUInt(nullptr, 16); + uint32_t size = ui->packerFilenameTableAddrEdt->text().toUInt(nullptr, 16) - startAddr; + + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); +} + +bool MainWindow::writeFntPadding(char paddingType, const std::string& savePath) +{ + uint32_t startAddr = ui->packerFilenameTableAddrEdt->text().toUInt(nullptr, 16) + ui->packerFilenameTableSizeEdt->text().toUInt(nullptr, 16); + uint32_t size = ui->packerFATAddrEdt->text().toUInt(nullptr, 16) - startAddr; + + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); +} + +bool MainWindow::writeFatPadding(char paddingType, const std::string& savePath) +{ + uint32_t startAddr = ui->packerFATAddrEdt->text().toUInt(nullptr, 16) + ui->packerFATSizeEdt->text().toUInt(nullptr, 16); + uint32_t size = ui->packerIconTitleEdt->text().toUInt(nullptr, 16) - startAddr; + + return ndsFactory.writePaddingToFile( + paddingType, + savePath, + startAddr, + size); +} + +bool MainWindow::writeArm9OverlayPadding(char paddingType, const std::string& savePath) +{ // FIXME TODO + return true; +} + +bool MainWindow::writeArm9OverlayFilesPadding(char paddingType, const std::string& savePath) +{ // FIXME TODO + return true; +} + +bool MainWindow::writeArm7OverlayPadding(char paddingType, const std::string& savePath) +{ // FIXME TODO + return true; +} + + +bool MainWindow::writeArm7OverlayFilesPadding(char paddingType, const std::string& savePath) +{ // FIXME TODO + return true; +} + +bool MainWindow::writeRomPadding(const std::string& savePath) +{ + uint32_t startAddr = ui->packerUsedRomSizeEdt->text().toUInt(nullptr, 16); + uint32_t size = static_cast(ndsFactory.getCardSizeInBytes(ui->packerCardSizeEdt->text().toInt())) - startAddr; + + return ndsFactory.writePaddingToFile( + static_cast('\xff'), + savePath, + startAddr, + size); +} + + +bool MainWindow::writeEverything(const std::string& savePath) +{ + bool res = true; + char paddingType; + bool isArm9FooterPresent = ndsFactory.checkArm9FooterPresence(ui->loadedArm9BinPathEdt->text().toStdString(), + ui->packerARM9SizeEdt->text().toUInt(nullptr, 16)); + if (ui->packerPadType00RdBtn->isChecked()) + paddingType = static_cast('\x00'); + else + paddingType = static_cast('\xff'); + + res &= writeHeader(savePath); + res &= writeHeaderPadding(paddingType, savePath); + res &= writeArm9Bin(savePath, isArm9FooterPresent); + res &= writeArm9BinPadding(paddingType, savePath, isArm9FooterPresent); + res &= writeArm7Bin(savePath); + res &= writeArm7BinPadding(paddingType, savePath); + res &= writeFnt(savePath); + res &= writeFntPadding(paddingType, savePath); + res &= writeFat(savePath); + res &= writeFatPadding(paddingType, savePath); + if(ui->packerARM9OverlayAddrEdt->text().toUInt(nullptr, 16) != 0) { + res &= writeArm9Overlay(savePath); + res &= writeArm9OverlayPadding(paddingType, savePath); + res &= writeArm9OverlayFiles(savePath); + res &= writeArm9OverlayFilesPadding(paddingType, savePath); + } + if(ui->packerARM7OverlayAddrEdt->text().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()) + { + res &= writeRomPadding(savePath); + } + return res; +} diff --git a/packertabsignals.cpp b/packertabsignals.cpp new file mode 100644 index 0000000..1cfae90 --- /dev/null +++ b/packertabsignals.cpp @@ -0,0 +1,185 @@ +#include +#include +#include "mainwindow.h" +#include "ui_mainwindow.h" + +void MainWindow::on_packerLoadHeaderBtn_clicked() +{ + std::vector romHeader; + NDSHeader *pNDSHeader; + + QString headerPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Header", + QDir::currentPath(), + "NDS Header (*.bin)"); + + if(headerPath.isNull()) + { + QMessageBox::critical(this, tr("NDS Factory"), tr("Unable to open file!")); + return; + } + + if (ndsFactory.loadRomHeader(headerPath.toStdString(), romHeader)) + { + pNDSHeader = reinterpret_cast(romHeader.data()); + populatePackerSectionHeader(pNDSHeader); + } +} + +void MainWindow::on_packerLoadArm9BinBtn_clicked() +{ + QString arm9BinPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Arm9Bin", + QDir::currentPath(), + "NDS Arm9Bin (*.bin)"); + + if(!arm9BinPath.isNull()) + { + ui->loadedArm9BinPathEdt->setText(arm9BinPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadArm7BinBtn_clicked() +{ + QString arm7BinPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Arm7Bin", + QDir::currentPath(), + "NDS Arm7Bin (*.bin)"); + + if(!arm7BinPath.isNull()) + { + ui->loadedArm7BinPathEdt->setText(arm7BinPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadFntBtn_clicked() +{ + QString fntPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Fnt", + QDir::currentPath(), + "NDS Fnt (*.bin)"); + + if(!fntPath.isNull()) + { + ui->loadedFntPathEdt->setText(fntPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadFatBtn_clicked() +{ + QString fatPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Fat", + QDir::currentPath(), + "NDS Fat (*.bin)"); + + if(!fatPath.isNull()) + { + ui->loadedFatPathEdt->setText(fatPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadArm9OverlayBtn_clicked() +{ + QString arm9OverlayPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Arm9Overlay", + QDir::currentPath(), + "NDS A9OVR (*.bin)"); + + if( !arm9OverlayPath.isNull() ) + { + ui->loadedArm9OverlayPathEdt->setText(arm9OverlayPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadArm9OverlayFilesBtn_clicked() +{ + QString arm9OverlayFilesPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Arm9Overlay Data", + QDir::currentPath(), + "NDS A9OVR_DATA (*.bin)"); + + if(!arm9OverlayFilesPath.isNull()) + { + ui->loadedArm9OverlayFilesPathEdt->setText(arm9OverlayFilesPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadArm7OverlayBtn_clicked() +{ + QString arm7OverlayPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Arm7Overlay", + QDir::currentPath(), + "NDS A7OVR (*.bin)"); + + if(!arm7OverlayPath.isNull()) + { + ui->loadedArm7OverlayPathEdt->setText(arm7OverlayPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadArm7OverlayFilesBtn_clicked() +{ + QString arm7OverlayFilesPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Arm7Overlay Data", + QDir::currentPath(), + "NDS A7OVR_DATA (*.bin)"); + + if(!arm7OverlayFilesPath.isNull()) + { + ui->loadedArm7OverlayFilesPathEdt->setText(arm7OverlayFilesPath.toUtf8()); + } +} + +void MainWindow::on_packerLoadIconTitleBtn_clicked() +{ + QString iconTitlePath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS IconTitleLogo", + QDir::currentPath(), + "NDS ITL (*.bin)"); + + if(!iconTitlePath.isNull()) + { + ui->loadedIconTitlePathEdt->setText(iconTitlePath.toUtf8()); + } +} + +void MainWindow::on_packerLoadFatFilesBtn_clicked() +{ + QString fatFilesPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Fat Data", + QDir::currentPath(), + "NDS FAT_DATA (*.bin)"); + + if(!fatFilesPath.isNull()) + { + ui->loadedFatFilesPathEdt->setText(fatFilesPath.toUtf8()); + ui->packerFatFilesAddrEdt->setText(QString::number((ui->packerIconTitleEdt->text().toUInt(nullptr, 16) + IconTitleSize), 16)); + } +} + +void MainWindow::on_packerBuildNDSRomBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS Rom", + "rom.nds", + "NDS ROM (*.nds)"); + + if (!dirPath.isNull()) + { + writeEverything(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Creation completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the creation!")); + } +} + diff --git a/unpackertabfunctions.cpp b/unpackertabfunctions.cpp new file mode 100644 index 0000000..d952cdb --- /dev/null +++ b/unpackertabfunctions.cpp @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "ui_mainwindow.h" + + +void MainWindow::populateHeader(NDSHeader* ndsHeader) +{ + + ui->unpackerGameTitleEdt->setText(QString::fromUtf8(ndsHeader->GameTitle, 0xC)); + ui->unpackerGameCodeEdt->setText(QString::fromUtf8(ndsHeader->GameCode, 0x4)); + ui->unpackerMakerCodeEdt->setText(QString::fromUtf8(reinterpret_cast(ndsHeader->MakerCode), 0x2)); + ui->unpackerUnitCodeEdt->setText(QString::number(ndsHeader->UnitCode, 16)); + + ui->unpackerDeviceCodeEdt->setText(QString::number(ndsHeader->DeviceType, 16)); + ui->unpackerCardSizeEdt->setText(QString::number(ndsHeader->DeviceSize, 16)); + ui->unpackerCardInfoEdt->setText(QString::number(ndsHeader->RomVersion, 16)); + ui->unpackerFlagsEdt->setText(QString::number(ndsHeader->Flags, 16)); + + ui->unpackerARM9RomAddrEdt->setText(QString::number(ndsHeader->Arm9RomAddr,16)); + ui->unpackerARM9EntryAddrEdt->setText(QString::number(ndsHeader->Arm9EntryAddr,16)); + ui->unpackerARM9RamAddrEdt->setText(QString::number(ndsHeader->Arm9RamAddr,16)); + ui->unpackerARM9SizeEdt->setText(QString::number(ndsHeader->Arm9Size,16)); + + ui->unpackerARM7RomAddrEdt->setText(QString::number(ndsHeader->Arm7RomAddr,16)); + ui->unpackerARM7EntryAddrEdt->setText(QString::number(ndsHeader->Arm7EntryAddr,16)); + ui->unpackerARM7RamAddrEdt->setText(QString::number(ndsHeader->Arm7RamAddr,16)); + ui->unpackerARM7SizeEdt->setText(QString::number(ndsHeader->Arm7Size,16)); + + ui->unpackerFilenameTableAddrEdt->setText(QString::number(ndsHeader->FilenameTableAddr,16)); + ui->unpackerFilenameTableSizeEdt->setText(QString::number(ndsHeader->FilenameSize,16)); + ui->unpackerFATAddrEdt->setText(QString::number(ndsHeader->FATAddr,16)); + ui->unpackerFATSizeEdt->setText(QString::number(ndsHeader->FATSize,16)); + + ui->unpackerARM9OverlayAddrEdt->setText(QString::number(ndsHeader->Arm9OverlayAddr,16)); + ui->unpackerARM9OverlaySizeEdt->setText(QString::number(ndsHeader->Arm9OverlaySize,16)); + ui->unpackerARM7OverlayAddrEdt->setText(QString::number(ndsHeader->Arm7OverlayAddr,16)); + ui->unpackerARM7OverlaySizeEdt->setText(QString::number(ndsHeader->Arm7OverlaySize,16)); + + ui->unpackerPortNCEdt->setText(QString::number(ndsHeader->NormalCommandsSettings,16)); + ui->unpackerPortKCEdt->setText(QString::number(ndsHeader->Key1CommandsSettings,16)); + ui->unpackerIconTitleEdt->setText(QString::number(ndsHeader->IconTitleAddr,16)); + ui->unpackerSecureAreaCRC16Edt->setText(QString::number(ndsHeader->SecureAreaCRC16,16)); + + ui->unpackerSecureAreaTimeoutEdt->setText(QString::number(ndsHeader->SecureAreaLoadingTimeout,16)); + ui->unpackerARM9AURamAddrEdt->setText(QString::number(ndsHeader->ARM9AutoLoadListRamAddr,16)); + ui->unpackerARM7AURamAddrEdt->setText(QString::number(ndsHeader->ARM7AutoLoadListRamAddr,16)); + ui->unpackerSecureAreaDisableEdt->setText(QString::number(ndsHeader->SecureAreaDisable,16)); + + ui->unpackerUsedRomSizeEdt->setText(QString::number(ndsHeader->RomSize,16)); + ui->unpackerHeaderSizeEdt->setText(QString::number(ndsHeader->HeaderSize,16)); + + ui->unpackerNintendoLogoEdt->setText(QByteArray::fromRawData(reinterpret_cast(ndsHeader->NintendoLogo), 0x9C).toHex()); + ui->unpackerNintendoLogoCRCEdt->setText(QString::number(ndsHeader->NintendoLogoCRC,16)); + + ui->unpackerHeaderCRCEdt->setText(QString::number(ndsHeader->HeaderCRC16,16)); + ui->unpackerDebugRomAddrEdt->setText(QString::number(ndsHeader->DebugRomAddr,16)); + ui->unpackerDebugSizeEdt->setText(QString::number(ndsHeader->DebugSize,16)); + ui->unpackerDebugRamAddrEdt->setText(QString::number(ndsHeader->DebugRamAddr,16)); + + ui->unpackerFatFilesOriginalAddrEdt->setText(QString::number((ndsHeader->IconTitleAddr+IconTitleSize),16)); +} + +void MainWindow::enableExtractionButtons() +{ + ui->unpackerExtractorGbx->setEnabled(true); + ui->unpackerExtraGbx->setEnabled(true); + if (ui->unpackerARM9OverlayAddrEdt->text().toUInt(nullptr, 16) == 0){ + ui->unpackerDumpArm9OverlayBtn->setEnabled(false); + ui->unpackerDumpArm9OverlayFilesBtn->setEnabled(false); + } + if (ui->unpackerARM7OverlayAddrEdt->text().toUInt(nullptr, 16) == 0){ + ui->unpackerDumpArm7OverlayBtn->setEnabled(false); + ui->unpackerDumpArm7OverlayFilesBtn->setEnabled(false); + } +} + +void MainWindow::disableExtractionButtons() +{ + ui->unpackerExtractorGbx->setEnabled(false); + ui->unpackerExtraGbx->setEnabled(false); +} + +bool MainWindow::dumpHeader(const std::string& dirPath) +{ + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + 0, + ui->unpackerHeaderSizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::dumpArm9Bin(const std::string& dirPath, bool dumpExtraBytes) +{ + uint32_t size = ui->unpackerARM9SizeEdt->text().toUInt(nullptr, 16); + if (dumpExtraBytes) + size += 12; + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + ui->unpackerARM9RomAddrEdt->text().toUInt(nullptr, 16), + size); +} + +bool MainWindow::dumpArm7Bin(const std::string& dirPath) +{ + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + ui->unpackerARM7RomAddrEdt->text().toUInt(nullptr, 16), + ui->unpackerARM7SizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::dumpFnt(const std::string& dirPath) +{ + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + ui->unpackerFilenameTableAddrEdt->text().toUInt(nullptr, 16), + ui->unpackerFilenameTableSizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::dumpFat(const std::string& dirPath) +{ + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + ui->unpackerFATAddrEdt->text().toUInt(nullptr, 16), + ui->unpackerFATSizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::dumpArm9Overlay(const std::string& dirPath) +{ + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + ui->unpackerARM9OverlayAddrEdt->text().toUInt(nullptr, 16), + ui->unpackerARM9OverlaySizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::dumpArm9OverlayFiles(const std::string& dirPath) +{ + return false; // TODO: implement me! +} + +bool MainWindow::dumpArm7Overlay(const std::string& dirPath) +{ + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + ui->unpackerARM7OverlayAddrEdt->text().toUInt(nullptr, 16), + ui->unpackerARM7OverlaySizeEdt->text().toUInt(nullptr, 16)); +} + +bool MainWindow::dumpArm7OverlayFiles(const std::string& dirPath) +{ + return false; // TODO: implement me! +} + +bool MainWindow::dumpIconTitle(const std::string& dirPath) +{ + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + ui->unpackerIconTitleEdt->text().toUInt(nullptr, 16), + 0xA00); +} + +bool MainWindow::dumpFatFiles(const std::string& dirPath) +{ + uint32_t startAddr = ui->unpackerIconTitleEdt->text().toUInt(nullptr, 16) + IconTitleSize; + uint32_t size = ui->unpackerUsedRomSizeEdt->text().toUInt(nullptr, 16) - startAddr; + + return ndsFactory.dumpDataFromFile( + ui->loadedRomPath->text().toStdString(), + dirPath, + startAddr, + size); +} + + +bool MainWindow::dumpEverything(QString dirPath) +{ + + if(!dumpHeader(QDir::toNativeSeparators(dirPath+"/header.bin").toStdString())) + return false; + if(!dumpArm9Bin(QDir::toNativeSeparators(dirPath+"/arm9.bin").toStdString(), true)) + return false; + if(!dumpArm7Bin(QDir::toNativeSeparators(dirPath+"/arm7.bin").toStdString())) + return false; + if(!dumpFnt(QDir::toNativeSeparators(dirPath+"/fnt.bin").toStdString())) + return false; + if(!dumpFat(QDir::toNativeSeparators(dirPath+"/fat.bin").toStdString())) + return false; + if(ui->unpackerARM9OverlayAddrEdt->text().toUInt(nullptr, 16) != 0) { + if(!dumpArm9Overlay(QDir::toNativeSeparators(dirPath+"/a9ovr.bin").toStdString())) + return false; + if(!dumpArm9OverlayFiles(QDir::toNativeSeparators(dirPath+"/a9ovr_data.bin").toStdString())) + return false; + } + if(ui->unpackerARM7OverlayAddrEdt->text().toUInt(nullptr, 16) != 0) { + if(!dumpArm7Overlay(QDir::toNativeSeparators(dirPath+"/a7ovr.bin").toStdString())) + return false; + if(!dumpArm7OverlayFiles(QDir::toNativeSeparators(dirPath+"/a7ovr_data.bin").toStdString())) + return false; + } + if(!dumpIconTitle(QDir::toNativeSeparators(dirPath+"/itl.bin").toStdString())) + return false; + if(!dumpFatFiles(QDir::toNativeSeparators(dirPath+"/fat_data.bin").toStdString())) + return false; + + return true; +} + +bool MainWindow::decodeFatFiles() +{ + // TODO: implement me! +} diff --git a/unpackertabsignals.cpp b/unpackertabsignals.cpp new file mode 100644 index 0000000..d90d8d3 --- /dev/null +++ b/unpackertabsignals.cpp @@ -0,0 +1,209 @@ +#include +#include +#include +#include "mainwindow.h" +#include "ui_mainwindow.h" + + +void MainWindow::on_loadRomBtn_clicked() +{ + std::vector romHeader; + NDSHeader *pNDSHeader; + + QString romPath = QFileDialog::getOpenFileName( + Q_NULLPTR, + "NDS Rom", + QDir::currentPath(), + "NDS Rom (*.nds)"); + + if( !romPath.isNull() ) + { + ui->loadedRomPath->setText(romPath.toUtf8()); + } + + if (ndsFactory.loadRomHeader(ui->loadedRomPath->text().toStdString(), romHeader)) + { + pNDSHeader = reinterpret_cast(romHeader.data()); + populateHeader(pNDSHeader); + enableExtractionButtons(); + } + else + { + disableExtractionButtons(); + } +} + +void MainWindow::on_unpackerDumpHeaderBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS Header", + "header.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpHeader(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpArm9Btn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS ARM9", + "arm9.bin", + "Binary (*.bin)"); + + QMessageBox::StandardButton dumpExtraBytes = QMessageBox::question( + this, + "NDS Factory", + "Do you want to dump the extra 12 bytes? (click yes if you want a 1:1 arm9 dump)", + QMessageBox::Yes|QMessageBox::No); + + if (!dirPath.isNull()) + { + dumpArm9Bin(dirPath.toStdString(), dumpExtraBytes == QMessageBox::Yes ? true : false) + ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpArm7Btn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS ARM7", + "arm7.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpArm7Bin(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpFntBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS FNT", + "fnt.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpFnt(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpFatBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS FAT", + "fat.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpFat(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpArm9OverlayBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS ARM9 Overlay", + "a9ovr.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpArm9Overlay(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpArm7OverlayBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS ARM7 Overlay", + "a7ovr.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpArm7Overlay(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpIconTitleLogoBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS IconTitleLogo", + "itl.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpIconTitle(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpFatFilesBtn_clicked() +{ + QString dirPath = QFileDialog::getSaveFileName( + Q_NULLPTR, + "NDS FAT Files", + "fat_data.bin", + "Binary (*.bin)"); + + if (!dirPath.isNull()) + { + dumpFatFiles(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDumpArm9OverlayFilesBtn_clicked() +{ + QMessageBox::warning(this, tr("NDS Factory"), tr("This function is currently not implemented!")); + //dumpArm9OverlayFiles() +} + +void MainWindow::on_unpackerDumpArm7OverlayFilesBtn_clicked() +{ + QMessageBox::warning(this, tr("NDS Factory"), tr("This function is currently not implemented!")); + //dumpArm7OverlayFiles() +} + +void MainWindow::on_unpackerDumpEverythingBtn_clicked() +{ + QString dirPath = QFileDialog::getExistingDirectory( + this, tr("Select Directory"), + "", + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + if (!dirPath.isNull()) + { + dumpEverything(dirPath) ? QMessageBox::information(this, tr("NDS Factory"), tr("Extraction completed!")) + : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the extraction!")); + } +} + +void MainWindow::on_unpackerDecodeFatFilesBtn_clicked() +{ + QMessageBox::warning(this, tr("NDS Factory"), tr("This function is currently not implemented!")); + decodeFatFiles(); +} +