Compare commits

..

No commits in common. "master" and "V1.0" have entirely different histories.
master ... V1.0

51 changed files with 3364 additions and 3952 deletions

View File

@ -1,154 +0,0 @@
name: Build and Release on Tag
on:
push:
tags:
- v*
jobs:
build-linux:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4.1.7
- name: Create Build Environment
run: |
sudo apt-get update
sudo apt-get install -y build-essential libgl1-mesa-dev libglvnd-dev cmake qt6-base-dev
mkdir build
- name: Configure CMake
working-directory: ${{github.workspace}}/build
shell: bash
run: |
cmake -DCMAKE_BUILD_TYPE=Release ..
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: |
make -j4
- name: Archive Artifact
working-directory: ${{github.workspace}}/build
shell: bash
run: |
tar -czvf NDSFactory-${{ github.ref_name }}-Linux-x64.tar.gz NDSFactory ../README.md ../LICENSE
- name: Release on GitHub
uses: softprops/action-gh-release@v2.0.8
if: startsWith(github.ref, 'refs/tags/')
with:
files: "build/NDSFactory-${{ github.ref_name }}-Linux-x64.tar.gz"
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4.1.7
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: "6.7.2"
- name: Install CMake
uses: lukka/get-cmake@latest
- name: Create Build Environment
run: |
mkdir -p build/x86_64 build/arm64 build/universal
- name: Configure CMake (x86_64)
working-directory: ${{ github.workspace }}/build/x86_64
shell: bash
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 ../..
- name: Configure CMake (arm64)
working-directory: ${{ github.workspace }}/build/arm64
shell: bash
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 ../..
- name: Build (x86_64)
working-directory: ${{ github.workspace }}/build/x86_64
shell: bash
run: |
make -j4
- name: Build (arm64)
working-directory: ${{ github.workspace }}/build/arm64
shell: bash
run: |
make -j4
- name: Create Universal Binary
working-directory: ${{ github.workspace }}/build
shell: bash
run: |
cp -R x86_64/NDSFactory.app universal/
lipo -create -output universal/NDSFactory.app/Contents/MacOS/NDSFactory x86_64/NDSFactory.app/Contents/MacOS/NDSFactory arm64/NDSFactory.app/Contents/MacOS/NDSFactory
- name: Deploy Qt Frameworks
working-directory: ${{ github.workspace }}/build/universal
shell: bash
run: |
macdeployqt NDSFactory.app -verbose=1
- name: Archive Artifact
working-directory: ${{ github.workspace }}/build/universal
shell: bash
run: |
zip -r NDSFactory-${{ github.ref_name }}-macOS.zip NDSFactory.app ../README.md ../LICENSE
- name: Release on GitHub
uses: softprops/action-gh-release@v2.0.8
if: startsWith(github.ref, 'refs/tags/')
with:
files: "build/universal/NDSFactory-${{ github.ref_name }}-macOS.zip"
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4.1.7
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: "6.7.2"
- name: Install CMake
uses: lukka/get-cmake@latest
- name: Create Build Environment
run: |
mkdir build
- name: Configure CMake
working-directory: ${{github.workspace}}/build
run: |
cmake ..
- name: Build
working-directory: ${{github.workspace}}/build
run: |
cmake --build . -j4 --config Release
mkdir .\Release\prod
move .\Release\NDSFactory.exe .\Release\prod
windeployqt .\Release\prod\NDSFactory.exe
- name: Archive Artifact
working-directory: ${{github.workspace}}/build/Release
run: |
xcopy ..\..\README.md .\prod
xcopy ..\..\LICENSE .\prod
powershell "Compress-Archive -Path .\prod\* -DestinationPath .\NDSFactory-${{ github.ref_name }}-Windows-x64.zip"
- name: Release on GitHub
uses: softprops/action-gh-release@v2.0.8
if: startsWith(github.ref, 'refs/tags/')
with:
files: "build/Release/NDSFactory-${{ github.ref_name }}-Windows-x64.zip"

398
.gitignore vendored
View File

@ -41,401 +41,3 @@ target_wrapper.*
# QtCreator CMake # QtCreator CMake
CMakeLists.txt.user* CMakeLists.txt.user*
# OS specific
.DS_Store
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
out/
build/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

View File

@ -1,105 +0,0 @@
cmake_minimum_required(VERSION 3.25)
project(NDSFactory)
# Require Qt6 components
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
# Include sanitizers
include(${CMAKE_SOURCE_DIR}/cmake/sanitizers.cmake)
# Determine the Git commit hash if in a git repository
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else()
set(GIT_COMMIT_HASH "")
endif()
# Configure the revision header file
configure_file(
${CMAKE_SOURCE_DIR}/ui/dialogs/about/revision.h.in
${CMAKE_SOURCE_DIR}/ui/dialogs/about/revision.h
)
# Collect source and header files
## Dialogs
file(GLOB_RECURSE DIALOGS_HEADERS ui/dialogs/*.h)
file(GLOB_RECURSE DIALOGS_SOURCES ui/dialogs/*.cpp)
file(GLOB_RECURSE DIALOGS_UIS ui/dialogs/*.ui)
## Tabs
file(GLOB_RECURSE TABS_HEADERS ui/tabs/*.h)
file(GLOB_RECURSE TABS_SOURCES ui/tabs/*.cpp)
## Models
file(GLOB_RECURSE MODELS_HEADERS ui/models/*.h)
file(GLOB_RECURSE MODELS_SOURCES ui/models/*.cpp)
## Utils
file(GLOB_RECURSE UTILS_HEADERS ui/utils/*.h)
## NDSFactory
file(GLOB_RECURSE NDSFACTORY_SOURCES ndsfactory/*.cpp)
file(GLOB_RECURSE NDSFACTORY_HEADERS ndsfactory/*.h)
set(SOURCES
main.cpp
ui/mainwindow.cpp
${NDSFACTORY_SOURCES}
${DIALOGS_SOURCES}
${MODELS_SOURCES}
${TABS_SOURCES}
)
SET(HEADERS
ui/mainwindow.h
${NDSFACTORY_HEADERS}
${TABS_HEADERS}
${MODELS_HEADERS}
${DIALOGS_HEADERS}
${UTILS_HEADERS}
)
set(FORMS
ui/mainwindow.ui
${DIALOGS_UIS}
)
# Platform-specific executable creation
if(APPLE)
set(MACOSX_BUNDLE_ICON_FILE ndsfactory.icns)
set(MACOS_ICNS "res/ndsfactory.icns")
set_source_files_properties(${MACOS_ICNS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SOURCES} ${HEADERS} ${FORMS} ${MACOS_ICNS})
elseif(WIN32)
set(WIN32_RESOURCES "res/resources.rc")
add_executable(${PROJECT_NAME} WIN32 ${SOURCES} ${HEADERS} ${FORMS} ${WIN32_RESOURCES})
else()
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS} ${FORMS})
endif()
# Set C++ standard for the target
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
# Enable Qt's automatic features for the target
set_target_properties(${PROJECT_NAME} PROPERTIES
AUTOMOC ON
AUTOUIC ON
)
# Add compile options for different compilers
if(MSVC)
target_compile_options(${PROJECT_NAME} PRIVATE /WX /W4 /EHsc)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)
endif()
# Link the necessary Qt6 libraries
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)

View File

@ -1,22 +0,0 @@
{
"version": 3,
"configurePresets": [
{
"hidden": true,
"name": "Qt",
"cacheVariables": {
"CMAKE_PREFIX_PATH": "$env{QTDIR}"
},
"vendor": {
"qt-project.org/Qt": {
"checksum": "wVa86FgEkvdCTVp1/nxvrkaemJc="
}
}
}
],
"vendor": {
"qt-project.org/Presets": {
"checksum": "67SmY24ZeVbebyKD0fGfIzb/bGI="
}
}
}

View File

@ -1,76 +0,0 @@
{
"version": 3,
"configurePresets": [
{
"name": "Qt-Debug",
"inherits": "Qt-Default",
"binaryDir": "${sourceDir}/out/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_FLAGS": "-DQT_QML_DEBUG"
},
"environment": {
"QML_DEBUG_ARGS": "-qmljsdebugger=file:{f93ee848-589e-4ca8-9f00-8ec9e59822e9},block"
}
},
{
"name": "Qt-Release",
"inherits": "Qt-Default",
"binaryDir": "${sourceDir}/out/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"hidden": true,
"name": "Qt-Default",
"inherits": "6.7.2_msvc2019_64",
"vendor": {
"qt-project.org/Default": {
"checksum": "gw/ERk1cQwC3YNpVspzQ2Sww4Qk="
}
}
},
{
"hidden": true,
"name": "6.7.2_msvc2019_64",
"inherits": "Qt",
"environment": {
"QTDIR": "C:/Qt/6.7.2/msvc2019_64"
},
"architecture": {
"strategy": "external",
"value": "x64"
},
"generator": "Ninja",
"vendor": {
"qt-project.org/Version": {
"checksum": "Bix3VTiu0VJT9MULsciS2xuiRSY="
}
}
},
{
"hidden": true,
"name": "QtDesignStudio_qt6_design_studio_reduced_version",
"inherits": "Qt",
"environment": {
"QTDIR": "C:/Qt/Tools/QtDesignStudio/qt6_design_studio_reduced_version"
},
"architecture": {
"strategy": "external",
"value": "x64"
},
"generator": "Ninja",
"vendor": {
"qt-project.org/Version": {
"checksum": "ygR+cS5HulD9XNDRlzjWPEl2jZo="
}
}
}
],
"vendor": {
"qt-project.org/Presets": {
"checksum": "Uup2yLzTIsD1yvrCY3TjhVEtXMo="
}
}
}

53
NDSFactory.pro Normal file
View File

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

View File

@ -3,64 +3,62 @@
[![GPL Licence](https://badges.frapsoft.com/os/gpl/gpl.png?v=103)](https://opensource.org/licenses/GPL-3.0/) [![GPL Licence](https://badges.frapsoft.com/os/gpl/gpl.png?v=103)](https://opensource.org/licenses/GPL-3.0/)
A tool to unpack & repack Nintendo DS ROMs (.nds) A tool to unpack & repack Nintendo DS roms (.nds)
If you find this software useful, please consider supporting it:
[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Z8Z511SOI) If you find this software useful, please [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Z8Z511SOI)
![screenshot](https://raw.githubusercontent.com/Luca1991/NDSFactory/master/screenshot.png) ![screenshot](https://raw.githubusercontent.com/Luca1991/NDSFactory/master/screenshot.png)
**!!!ROM WITH OVERLAY ARE CURRENTLY NOT SUPPORTED!!!**
# Description # Description
NDSFactory helps you easily unpack and repack Nintendo DS ROMs, but **some technical knowledge is required.** This software will help you to easily unpack and repack Nintendo DS roms, but **IT REQUIRES SOME KNOWLEDGE!**
A typical NDS ROM consists of the following sections: Basically an NDS software is composed of the following sections:
* Header * Header
* ARM9 Binary * ARM9 Binary
* ARM9 Overlay (Optional)
* ARM9 Overlay Files (Optional)
* ARM7 Binary * ARM7 Binary
* ARM7 Overlay (Optional)
* ARM7 Overlay Files (Optional)
* FNT (Filename Table) * FNT (Filename Table)
* FAT (File Allocation Table) * FAT (File Allocation Table)
* ARM9/ARM7 Overlay (Optional)
* ARM9/ARM7 Overlay Files (Optional)
* Icon/Title Logo * Icon/Title Logo
* FAT Files (The actual files used by the software, like Graphics, Music etc.) * FAT Files (The actual files used by the software, like Graphics, Music etc.)
NDSFactory allows you to extract these sections, modify them as needed, and rebuild the ROM with your edited sections. If modified sections are larger than the original, you must specify their new physical address and size in the header. **Ensure that sections do not overlap and remember to patch the FAT.BIN if necessary.** With NDSFactory you can extract these sections, modify them using your prefered way and the rebuild the rom with your edited sections.
If the modified sections are bigger than the original ones, you can specify their new physical adddress and size in the header: if so, **make
sure that they DON'T OVERLAP, and remember to PATCH THE FAT.BIN** (more on this later).
This tool is particularly useful for modding games or writing trainers. **This software will be particularly useful if you want to mod your games or write a trainer for them.**
# How to use # How to use it
## Unpacker Tab ## Unpacker Tab
In the Unpacker Tab, you can load your Nintendo DS software (.nds) and extract the ROM sections. Take note of the original address of the FAT files, as you will need this value if you alter the addresses and sizes of the sections or if you want to extract its contents. In the upacker tab you can load your Nintendo DS software (.nds) and then you can extract the rom sections.
Please note the Original Address of the FAT Files, you will need this value later if you are going to alter the addresses and size of the sections.
**You can then do what you want with these sections (inject code, apply patches etc.)** **You can then do what you want with these sections (inject code, apply patches etc.)**
## Packer Tab ## Packer Tab
In the Packer Tab, you can recreate a .nds file using your edited sections. In the packer tab you can re-create an .nds file using your edited sections. If your sections are bigger than the originals, you have to edit their addresses and size (in the header). **Make sure that the addresses don't overlap, or the final rom will be broken**. If you are repacking edited sections, and the FAT Files Address is different than the original one, **make sure to patch the FAT (fat.bin)**: the FAT is a list of absolute addresses (representing each file start adddress and end andress), so you need to update them (you can easily do this using the FAT Patching Tab).
If your sections are larger than the originals, you must update their addresses and sizes in the header.
Ensure that the addresses do not overlap, or the final ROM will be broken.
If you repack edited sections and the FAT files' address is different from the original, you must patch the FAT (fat.bin).
The FAT contains absolute addresses representing each file's start and end addresses, so you need to update them accordingly (use the FAT Patching Tab for this).
WARNING: if the ROM contains ARM9/ARM7 overlays and your sections are larger than the original, you must manually update the overlay offsets in the ovr and fat binaries (using an hex editor). ## Fat Patching Tab
In this tab you can easily patch the FAT section (fat.bin). You have to do this only if the FAT Files (fat_data.bin) final address is different than the original one.
Patching the FAT is easy, all you have to do is load your fat.bin, and fill the original address and the new address of fat_data.bin. This will produce a patched fat.bin that
you can use in the packing process.
## Fat Tools Tab
In this tab, you can:
* extract the FAT files from fat_data.bin.
* rebuild the FAT files into a new fat.bin and fat_data.bin.
If the ROM contains ARM9/ARM7 overlays you must provide the original fat.bin to extract the overlay offsets.
WARNING: DO NOT MODIFY FAT FILES NAMES OR EXTENSIONS, OR YOU WILL NEED A NEW fnt.bin.
* patch the FAT section (fat.bin): this is only necessary if the FAT files' final address (fat_data.bin) differs from the original.
Patching the FAT is straightforward: load your fat.bin, and fill in the original and new addresses of fat_data.bin. This will produce a patched fat.bin for use in the packing process.
# Credits # Know Limitations/Possible Future Featurs/Bugs
If you find a bug, feel free to open an issue or submit a pull request :) * Add support for roms with OVERLAY
* Add support to decode FAT Files (extract single files one by one)
* Add support to rebuild a new fat_data.bin and fat.bin from a set of files inside a directory
* Design a nice logo/icon
Special thanks to [Antonio Barba](https://github.com/antoniobarba) & [Davide Trogu](https://github.com/Dax89) If you found a bug, feel free to open an issue or send a PR :)
### Developed with ❤ by Luca D'Amico
### Special thanks to Antonio Barba & Davide Trogu
Developed with ❤ by Luca D'Amico

15
aboutdialog.cpp Normal file
View File

@ -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;
}

22
aboutdialog.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef ABOUTDIALOG_H
#define ABOUTDIALOG_H
#include <QDialog>
namespace Ui {
class AboutDialog;
}
class AboutDialog : public QDialog
{
Q_OBJECT
public:
AboutDialog(QWidget *parent = nullptr);
~AboutDialog();
private:
Ui::AboutDialog *ui;
};
#endif // ABOUTDIALOG_H

View File

@ -7,33 +7,33 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>400</width>
<height>179</height> <height>300</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>About</string> <string>Dialog</string>
</property> </property>
<widget class="QDialogButtonBox" name="aboutCloseBtnBx"> <widget class="QDialogButtonBox" name="aboutCloseBtnBx">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>300</x> <x>300</x>
<y>140</y> <y>260</y>
<width>81</width> <width>81</width>
<height>32</height> <height>32</height>
</rect> </rect>
</property> </property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Ok</set> <set>QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="aboutSoftwareNameLbl"> <widget class="QLabel" name="aboutSoftwareNameLbl">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>20</y> <y>150</y>
<width>381</width> <width>381</width>
<height>31</height> <height>31</height>
</rect> </rect>
@ -42,33 +42,33 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>NDSFactory V1.3.2</string> <string>NDS Factory V1.0</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="aboutSoftwareAuthorLbl"> <widget class="QLabel" name="aboutSoftwareAuthorLbl">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>70</y> <y>180</y>
<width>381</width> <width>381</width>
<height>20</height> <height>20</height>
</rect> </rect>
</property> </property>
<property name="text"> <property name="text">
<string>(C) 2019-2025 - Luca D'Amico</string> <string>(C) 2019 - Luca D'Amico</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="aboutSpecialThanks"> <widget class="QLabel" name="aboutSpecialThanks">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>90</y> <y>200</y>
<width>381</width> <width>381</width>
<height>20</height> <height>20</height>
</rect> </rect>
@ -77,14 +77,14 @@
<string>Special Thanks To:</string> <string>Special Thanks To:</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="aboutSpecialThanks2ndLine"> <widget class="QLabel" name="aboutSpecialThanks2ndLine">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>110</y> <y>220</y>
<width>381</width> <width>381</width>
<height>20</height> <height>20</height>
</rect> </rect>
@ -93,23 +93,7 @@
<string>Dax89 (Davide Trogu) &amp; Kaneb (Antonio Barba)</string> <string>Dax89 (Davide Trogu) &amp; Kaneb (Antonio Barba)</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set> <set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QLabel" name="aboutSoftwareBuildLbl">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>381</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Build Info</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property> </property>
</widget> </widget>
</widget> </widget>

View File

@ -1,55 +0,0 @@
# Build Types
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel tsan asan lsan msan ubsan"
FORCE)
# ThreadSanitizer
set(CMAKE_C_FLAGS_TSAN
"-fsanitize=thread -g -O1"
CACHE STRING "Flags used by the C compiler during ThreadSanitizer builds."
FORCE)
set(CMAKE_CXX_FLAGS_TSAN
"-fsanitize=thread -g -O1"
CACHE STRING "Flags used by the C++ compiler during ThreadSanitizer builds."
FORCE)
# AddressSanitize
set(CMAKE_C_FLAGS_ASAN
"-fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1"
CACHE STRING "Flags used by the C compiler during AddressSanitizer builds."
FORCE)
set(CMAKE_CXX_FLAGS_ASAN
"-fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1"
CACHE STRING "Flags used by the C++ compiler during AddressSanitizer builds."
FORCE)
# LeakSanitizer
set(CMAKE_C_FLAGS_LSAN
"-fsanitize=leak -fno-omit-frame-pointer -g -O1"
CACHE STRING "Flags used by the C compiler during LeakSanitizer builds."
FORCE)
set(CMAKE_CXX_FLAGS_LSAN
"-fsanitize=leak -fno-omit-frame-pointer -g -O1"
CACHE STRING "Flags used by the C++ compiler during LeakSanitizer builds."
FORCE)
# MemorySanitizer
set(CMAKE_C_FLAGS_MSAN
"-fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2"
CACHE STRING "Flags used by the C compiler during MemorySanitizer builds."
FORCE)
set(CMAKE_CXX_FLAGS_MSAN
"-fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2"
CACHE STRING "Flags used by the C++ compiler during MemorySanitizer builds."
FORCE)
# UndefinedBehaviour
set(CMAKE_C_FLAGS_UBSAN
"-fsanitize=undefined"
CACHE STRING "Flags used by the C compiler during UndefinedBehaviourSanitizer builds."
FORCE)
set(CMAKE_CXX_FLAGS_UBSAN
"-fsanitize=undefined"
CACHE STRING "Flags used by the C++ compiler during UndefinedBehaviourSanitizer builds."
FORCE)

View File

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

49
fatpatchingtabsignals.cpp Normal file
View File

@ -0,0 +1,49 @@
#include <QFileDialog>
#include <QMessageBox>
#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!"));
}

View File

@ -1,4 +1,5 @@
#pragma once #ifndef FATSTRUCT_H
#define FATSTRUCT_H
#include <cstdint> #include <cstdint>
@ -7,7 +8,4 @@ struct FatRange {
uint32_t endAddr; uint32_t endAddr;
}; };
struct FatFileID { #endif // FATSTRUCT_H
uint16_t id;
std::string path;
};

View File

@ -1,23 +1,11 @@
#include "ui/mainwindow.h" #include "mainwindow.h"
#include <QApplication> #include <QApplication>
#include <QStyleFactory>
#include "ui/utils/theme.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication::setStyle(QStyleFactory::create("Fusion")); QApplication a(argc, argv);
QApplication app(argc, argv); MainWindow w;
app.setApplicationName("NDSFactory"); w.show();
app.setOrganizationName("NDSFactory");
QString theme = getCurrentTheme(); return a.exec();
if(theme == "dark")
setDarkTheme(app);
else if(theme == "light")
setLightTheme(app);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
} }

View File

@ -1,8 +1,6 @@
#include <QApplication>
#include "mainwindow.h" #include "mainwindow.h"
#include "aboutdialog.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "dialogs/about/aboutdialog.h"
#include "utils/theme.h"
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
@ -27,18 +25,3 @@ void MainWindow::on_actionAbout_triggered()
AboutDialog aboutDialog; AboutDialog aboutDialog;
aboutDialog.exec(); aboutDialog.exec();
} }
void MainWindow::on_actionDark_triggered()
{
setTheme("dark");
}
void MainWindow::on_actionLight_triggered()
{
setTheme("light");
}
void MainWindow::on_actionDefault_triggered()
{
setTheme("default");
}

106
mainwindow.h Normal file
View File

@ -0,0 +1,106 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <cstdint>
#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

2066
mainwindow.ui Normal file

File diff suppressed because it is too large Load Diff

147
ndsfactory.cpp Normal file
View File

@ -0,0 +1,147 @@
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include "ndsfactory.h"
#include "fatstruct.h"
NDSFactory::NDSFactory()
{
}
bool NDSFactory::loadRomHeader(const std::string& romPath, std::vector<char>& 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<unsigned long>(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<char> 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<char>& 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<char> 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<char>& 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<char> paddingBytes(size, paddingChar);
return writeBytesToFile(paddingBytes, filePath, startAddr, size);
}
int NDSFactory::getCardSizeInBytes(int cardType)
{
return static_cast<int>(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<char> 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<unsigned long>(sectionSize));
sectionFile.seekg (0, std::ios::beg);
sectionFile.read (fatBytes.data(), sectionSize);
sectionFile.close();
FatRange* pfatrange = reinterpret_cast<FatRange*>(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<uint32_t>(sectionSize));
}

29
ndsfactory.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef NDSFACTORY_H
#define NDSFACTORY_H
#include <string>
#include <vector>
#include <cstdint>
#include "ndsheader.h"
class NDSFactory
{
public:
NDSFactory();
bool loadRomHeader(const std::string& romPath, std::vector<char>& header);
bool dumpDataFromFile(const std::string& romPath, const std::string& savePath, uint32_t startAddr, uint32_t size);
bool readBytesFromFile(std::vector<char>& 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<char>& 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

View File

@ -1,40 +0,0 @@
#pragma once
#include <cstdint>
static const uint16_t lCRCTable[] =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};

View File

@ -1,405 +0,0 @@
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <filesystem>
#include <format>
#include "ndsfactory.h"
#include "fatstruct.h"
#include "crctable.h"
// Byte offsets for interpreting memory
#define SECOND_BYTE_SHIFT 8
#define THIRD_BYTE_SHIFT 16
#define FOURTH_BYTE_SHIFT 24
// Magic values for FAT extraction
#define CONTROL_BYTE_LENGTH_MASK 0x7F
#define CONTROL_BYTE_DIR_MASK 0x80
#define DUMMY_CONTROL_VALUE 0xFF
#define FNT_HEADER_OFFSET_MASK 0XFFF
#define ROOT_DIRECTORY_ADDRESS 0xF000
NFResult NDSFactory::loadRomHeader(const std::string& romPath, std::vector<char>& romHeader)
{
std::streampos headerSize = sizeof(NDSHeader);
std::ifstream romFile (romPath, std::ios::binary);
if (!romFile.is_open())
return NFResult({ false, "Error opening file: " + romPath });
romHeader.resize(static_cast<unsigned long>(headerSize));
romFile.read (romHeader.data(), headerSize);
romFile.close();
return NFResult({ true, "" });
}
NFResult NDSFactory::dumpDataFromFile(const std::string& romPath, const std::string& savePath, uint32_t startAddr, uint32_t size)
{
std::ifstream romFile (romPath, std::ios::binary);
std::ofstream savedFile (savePath, std::ios::binary);
if (!romFile.is_open()) return NFResult({ false, "Error opening file: " + romPath });
if (!savedFile.is_open()) return NFResult({ false, "Error creating file: " + savePath });
std::vector<char> dumpBuffer(size);
romFile.seekg (startAddr, std::ios::beg);
romFile.read (dumpBuffer.data(), size);
romFile.close();
savedFile.write(dumpBuffer.data(), size);
savedFile.close();
return NFResult({ true, "" });
}
bool NDSFactory::logToFile(const std::string& logPath, const std::string& log)
{
std::ofstream savedFile(logPath, std::ios::out | std::ios::binary | std::ios::app);
if (!savedFile.is_open()) return false;
savedFile.write(log.c_str(), log.size());
savedFile.close();
return true;
}
NFResult NDSFactory::readBytesFromFile(std::vector<char>& byteBuffer, const std::string& romPath, uint32_t startAddr, uint32_t size)
{
std::ifstream romFile (romPath, std::ios::binary);
if (!romFile.is_open())
return NFResult({ false, "Error opening file: " + romPath });
romFile.seekg (startAddr, std::ios::beg);
romFile.read (byteBuffer.data(), size);
romFile.close();
return NFResult({ true, "" });
}
NFResult NDSFactory::writeSectionToFile(const std::string& sectionPath, const std::string& savePath, uint32_t startAddr, uint32_t size)
{
std::ifstream sectionFile (sectionPath, std::ios::binary);
if (!sectionFile.is_open())
return NFResult({ false, "Error opening file: " + sectionPath });
std::vector<char> dumpBuffer(size);
sectionFile.read (dumpBuffer.data(), size);
sectionFile.close();
return writeBytesToFile(dumpBuffer, savePath, startAddr, size);
}
NFResult NDSFactory::writeBytesToFile(std::vector<char>& byteBuffer, const std::string& savePath, uint32_t startAddr, uint32_t size)
{
std::ofstream savedFile (savePath, std::ios::in | std::ios::out | std::ios::binary);
if (!savedFile.is_open())
{
savedFile.open(savePath, std::ios::out | std::ios::binary);
if (!savedFile.is_open()) {
return NFResult({ false, "Error creating file: " + savePath });
}
savedFile.close();
savedFile.open(savePath, std::ios::in | std::ios::out | std::ios::binary);
if (!savedFile.is_open())
return NFResult({ false, "Error opening file: " + savePath });
}
savedFile.seekp(startAddr);
savedFile.write(byteBuffer.data(), size);
savedFile.close();
return NFResult({ true, "" });
}
NFResult NDSFactory::writePaddingToFile(char paddingChar, const std::string& filePath, uint32_t startAddr, const uint32_t size)
{
std::vector<char> paddingBytes(size, paddingChar);
return writeBytesToFile(paddingBytes, filePath, startAddr, size);
}
int NDSFactory::getCardSizeInBytes(int cardType)
{
return static_cast<int>(pow(2, 17 + cardType));
}
bool NDSFactory::checkArm9FooterPresence(const std::string& sectionPath, uint32_t size)
{
std::ifstream sectionFile (sectionPath, std::ios::binary | std::ios::ate);
if (sectionFile.is_open())
{
std::streamoff sectionRealSize = sectionFile.tellg();
sectionFile.close();
if (sectionRealSize >= size + Arm9FooterSize)
{
return true;
}
}
return false;
}
NFResult NDSFactory::extractFatData(const std::string& fatDataSectionPath, const std::string& fatSectionPath,
const std::string& fntSectionPath, uint32_t originalFatDataAddr, const std::string& savePath, bool logFileIDs)
{
std::vector<char> fatDataBytes;
std::vector<char> fatBytes;
std::vector<char> fntBytes;
std::ifstream fatDataSectionFile(fatDataSectionPath, std::ios::in | std::ios::binary | std::ios::ate);
if (!fatDataSectionFile.is_open()) return NFResult({ false, "Error opening file: " + fatDataSectionPath });
std::streamoff fatDataSectionSize = fatDataSectionFile.tellg();
fatDataBytes.resize(fatDataSectionSize);
fatDataSectionFile.seekg(0, std::ios::beg);
fatDataSectionFile.read(fatDataBytes.data(), fatDataSectionSize);
fatDataSectionFile.close();
std::ifstream fatSectionFile(fatSectionPath, std::ios::in | std::ios::binary | std::ios::ate);
if (!fatSectionFile.is_open()) return NFResult({ false, "Error opening file: " + fatSectionPath });
std::streamoff fatSectionSize = fatSectionFile.tellg();
fatBytes.resize(fatSectionSize);
fatSectionFile.seekg(0, std::ios::beg);
fatSectionFile.read(fatBytes.data(), fatSectionSize);
fatSectionFile.close();
std::ifstream fntSectionFile(fntSectionPath, std::ios::in | std::ios::binary | std::ios::ate);
if (!fntSectionFile.is_open()) return NFResult({ false, "Error opening file: " + fntSectionPath });
std::streamoff fntSectionSize = fntSectionFile.tellg();
fntBytes.resize(fntSectionSize);
fntSectionFile.seekg(0, std::ios::beg);
fntSectionFile.read(fntBytes.data(), fntSectionSize);
fntSectionFile.close();
FatRange* pfatrange = reinterpret_cast<FatRange*>(fatBytes.data());
// This lambda function was written by NyuBlara, all credits to him.
// I edited it a bit to make it work with the rest of the updated code.
auto parseFolder = [this, fntBytes, pfatrange, fatDataSectionPath, originalFatDataAddr, savePath, logFileIDs](uint32_t folderId, std::string curPath, auto& parseFolder) {
uint32_t currentOffset = 8 * (folderId & FNT_HEADER_OFFSET_MASK); // offset for the current directory's info in the FNT header
// Only the lower 12 bit of the given offset are relevant
// ---------------------------------------------------------------------
// About how the FAT and FNT work :
// The FNT has two sections :
// a "header" where every entry contains :
//// - a 4-byte address where the corresponding directory's data starts in the body
//// - a 2-byte offset that is the index of the first file of the directory in the FAT
//// (e.g. : if the offset is 42, the first file in the directory is situated at the ROM addresses stored in the 42nd FAT entry)
//// (and its second will be 43, etc.)
// a "body" where every entry contains :
//// - a length+status/control byte : lower 7 bits (control byte & 0x7F) are a length, highest bit (control byte & 0x80) is set if entry is a directory, and not set if it's a file
//// - a name which length is the length portion of the previous control byte (e.g. : if the control byte was 0x83, the name is three bytes long)
//// - if the entry is a directory, a 2-byte address (where only the lower 12 bit are relevant for some reason) at which this directory's info is located in the FNT header
// Thus, the FNT reading operation will consist in bouncing back and forth between body and header every time we must process a subdirectory
// Thank Heavens for random-access containers !
// ---------------------------------------------------------------------
// Get the 4-byte address for the folder data
uint32_t fntBodyOffset =
(uint32_t)((unsigned char)fntBytes[currentOffset + 3] << (uint32_t)FOURTH_BYTE_SHIFT |
(unsigned char)fntBytes[currentOffset + 2] << (uint32_t)THIRD_BYTE_SHIFT |
(unsigned char)fntBytes[currentOffset + 1] << (uint32_t)SECOND_BYTE_SHIFT |
(unsigned char)fntBytes[currentOffset]);
currentOffset += 4;
// Get the 2-byte offset for the folder's first file in the FAT
uint16_t fatOffset =
(uint16_t)((unsigned char)fntBytes[currentOffset + 1] << SECOND_BYTE_SHIFT |
(unsigned char)fntBytes[currentOffset]);
// Jump to FNT body a specified address
currentOffset = fntBodyOffset;
uint8_t controlByte = DUMMY_CONTROL_VALUE;
while (true)
{
controlByte = fntBytes[currentOffset]; // Entry's control byte
if (controlByte == 0) break; // A control byte of 0 terminates the directory's contents
currentOffset++;
uint8_t nameLength = controlByte & CONTROL_BYTE_LENGTH_MASK; // length of entry name
bool isDir = controlByte & CONTROL_BYTE_DIR_MASK; // set if entry is a directory
// Reconstitute name from bytes
// Btw I wish I could use the actual byte type but I have to comply with the software's choice of using char
std::vector<char> nameString;
for (size_t i = 0; i < nameLength; i++) nameString.push_back(fntBytes[currentOffset++]);
std::string name(&nameString[0], (size_t)nameLength);
std::string newPath = curPath + '/' + name;
if (isDir)
{
// Get the 2-byte address for this folder's info in the FNT header
uint16_t subFolderId = ((unsigned char)fntBytes[currentOffset + 1] << SECOND_BYTE_SHIFT |
(unsigned char)fntBytes[currentOffset]);
currentOffset += 2;
if (!std::filesystem::exists(newPath))
if (!std::filesystem::create_directory(newPath)) return NFResult({ false, "Error creating directory: " + newPath });
if (logFileIDs)
{
std::string log = std::format("{:x}",subFolderId) + ":::" + newPath.substr(savePath.size()+1) + '\n';
if (!logToFile(savePath + "/_file_IDs.txt", log)) return NFResult({ false, "Error writing to file: " + savePath + "/_file_IDs.txt" });
}
// Jump back to the FNT header and repeat the process for subdirectory !
if (!parseFolder(subFolderId, newPath, parseFolder).result) return NFResult({ false, "Error parsing folder: " + newPath });
}
else
{
// Remember we have the offset for the directory's first file in the FAT.
// From then, every file is just the next entry.
// So we just have to use that offset and increment it every time.
uint32_t fileStartAddr = (pfatrange + fatOffset)->startAddr - originalFatDataAddr;
uint32_t fileSize = (pfatrange + fatOffset)->endAddr - (pfatrange + fatOffset)->startAddr;
if (!dumpDataFromFile(fatDataSectionPath, newPath, fileStartAddr, fileSize).result) return NFResult({ false, "Error dumping file: " + newPath });
if (logFileIDs)
{
std::string log = std::format("{:x}", fatOffset) + ":::" + newPath.substr(savePath.size()+1) + '\n';
if (!logToFile(savePath + "/_file_IDs.txt", log)) return NFResult({ false, "Error writing to file: " + savePath + "/_file_IDs.txt" });
}
fatOffset++;
}
}
return NFResult({ true, "" });
};
return parseFolder(ROOT_DIRECTORY_ADDRESS, savePath, parseFolder);
}
NFResult NDSFactory::patchFat(const std::string& fatSectionPath, uint32_t shiftSize, const std::string& savePath)
{
std::vector<char> fatBytes;
std::ifstream sectionFile (fatSectionPath, std::ios::in|std::ios::binary|std::ios::ate);
if (!sectionFile.is_open())
return { false, "Error opening file: " + fatSectionPath };
std::streamoff sectionSize = sectionFile.tellg();
fatBytes.resize(sectionSize);
sectionFile.seekg (0, std::ios::beg);
sectionFile.read (fatBytes.data(), sectionSize);
sectionFile.close();
FatRange* pfatrange = reinterpret_cast<FatRange*>(fatBytes.data());
for(size_t i = 0; i < fatBytes.size(); i += sizeof(FatRange), pfatrange++) {
pfatrange->startAddr += shiftSize;
pfatrange->endAddr += shiftSize;
}
std::remove(savePath.c_str());
return writeBytesToFile(fatBytes, savePath, 0, static_cast<uint32_t>(sectionSize));
}
NFResult NDSFactory::buildFatData(const std::string& fatDataDirPath, const std::string& originalFatPath, uint32_t fatDataAddr, const std::string& savePath)
{
std::vector<char> fatDataBytes;
std::vector<FatRange> fat;
std::vector<char> fntBytes;
std::vector<FatFileID> fileIDs;
std::ifstream fileIDsFile(fatDataDirPath + "/_file_IDs.txt", std::ios::in);
if (!fileIDsFile.is_open()) return { false, "Error opening file: " + fatDataDirPath + "/_file_IDs.txt" };
std::string fileIDsLine;
while (std::getline(fileIDsFile, fileIDsLine))
{
FatFileID fatFileID;
fatFileID.id = static_cast<uint16_t>(std::stoi(fileIDsLine.substr(0, fileIDsLine.find(":::")), nullptr, 16));
fatFileID.path = fileIDsLine.substr(fileIDsLine.find(":::") + 3);
fileIDs.push_back(fatFileID);
}
fileIDsFile.close();
// This loop is needed to detect if roms has overlay files
// and if so, we need to extract their addresses from the original fat.bin
// it is a hacky but it works
for (FatFileID fatFileID : fileIDs)
{
std::string currentFile = fatDataDirPath + "/" + fatFileID.path;
if (std::filesystem::is_directory(std::filesystem::path(currentFile))) continue;
int firstFileId = fatFileID.id;
if (firstFileId > 0)
{
std::ifstream originalFatFile(originalFatPath, std::ios::in | std::ios::binary);
if (!originalFatFile.is_open()) return { false, "Error opening file: " + originalFatPath };
std::vector<char> ovrBytes;
uint32_t requiredBytes = firstFileId * sizeof(FatRange);
ovrBytes.resize(requiredBytes);
originalFatFile.read(ovrBytes.data(), requiredBytes);
originalFatFile.close();
FatRange* pfatrange = reinterpret_cast<FatRange*>(ovrBytes.data());
for (size_t i = 0; i < ovrBytes.size(); i += sizeof(FatRange), pfatrange++)
fat.push_back({ pfatrange->startAddr, pfatrange->endAddr });
}
break;
}
for (FatFileID fatFileID : fileIDs)
{
std::string currentFile = fatDataDirPath + "/" + fatFileID.path;
if (std::filesystem::is_directory(std::filesystem::path(currentFile))) continue;
FatRange fatRange;
fatRange.startAddr = fatDataAddr + static_cast<uint32_t>(fatDataBytes.size());
std::ifstream currentFatDataFile(currentFile, std::ios::in | std::ios::binary | std::ios::ate);
if (!currentFatDataFile.is_open()) return NFResult({ false, "Error opening file: " + currentFile });
std::streamsize size = currentFatDataFile.tellg();
currentFatDataFile.seekg(0, std::ios::beg);
std::vector<char> buffer(size);
if (currentFatDataFile.read(buffer.data(), size))
fatDataBytes.insert(fatDataBytes.end(), buffer.begin(), buffer.end());
else
{
currentFatDataFile.close();
return NFResult({ false, "Error reading file: " + currentFile });
}
currentFatDataFile.close();
fatRange.endAddr = fatDataAddr + static_cast<uint32_t>(fatDataBytes.size());
fat.push_back(fatRange);
}
const char* fat_ptr = reinterpret_cast<const char*>(fat.data());
std::vector<char> fatBytes(fat_ptr, fat_ptr + fat.size() * sizeof(FatRange));
std::remove((savePath + "/fat_data.bin").c_str());
std::remove((savePath + "/fat.bin").c_str());
if (!writeBytesToFile(fatDataBytes, savePath + "/fat_data.bin", 0, static_cast<uint32_t>(fatDataBytes.size())).result)
return NFResult({ false, "Error writing to file: " + savePath + "/fat_data.bin" });
if (!writeBytesToFile(fatBytes, savePath + "/fat.bin", 0, static_cast<uint32_t>(fatBytes.size())).result)
return NFResult({ false, "Error writing to file: " + savePath + "/fat.bin" });
return NFResult({ true, "" });
}
uint16_t NDSFactory::calcHeaderCrc16(const std::vector<char>& romHeader)
{
uint8_t loc;
uint16_t crc = 0xFFFF;
size_t size = 0x15E;
size_t index = 0;
while (size--)
{
loc = static_cast<unsigned char>(romHeader[index] ^ crc);
index++;
crc >>= 8;
crc ^= lCRCTable[loc];
}
return crc;
}

View File

@ -1,32 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <cstdint>
#include "ndsheader.h"
#include "fatstruct.h"
#include "nfresult.h"
class NDSFactory
{
public:
NFResult loadRomHeader(const std::string& romPath, std::vector<char>& header);
NFResult dumpDataFromFile(const std::string& romPath, const std::string& savePath, uint32_t startAddr, uint32_t size);
NFResult readBytesFromFile(std::vector<char>& byteBuffer, const std::string& romPath, uint32_t startAddr, uint32_t size);
NFResult writeSectionToFile(const std::string& sectionPath, const std::string& savePath, uint32_t startAddr, uint32_t size);
NFResult writeBytesToFile(std::vector<char>& byteBuffer, const std::string& savePath, uint32_t startAddr, uint32_t size);
NFResult 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);
NFResult extractFatData(const std::string& fatDataSectionPath, const std::string& fatSectionPath,
const std::string& fntSectionPath, uint32_t originalFatDataAddr, const std::string& savePath, bool logFileIDs);
NFResult patchFat(const std::string& sectionPath, uint32_t shiftSize, const std::string& savePath);
NFResult buildFatData(const std::string& fatDataDirPath, const std::string& originalFatPath, uint32_t fatDataAddr, const std::string& savePath);
uint16_t calcHeaderCrc16(const std::vector<char>& romHeader);
private:
bool logToFile(const std::string& logPath, const std::string& log);
};

View File

@ -1,9 +0,0 @@
#pragma once
#include <string>
struct NFResult
{
bool result;
std::string message;
};

View File

@ -1,4 +1,5 @@
#pragma once #ifndef NDSHEADER_H
#define NDSHEADER_H
#include <cstdint> #include <cstdint>
@ -68,3 +69,6 @@ struct NDSHeader
unsigned char Reserved4[0x90]; unsigned char Reserved4[0x90];
}; };
#pragma pack(pop) #pragma pack(pop)
#endif // NDSHEADER_H

353
packertabfunctions.cpp Normal file
View File

@ -0,0 +1,353 @@
#include <QDir>
#include <cstring>
#include <algorithm>
#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<char*>(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<char*>(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<char> romHeader(sizeof(NDSHeader));
NDSHeader* pRomHeader = reinterpret_cast<NDSHeader*>(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<unsigned char>(ui->packerUnitCodeEdt->text().toUInt(nullptr, 16));
pRomHeader->DeviceType = static_cast<unsigned char>(ui->packerDeviceCodeEdt->text().toUInt(nullptr, 16));
pRomHeader->DeviceSize = static_cast<unsigned char>(ui->packerCardSizeEdt->text().toUInt(nullptr, 16));
std::fill(std::begin(pRomHeader->Reserved1), std::end(pRomHeader->Reserved1), 0);
pRomHeader->RomVersion = static_cast<unsigned char>(ui->packerCardInfoEdt->text().toUInt(nullptr, 16));
pRomHeader->Flags = static_cast<unsigned char>(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<uint32_t>(ndsFactory.getCardSizeInBytes(ui->packerCardSizeEdt->text().toInt())) - startAddr;
return ndsFactory.writePaddingToFile(
static_cast<char>('\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<char>('\x00');
else
paddingType = static_cast<char>('\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;
}

View File

@ -1,13 +1,11 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include "./../../mainwindow.h" #include "mainwindow.h"
#include "./../../ui_mainwindow.h" #include "ui_mainwindow.h"
#include "./../../utils/filepicker.h"
#include "../commons/headernames.h"
void MainWindow::on_packerLoadHeaderBtn_clicked() void MainWindow::on_packerLoadHeaderBtn_clicked()
{ {
std::vector<char> romHeader;
NDSHeader *pNDSHeader; NDSHeader *pNDSHeader;
QString headerPath = QFileDialog::getOpenFileName( QString headerPath = QFileDialog::getOpenFileName(
@ -16,14 +14,16 @@ void MainWindow::on_packerLoadHeaderBtn_clicked()
QDir::currentPath(), QDir::currentPath(),
"NDS Header (*.bin)"); "NDS Header (*.bin)");
if (headerPath.isNull()) return; if(headerPath.isNull())
{
QMessageBox::critical(this, tr("NDS Factory"), tr("Unable to open file!"));
return;
}
if (ndsFactory.loadRomHeader(headerPath.toStdString(), romHeader).result) if (ndsFactory.loadRomHeader(headerPath.toStdString(), romHeader))
{ {
pNDSHeader = reinterpret_cast<NDSHeader*>(romHeader.data()); pNDSHeader = reinterpret_cast<NDSHeader*>(romHeader.data());
populatePackerSectionHeader(pNDSHeader); populatePackerSectionHeader(pNDSHeader);
enableCalcCrcButton();
enableBuildRomButton();
} }
} }
@ -32,7 +32,7 @@ void MainWindow::on_packerLoadArm9BinBtn_clicked()
QString arm9BinPath = QFileDialog::getOpenFileName( QString arm9BinPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Arm9Bin", "NDS Arm9Bin",
"", QDir::currentPath(),
"NDS Arm9Bin (*.bin)"); "NDS Arm9Bin (*.bin)");
if(!arm9BinPath.isNull()) if(!arm9BinPath.isNull())
@ -46,7 +46,7 @@ void MainWindow::on_packerLoadArm7BinBtn_clicked()
QString arm7BinPath = QFileDialog::getOpenFileName( QString arm7BinPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Arm7Bin", "NDS Arm7Bin",
"", QDir::currentPath(),
"NDS Arm7Bin (*.bin)"); "NDS Arm7Bin (*.bin)");
if(!arm7BinPath.isNull()) if(!arm7BinPath.isNull())
@ -60,7 +60,7 @@ void MainWindow::on_packerLoadFntBtn_clicked()
QString fntPath = QFileDialog::getOpenFileName( QString fntPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Fnt", "NDS Fnt",
"", QDir::currentPath(),
"NDS Fnt (*.bin)"); "NDS Fnt (*.bin)");
if(!fntPath.isNull()) if(!fntPath.isNull())
@ -74,7 +74,7 @@ void MainWindow::on_packerLoadFatBtn_clicked()
QString fatPath = QFileDialog::getOpenFileName( QString fatPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Fat", "NDS Fat",
"", QDir::currentPath(),
"NDS Fat (*.bin)"); "NDS Fat (*.bin)");
if(!fatPath.isNull()) if(!fatPath.isNull())
@ -88,7 +88,7 @@ void MainWindow::on_packerLoadArm9OverlayBtn_clicked()
QString arm9OverlayPath = QFileDialog::getOpenFileName( QString arm9OverlayPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Arm9Overlay", "NDS Arm9Overlay",
"", QDir::currentPath(),
"NDS A9OVR (*.bin)"); "NDS A9OVR (*.bin)");
if( !arm9OverlayPath.isNull() ) if( !arm9OverlayPath.isNull() )
@ -102,7 +102,7 @@ void MainWindow::on_packerLoadArm9OverlayFilesBtn_clicked()
QString arm9OverlayFilesPath = QFileDialog::getOpenFileName( QString arm9OverlayFilesPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Arm9Overlay Data", "NDS Arm9Overlay Data",
"", QDir::currentPath(),
"NDS A9OVR_DATA (*.bin)"); "NDS A9OVR_DATA (*.bin)");
if(!arm9OverlayFilesPath.isNull()) if(!arm9OverlayFilesPath.isNull())
@ -116,7 +116,7 @@ void MainWindow::on_packerLoadArm7OverlayBtn_clicked()
QString arm7OverlayPath = QFileDialog::getOpenFileName( QString arm7OverlayPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Arm7Overlay", "NDS Arm7Overlay",
"", QDir::currentPath(),
"NDS A7OVR (*.bin)"); "NDS A7OVR (*.bin)");
if(!arm7OverlayPath.isNull()) if(!arm7OverlayPath.isNull())
@ -130,7 +130,7 @@ void MainWindow::on_packerLoadArm7OverlayFilesBtn_clicked()
QString arm7OverlayFilesPath = QFileDialog::getOpenFileName( QString arm7OverlayFilesPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Arm7Overlay Data", "NDS Arm7Overlay Data",
"", QDir::currentPath(),
"NDS A7OVR_DATA (*.bin)"); "NDS A7OVR_DATA (*.bin)");
if(!arm7OverlayFilesPath.isNull()) if(!arm7OverlayFilesPath.isNull())
@ -144,7 +144,7 @@ void MainWindow::on_packerLoadIconTitleBtn_clicked()
QString iconTitlePath = QFileDialog::getOpenFileName( QString iconTitlePath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS IconTitleLogo", "NDS IconTitleLogo",
"", QDir::currentPath(),
"NDS ITL (*.bin)"); "NDS ITL (*.bin)");
if(!iconTitlePath.isNull()) if(!iconTitlePath.isNull())
@ -158,33 +158,28 @@ void MainWindow::on_packerLoadFatFilesBtn_clicked()
QString fatFilesPath = QFileDialog::getOpenFileName( QString fatFilesPath = QFileDialog::getOpenFileName(
Q_NULLPTR, Q_NULLPTR,
"NDS Fat Data", "NDS Fat Data",
"", QDir::currentPath(),
"NDS FAT_DATA (*.bin)"); "NDS FAT_DATA (*.bin)");
if(!fatFilesPath.isNull()) if(!fatFilesPath.isNull())
{ {
ui->loadedFatFilesPathEdt->setText(fatFilesPath.toUtf8()); ui->loadedFatFilesPathEdt->setText(fatFilesPath.toUtf8());
ui->packerFatFilesAddrEdt->setText(QString::number((ui->packerIconTitleEdt->text().toUInt(nullptr, 16) + IconTitleSize), 16));
} }
} }
void MainWindow::on_packerBuildNDSRomBtn_clicked() void MainWindow::on_packerBuildNDSRomBtn_clicked()
{ {
ui->packerBuildNDSRomBtn->setEnabled(false); QString dirPath = QFileDialog::getSaveFileName(
Q_NULLPTR,
QString dirPath = customSaveFileDialog("NDS Rom", "NDS Rom",
"rom.nds", "rom.nds",
"NDS ROM (*.nds)"); "NDS ROM (*.nds)");
if (!dirPath.isNull()) if (!dirPath.isNull())
{ {
NFResult nfResult = writeEverything(dirPath.toStdString()); writeEverything(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Creation completed!"))
nfResult.result? QMessageBox::information(this, tr("NDSFactory"), tr("Creation completed!")) : QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the creation!"));
: QMessageBox::critical(this, tr("NDSFactory"), nfResult.message.c_str());
} }
ui->packerBuildNDSRomBtn->setEnabled(true);
} }
void MainWindow::on_packerCalcHeaderCrcBtn_clicked()
{
calcHeaderCrc16();
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@ -1 +0,0 @@
IDI_ICON1 ICON "ndsfactory.ico"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -1,21 +0,0 @@
#include "aboutdialog.h"
#include "ui_aboutdialog.h"
#include "revision.h"
AboutDialog::AboutDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::AboutDialog)
{
ui->setupUi(this);
QString currentVersion = ui->aboutSoftwareNameLbl->text();
QString currentRevision = QString("Rev: %1").arg(GIT_COMMIT_HASH);
ui->aboutSoftwareNameLbl->setText(currentVersion + " " + currentRevision);
QString buildInfo = QString("Build Date: %1 Time: %2").arg(__DATE__, __TIME__);
ui->aboutSoftwareBuildLbl->setText(buildInfo);
}
AboutDialog::~AboutDialog()
{
delete ui;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include <QDialog>
namespace Ui {
class AboutDialog;
}
class AboutDialog : public QDialog
{
Q_OBJECT
public:
AboutDialog(QWidget *parent = nullptr);
~AboutDialog();
private:
Ui::AboutDialog *ui;
};

View File

@ -1,6 +0,0 @@
#ifndef REVISION_H
#define REVISION_H
#define GIT_COMMIT_HASH "c916f47"
#endif

View File

@ -1,6 +0,0 @@
#ifndef REVISION_H
#define REVISION_H
#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@"
#endif

View File

@ -1,116 +0,0 @@
#pragma once
#include <QMainWindow>
#include <cstdint>
#include "../ndsfactory/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_actionDark_triggered();
void on_actionLight_triggered();
void on_actionDefault_triggered();
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_packerCalcHeaderCrcBtn_clicked();
void on_packerBuildNDSRomBtn_clicked();
void on_fatPatcherLoadFatBtn_clicked();
void on_fatPatcherPatchFatBtn_clicked();
void on_fatExtractorLoadFatDataBtn_clicked();
void on_fatExtractorLoadFatBtn_clicked();
void on_fatExtractorLoadFntBtn_clicked();
void on_fatExtractorExtractBtn_clicked();
void on_fatBuilderOpenFatDataDirBtn_clicked();
void on_fatBuilderLoadOriginalFatBtn_clicked();
void on_fatBuilderBuildBtn_clicked();
private:
Ui::MainWindow *ui;
NDSFactory ndsFactory;
std::vector<char> romHeader;
void populateHeader(NDSHeader* ndsHeader);
void enableExtractionButtons();
void disableExtractionButtons();
NFResult dumpHeader(const std::string& dirPath);
NFResult dumpArm9Bin(const std::string& dirPath, bool dumpExtraBytes);
NFResult dumpArm7Bin(const std::string& dirPath);
NFResult dumpFnt(const std::string& dirPath);
NFResult dumpFat(const std::string& dirPath);
NFResult dumpArm9Overlay(const std::string& dirPath);
NFResult dumpArm9OverlayFiles(const std::string& dirPath);
NFResult dumpArm7Overlay(const std::string& dirPath);
NFResult dumpArm7OverlayFiles(const std::string& dirPath);
NFResult dumpIconTitle(const std::string& dirPath);
NFResult dumpFatFiles(const std::string& dirPath);
NFResult dumpEverything(QString dirPath);
void populatePackerSectionHeader(NDSHeader *ndsHeader);
void enableCalcCrcButton();
void enableBuildRomButton();
void generateHeader(NDSHeader* pRomHeader);
NFResult writeHeader(const std::string& savePath);
void calcHeaderCrc16();
NFResult writeArm9Bin(const std::string& savePath, bool isArm9FooterPresent);
NFResult writeArm7Bin(const std::string& savePath);
NFResult writeFnt(const std::string& savePath);
NFResult writeFat(const std::string& savePath);
NFResult writeArm9Overlay(const std::string& savePath);
NFResult writeArm9OverlayFiles(const std::string& savePath);
NFResult writeArm7Overlay(const std::string& savePath);
NFResult writeArm7OverlayFiles(const std::string& savePath);
NFResult writeIconTitle(const std::string& savePath);
NFResult writeFatFiles(const std::string& savePath);
NFResult writeEverything(const std::string& savePath);
NFResult writeHeaderPadding(char paddingByte, const std::string& savePath);
NFResult writeArm9BinPadding(char paddingByte, const std::string& savePath, bool isArm9FooterPresent);
NFResult writeArm7BinPadding(char paddingByte, const std::string& savePath);
NFResult writeFntPadding(char paddingByte, const std::string& savePath);
NFResult writeFatPadding(char paddingByte, const std::string& savePath);
NFResult writeRomPadding(const std::string& savePath);
QString extractPackerHeaderTableData(int index);
NFResult extractFatData(const std::string& fatDataSectionPath, const std::string& fatSectionPath,
const std::string& fntSectionPath, uint32_t originalFatDataAddr, const std::string& savePath, bool logFileIDs);
NFResult patchFat(const std::string& loadPath, uint32_t shiftSize, const std::string& savePath);
NFResult buildFatData(const std::string& fatDataDirPath, const std::string& originalFatPath, uint32_t fatDataAddr, const std::string& savePath);
};

File diff suppressed because it is too large Load Diff

View File

@ -1,190 +0,0 @@
#include <QMessageBox>
#include "ndsheadermodel.h"
#include "../../ndsfactory/ndsheader.h"
#include "../tabs/commons/headernames.h"
NDSHeaderModel::NDSHeaderModel(NDSHeader *ndsHeader, QObject *parent) : QAbstractTableModel(parent)
{
this->ndsHeader = ndsHeader;
}
int NDSHeaderModel::rowCount([[maybe_unused]] const QModelIndex &parent) const
{
return static_cast<int>(ndsHeaderNamesArr.size());
}
int NDSHeaderModel::columnCount([[maybe_unused]] const QModelIndex &parent) const
{
return 2;
}
QVariant NDSHeaderModel::data(const QModelIndex &index, int role) const
{
if(role == Qt::DisplayRole || role == Qt::EditRole)
{
if(index.column() == 0)
return QString::fromStdString(ndsHeaderNamesArr.at(static_cast<size_t>(index.row())));
else if(index.column() == 1) {
switch (index.row())
{
case 0: return QString::fromUtf8(ndsHeader->GameTitle, 0xC);
case 1: return QString::fromUtf8(ndsHeader->GameCode, 0x4);
case 2: return QString::fromUtf8(reinterpret_cast<char*>(ndsHeader->MakerCode), 0x2);
case 3: return QString::number(ndsHeader->UnitCode, 16);
case 4: return QString::number(ndsHeader->DeviceType, 16);
case 5: return QString::number(ndsHeader->DeviceSize, 16);
case 6: return QString::number(ndsHeader->RomVersion, 16);
case 7: return QString::number(ndsHeader->Flags, 16);
case 8: return QString::number(ndsHeader->Arm9RomAddr,16);
case 9: return QString::number(ndsHeader->Arm9EntryAddr,16);
case 10: return QString::number(ndsHeader->Arm9RamAddr,16);
case 11: return QString::number(ndsHeader->Arm9Size,16);
case 12: return QString::number(ndsHeader->Arm7RomAddr,16);
case 13: return QString::number(ndsHeader->Arm7EntryAddr,16);
case 14: return QString::number(ndsHeader->Arm7RamAddr,16);
case 15: return QString::number(ndsHeader->Arm7Size,16);
case 16: return QString::number(ndsHeader->FilenameTableAddr,16);
case 17: return QString::number(ndsHeader->FilenameSize,16);
case 18: return QString::number(ndsHeader->FATAddr,16);
case 19: return QString::number(ndsHeader->FATSize,16);
case 20: return QString::number(ndsHeader->Arm9OverlayAddr,16);
case 21: return QString::number(ndsHeader->Arm9OverlaySize,16);
case 22: return QString::number(ndsHeader->Arm7OverlayAddr,16);
case 23: return QString::number(ndsHeader->Arm7OverlaySize,16);
case 24: return QString::number(ndsHeader->NormalCommandsSettings,16);
case 25: return QString::number(ndsHeader->Key1CommandsSettings,16);
case 26: return QString::number(ndsHeader->IconTitleAddr,16);
case 27: return QString::number(ndsHeader->SecureAreaCRC16,16);
case 28: return QString::number(ndsHeader->SecureAreaLoadingTimeout,16);
case 29: return QString::number(ndsHeader->ARM9AutoLoadListRamAddr,16);
case 30: return QString::number(ndsHeader->ARM7AutoLoadListRamAddr,16);
case 31: return QString::number(ndsHeader->SecureAreaDisable,16);
case 32: return QString::number(ndsHeader->RomSize,16);
case 33: return QString::number(ndsHeader->HeaderSize,16);
case 34: return QByteArray::fromRawData(reinterpret_cast<char*>(ndsHeader->NintendoLogo), 0x9C).toHex();
case 35: return QString::number(ndsHeader->NintendoLogoCRC,16);
case 36: return QString::number(ndsHeader->HeaderCRC16,16);
case 37: return QString::number(ndsHeader->DebugRomAddr,16);
case 38: return QString::number(ndsHeader->DebugSize,16);
case 39: return QString::number(ndsHeader->DebugRamAddr,16);
case 40: return QString::number((ndsHeader->IconTitleAddr+IconTitleSize),16);
default: return QString("");
}
}
}
return QVariant();
}
bool NDSHeaderModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(role != Qt::EditRole)
return QAbstractTableModel::setData(index, value, role);
switch (index.row())
{
case 0:
{
std::fill_n(ndsHeader->GameTitle, 0xC, 0x0);
QString gameTitleStr = value.toString().toUpper();
size_t size = std::min<size_t>(gameTitleStr.size(), 0xC);
std::copy_n(qUtf8Printable(gameTitleStr), size, ndsHeader->GameTitle);
break;
}
case 1:
{
std::fill_n(ndsHeader->GameCode, 0x4, 0x0);
QString gameCodeStr = value.toString().toUpper();
size_t size = std::min<size_t>(gameCodeStr.size(), 0x4);
std::copy_n(qUtf8Printable(gameCodeStr), size, ndsHeader->GameCode);
break;
}
case 2:
{
std::fill_n(ndsHeader->MakerCode, 0x2, 0x0);
QString makerCodeStr = value.toString().toUpper();
size_t size = std::min<size_t>(makerCodeStr.size(), 0x2);
std::copy_n(qUtf8Printable(makerCodeStr), size, ndsHeader->MakerCode);
break;
}
case 3: ndsHeader->UnitCode = static_cast<unsigned char>(value.toString().toUInt(nullptr, 16)); break;
case 4: ndsHeader->DeviceType = static_cast<unsigned char>(value.toString().toUInt(nullptr, 16)); break;
case 5: ndsHeader->DeviceSize = static_cast<unsigned char>(value.toString().toUInt(nullptr, 16)); break;
case 6: ndsHeader->RomVersion = static_cast<unsigned char>(value.toString().toUInt(nullptr, 16)); break;
case 7: ndsHeader->Flags = static_cast<unsigned char>(value.toString().toUInt(nullptr, 16)); break;
case 8: ndsHeader->Arm9RomAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 9: ndsHeader->Arm9EntryAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 10: ndsHeader->Arm9RamAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 11: ndsHeader->Arm9Size = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 12: ndsHeader->Arm7RomAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 13: ndsHeader->Arm7EntryAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 14: ndsHeader->Arm7RamAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 15: ndsHeader->Arm7Size = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 16: ndsHeader->FilenameTableAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 17: ndsHeader->FilenameSize = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 18: ndsHeader->FATAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 19: ndsHeader->FATSize = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 20: ndsHeader->Arm9OverlayAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 21: ndsHeader->Arm9OverlaySize = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 22: ndsHeader->Arm7OverlayAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 23: ndsHeader->Arm7OverlaySize = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 24: ndsHeader->NormalCommandsSettings = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 25: ndsHeader->Key1CommandsSettings = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 26: ndsHeader->IconTitleAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 27: ndsHeader->SecureAreaCRC16 = static_cast<uint16_t>(value.toString().toUInt(nullptr, 16)); break;
case 28: ndsHeader->SecureAreaLoadingTimeout = static_cast<uint16_t>(value.toString().toUInt(nullptr, 16)); break;
case 29: ndsHeader->ARM9AutoLoadListRamAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 30: ndsHeader->ARM7AutoLoadListRamAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 31: ndsHeader->SecureAreaDisable = static_cast<uint64_t>(value.toString().toUInt(nullptr, 16)); break;
case 32: ndsHeader->RomSize = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 33: ndsHeader->HeaderSize = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 34:
{
std::fill_n(ndsHeader->NintendoLogo, 0x9C, 0x0);
QByteArray nintendoLogoBytes = QByteArray::fromHex(qUtf8Printable(value.toString()));
size_t size = std::min<size_t>(nintendoLogoBytes.size(), 0x9C);
std::copy_n(std::begin(nintendoLogoBytes), size, ndsHeader->NintendoLogo);
break;
}
case 35: ndsHeader->NintendoLogoCRC = static_cast<uint16_t>(value.toString().toUInt(nullptr, 16)); break;
case 36: ndsHeader->HeaderCRC16 = static_cast<uint16_t>(value.toString().toUInt(nullptr, 16)); break;
case 37: ndsHeader->DebugRomAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 38: ndsHeader->DebugSize = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 39: ndsHeader->DebugRamAddr = static_cast<uint32_t>(value.toString().toUInt(nullptr, 16)); break;
case 40: QMessageBox::information(nullptr, tr("NDSFactory"), tr("FAT files address is automatically calculated based on Icon/Title address!")); break;
default: return false;
}
Q_EMIT this->dataChanged(index, index);
return true;
}
QVariant NDSHeaderModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal)
{
if(role == Qt::DisplayRole)
{
switch(section)
{
case 0:
return "Name";
case 1:
return "Value";
}
}
}
return QVariant();
}
Qt::ItemFlags NDSHeaderModel::flags(const QModelIndex &index) const
{
if (index.isValid() && index.column() == 1 && isValueRowEditable)
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
return QAbstractItemModel::flags(index);
}
void NDSHeaderModel::setValueRowEditable(bool isEditable)
{
isValueRowEditable = isEditable;
}

View File

@ -1,22 +0,0 @@
#pragma once
#include <QAbstractTableModel>
struct NDSHeader;
class NDSHeaderModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit NDSHeaderModel(NDSHeader *ndsHeader, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
void setValueRowEditable(bool isEditable);
private:
NDSHeader *ndsHeader;
bool isValueRowEditable = false;
};

View File

@ -1,45 +0,0 @@
#include "headernames.h"
std::vector<std::string> ndsHeaderNamesArr = {
"Game Title",
"Game Code",
"Maker Code",
"Unit Code",
"Device Code",
"Card Size",
"Card Info",
"Flags",
"ARM9 Rom Address",
"ARM9 Entry Address",
"ARM9 Ram Address",
"ARM9 Size",
"ARM7 Rom Address",
"ARM7 Entry Address",
"ARM7 Ram Address",
"ARM7 Size",
"Filename Table Address",
"Filename Table Size",
"FAT Address",
"FAT Size",
"ARM9 Overlay Address",
"ARM9 Overlay Size",
"ARM7 Overlay Address",
"ARM7 Overlay Size",
"Port 40001A4h NC",
"Port 40001a4h KC",
"Icon/Title Address",
"Secure Area CRC16",
"Secure Area Timeout",
"ARM9 AL Ram Address",
"ARM7 AL Ram Address",
"Secure Area Disable",
"Used Rom Size",
"Header Size",
"Nintendo Logo",
"Nintendo Logo CRC",
"Header CRC",
"Debug Rom Address",
"Debug Size",
"Debug Ram Address",
"FAT Files Address"
};

View File

@ -1,53 +0,0 @@
#pragma once
#include <array>
#include <string>
#include <vector>
extern std::vector<std::string> ndsHeaderNamesArr;
namespace NDSHeaderNames {
enum {
GameTitle,
GameCode,
MakerCode,
UnitCode,
DeviceCode,
CardSize,
CardInfo,
Flags,
ARM9RomAddress,
ARM9EntryAddress,
ARM9RamAddress,
ARM9Size,
ARM7RomAddress,
ARM7EntryAddress,
ARM7RamAddress,
ARM7Size,
FilenameTableAddress,
FilenameTableSize,
FATAddress,
FATSize,
ARM9OverlayAddress,
ARM9OverlaySize,
ARM7OverlayAddress,
ARM7OverlaySize,
Port40001A4hNC,
Port40001a4hKC,
IconTitleAddress,
SecureAreaCRC16,
SecureAreaTimeout,
ARM9ALRamAddress,
ARM7ALRamAddress,
SecureAreaDisable,
UsedRomSize,
HeaderSize,
NintendoLogo,
NintendoLogoCRC,
HeaderCRC,
DebugRomAddress,
DebugSize,
DebugRamAddress,
FATFilesAddress
};
}

View File

@ -1,19 +0,0 @@
#include <filesystem>
#include "./../../mainwindow.h"
NFResult MainWindow::extractFatData(const std::string& fatDataSectionPath, const std::string& fatSectionPath,
const std::string& fntSectionPath, uint32_t originalFatDataAddr, const std::string& savePath, bool logFileIDs)
{
return ndsFactory.extractFatData(fatDataSectionPath, fatSectionPath, fntSectionPath, originalFatDataAddr, savePath, logFileIDs);
}
NFResult MainWindow::patchFat(const std::string& loadPath, uint32_t shiftSize, const std::string& savePath)
{
return ndsFactory.patchFat(loadPath, shiftSize, savePath);
}
NFResult MainWindow::buildFatData(const std::string& fatDataDirPath, const std::string& originalFatPath, uint32_t fatDataAddr, const std::string& savePath)
{
return ndsFactory.buildFatData(fatDataDirPath, originalFatPath, fatDataAddr, savePath);
}

View File

@ -1,155 +0,0 @@
#include <QFileDialog>
#include <QMessageBox>
#include "./../../mainwindow.h"
#include "./../../ui_mainwindow.h"
#include "./../../utils/filepicker.h"
void MainWindow::on_fatExtractorLoadFatDataBtn_clicked()
{
QString FatDataPath = QFileDialog::getOpenFileName(
Q_NULLPTR,
"NDS Fat Data",
"",
"NDS FAT_DATA (*.bin)");
if (!FatDataPath.isNull())
{
ui->fatExtractorFatDataPathEdt->setText(FatDataPath.toUtf8());
}
}
void MainWindow::on_fatExtractorLoadFatBtn_clicked()
{
QString FatPath = QFileDialog::getOpenFileName(
Q_NULLPTR,
"NDS Fat",
"",
"NDS FAT (*.bin)");
if (!FatPath.isNull())
{
ui->fatExtractorFatPathEdt->setText(FatPath.toUtf8());
}
}
void MainWindow::on_fatExtractorLoadFntBtn_clicked()
{
QString FntPath = QFileDialog::getOpenFileName(
Q_NULLPTR,
"NDS Fnt",
"",
"NDS FNT (*.bin)");
if (!FntPath.isNull())
{
ui->fatExtractorFntPathEdt->setText(FntPath.toUtf8());
}
}
void MainWindow::on_fatExtractorExtractBtn_clicked()
{
ui->fatExtractorExtractBtn->setEnabled(false);
QString dirPath = QFileDialog::getExistingDirectory(
this, tr("Select Directory"),
"",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dirPath.isNull()) {
NFResult nfResult = extractFatData(ui->fatExtractorFatDataPathEdt->text().toStdString(),
ui->fatExtractorFatPathEdt->text().toStdString(),
ui->fatExtractorFntPathEdt->text().toStdString(),
ui->fatExtractorOriginalFatFilesAddrEdt->text().toUInt(nullptr, 16),
dirPath.toStdString(),
ui->fatExtractorSaveFileIDsCbx->isChecked());
nfResult.result? QMessageBox::information(this, tr("NDSFactory"), tr("FAT files extraction completed!"))
: QMessageBox::critical(this, tr("NDSFactory"), nfResult.message.c_str());
}
ui->fatExtractorExtractBtn->setEnabled(true);
}
void MainWindow::on_fatPatcherLoadFatBtn_clicked()
{
QString fatPath = QFileDialog::getOpenFileName(
Q_NULLPTR,
"NDS Fat",
"",
"NDS Fat (*.bin)");
if(!fatPath.isNull())
ui->fatPatcherFatPathEdt->setText(fatPath.toUtf8());
}
void MainWindow::on_fatPatcherPatchFatBtn_clicked()
{
ui->fatPatcherPatchFatBtn->setEnabled(false);
uint32_t positionDiff = 0;
uint32_t originalPos = ui->fatPatcherOriginalFatFilesAddrEdt->text().toUInt(nullptr, 16);
uint32_t newPos = ui->fatPatcherNewFatFilesAddrEdt->text().toUInt(nullptr, 16);
QString dirPath = customSaveFileDialog("NDS FAT",
"fat.bin",
"Binary (*.bin)");
if (!dirPath.isNull())
{
if(originalPos < newPos)
positionDiff = newPos - originalPos;
else
positionDiff = originalPos - newPos;
NFResult nfResult = patchFat(ui->fatPatcherFatPathEdt->text().toStdString(), positionDiff, dirPath.toStdString());
nfResult.result ? QMessageBox::information(this, tr("NDSFactory"), tr("FAT patching completed!"))
: QMessageBox::critical(this, tr("NDSFactory"), nfResult.message.c_str());
}
ui->fatPatcherPatchFatBtn->setEnabled(true);
}
void MainWindow::on_fatBuilderOpenFatDataDirBtn_clicked()
{
QString fatDirPat = QFileDialog::getExistingDirectory(
this, tr("Select Directory"),
"",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!fatDirPat.isNull())
ui->fatBuilderFatDirPathEdt->setText(fatDirPat.toUtf8());
}
void MainWindow::on_fatBuilderLoadOriginalFatBtn_clicked()
{
QString fatPath = QFileDialog::getOpenFileName(
Q_NULLPTR,
"NDS Fat",
"",
"NDS Fat (*.bin)");
if (!fatPath.isNull())
ui->fatBuilderOriginalFatPathEdt->setText(fatPath.toUtf8());
}
void MainWindow::on_fatBuilderBuildBtn_clicked()
{
ui->fatBuilderOpenFatDataDirBtn->setEnabled(false);
QString dirPath = QFileDialog::getExistingDirectory(
this, tr("Select Directory"),
"",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dirPath.isNull())
{
NFResult nfResult = buildFatData(ui->fatBuilderFatDirPathEdt->text().toStdString(),
ui->fatBuilderOriginalFatPathEdt->text().toStdString(),
ui->fatBuilderFatAddrEdt->text().toUInt(nullptr, 16),
dirPath.toStdString());
nfResult.result? QMessageBox::information(this, tr("NDSFactory"), tr("fat_data.bin and fat.bin correctly built!"))
: QMessageBox::critical(this, tr("NDSFactory"), nfResult.message.c_str());
}
ui->fatBuilderOpenFatDataDirBtn->setEnabled(true);
}

View File

@ -1,369 +0,0 @@
#include <QDir>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include "./../../mainwindow.h"
#include "./../../ui_mainwindow.h"
#include "../commons/headernames.h"
#include "../../models/ndsheadermodel.h"
void MainWindow::populatePackerSectionHeader(NDSHeader *ndsHeader)
{
auto* headerDataModel = new NDSHeaderModel(ndsHeader);
headerDataModel->setValueRowEditable(true);
ui->packerHeaderDataTable->setModel(headerDataModel);
ui->packerHeaderDataTable->setEditTriggers(QAbstractItemView::AllEditTriggers);
ui->packerHeaderDataTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
ui->packerHeaderDataTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch);
}
void MainWindow::enableCalcCrcButton()
{
ui->packerCalcHeaderCrcBtn->setEnabled(true);
}
void MainWindow::enableBuildRomButton()
{
ui->packerBuildNDSRomBtn->setEnabled(true);
}
void MainWindow::generateHeader(NDSHeader* pRomHeader)
{
std::copy_n(extractPackerHeaderTableData(NDSHeaderNames::GameTitle).toLatin1().data(), 0xc, std::begin(pRomHeader->GameTitle));
std::copy_n(extractPackerHeaderTableData(NDSHeaderNames::GameCode).toLatin1().data(), 0x4, std::begin(pRomHeader->GameCode));
std::copy_n(extractPackerHeaderTableData(NDSHeaderNames::MakerCode).toLatin1().data(), 0x2, std::begin(pRomHeader->MakerCode));
pRomHeader->UnitCode = static_cast<unsigned char>(extractPackerHeaderTableData(NDSHeaderNames::UnitCode).toUInt(nullptr, 16));
pRomHeader->DeviceType = static_cast<unsigned char>(extractPackerHeaderTableData(NDSHeaderNames::DeviceCode).toUInt(nullptr, 16));
pRomHeader->DeviceSize = static_cast<unsigned char>(extractPackerHeaderTableData(NDSHeaderNames::CardSize).toUInt(nullptr, 16));
std::fill(std::begin(pRomHeader->Reserved1), std::end(pRomHeader->Reserved1), 0);
pRomHeader->RomVersion = static_cast<unsigned char>(extractPackerHeaderTableData(NDSHeaderNames::CardInfo).toUInt(nullptr, 16));
pRomHeader->Flags = static_cast<unsigned char>(extractPackerHeaderTableData(NDSHeaderNames::Flags).toUInt(nullptr, 16));
pRomHeader->Arm9RomAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9RomAddress).toUInt(nullptr, 16);
pRomHeader->Arm9EntryAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9EntryAddress).toUInt(nullptr, 16);
pRomHeader->Arm9RamAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9RamAddress).toUInt(nullptr, 16);
pRomHeader->Arm9Size = extractPackerHeaderTableData(NDSHeaderNames::ARM9Size).toUInt(nullptr, 16);
pRomHeader->Arm7RomAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7RomAddress).toUInt(nullptr, 16);
pRomHeader->Arm7EntryAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7EntryAddress).toUInt(nullptr, 16);
pRomHeader->Arm7RamAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7RamAddress).toUInt(nullptr, 16);
pRomHeader->Arm7Size = extractPackerHeaderTableData(NDSHeaderNames::ARM7Size).toUInt(nullptr, 16);
pRomHeader->FilenameTableAddr = extractPackerHeaderTableData(NDSHeaderNames::FilenameTableAddress).toUInt(nullptr, 16);
pRomHeader->FilenameSize = extractPackerHeaderTableData(NDSHeaderNames::FilenameTableSize).toUInt(nullptr, 16);
pRomHeader->FATAddr = extractPackerHeaderTableData(NDSHeaderNames::FATAddress).toUInt(nullptr, 16);
pRomHeader->FATSize = extractPackerHeaderTableData(NDSHeaderNames::FATSize).toUInt(nullptr, 16);
pRomHeader->Arm9OverlayAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16);
pRomHeader->Arm9OverlaySize = extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlaySize).toUInt(nullptr, 16);
pRomHeader->Arm7OverlayAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlayAddress).toUInt(nullptr, 16);
pRomHeader->Arm7OverlaySize = extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlaySize).toUInt(nullptr, 16);
pRomHeader->NormalCommandsSettings = extractPackerHeaderTableData(NDSHeaderNames::Port40001A4hNC).toUInt(nullptr, 16);
pRomHeader->Key1CommandsSettings = extractPackerHeaderTableData(NDSHeaderNames::Port40001a4hKC).toUInt(nullptr, 16);
pRomHeader->IconTitleAddr = extractPackerHeaderTableData(NDSHeaderNames::IconTitleAddress).toUInt(nullptr, 16);
pRomHeader->SecureAreaCRC16 = extractPackerHeaderTableData(NDSHeaderNames::SecureAreaCRC16).toUShort(nullptr, 16);
pRomHeader->SecureAreaLoadingTimeout = extractPackerHeaderTableData(NDSHeaderNames::SecureAreaTimeout).toUShort(nullptr, 16);
pRomHeader->ARM9AutoLoadListRamAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM9ALRamAddress).toUInt(nullptr, 16);
pRomHeader->ARM7AutoLoadListRamAddr = extractPackerHeaderTableData(NDSHeaderNames::ARM7ALRamAddress).toUInt(nullptr, 16);
pRomHeader->SecureAreaDisable = extractPackerHeaderTableData(NDSHeaderNames::SecureAreaDisable).toULong(nullptr, 16);
pRomHeader->RomSize = extractPackerHeaderTableData(NDSHeaderNames::UsedRomSize).toUInt(nullptr, 16);
pRomHeader->HeaderSize = extractPackerHeaderTableData(NDSHeaderNames::HeaderSize).toUInt(nullptr, 16);
std::fill(std::begin(pRomHeader->Reserved2), std::end(pRomHeader->Reserved2), 0);
std::copy_n(std::begin(QByteArray::fromHex(extractPackerHeaderTableData(NDSHeaderNames::NintendoLogo).toUtf8())), 0x9C, std::begin(pRomHeader->NintendoLogo));
pRomHeader->NintendoLogoCRC = extractPackerHeaderTableData(NDSHeaderNames::NintendoLogoCRC).toUShort(nullptr, 16);
pRomHeader->HeaderCRC16 = extractPackerHeaderTableData(NDSHeaderNames::HeaderCRC).toUShort(nullptr, 16);
pRomHeader->DebugRomAddr = extractPackerHeaderTableData(NDSHeaderNames::DebugRomAddress).toUInt(nullptr, 16);
pRomHeader->DebugSize = extractPackerHeaderTableData(NDSHeaderNames::DebugSize).toUInt(nullptr, 16);
pRomHeader->DebugRamAddr = extractPackerHeaderTableData(NDSHeaderNames::DebugRamAddress).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);
}
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);
}
NFResult MainWindow::writeHeader(const std::string& savePath)
{
std::vector<char> romHeaderBuffer(sizeof(NDSHeader));
NDSHeader* pRomHeader = reinterpret_cast<NDSHeader*>(romHeaderBuffer.data());
generateHeader(pRomHeader);
return ndsFactory.writeBytesToFile(romHeaderBuffer, savePath, 0, sizeof(NDSHeader));
}
NFResult 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);
}
NFResult MainWindow::writeArm9Bin(const std::string& savePath, bool isArm9FooterPresent)
{
uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::ARM9Size).toUInt(nullptr, 16);
if (isArm9FooterPresent)
size += Arm9FooterSize;
return ndsFactory.writeSectionToFile(
ui->loadedArm9BinPathEdt->text().toStdString(),
savePath,
extractPackerHeaderTableData(NDSHeaderNames::ARM9RomAddress).toUInt(nullptr, 16),
size);
}
NFResult 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)
{
startAddr += Arm9FooterSize;
size -= Arm9FooterSize;
}
return ndsFactory.writePaddingToFile(
paddingType,
savePath,
startAddr,
size);
}
NFResult 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));
}
NFResult 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);
}
NFResult MainWindow::writeArm7Bin(const std::string& savePath)
{
return ndsFactory.writeSectionToFile(
ui->loadedArm7BinPathEdt->text().toStdString(),
savePath,
extractPackerHeaderTableData(NDSHeaderNames::ARM7RomAddress).toUInt(nullptr, 16),
extractPackerHeaderTableData(NDSHeaderNames::ARM7Size).toUInt(nullptr, 16));
}
NFResult 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);
}
NFResult 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));
}
NFResult 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);
}
NFResult MainWindow::writeFnt(const std::string& savePath)
{
return ndsFactory.writeSectionToFile(
ui->loadedFntPathEdt->text().toStdString(),
savePath,
extractPackerHeaderTableData(NDSHeaderNames::FilenameTableAddress).toUInt(nullptr, 16),
extractPackerHeaderTableData(NDSHeaderNames::FilenameTableSize).toUInt(nullptr, 16));
}
NFResult 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);
}
NFResult MainWindow::writeFat(const std::string& savePath)
{
return ndsFactory.writeSectionToFile(
ui->loadedFatPathEdt->text().toStdString(),
savePath,
extractPackerHeaderTableData(NDSHeaderNames::FATAddress).toUInt(nullptr, 16),
extractPackerHeaderTableData(NDSHeaderNames::FATSize).toUInt(nullptr, 16));
}
NFResult 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);
}
NFResult MainWindow::writeIconTitle(const std::string& savePath)
{
return ndsFactory.writeSectionToFile(
ui->loadedIconTitlePathEdt->text().toStdString(),
savePath,
extractPackerHeaderTableData(NDSHeaderNames::IconTitleAddress).toUInt(nullptr, 16),
IconTitleSize);
}
NFResult MainWindow::writeFatFiles(const std::string& savePath)
{
uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::IconTitleAddress).toUInt(nullptr, 16) + IconTitleSize;
uint32_t size = extractPackerHeaderTableData(NDSHeaderNames::UsedRomSize).toUInt(nullptr, 16) - startAddr;
return ndsFactory.writeSectionToFile(
ui->loadedFatFilesPathEdt->text().toStdString(),
savePath,
startAddr,
size);
}
NFResult MainWindow::writeRomPadding(const std::string& savePath)
{
uint32_t startAddr = extractPackerHeaderTableData(NDSHeaderNames::UsedRomSize).toUInt(nullptr, 16);
uint32_t size = static_cast<uint32_t>(ndsFactory.getCardSizeInBytes(extractPackerHeaderTableData(NDSHeaderNames::CardSize).toInt())) - startAddr;
return ndsFactory.writePaddingToFile(
static_cast<char>('\xff'),
savePath,
startAddr,
size);
}
NFResult MainWindow::writeEverything(const std::string& savePath)
{
NFResult nfResult;
char paddingType;
bool isArm9FooterPresent = ndsFactory.checkArm9FooterPresence(ui->loadedArm9BinPathEdt->text().toStdString(),
extractPackerHeaderTableData(NDSHeaderNames::ARM9Size).toUInt(nullptr, 16));
if (ui->packerPadType00RdBtn->isChecked())
paddingType = static_cast<char>('\x00');
else
paddingType = static_cast<char>('\xff');
std::remove(savePath.c_str());
nfResult = writeHeader(savePath);
if (!nfResult.result) return nfResult;
nfResult = writeHeaderPadding(paddingType, savePath);
if (!nfResult.result) return nfResult;
nfResult = writeArm9Bin(savePath, isArm9FooterPresent);
if (!nfResult.result) return nfResult;
nfResult = writeArm9BinPadding(paddingType, savePath, isArm9FooterPresent);
if (!nfResult.result) return nfResult;
if (extractPackerHeaderTableData(NDSHeaderNames::ARM9OverlayAddress).toUInt(nullptr, 16) != 0)
{
nfResult = writeArm9Overlay(savePath);
if (!nfResult.result) return nfResult;
nfResult = writeArm9OverlayFiles(savePath);
if (!nfResult.result) return nfResult;
}
nfResult = writeArm7Bin(savePath);
if (!nfResult.result) return nfResult;
nfResult = writeArm7BinPadding(paddingType, savePath);
if (!nfResult.result) return nfResult;
if (extractPackerHeaderTableData(NDSHeaderNames::ARM7OverlayAddress).toUInt(nullptr, 16) != 0) {
nfResult = writeArm7Overlay(savePath);
if (!nfResult.result) return nfResult;
nfResult = writeArm7OverlayFiles(savePath);
if (!nfResult.result) return nfResult;
}
nfResult = writeFnt(savePath);
if (!nfResult.result) return nfResult;
nfResult = writeFntPadding(paddingType, savePath);
if (!nfResult.result) return nfResult;
nfResult = writeFat(savePath);
if (!nfResult.result) return nfResult;
nfResult = writeFatPadding(paddingType, savePath);
if (!nfResult.result) return nfResult;
nfResult = writeIconTitle(savePath);
if (!nfResult.result) return nfResult;
nfResult = writeFatFiles(savePath);
if (!nfResult.result) return nfResult;
if(!ui->packerTrimRomsCbx->isChecked())
{
nfResult = writeRomPadding(savePath);
if (!nfResult.result) return nfResult;
}
return { true, "" };
}
QString MainWindow::extractPackerHeaderTableData(int index)
{
return ui->packerHeaderDataTable->model()->index(index, 1).data().toString();
}

View File

@ -1,198 +0,0 @@
#include <QDir>
#include <stdlib.h>
#include <sstream>
#include <iomanip>
#include "../../mainwindow.h"
#include "../../ui_mainwindow.h"
#include "../commons/headernames.h"
#include "../../models/ndsheadermodel.h"
#include "../../../ndsfactory/fatstruct.h"
// Size constants
#define ICON_TITLE_SIZE 0xA00
void MainWindow::populateHeader(NDSHeader* ndsHeader)
{
auto* headerDataModel = new NDSHeaderModel(ndsHeader);
ui->unpackerHeaderDataTable->setModel(headerDataModel);
ui->unpackerHeaderDataTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
ui->unpackerHeaderDataTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch);
}
void MainWindow::enableExtractionButtons()
{
ui->unpackerExtractorGbx->setEnabled(true);
ui->unpackerExtraGbx->setEnabled(true);
if (ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9OverlayAddress, 1).data().toString().toUInt(nullptr,16) == 0)
{
ui->unpackerDumpArm9OverlayBtn->setEnabled(false);
ui->unpackerDumpArm9OverlayFilesBtn->setEnabled(false);
}
else
{
ui->unpackerDumpArm9OverlayBtn->setEnabled(true);
ui->unpackerDumpArm9OverlayFilesBtn->setEnabled(true);
}
if (ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7OverlayAddress, 1).data().toString().toUInt(nullptr,16) == 0)
{
ui->unpackerDumpArm7OverlayBtn->setEnabled(false);
ui->unpackerDumpArm7OverlayFilesBtn->setEnabled(false);
}
else
{
ui->unpackerDumpArm7OverlayBtn->setEnabled(true);
ui->unpackerDumpArm7OverlayFilesBtn->setEnabled(true);
}
}
void MainWindow::disableExtractionButtons()
{
ui->unpackerExtractorGbx->setEnabled(false);
ui->unpackerExtraGbx->setEnabled(false);
}
NFResult MainWindow::dumpHeader(const std::string& dirPath)
{
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
0,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::HeaderSize, 1).data().toString().toUInt(nullptr,16));
}
NFResult MainWindow::dumpArm9Bin(const std::string& dirPath, bool dumpExtraBytes)
{
uint32_t size = ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9Size, 1).data().toString().toUInt(nullptr,16);
if (dumpExtraBytes)
size += 12;
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9RomAddress, 1).data().toString().toUInt(nullptr,16),
size);
}
NFResult MainWindow::dumpArm7Bin(const std::string& dirPath)
{
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7RomAddress, 1).data().toString().toUInt(nullptr,16),
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7Size, 1).data().toString().toUInt(nullptr,16));
}
NFResult MainWindow::dumpFnt(const std::string& dirPath)
{
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::FilenameTableAddress, 1).data().toString().toUInt(nullptr,16),
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::FilenameTableSize, 1).data().toString().toUInt(nullptr,16));
}
NFResult MainWindow::dumpFat(const std::string& dirPath)
{
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::FATAddress, 1).data().toString().toUInt(nullptr,16),
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::FATSize, 1).data().toString().toUInt(nullptr,16));
}
NFResult MainWindow::dumpArm9Overlay(const std::string& dirPath)
{
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9OverlayAddress, 1).data().toString().toUInt(nullptr,16),
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9OverlaySize, 1).data().toString().toUInt(nullptr,16));
}
NFResult MainWindow::dumpArm9OverlayFiles(const std::string& dirPath)
{
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);
}
NFResult MainWindow::dumpArm7Overlay(const std::string& dirPath)
{
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7OverlayAddress, 1).data().toString().toUInt(nullptr,16),
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7OverlaySize, 1).data().toString().toUInt(nullptr,16));
}
NFResult MainWindow::dumpArm7OverlayFiles(const std::string& dirPath)
{
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);
}
NFResult MainWindow::dumpIconTitle(const std::string& dirPath)
{
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::IconTitleAddress, 1).data().toString().toUInt(nullptr,16),
ICON_TITLE_SIZE);
}
NFResult MainWindow::dumpFatFiles(const std::string& dirPath)
{
uint32_t startAddr = ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::IconTitleAddress, 1).data().toString().toUInt(nullptr,16) + IconTitleSize ;
uint32_t size = ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::UsedRomSize, 1).data().toString().toUInt(nullptr,16) - startAddr;
return ndsFactory.dumpDataFromFile(
ui->loadedRomPath->text().toStdString(),
dirPath,
startAddr,
size);
}
NFResult MainWindow::dumpEverything(QString dirPath)
{
NFResult nfResult;
nfResult = dumpHeader(QDir::toNativeSeparators(dirPath + "/header.bin").toStdString());
if (!nfResult.result) return nfResult;
nfResult = dumpArm9Bin(QDir::toNativeSeparators(dirPath+"/arm9.bin").toStdString(), true);
if (!nfResult.result) return nfResult;
nfResult = dumpArm7Bin(QDir::toNativeSeparators(dirPath+"/arm7.bin").toStdString());
if (!nfResult.result) return nfResult;
nfResult = dumpFnt(QDir::toNativeSeparators(dirPath+"/fnt.bin").toStdString());
if (!nfResult.result) return nfResult;
nfResult = dumpFat(QDir::toNativeSeparators(dirPath+"/fat.bin").toStdString());
if (!nfResult.result) return nfResult;
if(ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM9OverlayAddress, 1).data().toString().toUInt(nullptr,16) != 0) {
nfResult = dumpArm9Overlay(QDir::toNativeSeparators(dirPath+"/a9ovr.bin").toStdString());
if (!nfResult.result) return nfResult;
nfResult = dumpArm9OverlayFiles(QDir::toNativeSeparators(dirPath+"/a9ovr_data.bin").toStdString());
if (!nfResult.result) return nfResult;
}
if(ui->unpackerHeaderDataTable->model()->index(NDSHeaderNames::ARM7OverlayAddress, 1).data().toString().toUInt(nullptr,16) != 0) {
nfResult = dumpArm7Overlay(QDir::toNativeSeparators(dirPath+"/a7ovr.bin").toStdString());
if (!nfResult.result) return nfResult;
nfResult = dumpArm7OverlayFiles(QDir::toNativeSeparators(dirPath+"/a7ovr_data.bin").toStdString());
if (!nfResult.result) return nfResult;
}
nfResult = dumpIconTitle(QDir::toNativeSeparators(dirPath+"/itl.bin").toStdString());
if (!nfResult.result) return nfResult;
nfResult = dumpFatFiles(QDir::toNativeSeparators(dirPath+"/fat_data.bin").toStdString());
if (!nfResult.result) return nfResult;
return { true, "" };
}

View File

@ -1,175 +0,0 @@
#include <QFileDialog>
#include <vector>
#include <QMessageBox>
#include "./../../mainwindow.h"
#include "./../../ui_mainwindow.h"
#include "./../../utils/filepicker.h"
#include "./../../utils/ui.h"
void MainWindow::on_loadRomBtn_clicked()
{
NDSHeader *pNDSHeader;
QString romPath = QFileDialog::getOpenFileName(
Q_NULLPTR,
"NDS Rom",
QDir::currentPath(),
"NDS Rom (*.nds)");
if (romPath.isNull()) return;
ui->loadedRomPath->setText(romPath.toUtf8());
if (ndsFactory.loadRomHeader(ui->loadedRomPath->text().toStdString(), romHeader).result)
{
pNDSHeader = reinterpret_cast<NDSHeader*>(romHeader.data());
populateHeader(pNDSHeader);
enableExtractionButtons();
}
else
{
disableExtractionButtons();
}
}
void MainWindow::on_unpackerDumpHeaderBtn_clicked()
{
ui->unpackerDumpHeaderBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS Header", "header.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpHeader(dirPath.toStdString()));
ui->unpackerDumpHeaderBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpArm9Btn_clicked()
{
ui->unpackerDumpArm9Btn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS ARM9", "arm9.bin", "Binary (*.bin)");
QMessageBox::StandardButton dumpExtraBytes = QMessageBox::question(
this,
"NDSFactory",
"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()) notifyExtractionResult(dumpArm9Bin(dirPath.toStdString(), dumpExtraBytes == QMessageBox::Yes ? true : false));
ui->unpackerDumpArm9Btn->setEnabled(true);
}
void MainWindow::on_unpackerDumpArm7Btn_clicked()
{
ui->unpackerDumpArm7Btn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS ARM7", "arm7.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpArm7Bin(dirPath.toStdString()));
ui->unpackerDumpArm7Btn->setEnabled(true);
}
void MainWindow::on_unpackerDumpFntBtn_clicked()
{
ui->unpackerDumpFntBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS FNT", "fnt.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpFnt(dirPath.toStdString()));
ui->unpackerDumpFntBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpFatBtn_clicked()
{
ui->unpackerDumpFatBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS FAT", "fat.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpFat(dirPath.toStdString()));
ui->unpackerDumpFatBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpArm9OverlayBtn_clicked()
{
ui->unpackerDumpArm9OverlayBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS ARM9 Overlay", "a9ovr.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpArm9Overlay(dirPath.toStdString()));
ui->unpackerDumpArm9OverlayBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpArm7OverlayBtn_clicked()
{
ui->unpackerDumpArm7OverlayBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS ARM7 Overlay", "a7ovr.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpArm7Overlay(dirPath.toStdString()));
ui->unpackerDumpArm7OverlayBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpIconTitleLogoBtn_clicked()
{
ui->unpackerDumpIconTitleLogoBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS IconTitleLogo", "itl.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpIconTitle(dirPath.toStdString()));
ui->unpackerDumpIconTitleLogoBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpFatFilesBtn_clicked()
{
ui->unpackerDumpFatFilesBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS FAT Files", "fat_data.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpFatFiles(dirPath.toStdString()));
ui->unpackerDumpFatFilesBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpArm9OverlayFilesBtn_clicked()
{
ui->unpackerDumpArm9OverlayFilesBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS ARM9 Overlay Data", "a9ovr_data.bin", "Binary (*.bin)");
if (!dirPath.isNull()) notifyExtractionResult(dumpArm9OverlayFiles(dirPath.toStdString()));
ui->unpackerDumpArm9OverlayFilesBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpArm7OverlayFilesBtn_clicked()
{
ui->unpackerDumpArm7OverlayFilesBtn->setEnabled(false);
QString dirPath = customSaveFileDialog("NDS ARM7 Overlay Data", "a7ovr_data.bin", "Binary (*.bin)");
if (!dirPath.isNull())
notifyExtractionResult(dumpArm7OverlayFiles(dirPath.toStdString()));
ui->unpackerDumpArm7OverlayFilesBtn->setEnabled(true);
}
void MainWindow::on_unpackerDumpEverythingBtn_clicked()
{
ui->unpackerDumpEverythingBtn->setEnabled(false);
QString dirPath = QFileDialog::getExistingDirectory(
this, tr("Select Directory"),
"",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dirPath.isNull())
notifyExtractionResult(dumpEverything(dirPath));
ui->unpackerDumpEverythingBtn->setEnabled(true);
}

View File

@ -1,20 +0,0 @@
#pragma once
#include <QFileDialog>
inline QString customSaveFileDialog(const QString& title, const QString& defaultName, const QString& filter)
{
static QString lastUsedPath;
QString selectedPath = QFileDialog::getSaveFileName(
Q_NULLPTR,
title,
lastUsedPath + defaultName,
filter);
if (!selectedPath.isNull())
lastUsedPath = selectedPath.mid(0, selectedPath.lastIndexOf('/', Qt::CaseInsensitive)+1);
return selectedPath;
}

View File

@ -1,60 +0,0 @@
#pragma once
#include <QApplication>
#include <QPalette>
#include <QSettings>
#include <QMessageBox>
inline void setDarkTheme(QApplication& app)
{
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, QColor(35, 35, 35));
darkPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::BrightText, Qt::red);
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
darkPalette.setColor(QPalette::HighlightedText, Qt::black);
app.setPalette(darkPalette);
}
inline void setLightTheme(QApplication& app)
{
QPalette lightPalette;
lightPalette.setColor(QPalette::Window, QColor(240, 240, 240));
lightPalette.setColor(QPalette::WindowText, Qt::black);
lightPalette.setColor(QPalette::Base, QColor(255, 255, 255));
lightPalette.setColor(QPalette::AlternateBase, QColor(233, 233, 233));
lightPalette.setColor(QPalette::ToolTipBase, Qt::black);
lightPalette.setColor(QPalette::ToolTipText, Qt::white);
lightPalette.setColor(QPalette::Text, Qt::black);
lightPalette.setColor(QPalette::Button, QColor(240, 240, 240));
lightPalette.setColor(QPalette::ButtonText, Qt::black);
lightPalette.setColor(QPalette::BrightText, Qt::red);
lightPalette.setColor(QPalette::Link, QColor(42, 130, 218));
lightPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
lightPalette.setColor(QPalette::HighlightedText, Qt::white);
app.setPalette(lightPalette);
}
inline void setTheme(QString themeValue)
{
QSettings settings;
settings.setValue("theme", themeValue);
QMessageBox::information(nullptr, "NDSFactory", "Restart NDSFactory to change theme!");
}
inline QString getCurrentTheme()
{
QSettings settings;
return settings.value("theme", "default").toString();
}

View File

@ -1,16 +0,0 @@
#pragma once
#include <QMessageBox>
#include "../../ndsfactory/nfresult.h"
void notifyExtractionResult(NFResult nfResult)
{
if (nfResult.result)
{
QMessageBox::information(Q_NULLPTR, "NDSFactory", "Extraction completed!");
}
else
{
QMessageBox::critical(Q_NULLPTR, "NDSFactory", nfResult.message.c_str());
}
}

222
unpackertabfunctions.cpp Normal file
View File

@ -0,0 +1,222 @@
#include <QDir>
#include <stdlib.h>
#include <cstring>
#include <sstream>
#include <iomanip>
#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<char*>(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<char*>(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!
}

209
unpackertabsignals.cpp Normal file
View File

@ -0,0 +1,209 @@
#include <QFileDialog>
#include <vector>
#include <QMessageBox>
#include "mainwindow.h"
#include "ui_mainwindow.h"
void MainWindow::on_loadRomBtn_clicked()
{
std::vector<char> 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<NDSHeader*>(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();
}