mirror of
https://github.com/wiiu-env/wudd.git
synced 2024-11-22 09:59:16 +01:00
- Add SD support
- Disable auto shutdown
This commit is contained in:
parent
47cca1165d
commit
1ba090a969
@ -17,16 +17,29 @@ public:
|
||||
|
||||
virtual eSubState update(Input *input) = 0;
|
||||
|
||||
virtual void proccessMenuNavigation(Input *input, int32_t maxOptionValue) {
|
||||
virtual void proccessMenuNavigationY(Input *input, int32_t maxOptionValue) {
|
||||
if (input->data.buttons_d & Input::BUTTON_UP) {
|
||||
this->selectedOption--;
|
||||
this->selectedOptionY--;
|
||||
} else if (input->data.buttons_d & Input::BUTTON_DOWN) {
|
||||
this->selectedOption++;
|
||||
this->selectedOptionY++;
|
||||
}
|
||||
if (this->selectedOption < 0) {
|
||||
this->selectedOption = maxOptionValue;
|
||||
} else if (this->selectedOption >= maxOptionValue) {
|
||||
this->selectedOption = 0;
|
||||
if (this->selectedOptionY < 0) {
|
||||
this->selectedOptionY = maxOptionValue;
|
||||
} else if (this->selectedOptionY >= maxOptionValue) {
|
||||
this->selectedOptionY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void proccessMenuNavigationX(Input *input, int32_t maxOptionValue) {
|
||||
if (input->data.buttons_d & Input::BUTTON_LEFT) {
|
||||
this->selectedOptionX--;
|
||||
} else if (input->data.buttons_d & Input::BUTTON_RIGHT) {
|
||||
this->selectedOptionX++;
|
||||
}
|
||||
if (this->selectedOptionX < 0) {
|
||||
this->selectedOptionX = maxOptionValue;
|
||||
} else if (this->selectedOptionX >= maxOptionValue) {
|
||||
this->selectedOptionX = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,5 +59,6 @@ public:
|
||||
}
|
||||
|
||||
|
||||
int selectedOption = 0;
|
||||
int selectedOptionY = 0;
|
||||
int selectedOptionX = 0;
|
||||
};
|
@ -27,7 +27,7 @@
|
||||
|
||||
#define READ_BUFFER_SIZE (SECTOR_SIZE * 128)
|
||||
|
||||
GMPartitionsDumperState::GMPartitionsDumperState() {
|
||||
GMPartitionsDumperState::GMPartitionsDumperState(eDumpTarget pTargetDevice) : targetDevice(pTargetDevice) {
|
||||
this->sectorBufSize = SECTOR_SIZE;
|
||||
this->state = STATE_OPEN_ODD1;
|
||||
}
|
||||
@ -77,11 +77,11 @@ void GMPartitionsDumperState::render() {
|
||||
for (auto &content: partitionPair.second->tmd->contentList) {
|
||||
size += ROUNDUP(content->encryptedFileSize, 16);
|
||||
}
|
||||
WiiUScreen::drawLinef("%s %s (~%0.2f MiB)", index == (uint32_t) selectedOption ? ">" : " ", partitionPair.first->getVolumeId().c_str(), (float) size / 1024.0f / 1024.0f);
|
||||
WiiUScreen::drawLinef("%s %s (~%0.2f MiB)", index == (uint32_t) selectedOptionY ? ">" : " ", partitionPair.first->getVolumeId().c_str(), (float) size / 1024.0f / 1024.0f);
|
||||
index++;
|
||||
}
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLinef("%s Back", index == (uint32_t) selectedOption ? ">" : " ");
|
||||
WiiUScreen::drawLinef("%s Back", index == (uint32_t) selectedOptionY ? ">" : " ");
|
||||
}
|
||||
} else if (this->state == STATE_CREATE_DATA_PROVIDER) {
|
||||
WiiUScreen::drawLine("Create data provider from partition");
|
||||
@ -227,12 +227,12 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
|
||||
return SUBSTATE_RETURN;
|
||||
}
|
||||
}
|
||||
proccessMenuNavigation(input, (int32_t) gmPartitionPairs.size() + 1);
|
||||
proccessMenuNavigationY(input, (int32_t) gmPartitionPairs.size() + 1);
|
||||
if (entrySelected(input)) {
|
||||
if (selectedOption >= (int32_t) gmPartitionPairs.size()) {
|
||||
if (selectedOptionY >= (int32_t) gmPartitionPairs.size()) {
|
||||
return SUBSTATE_RETURN;
|
||||
}
|
||||
auto gmPartitionPair = gmPartitionPairs[selectedOption];
|
||||
auto gmPartitionPair = gmPartitionPairs[selectedOptionY];
|
||||
if (gmPartitionPair.first != nullptr) {
|
||||
this->curPartition = gmPartitionPair.first;
|
||||
this->curNUSTitle = gmPartitionPair.second;
|
||||
@ -243,8 +243,11 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
|
||||
return SUBSTATE_RUNNING;
|
||||
}
|
||||
|
||||
this->targetPath = StringTools::strfmt("%swudump/%s/%s", "ntfs0:/", this->discId, curPartition->getVolumeId().c_str());
|
||||
FSUtils::CreateSubfolder(targetPath.c_str());
|
||||
this->targetPath = StringTools::strfmt("%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;
|
||||
}
|
||||
|
||||
this->state = STATE_DUMP_PARTITION_TMD;
|
||||
}
|
||||
@ -388,6 +391,14 @@ void GMPartitionsDumperState::setError(GMPartitionsDumperState::eErrorState err)
|
||||
//OSEnableHomeButtonMenu(true);
|
||||
}
|
||||
|
||||
std::string GMPartitionsDumperState::getPathForDevice(eDumpTarget target) const {
|
||||
if(target == TARGET_SD){
|
||||
return "fs:/vol/external01/";
|
||||
} else if (target == TARGET_NTFS){
|
||||
return "ntfs0:/";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GMPartitionsDumperState::ErrorMessage() const {
|
||||
if (this->errorState == ERROR_MALLOC_FAILED) {
|
||||
return "ERROR_MALLOC_FAILED";
|
||||
@ -407,6 +418,9 @@ std::string GMPartitionsDumperState::ErrorMessage() const {
|
||||
if (this->errorState == ERROR_NO_GM_PARTITION) {
|
||||
return "ERROR_NO_GM_PARTITION";
|
||||
}
|
||||
if (this->errorState == ERROR_CREATE_DIR) {
|
||||
return "ERROR_CREATE_DIR";
|
||||
}
|
||||
if (this->errorState == ERROR_FAILED_TO_GET_NUSTITLE) {
|
||||
return "ERROR_FAILED_TO_GET_NUSTITLE";
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
ERROR_OPEN_ODD1,
|
||||
ERROR_PARSE_DISCHEADER,
|
||||
ERROR_NO_GM_PARTITION,
|
||||
ERROR_CREATE_DIR,
|
||||
ERROR_FAILED_TO_GET_NUSTITLE,
|
||||
ERROR_FAILED_WRITE_TMD,
|
||||
ERROR_FAILED_WRITE_TICKET,
|
||||
@ -69,7 +70,7 @@ public:
|
||||
ERROR_WRITE_CONTENT
|
||||
};
|
||||
|
||||
explicit GMPartitionsDumperState();
|
||||
explicit GMPartitionsDumperState(eDumpTarget pTargetDevice);
|
||||
|
||||
~GMPartitionsDumperState() override;
|
||||
|
||||
@ -82,6 +83,8 @@ public:
|
||||
|
||||
void setError(eErrorState err);
|
||||
|
||||
[[nodiscard]] std::string getPathForDevice(eDumpTarget target) const;
|
||||
|
||||
std::array<uint8_t, 11> discId{};
|
||||
std::array<uint8_t, 0x10> cKey{};
|
||||
|
||||
@ -107,4 +110,6 @@ public:
|
||||
[[nodiscard]] std::string ErrorDescription() const;
|
||||
|
||||
std::vector<std::pair<std::shared_ptr<WiiUGMPartition>, std::shared_ptr<NUSTitle>>> gmPartitionPairs;
|
||||
|
||||
eDumpTarget targetDevice = TARGET_SD;
|
||||
};
|
@ -40,10 +40,18 @@ void MainApplicationState::render() {
|
||||
if (this->state == STATE_WELCOME_SCREEN) {
|
||||
WiiUScreen::drawLine("Welcome to Wudump");
|
||||
WiiUScreen::drawLine("");
|
||||
WiiUScreen::drawLinef("%s Dump as WUX", this->selectedOption == 0 ? ">" : " ");
|
||||
WiiUScreen::drawLinef("%s Dump as WUD", this->selectedOption == 1 ? ">" : " ");
|
||||
WiiUScreen::drawLinef("%s Dump partition as .app", this->selectedOption == 2 ? ">" : " ");
|
||||
WiiUScreen::drawLinef("%s Exit", this->selectedOption == 3 ? ">" : " ");
|
||||
WiiUScreen::drawLinef("%s Dump as WUX", this->selectedOptionY == 0 ? ">" : " ");
|
||||
WiiUScreen::drawLinef("%s Dump as WUD", this->selectedOptionY == 1 ? ">" : " ");
|
||||
WiiUScreen::drawLinef("%s Dump partition as .app", this->selectedOptionY == 2 ? ">" : " ");
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLinef("%s Dumptarget:", this->selectedOptionY == 3 ? ">" : " ");
|
||||
if (ntfs_mount_count > 0) {
|
||||
WiiUScreen::drawLinef(" [%s] SD [%s] NTFS (USB)", dumpTarget == TARGET_SD ? "x" : " ", dumpTarget == TARGET_NTFS ? "x" : " ");
|
||||
} else {
|
||||
WiiUScreen::drawLinef(" [%s] SD ??? NTFS (USB) (not connected)", dumpTarget == TARGET_SD ? "*" : " ");
|
||||
}
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLinef("%s Exit", this->selectedOptionY == 4 ? ">" : " ");
|
||||
}
|
||||
|
||||
printFooter();
|
||||
@ -52,21 +60,33 @@ void MainApplicationState::render() {
|
||||
|
||||
ApplicationState::eSubState MainApplicationState::update(Input *input) {
|
||||
if (this->state == STATE_WELCOME_SCREEN) {
|
||||
proccessMenuNavigation(input, 4);
|
||||
proccessMenuNavigationY(input, 5);
|
||||
if (selectedOptionY == 3) {
|
||||
if (ntfs_mount_count > 0) {
|
||||
proccessMenuNavigationX(input, 2);
|
||||
if (selectedOptionX == 0) {
|
||||
dumpTarget = TARGET_SD;
|
||||
} else {
|
||||
dumpTarget = TARGET_NTFS;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) {
|
||||
if (this->selectedOptionY == 0) {
|
||||
this->state = STATE_DO_SUBSTATE;
|
||||
this->subState = std::make_unique<WUDDumperState>(WUDDumperState::DUMP_AS_WUX);
|
||||
} else if (this->selectedOption == 1) {
|
||||
this->subState = std::make_unique<WUDDumperState>(WUDDumperState::DUMP_AS_WUX, dumpTarget);
|
||||
} else if (this->selectedOptionY == 1) {
|
||||
this->state = STATE_DO_SUBSTATE;
|
||||
this->subState = std::make_unique<WUDDumperState>(WUDDumperState::DUMP_AS_WUD);
|
||||
} else if (this->selectedOption == 2) {
|
||||
this->subState = std::make_unique<WUDDumperState>(WUDDumperState::DUMP_AS_WUD, dumpTarget);
|
||||
} else if (this->selectedOptionY == 2) {
|
||||
this->state = STATE_DO_SUBSTATE;
|
||||
this->subState = std::make_unique<GMPartitionsDumperState>();
|
||||
this->subState = std::make_unique<GMPartitionsDumperState>(dumpTarget);
|
||||
} else if (this->selectedOptionY == 3) {
|
||||
//
|
||||
} else {
|
||||
SYSLaunchMenu();
|
||||
}
|
||||
this->selectedOption = 0;
|
||||
this->selectedOptionY = 0;
|
||||
}
|
||||
} else if (this->state == STATE_DO_SUBSTATE) {
|
||||
auto retSubState = this->subState->update(input);
|
||||
@ -74,7 +94,6 @@ ApplicationState::eSubState MainApplicationState::update(Input *input) {
|
||||
// keep running.
|
||||
return SUBSTATE_RUNNING;
|
||||
} else if (retSubState == SUBSTATE_RETURN) {
|
||||
DEBUG_FUNCTION_LINE("Delete sub state");
|
||||
this->subState.reset();
|
||||
this->state = STATE_WELCOME_SCREEN;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <ctime>
|
||||
#include <common/common.h>
|
||||
#include "input/Input.h"
|
||||
#include "fs/CFile.hpp"
|
||||
#include "ApplicationState.h"
|
||||
@ -46,4 +47,6 @@ private:
|
||||
std::unique_ptr<ApplicationState> subState{};
|
||||
|
||||
eGameState state = STATE_WELCOME_SCREEN;
|
||||
|
||||
eDumpTarget dumpTarget = TARGET_SD;
|
||||
};
|
@ -24,8 +24,8 @@
|
||||
#include <WUD/content/WiiUDiscContentsHeader.h>
|
||||
#include "WUDDumperState.h"
|
||||
|
||||
WUDDumperState::WUDDumperState(WUDDumperState::eDumpTargetFormat pTarget)
|
||||
: target(pTarget) {
|
||||
WUDDumperState::WUDDumperState(WUDDumperState::eDumpTargetFormat pTargetFormat, eDumpTarget pTargetDevice)
|
||||
: targetFormat(pTargetFormat), targetDevice(pTargetDevice) {
|
||||
this->sectorBufSize = READ_SECTOR_SIZE * READ_NUM_SECTORS;
|
||||
this->state = STATE_OPEN_ODD1;
|
||||
}
|
||||
@ -38,7 +38,6 @@ WUDDumperState::~WUDDumperState() {
|
||||
free(emptySector);
|
||||
}
|
||||
|
||||
|
||||
ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
||||
if (this->state == STATE_RETURN) {
|
||||
return ApplicationState::SUBSTATE_RETURN;
|
||||
@ -113,25 +112,27 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
||||
}
|
||||
|
||||
if (hasDiscKey) {
|
||||
if (!FSUtils::CreateSubfolder(StringTools::fmt("%swudump/%s", "ntfs0:/", discId))) {
|
||||
if (!FSUtils::CreateSubfolder(StringTools::fmt("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId))) {
|
||||
setError(ERROR_WRITE_FAILED);
|
||||
return SUBSTATE_RUNNING;
|
||||
}
|
||||
if (!FSUtils::saveBufferToFile(StringTools::fmt("%swudump/%s/game.key", "ntfs0:/", discId), discKey, 16)) {
|
||||
if (!FSUtils::saveBufferToFile(StringTools::fmt("%swudump/%s/game.key", getPathForDevice(targetDevice).c_str(), discId), discKey, 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", "ntfs0:/", discId))) {
|
||||
if (!FSUtils::CreateSubfolder(StringTools::fmt("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId))) {
|
||||
setError(ERROR_WRITE_FAILED);
|
||||
return ApplicationState::SUBSTATE_RUNNING;
|
||||
}
|
||||
if (target == DUMP_AS_WUX) {
|
||||
this->fileHandle = std::make_unique<WUXFileWriter>(StringTools::fmt("%swudump/%s/game.wux", "ntfs0:/", discId), CFile::WriteOnly, READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, SECTOR_SIZE);
|
||||
if (targetFormat == DUMP_AS_WUX) {
|
||||
this->fileHandle = std::make_unique<WUXFileWriter>(StringTools::fmt("%swudump/%s/game.wux", getPathForDevice(targetDevice).c_str(), discId), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS,
|
||||
SECTOR_SIZE, true);
|
||||
} else {
|
||||
this->fileHandle = std::make_unique<WUXFileWriter>(StringTools::fmt("%swudump/%s/game.wud", "ntfs0:/", discId), CFile::WriteOnly, READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, SECTOR_SIZE);
|
||||
this->fileHandle = std::make_unique<WUDFileWriter>(StringTools::fmt("%swudump/%s/game.wud", getPathForDevice(targetDevice).c_str(), discId), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS,
|
||||
SECTOR_SIZE, true);
|
||||
}
|
||||
if (!this->fileHandle->isOpen()) {
|
||||
DEBUG_FUNCTION_LINE("Failed to open file");
|
||||
@ -166,6 +167,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
||||
this->setError(ERROR_WRITE_FAILED);
|
||||
return ApplicationState::SUBSTATE_RUNNING;
|
||||
}
|
||||
this->fileHandle->finalize();
|
||||
this->fileHandle->close();
|
||||
}
|
||||
}
|
||||
@ -224,7 +226,6 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
||||
return ApplicationState::SUBSTATE_RUNNING;
|
||||
}
|
||||
|
||||
|
||||
void WUDDumperState::render() {
|
||||
WiiUScreen::clearScreen();
|
||||
ApplicationState::printHeader();
|
||||
@ -238,6 +239,8 @@ void WUDDumperState::render() {
|
||||
WiiUScreen::drawLine("Open /dev/odd01");
|
||||
} else if (this->state == STATE_PLEASE_INSERT_DISC) {
|
||||
WiiUScreen::drawLine("Please insert a Wii U disc and try again.\n\nPress A to return");
|
||||
} else if (this->state == STATE_DUMP_DISC_KEY) {
|
||||
WiiUScreen::drawLine("Read disc key");
|
||||
} else if (this->state == STATE_READ_DISC_INFO) {
|
||||
WiiUScreen::drawLine("Read disc information");
|
||||
} else if (this->state == STATE_READ_DISC_INFO_DONE) {
|
||||
@ -247,7 +250,7 @@ void WUDDumperState::render() {
|
||||
|
||||
float percent = this->currentSector / (WUD_FILE_SIZE / READ_SECTOR_SIZE * 1.0f) * 100.0f;
|
||||
WiiUScreen::drawLinef("Progress: %0.2f MiB / %5.2f MiB (%2.1f %%)", this->currentSector * (READ_SECTOR_SIZE / 1024.0f / 1024.0f), WUD_FILE_SIZE / 1024.0f / 1024.0f, percent);
|
||||
if (target == DUMP_AS_WUX) {
|
||||
if (targetFormat == DUMP_AS_WUX) {
|
||||
WiiUScreen::drawLinef("Written %0.2f MiB. Compression ratio 1:%0.2f", writtenSectors * (READ_SECTOR_SIZE / 1024.0f / 1024.0f),
|
||||
1.0f / (writtenSectors / (float) this->currentSector));
|
||||
}
|
||||
@ -324,3 +327,10 @@ std::string WUDDumperState::ErrorDescription() const {
|
||||
}
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
|
||||
std::string WUDDumperState::getPathForDevice(eDumpTarget target) const {
|
||||
if (target == TARGET_NTFS) {
|
||||
return "ntfs0:/";
|
||||
}
|
||||
return "fs:/vol/external01/";
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <input/Input.h>
|
||||
#include <common/common.h>
|
||||
#include "ApplicationState.h"
|
||||
#include "fs/WriteOnlyFileWithCache.h"
|
||||
#include "fs/WUXFileWriter.h"
|
||||
@ -61,12 +62,12 @@ public:
|
||||
ERROR_NO_DISC_FOUND
|
||||
};
|
||||
|
||||
explicit WUDDumperState(eDumpTargetFormat pTarget);
|
||||
explicit WUDDumperState(eDumpTargetFormat pTarget, eDumpTarget pTargetDevice);
|
||||
|
||||
~WUDDumperState() override;
|
||||
|
||||
eDumpState state;
|
||||
eDumpTargetFormat target;
|
||||
eDumpTargetFormat targetFormat;
|
||||
WUDDumperState::eErrorState errorState = ERROR_NONE;
|
||||
|
||||
void render() override;
|
||||
@ -79,6 +80,10 @@ public:
|
||||
|
||||
[[nodiscard]] std::string ErrorDescription() const;
|
||||
|
||||
[[nodiscard]] std::string getPathForDevice(eDumpTarget target) const;
|
||||
|
||||
eDumpTarget targetDevice = TARGET_SD;
|
||||
|
||||
void *sectorBuf = nullptr;
|
||||
|
||||
int readResult = 0;
|
||||
@ -105,4 +110,5 @@ public:
|
||||
int32_t writtenSectors{};
|
||||
|
||||
void *emptySector = nullptr;
|
||||
|
||||
};
|
@ -1,3 +1,6 @@
|
||||
#include "common.h"
|
||||
|
||||
int32_t gFSAfd = -1;
|
||||
|
||||
ntfs_md *ntfs_mounts = nullptr;
|
||||
int ntfs_mount_count = 0;
|
||||
|
@ -1,8 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <ntfs.h>
|
||||
|
||||
extern int32_t gFSAfd;
|
||||
|
||||
#define SECTOR_SIZE 0x8000
|
||||
#define READ_SECTOR_SIZE SECTOR_SIZE
|
||||
|
||||
extern ntfs_md *ntfs_mounts;
|
||||
extern int ntfs_mount_count;
|
||||
|
||||
enum eDumpTarget {
|
||||
TARGET_SD,
|
||||
TARGET_NTFS
|
||||
};
|
@ -40,7 +40,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void close();
|
||||
void close();
|
||||
|
||||
virtual int32_t read(uint8_t *ptr, size_t size);
|
||||
|
||||
@ -50,7 +50,7 @@ public:
|
||||
|
||||
virtual int32_t seek(int64_t offset, int32_t origin);
|
||||
|
||||
[[nodiscard]] uint64_t tell() const {
|
||||
[[nodiscard]] virtual uint64_t tell() const {
|
||||
return pos;
|
||||
};
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
#include <utils/logger.h>
|
||||
#include "WUDFileWriter.h"
|
||||
|
||||
WUDFileWriter::WUDFileWriter(const char *path, eOpenTypes mode, int32_t cacheSize, int32_t pSectorSize) :
|
||||
WriteOnlyFileWithCache(path, mode, cacheSize),
|
||||
WUDFileWriter::WUDFileWriter(const char *path, int32_t cacheSize, int32_t pSectorSize, bool split) :
|
||||
WriteOnlyFileWithCache(path, cacheSize, split),
|
||||
sectorSize(pSectorSize) {
|
||||
}
|
||||
|
||||
@ -30,6 +30,6 @@ int32_t WUDFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSecto
|
||||
return -1;
|
||||
}
|
||||
|
||||
WUDFileWriter::~WUDFileWriter() {
|
||||
WUDFileWriter::close();
|
||||
void WUDFileWriter::finalize() {
|
||||
|
||||
}
|
||||
|
@ -20,12 +20,11 @@
|
||||
|
||||
class WUDFileWriter : public WriteOnlyFileWithCache {
|
||||
public:
|
||||
WUDFileWriter(const char *string, eOpenTypes types, int32_t cacheSize, int32_t sectorSize);
|
||||
|
||||
~WUDFileWriter() override;
|
||||
WUDFileWriter(const char *string, int32_t cacheSize, int32_t sectorSize, bool split = false);
|
||||
|
||||
virtual int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors);
|
||||
|
||||
virtual void finalize();
|
||||
protected:
|
||||
int32_t sectorSize;
|
||||
};
|
||||
|
@ -18,8 +18,8 @@
|
||||
#include "WUXFileWriter.h"
|
||||
#include "WUDDumperState.h"
|
||||
|
||||
WUXFileWriter::WUXFileWriter(const char *path, CFile::eOpenTypes mode, int32_t cacheSize, int32_t sectorSize) :
|
||||
WUDFileWriter(path, mode, cacheSize, sectorSize) {
|
||||
WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sectorSize, bool split) :
|
||||
WUDFileWriter(path, cacheSize, sectorSize, split) {
|
||||
wuxHeader_t wuxHeader = {0};
|
||||
wuxHeader.magic0 = WUX_MAGIC_0;
|
||||
wuxHeader.magic1 = WUX_MAGIC_1;
|
||||
@ -28,7 +28,6 @@ WUXFileWriter::WUXFileWriter(const char *path, CFile::eOpenTypes mode, int32_t c
|
||||
wuxHeader.flags = 0;
|
||||
|
||||
this->write((uint8_t *) &wuxHeader, sizeof(wuxHeader_t));
|
||||
this->flush();
|
||||
this->sectorTableStart = this->tell();
|
||||
this->totalSectorCount = WUD_FILE_SIZE / this->sectorSize;
|
||||
|
||||
@ -44,7 +43,6 @@ WUXFileWriter::WUXFileWriter(const char *path, CFile::eOpenTypes mode, int32_t c
|
||||
WUDFileWriter::close();
|
||||
return;
|
||||
}
|
||||
this->flush();
|
||||
|
||||
this->sectorTableEnd = this->tell();
|
||||
uint64_t tableEnd = this->sectorTableEnd;
|
||||
@ -56,9 +54,9 @@ WUXFileWriter::WUXFileWriter(const char *path, CFile::eOpenTypes mode, int32_t c
|
||||
auto *paddingData = (uint8_t *) malloc(padding);
|
||||
memset(paddingData, 0, padding);
|
||||
this->write(reinterpret_cast<const uint8_t *>(paddingData), padding);
|
||||
this->flush();
|
||||
free(paddingData);
|
||||
this->hashMap.clear();
|
||||
flush();
|
||||
}
|
||||
|
||||
int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSectors) {
|
||||
@ -96,18 +94,22 @@ int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSecto
|
||||
|
||||
void WUXFileWriter::writeSectorIndexTable() {
|
||||
if (this->isOpen()) {
|
||||
flush();
|
||||
// We need to make sure to call CFile::seek!
|
||||
CFile::seek((int64_t) sectorTableStart, SEEK_SET);
|
||||
CFile::write((uint8_t *) sectorIndexTable, totalSectorCount * 4);
|
||||
seek((int64_t) sectorTableStart, SEEK_SET_BASE_CLASS);
|
||||
write((uint8_t *) sectorIndexTable, totalSectorCount * 4);
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
void WUXFileWriter::close() {
|
||||
writeSectorIndexTable();
|
||||
CFile::close();
|
||||
}
|
||||
|
||||
WUXFileWriter::~WUXFileWriter() {
|
||||
WUXFileWriter::close();
|
||||
free(sectorIndexTable);
|
||||
}
|
||||
|
||||
void WUXFileWriter::finalize() {
|
||||
WUDFileWriter::finalize();
|
||||
writeSectorIndexTable();
|
||||
WUXFileWriter::close();
|
||||
|
||||
}
|
||||
|
@ -33,13 +33,13 @@ typedef struct {
|
||||
|
||||
class WUXFileWriter : public WUDFileWriter {
|
||||
public:
|
||||
WUXFileWriter(const char *string, eOpenTypes types, int32_t cacheSize, int32_t pSectorSize);
|
||||
WUXFileWriter(const char *string, int32_t cacheSize, int32_t pSectorSize, bool split = false);
|
||||
|
||||
~WUXFileWriter() override;
|
||||
|
||||
int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors) override;
|
||||
|
||||
void close() override;
|
||||
void finalize() override;
|
||||
|
||||
private:
|
||||
void writeSectorIndexTable();
|
||||
|
@ -17,9 +17,14 @@
|
||||
#include <malloc.h>
|
||||
#include <coreinit/memory.h>
|
||||
#include <utils/logger.h>
|
||||
#include <utils/StringTools.h>
|
||||
#include "WriteOnlyFileWithCache.h"
|
||||
|
||||
WriteOnlyFileWithCache::WriteOnlyFileWithCache(const char *path, CFile::eOpenTypes mode, int32_t cacheSize) : CFile(path, mode) {
|
||||
#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) {
|
||||
if (!this->isOpen()) {
|
||||
return;
|
||||
}
|
||||
@ -50,20 +55,54 @@ bool WriteOnlyFileWithCache::flush() {
|
||||
}
|
||||
|
||||
int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
|
||||
if (writeSize == this->writeBufferSize) {
|
||||
auto finalAddr = addr;
|
||||
size_t finalWriteSize = writeSize;
|
||||
if (splitFile) {
|
||||
if (pos + writeBufferPos + finalWriteSize >= SPLIT_SIZE) {
|
||||
DEBUG_FUNCTION_LINE("We need to split");
|
||||
if (!flush()) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
uint32_t realWriteSize = SPLIT_SIZE - pos;
|
||||
|
||||
if (realWriteSize > 0) {
|
||||
DEBUG_FUNCTION_LINE("Write remaining %016lld bytes", realWriteSize);
|
||||
if (CFile::write(reinterpret_cast<const uint8_t *>(addr), realWriteSize) != (int32_t) realWriteSize) {
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
finalWriteSize = writeSize - realWriteSize;
|
||||
finalAddr = (uint8_t *) ((uint32_t) addr + realWriteSize);
|
||||
part++;
|
||||
if (!flush()) {
|
||||
return -2;
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (finalWriteSize == 0) {
|
||||
return (int32_t) writeSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (finalWriteSize == this->writeBufferSize) {
|
||||
if (!this->flush()) {
|
||||
DEBUG_FUNCTION_LINE("Flush failed");
|
||||
return -1;
|
||||
}
|
||||
return CFile::write(reinterpret_cast<const uint8_t *>(addr), writeSize);
|
||||
return CFile::write(reinterpret_cast<const uint8_t *>(addr), finalWriteSize);
|
||||
}
|
||||
|
||||
auto toWrite = (int32_t) writeSize;
|
||||
auto toWrite = (int32_t) finalWriteSize;
|
||||
if (toWrite == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t written = 0;
|
||||
auto written = (int32_t) (writeSize - finalWriteSize);
|
||||
|
||||
do {
|
||||
int32_t curWrite = toWrite;
|
||||
@ -71,7 +110,7 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
|
||||
if (this->writeBufferPos + curWrite > this->writeBufferSize) {
|
||||
curWrite = this->writeBufferSize - this->writeBufferPos;
|
||||
}
|
||||
OSBlockMove((void *) (((uint32_t) this->writeBuffer) + this->writeBufferPos), (void *) (addr + written), curWrite, 1);
|
||||
OSBlockMove((void *) (((uint32_t) this->writeBuffer) + this->writeBufferPos), (void *) (finalAddr + written), curWrite, 1);
|
||||
this->writeBufferPos += curWrite;
|
||||
|
||||
if (this->writeBufferPos == this->writeBufferSize) {
|
||||
@ -88,6 +127,20 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
|
||||
}
|
||||
|
||||
int32_t WriteOnlyFileWithCache::seek(int64_t offset, int32_t origin) {
|
||||
// Hacky trick because we may need a seek.
|
||||
if (origin == SEEK_SET_BASE_CLASS) {
|
||||
if (splitFile) {
|
||||
if ((offset / SPLIT_SIZE) + 1 != part) {
|
||||
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);
|
||||
}
|
||||
return CFile::seek(offset % SPLIT_SIZE, SEEK_SET);
|
||||
}
|
||||
return CFile::seek(offset, SEEK_SET);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,11 @@
|
||||
|
||||
#include <fs/CFile.hpp>
|
||||
|
||||
#define SEEK_SET_BASE_CLASS 0x4242
|
||||
|
||||
class WriteOnlyFileWithCache : public CFile {
|
||||
public:
|
||||
WriteOnlyFileWithCache(const char *string, eOpenTypes types, int32_t cacheSize);
|
||||
WriteOnlyFileWithCache(const char *string, int32_t cacheSize, bool split = false);
|
||||
|
||||
~WriteOnlyFileWithCache() override;
|
||||
|
||||
@ -30,9 +32,17 @@ public:
|
||||
|
||||
int32_t read(uint8_t *ptr, size_t size) override;
|
||||
|
||||
[[nodiscard]] uint64_t tell() const override {
|
||||
return pos + writeBufferPos;
|
||||
};
|
||||
|
||||
bool flush();
|
||||
|
||||
void *writeBuffer = nullptr;
|
||||
size_t writeBufferSize;
|
||||
size_t writeBufferPos;
|
||||
|
||||
bool splitFile = false;
|
||||
int32_t part = 1;
|
||||
std::string originalPath;
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <iosuhax.h>
|
||||
#include <ntfs.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/energysaver.h>
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "utils/WiiUScreen.h"
|
||||
@ -23,9 +24,6 @@ void main_loop();
|
||||
bool sIosuhaxMount = false;
|
||||
|
||||
|
||||
ntfs_md *ntfs_mounts = nullptr;
|
||||
int ntfs_mount_count = 0;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
WHBLogUdpInit();
|
||||
DEBUG_FUNCTION_LINE("Hello from wudump!");
|
||||
@ -37,6 +35,14 @@ int main(int argc, char **argv) {
|
||||
//DEBUG_FUNCTION_LINE("init fat");
|
||||
//fatInitDefault();
|
||||
|
||||
uint32_t isAPDEnabled;
|
||||
IMIsAPDEnabled(&isAPDEnabled);
|
||||
|
||||
if (isAPDEnabled) {
|
||||
DEBUG_FUNCTION_LINE("Disable auto shutdown");
|
||||
IMDisableAPD();
|
||||
}
|
||||
|
||||
ntfs_mount_count = ntfsMountAll((ntfs_md **) &ntfs_mounts, NTFS_DEFAULT | NTFS_RECOVER);
|
||||
|
||||
for (int i = 0; i < ntfs_mount_count; i++) {
|
||||
@ -53,6 +59,11 @@ int main(int argc, char **argv) {
|
||||
free(ntfs_mounts);
|
||||
}
|
||||
|
||||
if (isAPDEnabled) {
|
||||
DEBUG_FUNCTION_LINE("Enable auto shutdown");
|
||||
IMEnableAPD();
|
||||
}
|
||||
|
||||
deInitIOSUHax();
|
||||
|
||||
WiiUScreen::DeInit();
|
||||
|
Loading…
Reference in New Issue
Block a user