- Add SD support

- Disable auto shutdown
This commit is contained in:
Maschell 2021-10-16 13:03:32 +02:00
parent 47cca1165d
commit 1ba090a969
17 changed files with 236 additions and 78 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,6 @@
#include "common.h"
int32_t gFSAfd = -1;
ntfs_md *ntfs_mounts = nullptr;
int ntfs_mount_count = 0;

View File

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

View File

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

View File

@ -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() {
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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