Skip to content

Commit

Permalink
Replace fopen with open to fix new disc errors
Browse files Browse the repository at this point in the history
Latest devkitPPC update made fopen buffered which screws with the specific reading alignment/size that has to be used for .rpx files that are stored on the disc. So use unbuffered reads like the previous fopen behavior also used to do.

Fixes #33
  • Loading branch information
Crementif committed Apr 6, 2023
1 parent 3c36cba commit 72959cd
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 43 deletions.
44 changes: 23 additions & 21 deletions source/app/dumping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

#include <mocha/mocha.h>
#include <mocha/otp.h>
#include <sys/unistd.h>

// Dumping Functions
#define BUFFER_SIZE_ALIGNMENT 64
#define BUFFER_SIZE (1024 * BUFFER_SIZE_ALIGNMENT * 4)
// not sure which one is better
static_assert(BUFFER_SIZE % 0x8000 == 0, "Buffer size needs to be multiple of 0x8000 to properly read disc sections");
static_assert(BUFFER_SIZE % 0x10000 == 0, "Buffer size needs to be multiple of 0x10000 to properly read disc sections");


enum class WALK_EVENT {
Expand Down Expand Up @@ -53,6 +56,7 @@ bool callback_scanBuffer(uint64_t& totalBytes, uint64_t bufferSize) {
return true;
}

#define O_OPEN_UNENCRYPTED 0x4000000
bool callback_copyFile(TransferInterface* interface, bool& cancelledDumping, const char* filename, const std::string& srcPath, const std::string& destPath) {
// Check if file is an actual file first
struct stat fileStat{};
Expand All @@ -67,8 +71,8 @@ bool callback_copyFile(TransferInterface* interface, bool& cancelledDumping, con
return false;
}

FILE* readHandle = fopen(srcPath.c_str(), "rb");
if (readHandle == nullptr) {
int readHandle = open(srcPath.c_str(), srcPath.length() >= 10 && srcPath.ends_with(".nfs") ? O_OPEN_UNENCRYPTED | O_RDONLY : O_RDONLY);
if (readHandle == -1) {
std::wstring errorMessage;
errorMessage += L"Couldn't open the file to copy from!\n";
if (errno == EIO) errorMessage += L"For discs: Make sure that its clean!\nDumping is very sensitive to tiny errors!\n";
Expand All @@ -84,31 +88,29 @@ bool callback_copyFile(TransferInterface* interface, bool& cancelledDumping, con
while(true) {
uint8_t* copyBuffer = (uint8_t*)aligned_alloc(BUFFER_SIZE_ALIGNMENT, BUFFER_SIZE);
if (copyBuffer == nullptr) {
fclose(readHandle);
close(readHandle);
setErrorPrompt(L"Failed to allocate memory for chunk buffer!");
return false;
}

size_t bytesRead = fread(copyBuffer, sizeof(uint8_t), BUFFER_SIZE, readHandle);
if (bytesRead != BUFFER_SIZE) {
if (int fileError = ferror(readHandle); fileError != 0) {
free(copyBuffer);
copyBuffer = nullptr;
fclose(readHandle);
std::wstring errorMessage;
errorMessage += L"Failed to read all data from this file!\n";
if (errno == EIO) errorMessage += L"For discs: Make sure that its clean!\nDumping is very sensitive to tiny errors!\n";
errorMessage += L"Error "+std::to_wstring(errno)+L" when reading data from:\n";
errorMessage += toWstring(srcPath);
setErrorPrompt(errorMessage);
return false;
}
ssize_t bytesRead = read(readHandle, copyBuffer, BUFFER_SIZE);
if (bytesRead == -1) {
free(copyBuffer);
copyBuffer = nullptr;
close(readHandle);
std::wstring errorMessage;
errorMessage += L"Failed to read all data from this file!\n";
if (errno == EIO) errorMessage += L"For discs: Make sure that its clean!\nDumping is very sensitive to tiny errors!\n";
errorMessage += L"Error "+std::to_wstring(errno)+L" when reading data from:\n";
errorMessage += toWstring(srcPath);
setErrorPrompt(errorMessage);
return false;
}

bool endOfFile = feof(readHandle) != 0;
bool endOfFile = bytesRead < BUFFER_SIZE;
if (!interface->submitWriteFile(destPath, fileStat.st_size, copyBuffer, bytesRead, endOfFile)) {
free(copyBuffer);
fclose(readHandle);
close(readHandle);
setErrorPrompt(*interface->getStopError());
return false;
}
Expand All @@ -125,7 +127,7 @@ bool callback_copyFile(TransferInterface* interface, bool& cancelledDumping, con
WHBLogPrint("The app (likely) isn't frozen!");
WHBLogPrint("This should take a minute at most!");
WHBLogFreetypeDraw();
fclose(readHandle);
close(readHandle);
cancelledDumping = true;
return false;
}
Expand All @@ -135,7 +137,7 @@ bool callback_copyFile(TransferInterface* interface, bool& cancelledDumping, con
}
}

fclose(readHandle);
close(readHandle);
return true;
}

Expand Down
24 changes: 2 additions & 22 deletions source/app/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,34 +34,14 @@ bool unmountDefaultDevoptab() {
return true;
}

// Wii files hook
typedef int (*devoptab_open)(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
devoptab_open mlc_open = nullptr;
#define O_OPEN_UNENCRYPTED 0x4000000
int hook_openWiiFiles(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
std::string strPath(path);
int newFlags = flags;
if (strPath.length() >= 10 && strPath.ends_with(".nfs")) {
newFlags = newFlags | O_OPEN_UNENCRYPTED;
}
return mlc_open(r, fileStruct, path, newFlags, mode);
}

bool installWiiFilesHook(const char* dev_name) {
auto* dev = const_cast<devoptab_t*>(GetDeviceOpTab(dev_name));
if (dev == nullptr) return false;
mlc_open = dev->open_r;
dev->open_r = hook_openWiiFiles;
return true;
}

bool mountSystemDrives() {
WHBLogPrint("Mounting system drives...");
WHBLogFreetypeDraw();
if (USE_LIBMOCHA()) {
//unmountDefaultDevoptab();
if (Mocha_MountFS("storage_mlc01", nullptr, "/vol/storage_mlc01") == MOCHA_RESULT_SUCCESS && installWiiFilesHook("storage_mlc01:")) systemMLCMounted = true;
if (Mocha_MountFS("storage_usb01", nullptr, "/vol/storage_usb01") == MOCHA_RESULT_SUCCESS && installWiiFilesHook("storage_usb01:")) systemUSBMounted = true;
if (Mocha_MountFS("storage_mlc01", nullptr, "/vol/storage_mlc01") == MOCHA_RESULT_SUCCESS) systemMLCMounted = true;
if (Mocha_MountFS("storage_usb01", nullptr, "/vol/storage_usb01") == MOCHA_RESULT_SUCCESS) systemUSBMounted = true;
}
else {
systemMLCMounted = true;
Expand Down

0 comments on commit 72959cd

Please sign in to comment.