Fix handling of discs without a discId

This commit is contained in:
Maschell 2022-07-27 19:00:56 +02:00
parent 05aea5756b
commit 7c3997775c
5 changed files with 39 additions and 18 deletions

View File

@ -7,7 +7,7 @@ Features:
- Dump the GM Partitions (Game, Updates, DLCs) of an Wii U 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. - 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). Files will be dumped to `/wudump/[DISC-ID]/`. The disc id of a game can be found on the disc (e.g. WUP-P-ARDP for the EUR version of Super Mario 3D World). If WUDD fails to determine the disc id, "DISC" with a timestamp will be used instead.
## How to merge splitted files ## How to merge splitted files

View File

@ -32,6 +32,7 @@ GMPartitionsDumperState::GMPartitionsDumperState(eDumpTarget pTargetDevice) : ta
this->sectorBufSize = SECTOR_SIZE; this->sectorBufSize = SECTOR_SIZE;
this->state = STATE_OPEN_ODD1; this->state = STATE_OPEN_ODD1;
gBlockHomeButton = true; gBlockHomeButton = true;
dumpStartDate = OSGetTime();
} }
GMPartitionsDumperState::~GMPartitionsDumperState() { GMPartitionsDumperState::~GMPartitionsDumperState() {
@ -198,11 +199,6 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
if (FSAEx_RawRead(__wut_devoptab_fs_client, 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'; this->discId[10] = '\0';
memcpy(this->discId.data(), sectorBuf, 10); memcpy(this->discId.data(), sectorBuf, 10);
if (this->discId[0] == 0) {
setError(ERROR_NO_DISC_ID);
return ApplicationState::SUBSTATE_RUNNING;
}
this->state = STATE_READ_DISC_INFO_DONE; this->state = STATE_READ_DISC_INFO_DONE;
return ApplicationState::SUBSTATE_RUNNING; return ApplicationState::SUBSTATE_RUNNING;
} }
@ -278,7 +274,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
return SUBSTATE_RUNNING; return SUBSTATE_RUNNING;
} }
this->targetPath = string_format("%swudump/%s/%s", getPathForDevice(targetDevice).c_str(), this->discId, curPartition->getVolumeId().c_str()); this->targetPath = string_format("%swudump/%s/%s", getPathForDevice(targetDevice).c_str(), getPathNameForDisc().c_str(), curPartition->getVolumeId().c_str());
if (!FSUtils::CreateSubfolder(targetPath.c_str())) { if (!FSUtils::CreateSubfolder(targetPath.c_str())) {
this->setError(ERROR_CREATE_DIR); this->setError(ERROR_CREATE_DIR);
return SUBSTATE_RUNNING; return SUBSTATE_RUNNING;
@ -557,3 +553,14 @@ std::string GMPartitionsDumperState::ErrorDescription() const {
} }
return "UNKNOWN_ERROR"; return "UNKNOWN_ERROR";
} }
std::string GMPartitionsDumperState::getPathNameForDisc() {
if (this->discId[0] == '\0') {
OSCalendarTime tm;
OSTicksToCalendarTime(this->dumpStartDate, &tm);
return string_format("DISC-%04d-%02d-%02d-%02d-%02d-%02d",
tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
return std::string((char *) &discId[0]);
}

View File

@ -114,4 +114,8 @@ public:
std::vector<std::pair<std::shared_ptr<WiiUGMPartition>, std::shared_ptr<NUSTitle>>> gmPartitionPairs; std::vector<std::pair<std::shared_ptr<WiiUGMPartition>, std::shared_ptr<NUSTitle>>> gmPartitionPairs;
eDumpTarget targetDevice = TARGET_SD; eDumpTarget targetDevice = TARGET_SD;
std::string getPathNameForDisc();
OSTime dumpStartDate;
}; };

View File

@ -30,6 +30,7 @@ WUDDumperState::WUDDumperState(WUDDumperState::eDumpTargetFormat pTargetFormat,
this->sectorBufSize = READ_SECTOR_SIZE * READ_NUM_SECTORS; this->sectorBufSize = READ_SECTOR_SIZE * READ_NUM_SECTORS;
this->state = STATE_OPEN_ODD1; this->state = STATE_OPEN_ODD1;
gBlockHomeButton = true; gBlockHomeButton = true;
this->dumpStartDate = OSGetTime();
} }
WUDDumperState::~WUDDumperState() { WUDDumperState::~WUDDumperState() {
@ -85,10 +86,6 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
if (FSAEx_RawRead(__wut_devoptab_fs_client, 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'; this->discId[10] = '\0';
memcpy(this->discId.data(), sectorBuf, 10); memcpy(this->discId.data(), sectorBuf, 10);
if (this->discId[0] == 0) {
setError(ERROR_NO_DISC_ID);
return ApplicationState::SUBSTATE_RUNNING;
}
this->state = STATE_READ_DISC_INFO_DONE; this->state = STATE_READ_DISC_INFO_DONE;
return ApplicationState::SUBSTATE_RUNNING; return ApplicationState::SUBSTATE_RUNNING;
} }
@ -112,26 +109,26 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
} }
if (hasDiscKey) { if (hasDiscKey) {
if (!FSUtils::CreateSubfolder(string_format("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId).c_str())) { if (!FSUtils::CreateSubfolder(string_format("%swudump/%s", getPathForDevice(targetDevice).c_str(), getPathNameForDisc().c_str()).c_str())) {
setError(ERROR_WRITE_FAILED); setError(ERROR_WRITE_FAILED);
return SUBSTATE_RUNNING; return SUBSTATE_RUNNING;
} }
if (!FSUtils::saveBufferToFile(string_format("%swudump/%s/game.key", getPathForDevice(targetDevice).c_str(), discId).c_str(), discKey.key, 16)) { if (!FSUtils::saveBufferToFile(string_format("%swudump/%s/game.key", getPathForDevice(targetDevice).c_str(), getPathNameForDisc().c_str()).c_str(), discKey.key, 16)) {
setError(ERROR_WRITE_FAILED); setError(ERROR_WRITE_FAILED);
return SUBSTATE_RUNNING; return SUBSTATE_RUNNING;
} }
} }
this->state = STATE_DUMP_DISC_START; this->state = STATE_DUMP_DISC_START;
} else if (this->state == STATE_DUMP_DISC_START) { } else if (this->state == STATE_DUMP_DISC_START) {
if (!FSUtils::CreateSubfolder(string_format("%swudump/%s", getPathForDevice(targetDevice).c_str(), discId).c_str())) { if (!FSUtils::CreateSubfolder(string_format("%swudump/%s", getPathForDevice(targetDevice).c_str(), getPathNameForDisc().c_str()).c_str())) {
setError(ERROR_WRITE_FAILED); setError(ERROR_WRITE_FAILED);
return ApplicationState::SUBSTATE_RUNNING; return ApplicationState::SUBSTATE_RUNNING;
} }
if (targetFormat == DUMP_AS_WUX) { if (targetFormat == DUMP_AS_WUX) {
this->fileHandle = std::make_unique<WUXFileWriter>(string_format("%swudump/%s/game.wux", getPathForDevice(targetDevice).c_str(), discId).c_str(), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, this->fileHandle = std::make_unique<WUXFileWriter>(string_format("%swudump/%s/game.wux", getPathForDevice(targetDevice).c_str(), getPathNameForDisc().c_str()).c_str(), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS,
SECTOR_SIZE, targetDevice == TARGET_SD); SECTOR_SIZE, targetDevice == TARGET_SD);
} else { } else {
this->fileHandle = std::make_unique<WUDFileWriter>(string_format("%swudump/%s/game.wud", getPathForDevice(targetDevice).c_str(), discId).c_str(), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS, this->fileHandle = std::make_unique<WUDFileWriter>(string_format("%swudump/%s/game.wud", getPathForDevice(targetDevice).c_str(), getPathNameForDisc().c_str()).c_str(), READ_SECTOR_SIZE * WRITE_BUFFER_NUM_SECTORS,
SECTOR_SIZE, targetDevice == TARGET_SD); SECTOR_SIZE, targetDevice == TARGET_SD);
} }
if (!this->fileHandle->isOpen()) { if (!this->fileHandle->isOpen()) {
@ -264,9 +261,9 @@ void WUDDumperState::render() {
} else if (this->state == STATE_READ_DISC_INFO) { } else if (this->state == STATE_READ_DISC_INFO) {
WiiUScreen::drawLine("Read disc information"); WiiUScreen::drawLine("Read disc information");
} else if (this->state == STATE_READ_DISC_INFO_DONE) { } else if (this->state == STATE_READ_DISC_INFO_DONE) {
WiiUScreen::drawLinef("Dumping: %s", this->discId); WiiUScreen::drawLinef("Dumping: %s", getPathNameForDisc().c_str());
} else if (this->state == STATE_DUMP_DISC_START || this->state == STATE_DUMP_DISC || this->state == STATE_WAIT_USER_ERROR_CONFIRM) { } else if (this->state == STATE_DUMP_DISC_START || this->state == STATE_DUMP_DISC || this->state == STATE_WAIT_USER_ERROR_CONFIRM) {
WiiUScreen::drawLinef("Dumping: %s", this->discId); WiiUScreen::drawLinef("Dumping: %s", getPathNameForDisc().c_str());
float percent = this->currentSector / (WUD_FILE_SIZE / READ_SECTOR_SIZE * 1.0f) * 100.0f; 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); 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);
@ -362,3 +359,14 @@ std::string WUDDumperState::getPathForDevice(eDumpTarget target) const {
} }
return "fs:/vol/external01/"; return "fs:/vol/external01/";
} }
std::string WUDDumperState::getPathNameForDisc() {
if (this->discId[0] == '\0') {
OSCalendarTime tm;
OSTicksToCalendarTime(this->dumpStartDate, &tm);
return string_format("DISC-%04d-%02d-%02d-%02d-%02d-%02d",
tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
return std::string((char *) &discId[0]);
}

View File

@ -110,4 +110,6 @@ public:
int32_t writtenSectors{}; int32_t writtenSectors{};
void *emptySector = nullptr; void *emptySector = nullptr;
std::string getPathNameForDisc();
OSTime dumpStartDate;
}; };