mirror of
https://github.com/wiiu-env/wudd.git
synced 2024-11-22 09:59:16 +01:00
First commit
This commit is contained in:
commit
648c0d0fd7
66
.github/workflows/ci.yml
vendored
Normal file
66
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
name: CI-Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
|
||||
build-binary:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout submodules using a PAT
|
||||
run: |
|
||||
git config --file .gitmodules --get-regexp url | while read url; do
|
||||
git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
|
||||
done
|
||||
git submodule sync
|
||||
git submodule update --init --recursive
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.rpx"
|
||||
deploy-binary:
|
||||
needs: build-binary
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Get environment variables
|
||||
id: get_repository_name
|
||||
run: |
|
||||
echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//") >> $GITHUB_ENV
|
||||
echo DATETIME=$(echo $(date '+%Y%m%d-%H%M%S')) >> $GITHUB_ENV
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: wiiu
|
||||
- name: zip artifact
|
||||
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip wiiu
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
release_name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
body: |
|
||||
Not a stable release:
|
||||
${{ github.event.head_commit.message }}
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: ./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
||||
asset_name: ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
||||
asset_content_type: application/unknown
|
24
.github/workflows/pr.yml
vendored
Normal file
24
.github/workflows/pr.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: CI-PR
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build-binary:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout submodules using a PAT
|
||||
run: |
|
||||
git config --file .gitmodules --get-regexp url | while read url; do
|
||||
git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
|
||||
done
|
||||
git submodule sync
|
||||
git submodule update --init --recursive
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.rpx"
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
CMakeLists.txt
|
||||
.idea/
|
||||
build/
|
||||
cmake-build-debug/
|
||||
*.elf
|
||||
*.rpx
|
6
Dockerfile
Normal file
6
Dockerfile
Normal file
@ -0,0 +1,6 @@
|
||||
FROM wiiuenv/devkitppc:20210920
|
||||
|
||||
COPY --from=wiiuenv/libiosuhax:20211008 /artifacts $DEVKITPRO
|
||||
COPY --from=wiiuenv/libntfs:20201210 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
152
Makefile
Normal file
152
Makefile
Normal file
@ -0,0 +1,152 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
include $(DEVKITPRO)/wut/share/wut_rules
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#-------------------------------------------------------------------------------
|
||||
TARGET := wudump
|
||||
BUILD := build
|
||||
SOURCES := source \
|
||||
source/fs \
|
||||
source/input \
|
||||
source/common \
|
||||
source/utils \
|
||||
source/utils/blocksize \
|
||||
source/WUD \
|
||||
source/WUD/content \
|
||||
source/WUD/content/partitions \
|
||||
source/WUD/content/partitions/volumes \
|
||||
source/WUD/header \
|
||||
source/WUD/entities/FST \
|
||||
source/WUD/entities/FST/header \
|
||||
source/WUD/entities/FST/nodeentry \
|
||||
source/WUD/entities/FST/sectionentry \
|
||||
source/WUD/entities/FST/stringtable \
|
||||
source/WUD/entities/TMD
|
||||
|
||||
DATA := data
|
||||
INCLUDES := include source
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#-------------------------------------------------------------------------------
|
||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||
$(MACHDEP)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++20
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lwut -lntfs -liosuhax
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level
|
||||
# containing include and lib
|
||||
#-------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUT_ROOT)/usr
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#-------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#-------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#-------------------------------------------------------------------------------
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).rpx $(TARGET).elf
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#-------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).rpx
|
||||
|
||||
$(OUTPUT).rpx : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#-------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#-------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
27
README.md
Normal file
27
README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Wudump
|
||||
|
||||
RPX version of [wudump](https://github.com/FIX94/wudump).
|
||||
|
||||
Supports dumping as [WUX](https://gbatemp.net/threads/wii-u-image-wud-compression-tool.397901/) and WUD, but only to NTFS formatted USB drives and without dumping the `game.key`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [wut](https://github.com/decaf-emu/wut)
|
||||
- [libiosuhax](https://github.com/wiiu-env/libiosuhax)
|
||||
- [libfat](https://github.com/wiiu-env/libfat)
|
||||
- [libntfs](https://github.com/wiiu-env/libntfs)
|
||||
|
||||
## Building using the Dockerfile
|
||||
|
||||
It's possible to use a docker image for building. This way you don't need anything installed on your host system.
|
||||
|
||||
```
|
||||
# Build docker image (only needed once)
|
||||
docker build . -t wudump-builder
|
||||
|
||||
# make
|
||||
docker run -it --rm -v ${PWD}:/project wudump-builder make
|
||||
|
||||
# make clean
|
||||
docker run -it --rm -v ${PWD}:/project wudump-builder make clean
|
||||
```
|
861
source/ApplicationState.cpp
Normal file
861
source/ApplicationState.cpp
Normal file
@ -0,0 +1,861 @@
|
||||
#include "ApplicationState.h"
|
||||
#include "utils/WiiUScreen.h"
|
||||
#include "utils/ScreenUtils.h"
|
||||
#include "common/common.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/StringTools.h"
|
||||
#include "utils/rijndael.h"
|
||||
#include "fs/FSUtils.h"
|
||||
#include <sysapp/launch.h>
|
||||
#include <coreinit/ios.h>
|
||||
#include <iosuhax.h>
|
||||
#include <malloc.h>
|
||||
#include <coreinit/memdefaultheap.h>
|
||||
#include <cstdarg>
|
||||
#include <ntfs.h>
|
||||
#include <WUD/DiscReaderDiscDrive.h>
|
||||
#include <whb/proc.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <WUD/content/partitions/WiiUGMPartition.h>
|
||||
#include <WUD/header/WiiUDiscHeader.h>
|
||||
#include <WUD/entities/TMD/Content.h>
|
||||
#include <WUD/entities/TMD/TitleMetaData.h>
|
||||
#include <WUD/NUSDataProviderWUD.h>
|
||||
#include <WUD/NUSTitle.h>
|
||||
|
||||
extern ntfs_md *ntfs_mounts;
|
||||
extern int ntfs_mount_count;
|
||||
|
||||
|
||||
unsigned int swap_uint32(unsigned int val) {
|
||||
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
|
||||
return (val << 16) | (val >> 16);
|
||||
}
|
||||
|
||||
unsigned long long swap_uint64(unsigned long long val) {
|
||||
val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL);
|
||||
val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL);
|
||||
return (val << 32) | (val >> 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash function used to create a hash of each sector
|
||||
* The hashes are then compared to find duplicate sectors
|
||||
*/
|
||||
void calculateHash256(unsigned char *data, unsigned int length, unsigned char *hashOut) {
|
||||
// cheap and simple hash implementation
|
||||
// you can replace this part with your favorite hash method
|
||||
memset(hashOut, 0x00, 32);
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
hashOut[i % 32] ^= data[i];
|
||||
hashOut[(i + 7) % 32] += data[i];
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationState::ApplicationState() : log("fs:/vol/external01/wudump.log", CFile::WriteOnly) {
|
||||
this->log.fwrite("Started wudump\n");
|
||||
this->state = STATE_WELCOME_SCREEN;
|
||||
}
|
||||
|
||||
void ApplicationState::printHeader() {
|
||||
WiiUScreen::drawLine("Wudump");
|
||||
WiiUScreen::drawLine("==================");
|
||||
WiiUScreen::drawLine("");
|
||||
}
|
||||
|
||||
void ApplicationState::render() {
|
||||
WiiUScreen::clearScreen();
|
||||
|
||||
if (this->state == STATE_ERROR) {
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLinef("Error: %s", ErrorMessage().c_str());
|
||||
WiiUScreen::drawLinef("Description: %s", ErrorDescription().c_str());
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLine("Press A to return to the Wii U Menu.");
|
||||
} else if (this->state == STATE_WELCOME_SCREEN) {
|
||||
WiiUScreen::drawLine("Welcome to Wudump");
|
||||
WiiUScreen::drawLine("Press A to dump the currently inserted Disc");
|
||||
WiiUScreen::drawLine("");
|
||||
if (this->selectedOption == 0) {
|
||||
WiiUScreen::drawLine("> Dump as WUX Dump as WUD Dump as .app Exit");
|
||||
} else if (this->selectedOption == 1) {
|
||||
WiiUScreen::drawLine(" Dump as WUX > Dump as WUD Dump as .app Exit");
|
||||
} else if (this->selectedOption == 2) {
|
||||
WiiUScreen::drawLine(" Dump as WUX Dump as WUD > Dump as .app Exit");
|
||||
} else if (this->selectedOption == 3) {
|
||||
WiiUScreen::drawLine(" Dump as WUX Dump as WUD Dump as .app > Exit");
|
||||
}
|
||||
} else if (this->state == STATE_CHOOSE_TARGET) {
|
||||
printHeader();
|
||||
WiiUScreen::drawLine("Please choose your target:");
|
||||
std::vector<std::string> options;
|
||||
int32_t targetCount = 0;
|
||||
if (this->dumpFormat == DUMP_AS_APP) {
|
||||
options.emplace_back("SD");
|
||||
targetCount++;
|
||||
}
|
||||
for (int i = 0; i < ntfs_mount_count; i++) {
|
||||
options.emplace_back(ntfs_mounts[i].name);
|
||||
targetCount++;
|
||||
}
|
||||
|
||||
std::string curLine = "";
|
||||
if (this->selectedOption == 0) {
|
||||
curLine = "> Back\t";
|
||||
} else {
|
||||
curLine = " Back\t";
|
||||
}
|
||||
|
||||
if (targetCount == 0) {
|
||||
WiiUScreen::drawLine("Please insert a NTFS formatted USB drive and restart wudump\n");
|
||||
} else {
|
||||
for (int32_t i = 0; i < targetCount; i++) {
|
||||
if (this->selectedOption - 1 == i) {
|
||||
curLine += "> " + options[i];
|
||||
} else {
|
||||
curLine += " " + options[i];
|
||||
}
|
||||
curLine += "\t";
|
||||
}
|
||||
}
|
||||
WiiUScreen::drawLine(curLine.c_str());
|
||||
} else if (this->state == STATE_OPEN_ODD1) {
|
||||
WiiUScreen::drawLine("Open /dev/odd01");
|
||||
} else if (this->state == STATE_READ_DISC_INFO) {
|
||||
WiiUScreen::drawLine("Read disc information");
|
||||
} else if (this->state == STATE_READ_DISC_INFO_DONE) {
|
||||
WiiUScreen::drawLinef("Dumping: %s", this->discId);
|
||||
} else if (this->state == STATE_DUMP_TICKET) {
|
||||
WiiUScreen::drawLinef("Dumping game.key");
|
||||
} else if (this->state == STATE_DUMP_DISC_START || this->state == STATE_DUMP_DISC || this->state == STATE_WAIT_USER_ERROR_CONFIRM) {
|
||||
WiiUScreen::drawLinef("Dumping: %s", this->discId);
|
||||
|
||||
float percent = this->currentSector / (WUD_FILE_SIZE / READ_SECTOR_SIZE * 1.0f) * 100.0f;
|
||||
WiiUScreen::drawLinef("Progress: %0.2f MiB / %5.2f MiB (%2.1f %%)", this->currentSector * (READ_SECTOR_SIZE / 1024.0f / 1024.0f), WUD_FILE_SIZE / 1024.0f / 1024.0f, percent);
|
||||
if (doWUX) {
|
||||
WiiUScreen::drawLinef("Written %0.2f MiB. Compression ratio 1:%0.2f", this->hashMap.size() * (READ_SECTOR_SIZE / 1024.0f / 1024.0f),
|
||||
1.0f / (this->hashMap.size() / (float) this->currentSector));
|
||||
}
|
||||
|
||||
if (this->readResult < 0 || this->oddFd < 0) {
|
||||
WiiUScreen::drawLine();
|
||||
|
||||
if (this->oddFd < 0) {
|
||||
WiiUScreen::drawLine("Failed to open disc, try again.");
|
||||
} else {
|
||||
WiiUScreen::drawLinef("Error: Failed to read sector - Error %d", this->readResult);
|
||||
}
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLine("Press A to skip this sector (will be replaced by 0's)");
|
||||
WiiUScreen::drawLine("Press B to try again");
|
||||
} else {
|
||||
OSTime curTime = OSGetTime();
|
||||
float remaining = (WUD_FILE_SIZE - (READ_SECTOR_SIZE * this->currentSector)) / 1024.0f / 1024.0f;
|
||||
float curSpeed = READ_SECTOR_SIZE * ((this->readSectors / 1000.0f) / OSTicksToMilliseconds(curTime - startTime));
|
||||
int32_t remainingSec = remaining / curSpeed;
|
||||
int32_t minutes = (remainingSec / 60) % 60;
|
||||
int32_t seconds = remainingSec % 60;
|
||||
int32_t hours = remainingSec / 3600;
|
||||
|
||||
WiiUScreen::drawLinef("Speed: %.2f MiB/s ETA: %02dh %02dm %02ds", curSpeed, remaining, hours, minutes, seconds);
|
||||
}
|
||||
|
||||
WiiUScreen::drawLine();
|
||||
if (!this->skippedSectors.empty()) {
|
||||
WiiUScreen::drawLinef("Skipped dumping %d sectors", this->skippedSectors.size());
|
||||
}
|
||||
} else if (this->state == STATE_DUMP_DISC_DONE) {
|
||||
if (!flushWriteCache()) {
|
||||
setError(ERROR_WRITE_FAILED);
|
||||
}
|
||||
WiiUScreen::drawLinef("Dumping done! Press A to continue");
|
||||
} else if (this->state == STATE_DUMP_APP_FILES_DONE) {
|
||||
WiiUScreen::drawLinef("Dumping done! Press A to continue");
|
||||
}
|
||||
printFooter();
|
||||
WiiUScreen::flipBuffers();
|
||||
}
|
||||
|
||||
void ApplicationState::update(Input *input) {
|
||||
if (this->state == STATE_ERROR) {
|
||||
OSEnableHomeButtonMenu(true);
|
||||
if (entrySelected(input)) {
|
||||
SYSLaunchMenu();
|
||||
}
|
||||
} else if (this->state == STATE_WELCOME_SCREEN) {
|
||||
proccessMenuNavigation(input, 4);
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) {
|
||||
this->retryCount = 10;
|
||||
this->state = STATE_CHOOSE_TARGET;
|
||||
this->dumpFormat = DUMP_AS_WUX;
|
||||
} else if (this->selectedOption == 1) {
|
||||
this->retryCount = 10;
|
||||
this->state = STATE_CHOOSE_TARGET;
|
||||
this->dumpFormat = DUMP_AS_WUD;
|
||||
} else if (this->selectedOption == 2) {
|
||||
this->retryCount = 10;
|
||||
this->state = STATE_CHOOSE_TARGET;
|
||||
this->dumpFormat = DUMP_AS_APP;
|
||||
} else {
|
||||
SYSLaunchMenu();
|
||||
}
|
||||
this->selectedOption = 0;
|
||||
return;
|
||||
}
|
||||
} else if (this->state == STATE_CHOOSE_TARGET) {
|
||||
WiiUScreen::drawLine("Please choose your target");
|
||||
std::vector<std::string> options;
|
||||
uint32_t targetCount = 0;
|
||||
|
||||
if (this->dumpFormat == DUMP_AS_APP) {
|
||||
options.emplace_back("fs:/vol/external01/");
|
||||
targetCount++;
|
||||
}
|
||||
if (ntfs_mount_count > 0) {
|
||||
|
||||
for (int i = 0; i < ntfs_mount_count; i++) {
|
||||
options.emplace_back(std::string(ntfs_mounts[i].name) + ":/");
|
||||
targetCount++;
|
||||
}
|
||||
}
|
||||
|
||||
proccessMenuNavigation(input, targetCount + 1);
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) {
|
||||
this->state = STATE_WELCOME_SCREEN;
|
||||
} else if (targetCount > 0) {
|
||||
target = options[selectedOption - 1];
|
||||
this->state = STATE_OPEN_ODD1;
|
||||
}
|
||||
this->selectedOption = 0;
|
||||
}
|
||||
} else if (this->state == STATE_OPEN_ODD1) {
|
||||
if (this->readSectors > 0) {
|
||||
auto ret = IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &(this->oddFd));
|
||||
if (ret >= 0) {
|
||||
// continue!
|
||||
this->state = STATE_DUMP_DISC;
|
||||
} else {
|
||||
this->oddFd = -1;
|
||||
this->state = STATE_WAIT_USER_ERROR_CONFIRM;
|
||||
}
|
||||
return;
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("STATE_OPEN_ODD1");
|
||||
if (this->retryCount-- <= 0) {
|
||||
this->setError(ERROR_OPEN_ODD1);
|
||||
return;
|
||||
}
|
||||
auto ret = IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &(this->oddFd));
|
||||
if (ret >= 0) {
|
||||
if (this->sectorBuf == nullptr) {
|
||||
this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize);
|
||||
if (this->sectorBuf == nullptr) {
|
||||
this->setError(ERROR_MALLOC_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Opened /dev/odd01 %d", this->oddFd);
|
||||
this->state = STATE_READ_DISC_INFO;
|
||||
}
|
||||
} else if (this->state == STATE_READ_DISC_INFO) {
|
||||
DEBUG_FUNCTION_LINE("STATE_READ_DISC_INFO");
|
||||
if (IOSUHAX_FSA_RawRead(gFSAfd, this->sectorBuf, READ_SECTOR_SIZE, 1, 0, this->oddFd) >= 0) {
|
||||
this->discId[10] = '\0';
|
||||
memcpy(this->discId, sectorBuf, 10);
|
||||
if (this->discId[0] == 0) {
|
||||
setError(ERROR_NO_DISC_ID);
|
||||
return;
|
||||
}
|
||||
this->state = STATE_READ_DISC_INFO_DONE;
|
||||
return;
|
||||
}
|
||||
|
||||
this->setError(ERROR_READ_FIRST_SECTOR);
|
||||
return;
|
||||
} else if (this->state == STATE_READ_DISC_INFO_DONE) {
|
||||
DEBUG_FUNCTION_LINE("STATE_READ_DISC_INFO_DONE");
|
||||
this->state = STATE_DUMP_TICKET;
|
||||
} else if (this->state == STATE_DUMP_TICKET) {
|
||||
DEBUG_FUNCTION_LINE("STATE_DUMP_TICKET");
|
||||
|
||||
auto res = IOSUHAX_FSA_RawRead(gFSAfd, this->sectorBuf, READ_SECTOR_SIZE, 1, 3, this->oddFd);
|
||||
uint8_t discKey[16];
|
||||
bool hasDiscKey = false;
|
||||
if (res >= 0) {
|
||||
if (((uint32_t *) this->sectorBuf)[0] != 0xCCA6E67B) {
|
||||
uint8_t iv[16];
|
||||
memset(iv, 0, 16);
|
||||
|
||||
auto odm_handle = IOS_Open("/dev/odm", IOS_OPEN_READ);
|
||||
if (odm_handle >= 0) {
|
||||
uint32_t io_buffer[0x20 / 4];
|
||||
// disc encryption key, only works with patched IOSU
|
||||
io_buffer[0] = 3;
|
||||
if (IOS_Ioctl(odm_handle, 0x06, io_buffer, 0x14, io_buffer, 0x20) == 0) {
|
||||
memcpy(discKey, io_buffer, 16);
|
||||
hasDiscKey = true;
|
||||
}
|
||||
IOS_Close(odm_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDiscKey) {
|
||||
if (!FSUtils::CreateSubfolder(StringTools::fmt("%swudump/%s", target.c_str(), discId))) {
|
||||
setError(ERROR_WRITE_FAILED);
|
||||
return;
|
||||
}
|
||||
if (!FSUtils::saveBufferToFile(StringTools::fmt("%swudump/%s/game.key", target.c_str(), discId), discKey, 16)) {
|
||||
setError(ERROR_WRITE_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this->dumpFormat == DUMP_AS_WUX || this->dumpFormat == DUMP_AS_WUD) {
|
||||
if (this->dumpFormat == DUMP_AS_WUX) {
|
||||
this->doWUX = true;
|
||||
}
|
||||
this->state = STATE_DUMP_DISC_START;
|
||||
} else {
|
||||
this->state = STATE_DUMP_APP_FILES;
|
||||
}
|
||||
} else if (this->state == STATE_DUMP_APP_FILES) {
|
||||
ApplicationState::dumpAppFiles();
|
||||
if (this->state != STATE_ERROR) {
|
||||
this->state = STATE_DUMP_APP_FILES_DONE;
|
||||
}
|
||||
} else if (this->state == STATE_DUMP_APP_FILES_DONE) {
|
||||
if (entrySelected(input)) {
|
||||
this->state = STATE_WELCOME_SCREEN;
|
||||
if (this->oddFd >= 0) {
|
||||
IOSUHAX_FSA_RawClose(gFSAfd, this->oddFd);
|
||||
this->oddFd = -1;
|
||||
}
|
||||
this->currentSector = 0;
|
||||
this->readSectors = 0;
|
||||
}
|
||||
} else if (this->state == STATE_DUMP_DISC_START) {
|
||||
ApplicationState::clearWriteCache();
|
||||
DEBUG_FUNCTION_LINE("STATE_DUMP_DISC_START");
|
||||
if (!FSUtils::CreateSubfolder(StringTools::fmt("%swudump/%s", target.c_str(), discId))) {
|
||||
setError(ERROR_WRITE_FAILED);
|
||||
return;
|
||||
}
|
||||
this->fileHandle = new CFile(StringTools::fmt("%swudump/%s/game.%s", target.c_str(), discId, doWUX ? "wux" : "wud"), CFile::WriteOnly);
|
||||
|
||||
this->totalSectorCount = WUD_FILE_SIZE / SECTOR_SIZE;
|
||||
|
||||
if (!this->fileHandle->isOpen()) {
|
||||
DEBUG_FUNCTION_LINE("Failed to open file");
|
||||
this->setError(ERROR_FILE_OPEN_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (doWUX) {
|
||||
wuxHeader_t wuxHeader = {0};
|
||||
wuxHeader.magic0 = WUX_MAGIC_0;
|
||||
wuxHeader.magic1 = WUX_MAGIC_1;
|
||||
wuxHeader.sectorSize = swap_uint32(SECTOR_SIZE);
|
||||
wuxHeader.uncompressedSize = swap_uint64(WUD_FILE_SIZE);
|
||||
wuxHeader.flags = 0;
|
||||
|
||||
DEBUG_FUNCTION_LINE("Write header");
|
||||
this->fileHandle->write((uint8_t *) &wuxHeader, sizeof(wuxHeader_t));
|
||||
this->sectorTableStart = this->fileHandle->tell();
|
||||
|
||||
this->sectorIndexTable = (void *) malloc(totalSectorCount * 4);
|
||||
if (sectorIndexTable == nullptr) {
|
||||
this->setError(ERROR_MALLOC_FAILED);
|
||||
return;
|
||||
}
|
||||
memset(this->sectorIndexTable, 0, totalSectorCount * 4);
|
||||
|
||||
DEBUG_FUNCTION_LINE("Write empty sectorIndexTable");
|
||||
this->fileHandle->write((uint8_t *) this->sectorIndexTable, totalSectorCount * 4);
|
||||
|
||||
DEBUG_FUNCTION_LINE("Get sector table end");
|
||||
this->sectorTableEnd = this->fileHandle->tell();
|
||||
uint64_t tableEnd = this->sectorTableEnd;
|
||||
|
||||
this->sectorTableEnd += SECTOR_SIZE - 1;
|
||||
this->sectorTableEnd -= (this->sectorTableEnd % SECTOR_SIZE);
|
||||
|
||||
uint64_t padding = this->sectorTableEnd - tableEnd;
|
||||
auto *paddingData = (uint8_t *) malloc(padding);
|
||||
memset(paddingData, 0, padding);
|
||||
this->fileHandle->write(reinterpret_cast<const uint8_t *>(paddingData), padding);
|
||||
free(paddingData);
|
||||
this->hashMap.clear();
|
||||
}
|
||||
|
||||
this->writeBufferSize = READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS;
|
||||
this->writeBuffer = (void *) memalign(0x1000, this->writeBufferSize);
|
||||
if (this->writeBuffer == nullptr) {
|
||||
this->setError(ERROR_MALLOC_FAILED);
|
||||
return;
|
||||
}
|
||||
this->writeBufferPos = 0;
|
||||
|
||||
this->startTime = OSGetTime();
|
||||
|
||||
this->state = STATE_DUMP_DISC;
|
||||
this->currentSector = 0;
|
||||
this->retryCount = 10;
|
||||
this->selectedOption = 0;
|
||||
this->readSectors = 0;
|
||||
} else if (this->state == STATE_DUMP_DISC) {
|
||||
//DEBUG_FUNCTION_LINE("STATE_DUMP_DISC");
|
||||
int32_t numSectors = this->currentSector + READ_NUM_SECTORS > this->totalSectorCount ? this->totalSectorCount - this->currentSector : READ_NUM_SECTORS;
|
||||
if ((this->readResult = IOSUHAX_FSA_RawRead(gFSAfd, sectorBuf, READ_SECTOR_SIZE, numSectors, this->currentSector, this->oddFd)) >= 0) {
|
||||
if (!writeDataToFile(this->sectorBuf, numSectors)) {
|
||||
this->setError(ERROR_WRITE_FAILED);
|
||||
return;
|
||||
}
|
||||
//DEBUG_FUNCTION_LINE("Read done %lld %lld", this->currentSector, this->totalSectorCount);
|
||||
this->retryCount = 10;
|
||||
if (this->currentSector >= this->totalSectorCount) {
|
||||
this->state = STATE_DUMP_DISC_DONE;
|
||||
|
||||
if (this->fileHandle->isOpen()) {
|
||||
if (!this->flushWriteCache()) {
|
||||
this->setError(ERROR_WRITE_FAILED);
|
||||
return;
|
||||
}
|
||||
if (doWUX) {
|
||||
this->writeSectorIndexTable();
|
||||
}
|
||||
this->fileHandle->close();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->state = STATE_WAIT_USER_ERROR_CONFIRM;
|
||||
if (this->oddFd >= 0) {
|
||||
IOSUHAX_FSA_RawClose(gFSAfd, this->oddFd);
|
||||
this->oddFd = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (this->state == STATE_WAIT_USER_ERROR_CONFIRM) {
|
||||
if (this->autoSkip) {
|
||||
if (this->oddFd >= 0) {
|
||||
IOSUHAX_FSA_RawClose(gFSAfd, this->oddFd);
|
||||
this->oddFd = -1;
|
||||
}
|
||||
}
|
||||
if (this->autoSkip || (input->data.buttons_d & Input::BUTTON_A)) {
|
||||
this->log.fwrite("Skipped sector %d : 0x%ll016X-0x%ll016X, filled with 0's\n", this->currentSector, this->currentSector * READ_SECTOR_SIZE, (this->currentSector + 1) * READ_SECTOR_SIZE);
|
||||
this->state = STATE_OPEN_ODD1;
|
||||
this->skippedSectors.push_back(this->currentSector);
|
||||
// We can't use seek because we may have cached values.
|
||||
|
||||
if (this->emptySector == nullptr) {
|
||||
this->emptySector = memalign(0x100, READ_SECTOR_SIZE);
|
||||
if (this->emptySector == nullptr) {
|
||||
this->setError(ERROR_MALLOC_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->writeCached(reinterpret_cast<uint32_t>(emptySector), READ_SECTOR_SIZE)) {
|
||||
this->setError(ERROR_WRITE_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
this->currentSector += 1;
|
||||
this->readResult = 0;
|
||||
} else if (input->data.buttons_d & Input::BUTTON_B) {
|
||||
this->state = STATE_OPEN_ODD1;
|
||||
this->readResult = 0;
|
||||
} else if (input->data.buttons_d & Input::BUTTON_Y) {
|
||||
this->autoSkip = true;
|
||||
}
|
||||
} else if (this->state == STATE_DUMP_DISC_DONE) {
|
||||
if (entrySelected(input)) {
|
||||
if (this->oddFd >= 0) {
|
||||
IOSUHAX_FSA_RawClose(gFSAfd, this->oddFd);
|
||||
this->oddFd = -1;
|
||||
}
|
||||
this->state = STATE_WELCOME_SCREEN;
|
||||
this->selectedOption = 0;
|
||||
this->currentSector = 0;
|
||||
this->readSectors = 0;
|
||||
this->writtenSector = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string ApplicationState::ErrorMessage() {
|
||||
if (this->error == ERROR_NONE) {
|
||||
return "NONE";
|
||||
} else if (this->error == ERROR_IOSUHAX_FAILED) {
|
||||
return "ERROR_IOSUHAX_FAILED";
|
||||
} else if (this->error == ERROR_MALLOC_FAILED) {
|
||||
return "ERROR_MALLOC_FAILED";
|
||||
} else if (this->error == ERROR_FILE_OPEN_FAILED) {
|
||||
return "ERROR_FILE_OPEN_FAILED";
|
||||
} else if (this->error == ERROR_NO_DISC_ID) {
|
||||
return "ERROR_NO_DISC_ID";
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Error: %d", this->error);
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
|
||||
std::string ApplicationState::ErrorDescription() {
|
||||
if (this->error == ERROR_NONE) {
|
||||
return "-";
|
||||
} else if (this->error == ERROR_IOSUHAX_FAILED) {
|
||||
return "Failed to init IOSUHAX.";
|
||||
} else if (this->error == ERROR_MALLOC_FAILED) {
|
||||
return "Failed to allocate data.";
|
||||
} else if (this->error == ERROR_FILE_OPEN_FAILED) {
|
||||
return "Failed to create file";
|
||||
} else if (this->error == ERROR_NO_DISC_ID) {
|
||||
return "Failed to get the disc id";
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Error: %d", this->error);
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
|
||||
void ApplicationState::setError(eErrorState err) {
|
||||
this->state = STATE_ERROR;
|
||||
this->error = err;
|
||||
//OSEnableHomeButtonMenu(true);
|
||||
}
|
||||
|
||||
void ApplicationState::printFooter() {
|
||||
ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_TV, 0, 27, "By Maschell");
|
||||
ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_DRC, 0, 17, "By Maschell");
|
||||
}
|
||||
|
||||
void ApplicationState::proccessMenuNavigation(Input *input, int maxOptionValue) {
|
||||
if (input->data.buttons_d & Input::BUTTON_LEFT) {
|
||||
this->selectedOption--;
|
||||
} else if (input->data.buttons_d & Input::BUTTON_RIGHT) {
|
||||
this->selectedOption++;
|
||||
}
|
||||
if (this->selectedOption < 0) {
|
||||
this->selectedOption = maxOptionValue;
|
||||
} else if (this->selectedOption >= maxOptionValue) {
|
||||
this->selectedOption = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ApplicationState::entrySelected(Input *input) {
|
||||
return input->data.buttons_d & Input::BUTTON_A;
|
||||
}
|
||||
|
||||
ApplicationState::~ApplicationState() {
|
||||
this->log.close();
|
||||
if (this->fileHandle->isOpen()) {
|
||||
if (!this->flushWriteCache()) {
|
||||
|
||||
}
|
||||
if (doWUX) {
|
||||
this->writeSectorIndexTable();
|
||||
}
|
||||
this->fileHandle->close();
|
||||
}
|
||||
if (this->emptySector != nullptr) {
|
||||
free(this->emptySector);
|
||||
this->emptySector = nullptr;
|
||||
}
|
||||
if (this->writeBuffer != nullptr) {
|
||||
free(this->writeBuffer);
|
||||
this->writeBuffer = nullptr;
|
||||
}
|
||||
if (this->sectorIndexTable != nullptr) {
|
||||
free(this->sectorIndexTable);
|
||||
this->sectorIndexTable = nullptr;
|
||||
}
|
||||
if (this->sectorBuf != nullptr) {
|
||||
free(this->sectorBuf);
|
||||
this->sectorBuf = nullptr;
|
||||
}
|
||||
if (this->oddFd >= 0) {
|
||||
IOSUHAX_FSA_RawClose(gFSAfd, this->oddFd);
|
||||
this->oddFd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ApplicationState::writeDataToFile(void *buffer, int numberOfSectors) {
|
||||
if (!doWUX) {
|
||||
if (!writeCached(reinterpret_cast<uint32_t>(buffer), numberOfSectors * READ_SECTOR_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
this->currentSector += numberOfSectors;
|
||||
this->readSectors += numberOfSectors;
|
||||
} else {
|
||||
char hashOut[32];
|
||||
for (int i = 0; i < numberOfSectors; i++) {
|
||||
uint32_t addr = ((uint32_t) buffer) + (i * READ_SECTOR_SIZE);
|
||||
calculateHash256(reinterpret_cast<unsigned char *>(addr), READ_SECTOR_SIZE, reinterpret_cast<unsigned char *>(hashOut));
|
||||
char tmp[34];
|
||||
auto *test = (uint32_t *) hashOut;
|
||||
snprintf(tmp, 33, "%08X%08X%08X%08X", test[0], test[1], test[2], test[3]);
|
||||
std::string hash(tmp);
|
||||
|
||||
uint32_t *indexTable = (uint32_t *) this->sectorIndexTable;
|
||||
|
||||
auto it = hashMap.find(hash);
|
||||
if (it != hashMap.end()) {
|
||||
indexTable[this->currentSector] = swap_uint32(this->hashMap[hash]);
|
||||
} else {
|
||||
indexTable[this->currentSector] = swap_uint32(this->writtenSector);
|
||||
hashMap[hash] = this->writtenSector;
|
||||
if (this->fileHandle->isOpen()) {
|
||||
if (!writeCached(addr, READ_SECTOR_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this->writtenSector++;
|
||||
}
|
||||
this->currentSector++;
|
||||
this->readSectors++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ApplicationState::writeCached(uint32_t addr, uint32_t writeSize) {
|
||||
// DEBUG_FUNCTION_LINE("Lest write %d bytes", writeSize);
|
||||
|
||||
if (writeSize == this->writeBufferSize) {
|
||||
if (!this->flushWriteCache()) {
|
||||
return false;
|
||||
}
|
||||
int32_t res = this->fileHandle->write(reinterpret_cast<const uint8_t *>(addr), writeSize);
|
||||
return res >= 0;
|
||||
}
|
||||
|
||||
uint32_t toWrite = writeSize;
|
||||
if (toWrite == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t written = 0;
|
||||
|
||||
do {
|
||||
uint32_t curWrite = toWrite;
|
||||
|
||||
if (this->writeBufferPos + curWrite > this->writeBufferSize) {
|
||||
curWrite = this->writeBufferSize - this->writeBufferPos;
|
||||
}
|
||||
// DEBUG_FUNCTION_LINE("Copy from %08X into %08X, size %08X, %d",(addr + written),((uint32_t) this->writeBuffer) + this->writeBufferPos, curWrite, this->writeBufferPos/READ_SECTOR_SIZE);
|
||||
OSBlockMove((void *) (((uint32_t) this->writeBuffer) + this->writeBufferPos), (void *) (addr + written), curWrite, 1);
|
||||
this->writeBufferPos += curWrite;
|
||||
|
||||
if (this->writeBufferPos == this->writeBufferSize) {
|
||||
if (!flushWriteCache()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
toWrite -= curWrite;
|
||||
written += curWrite;
|
||||
} while (toWrite > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ApplicationState::flushWriteCache() {
|
||||
if (this->writeBufferPos > 0) {
|
||||
int32_t res = this->fileHandle->write(static_cast<const uint8_t *>(this->writeBuffer), this->writeBufferPos);
|
||||
if (res < 0) {
|
||||
return false;
|
||||
}
|
||||
this->writeBufferPos = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApplicationState::clearWriteCache() {
|
||||
this->writeBufferPos = 0;
|
||||
}
|
||||
|
||||
void ApplicationState::writeSectorIndexTable() {
|
||||
if (this->fileHandle->isOpen() && doWUX) {
|
||||
this->fileHandle->seek(this->sectorTableStart, SEEK_SET);
|
||||
this->fileHandle->write((uint8_t *) this->sectorIndexTable, totalSectorCount * 4);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationState::printDumpState(const char *fmt, ...) {
|
||||
WiiUScreen::clearScreen();
|
||||
ApplicationState::printHeader();
|
||||
char *buf = (char *) MEMAllocFromDefaultHeapEx(PRINTF_BUFFER_LENGTH, 4);
|
||||
va_list va;
|
||||
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(va, fmt);
|
||||
vsnprintf(buf, PRINTF_BUFFER_LENGTH, fmt, va);
|
||||
|
||||
WiiUScreen::drawLine(buf);
|
||||
|
||||
MEMFreeToDefaultHeap(buf);
|
||||
va_end(va);
|
||||
ApplicationState::printFooter();
|
||||
WiiUScreen::flipBuffers();
|
||||
}
|
||||
|
||||
void ApplicationState::dumpAppFiles() {
|
||||
uint8_t opt[0x400];
|
||||
IOSUHAX_read_otp(opt, 0x400);
|
||||
uint8_t cKey[0x10];
|
||||
memcpy(cKey, opt + 0xE0, 0x10);
|
||||
|
||||
DEBUG_FUNCTION_LINE("Reading Partitions");
|
||||
|
||||
printDumpState("Reading Partitions...");
|
||||
|
||||
auto discReader = new DiscReaderDiscDrive();
|
||||
if (!discReader->IsReady()) {
|
||||
DEBUG_FUNCTION_LINE("!IsReady");
|
||||
this->setError(ERROR_OPEN_ODD1);
|
||||
delete discReader;
|
||||
return;
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Read DiscHeader");
|
||||
auto *discHeader = new WiiUDiscHeader(discReader, 0);
|
||||
bool forceExit = false;
|
||||
for (auto &partition: discHeader->wiiUContentsInformation->partitions->partitions) {
|
||||
auto gmPartition = dynamic_cast<WiiUGMPartition *>(partition);
|
||||
if (gmPartition != nullptr) {
|
||||
auto *nusTitle = NUSTitle::loadTitleFromGMPartition(gmPartition, discReader, cKey);
|
||||
if (nusTitle == nullptr) {
|
||||
DEBUG_FUNCTION_LINE("nusTitle was null");
|
||||
continue;
|
||||
}
|
||||
auto *dataProvider = nusTitle->dataProcessor->getDataProvider();
|
||||
|
||||
uint64_t partitionSize = 0;
|
||||
uint64_t partitionSizeWritten = 0;
|
||||
for (auto &content: nusTitle->tmd->contentList) {
|
||||
partitionSize += ROUNDUP(content->encryptedFileSize, 16);
|
||||
}
|
||||
|
||||
auto partitionDumpInfo = StringTools::strfmt("Partition: %s\n\tProgress: %.2f MiB / %.2f MiB\n", partition->getVolumeId().c_str(), partitionSizeWritten / 1024.0f / 1024.0f,
|
||||
partitionSize / 1024.0f / 1024.0f);
|
||||
printDumpState("%s", partitionDumpInfo.c_str());
|
||||
|
||||
char buffer[512];
|
||||
snprintf(buffer, 500, "%swudump/%s/%s", target.c_str(), this->discId, gmPartition->getVolumeId().c_str());
|
||||
FSUtils::CreateSubfolder(buffer);
|
||||
|
||||
uint8_t *wBuffer = nullptr;
|
||||
uint32_t wBufferLen = 0;
|
||||
if (dataProvider->getRawTMD(&wBuffer, &wBufferLen)) {
|
||||
std::string fileName = std::string(buffer).append("/").append(WUD_TMD_FILENAME);
|
||||
printDumpState("%s\nSaving %s", partitionDumpInfo.c_str(), WUD_TMD_FILENAME);
|
||||
FSUtils::saveBufferToFile(fileName.c_str(), wBuffer, wBufferLen);
|
||||
free(wBuffer);
|
||||
}
|
||||
|
||||
if (dataProvider->getRawTicket(&wBuffer, &wBufferLen)) {
|
||||
std::string fileName = std::string(buffer).append("/").append(WUD_TICKET_FILENAME);
|
||||
printDumpState("%s\nSaving %s", partitionDumpInfo.c_str(), WUD_TICKET_FILENAME);
|
||||
FSUtils::saveBufferToFile(fileName.c_str(), wBuffer, wBufferLen);
|
||||
free(wBuffer);
|
||||
}
|
||||
if (dataProvider->getRawCert(&wBuffer, &wBufferLen)) {
|
||||
std::string fileName = std::string(buffer).append("/").append(WUD_TICKET_FILENAME);
|
||||
printDumpState("%s\nSaving %s", partitionDumpInfo.c_str(), WUD_CERT_FILENAME);
|
||||
FSUtils::saveBufferToFile(fileName.c_str(), wBuffer, wBufferLen);
|
||||
free(wBuffer);
|
||||
}
|
||||
|
||||
auto contentCount = nusTitle->tmd->contentList.size();
|
||||
auto contentI = 1;
|
||||
|
||||
for (auto &content: nusTitle->tmd->contentList) {
|
||||
char bufApp[32];
|
||||
snprintf(bufApp, 31, "%08X.app", content->ID);
|
||||
std::string appFileName = std::string(buffer) + "/" + bufApp;
|
||||
|
||||
partitionDumpInfo = StringTools::strfmt("Partition: %s\n\tProgress: %.2f MiB / %.2f MiB\n", partition->getVolumeId().c_str(), partitionSizeWritten / 1024.0f / 1024.0f,
|
||||
partitionSize / 1024.0f / 1024.0f);
|
||||
auto contentDumpInfo = StringTools::strfmt("Saving %s (Content %02d/%02d)\n", bufApp, contentI, contentCount);
|
||||
|
||||
printDumpState("%s\n%s", partitionDumpInfo.c_str(), contentDumpInfo.c_str());
|
||||
|
||||
uint32_t bufferSize = READ_NUM_SECTORS * READ_SECTOR_SIZE * 2;
|
||||
|
||||
auto *readBuffer = (uint8_t *) malloc(bufferSize);
|
||||
if (readBuffer == nullptr) {
|
||||
DEBUG_FUNCTION_LINE("Failed to alloc buffer");
|
||||
continue;
|
||||
}
|
||||
|
||||
CFile file(appFileName, CFile::WriteOnly);
|
||||
if (!file.isOpen()) {
|
||||
free(readBuffer);
|
||||
continue;
|
||||
}
|
||||
uint32_t readSoFar = 0;
|
||||
uint64_t curOffset = 0;
|
||||
uint32_t size = ROUNDUP(content->encryptedFileSize, 16);
|
||||
OSTime startTimeApp = OSGetTime();
|
||||
do {
|
||||
if (!WHBProcIsRunning()) {
|
||||
forceExit = true;
|
||||
break;
|
||||
}
|
||||
startTimeApp = OSGetTime();
|
||||
WiiUScreen::clearScreen();
|
||||
|
||||
uint32_t toRead = size - readSoFar;
|
||||
if (toRead > bufferSize) {
|
||||
toRead = bufferSize;
|
||||
}
|
||||
dataProvider->readRawContent(content, readBuffer, curOffset, toRead);
|
||||
if (file.write((const uint8_t *) readBuffer, toRead) != (int32_t) toRead) {
|
||||
DEBUG_FUNCTION_LINE("Failed to write");
|
||||
break;
|
||||
}
|
||||
|
||||
OSTime curTime = OSGetTime();
|
||||
auto curSpeed = (float) toRead / (float) OSTicksToMilliseconds(curTime - startTimeApp);
|
||||
|
||||
readSoFar += toRead;
|
||||
curOffset += toRead;
|
||||
|
||||
partitionSizeWritten += toRead;
|
||||
|
||||
partitionDumpInfo = StringTools::strfmt("Partition: %s\n\tProgress: %.2f MiB / %.2f MiB\n", partition->getVolumeId().c_str(), partitionSizeWritten / 1024.0f / 1024.0f,
|
||||
partitionSize / 1024.0f / 1024.0f);
|
||||
printDumpState("%s\n%s\tProgress: %.2f MiB / %.2f MiB (%0.2f%%)\n\tSpeed: %0.2f MiB/s", partitionDumpInfo.c_str(), contentDumpInfo.c_str(), readSoFar / 1024.0f / 1024.0f,
|
||||
size / 1024.0f / 1024.0f, ((readSoFar * 1.0f) / size) * 100.0f, curSpeed / 1024.0f);
|
||||
} while (readSoFar < size);
|
||||
|
||||
file.close();
|
||||
|
||||
if (forceExit) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t *h3Data = nullptr;
|
||||
uint32_t h3Length = 0;
|
||||
if (dataProvider->getContentH3Hash(content, &h3Data, &h3Length)) {
|
||||
char bufh3[32];
|
||||
snprintf(bufh3, 31, "%08X.h3", content->ID);
|
||||
std::string h3FileName = std::string(buffer) + "/" + bufh3;
|
||||
printDumpState("%s\n%s", partitionDumpInfo.c_str(), contentDumpInfo.c_str());
|
||||
FSUtils::saveBufferToFile(h3FileName.c_str(), h3Data, h3Length);
|
||||
}
|
||||
contentI++;
|
||||
}
|
||||
|
||||
delete nusTitle;
|
||||
|
||||
if (forceExit) {
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete discHeader;
|
||||
delete discReader;
|
||||
}
|
138
source/ApplicationState.h
Normal file
138
source/ApplicationState.h
Normal file
@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <coreinit/time.h>
|
||||
#include "input/Input.h"
|
||||
#include "fs/CFile.hpp"
|
||||
|
||||
#define SECTOR_SIZE 0x8000
|
||||
#define READ_SECTOR_SIZE SECTOR_SIZE
|
||||
#define READ_NUM_SECTORS 128
|
||||
#define WRITE_BUFFER_NUM_SECTORS 128
|
||||
#define WUD_FILE_SIZE 0x5D3A00000L
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned int magic0;
|
||||
unsigned int magic1;
|
||||
unsigned int sectorSize;
|
||||
unsigned long long uncompressedSize;
|
||||
unsigned int flags;
|
||||
} wuxHeader_t;
|
||||
|
||||
#define WUX_MAGIC_0 0x57555830
|
||||
#define WUX_MAGIC_1 swap_uint32(0x1099d02e)
|
||||
|
||||
class ApplicationState {
|
||||
public:
|
||||
|
||||
enum eDumpTargetFormat {
|
||||
DUMP_AS_WUX,
|
||||
DUMP_AS_WUD,
|
||||
DUMP_AS_APP,
|
||||
};
|
||||
|
||||
|
||||
enum eErrorState {
|
||||
ERROR_NONE,
|
||||
ERROR_IOSUHAX_FAILED,
|
||||
ERROR_OPEN_ODD1,
|
||||
ERROR_READ_FIRST_SECTOR,
|
||||
ERROR_FILE_OPEN_FAILED,
|
||||
ERROR_MALLOC_FAILED,
|
||||
ERROR_NO_DISC_ID,
|
||||
ERROR_SECTOR_SIZE,
|
||||
ERROR_MAGIC_NUMBER_WRONG,
|
||||
ERROR_WRITE_FAILED,
|
||||
};
|
||||
|
||||
enum eGameState {
|
||||
STATE_ERROR,
|
||||
STATE_WELCOME_SCREEN,
|
||||
STATE_CHOOSE_TARGET,
|
||||
STATE_OPEN_ODD1,
|
||||
STATE_DUMP_APP_FILES,
|
||||
STATE_DUMP_APP_FILES_DONE,
|
||||
STATE_READ_DISC_INFO,
|
||||
STATE_READ_DISC_INFO_DONE,
|
||||
STATE_DUMP_TICKET,
|
||||
STATE_DUMP_DISC_START,
|
||||
STATE_DUMP_DISC_DONE,
|
||||
STATE_WAIT_USER_ERROR_CONFIRM,
|
||||
STATE_DUMP_DISC,
|
||||
};
|
||||
|
||||
ApplicationState();
|
||||
|
||||
~ApplicationState();
|
||||
|
||||
void setError(eErrorState error);
|
||||
|
||||
void render();
|
||||
|
||||
void update(Input *input);
|
||||
|
||||
std::string ErrorMessage();
|
||||
|
||||
std::string ErrorDescription();
|
||||
|
||||
int selectedOption;
|
||||
|
||||
static void printFooter();
|
||||
|
||||
void proccessMenuNavigation(Input *input, int maxOptionValue);
|
||||
|
||||
static bool entrySelected(Input *input);
|
||||
|
||||
private:
|
||||
static void printHeader();
|
||||
|
||||
CFile log;
|
||||
eGameState state;
|
||||
eDumpTargetFormat dumpFormat;
|
||||
eErrorState error = ERROR_NONE;
|
||||
std::string target = "fs:/vol/external01/";
|
||||
int oddFd = -1;
|
||||
int retryCount = 0;
|
||||
void *sectorBuf = nullptr;
|
||||
int sectorBufSize = READ_NUM_SECTORS * READ_SECTOR_SIZE;
|
||||
char discId[11];
|
||||
uint64_t currentSector = 0;
|
||||
std::vector<uint64_t> skippedSectors;
|
||||
int readResult = 0;
|
||||
|
||||
[[nodiscard]] bool writeDataToFile(void* buffer, int numberOfSection);
|
||||
|
||||
uint64_t totalSectorCount = 0;
|
||||
|
||||
std::map<std::string, int32_t> hashMap;
|
||||
CFile *fileHandle;
|
||||
OSTime startTime;
|
||||
void *writeBuffer = nullptr;
|
||||
uint32_t writeBufferPos = 0;
|
||||
uint32_t writeBufferSize = 0;
|
||||
|
||||
[[nodiscard]] bool writeCached(uint32_t addr, uint32_t writeSize);
|
||||
void clearWriteCache();
|
||||
|
||||
[[nodiscard]] bool flushWriteCache();
|
||||
|
||||
uint32_t readSectors = 0;
|
||||
uint64_t sectorTableStart = 0;
|
||||
void *sectorIndexTable = nullptr;
|
||||
uint64_t sectorTableEnd = 0;
|
||||
|
||||
void writeSectorIndexTable();
|
||||
|
||||
void *emptySector = nullptr;
|
||||
bool doWUX = false;
|
||||
uint32_t writtenSector = 0;
|
||||
bool autoSkip = false;
|
||||
|
||||
void dumpAppFiles();
|
||||
|
||||
static void printDumpState(const char *fmt, ...);
|
||||
};
|
60
source/WUD/DefaultNUSDataProcessor.cpp
Normal file
60
source/WUD/DefaultNUSDataProcessor.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "DefaultNUSDataProcessor.h"
|
||||
|
||||
bool DefaultNUSDataProcessor::readPlainDecryptedContent(Content *pContent, uint8_t **data, uint32_t *length) {
|
||||
if (pContent == nullptr || data == nullptr || length == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((pContent->type & 0x0002) == 0x0002) {
|
||||
DEBUG_FUNCTION_LINE("Hashed content not supported yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
*length = ROUNDUP(pContent->encryptedFileSize, 16);
|
||||
*data = (uint8_t *) malloc(*length);
|
||||
if (*data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *inData = (uint8_t *) malloc(*length);
|
||||
|
||||
if (!dataProvider->readRawContent(pContent, inData, 0, *length)) {
|
||||
free(*data);
|
||||
free(inData);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t IV[16];
|
||||
memset(IV, 0, 16);
|
||||
uint16_t content_index = pContent->index;
|
||||
memcpy(IV, &content_index, 2);
|
||||
|
||||
nusDecryption->decryptData(IV, inData, *data, *length);
|
||||
free(inData);
|
||||
return true;
|
||||
}
|
||||
|
||||
NUSDataProvider *DefaultNUSDataProcessor::getDataProvider() {
|
||||
return dataProvider;
|
||||
}
|
||||
|
||||
DefaultNUSDataProcessor::DefaultNUSDataProcessor(NUSDataProvider *pDataProvider, NUSDecryption *pNUSDecryption) {
|
||||
dataProvider = pDataProvider;
|
||||
nusDecryption = pNUSDecryption;
|
||||
}
|
35
source/WUD/DefaultNUSDataProcessor.h
Normal file
35
source/WUD/DefaultNUSDataProcessor.h
Normal file
@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <utils/utils.h>
|
||||
#include "NUSDataProcessor.h"
|
||||
|
||||
class DefaultNUSDataProcessor : public NUSDataProcessor {
|
||||
public:
|
||||
DefaultNUSDataProcessor(NUSDataProvider *pDataProvider, NUSDecryption *pNUSDecryption);
|
||||
|
||||
~DefaultNUSDataProcessor() override = default;
|
||||
|
||||
bool readPlainDecryptedContent(Content *pContent, uint8_t **data, uint32_t *length) override;
|
||||
|
||||
NUSDataProvider* getDataProvider() override;
|
||||
|
||||
private:
|
||||
NUSDataProvider *dataProvider;
|
||||
NUSDecryption *nusDecryption;
|
||||
};
|
177
source/WUD/DiscReader.cpp
Normal file
177
source/WUD/DiscReader.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include <WUD/content/WiiUDiscContentsHeader.h>
|
||||
#include <ApplicationState.h>
|
||||
#include <utils/logger.h>
|
||||
#include <utils/rijndael.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include "DiscReader.h"
|
||||
|
||||
bool DiscReader::readDecryptedChunk(uint64_t readOffset, uint8_t *out_buffer, uint8_t *key, uint8_t *IV) const {
|
||||
int CHUNK_SIZE = 0x10000;
|
||||
|
||||
uint32_t sectorOffset = readOffset / READ_SECTOR_SIZE;
|
||||
|
||||
auto *encryptedBuffer = (uint8_t *) malloc(CHUNK_SIZE);
|
||||
|
||||
if (encryptedBuffer == nullptr) {
|
||||
DEBUG_FUNCTION_LINE("Failed to alloc buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
if (readEncryptedSector(encryptedBuffer, 2, sectorOffset)) {
|
||||
aes_set_key((uint8_t *) key);
|
||||
aes_decrypt((uint8_t *) IV, (uint8_t *) encryptedBuffer, out_buffer, CHUNK_SIZE);
|
||||
// Update IV
|
||||
memcpy(IV, &encryptedBuffer[CHUNK_SIZE - 16], 16);
|
||||
result = true;
|
||||
}
|
||||
|
||||
free(encryptedBuffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DiscReader::readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint64_t fileOffset, uint32_t size, uint8_t *key, uint8_t *IV, bool useFixedIV) const {
|
||||
uint8_t backupIV[0x10];
|
||||
memset(backupIV, 0, 16);
|
||||
uint8_t *usedIV = backupIV;
|
||||
if (useFixedIV) {
|
||||
usedIV = IV;
|
||||
if (IV == nullptr) {
|
||||
usedIV = backupIV;
|
||||
}
|
||||
}
|
||||
|
||||
int BLOCK_SIZE = 0x10000;
|
||||
|
||||
uint32_t usedSize = size;
|
||||
uint64_t usedFileOffset = fileOffset;
|
||||
auto *buffer = (uint8_t *) malloc(BLOCK_SIZE);
|
||||
if (buffer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t maxCopySize;
|
||||
uint32_t copySize;
|
||||
|
||||
uint64_t readOffset;
|
||||
|
||||
uint32_t totalread = 0;
|
||||
|
||||
bool result = true;
|
||||
|
||||
do {
|
||||
uint64_t totalOffset = (clusterOffset + usedFileOffset);
|
||||
uint64_t blockNumber = (totalOffset / BLOCK_SIZE);
|
||||
uint64_t blockOffset = (totalOffset % BLOCK_SIZE);
|
||||
|
||||
readOffset = (blockNumber * BLOCK_SIZE);
|
||||
if (!useFixedIV) {
|
||||
memset(usedIV, 0, 16);
|
||||
uint64_t ivTemp = usedFileOffset >> 16;
|
||||
memcpy(usedIV + 8, &ivTemp, 8);
|
||||
}
|
||||
|
||||
if (!readDecryptedChunk(readOffset, buffer, key, usedIV)) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
maxCopySize = BLOCK_SIZE - blockOffset;
|
||||
copySize = (usedSize > maxCopySize) ? maxCopySize : usedSize;
|
||||
|
||||
memcpy(out_buffer + totalread, buffer + blockOffset, copySize);
|
||||
|
||||
totalread += copySize;
|
||||
|
||||
// update counters
|
||||
usedSize -= copySize;
|
||||
usedFileOffset += copySize;
|
||||
} while (totalread < size);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DiscReader::readEncryptedAligned(uint8_t *buf, uint64_t offset_in_sector, uint32_t size) {
|
||||
auto full_block_count = size / SECTOR_SIZE;
|
||||
if (full_block_count > 0) {
|
||||
if (!readEncryptedSector(buf, full_block_count, offset_in_sector)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto remainingSize = size - (full_block_count * SECTOR_SIZE);
|
||||
if (remainingSize > 0) {
|
||||
auto newOffset = offset_in_sector + full_block_count;
|
||||
if (!readEncryptedSector(sector_buf, 1, newOffset)) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf + (full_block_count * SECTOR_SIZE), sector_buf, remainingSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DiscReader::readEncrypted(uint8_t *buf, uint64_t offset, uint32_t size) {
|
||||
if (size == 0) {
|
||||
return true;
|
||||
}
|
||||
uint32_t missingFromPrevSector = offset % SECTOR_SIZE;
|
||||
auto curOffset = offset;
|
||||
uint32_t offsetInBuf = 0;
|
||||
uint32_t totalRead = 0;
|
||||
if (missingFromPrevSector > 0) {
|
||||
auto offset_in_sectors = offset / SECTOR_SIZE;
|
||||
if (!readEncryptedSector(sector_buf, 1, offset_in_sectors)) {
|
||||
return false;
|
||||
}
|
||||
uint32_t toCopy = SECTOR_SIZE - missingFromPrevSector;
|
||||
if (toCopy > size) {
|
||||
toCopy = size;
|
||||
}
|
||||
memcpy(buf, sector_buf + missingFromPrevSector, toCopy);
|
||||
totalRead += toCopy;
|
||||
curOffset += missingFromPrevSector;
|
||||
offsetInBuf += missingFromPrevSector;
|
||||
|
||||
}
|
||||
|
||||
if (totalRead >= size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (curOffset % SECTOR_SIZE == 0) {
|
||||
if (!readEncryptedAligned(buf + offsetInBuf, offset / SECTOR_SIZE, size)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
OSFatal("Failed to read encrypted");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DiscReader::DiscReader() {
|
||||
this->sector_buf = (uint8_t *) malloc(READ_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
DiscReader::~DiscReader() {
|
||||
free(this->sector_buf);
|
||||
}
|
42
source/WUD/DiscReader.h
Normal file
42
source/WUD/DiscReader.h
Normal file
@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class DiscReader {
|
||||
public:
|
||||
DiscReader();
|
||||
virtual ~DiscReader();
|
||||
|
||||
virtual bool IsReady() = 0;
|
||||
|
||||
virtual bool readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint64_t offset_in_sector) const = 0;
|
||||
|
||||
bool readEncryptedAligned(uint8_t *buf, uint64_t offset_in_sector, uint32_t size);
|
||||
|
||||
bool readDecryptedChunk(uint64_t readOffset, uint8_t *out_buffer, uint8_t *key, uint8_t *IV) const;
|
||||
|
||||
bool readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint64_t fileOffset, uint32_t size, uint8_t *key, uint8_t *IV, bool useFixedIV) const;
|
||||
|
||||
virtual bool readEncrypted(uint8_t *buf, uint64_t offset, uint32_t size);
|
||||
|
||||
uint8_t discKey[16]{};
|
||||
bool hasDiscKey = false;
|
||||
private:
|
||||
uint8_t *sector_buf;
|
||||
};
|
97
source/WUD/DiscReaderDiscDrive.cpp
Normal file
97
source/WUD/DiscReaderDiscDrive.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <WUD/content/WiiUDiscContentsHeader.h>
|
||||
#include <common/common.h>
|
||||
#include <ApplicationState.h>
|
||||
#include <iosuhax.h>
|
||||
#include <utils/rijndael.h>
|
||||
#include <utils/logger.h>
|
||||
#include "DiscReaderDiscDrive.h"
|
||||
|
||||
|
||||
DiscReaderDiscDrive::DiscReaderDiscDrive() : DiscReader() {
|
||||
auto *sector_buf = (uint8_t *) malloc(READ_SECTOR_SIZE);
|
||||
if (sector_buf == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto ret = IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &device_handle);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto res = IOSUHAX_FSA_RawRead(gFSAfd, sector_buf, READ_SECTOR_SIZE, 1, 3, device_handle);
|
||||
|
||||
if (res >= 0) {
|
||||
if (((uint32_t *) sector_buf)[0] != WiiUDiscContentsHeader::MAGIC) {
|
||||
uint8_t iv[16];
|
||||
memset(iv, 0, 16);
|
||||
|
||||
auto discKeyRes = IOSUHAX_ODM_GetDiscKey(discKey);
|
||||
if (discKeyRes >= 0) {
|
||||
hasDiscKey = true;
|
||||
auto sector_buf_decrypted = (uint8_t *) malloc(READ_SECTOR_SIZE);
|
||||
if (sector_buf_decrypted != nullptr) {
|
||||
aes_set_key((uint8_t *) discKey);
|
||||
aes_decrypt((uint8_t *) iv, (uint8_t *) sector_buf, (uint8_t *) §or_buf_decrypted[0], READ_SECTOR_SIZE);
|
||||
if (((uint32_t *) sector_buf_decrypted)[0] == WiiUDiscContentsHeader::MAGIC) {
|
||||
DEBUG_FUNCTION_LINE("Key was correct");
|
||||
this->init_done = true;
|
||||
}
|
||||
free(sector_buf_decrypted);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->init_done = true;
|
||||
}
|
||||
}
|
||||
free(sector_buf);
|
||||
}
|
||||
|
||||
bool DiscReaderDiscDrive::readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint64_t offset_in_sectors) const {
|
||||
if (IOSUHAX_FSA_RawRead(gFSAfd, buffer, READ_SECTOR_SIZE, block_cnt, offset_in_sectors, device_handle) < 0) {
|
||||
DEBUG_FUNCTION_LINE("Failed to read from Disc");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DiscReaderDiscDrive::IsReady() {
|
||||
return init_done;
|
||||
}
|
||||
|
||||
DiscReaderDiscDrive::~DiscReaderDiscDrive() {
|
||||
if (device_handle != -1) {
|
||||
IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &device_handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool DiscReaderDiscDrive::readEncrypted(uint8_t *buf, uint64_t offset, uint32_t size) {
|
||||
if (size == 0) {
|
||||
return true;
|
||||
}
|
||||
if ((offset & 0x7FFF) != 0 || (size & 0x7FFF) != 0) {
|
||||
return DiscReader::readEncrypted(buf, offset, size);
|
||||
}
|
||||
uint32_t block_cnt = size >> 15;
|
||||
uint32_t offset_in_sectors = offset >> 15;
|
||||
if (IOSUHAX_FSA_RawRead(gFSAfd, buf, 0x8000, block_cnt, offset_in_sectors, device_handle) < 0) {
|
||||
DEBUG_FUNCTION_LINE("Failed to read from Disc");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
34
source/WUD/DiscReaderDiscDrive.h
Normal file
34
source/WUD/DiscReaderDiscDrive.h
Normal file
@ -0,0 +1,34 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "DiscReader.h"
|
||||
|
||||
class DiscReaderDiscDrive : public DiscReader{
|
||||
public:
|
||||
DiscReaderDiscDrive();
|
||||
~DiscReaderDiscDrive() override;
|
||||
bool readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint64_t offset_in_sector) const override;
|
||||
bool IsReady() override;
|
||||
|
||||
bool readEncrypted(uint8_t *buf, uint64_t offset, uint32_t size) override;
|
||||
|
||||
private:
|
||||
bool init_done = false;
|
||||
int32_t device_handle = -1;
|
||||
};
|
16
source/WUD/NUSDataProcessor.h
Normal file
16
source/WUD/NUSDataProcessor.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "NUSDataProvider.h"
|
||||
#include "NUSDecryption.h"
|
||||
|
||||
class NUSDataProcessor {
|
||||
protected:
|
||||
NUSDataProcessor() = default;
|
||||
|
||||
public:
|
||||
virtual ~NUSDataProcessor() = default;
|
||||
|
||||
virtual NUSDataProvider *getDataProvider() = 0;
|
||||
|
||||
virtual bool readPlainDecryptedContent(Content *pContent, uint8_t **data, uint32_t *length) = 0;
|
||||
};
|
41
source/WUD/NUSDataProvider.h
Normal file
41
source/WUD/NUSDataProvider.h
Normal file
@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <WUD/entities/TMD/Content.h>
|
||||
#include <WUD/entities/FST/FST.h>
|
||||
|
||||
class NUSDataProvider {
|
||||
|
||||
public:
|
||||
virtual ~NUSDataProvider() = default;
|
||||
|
||||
virtual bool readRawContent(Content *content, uint8_t *buffer, uint64_t offset, uint32_t size) = 0;
|
||||
|
||||
virtual bool getContentH3Hash(Content *content, uint8_t **data, uint32_t *size) = 0;
|
||||
|
||||
virtual bool getRawTMD(uint8_t **data, uint32_t *size) = 0;
|
||||
|
||||
virtual bool getRawTicket(uint8_t **data, uint32_t *size) = 0;
|
||||
|
||||
virtual bool getRawCert(uint8_t **data, uint32_t *size) = 0;
|
||||
|
||||
virtual void setFST(FST *fst) {
|
||||
|
||||
}
|
||||
};
|
114
source/WUD/NUSDataProviderWUD.cpp
Normal file
114
source/WUD/NUSDataProviderWUD.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "NUSDataProviderWUD.h"
|
||||
|
||||
NUSDataProviderWUD::NUSDataProviderWUD(WiiUGMPartition *pGamePartition, DiscReader *pDiscReader) {
|
||||
gamePartition = pGamePartition;
|
||||
discReader = pDiscReader;
|
||||
}
|
||||
|
||||
NUSDataProviderWUD::~NUSDataProviderWUD() {
|
||||
delete fst;
|
||||
}
|
||||
|
||||
bool NUSDataProviderWUD::readRawContent(Content *content, uint8_t *buffer, uint64_t offset, uint32_t size) {
|
||||
if (buffer == nullptr) {
|
||||
DEBUG_FUNCTION_LINE();
|
||||
return false;
|
||||
}
|
||||
auto offsetInWUD = getOffsetInWUD(content) + offset;
|
||||
return discReader->readEncrypted(buffer, offsetInWUD, size);
|
||||
}
|
||||
|
||||
bool NUSDataProviderWUD::getContentH3Hash(Content *content, uint8_t **data, uint32_t *size) {
|
||||
if (content == nullptr || data == nullptr || size == nullptr) {
|
||||
DEBUG_FUNCTION_LINE();
|
||||
return false;
|
||||
}
|
||||
auto cur = gamePartition->getVolumes().begin()->second->h3HashArrayList[content->index];
|
||||
if (cur == nullptr || cur->size == 0) {
|
||||
DEBUG_FUNCTION_LINE();
|
||||
return false;
|
||||
}
|
||||
*data = (uint8_t *) malloc(cur->size);
|
||||
*size = cur->size;
|
||||
memcpy(*data, cur->data, *size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NUSDataProviderWUD::setFST(FST *pFST) {
|
||||
// We need to set the correct blocksizes
|
||||
auto blockSize = gamePartition->getVolumes().begin()->second->blockSize;
|
||||
for (const auto &e: pFST->sectionEntries->getSections()) {
|
||||
e->address = AddressInVolumeBlocks(blockSize, e->address.value);
|
||||
e->size = SizeInVolumeBlocks(blockSize, e->size.value);
|
||||
}
|
||||
fst = pFST;
|
||||
}
|
||||
|
||||
bool NUSDataProviderWUD::getRawCert(uint8_t **data, uint32_t *size) {
|
||||
if (data == nullptr || size == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*data = (uint8_t *) malloc(gamePartition->certLen);
|
||||
if (*data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*size = gamePartition->certLen;
|
||||
memcpy(*data, gamePartition->rawCert, gamePartition->certLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NUSDataProviderWUD::getRawTicket(uint8_t **data, uint32_t *size) {
|
||||
if (data == nullptr || size == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*data = (uint8_t *) malloc(gamePartition->tikLen);
|
||||
if (*data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*size = gamePartition->tikLen;
|
||||
memcpy(*data, gamePartition->rawTicket, gamePartition->tikLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NUSDataProviderWUD::getRawTMD(uint8_t **data, uint32_t *size) {
|
||||
if (data == nullptr || size == nullptr) {
|
||||
DEBUG_FUNCTION_LINE("input was null");
|
||||
return false;
|
||||
}
|
||||
*data = (uint8_t *) malloc(gamePartition->TMDLen);
|
||||
if (*data == nullptr) {
|
||||
DEBUG_FUNCTION_LINE("Failed to alloc memory");
|
||||
return false;
|
||||
}
|
||||
*size = gamePartition->TMDLen;
|
||||
memcpy(*data, gamePartition->rawTMD, gamePartition->TMDLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t NUSDataProviderWUD::getOffsetInWUD(Content *content) const {
|
||||
if (content->index == 0) { // Index 0 is the FST which is at the beginning of the partition;
|
||||
auto *vh = gamePartition->getVolumes().begin()->second;
|
||||
return gamePartition->getSectionOffsetOnDefaultPartition() + vh->FSTAddress.getAddressInBytes();
|
||||
}
|
||||
auto *info = FSTUtils::getSectionEntryForIndex(fst, content->index);
|
||||
if (info == nullptr) {
|
||||
OSFatal("Failed to get section for Content");
|
||||
}
|
||||
return gamePartition->getSectionOffsetOnDefaultPartition() + info->address.getAddressInBytes();
|
||||
}
|
50
source/WUD/NUSDataProviderWUD.h
Normal file
50
source/WUD/NUSDataProviderWUD.h
Normal file
@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <WUD/content/partitions/WiiUGMPartition.h>
|
||||
#include "NUSDataProvider.h"
|
||||
#include "DiscReader.h"
|
||||
#include <utils/FSTUtils.h>
|
||||
#include <coreinit/debug.h>
|
||||
|
||||
class NUSDataProviderWUD : public NUSDataProvider {
|
||||
|
||||
public:
|
||||
NUSDataProviderWUD(WiiUGMPartition *pGamePartition, DiscReader *pDiscReader);
|
||||
|
||||
~NUSDataProviderWUD() override;
|
||||
|
||||
bool readRawContent(Content *content, uint8_t *buffer, uint64_t offset, uint32_t size) override;
|
||||
|
||||
bool getContentH3Hash(Content *content, uint8_t **data, uint32_t *size) override;
|
||||
|
||||
void setFST(FST *pFST) override;
|
||||
|
||||
bool getRawCert(uint8_t **data, uint32_t *size) override;
|
||||
|
||||
bool getRawTicket(uint8_t **data, uint32_t *size) override;
|
||||
|
||||
bool getRawTMD(uint8_t **data, uint32_t *size) override;
|
||||
|
||||
FST *fst{};
|
||||
WiiUGMPartition *gamePartition;
|
||||
DiscReader *discReader;
|
||||
|
||||
private:
|
||||
uint64_t getOffsetInWUD(Content *content) const;
|
||||
};
|
26
source/WUD/NUSDecryption.cpp
Normal file
26
source/WUD/NUSDecryption.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "NUSDecryption.h"
|
||||
|
||||
void NUSDecryption::decryptData(uint8_t *IV, uint8_t *inData, uint8_t *outData, uint32_t size) const {
|
||||
aes_set_key(ticket->ticketKeyDec);
|
||||
aes_decrypt(IV, inData, outData, size);
|
||||
}
|
||||
|
||||
NUSDecryption::NUSDecryption(Ticket *pTicket) {
|
||||
ticket = pTicket;
|
||||
}
|
28
source/WUD/NUSDecryption.h
Normal file
28
source/WUD/NUSDecryption.h
Normal file
@ -0,0 +1,28 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Ticket.h"
|
||||
|
||||
class NUSDecryption {
|
||||
public:
|
||||
explicit NUSDecryption(Ticket *pTicket);
|
||||
|
||||
void decryptData(uint8_t *IV, uint8_t *inData, uint8_t *outData, uint32_t size) const ;
|
||||
|
||||
Ticket *ticket;
|
||||
};
|
83
source/WUD/NUSTitle.cpp
Normal file
83
source/WUD/NUSTitle.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "NUSTitle.h"
|
||||
|
||||
NUSTitle *NUSTitle::loadTitle(NUSDataProvider *dataProvider, uint8_t *commonKey) {
|
||||
uint8_t *data = nullptr;
|
||||
uint32_t dataLen = 0;
|
||||
if (!dataProvider->getRawTMD(&data, &dataLen)) {
|
||||
DEBUG_FUNCTION_LINE("Failed to read TMD");
|
||||
delete dataProvider;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *tmd = new TitleMetaData(data);
|
||||
free(data);
|
||||
|
||||
if (!dataProvider->getRawTicket(&data, &dataLen)) {
|
||||
DEBUG_FUNCTION_LINE("Failed to read ticket");
|
||||
delete tmd;
|
||||
delete dataProvider;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *ticket = new Ticket(data, commonKey);
|
||||
free(data);
|
||||
auto *decryption = new NUSDecryption(ticket);
|
||||
auto *dpp = new DefaultNUSDataProcessor(dataProvider, decryption);
|
||||
|
||||
// If we have more than one content, the index 0 is the FST.
|
||||
Content *fstContent = tmd->getContentByIndex(0);
|
||||
|
||||
if (!dpp->readPlainDecryptedContent(fstContent, &data, &dataLen)) {
|
||||
DEBUG_FUNCTION_LINE("Failed to read decrypted content");
|
||||
delete dataProvider;
|
||||
delete dpp;
|
||||
delete decryption;
|
||||
delete ticket;
|
||||
delete tmd;
|
||||
return nullptr;
|
||||
}
|
||||
FST *fst = new FST(data, dataLen, 0, VolumeBlockSize(1));
|
||||
|
||||
// The dataprovider may need the FST to calculate the offset of a content
|
||||
// on the partition.
|
||||
dataProvider->setFST(fst);
|
||||
|
||||
return new NUSTitle(tmd, dpp, dataProvider, decryption, ticket, fst);
|
||||
}
|
||||
|
||||
NUSTitle::NUSTitle(TitleMetaData *pTMD, NUSDataProcessor *pProcessor, NUSDataProvider *pDataProvider, NUSDecryption *pDecryption, Ticket *pTicket, FST *pFST) {
|
||||
tmd = pTMD;
|
||||
dataProcessor = pProcessor;
|
||||
ticket = pTicket;
|
||||
fst = pFST;
|
||||
decryption = pDecryption;
|
||||
dataProvider = pDataProvider;
|
||||
}
|
||||
|
||||
NUSTitle::~NUSTitle() {
|
||||
delete dataProvider;
|
||||
delete dataProcessor;
|
||||
delete decryption;
|
||||
delete ticket;
|
||||
delete tmd;
|
||||
}
|
||||
|
||||
NUSTitle *NUSTitle::loadTitleFromGMPartition(WiiUGMPartition *pPartition, DiscReaderDiscDrive *pDrive, uint8_t *commonKey) {
|
||||
return loadTitle(new NUSDataProviderWUD(pPartition, pDrive), commonKey);
|
||||
}
|
48
source/WUD/NUSTitle.h
Normal file
48
source/WUD/NUSTitle.h
Normal file
@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <WUD/NUSDataProvider.h>
|
||||
#include <WUD/entities/TMD/TitleMetaData.h>
|
||||
#include <WUD/content/partitions/WiiUGMPartition.h>
|
||||
#include "Ticket.h"
|
||||
#include "NUSDataProcessor.h"
|
||||
#include "NUSDecryption.h"
|
||||
#include "DefaultNUSDataProcessor.h"
|
||||
#include "DiscReaderDiscDrive.h"
|
||||
#include "NUSDataProviderWUD.h"
|
||||
|
||||
class NUSTitle {
|
||||
|
||||
public:
|
||||
~NUSTitle();
|
||||
|
||||
NUSDataProcessor *dataProcessor;
|
||||
TitleMetaData *tmd;
|
||||
Ticket *ticket;
|
||||
FST *fst;
|
||||
NUSDecryption *decryption;
|
||||
NUSDataProvider *dataProvider;
|
||||
|
||||
static NUSTitle *loadTitleFromGMPartition(WiiUGMPartition *pPartition, DiscReaderDiscDrive *pDrive, uint8_t commonKey[16]);
|
||||
|
||||
private:
|
||||
static NUSTitle *loadTitle(NUSDataProvider *dataProvider, uint8_t commonKey[16]);
|
||||
|
||||
NUSTitle(TitleMetaData *pTMD, NUSDataProcessor *pProcessor, NUSDataProvider *pDataProvider, NUSDecryption *pDecryption, Ticket *pTicket, FST *pFST);
|
||||
|
||||
};
|
33
source/WUD/Ticket.cpp
Normal file
33
source/WUD/Ticket.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "Ticket.h"
|
||||
|
||||
Ticket::Ticket(uint8_t *data, uint8_t *commonKey) {
|
||||
uint8_t *tikKeyEnc = data + 0x1BF;
|
||||
uint8_t *title_id = data + 0x1DC;
|
||||
uint8_t IV[0x10];
|
||||
|
||||
int k;
|
||||
for (k = 0; k < 8; k++) {
|
||||
IV[k] = title_id[k];
|
||||
IV[k + 8] = 0x00;
|
||||
}
|
||||
|
||||
aes_set_key(commonKey);
|
||||
aes_decrypt(IV, tikKeyEnc, ticketKeyDec, 16);
|
||||
memcpy(ticketKeyEnc, tikKeyEnc, 16);
|
||||
}
|
29
source/WUD/Ticket.h
Normal file
29
source/WUD/Ticket.h
Normal file
@ -0,0 +1,29 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <utils/rijndael.h>
|
||||
#include <cstring>
|
||||
|
||||
class Ticket {
|
||||
public:
|
||||
Ticket(uint8_t *data, uint8_t commonKey[16]);
|
||||
|
||||
uint8_t ticketKeyEnc[16]{};
|
||||
uint8_t ticketKeyDec[16]{};
|
||||
};
|
37
source/WUD/content/WiiUContentsInformation.cpp
Normal file
37
source/WUD/content/WiiUContentsInformation.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <coreinit/debug.h>
|
||||
#include "WiiUContentsInformation.h"
|
||||
|
||||
uint32_t WiiUContentsInformation::LENGTH = 32768;
|
||||
WiiUContentsInformation::WiiUContentsInformation(DiscReader *reader, uint32_t offset) {
|
||||
uint32_t curOffset = offset;
|
||||
discContentHeader = new WiiUDiscContentsHeader(reader, curOffset);
|
||||
curOffset += WiiUDiscContentsHeader::LENGTH;
|
||||
|
||||
partitions = new WiiUPartitions(reader, curOffset, discContentHeader->numberOfPartition, discContentHeader->blockSize);
|
||||
curOffset += WiiUPartitions::LENGTH;
|
||||
|
||||
if (curOffset - offset != LENGTH) {
|
||||
OSFatal("Length mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
WiiUContentsInformation::~WiiUContentsInformation() {
|
||||
delete partitions;
|
||||
delete discContentHeader;
|
||||
}
|
35
source/WUD/content/WiiUContentsInformation.h
Normal file
35
source/WUD/content/WiiUContentsInformation.h
Normal file
@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "../DiscReader.h"
|
||||
#include "WiiUDiscContentsHeader.h"
|
||||
#include "partitions/WiiUPartitions.h"
|
||||
|
||||
class WiiUContentsInformation {
|
||||
|
||||
public:
|
||||
WiiUContentsInformation(DiscReader *reader, uint32_t offset);
|
||||
|
||||
~WiiUContentsInformation();
|
||||
|
||||
WiiUDiscContentsHeader *discContentHeader;
|
||||
|
||||
WiiUPartitions *partitions;
|
||||
|
||||
static uint32_t LENGTH;
|
||||
};
|
44
source/WUD/content/WiiUDiscContentsHeader.cpp
Normal file
44
source/WUD/content/WiiUDiscContentsHeader.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <utils/blocksize/DiscBlockSize.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <cstdlib>
|
||||
#include "WiiUDiscContentsHeader.h"
|
||||
|
||||
uint32_t WiiUDiscContentsHeader::LENGTH = 2048;
|
||||
uint32_t WiiUDiscContentsHeader::MAGIC = 0xCCA6E67B;
|
||||
|
||||
WiiUDiscContentsHeader::WiiUDiscContentsHeader(DiscReader *reader, uint32_t offset) {
|
||||
auto *buffer = (uint8_t *) malloc(LENGTH);
|
||||
if (!reader->hasDiscKey) {
|
||||
if(!reader->readEncrypted(buffer, offset, LENGTH)){
|
||||
OSFatal("WiiUDiscContentsHeader: Failed to read encrypted");
|
||||
}
|
||||
} else {
|
||||
if(!reader->readDecrypted(buffer, offset, 0, LENGTH, reader->discKey, nullptr, true)){
|
||||
OSFatal("WiiUDiscContentsHeader: Failed to read decrypted");
|
||||
}
|
||||
}
|
||||
|
||||
if (((uint32_t *) buffer)[0] != MAGIC) {
|
||||
OSFatal("WiiUDiscContentsHeader MAGIC mismatch.");
|
||||
}
|
||||
blockSize = DiscBlockSize(((uint32_t *) buffer)[1]);
|
||||
memcpy(tocHash, &buffer[8], 20);
|
||||
numberOfPartition = ((uint32_t *) buffer)[7];
|
||||
free(buffer);
|
||||
}
|
36
source/WUD/content/WiiUDiscContentsHeader.h
Normal file
36
source/WUD/content/WiiUDiscContentsHeader.h
Normal file
@ -0,0 +1,36 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <WUD/DiscReader.h>
|
||||
#include <utils/blocksize/DiscBlockSize.h>
|
||||
|
||||
class WiiUDiscContentsHeader {
|
||||
|
||||
public:
|
||||
WiiUDiscContentsHeader(DiscReader *reader, uint32_t offset);
|
||||
|
||||
~WiiUDiscContentsHeader() = default;
|
||||
|
||||
DiscBlockSize blockSize{};
|
||||
uint8_t tocHash[20]{};
|
||||
uint32_t numberOfPartition;
|
||||
|
||||
static uint32_t LENGTH;
|
||||
|
||||
static uint32_t MAGIC;
|
||||
};
|
43
source/WUD/content/partitions/WiiUDataPartition.cpp
Normal file
43
source/WUD/content/partitions/WiiUDataPartition.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "WiiUDataPartition.h"
|
||||
|
||||
WiiUDataPartition::~WiiUDataPartition() {
|
||||
delete basePartition;
|
||||
delete fst;
|
||||
}
|
||||
|
||||
WiiUDataPartition::WiiUDataPartition(WiiUPartition *partition, FST *pFST) {
|
||||
basePartition = partition;
|
||||
fst = pFST;
|
||||
}
|
||||
|
||||
std::string WiiUDataPartition::getVolumeId() const &{
|
||||
return basePartition->getVolumeId();
|
||||
}
|
||||
|
||||
std::map<AddressInDiscBlocks, VolumeHeader *> WiiUDataPartition::getVolumes() const &{
|
||||
return basePartition->getVolumes();
|
||||
}
|
||||
|
||||
uint16_t WiiUDataPartition::getFileSystemDescriptor() const {
|
||||
return basePartition->getFileSystemDescriptor();
|
||||
}
|
||||
|
||||
uint64_t WiiUDataPartition::getSectionOffsetOnDefaultPartition() {
|
||||
return basePartition->getSectionOffsetOnDefaultPartition();
|
||||
}
|
46
source/WUD/content/partitions/WiiUDataPartition.h
Normal file
46
source/WUD/content/partitions/WiiUDataPartition.h
Normal file
@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <WUD/entities/FST/FST.h>
|
||||
#include <utils/blocksize/AddressInDiscBlocks.h>
|
||||
#include "WiiUPartition.h"
|
||||
|
||||
class WiiUDataPartition : public WiiUPartition {
|
||||
|
||||
public:
|
||||
WiiUDataPartition(WiiUPartition *partition, FST *pFST);
|
||||
|
||||
~WiiUDataPartition() override;
|
||||
|
||||
[[nodiscard]] std::string getVolumeId() const & override;
|
||||
|
||||
[[nodiscard]] std::map<AddressInDiscBlocks, VolumeHeader *> getVolumes() const & override;
|
||||
|
||||
[[nodiscard]] uint16_t getFileSystemDescriptor() const override;
|
||||
|
||||
|
||||
[[nodiscard]] uint64_t getSectionOffsetOnDefaultPartition() override;
|
||||
|
||||
FST *fst{};
|
||||
|
||||
private:
|
||||
WiiUPartition *basePartition;
|
||||
};
|
||||
|
50
source/WUD/content/partitions/WiiUGMPartition.cpp
Normal file
50
source/WUD/content/partitions/WiiUGMPartition.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "WiiUGMPartition.h"
|
||||
|
||||
WiiUGMPartition::~WiiUGMPartition() {
|
||||
free(rawCert);
|
||||
free(rawTMD);
|
||||
free(rawTicket);
|
||||
delete basePartition;
|
||||
}
|
||||
|
||||
WiiUGMPartition::WiiUGMPartition(WiiUPartition *partition, uint8_t *pRawTIK, uint32_t pTikLen, uint8_t *pRawTMD, uint32_t pTMDLen, uint8_t *pRawCert, uint32_t pCertLen) {
|
||||
basePartition = partition;
|
||||
rawCert = pRawCert;
|
||||
rawTMD = pRawTMD;
|
||||
rawTicket = pRawTIK;
|
||||
tikLen = pTikLen;
|
||||
TMDLen = pTMDLen;
|
||||
certLen = pCertLen;
|
||||
}
|
||||
|
||||
std::string WiiUGMPartition::getVolumeId() const &{
|
||||
return basePartition->getVolumeId();
|
||||
}
|
||||
|
||||
std::map<AddressInDiscBlocks, VolumeHeader *> WiiUGMPartition::getVolumes() const &{
|
||||
return basePartition->getVolumes();
|
||||
}
|
||||
|
||||
uint16_t WiiUGMPartition::getFileSystemDescriptor() const {
|
||||
return basePartition->getFileSystemDescriptor();
|
||||
}
|
||||
|
||||
uint64_t WiiUGMPartition::getSectionOffsetOnDefaultPartition() {
|
||||
return basePartition->getSectionOffsetOnDefaultPartition();
|
||||
}
|
47
source/WUD/content/partitions/WiiUGMPartition.h
Normal file
47
source/WUD/content/partitions/WiiUGMPartition.h
Normal file
@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include "WiiUPartition.h"
|
||||
|
||||
class WiiUGMPartition : public WiiUPartition {
|
||||
public:
|
||||
WiiUGMPartition(WiiUPartition *partition, uint8_t *pRawTIK, uint32_t pTikLen, uint8_t *pRawTMD, uint32_t pTMDLen, uint8_t *pRawCert, uint32_t pCertLen);
|
||||
|
||||
~WiiUGMPartition() override;
|
||||
|
||||
[[nodiscard]] std::string getVolumeId() const & override;
|
||||
|
||||
[[nodiscard]] std::map<AddressInDiscBlocks, VolumeHeader *> getVolumes() const & override;
|
||||
|
||||
[[nodiscard]] uint16_t getFileSystemDescriptor() const override;
|
||||
|
||||
[[nodiscard]] uint64_t getSectionOffsetOnDefaultPartition() override;
|
||||
|
||||
uint8_t *rawTicket;
|
||||
uint8_t *rawTMD;
|
||||
uint8_t *rawCert;
|
||||
uint32_t tikLen;
|
||||
uint32_t TMDLen;
|
||||
uint32_t certLen;
|
||||
|
||||
private:
|
||||
WiiUPartition *basePartition;
|
||||
};
|
||||
|
79
source/WUD/content/partitions/WiiUPartition.cpp
Normal file
79
source/WUD/content/partitions/WiiUPartition.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <coreinit/debug.h>
|
||||
#include "WiiUPartition.h"
|
||||
|
||||
uint32_t WiiUPartition::LENGTH = 128;
|
||||
|
||||
WiiUPartition::WiiUPartition() = default;
|
||||
|
||||
WiiUPartition::~WiiUPartition() {
|
||||
for (auto const&[key, val]: volumes) {
|
||||
delete val;
|
||||
}
|
||||
volumes.clear();
|
||||
}
|
||||
|
||||
WiiUPartition::WiiUPartition(DiscReader *reader, uint32_t offset, const DiscBlockSize &blockSize) {
|
||||
auto buffer = (uint8_t *) malloc(LENGTH);
|
||||
if (buffer == nullptr) {
|
||||
OSFatal("WiiUPartition: alloc buffer failed");
|
||||
}
|
||||
if (!reader->hasDiscKey) {
|
||||
if (!reader->readEncrypted(buffer, offset, LENGTH)) {
|
||||
OSFatal("WiiUPartition: Failed to read encrypted");
|
||||
}
|
||||
} else {
|
||||
auto bufferBigger = (uint8_t *) malloc(LENGTH + 0x10);
|
||||
if (bufferBigger == nullptr) {
|
||||
OSFatal("WiiUPartition: alloc bufferBigger failed");
|
||||
}
|
||||
if (!reader->readDecrypted(bufferBigger, offset - 0x10, 0, LENGTH + 0x10, reader->discKey, nullptr, true)) {
|
||||
OSFatal("WiiUPartition: Failed to read encrypted");
|
||||
}
|
||||
|
||||
memcpy(buffer, bufferBigger + 0x10, LENGTH);
|
||||
|
||||
free(bufferBigger);
|
||||
}
|
||||
|
||||
char name[32];
|
||||
memset(name, 0, sizeof(name));
|
||||
memcpy(name, buffer, 31);
|
||||
volumeId = name;
|
||||
uint8_t num = buffer[31];
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
auto address = *((uint32_t *) &buffer[32 + (i * 4)]);
|
||||
AddressInDiscBlocks discLbaAddress = AddressInDiscBlocks(blockSize, address);
|
||||
auto vh = new VolumeHeader(reader, discLbaAddress.getAddressInBytes());
|
||||
volumes[discLbaAddress] = vh;
|
||||
}
|
||||
|
||||
fileSystemDescriptor = ((uint16_t *) &buffer[64])[0];
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
uint64_t WiiUPartition::getSectionOffsetOnDefaultPartition() {
|
||||
if (volumes.size() != 1) {
|
||||
OSFatal("We have more or less than 1 volume header.");
|
||||
}
|
||||
return volumes.begin()->first.getAddressInBytes();
|
||||
}
|
||||
|
||||
|
51
source/WUD/content/partitions/WiiUPartition.h
Normal file
51
source/WUD/content/partitions/WiiUPartition.h
Normal file
@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <utils/blocksize/DiscBlockSize.h>
|
||||
#include <utils/blocksize/AddressInDiscBlocks.h>
|
||||
#include "volumes/VolumeHeader.h"
|
||||
|
||||
class WiiUPartition {
|
||||
|
||||
public:
|
||||
WiiUPartition();
|
||||
explicit WiiUPartition(DiscReader *reader, uint32_t offset, const DiscBlockSize &blockSize);
|
||||
|
||||
virtual uint64_t getSectionOffsetOnDefaultPartition();
|
||||
|
||||
virtual ~WiiUPartition();
|
||||
|
||||
[[nodiscard]] virtual std::string getVolumeId() const &{
|
||||
return volumeId;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual std::map<AddressInDiscBlocks, VolumeHeader *> getVolumes() const&{
|
||||
return volumes;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual uint16_t getFileSystemDescriptor() const{
|
||||
return fileSystemDescriptor;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string volumeId;
|
||||
std::map<AddressInDiscBlocks, VolumeHeader *> volumes;
|
||||
uint16_t fileSystemDescriptor{};
|
||||
static uint32_t LENGTH;
|
||||
};
|
181
source/WUD/content/partitions/WiiUPartitions.cpp
Normal file
181
source/WUD/content/partitions/WiiUPartitions.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <utils/FSTUtils.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include "WiiUPartitions.h"
|
||||
#include "WiiUGMPartition.h"
|
||||
#include "WiiUDataPartition.h"
|
||||
|
||||
uint32_t WiiUPartitions::LENGTH = 30720;
|
||||
|
||||
WiiUPartitions::WiiUPartitions(DiscReader *reader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize &blockSize) {
|
||||
std::vector<WiiUPartition *> tmp;
|
||||
tmp.reserve(numberOfPartitions);
|
||||
for (uint32_t i = 0; i < numberOfPartitions; i++) {
|
||||
tmp.push_back(new WiiUPartition(reader, offset + (i * 128), blockSize));
|
||||
}
|
||||
WiiUPartition *SIPartition = nullptr;
|
||||
for (auto &partition: tmp) {
|
||||
if (partition->getVolumeId().starts_with("SI")) {
|
||||
SIPartition = partition;
|
||||
}
|
||||
}
|
||||
|
||||
if (SIPartition != nullptr) {
|
||||
for (auto const&[key, val]: SIPartition->getVolumes()) {
|
||||
auto volumeAddress = key;
|
||||
auto volumeAddressInBytes = volumeAddress.getAddressInBytes();
|
||||
auto volumeHeader = val;
|
||||
|
||||
auto fst = (uint8_t *) malloc(volumeHeader->FSTSize);
|
||||
if (fst == nullptr) {
|
||||
OSFatal("WiiUPartitions: Failed to alloc FST buffer");
|
||||
}
|
||||
|
||||
if (!reader->hasDiscKey) {
|
||||
if (!reader->readEncrypted(fst, volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(),
|
||||
volumeHeader->FSTSize)) {
|
||||
OSFatal("WiiUPartitions: Failed to read encrypted");
|
||||
}
|
||||
} else {
|
||||
if (!reader->readDecrypted(fst, volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), 0, volumeHeader->FSTSize,
|
||||
reader->discKey, nullptr, true)) {
|
||||
OSFatal("WiiUPartitions: Failed to read decrypted");
|
||||
}
|
||||
}
|
||||
|
||||
FST *siFST = new FST(fst, volumeHeader->FSTSize, 0, volumeHeader->blockSize);
|
||||
free(fst);
|
||||
|
||||
for (auto &child: siFST->getRootEntry()->getDirChildren()) {
|
||||
uint8_t *tikRaw = nullptr;
|
||||
uint32_t tikRawLen = 0;
|
||||
std::string tikFilePath = std::string(child->getFullPath() + '/' + WUD_TICKET_FILENAME);
|
||||
if (!getFSTEntryAsByte(&tikRaw, &tikRawLen, tikFilePath, siFST, volumeAddress, reader)) {
|
||||
OSFatal("tikRaw");
|
||||
}
|
||||
|
||||
uint8_t *tmdRaw = nullptr;
|
||||
uint32_t tmdRawLen = 0;
|
||||
std::string tmdFilePath = std::string(child->getFullPath() + '/' + WUD_TMD_FILENAME);
|
||||
if (!getFSTEntryAsByte(&tmdRaw, &tmdRawLen, tmdFilePath, siFST, volumeAddress, reader)) {
|
||||
OSFatal("tmdRaw");
|
||||
}
|
||||
|
||||
uint8_t *certRaw = nullptr;
|
||||
uint32_t certRawLen = 0;
|
||||
std::string certFilePath = std::string(child->getFullPath() + '/' + WUD_CERT_FILENAME);
|
||||
if (!getFSTEntryAsByte(&certRaw, &certRawLen, certFilePath, siFST, volumeAddress, reader)) {
|
||||
OSFatal("certRaw");
|
||||
}
|
||||
|
||||
char partitionNameRaw[0x12];
|
||||
memset(partitionNameRaw, 0, 0x12);
|
||||
snprintf(partitionNameRaw, 0x11, "%016llX", *((uint64_t *) &tikRaw[0x1DC]));
|
||||
|
||||
std::string partitionName = std::string("GM") + partitionNameRaw;
|
||||
|
||||
WiiUPartition *curPartition = nullptr;
|
||||
for (auto &partition: tmp) {
|
||||
if (partition->getVolumeId().starts_with(partitionName)) {
|
||||
curPartition = partition;
|
||||
}
|
||||
}
|
||||
|
||||
if (curPartition == nullptr) {
|
||||
OSFatal("Failed to get partition");
|
||||
}
|
||||
|
||||
auto *gmPartition = new WiiUGMPartition(curPartition, tikRaw, tikRawLen, tmdRaw, tmdRawLen, certRaw, certRawLen);
|
||||
partitions.push_back(gmPartition);
|
||||
}
|
||||
delete siFST;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (auto &partition: tmp) {
|
||||
if (partition->getVolumeId().starts_with("GM")) {
|
||||
continue;
|
||||
}
|
||||
if (partition->getVolumes().size() != 1) {
|
||||
OSFatal("We can't handle more or less than one partion address yet.");
|
||||
}
|
||||
auto volumeAddress = partition->getVolumes().begin()->first;
|
||||
auto vh = partition->getVolumes().begin()->second;
|
||||
auto *rawFST = (uint8_t *) malloc(vh->FSTSize);
|
||||
if (rawFST == nullptr) {
|
||||
OSFatal("Failed to alloc rawFST");
|
||||
}
|
||||
if (!reader->hasDiscKey) {
|
||||
if (!reader->readEncrypted(rawFST, volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), vh->FSTSize)) {
|
||||
OSFatal("WiiUPartition: Failed to read encrypted");
|
||||
}
|
||||
} else {
|
||||
if (!reader->readDecrypted(rawFST, volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), 0, vh->FSTSize,
|
||||
reader->discKey, nullptr, true)) {
|
||||
OSFatal("WiiUPartition: Failed to read encrypted");
|
||||
}
|
||||
}
|
||||
|
||||
FST *fst = new FST(rawFST, vh->FSTSize, 0, vh->blockSize);
|
||||
free(rawFST);
|
||||
partitions.push_back(new WiiUDataPartition(partition, fst));
|
||||
}
|
||||
}
|
||||
|
||||
WiiUPartitions::~WiiUPartitions() {
|
||||
for (auto &partition: partitions) {
|
||||
delete partition;
|
||||
}
|
||||
}
|
||||
|
||||
bool WiiUPartitions::getFSTEntryAsByte(uint8_t **buffer_out, uint32_t *outSize, std::string &filePath, FST *fst, const AddressInDiscBlocks &volumeAddress, DiscReader *discReader) {
|
||||
NodeEntry *entry = FSTUtils::getFSTEntryByFullPath(fst->nodeEntries->rootEntry, filePath);
|
||||
|
||||
auto asFileEntry = dynamic_cast<FileEntry *>(entry);
|
||||
if (asFileEntry == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SectionEntry *info = asFileEntry->getSectionEntry();
|
||||
if (info == nullptr) {
|
||||
OSFatal("WiiUPartitions::getFSTEntryAsByte, section info was null");
|
||||
}
|
||||
|
||||
uint64_t sectionOffsetOnDisc = volumeAddress.getAddressInBytes() + info->address.getAddressInBytes();
|
||||
|
||||
auto *buffer = (uint8_t *) malloc(asFileEntry->getSize());
|
||||
if (buffer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*buffer_out = buffer;
|
||||
*outSize = asFileEntry->getSize();
|
||||
|
||||
if (!discReader->hasDiscKey) {
|
||||
return discReader->readEncrypted(buffer, sectionOffsetOnDisc + asFileEntry->getOffset(), asFileEntry->getSize());
|
||||
}
|
||||
|
||||
// Calculating the IV
|
||||
uint8_t IV[16];
|
||||
memset(IV, 0, 16);
|
||||
uint64_t ivTemp = asFileEntry->getOffset() >> 16;
|
||||
memcpy(IV + 8, &ivTemp, 8);
|
||||
|
||||
return discReader->readDecrypted(buffer, sectionOffsetOnDisc, asFileEntry->getOffset(), asFileEntry->getSize(), discReader->discKey, IV, false);
|
||||
}
|
||||
|
42
source/WUD/content/partitions/WiiUPartitions.h
Normal file
42
source/WUD/content/partitions/WiiUPartitions.h
Normal file
@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <utils/blocksize/DiscBlockSize.h>
|
||||
#include <utils/blocksize/AddressInDiscBlocks.h>
|
||||
#include <WUD/entities/FST/FST.h>
|
||||
#include <WUD/DiscReader.h>
|
||||
#include "WiiUPartition.h"
|
||||
|
||||
#define WUD_TMD_FILENAME "title.tmd"
|
||||
#define WUD_TICKET_FILENAME "title.tik"
|
||||
#define WUD_CERT_FILENAME "title.cert"
|
||||
|
||||
class WiiUPartitions {
|
||||
|
||||
public:
|
||||
static bool getFSTEntryAsByte(uint8_t **buffer_out, uint32_t *outSize, std::string &filePath, FST *fst, const AddressInDiscBlocks& volumeAddress, DiscReader* discReader);
|
||||
|
||||
WiiUPartitions(DiscReader *reader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize& blockSize);
|
||||
|
||||
~WiiUPartitions();
|
||||
|
||||
std::vector<WiiUPartition *> partitions;
|
||||
static uint32_t LENGTH;
|
||||
|
||||
};
|
37
source/WUD/content/partitions/volumes/H3HashArray.cpp
Normal file
37
source/WUD/content/partitions/volumes/H3HashArray.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "H3HashArray.h"
|
||||
#include <cstring>
|
||||
#include <coreinit/debug.h>
|
||||
|
||||
H3HashArray::H3HashArray(uint8_t *pData, uint32_t pSize) {
|
||||
size = pSize;
|
||||
data = nullptr;
|
||||
if (pSize > 0) {
|
||||
data = (uint8_t *) malloc(pSize);
|
||||
if (data == nullptr) {
|
||||
OSFatal("H3HashArray: Failed to alloc");
|
||||
}
|
||||
memcpy(data, pData, pSize);
|
||||
}
|
||||
}
|
||||
|
||||
H3HashArray::~H3HashArray() {
|
||||
if (data) {
|
||||
free(data);
|
||||
}
|
||||
}
|
31
source/WUD/content/partitions/volumes/H3HashArray.h
Normal file
31
source/WUD/content/partitions/volumes/H3HashArray.h
Normal file
@ -0,0 +1,31 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <malloc.h>
|
||||
|
||||
class H3HashArray {
|
||||
|
||||
public:
|
||||
H3HashArray(uint8_t *pData, uint32_t pSize);
|
||||
|
||||
~H3HashArray();
|
||||
|
||||
uint8_t *data = nullptr;
|
||||
uint8_t size;
|
||||
};
|
94
source/WUD/content/partitions/volumes/VolumeHeader.cpp
Normal file
94
source/WUD/content/partitions/volumes/VolumeHeader.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include "VolumeHeader.h"
|
||||
#include <utils/utils.h>
|
||||
#include <coreinit/debug.h>
|
||||
|
||||
uint32_t VolumeHeader::MAGIC = 0xCC93A4F5;
|
||||
|
||||
VolumeHeader::VolumeHeader(DiscReader *reader, uint64_t offset) {
|
||||
auto buffer = (uint8_t *) malloc(64);
|
||||
if (buffer == nullptr) {
|
||||
OSFatal("VolumeHeader: failed to alloc buffer");
|
||||
}
|
||||
|
||||
if (!reader->readEncrypted(buffer, offset, 64)) {
|
||||
OSFatal("VolumeHeader: failed to read");
|
||||
}
|
||||
|
||||
auto *bufferUint = (uint32_t *) buffer;
|
||||
|
||||
if (bufferUint[0] != MAGIC) {
|
||||
OSFatal("VolumeHeader MAGIC mismatch.");
|
||||
}
|
||||
|
||||
blockSize = VolumeBlockSize(bufferUint[1]);
|
||||
volumeSize = SizeInVolumeBlocks(blockSize, bufferUint[2]);
|
||||
h3HashArrayListSize = bufferUint[3];
|
||||
numberOfH3HashArray = bufferUint[4];
|
||||
FSTSize = bufferUint[5];
|
||||
FSTAddress = AddressInVolumeBlocks(blockSize, bufferUint[6]);
|
||||
FSTHashMode = buffer[36];
|
||||
encryptType = buffer[37];
|
||||
majorVersion = buffer[38];
|
||||
minorVersion = buffer[39];
|
||||
expiringMajorVersion = buffer[40];
|
||||
|
||||
free(buffer);
|
||||
|
||||
auto bufferH3 = (uint8_t *) malloc(ROUNDUP(h3HashArrayListSize,16));
|
||||
if (bufferH3 == nullptr) {
|
||||
OSFatal("VolumeHeader: failed to alloc h3 buffer");
|
||||
}
|
||||
|
||||
if (!reader->readEncrypted(bufferH3,offset + 64, ROUNDUP(h3HashArrayListSize,16))) {
|
||||
OSFatal("VolumeHeader: failed to read h3");
|
||||
}
|
||||
|
||||
h3HashArrayList = getH3HashArray(bufferH3, numberOfH3HashArray, h3HashArrayListSize);
|
||||
|
||||
free(bufferH3);
|
||||
}
|
||||
|
||||
std::vector<H3HashArray *> VolumeHeader::getH3HashArray(uint8_t *h3Data, uint32_t pNumberOfH3HashArray, uint32_t pH3HashArrayListSize) {
|
||||
std::vector<H3HashArray *> arrayList;
|
||||
if(pNumberOfH3HashArray == 0){
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
for (uint32_t i = 1; i < pNumberOfH3HashArray; i++) {
|
||||
auto *offsetPtr = (uint32_t *) &h3Data[i * 4];
|
||||
uint32_t curOffset = offsetPtr[0];
|
||||
uint32_t curEnd = pH3HashArrayListSize;
|
||||
if (i < pNumberOfH3HashArray - 1) {
|
||||
// If it's not the last element, the end of our .h3 is the start of the next .h3
|
||||
curEnd = offsetPtr[1];
|
||||
}
|
||||
|
||||
arrayList.push_back(new H3HashArray(h3Data + curOffset, curEnd - curOffset));
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
VolumeHeader::~VolumeHeader() {
|
||||
for (auto &h3: h3HashArrayList) {
|
||||
delete h3;
|
||||
}
|
||||
}
|
||||
|
50
source/WUD/content/partitions/volumes/VolumeHeader.h
Normal file
50
source/WUD/content/partitions/volumes/VolumeHeader.h
Normal file
@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <WUD/DiscReader.h>
|
||||
#include <utils/blocksize/VolumeBlockSize.h>
|
||||
#include <utils/blocksize/AddressInVolumeBlocks.h>
|
||||
#include <utils/blocksize/SizeInVolumeBlocks.h>
|
||||
#include "H3HashArray.h"
|
||||
|
||||
class VolumeHeader {
|
||||
|
||||
public:
|
||||
static std::vector<H3HashArray *> getH3HashArray(uint8_t *h3Data, uint32_t numberOfH3HashArray, uint32_t h3HashArrayListSize);
|
||||
|
||||
VolumeHeader(DiscReader *reader, uint64_t offset);
|
||||
|
||||
~VolumeHeader();
|
||||
|
||||
static uint32_t MAGIC;
|
||||
VolumeBlockSize blockSize;
|
||||
SizeInVolumeBlocks volumeSize;
|
||||
uint32_t FSTSize;
|
||||
AddressInVolumeBlocks FSTAddress;
|
||||
uint8_t FSTHashMode;
|
||||
uint8_t encryptType;
|
||||
uint8_t majorVersion;
|
||||
uint8_t minorVersion;
|
||||
uint8_t expiringMajorVersion;
|
||||
std::vector<H3HashArray *> h3HashArrayList;
|
||||
|
||||
uint32_t h3HashArrayListSize;
|
||||
uint32_t numberOfH3HashArray;
|
||||
};
|
47
source/WUD/entities/FST/FST.cpp
Normal file
47
source/WUD/entities/FST/FST.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "FST.h"
|
||||
|
||||
FST::FST(uint8_t *data, uint32_t fstSize, uint32_t offset, const VolumeBlockSize &blockSize) {
|
||||
uint32_t curOffset = offset;
|
||||
|
||||
header = new FSTHeader(data + curOffset);
|
||||
curOffset += header->LENGTH;
|
||||
|
||||
sectionEntries = new SectionEntries(data + curOffset, header->numberOfSections, blockSize);
|
||||
curOffset += sectionEntries->getSizeInBytes();
|
||||
|
||||
uint32_t lastEntryNumber = RootEntry::parseLastEntryNumber(data, curOffset);
|
||||
|
||||
auto stringTableOffset = curOffset + (lastEntryNumber * 16);
|
||||
|
||||
stringTable = StringTable::parseData(data, fstSize - stringTableOffset, stringTableOffset, lastEntryNumber);
|
||||
|
||||
nodeEntries = NodeEntries::parseData(data, curOffset, sectionEntries, stringTable, header->blockSize);
|
||||
}
|
||||
|
||||
FST::~FST() {
|
||||
delete nodeEntries;
|
||||
delete stringTable;
|
||||
delete sectionEntries;
|
||||
delete header;
|
||||
}
|
||||
|
||||
RootEntry *FST::getRootEntry() const {
|
||||
return nodeEntries->rootEntry;
|
||||
}
|
||||
|
39
source/WUD/entities/FST/FST.h
Normal file
39
source/WUD/entities/FST/FST.h
Normal file
@ -0,0 +1,39 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <WUD/entities/FST/header/FSTHeader.h>
|
||||
#include <WUD/entities/FST/sectionentry/SectionEntries.h>
|
||||
#include <WUD/entities/FST/stringtable/StringTable.h>
|
||||
#include <WUD/entities/FST/nodeentry/NodeEntries.h>
|
||||
#include <WUD/entities/FST/nodeentry/RootEntry.h>
|
||||
|
||||
class FST {
|
||||
|
||||
public:
|
||||
FST(uint8_t *data, uint32_t fstSize, uint32_t offset, const VolumeBlockSize& blockSize);
|
||||
|
||||
~FST();
|
||||
|
||||
FSTHeader *header;
|
||||
SectionEntries *sectionEntries;
|
||||
StringTable *stringTable;
|
||||
NodeEntries *nodeEntries;
|
||||
|
||||
[[nodiscard]] RootEntry * getRootEntry() const;
|
||||
};
|
30
source/WUD/entities/FST/header/FSTHeader.cpp
Normal file
30
source/WUD/entities/FST/header/FSTHeader.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <utils/blocksize/SectionBlockSize.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include "FSTHeader.h"
|
||||
|
||||
FSTHeader::FSTHeader(uint8_t *data) {
|
||||
auto *dataAsUint = (uint32_t *) data;
|
||||
if ((dataAsUint[0] & 0xFFFFFF00) != 0x46535400) {
|
||||
OSFatal("FST Header magic was wrong");
|
||||
}
|
||||
FSTVersion = data[3];
|
||||
blockSize = SectionBlockSize(dataAsUint[1]);
|
||||
numberOfSections = dataAsUint[2];
|
||||
hashDisabled = data[12];
|
||||
}
|
35
source/WUD/entities/FST/header/FSTHeader.h
Normal file
35
source/WUD/entities/FST/header/FSTHeader.h
Normal file
@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <utils/blocksize/SectionBlockSize.h>
|
||||
|
||||
class FSTHeader {
|
||||
|
||||
public:
|
||||
explicit FSTHeader(uint8_t *data) ;
|
||||
|
||||
~FSTHeader()= default;
|
||||
|
||||
uint8_t FSTVersion;
|
||||
SectionBlockSize blockSize;
|
||||
uint8_t hashDisabled;
|
||||
uint32_t numberOfSections;
|
||||
uint32_t LENGTH = 32;
|
||||
|
||||
};
|
82
source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp
Normal file
82
source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <coreinit/debug.h>
|
||||
#include "DirectoryEntry.h"
|
||||
|
||||
DirectoryEntry *DirectoryEntry::parseData(const uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable) {
|
||||
auto *directoryEntry = new DirectoryEntry();
|
||||
directoryEntry->entryNumber = param.entryNumber;
|
||||
directoryEntry->parent = param.parent;
|
||||
directoryEntry->entryType = param.type;
|
||||
directoryEntry->nameString = stringTable->getStringEntry(param.uint24);
|
||||
if (directoryEntry->nameString == nullptr) {
|
||||
OSFatal("Failed to find string for offset");
|
||||
}
|
||||
|
||||
directoryEntry->parentEntryNumber = ((uint32_t *) &data[4])[0];
|
||||
directoryEntry->lastEntryNumber = ((uint32_t *) &data[8])[0];
|
||||
|
||||
directoryEntry->permission = param.permission;
|
||||
|
||||
if (param.sectionNumber > sectionEntries->size()) {
|
||||
OSFatal("section number does not match");
|
||||
}
|
||||
directoryEntry->sectionEntry = sectionEntries->getSection(param.sectionNumber);
|
||||
|
||||
return directoryEntry;
|
||||
}
|
||||
|
||||
DirectoryEntry::~DirectoryEntry() {
|
||||
for (auto &child: children) {
|
||||
delete child;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DirectoryEntry *> DirectoryEntry::getDirChildren() const {
|
||||
std::vector<DirectoryEntry *> res;
|
||||
for (auto &cur: children) {
|
||||
if (cur->isDirectory()) {
|
||||
res.push_back(dynamic_cast<DirectoryEntry *>(cur));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<FileEntry *> DirectoryEntry::getFileChildren() const {
|
||||
std::vector<FileEntry *> res;
|
||||
for (auto &cur: children) {
|
||||
if (cur->isFile()) {
|
||||
res.push_back(dynamic_cast<FileEntry *>(cur));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<NodeEntry *> DirectoryEntry::getChildren() const {
|
||||
return children;
|
||||
}
|
||||
|
||||
void DirectoryEntry::printPathRecursive() {
|
||||
DEBUG_FUNCTION_LINE("%s", getFullPath().c_str());
|
||||
for (auto &child: children) {
|
||||
child->printPathRecursive();
|
||||
}
|
||||
}
|
||||
|
||||
void DirectoryEntry::addChild(NodeEntry *entry) {
|
||||
children.push_back(entry);
|
||||
}
|
46
source/WUD/entities/FST/nodeentry/DirectoryEntry.h
Normal file
46
source/WUD/entities/FST/nodeentry/DirectoryEntry.h
Normal file
@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <WUD/entities/FST/sectionentry/SectionEntries.h>
|
||||
#include <WUD/entities/FST/stringtable/StringTable.h>
|
||||
#include "NodeEntryParam.h"
|
||||
#include "NodeEntry.h"
|
||||
#include "FileEntry.h"
|
||||
|
||||
class DirectoryEntry : public NodeEntry {
|
||||
|
||||
|
||||
public:
|
||||
~DirectoryEntry() override;
|
||||
|
||||
static DirectoryEntry *parseData(const uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable);
|
||||
|
||||
uint32_t parentEntryNumber{};
|
||||
uint32_t lastEntryNumber{};
|
||||
std::vector<NodeEntry *> children;
|
||||
|
||||
void addChild(NodeEntry *entry);
|
||||
|
||||
[[nodiscard]] std::vector<DirectoryEntry *> getDirChildren() const;
|
||||
|
||||
[[nodiscard]] std::vector<FileEntry *> getFileChildren() const;
|
||||
|
||||
[[nodiscard]] std::vector<NodeEntry *> getChildren() const;
|
||||
|
||||
void printPathRecursive() override;
|
||||
};
|
56
source/WUD/entities/FST/nodeentry/FileEntry.cpp
Normal file
56
source/WUD/entities/FST/nodeentry/FileEntry.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "FileEntry.h"
|
||||
#include <WUD/entities/FST/stringtable/StringTable.h>
|
||||
#include <coreinit/debug.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
FileEntry::FileEntry(SectionAddress address) : address(std::move(address)) {
|
||||
|
||||
}
|
||||
|
||||
NodeEntry *FileEntry::parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize) {
|
||||
auto *entry = new FileEntry(SectionAddress(blockSize, ((uint32_t *) &data[4])[0]));
|
||||
|
||||
entry->entryNumber = param.entryNumber;
|
||||
entry->parent = param.parent;
|
||||
entry->entryType = param.type;
|
||||
entry->nameString = stringTable->getStringEntry(param.uint24);
|
||||
if (entry->nameString == nullptr) {
|
||||
OSFatal("Failed to find string for offset");
|
||||
}
|
||||
|
||||
entry->size = ((uint32_t *) &data[8])[0];
|
||||
|
||||
entry->permission = param.permission;
|
||||
entry->sectionEntry = sectionEntries->getSection(param.sectionNumber);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
SectionEntry *FileEntry::getSectionEntry() {
|
||||
return sectionEntry;
|
||||
}
|
||||
|
||||
uint64_t FileEntry::getOffset() const {
|
||||
return address.getAddressInBytes();
|
||||
}
|
||||
|
||||
uint32_t FileEntry::getSize() const {
|
||||
return size;
|
||||
}
|
41
source/WUD/entities/FST/nodeentry/FileEntry.h
Normal file
41
source/WUD/entities/FST/nodeentry/FileEntry.h
Normal file
@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <utils/blocksize/SectionAddress.h>
|
||||
|
||||
#include "NodeEntry.h"
|
||||
|
||||
class FileEntry : public NodeEntry {
|
||||
public:
|
||||
explicit FileEntry(SectionAddress address);
|
||||
|
||||
static NodeEntry *parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize);
|
||||
|
||||
~FileEntry() override = default;
|
||||
|
||||
SectionEntry *getSectionEntry();
|
||||
|
||||
[[nodiscard]] uint64_t getOffset() const;
|
||||
|
||||
[[nodiscard]] uint32_t getSize() const;
|
||||
|
||||
private:
|
||||
SectionAddress address;
|
||||
uint32_t size{};
|
||||
};
|
57
source/WUD/entities/FST/nodeentry/NodeEntries.cpp
Normal file
57
source/WUD/entities/FST/nodeentry/NodeEntries.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <coreinit/debug.h>
|
||||
#include "NodeEntries.h"
|
||||
|
||||
NodeEntries::NodeEntries(RootEntry *pEntry) {
|
||||
rootEntry = pEntry;
|
||||
}
|
||||
|
||||
NodeEntries::~NodeEntries() {
|
||||
delete rootEntry;
|
||||
}
|
||||
|
||||
NodeEntry *NodeEntries::DeserializeImpl(uint8_t *data, uint32_t offset, DirectoryEntry *parent, uint32_t entryNumber, SectionEntries *sectionEntries, StringTable *stringTable,
|
||||
const SectionBlockSize &blockSize) {
|
||||
NodeEntry *nodeEntry = NodeEntry::AutoDeserialize(data, offset, parent, entryNumber, sectionEntries, stringTable, blockSize);
|
||||
auto asDirEntry = dynamic_cast<DirectoryEntry *>(nodeEntry);
|
||||
if (asDirEntry != nullptr) {
|
||||
uint32_t curEntryNumber = asDirEntry->entryNumber + 1;
|
||||
while (curEntryNumber < asDirEntry->lastEntryNumber) {
|
||||
NodeEntry *entry = NodeEntries::DeserializeImpl(data, offset + (curEntryNumber - asDirEntry->entryNumber) * NodeEntry::LENGTH,
|
||||
asDirEntry, curEntryNumber, sectionEntries, stringTable, blockSize);
|
||||
asDirEntry->addChild(entry);
|
||||
auto *childAsDir = dynamic_cast<DirectoryEntry *>(entry);
|
||||
if (childAsDir != nullptr) {
|
||||
curEntryNumber = childAsDir->lastEntryNumber;
|
||||
} else {
|
||||
curEntryNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeEntry;
|
||||
}
|
||||
|
||||
NodeEntries *NodeEntries::parseData(unsigned char *data, uint32_t offset, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize) {
|
||||
NodeEntry *rootEntry = NodeEntries::DeserializeImpl(data, offset, (DirectoryEntry *) nullptr, 0, sectionEntries, stringTable, blockSize);
|
||||
auto rootEntryCasted = dynamic_cast<RootEntry *>(rootEntry);
|
||||
if (rootEntryCasted != nullptr) {
|
||||
return new NodeEntries(rootEntryCasted);
|
||||
}
|
||||
OSFatal("Failed to parse Root");
|
||||
return nullptr;
|
||||
}
|
40
source/WUD/entities/FST/nodeentry/NodeEntries.h
Normal file
40
source/WUD/entities/FST/nodeentry/NodeEntries.h
Normal file
@ -0,0 +1,40 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <WUD/entities/FST/stringtable/StringTable.h>
|
||||
#include <utils/blocksize/SectionBlockSize.h>
|
||||
#include <WUD/entities/FST/sectionentry/SectionEntries.h>
|
||||
#include "DirectoryEntry.h"
|
||||
#include "RootEntry.h"
|
||||
#include "NodeEntry.h"
|
||||
#include "NodeEntries.h"
|
||||
|
||||
class NodeEntries {
|
||||
|
||||
public:
|
||||
explicit NodeEntries(RootEntry *pEntry);
|
||||
|
||||
~NodeEntries();
|
||||
|
||||
static NodeEntry *
|
||||
DeserializeImpl(unsigned char *data, uint32_t offset, DirectoryEntry *parent, uint32_t entryNumber, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize);
|
||||
|
||||
static NodeEntries *parseData(unsigned char *data, uint32_t offset, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize);
|
||||
|
||||
RootEntry *rootEntry;
|
||||
};
|
83
source/WUD/entities/FST/nodeentry/NodeEntry.cpp
Normal file
83
source/WUD/entities/FST/nodeentry/NodeEntry.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <utils/blocksize/SectionBlockSize.h>
|
||||
#include <WUD/entities/FST/stringtable/StringTable.h>
|
||||
#include <WUD/entities/FST/sectionentry/SectionEntries.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include "NodeEntry.h"
|
||||
#include "DirectoryEntry.h"
|
||||
#include "RootEntry.h"
|
||||
|
||||
uint32_t NodeEntry::LENGTH = 16;
|
||||
|
||||
NodeEntry *NodeEntry::AutoDeserialize(uint8_t *data, uint32_t offset, DirectoryEntry *pParent, uint32_t eEntryNumber, SectionEntries *sectionEntries,
|
||||
StringTable *stringTable, const SectionBlockSize &blockSize) {
|
||||
uint8_t *curEntryData = &data[offset];
|
||||
|
||||
NodeEntryParam param{};
|
||||
param.permission = ((uint16_t *) &curEntryData[12])[0];
|
||||
param.sectionNumber = ((uint16_t *) &curEntryData[14])[0];
|
||||
param.entryNumber = eEntryNumber;
|
||||
param.parent = pParent;
|
||||
param.type = curEntryData[0];
|
||||
param.uint24 = ((uint32_t *) curEntryData)[0] & 0x00FFFFFF;
|
||||
|
||||
if ((param.type & ENTRY_TYPE_Directory) == ENTRY_TYPE_Directory && param.uint24 == 0) { // Root
|
||||
return (NodeEntry *) RootEntry::parseData(curEntryData, param, sectionEntries, stringTable);
|
||||
} else if ((param.type & ENTRY_TYPE_Directory) == ENTRY_TYPE_Directory) {
|
||||
return (NodeEntry *) DirectoryEntry::parseData(curEntryData, param, sectionEntries, stringTable);
|
||||
} else if ((param.type & ENTRY_TYPE_File) == ENTRY_TYPE_File) {
|
||||
return (NodeEntry *) FileEntry::parseData(curEntryData, param, sectionEntries, stringTable, blockSize);
|
||||
}
|
||||
|
||||
OSFatal("FST Unknown Node Type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string NodeEntry::getName() const &{
|
||||
if (nameString != nullptr) {
|
||||
return nameString->toString();
|
||||
}
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
std::string NodeEntry::getFullPathInternal() const &{
|
||||
if (parent != nullptr) {
|
||||
return parent->getFullPathInternal().append("/").append(getName());
|
||||
}
|
||||
return getName();
|
||||
}
|
||||
|
||||
std::string NodeEntry::getFullPath() const &{
|
||||
return getFullPathInternal();
|
||||
}
|
||||
|
||||
std::string NodeEntry::getPath() const &{
|
||||
if (parent != nullptr) {
|
||||
return parent->getFullPath().append("/");
|
||||
}
|
||||
return "/";
|
||||
}
|
||||
|
||||
bool NodeEntry::isDirectory() const {
|
||||
return (entryType & ENTRY_TYPE_Directory) == ENTRY_TYPE_Directory;
|
||||
}
|
||||
|
||||
|
||||
bool NodeEntry::isFile() const {
|
||||
return (entryType & ENTRY_TYPE_File) == ENTRY_TYPE_File;
|
||||
}
|
65
source/WUD/entities/FST/nodeentry/NodeEntry.h
Normal file
65
source/WUD/entities/FST/nodeentry/NodeEntry.h
Normal file
@ -0,0 +1,65 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <utils/blocksize/SectionBlockSize.h>
|
||||
#include <WUD/entities/FST/stringtable/StringEntry.h>
|
||||
#include <WUD/entities/FST/sectionentry/SectionEntry.h>
|
||||
#include <WUD/entities/FST/sectionentry/SectionEntries.h>
|
||||
#include <utils/logger.h>
|
||||
#include "NodeEntryParam.h"
|
||||
|
||||
#define ENTRY_TYPE_File 0
|
||||
#define ENTRY_TYPE_Directory 1
|
||||
#define ENTRY_TYPE_Link 0x80
|
||||
|
||||
class DirectoryEntry;
|
||||
|
||||
class NodeEntry {
|
||||
|
||||
public:
|
||||
uint16_t permission{};
|
||||
StringEntry *nameString{};
|
||||
SectionEntry *sectionEntry{};
|
||||
DirectoryEntry *parent{};
|
||||
uint8_t entryType{};
|
||||
uint32_t entryNumber{};
|
||||
|
||||
static NodeEntry *AutoDeserialize(uint8_t *data, uint32_t offset, DirectoryEntry *pParent, uint32_t eEntryNumber, SectionEntries *sectionEntries,
|
||||
StringTable *stringTable, const SectionBlockSize& blockSize);
|
||||
|
||||
virtual ~NodeEntry()= default;
|
||||
|
||||
virtual void printPathRecursive() {
|
||||
DEBUG_FUNCTION_LINE("%s", getFullPath().c_str());
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string getFullPath() const&;
|
||||
|
||||
[[nodiscard]] std::string getPath() const&;
|
||||
|
||||
[[nodiscard]] std::string getName() const&;
|
||||
|
||||
[[nodiscard]] bool isDirectory() const;
|
||||
|
||||
[[nodiscard]] bool isFile() const;
|
||||
|
||||
static uint32_t LENGTH;
|
||||
private:
|
||||
[[nodiscard]] std::string getFullPathInternal() const &;
|
||||
};
|
30
source/WUD/entities/FST/nodeentry/NodeEntryParam.h
Normal file
30
source/WUD/entities/FST/nodeentry/NodeEntryParam.h
Normal file
@ -0,0 +1,30 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
class DirectoryEntry;
|
||||
|
||||
class NodeEntryParam {
|
||||
public:
|
||||
uint16_t sectionNumber;
|
||||
uint32_t entryNumber;
|
||||
DirectoryEntry* parent;
|
||||
uint16_t permission;
|
||||
uint8_t type;
|
||||
uint32_t uint24;
|
||||
};
|
45
source/WUD/entities/FST/nodeentry/RootEntry.cpp
Normal file
45
source/WUD/entities/FST/nodeentry/RootEntry.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <coreinit/debug.h>
|
||||
#include "RootEntry.h"
|
||||
|
||||
RootEntry::RootEntry(DirectoryEntry *input) {
|
||||
if ((input->entryType & ENTRY_TYPE_Directory) != ENTRY_TYPE_Directory || input->entryNumber != 0) {
|
||||
OSFatal("Input is no root entry.");
|
||||
}
|
||||
|
||||
entryNumber = input->entryNumber;
|
||||
parent = input->parent;
|
||||
nameString = input->nameString;
|
||||
if(nameString == nullptr){
|
||||
OSFatal("nameString was null");
|
||||
}
|
||||
entryType = input->entryType;
|
||||
|
||||
parentEntryNumber = input->parentEntryNumber;
|
||||
lastEntryNumber = input->lastEntryNumber;
|
||||
permission = input->permission;
|
||||
sectionEntry = input->sectionEntry;
|
||||
}
|
||||
|
||||
uint32_t RootEntry::parseLastEntryNumber(uint8_t *data, uint32_t offset) {
|
||||
return ((uint32_t *) &data[8 + offset])[0];
|
||||
}
|
||||
|
||||
RootEntry *RootEntry::parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable) {
|
||||
return new RootEntry(DirectoryEntry::parseData(data, param, sectionEntries, stringTable));
|
||||
}
|
36
source/WUD/entities/FST/nodeentry/RootEntry.h
Normal file
36
source/WUD/entities/FST/nodeentry/RootEntry.h
Normal file
@ -0,0 +1,36 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <WUD/entities/FST/stringtable/StringTable.h>
|
||||
#include <utils/blocksize/SectionBlockSize.h>
|
||||
#include <WUD/entities/FST/sectionentry/SectionEntries.h>
|
||||
#include "DirectoryEntry.h"
|
||||
|
||||
class RootEntry : public DirectoryEntry {
|
||||
|
||||
explicit RootEntry(DirectoryEntry *input);
|
||||
|
||||
public:
|
||||
|
||||
~RootEntry() override = default;
|
||||
|
||||
static RootEntry *parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable);
|
||||
|
||||
static uint32_t parseLastEntryNumber(uint8_t *data, uint32_t offset);
|
||||
};
|
40
source/WUD/entities/FST/sectionentry/SectionEntries.cpp
Normal file
40
source/WUD/entities/FST/sectionentry/SectionEntries.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "SectionEntries.h"
|
||||
|
||||
SectionEntries::SectionEntries(uint8_t *data, uint32_t numberOfSections, const VolumeBlockSize &pBlockSize) {
|
||||
for (uint32_t i = 0; i < numberOfSections; i++) {
|
||||
list.push_back(new SectionEntry(data + (i * 32), i, pBlockSize));
|
||||
}
|
||||
}
|
||||
|
||||
SectionEntry *SectionEntries::getSection(uint16_t sectionNumber) const {
|
||||
for (auto const &e: list) {
|
||||
if (e->sectionNumber == sectionNumber) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t SectionEntries::getSizeInBytes() const {
|
||||
return list.size() * 32;
|
||||
}
|
||||
|
||||
uint32_t SectionEntries::size() const {
|
||||
return list.size();
|
||||
}
|
41
source/WUD/entities/FST/sectionentry/SectionEntries.h
Normal file
41
source/WUD/entities/FST/sectionentry/SectionEntries.h
Normal file
@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <utils/blocksize/VolumeBlockSize.h>
|
||||
#include "SectionEntry.h"
|
||||
|
||||
class SectionEntries {
|
||||
|
||||
public:
|
||||
SectionEntries(uint8_t *data, uint32_t numberOfSections, const VolumeBlockSize &pBlockSize);
|
||||
|
||||
[[nodiscard]] uint32_t getSizeInBytes() const;
|
||||
|
||||
[[nodiscard]] uint32_t size() const;
|
||||
|
||||
[[nodiscard]] SectionEntry *getSection(uint16_t sectionNumber) const;
|
||||
|
||||
[[nodiscard]] std::vector<SectionEntry *> getSections() const &{
|
||||
return list;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<SectionEntry *> list;
|
||||
};
|
32
source/WUD/entities/FST/sectionentry/SectionEntry.cpp
Normal file
32
source/WUD/entities/FST/sectionentry/SectionEntry.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "SectionEntry.h"
|
||||
|
||||
SectionEntry::SectionEntry(uint8_t *data, uint32_t pSectionNumber, const VolumeBlockSize& pBlockSize) {
|
||||
auto *dataAsUint = (uint32_t *) data;
|
||||
address = AddressInVolumeBlocks(pBlockSize, dataAsUint[0]);
|
||||
size = SizeInVolumeBlocks(pBlockSize, dataAsUint[1]);
|
||||
|
||||
ownerID = ((uint64_t *) (&data[8]))[0];
|
||||
groupID = ((uint64_t *) (&data[16]))[0];
|
||||
hashMode = data[20];
|
||||
char buff[32];
|
||||
snprintf(buff, sizeof(buff), "Section: %d", pSectionNumber);
|
||||
|
||||
name = std::string(buff);
|
||||
sectionNumber = pSectionNumber;
|
||||
}
|
37
source/WUD/entities/FST/sectionentry/SectionEntry.h
Normal file
37
source/WUD/entities/FST/sectionentry/SectionEntry.h
Normal file
@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utils/blocksize/AddressInVolumeBlocks.h>
|
||||
#include <utils/blocksize/SizeInVolumeBlocks.h>
|
||||
|
||||
class SectionEntry {
|
||||
public:
|
||||
SectionEntry(uint8_t *data, uint32_t pSectionNumber, const VolumeBlockSize &pBlockSize);
|
||||
|
||||
~SectionEntry() = default;
|
||||
|
||||
AddressInVolumeBlocks address;
|
||||
SizeInVolumeBlocks size;
|
||||
uint8_t hashMode;
|
||||
uint64_t ownerID;
|
||||
uint64_t groupID;
|
||||
std::string name;
|
||||
uint32_t sectionNumber;
|
||||
};
|
27
source/WUD/entities/FST/stringtable/StringEntry.cpp
Normal file
27
source/WUD/entities/FST/stringtable/StringEntry.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "StringEntry.h"
|
||||
#include "StringTable.h"
|
||||
|
||||
std::string StringEntry::toString() const{
|
||||
return stringTable->getByAddress(offset);
|
||||
}
|
||||
|
||||
StringEntry::StringEntry(StringTable *pTable, uint32_t pOffset) {
|
||||
stringTable = pTable;
|
||||
offset = pOffset;
|
||||
}
|
33
source/WUD/entities/FST/stringtable/StringEntry.h
Normal file
33
source/WUD/entities/FST/stringtable/StringEntry.h
Normal file
@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class StringTable;
|
||||
|
||||
class StringEntry {
|
||||
|
||||
public:
|
||||
StringEntry(StringTable *pTable, uint32_t pOffset);
|
||||
|
||||
[[nodiscard]] std::string toString() const;
|
||||
|
||||
StringTable *stringTable;
|
||||
uint32_t offset;
|
||||
};
|
71
source/WUD/entities/FST/stringtable/StringTable.cpp
Normal file
71
source/WUD/entities/FST/stringtable/StringTable.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <cstring>
|
||||
#include <coreinit/debug.h>
|
||||
#include "StringTable.h"
|
||||
|
||||
StringTable *StringTable::parseData(uint8_t *data, uint32_t dataLength, uint32_t offset, uint32_t stringCount) {
|
||||
auto *stringTable = new StringTable();
|
||||
uint32_t curOffset = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; curOffset < dataLength && i < stringCount; ++curOffset) {
|
||||
if (data[offset + curOffset] == (uint8_t) 0) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < stringCount) {
|
||||
OSFatal("stringtable is broken");
|
||||
}
|
||||
|
||||
uint32_t curLength = 0;
|
||||
for (i = 0; i < stringCount; ++i) {
|
||||
curOffset = offset + curLength;
|
||||
stringTable->stringMap[curLength] = new StringEntry(stringTable, curLength);
|
||||
stringTable->strings[curLength] = (char *) &data[curOffset];
|
||||
|
||||
curLength += strlen((char *) &data[curOffset]) + 1;
|
||||
}
|
||||
|
||||
return stringTable;
|
||||
}
|
||||
|
||||
std::string StringTable::getByAddress(uint32_t address) {
|
||||
return strings[address];
|
||||
}
|
||||
|
||||
StringEntry *StringTable::getStringEntry(uint32_t address) {
|
||||
return stringMap[address];
|
||||
}
|
||||
|
||||
uint32_t StringTable::getSize() {
|
||||
uint32_t capacity = 1; // root entry
|
||||
for (auto &cur: strings) {
|
||||
capacity += cur.second.length() + 1;
|
||||
}
|
||||
return capacity;
|
||||
}
|
||||
|
||||
StringEntry *StringTable::getEntry(std::string &str) {
|
||||
for (auto &cur: strings) {
|
||||
if (cur.second == str) {
|
||||
return stringMap[cur.first];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
47
source/WUD/entities/FST/stringtable/StringTable.h
Normal file
47
source/WUD/entities/FST/stringtable/StringTable.h
Normal file
@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "StringEntry.h"
|
||||
|
||||
class StringTable {
|
||||
|
||||
public:
|
||||
~StringTable() {
|
||||
for (auto &cur: stringMap) {
|
||||
delete cur.second;
|
||||
}
|
||||
stringMap.clear();
|
||||
strings.clear();
|
||||
}
|
||||
|
||||
static StringTable *parseData(uint8_t *data, uint32_t dataLength, uint32_t offset, uint32_t stringCount);
|
||||
|
||||
std::string getByAddress(uint32_t address);
|
||||
|
||||
StringEntry *getStringEntry(uint32_t address);
|
||||
|
||||
uint32_t getSize();
|
||||
|
||||
StringEntry *getEntry(std::string &str);
|
||||
|
||||
private:
|
||||
std::map<uint32_t, StringEntry *> stringMap;
|
||||
std::map<uint32_t, std::string> strings;
|
||||
};
|
28
source/WUD/entities/TMD/Content.cpp
Normal file
28
source/WUD/entities/TMD/Content.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <cstring>
|
||||
#include "Content.h"
|
||||
|
||||
uint32_t Content::LENGTH = 0x30;
|
||||
|
||||
Content::Content(uint8_t *data) {
|
||||
ID = ((uint32_t *) &data[0x00])[0];
|
||||
index = ((uint16_t *) &data[0x04])[0];
|
||||
type = ((uint16_t *) &data[0x06])[0];
|
||||
encryptedFileSize = ((uint64_t *) &data[0x08])[0];
|
||||
memcpy(hash, &data[0x10], 0x14);
|
||||
}
|
32
source/WUD/entities/TMD/Content.h
Normal file
32
source/WUD/entities/TMD/Content.h
Normal file
@ -0,0 +1,32 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class Content {
|
||||
public:
|
||||
static uint32_t LENGTH;
|
||||
|
||||
explicit Content(uint8_t *data);
|
||||
|
||||
uint16_t index;
|
||||
uint32_t ID;
|
||||
uint16_t type;
|
||||
uint64_t encryptedFileSize;
|
||||
uint8_t hash[0x14]{};
|
||||
};
|
42
source/WUD/entities/TMD/TitleMetaData.cpp
Normal file
42
source/WUD/entities/TMD/TitleMetaData.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "TitleMetaData.h"
|
||||
|
||||
TitleMetaData::TitleMetaData(uint8_t *data) {
|
||||
contentCount = ((uint16_t *) &data[0x1DE])[0];
|
||||
// Get Contents
|
||||
for (uint16_t i = 0; i < contentCount; i++) {
|
||||
auto curOffset = 0xB04 + (i * Content::LENGTH);
|
||||
auto *c = new Content((uint8_t *) &data[curOffset]);
|
||||
contentList.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
TitleMetaData::~TitleMetaData() {
|
||||
for (auto &content: contentList) {
|
||||
delete content;
|
||||
}
|
||||
}
|
||||
|
||||
Content* TitleMetaData::getContentByIndex(uint16_t i) {
|
||||
for (auto &content: contentList) {
|
||||
if(content->index == i){
|
||||
return content;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
35
source/WUD/entities/TMD/TitleMetaData.h
Normal file
35
source/WUD/entities/TMD/TitleMetaData.h
Normal file
@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "Content.h"
|
||||
|
||||
class TitleMetaData {
|
||||
public:
|
||||
explicit TitleMetaData(uint8_t *data);
|
||||
|
||||
~TitleMetaData();
|
||||
|
||||
std::vector<Content *> contentList;
|
||||
|
||||
Content* getContentByIndex(uint16_t index);
|
||||
|
||||
private:
|
||||
uint16_t contentCount;
|
||||
};
|
40
source/WUD/header/WiiUDiscHeader.cpp
Normal file
40
source/WUD/header/WiiUDiscHeader.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "WiiUDiscHeader.h"
|
||||
#include <coreinit/debug.h>
|
||||
|
||||
uint32_t WiiUDiscHeader::LENGTH = 131072L;
|
||||
|
||||
WiiUDiscHeader::WiiUDiscHeader(DiscReader *reader, uint32_t offset) {
|
||||
uint32_t curOffset = offset;
|
||||
manufactorDiscID = new WiiUManufactorDiscID(reader, 0);
|
||||
curOffset += WiiUManufactorDiscID::LENGTH;
|
||||
discId = new WiiUDiscID(reader, curOffset);
|
||||
curOffset += WiiUDiscID::LENGTH;
|
||||
wiiUContentsInformation = new WiiUContentsInformation(reader, curOffset);
|
||||
curOffset += WiiUContentsInformation::LENGTH;
|
||||
|
||||
if (curOffset - offset != LENGTH) {
|
||||
OSFatal("Length mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
WiiUDiscHeader::~WiiUDiscHeader() {
|
||||
delete manufactorDiscID;
|
||||
delete discId;
|
||||
delete wiiUContentsInformation;
|
||||
}
|
37
source/WUD/header/WiiUDiscHeader.h
Normal file
37
source/WUD/header/WiiUDiscHeader.h
Normal file
@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <WUD/DiscReader.h>
|
||||
#include <WUD/content/WiiUContentsInformation.h>
|
||||
#include "WiiUManufactorDiscID.h"
|
||||
#include "WiiUDiscID.h"
|
||||
|
||||
class WiiUDiscHeader {
|
||||
|
||||
public:
|
||||
static uint32_t LENGTH;
|
||||
|
||||
WiiUDiscHeader(DiscReader *reader, uint32_t offset);
|
||||
|
||||
WiiUManufactorDiscID *manufactorDiscID = nullptr;
|
||||
WiiUDiscID *discId = nullptr;
|
||||
WiiUContentsInformation *wiiUContentsInformation = nullptr;
|
||||
|
||||
~WiiUDiscHeader();
|
||||
};
|
43
source/WUD/header/WiiUDiscID.cpp
Normal file
43
source/WUD/header/WiiUDiscID.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "WiiUDiscID.h"
|
||||
#include <coreinit/debug.h>
|
||||
|
||||
uint32_t WiiUDiscID::LENGTH = 32768;
|
||||
uint32_t WiiUDiscID::MAGIC = 0xCC549EB9;
|
||||
|
||||
WiiUDiscID::WiiUDiscID(DiscReader *reader, uint32_t offset) {
|
||||
auto data = (uint8_t *) malloc(LENGTH);
|
||||
if (data == nullptr) {
|
||||
OSFatal("Failed to alloc for WiiUDiscID");
|
||||
}
|
||||
|
||||
if (!reader->readEncrypted(data, offset, LENGTH)) {
|
||||
OSFatal("Failed to read data");
|
||||
}
|
||||
|
||||
if (((uint32_t *) data)[0] != MAGIC) {
|
||||
OSFatal("MAGIC FAIL");
|
||||
}
|
||||
|
||||
majorVersion = data[5];
|
||||
minorVersion = data[6];
|
||||
|
||||
footprint = std::string((char *) &data[32]);
|
||||
|
||||
free(data);
|
||||
}
|
32
source/WUD/header/WiiUDiscID.h
Normal file
32
source/WUD/header/WiiUDiscID.h
Normal file
@ -0,0 +1,32 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <WUD/DiscReader.h>
|
||||
|
||||
class WiiUDiscID {
|
||||
|
||||
public:
|
||||
WiiUDiscID(DiscReader *reader, uint32_t offset);
|
||||
|
||||
static uint32_t LENGTH;
|
||||
static uint32_t MAGIC;
|
||||
uint8_t majorVersion;
|
||||
uint8_t minorVersion;
|
||||
std::string footprint;
|
||||
};
|
26
source/WUD/header/WiiUManufactorDiscID.cpp
Normal file
26
source/WUD/header/WiiUManufactorDiscID.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "WiiUManufactorDiscID.h"
|
||||
#include <coreinit/debug.h>
|
||||
|
||||
uint32_t WiiUManufactorDiscID::LENGTH = 65536;
|
||||
|
||||
WiiUManufactorDiscID::WiiUManufactorDiscID(DiscReader *reader, uint32_t offset) {
|
||||
if(!reader->readEncrypted(data, offset, LENGTH)){
|
||||
OSFatal("WiiUManufactorDiscID: read failed");
|
||||
}
|
||||
}
|
30
source/WUD/header/WiiUManufactorDiscID.h
Normal file
30
source/WUD/header/WiiUManufactorDiscID.h
Normal file
@ -0,0 +1,30 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <WUD/DiscReader.h>
|
||||
|
||||
class WiiUManufactorDiscID {
|
||||
|
||||
public:
|
||||
WiiUManufactorDiscID(DiscReader *reader, uint32_t offset);
|
||||
|
||||
static uint32_t LENGTH;
|
||||
private:
|
||||
uint8_t data[65536]{};
|
||||
};
|
3
source/common/common.cpp
Normal file
3
source/common/common.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "common.h"
|
||||
|
||||
int32_t gFSAfd = -1;
|
5
source/common/common.h
Normal file
5
source/common/common.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
extern int32_t gFSAfd;
|
173
source/fs/CFile.cpp
Normal file
173
source/fs/CFile.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include "CFile.hpp"
|
||||
|
||||
CFile::CFile() {
|
||||
iFd = -1;
|
||||
mem_file = NULL;
|
||||
filesize = 0;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
CFile::CFile(const std::string &filepath, eOpenTypes mode) {
|
||||
iFd = -1;
|
||||
this->open(filepath, mode);
|
||||
}
|
||||
|
||||
CFile::CFile(const uint8_t *mem, int32_t size) {
|
||||
iFd = -1;
|
||||
this->open(mem, size);
|
||||
}
|
||||
|
||||
CFile::~CFile() {
|
||||
this->close();
|
||||
}
|
||||
|
||||
int32_t CFile::open(const std::string &filepath, eOpenTypes mode) {
|
||||
this->close();
|
||||
int32_t openMode = 0;
|
||||
|
||||
// This depend on the devoptab implementation.
|
||||
// see https://github.com/devkitPro/wut/blob/master/libraries/wutdevoptab/devoptab_fs_open.c#L21 fpr reference
|
||||
|
||||
switch (mode) {
|
||||
default:
|
||||
case ReadOnly: // file must exist
|
||||
openMode = O_RDONLY;
|
||||
break;
|
||||
case WriteOnly: // file will be created / zerod
|
||||
openMode = O_TRUNC | O_CREAT | O_WRONLY;
|
||||
break;
|
||||
case ReadWrite: // file must exist
|
||||
openMode = O_RDWR;
|
||||
break;
|
||||
case Append: // append to file, file will be created if missing. write only
|
||||
openMode = O_CREAT | O_APPEND | O_WRONLY;
|
||||
break;
|
||||
}
|
||||
|
||||
//! Using fopen works only on the first launch as expected
|
||||
//! on the second launch it causes issues because we don't overwrite
|
||||
//! the .data sections which is needed for a normal application to re-init
|
||||
//! this will be added with launching as RPX
|
||||
iFd = ::open(filepath.c_str(), openMode);
|
||||
if (iFd < 0)
|
||||
return iFd;
|
||||
|
||||
|
||||
filesize = ::lseek(iFd, 0, SEEK_END);
|
||||
::lseek(iFd, 0, SEEK_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t CFile::open(const uint8_t *mem, int32_t size) {
|
||||
this->close();
|
||||
|
||||
mem_file = mem;
|
||||
filesize = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CFile::close() {
|
||||
if (iFd >= 0)
|
||||
::close(iFd);
|
||||
|
||||
iFd = -1;
|
||||
mem_file = NULL;
|
||||
filesize = 0;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
int32_t CFile::read(uint8_t *ptr, size_t size) {
|
||||
if (iFd >= 0) {
|
||||
int32_t ret = ::read(iFd, ptr, size);
|
||||
if (ret > 0)
|
||||
pos += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t readsize = size;
|
||||
|
||||
if (readsize > (int64_t) (filesize - pos))
|
||||
readsize = filesize - pos;
|
||||
|
||||
if (readsize <= 0)
|
||||
return readsize;
|
||||
|
||||
if (mem_file != NULL) {
|
||||
memcpy(ptr, mem_file + pos, readsize);
|
||||
pos += readsize;
|
||||
return readsize;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t CFile::write(const uint8_t *ptr, size_t size) {
|
||||
if (iFd >= 0) {
|
||||
size_t done = 0;
|
||||
while (done < size) {
|
||||
int32_t ret = ::write(iFd, ptr, size - done);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
ptr += ret;
|
||||
done += ret;
|
||||
pos += ret;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t CFile::seek(long int offset, int32_t origin) {
|
||||
int32_t ret = 0;
|
||||
int64_t newPos = pos;
|
||||
|
||||
if (origin == SEEK_SET) {
|
||||
newPos = offset;
|
||||
} else if (origin == SEEK_CUR) {
|
||||
newPos += offset;
|
||||
} else if (origin == SEEK_END) {
|
||||
newPos = filesize + offset;
|
||||
}
|
||||
|
||||
if (newPos < 0) {
|
||||
pos = 0;
|
||||
} else {
|
||||
pos = newPos;
|
||||
}
|
||||
|
||||
if (iFd >= 0)
|
||||
ret = ::lseek(iFd, pos, SEEK_SET);
|
||||
|
||||
if (mem_file != NULL) {
|
||||
if (pos > filesize) {
|
||||
pos = filesize;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t CFile::fwrite(const char *format, ...) {
|
||||
char tmp[512];
|
||||
tmp[0] = 0;
|
||||
int32_t result = -1;
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
if ((vsprintf(tmp, format, va) >= 0)) {
|
||||
result = this->write((uint8_t *) tmp, strlen(tmp));
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
71
source/fs/CFile.hpp
Normal file
71
source/fs/CFile.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef CFILE_HPP_
|
||||
#define CFILE_HPP_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <wut_types.h>
|
||||
|
||||
class CFile {
|
||||
public:
|
||||
enum eOpenTypes {
|
||||
ReadOnly,
|
||||
WriteOnly,
|
||||
ReadWrite,
|
||||
Append
|
||||
};
|
||||
|
||||
CFile();
|
||||
|
||||
CFile(const std::string &filepath, eOpenTypes mode);
|
||||
|
||||
CFile(const uint8_t *memory, int32_t memsize);
|
||||
|
||||
virtual ~CFile();
|
||||
|
||||
int32_t open(const std::string &filepath, eOpenTypes mode);
|
||||
|
||||
int32_t open(const uint8_t *memory, int32_t memsize);
|
||||
|
||||
BOOL isOpen() const {
|
||||
if (iFd >= 0)
|
||||
return true;
|
||||
|
||||
if (mem_file)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void close();
|
||||
|
||||
int32_t read(uint8_t *ptr, size_t size);
|
||||
|
||||
int32_t write(const uint8_t *ptr, size_t size);
|
||||
|
||||
int32_t fwrite(const char *format, ...);
|
||||
|
||||
int32_t seek(long int offset, int32_t origin);
|
||||
|
||||
uint64_t tell() {
|
||||
return pos;
|
||||
};
|
||||
|
||||
uint64_t size() {
|
||||
return filesize;
|
||||
};
|
||||
|
||||
void rewind() {
|
||||
this->seek(0, SEEK_SET);
|
||||
};
|
||||
|
||||
protected:
|
||||
int32_t iFd;
|
||||
const uint8_t *mem_file;
|
||||
uint64_t filesize;
|
||||
uint64_t pos;
|
||||
};
|
||||
|
||||
#endif
|
174
source/fs/FSUtils.cpp
Normal file
174
source/fs/FSUtils.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "FSUtils.h"
|
||||
#include "CFile.hpp"
|
||||
#include "utils/logger.h"
|
||||
|
||||
int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) {
|
||||
//! always initialze input
|
||||
*inbuffer = nullptr;
|
||||
if (size)
|
||||
*size = 0;
|
||||
|
||||
int32_t iFd = open(filepath, O_RDONLY);
|
||||
if (iFd < 0)
|
||||
return -1;
|
||||
|
||||
uint32_t filesize = lseek(iFd, 0, SEEK_END);
|
||||
lseek(iFd, 0, SEEK_SET);
|
||||
|
||||
auto *buffer = (uint8_t *) malloc(filesize);
|
||||
if (buffer == nullptr) {
|
||||
close(iFd);
|
||||
return -2;
|
||||
}
|
||||
|
||||
uint32_t blocksize = 0x4000;
|
||||
uint32_t done = 0;
|
||||
int32_t readBytes = 0;
|
||||
|
||||
while (done < filesize) {
|
||||
if (done + blocksize > filesize) {
|
||||
blocksize = filesize - done;
|
||||
}
|
||||
readBytes = read(iFd, buffer + done, blocksize);
|
||||
if (readBytes <= 0)
|
||||
break;
|
||||
done += readBytes;
|
||||
}
|
||||
|
||||
close(iFd);
|
||||
|
||||
if (done != filesize) {
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
return -3;
|
||||
}
|
||||
|
||||
*inbuffer = buffer;
|
||||
|
||||
//! sign is optional input
|
||||
if (size) {
|
||||
*size = filesize;
|
||||
}
|
||||
|
||||
return filesize;
|
||||
}
|
||||
|
||||
int32_t FSUtils::CheckFile(const char *filepath) {
|
||||
if (!filepath)
|
||||
return 0;
|
||||
|
||||
struct stat filestat;
|
||||
|
||||
char dirnoslash[strlen(filepath) + 2];
|
||||
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
|
||||
|
||||
while (dirnoslash[strlen(dirnoslash) - 1] == '/')
|
||||
dirnoslash[strlen(dirnoslash) - 1] = '\0';
|
||||
|
||||
char *notRoot = strrchr(dirnoslash, '/');
|
||||
if (!notRoot) {
|
||||
strcat(dirnoslash, "/");
|
||||
}
|
||||
|
||||
if (stat(dirnoslash, &filestat) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t FSUtils::CreateSubfolder(const char *fullpath) {
|
||||
if (!fullpath)
|
||||
return 0;
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
char dirnoslash[strlen(fullpath) + 1];
|
||||
strcpy(dirnoslash, fullpath);
|
||||
|
||||
int32_t pos = strlen(dirnoslash) - 1;
|
||||
while (dirnoslash[pos] == '/') {
|
||||
dirnoslash[pos] = '\0';
|
||||
pos--;
|
||||
}
|
||||
|
||||
if (CheckFile(dirnoslash)) {
|
||||
return 1;
|
||||
} else {
|
||||
char parentpath[strlen(dirnoslash) + 2];
|
||||
strcpy(parentpath, dirnoslash);
|
||||
char *ptr = strrchr(parentpath, '/');
|
||||
|
||||
if (!ptr) {
|
||||
//!Device root directory (must be with '/')
|
||||
strcat(parentpath, "/");
|
||||
struct stat filestat;
|
||||
if (stat(parentpath, &filestat) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
ptr[0] = '\0';
|
||||
|
||||
result = CreateSubfolder(parentpath);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
if (mkdir(dirnoslash, 0777) == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool FSUtils::copyFile(const std::string &in, const std::string &out) {
|
||||
// Using C++ buffers is **really** slow. Copying in 1023 byte chunks.
|
||||
// Let's do it the old way.
|
||||
size_t size;
|
||||
|
||||
int source = open(in.c_str(), O_RDONLY, 0);
|
||||
int dest = open(out.c_str(), 0x602, 0644);
|
||||
if (source < 0) {
|
||||
return false;
|
||||
}
|
||||
if (dest < 0) {
|
||||
close(source);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bufferSize = 1024 * 1024;
|
||||
char *buf = (char *) malloc(bufferSize);
|
||||
if (buf == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((size = read(source, buf, bufferSize)) > 0) {
|
||||
write(dest, buf, size);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
close(source);
|
||||
close(dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) {
|
||||
CFile file(path, CFile::WriteOnly);
|
||||
if (!file.isOpen()) {
|
||||
return -1;
|
||||
}
|
||||
int32_t written = file.write((const uint8_t *) buffer, size);
|
||||
file.close();
|
||||
return written;
|
||||
}
|
||||
|
17
source/fs/FSUtils.h
Normal file
17
source/fs/FSUtils.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <wut_types.h>
|
||||
#include <string>
|
||||
|
||||
class FSUtils {
|
||||
public:
|
||||
static int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size);
|
||||
|
||||
static int32_t CreateSubfolder(const char *fullpath);
|
||||
|
||||
static int32_t CheckFile(const char *filepath);
|
||||
|
||||
static bool copyFile(const std::string &in, const std::string &out);
|
||||
|
||||
static int32_t saveBufferToFile(const char *path, void *buffer, uint32_t size);
|
||||
};
|
60
source/input/Input.h
Normal file
60
source/input/Input.h
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
class Input {
|
||||
public:
|
||||
//!Constructor
|
||||
Input() = default;
|
||||
|
||||
//!Destructor
|
||||
virtual ~Input() = default;
|
||||
|
||||
enum eButtons {
|
||||
BUTTON_NONE = 0x0000,
|
||||
VPAD_TOUCH = 0x80000000,
|
||||
BUTTON_Z = 0x20000,
|
||||
BUTTON_C = 0x10000,
|
||||
BUTTON_A = 0x8000,
|
||||
BUTTON_B = 0x4000,
|
||||
BUTTON_X = 0x2000,
|
||||
BUTTON_Y = 0x1000,
|
||||
BUTTON_1 = BUTTON_Y,
|
||||
BUTTON_2 = BUTTON_X,
|
||||
BUTTON_LEFT = 0x0800,
|
||||
BUTTON_RIGHT = 0x0400,
|
||||
BUTTON_UP = 0x0200,
|
||||
BUTTON_DOWN = 0x0100,
|
||||
BUTTON_ZL = 0x0080,
|
||||
BUTTON_ZR = 0x0040,
|
||||
BUTTON_L = 0x0020,
|
||||
BUTTON_R = 0x0010,
|
||||
BUTTON_PLUS = 0x0008,
|
||||
BUTTON_MINUS = 0x0004,
|
||||
BUTTON_HOME = 0x0002,
|
||||
BUTTON_SYNC = 0x0001,
|
||||
STICK_R_LEFT = 0x04000000,
|
||||
STICK_R_RIGHT = 0x02000000,
|
||||
STICK_R_UP = 0x01000000,
|
||||
STICK_R_DOWN = 0x00800000,
|
||||
STICK_L_LEFT = 0x40000000,
|
||||
STICK_L_RIGHT = 0x20000000,
|
||||
STICK_L_UP = 0x10000000,
|
||||
STICK_L_DOWN = 0x08000000
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t buttons_h;
|
||||
uint32_t buttons_d;
|
||||
uint32_t buttons_r;
|
||||
bool validPointer;
|
||||
bool touched;
|
||||
float pointerAngle;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
} PadData;
|
||||
|
||||
PadData data{};
|
||||
PadData lastData{};
|
||||
};
|
59
source/input/VPADInput.h
Normal file
59
source/input/VPADInput.h
Normal file
@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2015 Dimok
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include <vpad/input.h>
|
||||
#include "Input.h"
|
||||
|
||||
class VPadInput : public Input {
|
||||
public:
|
||||
//!Constructor
|
||||
VPadInput() {
|
||||
memset(&vpad, 0, sizeof(vpad));
|
||||
}
|
||||
|
||||
//!Destructor
|
||||
~VPadInput() override {}
|
||||
|
||||
bool update(int32_t width, int32_t height) {
|
||||
lastData = data;
|
||||
|
||||
VPADReadError vpadError = VPAD_READ_NO_SAMPLES;
|
||||
VPADRead(VPAD_CHAN_0, &vpad, 1, &vpadError);
|
||||
|
||||
if (vpadError == VPAD_READ_SUCCESS) {
|
||||
data.buttons_r = vpad.release;
|
||||
data.buttons_h = vpad.hold;
|
||||
data.buttons_d = vpad.trigger;
|
||||
data.validPointer = !vpad.tpNormal.validity;
|
||||
data.touched = vpad.tpNormal.touched;
|
||||
|
||||
VPADGetTPCalibratedPoint(VPAD_CHAN_0, &tpCalib, &vpad.tpFiltered1);
|
||||
|
||||
//! calculate the screen offsets
|
||||
data.x = -(width >> 1) + (int32_t) (((float) tpCalib.x / 1280.0f) * (float) width);
|
||||
data.y = -(height >> 1) + (int32_t) (float) height - (((float) tpCalib.y / 720.0f) * (float) height);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
VPADStatus vpad{};
|
||||
VPADTouchData tpCalib{};
|
||||
};
|
108
source/main.cpp
Normal file
108
source/main.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
#include <whb/proc.h>
|
||||
#include <whb/log.h>
|
||||
#include <whb/log_udp.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <iosuhax.h>
|
||||
#include <ntfs.h>
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "utils/WiiUScreen.h"
|
||||
#include "input/VPADInput.h"
|
||||
#include "ApplicationState.h"
|
||||
#include "common/common.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
void initIOSUHax();
|
||||
|
||||
void deInitIOSUHax();
|
||||
|
||||
void main_loop();
|
||||
|
||||
bool sIosuhaxMount = false;
|
||||
|
||||
|
||||
ntfs_md *ntfs_mounts = nullptr;
|
||||
int ntfs_mount_count = 0;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
WHBLogUdpInit();
|
||||
DEBUG_FUNCTION_LINE("Hello from wudump!");
|
||||
WHBProcInit();
|
||||
WiiUScreen::Init();
|
||||
|
||||
initIOSUHax();
|
||||
|
||||
//DEBUG_FUNCTION_LINE("init fat");
|
||||
//fatInitDefault();
|
||||
|
||||
ntfs_mount_count = ntfsMountAll((ntfs_md **) &ntfs_mounts, NTFS_DEFAULT | NTFS_RECOVER);
|
||||
|
||||
for (int i = 0; i < ntfs_mount_count; i++) {
|
||||
DEBUG_FUNCTION_LINE("%s:", ntfs_mounts[i].name);
|
||||
}
|
||||
|
||||
main_loop();
|
||||
|
||||
if (ntfs_mounts != nullptr) {
|
||||
int i = 0;
|
||||
for (i = 0; i < ntfs_mount_count; i++) {
|
||||
ntfsUnmount(ntfs_mounts[i].name, true);
|
||||
}
|
||||
free(ntfs_mounts);
|
||||
}
|
||||
|
||||
deInitIOSUHax();
|
||||
|
||||
WiiUScreen::DeInit();
|
||||
WHBProcShutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main_loop() {
|
||||
DEBUG_FUNCTION_LINE("Creating state");
|
||||
ApplicationState state;
|
||||
VPadInput input;
|
||||
|
||||
DEBUG_FUNCTION_LINE();
|
||||
|
||||
if (gFSAfd < 0 || !sIosuhaxMount) {
|
||||
DEBUG_FUNCTION_LINE();
|
||||
state.setError(ApplicationState::eErrorState::ERROR_IOSUHAX_FAILED);
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("Entering main loop");
|
||||
while (WHBProcIsRunning()) {
|
||||
input.update(1280, 720);
|
||||
state.update(&input);
|
||||
state.render();
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void initIOSUHax() {
|
||||
sIosuhaxMount = false;
|
||||
int res = IOSUHAX_Open(nullptr);
|
||||
if (res < 0) {
|
||||
DEBUG_FUNCTION_LINE("IOSUHAX_open failed");
|
||||
} else {
|
||||
sIosuhaxMount = true;
|
||||
gFSAfd = IOSUHAX_FSA_Open();
|
||||
if (gFSAfd < 0) {
|
||||
DEBUG_FUNCTION_LINE("IOSUHAX_FSA_Open failed");
|
||||
} else {
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("IOSUHAX done");
|
||||
}
|
||||
}
|
||||
|
||||
void deInitIOSUHax() {
|
||||
if (sIosuhaxMount) {
|
||||
if (gFSAfd >= 0) {
|
||||
IOSUHAX_FSA_Close(gFSAfd);
|
||||
}
|
||||
IOSUHAX_Close();
|
||||
}
|
||||
}
|
61
source/utils/FSTUtils.cpp
Normal file
61
source/utils/FSTUtils.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
#include "FSTUtils.h"
|
||||
#include "logger.h"
|
||||
#include <filesystem>
|
||||
|
||||
NodeEntry *FSTUtils::getFSTEntryByFullPath(DirectoryEntry *root, std::string &givenFullPath) {
|
||||
std::string fullPath = givenFullPath;
|
||||
if (strncmp(fullPath.c_str(), "/", 1) != 0) {
|
||||
fullPath = "/" + fullPath;
|
||||
}
|
||||
|
||||
DirectoryEntry *pathOpt = root;
|
||||
std::filesystem::path asPath = fullPath;
|
||||
std::string dirPath = asPath.parent_path().string();
|
||||
if (dirPath != "/") {
|
||||
pathOpt = getFileEntryDir(root, dirPath);
|
||||
}
|
||||
if (pathOpt == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (auto &child: pathOpt->getChildren()) {
|
||||
if (child->getFullPath() == fullPath) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DirectoryEntry *FSTUtils::getFileEntryDir(DirectoryEntry *curEntry, std::string &string) {
|
||||
// We add the "/" at the end so we don't get false results when using the "startWith" function.
|
||||
if (!string.ends_with("/")) {
|
||||
string += "/";
|
||||
}
|
||||
for (auto &curChild: curEntry->getDirChildren()) {
|
||||
std::string compareTo = curChild->getFullPath();
|
||||
if (!compareTo.ends_with("/")) {
|
||||
compareTo += "/";
|
||||
}
|
||||
if (string.starts_with(compareTo)) {
|
||||
if (string == compareTo) {
|
||||
return curChild;
|
||||
}
|
||||
return getFileEntryDir(curChild, string);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SectionEntry *FSTUtils::getSectionEntryForIndex(FST *pFst, uint16_t index) {
|
||||
if (pFst == nullptr || pFst->sectionEntries == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const auto &entry: pFst->sectionEntries->getSections()) {
|
||||
if (entry->sectionNumber == index) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
16
source/utils/FSTUtils.h
Normal file
16
source/utils/FSTUtils.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <WUD/entities/FST/nodeentry/NodeEntry.h>
|
||||
#include <WUD/entities/FST/nodeentry/DirectoryEntry.h>
|
||||
#include <WUD/entities/FST/FST.h>
|
||||
|
||||
class FSTUtils{
|
||||
public:
|
||||
static NodeEntry *getFSTEntryByFullPath(DirectoryEntry *root, std::string &givenFullPath);
|
||||
|
||||
static DirectoryEntry *getFileEntryDir(DirectoryEntry *curEntry, std::string &string);
|
||||
|
||||
static SectionEntry *getSectionEntryForIndex(FST *pFst, uint16_t index);
|
||||
};
|
||||
|
48
source/utils/ScreenUtils.cpp
Normal file
48
source/utils/ScreenUtils.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2018 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <coreinit/screen.h>
|
||||
#include "ScreenUtils.h"
|
||||
|
||||
void ScreenUtils::printTextOnScreen(ConsoleScreenID screen, int x, int y, const char *msg) {
|
||||
if (!msg) {
|
||||
return;
|
||||
}
|
||||
if (screen != CONSOLE_SCREEN_DRC) { // Draw TV if it's not DRC exclusive.
|
||||
OSScreenPutFontEx(SCREEN_TV, x, y, msg);
|
||||
}
|
||||
if (screen != CONSOLE_SCREEN_TV) { // Draw DRC if it's not TV exclusive.
|
||||
OSScreenPutFontEx(SCREEN_DRC, x, y, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenUtils::OSScreenClear(ConsoleScreenID screen, uint32_t color) {
|
||||
if (screen != CONSOLE_SCREEN_DRC) { // Clear TV if it's not DRC exclusive.
|
||||
OSScreenClearBufferEx(SCREEN_TV, color);
|
||||
}
|
||||
if (screen != CONSOLE_SCREEN_TV) { // Clear DRC if it's not TV exclusive.
|
||||
OSScreenClearBufferEx(SCREEN_DRC, color);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenUtils::flipBuffers(ConsoleScreenID screen) {
|
||||
if (screen != CONSOLE_SCREEN_DRC) { // Flip TV buffer if it's not DRC exclusive.
|
||||
OSScreenFlipBuffersEx(SCREEN_TV);
|
||||
}
|
||||
if (screen != CONSOLE_SCREEN_TV) { // Flip DRC buffer if it's not TV exclusive.
|
||||
OSScreenFlipBuffersEx(SCREEN_DRC);
|
||||
}
|
||||
}
|
55
source/utils/ScreenUtils.h
Normal file
55
source/utils/ScreenUtils.h
Normal file
@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2018-2020 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
//! Defines the ID of a display usable with OSScreen.
|
||||
typedef enum ConsoleScreenID {
|
||||
//! Represents the TV connected to the system.
|
||||
CONSOLE_SCREEN_TV = 0,
|
||||
//! Represents the screen in the DRC (gamepad).
|
||||
CONSOLE_SCREEN_DRC = 1,
|
||||
//! Represents both screens
|
||||
CONSOLE_SCREEN_BOTH = 2,
|
||||
} ConsoleScreenID;
|
||||
|
||||
class ScreenUtils {
|
||||
public:
|
||||
/**
|
||||
Clears the screen for the given screens
|
||||
\param screen defines on which screens should be printed
|
||||
\param x defines the x position (character position) where the text should be printed
|
||||
\param y defines on which line the text should be printed
|
||||
\param msg C string that contains the text to be printed.
|
||||
**/
|
||||
static void printTextOnScreen(ConsoleScreenID screen, int x, int y, const char *msg);
|
||||
|
||||
/**
|
||||
Clears the screen for the given screens
|
||||
\param screen defines which screens should be cleared
|
||||
**/
|
||||
static void OSScreenClear(ConsoleScreenID screen, uint32_t i);
|
||||
|
||||
/**
|
||||
Flips the buffer for the given screens
|
||||
\param screen defines which screens should be flipped.
|
||||
**/
|
||||
static void flipBuffers(ConsoleScreenID screen);
|
||||
|
||||
private:
|
||||
ScreenUtils() = default;
|
||||
~ScreenUtils() = default;
|
||||
};
|
234
source/utils/StringTools.cpp
Normal file
234
source/utils/StringTools.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
* for WiiXplorer 2010
|
||||
***************************************************************************/
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <strings.h>
|
||||
#include <wut_types.h>
|
||||
#include <stdio.h>
|
||||
#include "StringTools.h"
|
||||
|
||||
|
||||
BOOL StringTools::EndsWith(const std::string &a, const std::string &b) {
|
||||
if (b.size() > a.size())
|
||||
return false;
|
||||
return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
|
||||
}
|
||||
|
||||
const char *StringTools::byte_to_binary(int32_t x) {
|
||||
static char b[9];
|
||||
b[0] = '\0';
|
||||
|
||||
int32_t z;
|
||||
for (z = 128; z > 0; z >>= 1) {
|
||||
strcat(b, ((x & z) == z) ? "1" : "0");
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
std::string StringTools::removeCharFromString(std::string &input, char toBeRemoved) {
|
||||
std::string output = input;
|
||||
size_t position;
|
||||
while (1) {
|
||||
position = output.find(toBeRemoved);
|
||||
if (position == std::string::npos)
|
||||
break;
|
||||
output.erase(position, 1);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
const char *StringTools::fmt(const char *format, ...) {
|
||||
static char strChar[512];
|
||||
strChar[0] = 0;
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
if ((vsprintf(strChar, format, va) >= 0)) {
|
||||
va_end(va);
|
||||
return (const char *) strChar;
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const wchar_t *StringTools::wfmt(const char *format, ...) {
|
||||
static char tmp[512];
|
||||
static wchar_t strWChar[512];
|
||||
strWChar[0] = 0;
|
||||
tmp[0] = 0;
|
||||
|
||||
if (!format)
|
||||
return (const wchar_t *) strWChar;
|
||||
|
||||
if (strcmp(format, "") == 0)
|
||||
return (const wchar_t *) strWChar;
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
if ((vsprintf(tmp, format, va) >= 0)) {
|
||||
int32_t bt;
|
||||
int32_t strlength = strlen(tmp);
|
||||
bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512);
|
||||
|
||||
if (bt > 0) {
|
||||
strWChar[bt] = 0;
|
||||
return (const wchar_t *) strWChar;
|
||||
}
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t StringTools::strprintf(std::string &str, const char *format, ...) {
|
||||
static char tmp[512];
|
||||
tmp[0] = 0;
|
||||
int32_t result = 0;
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
if ((vsprintf(tmp, format, va) >= 0)) {
|
||||
str = tmp;
|
||||
result = str.size();
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string StringTools::strfmt(const char *format, ...) {
|
||||
std::string str;
|
||||
static char tmp[512];
|
||||
tmp[0] = 0;
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
if ((vsprintf(tmp, format, va) >= 0)) {
|
||||
str = tmp;
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
BOOL StringTools::char2wchar_t(const char *strChar, wchar_t *dest) {
|
||||
if (!strChar || !dest)
|
||||
return false;
|
||||
|
||||
int32_t bt;
|
||||
bt = mbstowcs(dest, strChar, strlen(strChar));
|
||||
if (bt > 0) {
|
||||
dest[bt] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t StringTools::strtokcmp(const char *string, const char *compare, const char *separator) {
|
||||
if (!string || !compare)
|
||||
return -1;
|
||||
|
||||
char TokCopy[512];
|
||||
strncpy(TokCopy, compare, sizeof(TokCopy));
|
||||
TokCopy[511] = '\0';
|
||||
|
||||
char *strTok = strtok(TokCopy, separator);
|
||||
|
||||
while (strTok != NULL) {
|
||||
if (strcasecmp(string, strTok) == 0) {
|
||||
return 0;
|
||||
}
|
||||
strTok = strtok(NULL, separator);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t StringTools::strextcmp(const char *string, const char *extension, char seperator) {
|
||||
if (!string || !extension)
|
||||
return -1;
|
||||
|
||||
char *ptr = strrchr(string, seperator);
|
||||
if (!ptr)
|
||||
return -1;
|
||||
|
||||
return strcasecmp(ptr + 1, extension);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> StringTools::stringSplit(const std::string &inValue, const std::string &splitter) {
|
||||
std::string value = inValue;
|
||||
std::vector<std::string> result;
|
||||
while (true) {
|
||||
uint32_t index = value.find(splitter);
|
||||
if (index == std::string::npos) {
|
||||
result.push_back(value);
|
||||
break;
|
||||
}
|
||||
std::string first = value.substr(0, index);
|
||||
result.push_back(first);
|
||||
if (index + splitter.size() == value.length()) {
|
||||
result.push_back("");
|
||||
break;
|
||||
}
|
||||
if (index + splitter.size() > value.length()) {
|
||||
break;
|
||||
}
|
||||
value = value.substr(index + splitter.size(), value.length());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool StringTools::findStringIC(const std::string &strHaystack, const std::string &strNeedle) {
|
||||
auto it = std::search(
|
||||
strHaystack.begin(), strHaystack.end(),
|
||||
strNeedle.begin(), strNeedle.end(),
|
||||
[](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }
|
||||
);
|
||||
return (it != strHaystack.end());
|
||||
}
|
||||
|
||||
bool StringTools::replace(std::string &str, const std::string &from, const std::string &to) {
|
||||
size_t start_pos = str.find(from);
|
||||
if (start_pos == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
str.replace(start_pos, from.length(), to);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool StringTools::strCompareIC(const std::string &str1, const std::string &str2) {
|
||||
return str1.size() == str2.size() && std::equal(str1.begin(), str1.end(), str2.begin(), [](auto a, auto b) { return std::tolower(a) == std::tolower(b); });
|
||||
}
|
95
source/utils/StringTools.h
Normal file
95
source/utils/StringTools.h
Normal file
@ -0,0 +1,95 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
* for WiiXplorer 2010
|
||||
***************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <wut_types.h>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
class StringTools {
|
||||
public:
|
||||
static BOOL EndsWith(const std::string &a, const std::string &b);
|
||||
|
||||
static const char *byte_to_binary(int32_t x);
|
||||
|
||||
static std::string removeCharFromString(std::string &input, char toBeRemoved);
|
||||
|
||||
static const char *fmt(const char *format, ...);
|
||||
|
||||
static const wchar_t *wfmt(const char *format, ...);
|
||||
|
||||
static int32_t strprintf(std::string &str, const char *format, ...);
|
||||
|
||||
static std::string strfmt(const char *format, ...);
|
||||
|
||||
static BOOL char2wchar_t(const char *src, wchar_t *dest);
|
||||
|
||||
static int32_t strtokcmp(const char *string, const char *compare, const char *separator);
|
||||
|
||||
static int32_t strextcmp(const char *string, const char *extension, char seperator);
|
||||
|
||||
static const char *FullpathToFilename(const char *path) {
|
||||
if (!path)
|
||||
return path;
|
||||
|
||||
const char *ptr = path;
|
||||
const char *Filename = ptr;
|
||||
|
||||
while (*ptr != '\0') {
|
||||
if (ptr[0] == '/' && ptr[1] != '\0')
|
||||
Filename = ptr + 1;
|
||||
|
||||
++ptr;
|
||||
}
|
||||
|
||||
return Filename;
|
||||
}
|
||||
|
||||
static void RemoveDoubleSlashs(std::string &str) {
|
||||
uint32_t length = str.size();
|
||||
|
||||
//! clear path of double slashes
|
||||
for (uint32_t i = 1; i < length; ++i) {
|
||||
if (str[i - 1] == '/' && str[i] == '/') {
|
||||
str.erase(i, 1);
|
||||
i--;
|
||||
length--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> stringSplit(const std::string &value, const std::string &splitter);
|
||||
|
||||
// https://stackoverflow.com/a/19839371
|
||||
static bool findStringIC(const std::string &strHaystack, const std::string &strNeedle);
|
||||
|
||||
// https://stackoverflow.com/a/3418285
|
||||
static bool replace(std::string& str, const std::string& from, const std::string& to);
|
||||
|
||||
static bool strCompareIC(const std::string &str1, const std::string &str2);
|
||||
};
|
196
source/utils/TinySHA1.hpp
Normal file
196
source/utils/TinySHA1.hpp
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
*
|
||||
* TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based
|
||||
* on the implementation in boost::uuid::details.
|
||||
*
|
||||
* SHA1 Wikipedia Page: http://en.wikipedia.org/wiki/SHA-1
|
||||
*
|
||||
* Copyright (c) 2012-22 SAURAV MOHAPATRA <mohaps@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef _TINY_SHA1_HPP_
|
||||
#define _TINY_SHA1_HPP_
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdint.h>
|
||||
namespace sha1
|
||||
{
|
||||
class SHA1
|
||||
{
|
||||
public:
|
||||
typedef uint32_t digest32_t[5];
|
||||
typedef uint8_t digest8_t[20];
|
||||
inline static uint32_t LeftRotate(uint32_t value, size_t count) {
|
||||
return (value << count) ^ (value >> (32-count));
|
||||
}
|
||||
SHA1(){ reset(); }
|
||||
virtual ~SHA1() {}
|
||||
SHA1(const SHA1& s) { *this = s; }
|
||||
const SHA1& operator = (const SHA1& s) {
|
||||
memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
|
||||
memcpy(m_block, s.m_block, 64);
|
||||
m_blockByteIndex = s.m_blockByteIndex;
|
||||
m_byteCount = s.m_byteCount;
|
||||
return *this;
|
||||
}
|
||||
SHA1& reset() {
|
||||
m_digest[0] = 0x67452301;
|
||||
m_digest[1] = 0xEFCDAB89;
|
||||
m_digest[2] = 0x98BADCFE;
|
||||
m_digest[3] = 0x10325476;
|
||||
m_digest[4] = 0xC3D2E1F0;
|
||||
m_blockByteIndex = 0;
|
||||
m_byteCount = 0;
|
||||
return *this;
|
||||
}
|
||||
SHA1& processByte(uint8_t octet) {
|
||||
this->m_block[this->m_blockByteIndex++] = octet;
|
||||
++this->m_byteCount;
|
||||
if(m_blockByteIndex == 64) {
|
||||
this->m_blockByteIndex = 0;
|
||||
processBlock();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
SHA1& processBlock(const void* const start, const void* const end) {
|
||||
const uint8_t* begin = static_cast<const uint8_t*>(start);
|
||||
const uint8_t* finish = static_cast<const uint8_t*>(end);
|
||||
while(begin != finish) {
|
||||
processByte(*begin);
|
||||
begin++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
SHA1& processBytes(const void* const data, size_t len) {
|
||||
const uint8_t* block = static_cast<const uint8_t*>(data);
|
||||
processBlock(block, block + len);
|
||||
return *this;
|
||||
}
|
||||
const uint32_t* getDigest(digest32_t digest) {
|
||||
size_t bitCount = this->m_byteCount * 8;
|
||||
processByte(0x80);
|
||||
if (this->m_blockByteIndex > 56) {
|
||||
while (m_blockByteIndex != 0) {
|
||||
processByte(0);
|
||||
}
|
||||
while (m_blockByteIndex < 56) {
|
||||
processByte(0);
|
||||
}
|
||||
} else {
|
||||
while (m_blockByteIndex < 56) {
|
||||
processByte(0);
|
||||
}
|
||||
}
|
||||
processByte(0);
|
||||
processByte(0);
|
||||
processByte(0);
|
||||
processByte(0);
|
||||
processByte( static_cast<unsigned char>((bitCount>>24) & 0xFF));
|
||||
processByte( static_cast<unsigned char>((bitCount>>16) & 0xFF));
|
||||
processByte( static_cast<unsigned char>((bitCount>>8 ) & 0xFF));
|
||||
processByte( static_cast<unsigned char>((bitCount) & 0xFF));
|
||||
|
||||
memcpy(digest, m_digest, 5 * sizeof(uint32_t));
|
||||
return digest;
|
||||
}
|
||||
const uint8_t* getDigestBytes(digest8_t digest) {
|
||||
digest32_t d32;
|
||||
getDigest(d32);
|
||||
size_t di = 0;
|
||||
digest[di++] = ((d32[0] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[0] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[0] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[0]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[1] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[1] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[1] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[1]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[2] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[2] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[2] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[2]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[3] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[3] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[3] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[3]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[4] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[4] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[4] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[4]) & 0xFF);
|
||||
return digest;
|
||||
}
|
||||
|
||||
protected:
|
||||
void processBlock() {
|
||||
uint32_t w[80];
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
w[i] = (m_block[i*4 + 0] << 24);
|
||||
w[i] |= (m_block[i*4 + 1] << 16);
|
||||
w[i] |= (m_block[i*4 + 2] << 8);
|
||||
w[i] |= (m_block[i*4 + 3]);
|
||||
}
|
||||
for (size_t i = 16; i < 80; i++) {
|
||||
w[i] = LeftRotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
|
||||
}
|
||||
|
||||
uint32_t a = m_digest[0];
|
||||
uint32_t b = m_digest[1];
|
||||
uint32_t c = m_digest[2];
|
||||
uint32_t d = m_digest[3];
|
||||
uint32_t e = m_digest[4];
|
||||
|
||||
for (std::size_t i=0; i<80; ++i) {
|
||||
uint32_t f = 0;
|
||||
uint32_t k = 0;
|
||||
|
||||
if (i<20) {
|
||||
f = (b & c) | (~b & d);
|
||||
k = 0x5A827999;
|
||||
} else if (i<40) {
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ED9EBA1;
|
||||
} else if (i<60) {
|
||||
f = (b & c) | (b & d) | (c & d);
|
||||
k = 0x8F1BBCDC;
|
||||
} else {
|
||||
f = b ^ c ^ d;
|
||||
k = 0xCA62C1D6;
|
||||
}
|
||||
uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
|
||||
e = d;
|
||||
d = c;
|
||||
c = LeftRotate(b, 30);
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
m_digest[0] += a;
|
||||
m_digest[1] += b;
|
||||
m_digest[2] += c;
|
||||
m_digest[3] += d;
|
||||
m_digest[4] += e;
|
||||
}
|
||||
private:
|
||||
digest32_t m_digest;
|
||||
uint8_t m_block[64];
|
||||
size_t m_blockByteIndex;
|
||||
size_t m_byteCount;
|
||||
};
|
||||
}
|
||||
#endif
|
94
source/utils/WiiUScreen.cpp
Normal file
94
source/utils/WiiUScreen.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "WiiUScreen.h"
|
||||
#include "ScreenUtils.h"
|
||||
#include <coreinit/memdefaultheap.h>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
void *WiiUScreen::sBufferTV = nullptr;
|
||||
void *WiiUScreen::sBufferDRC = nullptr;
|
||||
uint32_t WiiUScreen::sBufferSizeTV = 0;
|
||||
uint32_t WiiUScreen::sBufferSizeDRC = 0;
|
||||
bool WiiUScreen::sConsoleHasForeground = true;
|
||||
uint32_t WiiUScreen::consoleColor = 0x041F60FF;
|
||||
uint32_t WiiUScreen::consoleCursorY = 0;
|
||||
|
||||
|
||||
uint32_t WiiUScreen::ProcCallbackAcquired(void *context) {
|
||||
MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||
if (sBufferSizeTV) {
|
||||
sBufferTV = MEMAllocFromFrmHeapEx(heap, sBufferSizeTV, 4);
|
||||
}
|
||||
|
||||
if (sBufferSizeDRC) {
|
||||
sBufferDRC = MEMAllocFromFrmHeapEx(heap, sBufferSizeDRC, 4);
|
||||
}
|
||||
|
||||
sConsoleHasForeground = true;
|
||||
OSScreenSetBufferEx(SCREEN_TV, sBufferTV);
|
||||
OSScreenSetBufferEx(SCREEN_DRC, sBufferDRC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t WiiUScreen::ProcCallbackReleased(void *context) {
|
||||
MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||
MEMFreeByStateToFrmHeap(heap, CONSOLE_FRAME_HEAP_TAG);
|
||||
sConsoleHasForeground = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WiiUScreen::Init() {
|
||||
OSScreenInit();
|
||||
sBufferSizeTV = OSScreenGetBufferSizeEx(SCREEN_TV);
|
||||
sBufferSizeDRC = OSScreenGetBufferSizeEx(SCREEN_DRC);
|
||||
|
||||
WiiUScreen::ProcCallbackAcquired(nullptr);
|
||||
OSScreenEnableEx(SCREEN_TV, 1);
|
||||
OSScreenEnableEx(SCREEN_DRC, 1);
|
||||
|
||||
ScreenUtils::OSScreenClear(CONSOLE_SCREEN_BOTH, WiiUScreen::consoleColor);
|
||||
|
||||
ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, WiiUScreen::ProcCallbackAcquired, nullptr, 100);
|
||||
ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, WiiUScreen::ProcCallbackReleased, nullptr, 100);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WiiUScreen::DeInit() {
|
||||
if (sConsoleHasForeground) {
|
||||
OSScreenShutdown();
|
||||
WiiUScreen::ProcCallbackReleased(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void WiiUScreen::drawLinef(const char *fmt, ...) {
|
||||
char *buf = (char *) MEMAllocFromDefaultHeapEx(PRINTF_BUFFER_LENGTH, 4);
|
||||
va_list va;
|
||||
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(va, fmt);
|
||||
vsnprintf(buf, PRINTF_BUFFER_LENGTH, fmt, va);
|
||||
|
||||
WiiUScreen::drawLine(buf);
|
||||
|
||||
MEMFreeToDefaultHeap(buf);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void WiiUScreen::drawLine() {
|
||||
WiiUScreen::drawLine("");
|
||||
}
|
||||
|
||||
void WiiUScreen::drawLine(const char *msg) {
|
||||
ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_BOTH, 0, consoleCursorY++, msg);
|
||||
}
|
||||
|
||||
void WiiUScreen::flipBuffers() {
|
||||
ScreenUtils::flipBuffers(CONSOLE_SCREEN_BOTH);
|
||||
}
|
||||
|
||||
void WiiUScreen::clearScreen() {
|
||||
ScreenUtils::OSScreenClear(CONSOLE_SCREEN_BOTH, WiiUScreen::consoleColor);
|
||||
consoleCursorY = 0;
|
||||
}
|
53
source/utils/WiiUScreen.h
Normal file
53
source/utils/WiiUScreen.h
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include <whb/log.h>
|
||||
#include <whb/log_console.h>
|
||||
|
||||
#include <coreinit/memheap.h>
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/memfrmheap.h>
|
||||
#include <coreinit/memory.h>
|
||||
#include <coreinit/screen.h>
|
||||
#include <proc_ui/procui.h>
|
||||
#include <cstring>
|
||||
#include "utils/logger.h"
|
||||
|
||||
#define NUM_LINES (16)
|
||||
#define LINE_LENGTH (128)
|
||||
#define CONSOLE_FRAME_HEAP_TAG (0x000DECAF)
|
||||
#define PRINTF_BUFFER_LENGTH 2048
|
||||
|
||||
#define DEBUG_CONSOLE_LOG(FMT, ARGS...)do { \
|
||||
DEBUG_FUNCTION_LINE(FMT, ## ARGS); \
|
||||
WiiUScreen::drawLinef(FMT, ## ARGS); \
|
||||
} while (0)
|
||||
|
||||
|
||||
class WiiUScreen {
|
||||
|
||||
public:
|
||||
static uint32_t ProcCallbackAcquired(void *context);
|
||||
|
||||
static uint32_t ProcCallbackReleased(void *context);
|
||||
|
||||
static bool Init();
|
||||
|
||||
static void DeInit();
|
||||
|
||||
static void drawLinef(const char *fmt, ...);
|
||||
|
||||
static void drawLine(const char *fmt);
|
||||
|
||||
static void drawLine();
|
||||
|
||||
static void flipBuffers();
|
||||
|
||||
static void clearScreen();
|
||||
|
||||
private:
|
||||
static void *sBufferTV, *sBufferDRC;
|
||||
static uint32_t sBufferSizeTV, sBufferSizeDRC;
|
||||
static bool sConsoleHasForeground;
|
||||
static uint32_t consoleColor;
|
||||
static uint32_t consoleCursorY;
|
||||
};
|
36
source/utils/blocksize/AddressInBlocks.h
Normal file
36
source/utils/blocksize/AddressInBlocks.h
Normal file
@ -0,0 +1,36 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "BlockSize.h"
|
||||
|
||||
class AddressInBlocks {
|
||||
public:
|
||||
explicit AddressInBlocks(const BlockSize &blockSize, uint32_t pValue) : blockSize(blockSize) {
|
||||
value = pValue;
|
||||
}
|
||||
|
||||
AddressInBlocks() = default;
|
||||
|
||||
[[nodiscard]] virtual uint64_t getAddressInBytes() const {
|
||||
return (uint64_t) value * blockSize.blockSize;
|
||||
}
|
||||
|
||||
BlockSize blockSize;
|
||||
uint32_t value{};
|
||||
};
|
41
source/utils/blocksize/AddressInDiscBlocks.h
Normal file
41
source/utils/blocksize/AddressInDiscBlocks.h
Normal file
@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "AddressInBlocks.h"
|
||||
#include "DiscBlockSize.h"
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
class AddressInDiscBlocks : public AddressInBlocks {
|
||||
|
||||
public:
|
||||
AddressInDiscBlocks(const DiscBlockSize &blockSize, uint32_t value) : AddressInBlocks(blockSize, value) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct less<AddressInDiscBlocks> {
|
||||
bool operator()(const AddressInDiscBlocks &lhs, const AddressInDiscBlocks &rhs) const {
|
||||
return lhs.getAddressInBytes() < rhs.getAddressInBytes();
|
||||
}
|
||||
};
|
||||
}
|
28
source/utils/blocksize/AddressInVolumeBlocks.h
Normal file
28
source/utils/blocksize/AddressInVolumeBlocks.h
Normal file
@ -0,0 +1,28 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "VolumeBlockSize.h"
|
||||
#include "AddressInBlocks.h"
|
||||
|
||||
class AddressInVolumeBlocks : public AddressInBlocks {
|
||||
|
||||
public:
|
||||
AddressInVolumeBlocks() = default;
|
||||
AddressInVolumeBlocks(const VolumeBlockSize &pBlockSize, uint32_t pValue) : AddressInBlocks(pBlockSize, pValue) {
|
||||
}
|
||||
};
|
30
source/utils/blocksize/BlockSize.h
Normal file
30
source/utils/blocksize/BlockSize.h
Normal file
@ -0,0 +1,30 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class BlockSize {
|
||||
public:
|
||||
BlockSize() = default;
|
||||
|
||||
explicit BlockSize(uint32_t blockSize) {
|
||||
this->blockSize = blockSize;
|
||||
}
|
||||
|
||||
uint32_t blockSize {};
|
||||
};
|
29
source/utils/blocksize/DiscBlockSize.h
Normal file
29
source/utils/blocksize/DiscBlockSize.h
Normal file
@ -0,0 +1,29 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "BlockSize.h"
|
||||
|
||||
class DiscBlockSize : public BlockSize {
|
||||
|
||||
public:
|
||||
DiscBlockSize() = default;
|
||||
explicit DiscBlockSize(uint32_t blockSize) : BlockSize(blockSize) {
|
||||
|
||||
}
|
||||
};
|
27
source/utils/blocksize/SectionAddress.h
Normal file
27
source/utils/blocksize/SectionAddress.h
Normal file
@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "AddressInBlocks.h"
|
||||
#include "SectionBlockSize.h"
|
||||
|
||||
class SectionAddress : public AddressInBlocks {
|
||||
|
||||
public:
|
||||
SectionAddress(const SectionBlockSize &pBlockSize, uint32_t pValue) : AddressInBlocks(pBlockSize, pValue) {
|
||||
}
|
||||
};
|
29
source/utils/blocksize/SectionBlockSize.h
Normal file
29
source/utils/blocksize/SectionBlockSize.h
Normal file
@ -0,0 +1,29 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "BlockSize.h"
|
||||
|
||||
class SectionBlockSize : public BlockSize {
|
||||
|
||||
public:
|
||||
SectionBlockSize() = default;
|
||||
|
||||
explicit SectionBlockSize(uint32_t pBlockSize) : BlockSize(pBlockSize) {
|
||||
}
|
||||
};
|
37
source/utils/blocksize/SizeInBlocks.h
Normal file
37
source/utils/blocksize/SizeInBlocks.h
Normal file
@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016-2021 Maschell
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include "BlockSize.h"
|
||||
|
||||
class SizeInBlocks {
|
||||
public:
|
||||
SizeInBlocks() = default;
|
||||
|
||||
explicit SizeInBlocks(const BlockSize &blockSize, uint32_t pValue) : blockSize(blockSize) {
|
||||
value = pValue;
|
||||
}
|
||||
|
||||
virtual uint64_t getSizeInBytes() {
|
||||
return (uint64_t) value * blockSize.blockSize;
|
||||
}
|
||||
|
||||
BlockSize blockSize;
|
||||
uint64_t value{};
|
||||
};
|
14
source/utils/blocksize/SizeInVolumeBlocks.h
Normal file
14
source/utils/blocksize/SizeInVolumeBlocks.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "VolumeBlockSize.h"
|
||||
#include "SizeInBlocks.h"
|
||||
|
||||
class SizeInVolumeBlocks : public SizeInBlocks {
|
||||
|
||||
public:
|
||||
SizeInVolumeBlocks() = default;
|
||||
|
||||
SizeInVolumeBlocks(const VolumeBlockSize &blockSize, uint32_t value) : SizeInBlocks(blockSize, value) {
|
||||
|
||||
}
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user