From 05aea5756b26cbf16f1b30dcc3b1db7e3413d930 Mon Sep 17 00:00:00 2001 From: Maschell Date: Tue, 26 Jul 2022 09:24:06 +0200 Subject: [PATCH] Various improvements including: - Display name/type of the partition - Block home menu when launching via HBL - Use libmocha instead of libiosuhax, which should result in a small performance boost - Improve logging - Improve memory management - Add option to abort dumps - Slightly improve .wux handling --- Dockerfile | 4 +- Makefile | 19 +- README.md | 18 +- source/ApplicationState.h | 12 +- source/GMPartitionsDumperState.cpp | 87 ++++++-- source/GMPartitionsDumperState.h | 7 +- source/WUD/DefaultNUSDataProcessor.cpp | 24 +- source/WUD/DefaultNUSDataProcessor.h | 2 +- source/WUD/DiscReader.cpp | 56 +++-- source/WUD/DiscReader.h | 9 +- source/WUD/DiscReaderDiscDrive.cpp | 75 ++++--- source/WUD/DiscReaderDiscDrive.h | 8 +- source/WUD/NUSDataProcessor.h | 2 +- source/WUD/NUSDataProviderWUD.cpp | 46 ++-- source/WUD/NUSDataProviderWUD.h | 5 +- source/WUD/NUSDecryption.cpp | 2 +- source/WUD/NUSDecryption.h | 4 +- source/WUD/NUSTitle.cpp | 90 ++++++-- source/WUD/NUSTitle.h | 31 ++- source/WUD/Ticket.cpp | 12 +- source/WUD/Ticket.h | 2 +- .../WUD/content/WiiUContentsInformation.cpp | 14 +- source/WUD/content/WiiUContentsInformation.h | 2 +- source/WUD/content/WiiUDiscContentsHeader.cpp | 25 ++- source/WUD/content/WiiUDiscContentsHeader.h | 2 +- .../content/partitions/WiiUDataPartition.cpp | 4 +- .../content/partitions/WiiUDataPartition.h | 8 +- .../content/partitions/WiiUGMPartition.cpp | 14 +- .../WUD/content/partitions/WiiUGMPartition.h | 31 ++- .../WUD/content/partitions/WiiUPartition.cpp | 46 ++-- source/WUD/content/partitions/WiiUPartition.h | 15 +- .../WUD/content/partitions/WiiUPartitions.cpp | 194 +++++++++-------- .../WUD/content/partitions/WiiUPartitions.h | 6 +- .../partitions/volumes/H3HashArray.cpp | 13 +- .../content/partitions/volumes/H3HashArray.h | 3 +- .../partitions/volumes/VolumeHeader.cpp | 46 ++-- .../content/partitions/volumes/VolumeHeader.h | 8 +- source/WUD/entities/FST/FST.cpp | 12 +- source/WUD/entities/FST/header/FSTHeader.cpp | 2 +- .../entities/FST/nodeentry/DirectoryEntry.cpp | 4 +- .../WUD/entities/FST/nodeentry/FileEntry.cpp | 4 +- .../entities/FST/nodeentry/NodeEntries.cpp | 8 +- .../WUD/entities/FST/nodeentry/NodeEntry.cpp | 12 +- .../WUD/entities/FST/nodeentry/RootEntry.cpp | 4 +- .../FST/sectionentry/SectionEntries.cpp | 3 +- .../entities/FST/stringtable/StringTable.cpp | 4 +- source/WUD/entities/TMD/TitleMetaData.cpp | 14 +- source/WUD/entities/TMD/TitleMetaData.h | 5 +- source/WUD/header/WiiUDiscHeader.cpp | 24 +- source/WUD/header/WiiUDiscHeader.h | 8 +- source/WUD/header/WiiUDiscId.cpp | 24 +- source/WUD/header/WiiUDiscId.h | 4 +- ...rDiscId.cpp => WiiUManufacturerDiscId.cpp} | 16 +- ...actorDiscId.h => WiiUManufacturerDiscId.h} | 8 +- source/WUDDumperState.cpp | 71 ++++-- source/WUDDumperState.h | 1 + source/common/common.cpp | 11 +- source/common/common.h | 6 +- source/fs/FSUtils.cpp | 5 +- source/fs/WUXFileWriter.cpp | 20 +- source/fs/WUXFileWriter.h | 2 +- source/fs/WriteOnlyFileWithCache.cpp | 12 +- source/main.cpp | 91 ++++---- source/utils/ScreenUtils.cpp | 2 +- source/utils/ScreenUtils.h | 3 +- source/utils/StringTools.cpp | 206 +----------------- source/utils/StringTools.h | 78 ++----- source/utils/WUDUtils.cpp | 15 ++ source/utils/WUDUtils.h | 11 + source/utils/WiiUScreen.cpp | 4 +- source/utils/WiiUScreen.h | 4 +- source/utils/logger.c | 38 ++++ source/utils/logger.h | 56 ++++- source/utils/utils.h | 19 +- 74 files changed, 930 insertions(+), 827 deletions(-) rename source/WUD/header/{WiiUManufactorDiscId.cpp => WiiUManufacturerDiscId.cpp} (60%) rename source/WUD/header/{WiiUManufactorDiscId.h => WiiUManufacturerDiscId.h} (76%) create mode 100644 source/utils/WUDUtils.cpp create mode 100644 source/utils/WUDUtils.h create mode 100644 source/utils/logger.c diff --git a/Dockerfile b/Dockerfile index aa0e6be..ccf6ee6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM wiiuenv/devkitppc:20220724 -COPY --from=wiiuenv/libiosuhax:20220523 /artifacts $DEVKITPRO -COPY --from=wiiuenv/libntfs:20201210 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libntfs:20220726 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libmocha:20220726 /artifacts $DEVKITPRO WORKDIR project \ No newline at end of file diff --git a/Makefile b/Makefile index 7853ab2..0e4f4b7 100644 --- a/Makefile +++ b/Makefile @@ -51,12 +51,12 @@ SOURCES := source \ source/WUD/entities/TMD DATA := data -INCLUDES := include source +INCLUDES := source #------------------------------------------------------------------------------- # options for code generation #------------------------------------------------------------------------------- -CFLAGS := -g -Wall -O0 -ffunction-sections \ +CFLAGS := -g -Wall -O2 -ffunction-sections \ $(MACHDEP) CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ @@ -66,7 +66,7 @@ CXXFLAGS := $(CFLAGS) -std=gnu++20 ASFLAGS := -g $(ARCH) LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -LIBS := -lwut -lntfs -liosuhax +LIBS := -lwut -lntfs -lmocha #------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level @@ -74,6 +74,17 @@ LIBS := -lwut -lntfs -liosuhax #------------------------------------------------------------------------------- LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUT_ROOT)/usr +ifeq ($(DEBUG),1) +export DEBUG=1 +CXXFLAGS += -DDEBUG -g +CFLAGS += -DDEBUG -g +endif + +ifeq ($(DEBUG),VERBOSE) +export DEBUG=VERBOSE +CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g +CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g +endif #------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional @@ -178,6 +189,8 @@ $(OUTPUT).elf : $(OFILES) $(OFILES_SRC) : $(HFILES_BIN) +-include $(DEPENDS) + #------------------------------------------------------------------------------- endif #------------------------------------------------------------------------------- diff --git a/README.md b/README.md index d14c4de..11288a1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Inspired by [wudump](https://github.com/FIX94/wudump) from FIX94. Features: - Dump a Wii U Disc in WUD (uncompressed) or [WUX](https://gbatemp.net/threads/wii-u-image-wud-compression-tool.397901/) (loseless compression) format (including the game.key) -- Dump the GM Partitions (Game, Updates, DLCs) of an WiiU Disc as *.app,*.h3, .tmd, .tik, .cert files +- Dump the GM Partitions (Game, Updates, DLCs) of an Wii U Disc as *.app,*.h3, .tmd, .tik, .cert files - Supports dumping to SD (FAT32) and USB (NTFS only). When dumping to SD the files get slitted in 2 GiB parts. Files will be dumped to `/wudump/[DISC-ID]/`. The DiscID of a game can be found on the disc (e.g. WUP-P-ARDP for the EUR version of Super Mario 3D World). @@ -14,14 +14,26 @@ Files will be dumped to `/wudump/[DISC-ID]/`. The DiscID of a game can be found When you dump a .wux or .wud to the SD card it gets splitted into 2 GiB parts (FAT32 limitation). To merge them you can use the `copy` cmd tool. Example: -`copy /b "game.wux.part1" + "game.wux.part2" "C:\wudump\game.wux"` +`copy /b game.wux.part1 + game.wux.part2 game.wux` ## Dependencies +Requires an [Environment](https://github.com/wiiu-env/EnvironmentLoader) (e.g. Tiramisu or Aroma) with [MochaPayload](https://github.com/wiiu-env/MochaPayload) (Nightly-MochaPayload-20220725-155554 or newer) - [wut](https://github.com/devkitPro/wut) -- [libiosuhax](https://github.com/wiiu-env/libiosuhax) +- [libmocha](https://github.com/wiiu-env/libmocha) - [libntfs](https://github.com/wiiu-env/libntfs) +## Buildflags + +### Logging +Building via `make` only logs errors (via OSReport). To enable logging via the [LoggingModule](https://github.com/wiiu-env/LoggingModule) set `DEBUG` to `1` or `VERBOSE`. + +`make` Logs errors only (via OSReport). +`make DEBUG=1` Enables information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule). +`make DEBUG=VERBOSE` Enables verbose information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule). + +If the [LoggingModule](https://github.com/wiiu-env/LoggingModule) is not present, it'll fallback to UDP (Port 4405) and [CafeOS](https://github.com/wiiu-env/USBSerialLoggingModule) logging. + ## 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. diff --git a/source/ApplicationState.h b/source/ApplicationState.h index 0a2d4fc..73c9619 100644 --- a/source/ApplicationState.h +++ b/source/ApplicationState.h @@ -26,7 +26,7 @@ public: this->selectedOptionY++; } if (this->selectedOptionY < 0) { - this->selectedOptionY = maxOptionValue; + this->selectedOptionY = maxOptionValue - 1; } else if (this->selectedOptionY >= maxOptionValue) { this->selectedOptionY = 0; } @@ -46,6 +46,10 @@ public: } } + virtual bool buttonPressed(Input *input, Input::eButtons button) { + return input->data.buttons_d & button; + } + virtual bool entrySelected(Input *input) { return input->data.buttons_d & Input::BUTTON_A; } @@ -57,9 +61,13 @@ public: } virtual void printFooter() { - if (gRunFromHBL) { + if (gRunFromHBL && !gBlockHomeButton) { ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_TV, 0, 25, "Press HOME to exit to HBL"); ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_DRC, 0, 15, "Press HOME to exit to HBL"); + } else if (gRunFromHBL && gBlockHomeButtonCooldown > 0) { + ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_TV, 0, 25, "You can not exit while dumping."); + ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_DRC, 0, 15, "You can not exit while dumping."); + gBlockHomeButtonCooldown--; } ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_TV, 0, 27, "Created by Maschell, inspired by wudump from FIX94"); ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_DRC, 0, 17, "Created by Maschell, inspired by wudump from FIX94"); diff --git a/source/GMPartitionsDumperState.cpp b/source/GMPartitionsDumperState.cpp index 7cbcafb..7fbff41 100644 --- a/source/GMPartitionsDumperState.cpp +++ b/source/GMPartitionsDumperState.cpp @@ -21,8 +21,9 @@ #include #include #include -#include #include +#include +#include #include #define READ_BUFFER_SIZE (SECTOR_SIZE * 128) @@ -30,6 +31,7 @@ GMPartitionsDumperState::GMPartitionsDumperState(eDumpTarget pTargetDevice) : targetDevice(pTargetDevice) { this->sectorBufSize = SECTOR_SIZE; this->state = STATE_OPEN_ODD1; + gBlockHomeButton = true; } GMPartitionsDumperState::~GMPartitionsDumperState() { @@ -37,6 +39,7 @@ GMPartitionsDumperState::~GMPartitionsDumperState() { this->sectorBuf = nullptr; free(this->readBuffer); this->readBuffer = nullptr; + gBlockHomeButton = false; } void GMPartitionsDumperState::render() { @@ -73,11 +76,22 @@ void GMPartitionsDumperState::render() { } else { uint32_t index = 0; for (auto &partitionPair : gmPartitionPairs) { - uint32_t size = 0; + uint64_t size = 0; for (auto &content : partitionPair.second->tmd->contentList) { size += ROUNDUP(content->encryptedFileSize, 16); } - WiiUScreen::drawLinef("%s %s (~%0.2f MiB)", index == (uint32_t) selectedOptionY ? ">" : " ", partitionPair.first->getVolumeId().c_str(), (float) size / 1024.0f / 1024.0f); + std::string titleId = partitionPair.first->getVolumeId().substr(2, 18); + std::string appType = "Other "; + if (titleId.starts_with("00050000")) { + appType = "Game "; + } else if (titleId.starts_with("0005000C")) { + appType = "DLC "; + } else if (titleId.starts_with("0005000E")) { + appType = "Update"; + } + WiiUScreen::drawLinef("%s %s - %s (~%0.2f GiB) (%s)", index == (uint32_t) selectedOptionY ? ">" : " ", appType.c_str(), + partitionPair.second->getShortnameEn().c_str(), + (float) ((float) size / 1024.0f / 1024.0f / 1024.0f), titleId.c_str()); index++; } WiiUScreen::drawLine(); @@ -94,6 +108,8 @@ void GMPartitionsDumperState::render() { } else if (this->state == STATE_DUMP_PARTITION_CONTENTS) { if (curPartition != nullptr) { WiiUScreen::drawLinef("Dumping Partition %s", curPartition->getVolumeId().c_str()); + WiiUScreen::drawLinef("Name: %s", curNUSTitle->getLongnameEn().c_str(), curNUSTitle->tmd->titleId); + WiiUScreen::drawLinef("TitleID: %016llX", curNUSTitle->tmd->titleId); } else { WiiUScreen::drawLine("Dumping Partition"); } @@ -127,10 +143,22 @@ void GMPartitionsDumperState::render() { if (size > 0) { WiiUScreen::drawLinef("Progress: %.2f MiB / %.2f MiB (%0.2f%%)", offset / 1024.0f / 1024.0f, size / 1024.0f / 1024.0f, ((offset * 1.0f) / size) * 100.0f); + } else { + WiiUScreen::drawLine(); } + WiiUScreen::drawLine(); + WiiUScreen::drawLine("Press B to abort the dumping"); } else if (this->state == STATE_DUMP_DONE) { WiiUScreen::drawLine("Dumping done. Press A to return."); + } else if (this->state == STATE_ABORT_CONFIRMATION) { + WiiUScreen::drawLinef("Do you really want to abort the disc dumping?"); + WiiUScreen::drawLinef(""); + if (selectedOptionX == 0) { + WiiUScreen::drawLinef("> Continue dumping Abort dumping"); + } else { + WiiUScreen::drawLinef(" Continue dumping > Abort dumping"); + } } ApplicationState::printFooter(); @@ -149,17 +177,15 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { } if (this->state == STATE_OPEN_ODD1) { - auto ret = IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &(this->oddFd)); + auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &(this->oddFd)); if (ret >= 0) { if (this->sectorBuf == nullptr) { this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize); if (this->sectorBuf == nullptr) { - DEBUG_FUNCTION_LINE("ERROR_MALLOC_FAILED"); this->setError(ERROR_MALLOC_FAILED); return ApplicationState::SUBSTATE_RUNNING; } } - DEBUG_FUNCTION_LINE("Opened /dev/odd01 %d", this->oddFd); this->state = STATE_READ_DISC_INFO; } else { this->state = STATE_PLEASE_INSERT_DISC; @@ -169,7 +195,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { return ApplicationState::SUBSTATE_RETURN; } } else if (this->state == STATE_READ_DISC_INFO) { - if (IOSUHAX_FSA_RawRead(gFSAfd, this->sectorBuf, READ_SECTOR_SIZE, 1, 0, this->oddFd) >= 0) { + if (FSAEx_RawRead(__wut_devoptab_fs_client, this->sectorBuf, READ_SECTOR_SIZE, 1, 0, this->oddFd) >= 0) { this->discId[10] = '\0'; memcpy(this->discId.data(), sectorBuf, 10); if (this->discId[0] == 0) { @@ -180,27 +206,30 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { this->state = STATE_READ_DISC_INFO_DONE; return ApplicationState::SUBSTATE_RUNNING; } + FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd); + this->oddFd = -1; this->setError(ERROR_READ_FIRST_SECTOR); return ApplicationState::SUBSTATE_RUNNING; } else if (this->state == STATE_READ_DISC_INFO_DONE) { this->state = STATE_READ_COMMON_KEY; } else if (this->state == STATE_READ_COMMON_KEY) { - uint8_t opt[0x400]; - IOSUHAX_read_otp(opt, 0x400); - memcpy(cKey.data(), opt + 0xE0, 0x10); + WiiUConsoleOTP otp; + Mocha_ReadOTP(&otp); + memcpy(cKey.data(), otp.wiiUBank.wiiUCommonKey, 0x10); this->state = STATE_CREATE_DISC_READER; } else if (this->state == STATE_CREATE_DISC_READER) { - this->discReader = std::make_shared(); - if (!discReader->IsReady()) { + auto discReaderOpt = DiscReaderDiscDrive::make_unique(); + if (!discReaderOpt) { this->setError(ERROR_OPEN_ODD1); return SUBSTATE_RUNNING; } - this->state = STATE_PARSE_DISC_HEADER; + this->discReader = std::move(discReaderOpt.value()); + this->state = STATE_PARSE_DISC_HEADER; } else if (this->state == STATE_PARSE_DISC_HEADER) { auto discHeaderOpt = WiiUDiscHeader::make_unique(discReader); if (!discHeaderOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to read DiscHeader"); + DEBUG_FUNCTION_LINE_ERR("Failed to read DiscHeader"); this->setError(ERROR_PARSE_DISCHEADER); return SUBSTATE_RUNNING; } @@ -217,9 +246,10 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { return SUBSTATE_RUNNING; } - this->gmPartitionPairs.emplace_back(gmPartition, nusTitleOpt.value()); + this->gmPartitionPairs.emplace_back(gmPartition, std::move(nusTitleOpt.value())); } } + this->state = STATE_CHOOSE_PARTITION_TO_DUMP; } else if (this->state == STATE_CHOOSE_PARTITION_TO_DUMP) { if (gmPartitionPairs.empty()) { @@ -227,6 +257,11 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { return SUBSTATE_RETURN; } } + + if (buttonPressed(input, Input::BUTTON_B)) { + return SUBSTATE_RETURN; + } + proccessMenuNavigationY(input, (int32_t) gmPartitionPairs.size() + 1); if (entrySelected(input)) { if (selectedOptionY >= (int32_t) gmPartitionPairs.size()) { @@ -243,7 +278,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { return SUBSTATE_RUNNING; } - this->targetPath = StringTools::strfmt("%swudump/%s/%s", getPathForDevice(targetDevice).c_str(), this->discId, curPartition->getVolumeId().c_str()); + this->targetPath = string_format("%swudump/%s/%s", getPathForDevice(targetDevice).c_str(), this->discId, curPartition->getVolumeId().c_str()); if (!FSUtils::CreateSubfolder(targetPath.c_str())) { this->setError(ERROR_CREATE_DIR); return SUBSTATE_RUNNING; @@ -292,6 +327,10 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { this->curContentIndex = 0; this->state = STATE_DUMP_PARTITION_CONTENTS; } else if (this->state == STATE_DUMP_PARTITION_CONTENTS) { + if (buttonPressed(input, Input::BUTTON_B)) { + this->state = STATE_ABORT_CONFIRMATION; + return ApplicationState::SUBSTATE_RUNNING; + } // Get current content by index. if (curContent == nullptr) { auto curContentOpt = curNUSTitle->tmd->getContentByIndex(curContentIndex); @@ -350,7 +389,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { // alloc readBuffer if needed if (this->readBuffer == nullptr) { - readBuffer = (uint8_t *) malloc(READ_BUFFER_SIZE); + readBuffer = (uint8_t *) memalign(0x40, ROUNDUP(READ_BUFFER_SIZE, 0x40)); if (readBuffer == nullptr) { this->setError(ERROR_MALLOC_FAILED); return SUBSTATE_RUNNING; @@ -376,6 +415,20 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) { // Go on! this->state = STATE_DUMP_PARTITION_CONTENTS; return ApplicationState::SUBSTATE_RUNNING; + } else if (this->state == STATE_ABORT_CONFIRMATION) { + if (buttonPressed(input, Input::BUTTON_B)) { + this->state = STATE_DUMP_PARTITION_CONTENTS; + return ApplicationState::SUBSTATE_RUNNING; + } + proccessMenuNavigationX(input, 2); + if (buttonPressed(input, Input::BUTTON_A)) { + if (selectedOptionX == 0) { + this->state = STATE_DUMP_PARTITION_CONTENTS; + return ApplicationState::SUBSTATE_RUNNING; + } else { + return ApplicationState::SUBSTATE_RETURN; + } + } } else if (state == STATE_DUMP_DONE) { if (entrySelected(input)) { return ApplicationState::SUBSTATE_RETURN; diff --git a/source/GMPartitionsDumperState.h b/source/GMPartitionsDumperState.h index 3fcd671..c900d89 100644 --- a/source/GMPartitionsDumperState.h +++ b/source/GMPartitionsDumperState.h @@ -48,7 +48,8 @@ public: STATE_DUMP_PARTITION_TICKET, STATE_DUMP_PARTITION_CERT, STATE_DUMP_PARTITION_CONTENTS, - STATE_DUMP_DONE + STATE_DUMP_DONE, + STATE_ABORT_CONFIRMATION }; enum eErrorState { @@ -92,8 +93,8 @@ public: int32_t oddFd = -1; void *sectorBuf = nullptr; uint32_t sectorBufSize; - std::shared_ptr discReader = nullptr; - std::unique_ptr discHeader = nullptr; + std::shared_ptr discReader; + std::unique_ptr discHeader; std::shared_ptr curPartition = nullptr; std::shared_ptr dataProvider = nullptr; diff --git a/source/WUD/DefaultNUSDataProcessor.cpp b/source/WUD/DefaultNUSDataProcessor.cpp index 889c31c..82e21b9 100644 --- a/source/WUD/DefaultNUSDataProcessor.cpp +++ b/source/WUD/DefaultNUSDataProcessor.cpp @@ -16,24 +16,27 @@ ****************************************************************************/ #include "DefaultNUSDataProcessor.h" - bool DefaultNUSDataProcessor::readPlainDecryptedContent(const std::shared_ptr &pContent, std::vector &out_data) { if ((pContent->type & 0x0002) == 0x0002) { - DEBUG_FUNCTION_LINE("Hashed content not supported yet"); + DEBUG_FUNCTION_LINE_ERR("Hashed content not supported yet"); return false; } auto contentSize = ROUNDUP(pContent->encryptedFileSize, 16); out_data.resize(contentSize); - auto *inData = (uint8_t *) malloc(contentSize); - if (inData == nullptr) { - DEBUG_FUNCTION_LINE("Failed to alloc"); + if (contentSize > UINT32_MAX) { + DEBUG_FUNCTION_LINE_ERR("Content is too big to read"); + OSFatal("Content is too big to read"); + } + + auto inData = make_unique_nothrow((uint32_t) contentSize); + if (!inData) { + DEBUG_FUNCTION_LINE_ERR("Failed to alloc"); return false; } - if (!dataProvider->readRawContent(pContent, inData, 0, contentSize)) { - DEBUG_FUNCTION_LINE("Failed tor read content"); - free(inData); + if (!dataProvider->readRawContent(pContent, inData.get(), 0, contentSize)) { + DEBUG_FUNCTION_LINE_ERR("Failed tor read content"); return false; } @@ -42,12 +45,11 @@ bool DefaultNUSDataProcessor::readPlainDecryptedContent(const std::shared_ptrindex; memcpy(IV.data(), &content_index, 2); - nusDecryption->decryptData(IV, inData, out_data.data(), contentSize); - free(inData); + nusDecryption->decryptData(IV, inData.get(), out_data.data(), contentSize); return true; } -std::shared_ptr DefaultNUSDataProcessor::getDataProvider() { +std::shared_ptr &DefaultNUSDataProcessor::getDataProvider() { return dataProvider; } diff --git a/source/WUD/DefaultNUSDataProcessor.h b/source/WUD/DefaultNUSDataProcessor.h index f728d9c..633aa3a 100644 --- a/source/WUD/DefaultNUSDataProcessor.h +++ b/source/WUD/DefaultNUSDataProcessor.h @@ -27,7 +27,7 @@ public: bool readPlainDecryptedContent(const std::shared_ptr &pContent, std::vector &out_data) override; - std::shared_ptr getDataProvider() override; + std::shared_ptr &getDataProvider() override; private: std::shared_ptr dataProvider; diff --git a/source/WUD/DiscReader.cpp b/source/WUD/DiscReader.cpp index 585ad0b..d534071 100644 --- a/source/WUD/DiscReader.cpp +++ b/source/WUD/DiscReader.cpp @@ -15,21 +15,21 @@ * along with this program. If not, see . ****************************************************************************/ -#include +#include "utils/utils.h" #include #include #include #include bool DiscReader::readDecryptedChunk(uint64_t readOffset, uint8_t *out_buffer, uint8_t *key, uint8_t *IV) const { - int CHUNK_SIZE = 0x10000; + uint32_t CHUNK_SIZE = 0x10000; uint32_t sectorOffset = readOffset / READ_SECTOR_SIZE; - auto *encryptedBuffer = (uint8_t *) malloc(CHUNK_SIZE); + auto encryptedBuffer = (uint8_t *) memalign(0x40, CHUNK_SIZE); - if (encryptedBuffer == nullptr) { - DEBUG_FUNCTION_LINE("Failed to alloc buffer"); + if (!encryptedBuffer) { + DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffer"); return false; } @@ -41,8 +41,8 @@ bool DiscReader::readDecryptedChunk(uint64_t readOffset, uint8_t *out_buffer, ui memcpy(IV, &encryptedBuffer[CHUNK_SIZE - 16], 16); result = true; } - free(encryptedBuffer); + return result; } @@ -61,8 +61,9 @@ bool DiscReader::readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint uint32_t usedSize = size; uint64_t usedFileOffset = fileOffset; - auto *buffer = (uint8_t *) malloc(BLOCK_SIZE); - if (buffer == nullptr) { + auto buffer = make_unique_nothrow((size_t) BLOCK_SIZE); + if (!buffer) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate buffer"); return false; } @@ -77,8 +78,8 @@ bool DiscReader::readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint do { uint64_t totalOffset = (clusterOffset + usedFileOffset); - uint64_t blockNumber = (totalOffset / BLOCK_SIZE); - uint64_t blockOffset = (totalOffset % BLOCK_SIZE); + uint32_t blockNumber = (totalOffset / BLOCK_SIZE); + uint32_t blockOffset = (totalOffset % BLOCK_SIZE); readOffset = (blockNumber * BLOCK_SIZE); if (!useFixedIV) { @@ -87,14 +88,14 @@ bool DiscReader::readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint memcpy(usedIV + 8, &ivTemp, 8); } - if (!readDecryptedChunk(readOffset, buffer, key, usedIV)) { + if (!readDecryptedChunk(readOffset, buffer.get(), key, usedIV)) { result = false; break; } maxCopySize = BLOCK_SIZE - blockOffset; copySize = (usedSize > maxCopySize) ? maxCopySize : usedSize; - memcpy(out_buffer + totalread, buffer + blockOffset, copySize); + memcpy(out_buffer + totalread, buffer.get() + blockOffset, copySize); totalread += copySize; @@ -103,22 +104,21 @@ bool DiscReader::readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint usedFileOffset += copySize; } while (totalread < size); - free(buffer); - return result; } -bool DiscReader::readEncryptedAligned(uint8_t *buf, uint64_t offset_in_sector, uint32_t size) { +bool DiscReader::readEncryptedAligned(uint8_t *buf, uint32_t block_offset, uint32_t size) { auto full_block_count = size / SECTOR_SIZE; if (full_block_count > 0) { - if (!readEncryptedSector(buf, full_block_count, offset_in_sector)) { + if (!readEncryptedSector(buf, full_block_count, block_offset)) { return false; } } - auto remainingSize = size - (full_block_count * SECTOR_SIZE); if (remainingSize > 0) { - auto newOffset = offset_in_sector + full_block_count; + std::lock_guard lock(sector_buf_mutex); + auto newOffset = block_offset + full_block_count; + if (!readEncryptedSector(sector_buf, 1, newOffset)) { return false; } @@ -136,40 +136,48 @@ bool DiscReader::readEncrypted(uint8_t *buf, uint64_t offset, uint32_t size) { auto curOffset = offset; uint32_t offsetInBuf = 0; uint32_t totalRead = 0; + if (missingFromPrevSector > 0) { + std::lock_guard lock(sector_buf_mutex); 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; + curOffset += toCopy; + offsetInBuf += toCopy; } - if (totalRead >= size) { return true; } if (curOffset % SECTOR_SIZE == 0) { - if (!readEncryptedAligned(buf + offsetInBuf, offset / SECTOR_SIZE, size)) { + if (!readEncryptedAligned(buf + offsetInBuf, curOffset / SECTOR_SIZE, size)) { return false; } } else { - OSFatal("Failed to read encrypted"); + return false; } return true; } DiscReader::DiscReader() { - this->sector_buf = (uint8_t *) malloc(READ_SECTOR_SIZE); + this->sector_buf = static_cast(memalign(0x40, READ_SECTOR_SIZE)); + if (!this->sector_buf) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate sector_buf"); + OSFatal("Failed to allocate sector_buf"); + } } DiscReader::~DiscReader() { free(this->sector_buf); + this->sector_buf = nullptr; } diff --git a/source/WUD/DiscReader.h b/source/WUD/DiscReader.h index 634609a..49117e6 100644 --- a/source/WUD/DiscReader.h +++ b/source/WUD/DiscReader.h @@ -17,6 +17,8 @@ #pragma once #include +#include +#include class DiscReader { public: @@ -26,9 +28,9 @@ public: virtual bool IsReady() = 0; - virtual bool readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint64_t offset_in_sector) const = 0; + virtual bool readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint32_t block_offset) const = 0; - bool readEncryptedAligned(uint8_t *buf, uint64_t offset_in_sector, uint32_t size); + bool readEncryptedAligned(uint8_t *buf, uint32_t block_offset, uint32_t size); bool readDecryptedChunk(uint64_t readOffset, uint8_t *out_buffer, uint8_t *key, uint8_t *IV) const; @@ -40,5 +42,6 @@ public: bool hasDiscKey = false; private: - uint8_t *sector_buf; + std::mutex sector_buf_mutex; + uint8_t *sector_buf = nullptr; }; \ No newline at end of file diff --git a/source/WUD/DiscReaderDiscDrive.cpp b/source/WUD/DiscReaderDiscDrive.cpp index ef9659f..4aa234e 100644 --- a/source/WUD/DiscReaderDiscDrive.cpp +++ b/source/WUD/DiscReaderDiscDrive.cpp @@ -15,56 +15,67 @@ * along with this program. If not, see . ****************************************************************************/ #include "DiscReaderDiscDrive.h" -#include +#include "utils/utils.h" #include #include -#include +#include +#include +#include #include #include - DiscReaderDiscDrive::DiscReaderDiscDrive() : DiscReader() { - auto *sector_buf = (uint8_t *) malloc(READ_SECTOR_SIZE); - if (sector_buf == nullptr) { + auto sector_buf = (uint8_t *) memalign(0x40, (size_t) READ_SECTOR_SIZE); + if (!sector_buf) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate buffer"); return; } - auto ret = IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &device_handle); + auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &device_handle); if (ret < 0) { + free(sector_buf); return; } - auto res = IOSUHAX_FSA_RawRead(gFSAfd, sector_buf, READ_SECTOR_SIZE, 1, 3, device_handle); - + auto res = FSAEx_RawRead(__wut_devoptab_fs_client, 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); + WUDDiscKey discKeyLocal; + + auto discKeyRes = Mocha_ODMGetDiscKey(&discKeyLocal); + if (discKeyRes == MOCHA_RESULT_SUCCESS) { + hasDiscKey = true; + memcpy(this->discKey, discKeyLocal.key, 16); + auto sector_buf_decrypted = make_unique_nothrow((size_t) READ_SECTOR_SIZE); + if (!sector_buf_decrypted) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory"); + free(sector_buf); + return; } + aes_set_key((uint8_t *) discKey); + aes_decrypt((uint8_t *) iv, (uint8_t *) §or_buf[0], (uint8_t *) §or_buf_decrypted[0], READ_SECTOR_SIZE); + if (((uint32_t *) sector_buf_decrypted.get())[0] == WiiUDiscContentsHeader::MAGIC) { + this->init_done = true; + } else { + DEBUG_FUNCTION_LINE_ERR("Invalid disc key"); + } + } else { + DEBUG_FUNCTION_LINE_ERR("Failed to get the DiscKey"); + this->init_done = false; } } else { this->init_done = true; } + } else { + DEBUG_FUNCTION_LINE_ERR("Raw read failed %d", ret); } - 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"); +bool DiscReaderDiscDrive::readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint32_t block_offset) const { + if (FSAEx_RawRead(__wut_devoptab_fs_client, buffer, READ_SECTOR_SIZE, block_cnt, block_offset, device_handle) < 0) { return false; } return true; @@ -76,7 +87,8 @@ bool DiscReaderDiscDrive::IsReady() { DiscReaderDiscDrive::~DiscReaderDiscDrive() { if (device_handle != -1) { - IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &device_handle); + FSAEx_RawClose(__wut_devoptab_fs_client, device_handle); + device_handle = -1; } } @@ -84,22 +96,23 @@ bool DiscReaderDiscDrive::readEncrypted(uint8_t *buf, uint64_t offset, uint32_t if (size == 0) { return true; } - if ((offset & 0x7FFF) != 0 || (size & 0x7FFF) != 0) { + + if ((offset & (SECTOR_SIZE - 0x1)) != 0 || (size & (SECTOR_SIZE - 0x1)) != 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) { + if (FSAEx_RawRead(__wut_devoptab_fs_client, buf, 0x8000, block_cnt, offset_in_sectors, device_handle) < 0) { DEBUG_FUNCTION_LINE("Failed to read from Disc"); return false; } return true; } -std::optional DiscReaderDiscDrive::Create() { - auto discReader = new DiscReaderDiscDrive(); - if (!discReader->IsReady()) { - delete discReader; +std::optional> DiscReaderDiscDrive::make_unique() { + auto discReader = make_unique_nothrow(); + if (!discReader || !discReader->IsReady()) { + DEBUG_FUNCTION_LINE_ERR("Failed to init DiscReader %d %d", !discReader, discReader->IsReady()); return {}; } return discReader; diff --git a/source/WUD/DiscReaderDiscDrive.h b/source/WUD/DiscReaderDiscDrive.h index a5f90b6..87ba5b9 100644 --- a/source/WUD/DiscReaderDiscDrive.h +++ b/source/WUD/DiscReaderDiscDrive.h @@ -18,6 +18,7 @@ #include "DiscReader.h" #include +#include #include class DiscReaderDiscDrive : public DiscReader { @@ -26,15 +27,14 @@ public: ~DiscReaderDiscDrive() override; - static std::optional Create(); + static std::optional> make_unique(); - bool readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint64_t offset_in_sector) const override; - - bool IsReady() override; + bool readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint32_t block_offset) const override; bool readEncrypted(uint8_t *buf, uint64_t offset, uint32_t size) override; private: + bool IsReady() override; bool init_done = false; int32_t device_handle = -1; }; \ No newline at end of file diff --git a/source/WUD/NUSDataProcessor.h b/source/WUD/NUSDataProcessor.h index 5ce9c01..02599ba 100644 --- a/source/WUD/NUSDataProcessor.h +++ b/source/WUD/NUSDataProcessor.h @@ -10,7 +10,7 @@ protected: public: virtual ~NUSDataProcessor() = default; - virtual std::shared_ptr getDataProvider() = 0; + virtual std::shared_ptr &getDataProvider() = 0; virtual bool readPlainDecryptedContent(const std::shared_ptr &pContent, std::vector &out_data) = 0; }; \ No newline at end of file diff --git a/source/WUD/NUSDataProviderWUD.cpp b/source/WUD/NUSDataProviderWUD.cpp index 4fc32bc..11ebc96 100644 --- a/source/WUD/NUSDataProviderWUD.cpp +++ b/source/WUD/NUSDataProviderWUD.cpp @@ -15,33 +15,44 @@ * along with this program. If not, see . ****************************************************************************/ #include "NUSDataProviderWUD.h" +#include "utils/WUDUtils.h" -NUSDataProviderWUD::NUSDataProviderWUD(const std::shared_ptr &pGamePartition, const std::shared_ptr &pDiscReader) { - gamePartition = pGamePartition; - discReader = pDiscReader; +NUSDataProviderWUD::NUSDataProviderWUD(std::shared_ptr pGamePartition, std::shared_ptr pDiscReader) { + gamePartition = std::move(pGamePartition); + discReader = std::move(pDiscReader); } NUSDataProviderWUD::~NUSDataProviderWUD() = default; bool NUSDataProviderWUD::readRawContent(const std::shared_ptr &content, uint8_t *buffer, uint64_t offset, uint32_t size) { if (buffer == nullptr) { + DEBUG_FUNCTION_LINE_ERR("buffer was NULL"); return false; } - auto offsetInWUDOpt = getOffsetInWUD(content); - if (!offsetInWUDOpt.has_value()) { + if (!discReader) { + DEBUG_FUNCTION_LINE_ERR("No valid disc reader"); + return false; + } + + auto offsetInWUDOpt = WUDUtils::getOffsetOfContent(this->gamePartition, this->fst, content); + if (!offsetInWUDOpt) { + DEBUG_FUNCTION_LINE_ERR("Failed to get offset for content"); return false; } auto offsetInWUD = offsetInWUDOpt.value() + offset; + if (!discReader) { + return false; + } return discReader->readEncrypted(buffer, offsetInWUD, size); } bool NUSDataProviderWUD::getContentH3Hash(const std::shared_ptr &content, std::vector &out_data) { - auto cur = gamePartition->getVolumes().begin()->second->h3HashArrayList[content->index]; + auto &cur = gamePartition->getVolumes().begin()->second->h3HashArrayList[content->index]; if (cur == nullptr || cur->size == 0) { return false; } out_data.resize(cur->size); - memcpy(out_data.data(), cur->data, cur->size); + memcpy(out_data.data(), cur->data.get(), cur->size); return true; } @@ -56,29 +67,16 @@ void NUSDataProviderWUD::setFST(const std::shared_ptr &pFST) { } bool NUSDataProviderWUD::getRawCert(std::vector &out_data) { - out_data = gamePartition->rawCert; + out_data = gamePartition->getRawCert(); return true; } bool NUSDataProviderWUD::getRawTicket(std::vector &out_data) { - out_data = gamePartition->rawTicket; + out_data = gamePartition->getRawTicket(); return true; } bool NUSDataProviderWUD::getRawTMD(std::vector &out_data) { - out_data = gamePartition->rawTMD; + out_data = gamePartition->getRawTMD(); return true; -} - -std::optional NUSDataProviderWUD::getOffsetInWUD(const std::shared_ptr &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.has_value()) { - DEBUG_FUNCTION_LINE("Failed to get section for Content"); - return {}; - } - return gamePartition->getSectionOffsetOnDefaultPartition() + info.value()->address.getAddressInBytes(); -} +} \ No newline at end of file diff --git a/source/WUD/NUSDataProviderWUD.h b/source/WUD/NUSDataProviderWUD.h index 0f7620c..ff73720 100644 --- a/source/WUD/NUSDataProviderWUD.h +++ b/source/WUD/NUSDataProviderWUD.h @@ -25,7 +25,7 @@ class NUSDataProviderWUD : public NUSDataProvider { public: - NUSDataProviderWUD(const std::shared_ptr &pPartition, const std::shared_ptr &pDrive); + NUSDataProviderWUD(std::shared_ptr pPartition, std::shared_ptr pDiscReader); ~NUSDataProviderWUD() override; @@ -44,7 +44,4 @@ public: std::shared_ptr fst; std::shared_ptr gamePartition; std::shared_ptr discReader; - -private: - [[nodiscard]] std::optional getOffsetInWUD(const std::shared_ptr &content) const; }; \ No newline at end of file diff --git a/source/WUD/NUSDecryption.cpp b/source/WUD/NUSDecryption.cpp index 5abf879..56815a1 100644 --- a/source/WUD/NUSDecryption.cpp +++ b/source/WUD/NUSDecryption.cpp @@ -24,5 +24,5 @@ void NUSDecryption::decryptData(const std::array &IV, uint8_t *in aes_decrypt((uint8_t *) IV.data(), inData, outData, size); } -NUSDecryption::NUSDecryption(std::shared_ptr pTicket) : ticket(std::move(pTicket)) { +NUSDecryption::NUSDecryption(std::unique_ptr pTicket) : ticket(std::move(pTicket)) { } \ No newline at end of file diff --git a/source/WUD/NUSDecryption.h b/source/WUD/NUSDecryption.h index a23bbea..fbe89a7 100644 --- a/source/WUD/NUSDecryption.h +++ b/source/WUD/NUSDecryption.h @@ -21,9 +21,9 @@ class NUSDecryption { public: - explicit NUSDecryption(std::shared_ptr pTicket); + explicit NUSDecryption(std::unique_ptr pTicket); void decryptData(const std::array &IV, uint8_t *inData, uint8_t *outData, uint32_t size) const; - std::shared_ptr ticket; + std::unique_ptr ticket; }; diff --git a/source/WUD/NUSTitle.cpp b/source/WUD/NUSTitle.cpp index cdcdef7..ad74361 100644 --- a/source/WUD/NUSTitle.cpp +++ b/source/WUD/NUSTitle.cpp @@ -16,66 +16,77 @@ ****************************************************************************/ #include "NUSTitle.h" +#include #include -std::optional> NUSTitle::loadTitle(const std::shared_ptr &dataProvider, const std::array &commonKey) { +std::optional> NUSTitle::make_unique(std::unique_ptr dataProvider, const std::array &commonKey) { std::vector dataBuffer; if (!dataProvider->getRawTMD(dataBuffer)) { - DEBUG_FUNCTION_LINE("Failed to read TMD"); + DEBUG_FUNCTION_LINE_ERR("Failed to read TMD"); return {}; } - auto tmdOpt = TitleMetaData::make_shared(dataBuffer); + auto tmdOpt = TitleMetaData::make_unique(dataBuffer); if (!tmdOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse TMD"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse TMD"); return {}; } dataBuffer.clear(); if (!dataProvider->getRawTicket(dataBuffer)) { - DEBUG_FUNCTION_LINE("Failed to read ticket data"); + DEBUG_FUNCTION_LINE_ERR("Failed to read ticket data"); return {}; } - auto ticketOpt = Ticket::make_shared(dataBuffer, commonKey); + auto ticketOpt = Ticket::make_unique(dataBuffer, commonKey); if (!ticketOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse ticket"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse ticket"); return {}; } dataBuffer.clear(); + + std::shared_ptr dataProviderShared = std::move(dataProvider); + auto decryption = std::make_shared(std::move(ticketOpt.value())); - auto dpp = std::shared_ptr(new DefaultNUSDataProcessor(dataProvider, decryption)); + auto dpp = std::unique_ptr(new DefaultNUSDataProcessor(dataProviderShared, decryption)); // If we have more than one content, the index 0 is the FST. auto fstContentOpt = tmdOpt.value()->getContentByIndex(0); if (!fstContentOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to get content for index 0"); + DEBUG_FUNCTION_LINE_ERR("Failed to get content for index 0"); return {}; } if (!dpp->readPlainDecryptedContent(fstContentOpt.value(), dataBuffer)) { - DEBUG_FUNCTION_LINE("Failed to read decrypted content"); + DEBUG_FUNCTION_LINE_ERR("Failed to read decrypted content"); return {}; } auto fstOpt = FST::make_shared(dataBuffer, 0, VolumeBlockSize(1)); if (!fstOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse FST"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse FST"); return {}; } // The dataprovider may need the FST to calculate the offset of a content // on the partition. - dataProvider->setFST(fstOpt.value()); - return std::shared_ptr(new NUSTitle(tmdOpt.value(), dpp, dataProvider, decryption, ticketOpt.value(), fstOpt.value())); + dataProviderShared->setFST(fstOpt.value()); + + return std::unique_ptr(new NUSTitle( + std::move(tmdOpt.value()), + std::move(dpp), + dataProviderShared, + decryption, + std::move(ticketOpt.value()), + fstOpt.value())); } -NUSTitle::NUSTitle(std::shared_ptr pTMD, - std::shared_ptr pProcessor, +NUSTitle::NUSTitle(std::unique_ptr pTMD, + std::unique_ptr pProcessor, std::shared_ptr pDataProvider, std::shared_ptr pDecryption, - std::shared_ptr pTicket, + std::unique_ptr pTicket, std::shared_ptr pFST) : dataProcessor(std::move(pProcessor)), @@ -86,9 +97,50 @@ NUSTitle::NUSTitle(std::shared_ptr pTMD, dataProvider(std::move(pDataProvider)) { } -std::optional> -NUSTitle::loadTitleFromGMPartition(const std::shared_ptr &pPartition, const std::shared_ptr &pDrive, const std::array &commonKey) { - return loadTitle(std::shared_ptr(new NUSDataProviderWUD(pPartition, pDrive)), commonKey); +std::optional> +NUSTitle::loadTitleFromGMPartition(std::shared_ptr pPartition, std::shared_ptr pDiscReader, const std::array &commonKey) { + return make_unique(std::unique_ptr(new NUSDataProviderWUD(std::move(pPartition), std::move(pDiscReader))), commonKey); +} + +std::string NUSTitle::getLongnameEn() { + if (!longname_en) { + auto *xml = (ACPMetaXml *) memalign(0x40, sizeof(ACPMetaXml)); + if (xml) { + if (ACPGetTitleMetaXml(tmd->titleId, xml) == ACP_RESULT_SUCCESS) { + std::string tmp = xml->longname_en; + StringTools::StripUnicodeAndLineBreak(tmp); + longname_en = tmp; + } + free(xml); + } else { + longname_en = "Unknown"; + } + + if (!longname_en || longname_en->empty() || longname_en.value() == " ") { + longname_en = "Unknown"; + } + } + return longname_en.value(); +} + +std::string NUSTitle::getShortnameEn() { + if (!shortname_en) { + auto *xml = (ACPMetaXml *) memalign(0x40, sizeof(ACPMetaXml)); + if (xml) { + if (ACPGetTitleMetaXml(tmd->titleId, xml) == ACP_RESULT_SUCCESS) { + std::string tmp = xml->shortname_en; + StringTools::StripUnicodeAndLineBreak(tmp); + shortname_en = tmp; + } + free(xml); + } else { + shortname_en = "Unknown"; + } + if (!shortname_en || shortname_en->empty() || shortname_en.value() == " ") { + shortname_en = "Unknown"; + } + } + return shortname_en.value(); } NUSTitle::~NUSTitle() = default; diff --git a/source/WUD/NUSTitle.h b/source/WUD/NUSTitle.h index 0ad5269..53db90d 100644 --- a/source/WUD/NUSTitle.h +++ b/source/WUD/NUSTitle.h @@ -22,34 +22,43 @@ #include "NUSDataProviderWUD.h" #include "NUSDecryption.h" #include "Ticket.h" +#include "utils/StringTools.h" #include #include #include +#include class NUSTitle { public: ~NUSTitle(); - std::shared_ptr dataProcessor; - std::shared_ptr tmd; - std::shared_ptr ticket; + std::unique_ptr dataProcessor; + std::unique_ptr tmd; + std::unique_ptr ticket; std::shared_ptr fst; std::shared_ptr decryption; std::shared_ptr dataProvider; - static std::optional> loadTitleFromGMPartition( - const std::shared_ptr &pPartition, - const std::shared_ptr &pDrive, + static std::optional> loadTitleFromGMPartition( + std::shared_ptr pPartition, + std::shared_ptr pDiscReader, const std::array &commonKey); -private: - static std::optional> loadTitle(const std::shared_ptr &dataProvider, const std::array &commonKey); + std::string getLongnameEn(); - NUSTitle(std::shared_ptr pTMD, - std::shared_ptr pProcessor, + std::string getShortnameEn(); + +private: + std::optional longname_en; + std::optional shortname_en; + + static std::optional> make_unique(std::unique_ptr dataProvider, const std::array &commonKey); + + NUSTitle(std::unique_ptr pTMD, + std::unique_ptr pProcessor, std::shared_ptr pDataProvider, std::shared_ptr pDecryption, - std::shared_ptr pTicket, + std::unique_ptr pTicket, std::shared_ptr pFST); }; \ No newline at end of file diff --git a/source/WUD/Ticket.cpp b/source/WUD/Ticket.cpp index ce1ce0a..413f93b 100644 --- a/source/WUD/Ticket.cpp +++ b/source/WUD/Ticket.cpp @@ -22,9 +22,9 @@ Ticket::Ticket(const std::array &pEncryptedKey, const std::array> Ticket::make_shared(const std::vector &data, std::optional> commonKey) { +std::optional> Ticket::make_unique(const std::vector &data, std::optional> commonKey) { if (data.size() <= 0x1DC + 0x10) { - DEBUG_FUNCTION_LINE("Not enough data to parse a ticket"); + DEBUG_FUNCTION_LINE_ERR("Not enough data to parse a ticket"); return {}; } @@ -46,6 +46,10 @@ std::optional> Ticket::make_shared(const std::vector(new Ticket(encryptedKey, decryptedKey)); + auto ticket = new (std::nothrow) Ticket(encryptedKey, decryptedKey); + if (!ticket) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate Ticket"); + return {}; + } + return std::unique_ptr(ticket); } diff --git a/source/WUD/Ticket.h b/source/WUD/Ticket.h index a42424c..b2ace75 100644 --- a/source/WUD/Ticket.h +++ b/source/WUD/Ticket.h @@ -29,7 +29,7 @@ public: std::array ticketKeyEnc; std::array ticketKeyDec; - static std::optional> make_shared(const std::vector &data, std::optional> commonKey); + static std::optional> make_unique(const std::vector &data, std::optional> commonKey); private: Ticket(const std::array &encryptedKey, const std::array &decryptedKey); diff --git a/source/WUD/content/WiiUContentsInformation.cpp b/source/WUD/content/WiiUContentsInformation.cpp index eaf2eea..f156646 100644 --- a/source/WUD/content/WiiUContentsInformation.cpp +++ b/source/WUD/content/WiiUContentsInformation.cpp @@ -19,24 +19,24 @@ uint32_t WiiUContentsInformation::LENGTH = 32768; -std::optional> WiiUContentsInformation::make_unique(const std::shared_ptr &discReader, uint32_t offset) { +std::optional> WiiUContentsInformation::make_unique(std::shared_ptr &discReader, uint32_t offset) { uint32_t curOffset = offset; auto discContentHeaderOpt = WiiUDiscContentsHeader::make_unique(discReader, curOffset); if (!discContentHeaderOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to read WiiUDiscContentsHeader"); + DEBUG_FUNCTION_LINE_ERR("Failed to read WiiUDiscContentsHeader"); return {}; } curOffset += WiiUDiscContentsHeader::LENGTH; auto partitionsOpt = WiiUPartitions::make_unique(discReader, curOffset, discContentHeaderOpt.value()->numberOfPartition, discContentHeaderOpt.value()->blockSize); if (!partitionsOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to read Partitions"); + DEBUG_FUNCTION_LINE_ERR("Failed to read Partitions"); return {}; } curOffset += WiiUPartitions::LENGTH; if (curOffset - offset != LENGTH) { - DEBUG_FUNCTION_LINE("Unexpected offset"); + DEBUG_FUNCTION_LINE_ERR("Unexpected offset"); return {}; } @@ -45,9 +45,7 @@ std::optional> WiiUContentsInformation: std::move(partitionsOpt.value()))); } - WiiUContentsInformation::WiiUContentsInformation(std::unique_ptr pDiscContentHeader, std::unique_ptr pPartitions) : discContentHeader(std::move(pDiscContentHeader)), - partitions(std::move(pPartitions)){ - - }; + partitions(std::move(pPartitions)) { +} diff --git a/source/WUD/content/WiiUContentsInformation.h b/source/WUD/content/WiiUContentsInformation.h index 79031d6..74c531b 100644 --- a/source/WUD/content/WiiUContentsInformation.h +++ b/source/WUD/content/WiiUContentsInformation.h @@ -30,7 +30,7 @@ public: static uint32_t LENGTH; - static std::optional> make_unique(const std::shared_ptr &discReader, uint32_t offset); + static std::optional> make_unique(std::shared_ptr &discReader, uint32_t offset); private: WiiUContentsInformation(std::unique_ptr pDiscContentsHeader, std::unique_ptr pPartitions); diff --git a/source/WUD/content/WiiUDiscContentsHeader.cpp b/source/WUD/content/WiiUDiscContentsHeader.cpp index 1eeaf73..3faf617 100644 --- a/source/WUD/content/WiiUDiscContentsHeader.cpp +++ b/source/WUD/content/WiiUDiscContentsHeader.cpp @@ -15,36 +15,37 @@ * along with this program. If not, see . ****************************************************************************/ #include "WiiUDiscContentsHeader.h" +#include "utils/utils.h" #include #include -std::optional> WiiUDiscContentsHeader::make_unique(const std::shared_ptr &discReader, uint32_t offset) { - auto *buffer = (uint8_t *) malloc(LENGTH); +std::optional> WiiUDiscContentsHeader::make_unique(std::shared_ptr &discReader, uint32_t offset) { + auto buffer = make_unique_nothrow(LENGTH); if (!buffer) { - DEBUG_FUNCTION_LINE("Failed to alloc buffer"); + DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffer"); return {}; } if (!discReader->hasDiscKey) { - if (!discReader->readEncrypted(buffer, offset, LENGTH)) { - DEBUG_FUNCTION_LINE("Failed to read data"); + DEBUG_FUNCTION_LINE_ERR(); + if (!discReader->readEncrypted(buffer.get(), offset, LENGTH)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read data"); return {}; } } else { - if (!discReader->readDecrypted(buffer, offset, 0, LENGTH, discReader->discKey, nullptr, true)) { - DEBUG_FUNCTION_LINE("Failed to read data"); + if (!discReader->readDecrypted(buffer.get(), offset, 0, LENGTH, discReader->discKey, nullptr, true)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read data"); return {}; } } - if (((uint32_t *) buffer)[0] != MAGIC) { - DEBUG_FUNCTION_LINE("MAGIC mismatch"); + if (((uint32_t *) buffer.get())[0] != MAGIC) { + DEBUG_FUNCTION_LINE_ERR("MAGIC mismatch"); return {}; } - auto blockSize = DiscBlockSize(((uint32_t *) buffer)[1]); + auto blockSize = DiscBlockSize(((uint32_t *) buffer.get())[1]); std::array tocHash{}; memcpy(tocHash.data(), &buffer[8], 20); - auto numberOfPartition = ((uint32_t *) buffer)[7]; - free(buffer); + auto numberOfPartition = ((uint32_t *) buffer.get())[7]; return std::unique_ptr(new WiiUDiscContentsHeader(blockSize, tocHash, numberOfPartition)); } diff --git a/source/WUD/content/WiiUDiscContentsHeader.h b/source/WUD/content/WiiUDiscContentsHeader.h index d0b7997..143e618 100644 --- a/source/WUD/content/WiiUDiscContentsHeader.h +++ b/source/WUD/content/WiiUDiscContentsHeader.h @@ -33,7 +33,7 @@ public: static constexpr uint32_t LENGTH = 2048; static constexpr uint32_t MAGIC = 0xCCA6E67B; - static std::optional> make_unique(const std::shared_ptr &discReader, uint32_t offset); + static std::optional> make_unique(std::shared_ptr &discReader, uint32_t offset); private: WiiUDiscContentsHeader(DiscBlockSize pSize, const std::array &pTocHash, uint32_t pNumberOfPartitions); diff --git a/source/WUD/content/partitions/WiiUDataPartition.cpp b/source/WUD/content/partitions/WiiUDataPartition.cpp index e9459a9..e233e68 100644 --- a/source/WUD/content/partitions/WiiUDataPartition.cpp +++ b/source/WUD/content/partitions/WiiUDataPartition.cpp @@ -26,11 +26,11 @@ WiiUDataPartition::WiiUDataPartition( basePartition(std::move(pPartition)) { } -std::string WiiUDataPartition::getVolumeId() const & { +const std::string &WiiUDataPartition::getVolumeId() const { return basePartition->getVolumeId(); } -std::map> WiiUDataPartition::getVolumes() const & { +const std::map> &WiiUDataPartition::getVolumes() const { return basePartition->getVolumes(); } diff --git a/source/WUD/content/partitions/WiiUDataPartition.h b/source/WUD/content/partitions/WiiUDataPartition.h index cfc9dfd..e21d5e9 100644 --- a/source/WUD/content/partitions/WiiUDataPartition.h +++ b/source/WUD/content/partitions/WiiUDataPartition.h @@ -29,17 +29,15 @@ public: ~WiiUDataPartition() override; - [[nodiscard]] std::string getVolumeId() const & override; + [[nodiscard]] const std::string &getVolumeId() const override; - [[nodiscard]] std::map> getVolumes() const & override; + [[nodiscard]] const std::map> &getVolumes() const override; [[nodiscard]] uint16_t getFileSystemDescriptor() const override; - [[nodiscard]] uint64_t getSectionOffsetOnDefaultPartition() override; - std::shared_ptr fst; - private: + std::shared_ptr fst; std::shared_ptr basePartition; }; diff --git a/source/WUD/content/partitions/WiiUGMPartition.cpp b/source/WUD/content/partitions/WiiUGMPartition.cpp index b8229f9..475b388 100644 --- a/source/WUD/content/partitions/WiiUGMPartition.cpp +++ b/source/WUD/content/partitions/WiiUGMPartition.cpp @@ -15,23 +15,27 @@ * along with this program. If not, see . ****************************************************************************/ #include "WiiUGMPartition.h" +#include "WUD/entities/FST/FST.h" +#include "WUD/entities/TMD/Content.h" -WiiUGMPartition::WiiUGMPartition(std::shared_ptr partition, +WiiUGMPartition::WiiUGMPartition(std::unique_ptr partition, std::vector pRawTicket, std::vector pRawTMD, - std::vector pRawCert) + std::vector pRawCert, + std::string pathOnSIPartition) : WiiUPartition(), rawTicket(std::move(pRawTicket)), rawTMD(std::move(pRawTMD)), rawCert(std::move(pRawCert)), + pathOnSIPartition(std::move(pathOnSIPartition)), basePartition(std::move(partition)) { } -std::string WiiUGMPartition::getVolumeId() const & { +const std::string &WiiUGMPartition::getVolumeId() const { return basePartition->getVolumeId(); } -std::map> WiiUGMPartition::getVolumes() const & { +const std::map> &WiiUGMPartition::getVolumes() const { return basePartition->getVolumes(); } @@ -41,4 +45,4 @@ uint16_t WiiUGMPartition::getFileSystemDescriptor() const { uint64_t WiiUGMPartition::getSectionOffsetOnDefaultPartition() { return basePartition->getSectionOffsetOnDefaultPartition(); -} +} \ No newline at end of file diff --git a/source/WUD/content/partitions/WiiUGMPartition.h b/source/WUD/content/partitions/WiiUGMPartition.h index a647619..69096c9 100644 --- a/source/WUD/content/partitions/WiiUGMPartition.h +++ b/source/WUD/content/partitions/WiiUGMPartition.h @@ -23,23 +23,40 @@ class WiiUGMPartition : public WiiUPartition { public: - WiiUGMPartition(std::shared_ptr partition, + WiiUGMPartition(std::unique_ptr partition, std::vector pRawTicket, std::vector pRawTMD, - std::vector pRawCert); + std::vector pRawCert, + std::string pathOnSIPartition); - [[nodiscard]] std::string getVolumeId() const & override; + [[nodiscard]] const std::string &getVolumeId() const override; - [[nodiscard]] std::map> getVolumes() const & override; + [[nodiscard]] const std::map> &getVolumes() const override; [[nodiscard]] uint16_t getFileSystemDescriptor() const override; [[nodiscard]] uint64_t getSectionOffsetOnDefaultPartition() override; + [[nodiscard]] const std::string &getPathOnSIPartition() const { + return pathOnSIPartition; + } + + [[nodiscard]] const std::vector &getRawCert() const { + return rawCert; + } + + [[nodiscard]] const std::vector &getRawTicket() const { + return rawTicket; + } + + [[nodiscard]] const std::vector &getRawTMD() const { + return rawTMD; + } + +private: std::vector rawTicket; std::vector rawTMD; std::vector rawCert; - -private: - std::shared_ptr basePartition; + std::string pathOnSIPartition; + std::unique_ptr basePartition; }; diff --git a/source/WUD/content/partitions/WiiUPartition.cpp b/source/WUD/content/partitions/WiiUPartition.cpp index b5a346b..ed63579 100644 --- a/source/WUD/content/partitions/WiiUPartition.cpp +++ b/source/WUD/content/partitions/WiiUPartition.cpp @@ -25,63 +25,61 @@ uint64_t WiiUPartition::getSectionOffsetOnDefaultPartition() { return volumes.begin()->first.getAddressInBytes(); } -std::optional> WiiUPartition::make_shared(const std::shared_ptr &discReader, uint32_t offset, const DiscBlockSize &blockSize) { - auto buffer = (uint8_t *) malloc(LENGTH); - if (buffer == nullptr) { +std::optional> WiiUPartition::make_unique(std::shared_ptr &discReader, uint32_t offset, const DiscBlockSize &blockSize) { + // If we have the discKey, the content is encrypted but we don't know the IV. + // So in this case we read the 0x10 bytes before to the actual offset get the IV. + auto bufferReal = make_unique_nothrow(discReader->hasDiscKey ? LENGTH + 0x10 : LENGTH); + if (!bufferReal) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory"); return {}; } + uint8_t *buffer = bufferReal.get(); if (!discReader->hasDiscKey) { - if (!discReader->readEncrypted(buffer, offset, LENGTH)) { + if (!discReader->readEncrypted(bufferReal.get(), offset, LENGTH)) { return {}; } } else { - auto bufferBigger = (uint8_t *) malloc(LENGTH + 0x10); - if (bufferBigger == nullptr) { + if (offset < 0x10) { + DEBUG_FUNCTION_LINE_ERR("Tried to read from an invalid offset"); + OSFatal("Tried to read from an invalid offset"); + } + if (!discReader->readDecrypted(bufferReal.get(), offset - 0x10, 0, LENGTH + 0x10, discReader->discKey, nullptr, true)) { return {}; } - if (!discReader->readDecrypted(bufferBigger, offset - 0x10, 0, LENGTH + 0x10, discReader->discKey, nullptr, true)) { - return {}; - } - - memcpy(buffer, bufferBigger + 0x10, LENGTH); - - free(bufferBigger); + buffer = bufferReal.get() + 0x10; } char name[32]; memset(name, 0, sizeof(name)); memcpy(name, buffer, 31); - auto volumeId = name; - uint8_t num = buffer[31]; + std::string volumeId = name; + uint8_t num = buffer[31]; - std::map> volumes; + std::map> volumes; for (int i = 0; i < num; i++) { auto address = *((uint32_t *) &buffer[32 + (i * 4)]); AddressInDiscBlocks discLbaAddress = AddressInDiscBlocks(blockSize, address); - auto vh = VolumeHeader::make_shared(discReader, discLbaAddress.getAddressInBytes()); + auto vh = VolumeHeader::make_unique(discReader, discLbaAddress.getAddressInBytes()); if (!vh.has_value()) { - free(buffer); return {}; } - volumes[discLbaAddress] = vh.value(); + volumes[discLbaAddress] = std::move(vh.value()); } auto fileSystemDescriptor = ((uint16_t *) &buffer[64])[0]; - free(buffer); - return std::unique_ptr(new WiiUPartition( volumeId, - volumes, + std::move(volumes), fileSystemDescriptor)); } -std::string WiiUPartition::getVolumeId() const & { +const std::string &WiiUPartition::getVolumeId() const { return volumeId; } -std::map> WiiUPartition::getVolumes() const & { +const std::map> &WiiUPartition::getVolumes() const { return volumes; } diff --git a/source/WUD/content/partitions/WiiUPartition.h b/source/WUD/content/partitions/WiiUPartition.h index 5fe73a2..990bde5 100644 --- a/source/WUD/content/partitions/WiiUPartition.h +++ b/source/WUD/content/partitions/WiiUPartition.h @@ -18,7 +18,6 @@ #include "volumes/VolumeHeader.h" #include -#include #include #include #include @@ -32,23 +31,23 @@ public: virtual uint64_t getSectionOffsetOnDefaultPartition(); - [[nodiscard]] virtual std::string getVolumeId() const &; + [[nodiscard]] virtual const std::string &getVolumeId() const; - [[nodiscard]] virtual std::map> getVolumes() const &; + [[nodiscard]] virtual const std::map> &getVolumes() const; [[nodiscard]] virtual uint16_t getFileSystemDescriptor() const; - static std::optional> make_shared(const std::shared_ptr &discReader, uint32_t offset, const DiscBlockSize &blockSize); + static std::optional> make_unique(std::shared_ptr &discReader, uint32_t offset, const DiscBlockSize &blockSize); protected: WiiUPartition() = default; private: - WiiUPartition(char *pVolumeId, std::map> pVolumes, uint16_t pFileSystemDescriptor) - : volumeId(pVolumeId), volumes(std::move(pVolumes)), fileSystemDescriptor(pFileSystemDescriptor) { + WiiUPartition(std::string pVolumeId, std::map> pVolumes, uint16_t pFileSystemDescriptor) + : volumeId(std::move(pVolumeId)), volumes(std::move(pVolumes)), fileSystemDescriptor(pFileSystemDescriptor) { } - std::string volumeId; - std::map> volumes; + const std::string volumeId; + std::map> volumes; uint16_t fileSystemDescriptor{}; }; \ No newline at end of file diff --git a/source/WUD/content/partitions/WiiUPartitions.cpp b/source/WUD/content/partitions/WiiUPartitions.cpp index 8b16bba..09669d0 100644 --- a/source/WUD/content/partitions/WiiUPartitions.cpp +++ b/source/WUD/content/partitions/WiiUPartitions.cpp @@ -14,18 +14,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ -#include -#include - +#include "WiiUPartitions.h" #include "WiiUDataPartition.h" #include "WiiUGMPartition.h" -#include "WiiUPartitions.h" +#include +#include #include +#include bool WiiUPartitions::getFSTEntryAsByte(std::string &filePath, const std::shared_ptr &fst, const AddressInDiscBlocks &volumeAddress, - const std::shared_ptr &discReader, + std::shared_ptr &discReader, std::vector &out_data) { auto entryOpt = FSTUtils::getFSTEntryByFullPath(fst->getRootEntry(), filePath); if (!entryOpt.has_value()) { @@ -56,136 +56,148 @@ bool WiiUPartitions::getFSTEntryAsByte(std::string &filePath, } std::optional> -WiiUPartitions::make_unique(const std::shared_ptr &discReader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize &blockSize) { - std::vector> tmp; - std::vector> partitions; - partitions.reserve(numberOfPartitions); +WiiUPartitions::make_unique(std::shared_ptr &discReader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize &blockSize) { + std::vector> tmp; + std::vector> result; + result.reserve(numberOfPartitions); tmp.reserve(numberOfPartitions); for (uint32_t i = 0; i < numberOfPartitions; i++) { - auto partitionOpt = WiiUPartition::make_shared(discReader, offset + (i * 128), blockSize); + auto partitionOpt = WiiUPartition::make_unique(discReader, offset + (i * 128), blockSize); if (!partitionOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to read partition"); + DEBUG_FUNCTION_LINE_ERR("Failed to read partition"); return {}; } - tmp.push_back(partitionOpt.value()); - } - std::optional> SIPartition; - for (auto &partition : tmp) { - if (partition->getVolumeId().starts_with("SI")) { - SIPartition = partition; - break; - } + tmp.push_back(std::move(partitionOpt.value())); } - if (SIPartition.has_value()) { - for (auto const &[key, val] : SIPartition.value()->getVolumes()) { - auto volumeAddress = key; - auto volumeAddressInBytes = volumeAddress.getAddressInBytes(); - auto volumeHeader = val; + auto SIPartitionOpt = movePartitionFromList(tmp, "SI"); - std::vector fstData; - fstData.resize(volumeHeader->FSTSize); + if (!SIPartitionOpt) { + DEBUG_FUNCTION_LINE_ERR("Failed to find SI partition"); + return {}; + } - if (!discReader->hasDiscKey) { - if (!discReader->readEncrypted(fstData.data(), volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), - volumeHeader->FSTSize)) { - DEBUG_FUNCTION_LINE("Failed to read FST"); - return {}; - } - } else { - if (!discReader->readDecrypted(fstData.data(), volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), 0, volumeHeader->FSTSize, - discReader->discKey, nullptr, true)) { - DEBUG_FUNCTION_LINE("Failed to read FST"); - return {}; - } + auto SIPartition = std::move(SIPartitionOpt.value()); + + for (auto const &[key, val] : SIPartition->getVolumes()) { + auto volumeAddress = key; + auto volumeAddressInBytes = volumeAddress.getAddressInBytes(); + auto &volumeHeader = val; + + std::vector fstData; + fstData.resize(volumeHeader->FSTSize); + + if (!discReader->hasDiscKey) { + if (!discReader->readEncrypted(fstData.data(), volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), + volumeHeader->FSTSize)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read FST"); + return {}; } + } else { + if (!discReader->readDecrypted(fstData.data(), volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), 0, volumeHeader->FSTSize, + discReader->discKey, nullptr, true)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read FST"); + return {}; + } + } - auto siFST = FST::make_shared(fstData, 0, volumeHeader->blockSize); - if (!siFST.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse FST"); + auto siFST = FST::make_shared(fstData, 0, volumeHeader->blockSize); + if (!siFST.has_value()) { + DEBUG_FUNCTION_LINE_ERR("Failed to parse FST"); + return {}; + } + + for (auto &child : siFST.value()->getRootEntry()->getDirChildren()) { + std::vector bufferTicket; + std::string tikFilePath = std::string(child->getFullPath() + '/' + WUD_TICKET_FILENAME); + if (!getFSTEntryAsByte(tikFilePath, siFST.value(), volumeAddress, discReader, bufferTicket)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read FSTEntry"); return {}; } - for (auto &child : siFST.value()->getRootEntry()->getDirChildren()) { - std::vector bufferTicket; - std::string tikFilePath = std::string(child->getFullPath() + '/' + WUD_TICKET_FILENAME); - if (!getFSTEntryAsByte(tikFilePath, siFST.value(), volumeAddress, discReader, bufferTicket)) { - DEBUG_FUNCTION_LINE("Failted to read FSTEntry"); - return {}; - } - - std::vector bufferTMD; - std::string tmdFilePath = std::string(child->getFullPath() + '/' + WUD_TMD_FILENAME); - if (!getFSTEntryAsByte(tmdFilePath, siFST.value(), volumeAddress, discReader, bufferTMD)) { - DEBUG_FUNCTION_LINE("Failted to read FSTEntry"); - return {}; - } - - std::vector bufferCert; - std::string certFilePath = std::string(child->getFullPath() + '/' + WUD_CERT_FILENAME); - if (!getFSTEntryAsByte(certFilePath, siFST.value(), volumeAddress, discReader, bufferCert)) { - DEBUG_FUNCTION_LINE("Failted to read FSTEntry"); - return {}; - } - - char partitionNameRaw[0x12]; - memset(partitionNameRaw, 0, 0x12); - snprintf(partitionNameRaw, 0x11, "%016llX", *((uint64_t *) &bufferTicket[0x1DC])); - - std::string partitionName = std::string("GM") + partitionNameRaw; - - std::optional> curPartition; - for (auto &partition : tmp) { - if (partition->getVolumeId().starts_with(partitionName)) { - curPartition = partition; - break; - } - } - - if (!curPartition.has_value()) { - DEBUG_FUNCTION_LINE("Failed to find partition"); - return {}; - } - - auto gmPartition = std::shared_ptr(new WiiUGMPartition(curPartition.value(), bufferTicket, bufferTMD, bufferCert)); - partitions.push_back(gmPartition); + std::vector bufferTMD; + std::string tmdFilePath = std::string(child->getFullPath() + '/' + WUD_TMD_FILENAME); + if (!getFSTEntryAsByte(tmdFilePath, siFST.value(), volumeAddress, discReader, bufferTMD)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read FSTEntry"); + return {}; } + + std::vector bufferCert; + std::string certFilePath = std::string(child->getFullPath() + '/' + WUD_CERT_FILENAME); + if (!getFSTEntryAsByte(certFilePath, siFST.value(), volumeAddress, discReader, bufferCert)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read FSTEntry"); + return {}; + } + + char partitionNameRaw[0x12]; + memset(partitionNameRaw, 0, 0x12); + snprintf(partitionNameRaw, 0x11, "%016llX", *((uint64_t *) &bufferTicket[0x1DC])); + + std::string partitionName = std::string("GM") + partitionNameRaw; + + + auto partitionOpt = movePartitionFromList(tmp, partitionName); + if (!partitionOpt) { + DEBUG_FUNCTION_LINE_ERR("Failed to find partition %s", partitionName.c_str()); + return {}; + } + + auto gmPartition = std::unique_ptr(new WiiUGMPartition(std::move(partitionOpt.value()), bufferTicket, bufferTMD, bufferCert, child->getFullPath())); + result.push_back(std::move(gmPartition)); } } - for (auto &partition : tmp) { + auto it = tmp.begin(); + while (it != tmp.end()) { + auto &partition = *it; 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."); + DEBUG_FUNCTION_LINE_ERR("We can't handle more or less than one partition address yet."); + OSFatal("We can't handle more or less than one partition address yet."); } - auto volumeAddress = partition->getVolumes().begin()->first; - auto vh = partition->getVolumes().begin()->second; + auto &volumeAddress = partition->getVolumes().begin()->first; + auto &vh = partition->getVolumes().begin()->second; std::vector fstData; fstData.resize(vh->FSTSize); if (!discReader->hasDiscKey) { if (!discReader->readEncrypted(fstData.data(), volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), vh->FSTSize)) { + DEBUG_FUNCTION_LINE_ERR("WiiUPartition: Failed to read encrypted"); OSFatal("WiiUPartition: Failed to read encrypted"); } } else { if (!discReader->readDecrypted(fstData.data(), volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), 0, vh->FSTSize, discReader->discKey, nullptr, true)) { + DEBUG_FUNCTION_LINE_ERR("WiiUPartition: Failed to read encrypted"); OSFatal("WiiUPartition: Failed to read encrypted"); } } auto fstOpt = FST::make_shared(fstData, 0, vh->blockSize); if (!fstOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse FST"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse FST"); return {}; } - partitions.push_back(std::shared_ptr(new WiiUDataPartition(partition, fstOpt.value()))); + + auto partitionCopy = std::move(*it); + it = tmp.erase(it); + result.push_back(std::unique_ptr(new WiiUDataPartition(std::move(partitionCopy), fstOpt.value()))); } - return std::unique_ptr(new WiiUPartitions(partitions)); + return std::unique_ptr(new WiiUPartitions(std::move(result))); } WiiUPartitions::WiiUPartitions(std::vector> pPartitions) : partitions(std::move(pPartitions)) { } + +std::optional> WiiUPartitions::movePartitionFromList(std::vector> &list, std::string partitionName) { + auto siPartitionIt = std::find_if(std::begin(list), std::end(list), [partitionName](auto &partition) { return partition->getVolumeId().starts_with(partitionName); }); + if (siPartitionIt == std::end(list)) { + return {}; + } + auto SIPartition = std::move(*siPartitionIt); + list.erase(siPartitionIt); + return SIPartition; +} diff --git a/source/WUD/content/partitions/WiiUPartitions.h b/source/WUD/content/partitions/WiiUPartitions.h index 92dbcd3..040d8c9 100644 --- a/source/WUD/content/partitions/WiiUPartitions.h +++ b/source/WUD/content/partitions/WiiUPartitions.h @@ -34,18 +34,20 @@ public: static bool getFSTEntryAsByte(std::string &filePath, const std::shared_ptr &fst, const AddressInDiscBlocks &volumeAddress, - const std::shared_ptr &discReader, + std::shared_ptr &discReader, std::vector &out_data); std::vector> partitions; static constexpr uint32_t LENGTH = 30720; static std::optional> make_unique( - const std::shared_ptr &discReader, + std::shared_ptr &discReader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize &blockSize); private: explicit WiiUPartitions(std::vector> pPartitions); + + static std::optional> movePartitionFromList(std::vector> &list, std::string partitionName); }; \ No newline at end of file diff --git a/source/WUD/content/partitions/volumes/H3HashArray.cpp b/source/WUD/content/partitions/volumes/H3HashArray.cpp index 80258b6..d12f1c0 100644 --- a/source/WUD/content/partitions/volumes/H3HashArray.cpp +++ b/source/WUD/content/partitions/volumes/H3HashArray.cpp @@ -15,6 +15,7 @@ * along with this program. If not, see . ****************************************************************************/ #include "H3HashArray.h" +#include "utils/utils.h" #include #include @@ -22,16 +23,12 @@ H3HashArray::H3HashArray(uint8_t *pData, uint32_t pSize) { size = pSize; data = nullptr; if (pSize > 0) { - data = (uint8_t *) malloc(pSize); - if (data == nullptr) { + data = make_unique_nothrow(pSize); + if (!data) { OSFatal("H3HashArray: Failed to alloc"); } - memcpy(data, pData, pSize); + memcpy(data.get(), pData, pSize); } } -H3HashArray::~H3HashArray() { - if (data) { - free(data); - } -} \ No newline at end of file +H3HashArray::~H3HashArray() = default; \ No newline at end of file diff --git a/source/WUD/content/partitions/volumes/H3HashArray.h b/source/WUD/content/partitions/volumes/H3HashArray.h index 472c517..64b45aa 100644 --- a/source/WUD/content/partitions/volumes/H3HashArray.h +++ b/source/WUD/content/partitions/volumes/H3HashArray.h @@ -18,6 +18,7 @@ #include #include +#include class H3HashArray { @@ -26,6 +27,6 @@ public: ~H3HashArray(); - uint8_t *data = nullptr; + std::unique_ptr data; uint8_t size; }; diff --git a/source/WUD/content/partitions/volumes/VolumeHeader.cpp b/source/WUD/content/partitions/volumes/VolumeHeader.cpp index 01b82a8..e070645 100644 --- a/source/WUD/content/partitions/volumes/VolumeHeader.cpp +++ b/source/WUD/content/partitions/volumes/VolumeHeader.cpp @@ -22,8 +22,8 @@ uint32_t VolumeHeader::MAGIC = 0xCC93A4F5; -std::vector> VolumeHeader::getH3HashArray(uint8_t *h3Data, uint32_t pNumberOfH3HashArray, uint32_t pH3HashArrayListSize) { - std::vector> arrayList; +std::vector> VolumeHeader::getH3HashArray(uint8_t *h3Data, uint32_t pNumberOfH3HashArray, uint32_t pH3HashArrayListSize) { + std::vector> arrayList; if (pNumberOfH3HashArray == 0) { return arrayList; } @@ -37,30 +37,28 @@ std::vector> VolumeHeader::getH3HashArray(uint8_t * curEnd = offsetPtr[1]; } - arrayList.push_back(std::make_shared(h3Data + curOffset, curEnd - curOffset)); + arrayList.push_back(std::make_unique(h3Data + curOffset, curEnd - curOffset)); } return arrayList; } -std::optional> VolumeHeader::make_shared(const std::shared_ptr &discReader, uint64_t offset) { - auto buffer = (uint8_t *) malloc(64); - if (buffer == nullptr) { - DEBUG_FUNCTION_LINE("Failed to alloc buffer"); +std::optional> VolumeHeader::make_unique(std::shared_ptr &discReader, uint64_t offset) { + auto buffer = make_unique_nothrow((size_t) 64); + if (!buffer) { + DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffer"); return {}; } - if (!discReader->readEncrypted(buffer, offset, 64)) { - free(buffer); - DEBUG_FUNCTION_LINE("Failed to read data"); + if (!discReader->readEncrypted(buffer.get(), offset, 64)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read data"); return {}; } - auto *bufferUint = (uint32_t *) buffer; + auto *bufferUint = (uint32_t *) buffer.get(); if (bufferUint[0] != MAGIC) { - DEBUG_FUNCTION_LINE("MAGIC mismatch"); - free(buffer); + DEBUG_FUNCTION_LINE_ERR("MAGIC mismatch"); return {}; } @@ -76,26 +74,22 @@ std::optional> VolumeHeader::make_shared(const std auto minorVersion = buffer[39]; auto expiringMajorVersion = buffer[40]; - free(buffer); - - auto bufferH3 = (uint8_t *) malloc(ROUNDUP(h3HashArrayListSize, 16)); - if (bufferH3 == nullptr) { - DEBUG_FUNCTION_LINE("Failed to alloc h3 buffer"); + auto alignedH3ArrayListSize = ROUNDUP(h3HashArrayListSize, 16); + auto bufferH3 = make_unique_nothrow(alignedH3ArrayListSize); + if (!bufferH3) { + DEBUG_FUNCTION_LINE_ERR("Failed to alloc h3 buffer"); return {}; } - if (!discReader->readEncrypted(bufferH3, offset + 64, ROUNDUP(h3HashArrayListSize, 16))) { - DEBUG_FUNCTION_LINE("Failed to read h3 data"); - free(bufferH3); + if (!discReader->readEncrypted(bufferH3.get(), offset + 64, alignedH3ArrayListSize)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read h3 data"); return {}; } - auto h3HashArrayList = getH3HashArray(bufferH3, numberOfH3HashArray, h3HashArrayListSize); - - free(bufferH3); + auto h3HashArrayList = getH3HashArray(bufferH3.get(), numberOfH3HashArray, h3HashArrayListSize); return std::unique_ptr( - new VolumeHeader(blockSize, volumeSize, FSTSize, FSTAddress, FSTHashMode, encryptType, majorVersion, minorVersion, expiringMajorVersion, h3HashArrayList, h3HashArrayListSize, + new VolumeHeader(blockSize, volumeSize, FSTSize, FSTAddress, FSTHashMode, encryptType, majorVersion, minorVersion, expiringMajorVersion, std::move(h3HashArrayList), h3HashArrayListSize, numberOfH3HashArray)); } @@ -108,7 +102,7 @@ VolumeHeader::VolumeHeader(const VolumeBlockSize &pBlockSize, uint8_t pMajorVersion, uint8_t pMinorVersion, uint8_t pExpiringMajorVersion, - std::vector> pH3HashArrayList, + std::vector> pH3HashArrayList, uint32_t pH3HashArrayListSize, uint32_t pNumberOfH3HashArray) : blockSize(pBlockSize), volumeSize(std::move(pVolumeSize)), diff --git a/source/WUD/content/partitions/volumes/VolumeHeader.h b/source/WUD/content/partitions/volumes/VolumeHeader.h index 1b5cd82..b657309 100644 --- a/source/WUD/content/partitions/volumes/VolumeHeader.h +++ b/source/WUD/content/partitions/volumes/VolumeHeader.h @@ -31,7 +31,7 @@ class VolumeHeader { public: - static std::vector> getH3HashArray(uint8_t *h3Data, uint32_t numberOfH3HashArray, uint32_t h3HashArrayListSize); + static std::vector> getH3HashArray(uint8_t *h3Data, uint32_t numberOfH3HashArray, uint32_t h3HashArrayListSize); static uint32_t MAGIC; VolumeBlockSize blockSize; @@ -43,12 +43,12 @@ public: uint8_t majorVersion; uint8_t minorVersion; uint8_t expiringMajorVersion; - std::vector> h3HashArrayList; + std::vector> h3HashArrayList; uint32_t h3HashArrayListSize; uint32_t numberOfH3HashArray; - static std::optional> make_shared(const std::shared_ptr &discReader, uint64_t offset); + static std::optional> make_unique(std::shared_ptr &discReader, uint64_t offset); private: VolumeHeader( @@ -61,7 +61,7 @@ private: uint8_t pMajorVersion, uint8_t pMinorVersion, uint8_t pExpiringMajorVersion, - std::vector> pH3HashArrayList, + std::vector> pH3HashArrayList, uint32_t pH3HashArrayListSize, uint32_t pNumberOfH3HashArray); }; \ No newline at end of file diff --git a/source/WUD/entities/FST/FST.cpp b/source/WUD/entities/FST/FST.cpp index 02841fb..c4afc57 100644 --- a/source/WUD/entities/FST/FST.cpp +++ b/source/WUD/entities/FST/FST.cpp @@ -25,7 +25,7 @@ std::optional> FST::make_shared(const std::vector uint32_t curOffset = offset; if (curOffset + FSTHeader::LENGTH > data.size()) { - DEBUG_FUNCTION_LINE("Not enough data to parse the FSTHeader"); + DEBUG_FUNCTION_LINE_ERR("Not enough data to parse the FSTHeader"); return {}; } @@ -34,14 +34,14 @@ std::optional> FST::make_shared(const std::vector auto headerOpt = FSTHeader::make_unique(fstData); if (!headerOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse FSTHeader"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse FSTHeader"); return {}; } curOffset += FSTHeader::LENGTH; uint32_t sectionEntriesDataSize = headerOpt.value()->numberOfSections * SectionEntry::LENGTH; if (curOffset + sectionEntriesDataSize > data.size()) { - DEBUG_FUNCTION_LINE("Not enough data to parse the SectionEntries"); + DEBUG_FUNCTION_LINE_ERR("Not enough data to parse the SectionEntries"); return {}; } @@ -51,7 +51,7 @@ std::optional> FST::make_shared(const std::vector auto sectionEntriesOpt = SectionEntries::make_shared(sectionEntriesData, headerOpt.value()->numberOfSections, blockSize); if (!sectionEntriesOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse FSTHeader"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse FSTHeader"); return {}; } curOffset += sectionEntriesOpt.value()->getSizeInBytes(); @@ -65,13 +65,13 @@ std::optional> FST::make_shared(const std::vector auto stringTableOpt = StringTable::make_shared(data, stringTableOffset, lastEntryNumber); if (!stringTableOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse StringTable"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse StringTable"); return {}; } auto nodeEntriesOpt = NodeEntries::make_unique(data, curOffset, sectionEntriesOpt.value(), stringTableOpt.value(), headerOpt.value()->blockSize); if (!nodeEntriesOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse NodeEntries"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse NodeEntries"); return {}; } diff --git a/source/WUD/entities/FST/header/FSTHeader.cpp b/source/WUD/entities/FST/header/FSTHeader.cpp index 2a03da1..dfc31a8 100644 --- a/source/WUD/entities/FST/header/FSTHeader.cpp +++ b/source/WUD/entities/FST/header/FSTHeader.cpp @@ -21,7 +21,7 @@ std::optional> FSTHeader::make_unique(const std::array &data) { auto *dataAsUint = (uint32_t *) data.data(); if ((dataAsUint[0] & 0xFFFFFF00) != 0x46535400) { - DEBUG_FUNCTION_LINE("FST Header magic was wrong"); + DEBUG_FUNCTION_LINE_ERR("FST Header magic was wrong"); return {}; } auto FSTVersion = data[3]; diff --git a/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp b/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp index 17055f1..fcefa45 100644 --- a/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp @@ -24,13 +24,13 @@ DirectoryEntry::parseData(const std::array &data, co auto lastEntryNumber = ((uint32_t *) &data[8])[0]; auto stringNameOpt = stringTable->getStringEntry(param.uint24); if (!stringNameOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to get string name"); + DEBUG_FUNCTION_LINE_ERR("Failed to get string name"); return {}; } auto sectionEntryOpt = sectionEntries->getSection(param.sectionNumber); if (!sectionEntryOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to get section entry"); + DEBUG_FUNCTION_LINE_ERR("Failed to get section entry"); return {}; } diff --git a/source/WUD/entities/FST/nodeentry/FileEntry.cpp b/source/WUD/entities/FST/nodeentry/FileEntry.cpp index 8b1f2d5..f585563 100644 --- a/source/WUD/entities/FST/nodeentry/FileEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/FileEntry.cpp @@ -32,13 +32,13 @@ FileEntry::parseData(const std::array &data, auto stringNameOpt = stringTable->getStringEntry(param.uint24); if (!stringNameOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to get string name"); + DEBUG_FUNCTION_LINE_ERR("Failed to get string name"); return {}; } auto sectionEntryOpt = sectionEntries->getSection(param.sectionNumber); if (!sectionEntryOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to get section entry"); + DEBUG_FUNCTION_LINE_ERR("Failed to get section entry"); return {}; } diff --git a/source/WUD/entities/FST/nodeentry/NodeEntries.cpp b/source/WUD/entities/FST/nodeentry/NodeEntries.cpp index b74b326..a1424a7 100644 --- a/source/WUD/entities/FST/nodeentry/NodeEntries.cpp +++ b/source/WUD/entities/FST/nodeentry/NodeEntries.cpp @@ -26,7 +26,7 @@ std::optional> NodeEntries::DeserializeImpl(const std const SectionBlockSize &pBlockSize) { auto nodeEntry = NodeEntry::AutoDeserialize(pData, pOffset, pParent, pEntryNumber, pSectionEntries, pStringTable, pBlockSize); if (!nodeEntry.has_value()) { - DEBUG_FUNCTION_LINE("Failed to AutoDeserialize NodeEntry"); + DEBUG_FUNCTION_LINE_ERR("Failed to AutoDeserialize NodeEntry"); return {}; } auto asDirEntry = std::dynamic_pointer_cast(nodeEntry.value()); @@ -36,7 +36,7 @@ std::optional> NodeEntries::DeserializeImpl(const std auto entry = NodeEntries::DeserializeImpl(pData, pOffset + (curEntryNumber - asDirEntry->entryNumber) * NodeEntry::LENGTH, asDirEntry, curEntryNumber, pSectionEntries, pStringTable, pBlockSize); if (!entry.has_value()) { - DEBUG_FUNCTION_LINE("Failed to Deserialize child of NodeEntry"); + DEBUG_FUNCTION_LINE_ERR("Failed to Deserialize child of NodeEntry"); return {}; } asDirEntry->addChild(entry.value()); @@ -56,14 +56,14 @@ NodeEntries::make_unique(const std::vector &data, uint32_t offset, cons const SectionBlockSize &blockSize) { auto rootEntry = NodeEntries::DeserializeImpl(data, offset, std::nullopt, 0, pSectionEntries, pStringTable, blockSize); if (!rootEntry.has_value()) { - DEBUG_FUNCTION_LINE("DeserializeImpl for root entry has failed"); + DEBUG_FUNCTION_LINE_ERR("DeserializeImpl for root entry has failed"); return {}; } auto rootEntryCasted = std::dynamic_pointer_cast(rootEntry.value()); if (rootEntryCasted != nullptr) { return std::unique_ptr(new NodeEntries(rootEntryCasted)); } - DEBUG_FUNCTION_LINE("Failed to parse Root"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse Root"); return {}; } diff --git a/source/WUD/entities/FST/nodeentry/NodeEntry.cpp b/source/WUD/entities/FST/nodeentry/NodeEntry.cpp index 10c2b0b..0a133b8 100644 --- a/source/WUD/entities/FST/nodeentry/NodeEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/NodeEntry.cpp @@ -49,19 +49,19 @@ NodeEntry::AutoDeserialize(const std::vector &data, if ((param.type & ENTRY_TYPE_Directory) == ENTRY_TYPE_Directory && param.uint24 == 0) { // Root auto res = RootEntry::parseData(curEntryData, param, sectionEntries, stringTable); if (!res.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse node"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse node"); return {}; } return res; } else if ((param.type & ENTRY_TYPE_Directory) == ENTRY_TYPE_Directory) { auto res = DirectoryEntry::parseData(curEntryData, param, sectionEntries, stringTable); if (!res.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse node"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse node"); return {}; } auto resAsNodeEntry = std::dynamic_pointer_cast(res.value()); if (resAsNodeEntry == nullptr) { - DEBUG_FUNCTION_LINE("Failed to cast to NodeEntry"); + DEBUG_FUNCTION_LINE_ERR("Failed to cast to NodeEntry"); return {}; } return resAsNodeEntry; @@ -69,18 +69,18 @@ NodeEntry::AutoDeserialize(const std::vector &data, auto res = FileEntry::parseData(curEntryData, param, sectionEntries, stringTable, blockSize); if (!res.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse node"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse node"); return {}; } auto resAsNodeEntry = std::dynamic_pointer_cast(res.value()); if (resAsNodeEntry == nullptr) { - DEBUG_FUNCTION_LINE("Failed to cast to NodeEntry"); + DEBUG_FUNCTION_LINE_ERR("Failed to cast to NodeEntry"); return {}; } return resAsNodeEntry; } - DEBUG_FUNCTION_LINE("FST Unknown Node Type"); + DEBUG_FUNCTION_LINE_ERR("FST Unknown Node Type"); return {}; } diff --git a/source/WUD/entities/FST/nodeentry/RootEntry.cpp b/source/WUD/entities/FST/nodeentry/RootEntry.cpp index 33ce44d..20474e3 100644 --- a/source/WUD/entities/FST/nodeentry/RootEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/RootEntry.cpp @@ -32,11 +32,11 @@ RootEntry::parseData(const std::array &data, auto dir = DirectoryEntry::parseData(data, param, sectionEntries, stringTable); if (dir.has_value()) { if ((dir.value()->entryType & ENTRY_TYPE_Directory) != ENTRY_TYPE_Directory || dir.value()->entryNumber != 0) { - DEBUG_FUNCTION_LINE("Input is no root entry."); + DEBUG_FUNCTION_LINE_ERR("Input is no root entry."); return {}; } return std::shared_ptr(new RootEntry(dir.value())); } - DEBUG_FUNCTION_LINE("Failed to parse dir"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse dir"); return {}; } diff --git a/source/WUD/entities/FST/sectionentry/SectionEntries.cpp b/source/WUD/entities/FST/sectionentry/SectionEntries.cpp index 178f121..0f12682 100644 --- a/source/WUD/entities/FST/sectionentry/SectionEntries.cpp +++ b/source/WUD/entities/FST/sectionentry/SectionEntries.cpp @@ -37,13 +37,12 @@ std::optional> SectionEntries::make_shared(const std::vector> list; for (uint32_t i = 0; i < numberOfSections; i++) { if (data.size() < (i + 1) * SectionEntry::LENGTH) { - DEBUG_FUNCTION_LINE("Failed to parse SectionEntries"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse SectionEntries"); return {}; } std::array sectionEntryData{}; memcpy(sectionEntryData.data(), data.data() + (i * SectionEntry::LENGTH), SectionEntry::LENGTH); list.push_back(std::make_shared(sectionEntryData, i, pBlockSize)); - ; } return std::shared_ptr(new SectionEntries(list)); } diff --git a/source/WUD/entities/FST/stringtable/StringTable.cpp b/source/WUD/entities/FST/stringtable/StringTable.cpp index 83facbc..1f3de5d 100644 --- a/source/WUD/entities/FST/stringtable/StringTable.cpp +++ b/source/WUD/entities/FST/stringtable/StringTable.cpp @@ -22,7 +22,7 @@ std::optional> StringTable::make_shared(const std::vector &data, uint32_t offset, uint32_t stringCount) { if (offset >= data.size()) { - DEBUG_FUNCTION_LINE("Invalid offset for reading StringTable"); + DEBUG_FUNCTION_LINE_ERR("Invalid offset for reading StringTable"); return {}; } auto stringTable = std::shared_ptr(new StringTable()); @@ -35,7 +35,7 @@ std::optional> StringTable::make_shared(const std:: } if (i < stringCount) { - DEBUG_FUNCTION_LINE("stringtable is broken"); + DEBUG_FUNCTION_LINE_ERR("StringTable is broken"); return {}; } diff --git a/source/WUD/entities/TMD/TitleMetaData.cpp b/source/WUD/entities/TMD/TitleMetaData.cpp index 15ce3bc..ead4f60 100644 --- a/source/WUD/entities/TMD/TitleMetaData.cpp +++ b/source/WUD/entities/TMD/TitleMetaData.cpp @@ -19,9 +19,8 @@ #include #include -TitleMetaData::TitleMetaData(std::vector> pContentList) : contentList(std::move(pContentList)) { - - // Get Contents +TitleMetaData::TitleMetaData(uint64_t titleId, std::vector> pContentList) : contentList(std::move(pContentList)) { + this->titleId = titleId; } std::optional> TitleMetaData::getContentByIndex(uint16_t i) { @@ -33,16 +32,17 @@ std::optional> TitleMetaData::getContentByIndex(uint16_ return {}; } -std::optional> TitleMetaData::make_shared(const std::vector &data) { +std::optional> TitleMetaData::make_unique(const std::vector &data) { if (data.empty() || data.size() <= 0xB04) { return {}; } std::vector> contentList; auto contentCount = ((uint16_t *) &data[0x1DE])[0]; + auto titleID = ((uint64_t *) &data[0x18C])[0]; for (uint16_t i = 0; i < contentCount; i++) { auto curOffset = 0xB04 + (i * Content::LENGTH); if (data.size() < curOffset + Content::LENGTH) { - DEBUG_FUNCTION_LINE("Failed to parse TitleMetaData"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse TitleMetaData"); return {}; } std::array contentData{}; @@ -50,11 +50,11 @@ std::optional> TitleMetaData::make_shared(const s auto curContentOpt = Content::make_shared(contentData); if (!curContentOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to parse Content"); + DEBUG_FUNCTION_LINE_ERR("Failed to parse Content"); return {}; } contentList.push_back(curContentOpt.value()); } - return std::shared_ptr(new TitleMetaData(contentList)); + return std::unique_ptr(new TitleMetaData(titleID, contentList)); } diff --git a/source/WUD/entities/TMD/TitleMetaData.h b/source/WUD/entities/TMD/TitleMetaData.h index 552423a..1374140 100644 --- a/source/WUD/entities/TMD/TitleMetaData.h +++ b/source/WUD/entities/TMD/TitleMetaData.h @@ -28,8 +28,9 @@ public: std::optional> getContentByIndex(uint16_t index); - static std::optional> make_shared(const std::vector &data); + static std::optional> make_unique(const std::vector &data); + uint64_t titleId; private: - explicit TitleMetaData(std::vector> pContentList); + explicit TitleMetaData(uint64_t titleId, std::vector> pContentList); }; diff --git a/source/WUD/header/WiiUDiscHeader.cpp b/source/WUD/header/WiiUDiscHeader.cpp index 3025f7a..98be399 100644 --- a/source/WUD/header/WiiUDiscHeader.cpp +++ b/source/WUD/header/WiiUDiscHeader.cpp @@ -19,42 +19,42 @@ uint32_t WiiUDiscHeader::LENGTH = 131072L; -WiiUDiscHeader::WiiUDiscHeader(std::unique_ptr pManufactorDiscId, +WiiUDiscHeader::WiiUDiscHeader(std::unique_ptr pManufacturerDiscId, std::unique_ptr pDiscId, - std::unique_ptr pWiiUContentsInformation) : manufactorDiscId(std::move(pManufactorDiscId)), + std::unique_ptr pWiiUContentsInformation) : manufacturerDiscId(std::move(pManufacturerDiscId)), discId(std::move(pDiscId)), wiiUContentsInformation(std::move(pWiiUContentsInformation)) { } -std::optional> WiiUDiscHeader::make_unique(const std::shared_ptr &discReader) { +std::optional> WiiUDiscHeader::make_unique(std::shared_ptr &discReader) { if (!discReader->IsReady()) { - DEBUG_FUNCTION_LINE("DiscReader is not ready"); + DEBUG_FUNCTION_LINE_ERR("DiscReader is not ready"); return {}; } uint32_t offset = 0; uint32_t curOffset = offset; - auto manufactorDiscIDOpt = WiiUManufactorDiscId::make_unique(discReader); + auto manufactorDiscIDOpt = WiiUManufacturerDiscId::make_unique(discReader); if (!manufactorDiscIDOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to read ManufactorDiscId"); + DEBUG_FUNCTION_LINE_ERR("Failed to read ManufactorDiscId"); return {}; } - curOffset += WiiUManufactorDiscId::LENGTH; + curOffset += WiiUManufacturerDiscId::LENGTH; auto discIdOpt = WiiUDiscId::make_unique(discReader, curOffset); - if (!discIdOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to read DiscId"); + if (!discIdOpt) { + DEBUG_FUNCTION_LINE_ERR("Failed to read DiscId"); return {}; } curOffset += WiiUDiscId::LENGTH; auto wiiUContentsInformationOpt = WiiUContentsInformation::make_unique(discReader, curOffset); - if (!wiiUContentsInformationOpt.has_value()) { - DEBUG_FUNCTION_LINE("Failed to read WiiUContentsInformation"); + if (!wiiUContentsInformationOpt) { + DEBUG_FUNCTION_LINE_ERR("Failed to read WiiUContentsInformation"); return {}; } curOffset += WiiUContentsInformation::LENGTH; if (curOffset - offset != LENGTH) { - DEBUG_FUNCTION_LINE("Unexpected offset"); + DEBUG_FUNCTION_LINE_ERR("Unexpected offset"); return {}; } return std::unique_ptr(new WiiUDiscHeader( diff --git a/source/WUD/header/WiiUDiscHeader.h b/source/WUD/header/WiiUDiscHeader.h index f3dcf0f..fa39640 100644 --- a/source/WUD/header/WiiUDiscHeader.h +++ b/source/WUD/header/WiiUDiscHeader.h @@ -17,7 +17,7 @@ #pragma once #include "WiiUDiscId.h" -#include "WiiUManufactorDiscId.h" +#include "WiiUManufacturerDiscId.h" #include #include #include @@ -26,9 +26,9 @@ class WiiUDiscHeader { public: - static std::optional> make_unique(const std::shared_ptr &discReader); + static std::optional> make_unique(std::shared_ptr &discReader); - std::unique_ptr manufactorDiscId; + std::unique_ptr manufacturerDiscId; std::unique_ptr discId; std::unique_ptr wiiUContentsInformation; @@ -36,7 +36,7 @@ public: private: explicit WiiUDiscHeader( - std::unique_ptr pManufactorDiscId, + std::unique_ptr pManufacturerDiscId, std::unique_ptr pDiscId, std::unique_ptr pWiiUContentsInformation); }; \ No newline at end of file diff --git a/source/WUD/header/WiiUDiscId.cpp b/source/WUD/header/WiiUDiscId.cpp index 2fce86e..d6e8455 100644 --- a/source/WUD/header/WiiUDiscId.cpp +++ b/source/WUD/header/WiiUDiscId.cpp @@ -15,24 +15,26 @@ * along with this program. If not, see . ****************************************************************************/ #include "WiiUDiscId.h" +#include "utils/utils.h" #include #include +#include #include -std::optional> WiiUDiscId::make_unique(const std::shared_ptr &discReader, uint32_t offset) { - auto data = (uint8_t *) malloc(WiiUDiscId::LENGTH); +std::optional> WiiUDiscId::make_unique(std::shared_ptr &discReader, uint32_t offset) { + auto data = make_unique_nothrow(WiiUDiscId::LENGTH); if (data == nullptr) { - DEBUG_FUNCTION_LINE("Failed to alloc memory"); + DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory"); return {}; } - if (!discReader->readEncrypted(data, offset, WiiUDiscId::LENGTH)) { - DEBUG_FUNCTION_LINE("Failed to read data"); + if (!discReader->readEncrypted(data.get(), offset, WiiUDiscId::LENGTH)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read data"); return {}; } - if (((uint32_t *) data)[0] != WiiUDiscId::MAGIC) { - DEBUG_FUNCTION_LINE("MAGIC mismatch"); + if (((uint32_t *) data.get())[0] != WiiUDiscId::MAGIC) { + DEBUG_FUNCTION_LINE_ERR("MAGIC mismatch"); return {}; } @@ -41,12 +43,10 @@ std::optional> WiiUDiscId::make_unique(const std::sh auto footprint = std::string((char *) &data[32]); - free(data); - return std::unique_ptr(new WiiUDiscId(minorVersion, majorVersion, footprint)); } -WiiUDiscId::WiiUDiscId(uint8_t pMinorVersion, uint8_t pMajorVersion, const std::string &pFootprint) : minorVersion(pMinorVersion), - majorVersion(pMajorVersion), - footprint(pFootprint) { +WiiUDiscId::WiiUDiscId(uint8_t pMinorVersion, uint8_t pMajorVersion, std::string pFootprint) : minorVersion(pMinorVersion), + majorVersion(pMajorVersion), + footprint(std::move(pFootprint)) { } diff --git a/source/WUD/header/WiiUDiscId.h b/source/WUD/header/WiiUDiscId.h index 8e1a0b5..17a6e04 100644 --- a/source/WUD/header/WiiUDiscId.h +++ b/source/WUD/header/WiiUDiscId.h @@ -31,8 +31,8 @@ public: uint8_t majorVersion; std::string footprint; - static std::optional> make_unique(const std::shared_ptr &discReader, uint32_t offset); + static std::optional> make_unique(std::shared_ptr &discReader, uint32_t offset); private: - WiiUDiscId(uint8_t pMinorVersion, uint8_t pMajorVersion, const std::string &pFootprint); + WiiUDiscId(uint8_t pMinorVersion, uint8_t pMajorVersion, std::string pFootprint); }; diff --git a/source/WUD/header/WiiUManufactorDiscId.cpp b/source/WUD/header/WiiUManufacturerDiscId.cpp similarity index 60% rename from source/WUD/header/WiiUManufactorDiscId.cpp rename to source/WUD/header/WiiUManufacturerDiscId.cpp index 5fabbe0..0dd0aa7 100644 --- a/source/WUD/header/WiiUManufactorDiscId.cpp +++ b/source/WUD/header/WiiUManufacturerDiscId.cpp @@ -14,24 +14,24 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ -#include "WiiUManufactorDiscId.h" +#include "WiiUManufacturerDiscId.h" #include #include -std::optional> WiiUManufactorDiscId::make_unique(const std::shared_ptr &discReader) { +std::optional> WiiUManufacturerDiscId::make_unique(std::shared_ptr &discReader) { if (!discReader->IsReady()) { - DEBUG_FUNCTION_LINE("DiscReader is not ready"); + DEBUG_FUNCTION_LINE_ERR("DiscReader is not ready"); return {}; } - std::array data{}; + std::array data{}; - if (!discReader->readEncrypted(data.data(), 0, WiiUManufactorDiscId::LENGTH)) { - DEBUG_FUNCTION_LINE("Failed to read data"); + if (!discReader->readEncrypted(data.data(), 0, WiiUManufacturerDiscId::LENGTH)) { + DEBUG_FUNCTION_LINE_ERR("Failed to read data"); return {}; } - return std::unique_ptr(new WiiUManufactorDiscId(data)); + return std::unique_ptr(new WiiUManufacturerDiscId(data)); } -WiiUManufactorDiscId::WiiUManufactorDiscId(const std::array &pData) : data(pData) { +WiiUManufacturerDiscId::WiiUManufacturerDiscId(const std::array &pData) : data(pData) { this->data = pData; } \ No newline at end of file diff --git a/source/WUD/header/WiiUManufactorDiscId.h b/source/WUD/header/WiiUManufacturerDiscId.h similarity index 76% rename from source/WUD/header/WiiUManufactorDiscId.h rename to source/WUD/header/WiiUManufacturerDiscId.h index 431fdf8..a56a094 100644 --- a/source/WUD/header/WiiUManufactorDiscId.h +++ b/source/WUD/header/WiiUManufacturerDiscId.h @@ -22,15 +22,15 @@ #include #include -class WiiUManufactorDiscId { +class WiiUManufacturerDiscId { public: - static std::optional> make_unique(const std::shared_ptr &discReader); + static std::optional> make_unique(std::shared_ptr &discReader); static constexpr uint32_t LENGTH = 65536; - std::array data; + std::array data; private: - explicit WiiUManufactorDiscId(const std::array &pData); + explicit WiiUManufacturerDiscId(const std::array &pData); }; diff --git a/source/WUDDumperState.cpp b/source/WUDDumperState.cpp index 74d5d70..57bdeaf 100644 --- a/source/WUDDumperState.cpp +++ b/source/WUDDumperState.cpp @@ -18,8 +18,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -28,14 +29,16 @@ WUDDumperState::WUDDumperState(WUDDumperState::eDumpTargetFormat pTargetFormat, : targetFormat(pTargetFormat), targetDevice(pTargetDevice) { this->sectorBufSize = READ_SECTOR_SIZE * READ_NUM_SECTORS; this->state = STATE_OPEN_ODD1; + gBlockHomeButton = true; } WUDDumperState::~WUDDumperState() { if (this->oddFd >= 0) { - IOSUHAX_FSA_RawClose(gFSAfd, oddFd); + FSAEx_RawClose(__wut_devoptab_fs_client, oddFd); } free(sectorBuf); free(emptySector); + gBlockHomeButton = false; } ApplicationState::eSubState WUDDumperState::update(Input *input) { @@ -47,7 +50,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) { } if (this->state == STATE_OPEN_ODD1) { if (this->currentSector > 0) { - auto ret = IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &(this->oddFd)); + auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &(this->oddFd)); if (ret >= 0) { // continue! this->state = STATE_DUMP_DISC; @@ -61,7 +64,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) { this->state = STATE_PLEASE_INSERT_DISC; return ApplicationState::SUBSTATE_RUNNING; } - auto ret = IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &(this->oddFd)); + auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &(this->oddFd)); if (ret >= 0) { if (this->sectorBuf == nullptr) { this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize); @@ -79,7 +82,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) { return SUBSTATE_RETURN; } } else if (this->state == STATE_READ_DISC_INFO) { - if (IOSUHAX_FSA_RawRead(gFSAfd, this->sectorBuf, READ_SECTOR_SIZE, 1, 0, this->oddFd) >= 0) { + if (FSAEx_RawRead(__wut_devoptab_fs_client, this->sectorBuf, READ_SECTOR_SIZE, 1, 0, this->oddFd) >= 0) { this->discId[10] = '\0'; memcpy(this->discId.data(), sectorBuf, 10); if (this->discId[0] == 0) { @@ -96,39 +99,39 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) { this->state = STATE_DUMP_DISC_KEY; } else if (this->state == STATE_DUMP_DISC_KEY) { // Read the WiiUDiscContentsHeader to determine if we need disckey and if it's the correct one. - auto res = IOSUHAX_FSA_RawRead(gFSAfd, this->sectorBuf, READ_SECTOR_SIZE, 1, 3, this->oddFd); - uint8_t discKey[16]; + auto res = FSAEx_RawRead(__wut_devoptab_fs_client, this->sectorBuf, READ_SECTOR_SIZE, 1, 3, this->oddFd); + WUDDiscKey discKey; bool hasDiscKey = false; if (res >= 0) { if (((uint32_t *) this->sectorBuf)[0] != WiiUDiscContentsHeader::MAGIC) { - auto discKeyRes = IOSUHAX_ODM_GetDiscKey(discKey); - if (discKeyRes >= 0) { + auto discKeyRes = Mocha_ODMGetDiscKey(&discKey); + if (discKeyRes == MOCHA_RESULT_SUCCESS) { hasDiscKey = true; } } } if (hasDiscKey) { - if (!FSUtils::CreateSubfolder(StringTools::fmt("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId))) { + if (!FSUtils::CreateSubfolder(string_format("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId).c_str())) { setError(ERROR_WRITE_FAILED); return SUBSTATE_RUNNING; } - if (!FSUtils::saveBufferToFile(StringTools::fmt("%swudump/%s/game.key", getPathForDevice(targetDevice).c_str(), discId), discKey, 16)) { + if (!FSUtils::saveBufferToFile(string_format("%swudump/%s/game.key", getPathForDevice(targetDevice).c_str(), discId).c_str(), discKey.key, 16)) { setError(ERROR_WRITE_FAILED); return SUBSTATE_RUNNING; } } this->state = STATE_DUMP_DISC_START; } else if (this->state == STATE_DUMP_DISC_START) { - if (!FSUtils::CreateSubfolder(StringTools::fmt("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId))) { + if (!FSUtils::CreateSubfolder(string_format("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId).c_str())) { setError(ERROR_WRITE_FAILED); return ApplicationState::SUBSTATE_RUNNING; } if (targetFormat == DUMP_AS_WUX) { - this->fileHandle = std::make_unique(StringTools::fmt("%swudump/%s/game.wux", getPathForDevice(targetDevice).c_str(), discId), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, + this->fileHandle = std::make_unique(string_format("%swudump/%s/game.wux", getPathForDevice(targetDevice).c_str(), discId).c_str(), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, SECTOR_SIZE, targetDevice == TARGET_SD); } else { - this->fileHandle = std::make_unique(StringTools::fmt("%swudump/%s/game.wud", getPathForDevice(targetDevice).c_str(), discId), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, + this->fileHandle = std::make_unique(string_format("%swudump/%s/game.wud", getPathForDevice(targetDevice).c_str(), discId).c_str(), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, SECTOR_SIZE, targetDevice == TARGET_SD); } if (!this->fileHandle->isOpen()) { @@ -145,8 +148,13 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) { this->writtenSectors = 0; this->retryCount = 10; } else if (this->state == STATE_DUMP_DISC) { + if (buttonPressed(input, Input::BUTTON_B)) { + this->state = STATE_ABORT_CONFIRMATION; + return ApplicationState::SUBSTATE_RUNNING; + } + size_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 ((this->readResult = FSAEx_RawRead(__wut_devoptab_fs_client, sectorBuf, READ_SECTOR_SIZE, numSectors, this->currentSector, this->oddFd)) >= 0) { auto curWrittenSectors = fileHandle->writeSector((const uint8_t *) this->sectorBuf, numSectors); if (curWrittenSectors < 0) { this->setError(ERROR_WRITE_FAILED); @@ -171,15 +179,30 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) { } else { this->state = STATE_WAIT_USER_ERROR_CONFIRM; if (this->oddFd >= 0) { - IOSUHAX_FSA_RawClose(gFSAfd, this->oddFd); + FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd); this->oddFd = -1; } return ApplicationState::SUBSTATE_RUNNING; } + } else if (this->state == STATE_ABORT_CONFIRMATION) { + + if (buttonPressed(input, Input::BUTTON_B)) { + this->state = STATE_DUMP_DISC; + return ApplicationState::SUBSTATE_RUNNING; + } + proccessMenuNavigationX(input, 2); + if (buttonPressed(input, Input::BUTTON_A)) { + if (selectedOptionX == 0) { + this->state = STATE_DUMP_DISC; + return ApplicationState::SUBSTATE_RUNNING; + } else { + return ApplicationState::SUBSTATE_RETURN; + } + } } else if (this->state == STATE_WAIT_USER_ERROR_CONFIRM) { if (this->autoSkipOnError) { if (this->oddFd >= 0) { - IOSUHAX_FSA_RawClose(gFSAfd, this->oddFd); + FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd); this->oddFd = -1; } } @@ -206,10 +229,10 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) { this->currentSector += 1; this->writtenSectors += curWrittenSectors; this->readResult = 0; - } else if (input->data.buttons_d & Input::BUTTON_B) { + } else if (buttonPressed(input, Input::BUTTON_B)) { this->state = STATE_OPEN_ODD1; this->readResult = 0; - } else if (input->data.buttons_d & Input::BUTTON_Y) { + } else if (buttonPressed(input, Input::BUTTON_Y)) { this->autoSkipOnError = true; } } else if (this->state == STATE_DUMP_DISC_DONE) { @@ -278,9 +301,19 @@ void WUDDumperState::render() { WiiUScreen::drawLine(); if (!this->skippedSectors.empty()) { WiiUScreen::drawLinef("Skipped dumping %d sectors", this->skippedSectors.size()); + WiiUScreen::drawLine(); } + WiiUScreen::drawLinef("Press B to abort"); } else if (this->state == STATE_DUMP_DISC_DONE) { WiiUScreen::drawLinef("Dumping done! Press A to continue"); + } else if (this->state == STATE_ABORT_CONFIRMATION) { + WiiUScreen::drawLinef("Do you really want to abort the disc dumping?"); + WiiUScreen::drawLinef(""); + if (selectedOptionX == 0) { + WiiUScreen::drawLinef("> Continue dumping Abort dumping"); + } else { + WiiUScreen::drawLinef(" Continue dumping > Abort dumping"); + } } ApplicationState::printFooter(); diff --git a/source/WUDDumperState.h b/source/WUDDumperState.h index 1dfb98b..e45e346 100644 --- a/source/WUDDumperState.h +++ b/source/WUDDumperState.h @@ -49,6 +49,7 @@ public: STATE_DUMP_DISC_DONE, STATE_WAIT_USER_ERROR_CONFIRM, STATE_DUMP_DISC, + STATE_ABORT_CONFIRMATION, }; enum eErrorState { diff --git a/source/common/common.cpp b/source/common/common.cpp index 190c005..e897af4 100644 --- a/source/common/common.cpp +++ b/source/common/common.cpp @@ -1,7 +1,6 @@ #include "common.h" - -int32_t gFSAfd = -1; - -ntfs_md *ntfs_mounts = nullptr; -int ntfs_mount_count = 0; -BOOL gRunFromHBL = false; +ntfs_md *ntfs_mounts = nullptr; +int ntfs_mount_count = 0; +BOOL gRunFromHBL = false; +BOOL gBlockHomeButton = false; +uint32_t gBlockHomeButtonCooldown = 0; diff --git a/source/common/common.h b/source/common/common.h index 131de26..8dd231b 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -3,15 +3,17 @@ #include #include -extern int32_t gFSAfd; - #define SECTOR_SIZE 0x8000 #define READ_SECTOR_SIZE SECTOR_SIZE extern ntfs_md *ntfs_mounts; extern int ntfs_mount_count; +extern "C" FSClient *__wut_devoptab_fs_client; + extern BOOL gRunFromHBL; +extern BOOL gBlockHomeButton; +extern uint32_t gBlockHomeButtonCooldown; enum eDumpTarget { TARGET_SD, diff --git a/source/fs/FSUtils.cpp b/source/fs/FSUtils.cpp index 0faf2bd..6bbd45a 100644 --- a/source/fs/FSUtils.cpp +++ b/source/fs/FSUtils.cpp @@ -1,6 +1,7 @@ #include "FSUtils.h" #include "CFile.hpp" #include "utils/logger.h" +#include "utils/utils.h" #include #include #include @@ -20,7 +21,7 @@ int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_ uint32_t filesize = lseek(iFd, 0, SEEK_END); lseek(iFd, 0, SEEK_SET); - auto *buffer = (uint8_t *) malloc(filesize); + auto *buffer = (uint8_t *) memalign(0x40, ROUNDUP(filesize, 0x40)); if (buffer == nullptr) { close(iFd); return -2; @@ -146,7 +147,7 @@ bool FSUtils::copyFile(const std::string &in, const std::string &out) { } auto bufferSize = 1024 * 1024; - char *buf = (char *) malloc(bufferSize); + char *buf = (char *) memalign(0x40, ROUNDUP(bufferSize, 0x40)); if (buf == NULL) { return false; } diff --git a/source/fs/WUXFileWriter.cpp b/source/fs/WUXFileWriter.cpp index cedc5a2..583838c 100644 --- a/source/fs/WUXFileWriter.cpp +++ b/source/fs/WUXFileWriter.cpp @@ -16,6 +16,7 @@ ****************************************************************************/ #include "WUXFileWriter.h" #include "WUDDumperState.h" +#include "utils/StringTools.h" #include WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sectorSize, bool split) : WUDFileWriter(path, cacheSize, sectorSize, split) { @@ -30,7 +31,7 @@ WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sector this->sectorTableStart = this->tell(); this->totalSectorCount = WUD_FILE_SIZE / this->sectorSize; - this->sectorIndexTable = (void *) malloc(totalSectorCount * 4); + this->sectorIndexTable = (void *) memalign(0x40, ROUNDUP(totalSectorCount * 4, 0x40)); if (sectorIndexTable == nullptr) { DEBUG_FUNCTION_LINE("Failed to alloc"); WUDFileWriter::close(); @@ -50,7 +51,7 @@ WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sector this->sectorTableEnd -= (this->sectorTableEnd % this->sectorSize); uint64_t padding = this->sectorTableEnd - tableEnd; - auto *paddingData = (uint8_t *) malloc(padding); + auto *paddingData = (uint8_t *) memalign(0x40, ROUNDUP(padding, 0x40)); memset(paddingData, 0, padding); this->write(reinterpret_cast(paddingData), padding); free(paddingData); @@ -58,25 +59,22 @@ WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sector flush(); } + int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSectors) { - char hashOut[32]; int32_t curWrittenSectors = 0; for (uint32_t i = 0; i < numberOfSectors; i++) { uint32_t addr = ((uint32_t) buffer) + (i * this->sectorSize); - calculateHash256(reinterpret_cast(addr), this->sectorSize, reinterpret_cast(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); + std::array hashOut{}; + calculateHash256(reinterpret_cast(addr), this->sectorSize, reinterpret_cast(hashOut.data())); auto *indexTable = (uint32_t *) this->sectorIndexTable; - auto it = hashMap.find(hash); + auto it = hashMap.find(hashOut); if (it != hashMap.end()) { - indexTable[this->currentSector] = swap_uint32(this->hashMap[hash]); + indexTable[this->currentSector] = swap_uint32(this->hashMap[hashOut]); } else { indexTable[this->currentSector] = swap_uint32(this->writtenSector); - hashMap[hash] = writtenSector; + hashMap[hashOut] = writtenSector; if (isOpen()) { if (!write((uint8_t *) addr, this->sectorSize)) { DEBUG_FUNCTION_LINE("Write failed"); diff --git a/source/fs/WUXFileWriter.h b/source/fs/WUXFileWriter.h index cb39cd5..8eed01b 100644 --- a/source/fs/WUXFileWriter.h +++ b/source/fs/WUXFileWriter.h @@ -50,7 +50,7 @@ private: uint64_t sectorTableEnd; void *sectorIndexTable = nullptr; - std::map hashMap; + std::map, uint32_t> hashMap; uint32_t currentSector = 0; uint32_t writtenSector = 0; }; \ No newline at end of file diff --git a/source/fs/WriteOnlyFileWithCache.cpp b/source/fs/WriteOnlyFileWithCache.cpp index e4afdd3..af53fc8 100644 --- a/source/fs/WriteOnlyFileWithCache.cpp +++ b/source/fs/WriteOnlyFileWithCache.cpp @@ -23,8 +23,8 @@ #define SPLIT_SIZE (0x80000000) WriteOnlyFileWithCache::WriteOnlyFileWithCache(const char *path, int32_t cacheSize, bool split) : CFile(split ? std::string(path) + ".part1" : path, WriteOnly), - originalPath(path), - splitFile(split) { + splitFile(split), + originalPath(path) { if (!this->isOpen()) { return; } @@ -81,8 +81,8 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) { CFile::close(); // open the next part - DEBUG_FUNCTION_LINE("Open %s", StringTools::strfmt("%s.part%d", originalPath.c_str(), part).c_str()); - this->open(StringTools::strfmt("%s.part%d", originalPath.c_str(), part), WriteOnly); + DEBUG_FUNCTION_LINE("Open %s", string_format("%s.part%d", originalPath.c_str(), part).c_str()); + this->open(string_format("%s.part%d", originalPath.c_str(), part), WriteOnly); } if (finalWriteSize == 0) { return (int32_t) writeSize; @@ -134,8 +134,8 @@ int32_t WriteOnlyFileWithCache::seek(int64_t offset, int32_t origin) { flush(); close(); part = (offset / SPLIT_SIZE) + 1; - DEBUG_FUNCTION_LINE("Open %s", StringTools::strfmt("%s.part%d", originalPath.c_str(), part).c_str()); - this->open(StringTools::strfmt("%s.part%d", originalPath.c_str(), part), ReadWrite); + DEBUG_FUNCTION_LINE("Open %s", string_format("%s.part%d", originalPath.c_str(), part).c_str()); + this->open(string_format("%s.part%d", originalPath.c_str(), part), ReadWrite); } return CFile::seek(offset % SPLIT_SIZE, SEEK_SET); } diff --git a/source/main.cpp b/source/main.cpp index f716cd3..d14bb52 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,39 +1,48 @@ -#include -#include -#include - -#include - +#include "MainApplicationState.h" +#include "input/VPADInput.h" +#include "utils/WiiUScreen.h" +#include "utils/logger.h" #include #include #include #include #include -#include +#include +#include #include #include +#include +#include +#include -#include "MainApplicationState.h" -#include "input/VPADInput.h" -#include "utils/WiiUScreen.h" -#include "utils/logger.h" +void initMochaLib(); - -void initIOSUHax(); - -void deInitIOSUHax(); +void deInitMochaLib(); void main_loop(); -bool sIosuhaxMount = false; +bool slibMochaMount = false; + +extern "C" void ACPInitialize(); + +static uint32_t +procHomeButtonDeniedCustom(void *context) { + if (!gBlockHomeButton && gRunFromHBL) { + WHBProcStopRunning(); + } else { + gBlockHomeButtonCooldown = 5; + } + return 0; +} int main(int argc, char **argv) { - WHBLogUdpInit(); + initLogging(); DEBUG_FUNCTION_LINE("Hello from wudump!"); WHBProcInit(); WiiUScreen::Init(); - initIOSUHax(); + initMochaLib(); + ACPInitialize(); uint64_t titleID = OSGetTitleID(); if (titleID == 0x0005000013374842 || @@ -41,6 +50,12 @@ int main(int argc, char **argv) { titleID == 0x000500101004A100 || titleID == 0x000500101004A200) { gRunFromHBL = true; + + ProcUIClearCallbacks(); + ProcUIRegisterCallback(PROCUI_CALLBACK_HOME_BUTTON_DENIED, + &procHomeButtonDeniedCustom, NULL, 100); + + } else { gRunFromHBL = false; } @@ -66,7 +81,7 @@ int main(int argc, char **argv) { WPADInput::close(); if (ntfs_mounts != nullptr) { - int i = 0; + int i; for (i = 0; i < ntfs_mount_count; i++) { ntfsUnmount(ntfs_mounts[i].name, true); } @@ -78,7 +93,7 @@ int main(int argc, char **argv) { IMEnableAPD(); } - deInitIOSUHax(); + deInitMochaLib(); WiiUScreen::DeInit(); WHBProcShutdown(); @@ -97,11 +112,6 @@ void main_loop() { WPAD_CHAN_2, WPAD_CHAN_3}; - if (gFSAfd < 0 || !sIosuhaxMount) { - // state.setError(MainApplicationState::eErrorState::ERROR_IOSUHAX_FAILED); - OSFatal("IOSUHAX Failed"); - } - DEBUG_FUNCTION_LINE("Entering main loop"); while (WHBProcIsRunning()) { baseInput.reset(); @@ -119,27 +129,22 @@ void main_loop() { } } -void initIOSUHax() { - sIosuhaxMount = false; - int res = IOSUHAX_Open(nullptr); - if (res < 0) { - DEBUG_FUNCTION_LINE("IOSUHAX_open failed"); +void initMochaLib() { + slibMochaMount = false; + MochaUtilsStatus res = Mocha_InitLibrary(); + if (res != MOCHA_RESULT_SUCCESS) { + DEBUG_FUNCTION_LINE_ERR("Mocha_InitLibrary failed: %s", Mocha_GetStatusStr(res)); + OSFatal("Failed to init libmocha. Please update MochaPayload."); } else { - sIosuhaxMount = true; - gFSAfd = IOSUHAX_FSA_Open(); - if (gFSAfd < 0) { - DEBUG_FUNCTION_LINE("IOSUHAX_FSA_Open failed"); - } else { - DEBUG_FUNCTION_LINE("IOSUHAX done"); - } + slibMochaMount = true; } } -void deInitIOSUHax() { - if (sIosuhaxMount) { - if (gFSAfd >= 0) { - IOSUHAX_FSA_Close(gFSAfd); - } - IOSUHAX_Close(); +void deInitMochaLib() { + if (slibMochaMount) { + Mocha_DeinitLibrary(); } + + Mocha_sdio_disc_interface.shutdown(); + Mocha_usb_disc_interface.shutdown(); } \ No newline at end of file diff --git a/source/utils/ScreenUtils.cpp b/source/utils/ScreenUtils.cpp index 8ffc8a6..6990f15 100644 --- a/source/utils/ScreenUtils.cpp +++ b/source/utils/ScreenUtils.cpp @@ -17,7 +17,7 @@ #include "ScreenUtils.h" #include -void ScreenUtils::printTextOnScreen(ConsoleScreenID screen, int x, int y, const char *msg) { +void ScreenUtils::printTextOnScreen(ConsoleScreenID screen, uint32_t x, uint32_t y, const char *msg) { if (!msg) { return; } diff --git a/source/utils/ScreenUtils.h b/source/utils/ScreenUtils.h index 30af8ad..93eaf02 100644 --- a/source/utils/ScreenUtils.h +++ b/source/utils/ScreenUtils.h @@ -15,6 +15,7 @@ * along with this program. If not, see . ****************************************************************************/ #pragma once + #include //! Defines the ID of a display usable with OSScreen. @@ -36,7 +37,7 @@ public: \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); + static void printTextOnScreen(ConsoleScreenID screen, uint32_t x, uint32_t y, const char *msg); /** Clears the screen for the given screens diff --git a/source/utils/StringTools.cpp b/source/utils/StringTools.cpp index 14ffcfa..fcafa7a 100644 --- a/source/utils/StringTools.cpp +++ b/source/utils/StringTools.cpp @@ -24,209 +24,15 @@ * for WiiXplorer 2010 ***************************************************************************/ #include "StringTools.h" -#include -#include -#include -#include #include -#include #include -#include -#include - -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()); +bool invalidChar(unsigned char c) { + return !(c >= 0 && c < 128) || c == 0x0A || c == 0x0D; } -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 StringTools::stringSplit(const std::string &inValue, const std::string &splitter) { - std::string value = inValue; - std::vector 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); }); +void StringTools::StripUnicodeAndLineBreak(std::string &str) { + std::replace(str.begin(), str.end(), (char) 0x0A, ' '); // replace LF with space + std::replace(str.begin(), str.end(), (char) 0x0D, ' '); // replace CR with space + str.erase(remove_if(str.begin(), str.end(), invalidChar), str.end()); } \ No newline at end of file diff --git a/source/utils/StringTools.h b/source/utils/StringTools.h index d84f4ef..77e5916 100644 --- a/source/utils/StringTools.h +++ b/source/utils/StringTools.h @@ -25,71 +25,31 @@ ***************************************************************************/ #pragma once +#include "logger.h" +#include "utils.h" #include #include +#include +#include #include #include #include +template +std::string string_format(const std::string &format, Args... args) { + int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' + auto size = static_cast(size_s); + auto buf = make_unique_nothrow(size); + if (!buf) { + DEBUG_FUNCTION_LINE_ERR("string_format failed, not enough memory"); + OSFatal("string_format failed, not enough memory"); + return std::string(""); + } + std::snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} + 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 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); + static void StripUnicodeAndLineBreak(std::string &str); }; diff --git a/source/utils/WUDUtils.cpp b/source/utils/WUDUtils.cpp new file mode 100644 index 0000000..7d67af9 --- /dev/null +++ b/source/utils/WUDUtils.cpp @@ -0,0 +1,15 @@ +#include "WUDUtils.h" +#include "FSTUtils.h" + +std::optional WUDUtils::getOffsetOfContent(const std::shared_ptr &gamePartition, const std::shared_ptr &fst, const std::shared_ptr &content) { + 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.has_value()) { + DEBUG_FUNCTION_LINE_ERR("Failed to get section for Content"); + return {}; + } + return gamePartition->getSectionOffsetOnDefaultPartition() + info.value()->address.getAddressInBytes(); +} \ No newline at end of file diff --git a/source/utils/WUDUtils.h b/source/utils/WUDUtils.h new file mode 100644 index 0000000..8d69c16 --- /dev/null +++ b/source/utils/WUDUtils.h @@ -0,0 +1,11 @@ +#pragma once +#include "WUD/content/partitions/WiiUGMPartition.h" +#include "WUD/entities/FST/FST.h" +#include "WUD/entities/TMD/Content.h" +#include +#include + +class WUDUtils { +public: + static std::optional getOffsetOfContent(const std::shared_ptr &gamePartition, const std::shared_ptr &fst, const std::shared_ptr &content); +}; diff --git a/source/utils/WiiUScreen.cpp b/source/utils/WiiUScreen.cpp index b42213c..af30c38 100644 --- a/source/utils/WiiUScreen.cpp +++ b/source/utils/WiiUScreen.cpp @@ -13,7 +13,7 @@ uint32_t WiiUScreen::consoleColor = 0x041F60FF; uint32_t WiiUScreen::consoleCursorY = 0; -uint32_t WiiUScreen::ProcCallbackAcquired(void *context) { +uint32_t WiiUScreen::ProcCallbackAcquired([[maybe_unused]] void *context) { MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); if (sBufferSizeTV) { sBufferTV = MEMAllocFromFrmHeapEx(heap, sBufferSizeTV, 4); @@ -29,7 +29,7 @@ uint32_t WiiUScreen::ProcCallbackAcquired(void *context) { return 0; } -uint32_t WiiUScreen::ProcCallbackReleased(void *context) { +uint32_t WiiUScreen::ProcCallbackReleased([[maybe_unused]] void *context) { MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); MEMFreeByStateToFrmHeap(heap, CONSOLE_FRAME_HEAP_TAG); sConsoleHasForeground = FALSE; diff --git a/source/utils/WiiUScreen.h b/source/utils/WiiUScreen.h index 71819b9..672e722 100644 --- a/source/utils/WiiUScreen.h +++ b/source/utils/WiiUScreen.h @@ -27,9 +27,9 @@ class WiiUScreen { public: - static uint32_t ProcCallbackAcquired(void *context); + static uint32_t ProcCallbackAcquired([[maybe_unused]] void *context); - static uint32_t ProcCallbackReleased(void *context); + static uint32_t ProcCallbackReleased([[maybe_unused]] void *context); static bool Init(); diff --git a/source/utils/logger.c b/source/utils/logger.c new file mode 100644 index 0000000..36a73ae --- /dev/null +++ b/source/utils/logger.c @@ -0,0 +1,38 @@ +#ifdef DEBUG +#include +#include +#include +#include +#include + +uint32_t moduleLogInit = false; +uint32_t cafeLogInit = false; +uint32_t udpLogInit = false; +#endif // DEBUG + +void initLogging() { +#ifdef DEBUG + if (!(moduleLogInit = WHBLogModuleInit())) { + socket_lib_init(); + cafeLogInit = WHBLogCafeInit(); + udpLogInit = WHBLogUdpInit(); + } +#endif // DEBUG +} + +void deinitLogging() { +#ifdef DEBUG + if (moduleLogInit) { + WHBLogModuleDeinit(); + moduleLogInit = false; + } + if (cafeLogInit) { + WHBLogCafeDeinit(); + cafeLogInit = false; + } + if (udpLogInit) { + WHBLogUdpDeinit(); + udpLogInit = false; + } +#endif // DEBUG +} \ No newline at end of file diff --git a/source/utils/logger.h b/source/utils/logger.h index aabe62c..2b37b93 100644 --- a/source/utils/logger.h +++ b/source/utils/logger.h @@ -1,25 +1,57 @@ #pragma once +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include -#include +#define LOG_APP_TYPE "H" +#define LOG_APP_NAME "WUDD" -#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) -#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__) +#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__) -#define DEBUG_FUNCTION_LINE(FMT, ARGS...) \ - do { \ - WHBLogPrintf("[%23s]%30s@L%04d: " FMT, __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \ +#define LOG(LOG_FUNC, FMT, ARGS...) LOG_EX(LOG_FUNC, "", "", FMT, ##ARGS) + +#define LOG_EX(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \ + do { \ + LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \ } while (0) -#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) \ - do { \ - WHBLogWritef("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \ - } while (0) + +#ifdef DEBUG + +#ifdef VERBOSE_DEBUG +#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS) +#else +#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0) +#endif + +#define DEBUG_FUNCTION_LINE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS) + +#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) LOG(WHBLogWritef, FMT, ##ARGS) + +#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX(WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS) + +#else + +#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0) + +#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0) + +#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0) + +#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX(OSReport, "##ERROR## ", "\n", FMT, ##ARGS) + +#endif + +void initLogging(); + +void deinitLogging(); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/source/utils/utils.h b/source/utils/utils.h index 0350a77..8b46d72 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -1,12 +1,9 @@ #pragma once #include +#include #include -#ifdef __cplusplus -extern "C" { -#endif - #define LIMIT(x, min, max) \ ({ \ typeof(x) _x = x; \ @@ -37,10 +34,20 @@ unsigned long long swap_uint64(unsigned long long val); void calculateHash256(unsigned char *data, unsigned int length, unsigned char *hashOut); -#ifdef __cplusplus +template +std::unique_ptr make_unique_nothrow(Args &&...args) noexcept(noexcept(T(std::forward(args)...))) { + return std::unique_ptr(new (std::nothrow) T(std::forward(args)...)); } -#endif +template +inline typename std::unique_ptr make_unique_nothrow(size_t num) noexcept { + return std::unique_ptr(new (std::nothrow) std::remove_extent_t[num]()); +} + +template +std::shared_ptr make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::forward(args)...))) { + return std::shared_ptr(new (std::nothrow) T(std::forward(args)...)); +} class Utils { public: