mirror of
https://github.com/Luca1991/NDSFactory.git
synced 2025-07-09 05:30:12 +02:00
Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2e129375f9 | ||
|
0ee258df2d | ||
|
82cb6f3108 | ||
|
732a2541ee | ||
|
55fa399dc9 | ||
|
bf4195b581 | ||
|
c916f47f75 | ||
|
11367bfec2 | ||
|
a7537b5515 | ||
|
dec52435c5 | ||
|
4d94a0dc34 | ||
|
8f755e4b65 | ||
|
872514cce5 | ||
|
ac5df00de3 | ||
|
f46e5275d3 | ||
|
e2e53cbed7 | ||
|
c453236abd | ||
|
a2739a9ca8 | ||
|
e17d3805aa | ||
|
099d04d432 | ||
|
dadd1d5c1f | ||
|
ca8ad8259b | ||
|
fb12309ea0 | ||
|
e788d95289 | ||
|
921eef86e2 | ||
|
d69e4e13fa | ||
|
4b886a9033 | ||
|
aa2ed50ade | ||
|
ec81e2bfbe | ||
|
30425b6bb8 | ||
|
319d0e232e | ||
|
f64b0702a4 | ||
|
31148e2337 | ||
|
7f81130d90 | ||
|
93a037e6c1 | ||
|
658ca1b74c | ||
|
c8fc9006f2 | ||
|
b334ff78ff | ||
|
3c7bae69f8 | ||
|
bf8224eeb0 | ||
|
439fe70f31 | ||
|
573fc3b3cd | ||
|
1b7e29a7b0 | ||
|
a4c6b5f66e | ||
|
a3e006fa2f | ||
|
d0d4138d3f | ||
|
aaa60c9bb0 | ||
|
33d797ca21 |
154
.github/workflows/build.yml
vendored
Normal file
154
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
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
398
.gitignore
vendored
@ -41,3 +41,401 @@ target_wrapper.*
|
||||
|
||||
# QtCreator CMake
|
||||
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
|
||||
|
105
CMakeLists.txt
Normal file
105
CMakeLists.txt
Normal file
@ -0,0 +1,105 @@
|
||||
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)
|
22
CMakePresets.json
Normal file
22
CMakePresets.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"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="
|
||||
}
|
||||
}
|
||||
}
|
76
CMakeUserPresets.json
Normal file
76
CMakeUserPresets.json
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"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="
|
||||
}
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# 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
|
62
README.md
62
README.md
@ -3,62 +3,64 @@
|
||||
[](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 [](https://ko-fi.com/Z8Z511SOI)
|
||||
If you find this software useful, please consider supporting it:
|
||||
[](https://ko-fi.com/Z8Z511SOI)
|
||||
|
||||

|
||||
|
||||
**!!!ROM WITH OVERLAY ARE CURRENTLY NOT SUPPORTED!!!**
|
||||
|
||||
# Description
|
||||
|
||||
This software will help you to easily unpack and repack Nintendo DS roms, but **IT REQUIRES SOME KNOWLEDGE!**
|
||||
NDSFactory helps you easily unpack and repack Nintendo DS ROMs, but **some technical knowledge is required.**
|
||||
|
||||
Basically an NDS software is composed of the following sections:
|
||||
A typical NDS ROM consists of the following sections:
|
||||
* Header
|
||||
* ARM9 Binary
|
||||
* ARM9 Overlay (Optional)
|
||||
* ARM9 Overlay Files (Optional)
|
||||
* ARM7 Binary
|
||||
* ARM7 Overlay (Optional)
|
||||
* ARM7 Overlay Files (Optional)
|
||||
* FNT (Filename Table)
|
||||
* FAT (File Allocation Table)
|
||||
* ARM9/ARM7 Overlay (Optional)
|
||||
* ARM9/ARM7 Overlay Files (Optional)
|
||||
* Icon/Title Logo
|
||||
* FAT Files (The actual files used by the software, like Graphics, Music etc.)
|
||||
|
||||
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).
|
||||
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.**
|
||||
|
||||
**This software will be particularly useful if you want to mod your games or write a trainer for them.**
|
||||
This tool is particularly useful for modding games or writing trainers.
|
||||
|
||||
# How to use it
|
||||
# How to use
|
||||
|
||||
## Unpacker Tab
|
||||
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.
|
||||
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.
|
||||
|
||||
**You can then do what you want with these sections (inject code, apply patches etc.)**
|
||||
|
||||
## Packer Tab
|
||||
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).
|
||||
In the Packer Tab, you can recreate a .nds file using your edited sections.
|
||||
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).
|
||||
|
||||
## 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.
|
||||
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 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.
|
||||
|
||||
# Know Limitations/Possible Future Featurs/Bugs
|
||||
# Credits
|
||||
|
||||
* 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
|
||||
If you find a bug, feel free to open an issue or submit a pull request :)
|
||||
|
||||
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
|
||||
Special thanks to [Antonio Barba](https://github.com/antoniobarba) & [Davide Trogu](https://github.com/Dax89)
|
||||
|
||||
Developed with ❤ by Luca D'Amico
|
||||
|
@ -1,15 +0,0 @@
|
||||
#include "aboutdialog.h"
|
||||
#include "ui_aboutdialog.h"
|
||||
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#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
|
55
cmake/sanitizers.cmake
Normal file
55
cmake/sanitizers.cmake
Normal file
@ -0,0 +1,55 @@
|
||||
# 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)
|
||||
|
@ -1,7 +0,0 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
|
||||
bool MainWindow::patchFat(const std::string& loadPath, uint32_t shiftSize, const std::string& savePath)
|
||||
{
|
||||
return ndsFactory.patchFat(loadPath, shiftSize, savePath);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
#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!"));
|
||||
|
||||
}
|
22
main.cpp
22
main.cpp
@ -1,11 +1,23 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include <QApplication>
|
||||
#include <QStyleFactory>
|
||||
#include "ui/utils/theme.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationName("NDSFactory");
|
||||
app.setOrganizationName("NDSFactory");
|
||||
|
||||
return a.exec();
|
||||
QString theme = getCurrentTheme();
|
||||
if(theme == "dark")
|
||||
setDarkTheme(app);
|
||||
else if(theme == "light")
|
||||
setLightTheme(app);
|
||||
|
||||
MainWindow mainWindow;
|
||||
mainWindow.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
106
mainwindow.h
106
mainwindow.h
@ -1,106 +0,0 @@
|
||||
#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
2066
mainwindow.ui
File diff suppressed because it is too large
Load Diff
147
ndsfactory.cpp
147
ndsfactory.cpp
@ -1,147 +0,0 @@
|
||||
#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
29
ndsfactory.h
@ -1,29 +0,0 @@
|
||||
#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
|
40
ndsfactory/crctable.h
Normal file
40
ndsfactory/crctable.h
Normal file
@ -0,0 +1,40 @@
|
||||
#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
|
||||
};
|
@ -1,5 +1,4 @@
|
||||
#ifndef FATSTRUCT_H
|
||||
#define FATSTRUCT_H
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@ -8,4 +7,7 @@ struct FatRange {
|
||||
uint32_t endAddr;
|
||||
};
|
||||
|
||||
#endif // FATSTRUCT_H
|
||||
struct FatFileID {
|
||||
uint16_t id;
|
||||
std::string path;
|
||||
};
|
405
ndsfactory/ndsfactory.cpp
Normal file
405
ndsfactory/ndsfactory.cpp
Normal file
@ -0,0 +1,405 @@
|
||||
#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;
|
||||
|
||||
}
|
32
ndsfactory/ndsfactory.h
Normal file
32
ndsfactory/ndsfactory.h
Normal file
@ -0,0 +1,32 @@
|
||||
#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);
|
||||
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef NDSHEADER_H
|
||||
#define NDSHEADER_H
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@ -69,6 +68,3 @@ struct NDSHeader
|
||||
unsigned char Reserved4[0x90];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#endif // NDSHEADER_H
|
9
ndsfactory/nfresult.h
Normal file
9
ndsfactory/nfresult.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
struct NFResult
|
||||
{
|
||||
bool result;
|
||||
std::string message;
|
||||
};
|
@ -1,353 +0,0 @@
|
||||
#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;
|
||||
}
|
BIN
res/ndsfactory.icns
Normal file
BIN
res/ndsfactory.icns
Normal file
Binary file not shown.
BIN
res/ndsfactory.ico
Normal file
BIN
res/ndsfactory.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
1
res/resources.rc
Normal file
1
res/resources.rc
Normal file
@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON "ndsfactory.ico"
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 45 KiB |
21
ui/dialogs/about/aboutdialog.cpp
Normal file
21
ui/dialogs/about/aboutdialog.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#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;
|
||||
}
|
19
ui/dialogs/about/aboutdialog.h
Normal file
19
ui/dialogs/about/aboutdialog.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class AboutDialog;
|
||||
}
|
||||
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AboutDialog(QWidget *parent = nullptr);
|
||||
~AboutDialog();
|
||||
|
||||
private:
|
||||
Ui::AboutDialog *ui;
|
||||
|
||||
};
|
@ -7,33 +7,33 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
<height>179</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>About</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="aboutCloseBtnBx">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>300</x>
|
||||
<y>260</y>
|
||||
<y>140</y>
|
||||
<width>81</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="aboutSoftwareNameLbl">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>150</y>
|
||||
<y>20</y>
|
||||
<width>381</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
@ -42,33 +42,33 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NDS Factory V1.0</string>
|
||||
<string>NDSFactory V1.3.2</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="aboutSoftwareAuthorLbl">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>180</y>
|
||||
<y>70</y>
|
||||
<width>381</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>(C) 2019 - Luca D'Amico</string>
|
||||
<string>(C) 2019-2025 - Luca D'Amico</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="aboutSpecialThanks">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>200</y>
|
||||
<y>90</y>
|
||||
<width>381</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
@ -77,14 +77,14 @@
|
||||
<string>Special Thanks To:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="aboutSpecialThanks2ndLine">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>220</y>
|
||||
<y>110</y>
|
||||
<width>381</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
@ -93,7 +93,23 @@
|
||||
<string>Dax89 (Davide Trogu) & Kaneb (Antonio Barba)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::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>
|
||||
</widget>
|
||||
</widget>
|
6
ui/dialogs/about/revision.h
Normal file
6
ui/dialogs/about/revision.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef REVISION_H
|
||||
#define REVISION_H
|
||||
|
||||
#define GIT_COMMIT_HASH "c916f47"
|
||||
|
||||
#endif
|
6
ui/dialogs/about/revision.h.in
Normal file
6
ui/dialogs/about/revision.h.in
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef REVISION_H
|
||||
#define REVISION_H
|
||||
|
||||
#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@"
|
||||
|
||||
#endif
|
@ -1,6 +1,8 @@
|
||||
#include <QApplication>
|
||||
#include "mainwindow.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "dialogs/about/aboutdialog.h"
|
||||
#include "utils/theme.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
@ -25,3 +27,18 @@ void MainWindow::on_actionAbout_triggered()
|
||||
AboutDialog aboutDialog;
|
||||
aboutDialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionDark_triggered()
|
||||
{
|
||||
setTheme("dark");
|
||||
}
|
||||
|
||||
void MainWindow::on_actionLight_triggered()
|
||||
{
|
||||
setTheme("light");
|
||||
}
|
||||
|
||||
void MainWindow::on_actionDefault_triggered()
|
||||
{
|
||||
setTheme("default");
|
||||
}
|
116
ui/mainwindow.h
Normal file
116
ui/mainwindow.h
Normal file
@ -0,0 +1,116 @@
|
||||
#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);
|
||||
};
|
1029
ui/mainwindow.ui
Normal file
1029
ui/mainwindow.ui
Normal file
File diff suppressed because it is too large
Load Diff
190
ui/models/ndsheadermodel.cpp
Normal file
190
ui/models/ndsheadermodel.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#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;
|
||||
}
|
22
ui/models/ndsheadermodel.h
Normal file
22
ui/models/ndsheadermodel.h
Normal file
@ -0,0 +1,22 @@
|
||||
#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;
|
||||
};
|
45
ui/tabs/commons/headernames.cpp
Normal file
45
ui/tabs/commons/headernames.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#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"
|
||||
};
|
53
ui/tabs/commons/headernames.h
Normal file
53
ui/tabs/commons/headernames.h
Normal file
@ -0,0 +1,53 @@
|
||||
#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
|
||||
};
|
||||
}
|
19
ui/tabs/fattools/fattoolstabfunctions.cpp
Normal file
19
ui/tabs/fattools/fattoolstabfunctions.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#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);
|
||||
}
|
155
ui/tabs/fattools/fattoolstabsignals.cpp
Normal file
155
ui/tabs/fattools/fattoolstabsignals.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
#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);
|
||||
}
|
369
ui/tabs/packer/packertabfunctions.cpp
Normal file
369
ui/tabs/packer/packertabfunctions.cpp
Normal file
@ -0,0 +1,369 @@
|
||||
#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();
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "./../../mainwindow.h"
|
||||
#include "./../../ui_mainwindow.h"
|
||||
#include "./../../utils/filepicker.h"
|
||||
#include "../commons/headernames.h"
|
||||
|
||||
|
||||
void MainWindow::on_packerLoadHeaderBtn_clicked()
|
||||
{
|
||||
std::vector<char> romHeader;
|
||||
NDSHeader *pNDSHeader;
|
||||
|
||||
QString headerPath = QFileDialog::getOpenFileName(
|
||||
@ -14,16 +16,14 @@ void MainWindow::on_packerLoadHeaderBtn_clicked()
|
||||
QDir::currentPath(),
|
||||
"NDS Header (*.bin)");
|
||||
|
||||
if(headerPath.isNull())
|
||||
{
|
||||
QMessageBox::critical(this, tr("NDS Factory"), tr("Unable to open file!"));
|
||||
return;
|
||||
}
|
||||
if (headerPath.isNull()) return;
|
||||
|
||||
if (ndsFactory.loadRomHeader(headerPath.toStdString(), romHeader))
|
||||
if (ndsFactory.loadRomHeader(headerPath.toStdString(), romHeader).result)
|
||||
{
|
||||
pNDSHeader = reinterpret_cast<NDSHeader*>(romHeader.data());
|
||||
populatePackerSectionHeader(pNDSHeader);
|
||||
enableCalcCrcButton();
|
||||
enableBuildRomButton();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ void MainWindow::on_packerLoadArm9BinBtn_clicked()
|
||||
QString arm9BinPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Arm9Bin",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS Arm9Bin (*.bin)");
|
||||
|
||||
if(!arm9BinPath.isNull())
|
||||
@ -46,7 +46,7 @@ void MainWindow::on_packerLoadArm7BinBtn_clicked()
|
||||
QString arm7BinPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Arm7Bin",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS Arm7Bin (*.bin)");
|
||||
|
||||
if(!arm7BinPath.isNull())
|
||||
@ -60,7 +60,7 @@ void MainWindow::on_packerLoadFntBtn_clicked()
|
||||
QString fntPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Fnt",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS Fnt (*.bin)");
|
||||
|
||||
if(!fntPath.isNull())
|
||||
@ -74,7 +74,7 @@ void MainWindow::on_packerLoadFatBtn_clicked()
|
||||
QString fatPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Fat",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS Fat (*.bin)");
|
||||
|
||||
if(!fatPath.isNull())
|
||||
@ -88,7 +88,7 @@ void MainWindow::on_packerLoadArm9OverlayBtn_clicked()
|
||||
QString arm9OverlayPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Arm9Overlay",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS A9OVR (*.bin)");
|
||||
|
||||
if( !arm9OverlayPath.isNull() )
|
||||
@ -102,7 +102,7 @@ void MainWindow::on_packerLoadArm9OverlayFilesBtn_clicked()
|
||||
QString arm9OverlayFilesPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Arm9Overlay Data",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS A9OVR_DATA (*.bin)");
|
||||
|
||||
if(!arm9OverlayFilesPath.isNull())
|
||||
@ -116,7 +116,7 @@ void MainWindow::on_packerLoadArm7OverlayBtn_clicked()
|
||||
QString arm7OverlayPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Arm7Overlay",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS A7OVR (*.bin)");
|
||||
|
||||
if(!arm7OverlayPath.isNull())
|
||||
@ -130,7 +130,7 @@ void MainWindow::on_packerLoadArm7OverlayFilesBtn_clicked()
|
||||
QString arm7OverlayFilesPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Arm7Overlay Data",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS A7OVR_DATA (*.bin)");
|
||||
|
||||
if(!arm7OverlayFilesPath.isNull())
|
||||
@ -144,7 +144,7 @@ void MainWindow::on_packerLoadIconTitleBtn_clicked()
|
||||
QString iconTitlePath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS IconTitleLogo",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS ITL (*.bin)");
|
||||
|
||||
if(!iconTitlePath.isNull())
|
||||
@ -158,28 +158,33 @@ void MainWindow::on_packerLoadFatFilesBtn_clicked()
|
||||
QString fatFilesPath = QFileDialog::getOpenFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Fat Data",
|
||||
QDir::currentPath(),
|
||||
"",
|
||||
"NDS FAT_DATA (*.bin)");
|
||||
|
||||
if(!fatFilesPath.isNull())
|
||||
{
|
||||
ui->loadedFatFilesPathEdt->setText(fatFilesPath.toUtf8());
|
||||
ui->packerFatFilesAddrEdt->setText(QString::number((ui->packerIconTitleEdt->text().toUInt(nullptr, 16) + IconTitleSize), 16));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_packerBuildNDSRomBtn_clicked()
|
||||
{
|
||||
QString dirPath = QFileDialog::getSaveFileName(
|
||||
Q_NULLPTR,
|
||||
"NDS Rom",
|
||||
"rom.nds",
|
||||
"NDS ROM (*.nds)");
|
||||
ui->packerBuildNDSRomBtn->setEnabled(false);
|
||||
|
||||
QString dirPath = customSaveFileDialog("NDS Rom",
|
||||
"rom.nds",
|
||||
"NDS ROM (*.nds)");
|
||||
|
||||
if (!dirPath.isNull())
|
||||
{
|
||||
writeEverything(dirPath.toStdString()) ? QMessageBox::information(this, tr("NDS Factory"), tr("Creation completed!"))
|
||||
: QMessageBox::critical(this, tr("NDS Factory"), tr("Error during the creation!"));
|
||||
NFResult nfResult = writeEverything(dirPath.toStdString());
|
||||
nfResult.result? QMessageBox::information(this, tr("NDSFactory"), tr("Creation completed!"))
|
||||
: QMessageBox::critical(this, tr("NDSFactory"), nfResult.message.c_str());
|
||||
}
|
||||
ui->packerBuildNDSRomBtn->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::on_packerCalcHeaderCrcBtn_clicked()
|
||||
{
|
||||
calcHeaderCrc16();
|
||||
}
|
198
ui/tabs/unpacker/unpackertabfunctions.cpp
Normal file
198
ui/tabs/unpacker/unpackertabfunctions.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
#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, "" };
|
||||
}
|
175
ui/tabs/unpacker/unpackertabsignals.cpp
Normal file
175
ui/tabs/unpacker/unpackertabsignals.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
#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);
|
||||
}
|
20
ui/utils/filepicker.h
Normal file
20
ui/utils/filepicker.h
Normal file
@ -0,0 +1,20 @@
|
||||
#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;
|
||||
}
|
60
ui/utils/theme.h
Normal file
60
ui/utils/theme.h
Normal file
@ -0,0 +1,60 @@
|
||||
#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();
|
||||
}
|
16
ui/utils/ui.h
Normal file
16
ui/utils/ui.h
Normal file
@ -0,0 +1,16 @@
|
||||
#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());
|
||||
}
|
||||
}
|
@ -1,222 +0,0 @@
|
||||
#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!
|
||||
}
|
@ -1,209 +0,0 @@
|
||||
#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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user