mirror of
https://github.com/wiiu-env/wudd.git
synced 2025-04-25 15:51:28 +02:00
Compare commits
31 Commits
wudd-20220
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
04872a3e83 | ||
![]() |
498696953a | ||
![]() |
86815beb77 | ||
![]() |
c3dfb55869 | ||
![]() |
57f823a5de | ||
![]() |
0da71f9420 | ||
![]() |
60688c0663 | ||
![]() |
8a61dda7df | ||
![]() |
eab18ef051 | ||
![]() |
2b46671df6 | ||
![]() |
cda26ddfd4 | ||
![]() |
5462d030d5 | ||
![]() |
16496baa65 | ||
![]() |
359d2e1450 | ||
![]() |
84a32a5142 | ||
![]() |
bb559cb904 | ||
![]() |
6e3cea9b93 | ||
![]() |
6899987864 | ||
![]() |
f09f8f2b29 | ||
![]() |
c8a687950f | ||
![]() |
2d2267807b | ||
![]() |
d6e6b9165d | ||
![]() |
a53b47f2b8 | ||
![]() |
4b5a1eca5f | ||
![]() |
26f69ca852 | ||
![]() |
8ece8d1886 | ||
![]() |
bb6734a499 | ||
![]() |
bc74da90dc | ||
![]() |
4a6269a8e5 | ||
![]() |
5a4f9484c3 | ||
![]() |
d58486e9c6 |
10
.github/dependabot.yml
vendored
Normal file
10
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "docker"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
57
.github/workflows/ci.yml
vendored
57
.github/workflows/ci.yml
vendored
@ -7,39 +7,35 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
run: |
|
run: |
|
||||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source
|
||||||
build-binary:
|
build-binary:
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-22.04
|
||||||
needs: clang-format
|
needs: clang-format
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Checkout submodules using a PAT
|
- name: create version.h
|
||||||
run: |
|
run: |
|
||||||
git config --file .gitmodules --get-regexp url | while read url; do
|
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||||
git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
|
cat <<EOF > ./source/version.h
|
||||||
done
|
#pragma once
|
||||||
git submodule sync
|
#define VERSION_EXTRA " (nightly-$git_hash)"
|
||||||
git submodule update --init --recursive
|
EOF
|
||||||
- name: build binary
|
- name: build binary
|
||||||
run: |
|
run: |
|
||||||
docker build . -t builder
|
docker build . -t builder
|
||||||
docker run --rm -v ${PWD}:/project builder make
|
docker run --rm -v ${PWD}:/project builder make
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
with:
|
with:
|
||||||
name: wuhb-binary
|
name: wuhb-binary
|
||||||
path: "*.wuhb"
|
path: "*.wuhb"
|
||||||
- uses: actions/upload-artifact@master
|
|
||||||
with:
|
|
||||||
name: rpx-binary
|
|
||||||
path: "*.rpx"
|
|
||||||
deploy-binary:
|
deploy-binary:
|
||||||
needs: build-binary
|
needs: build-binary
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Get environment variables
|
- name: Get environment variables
|
||||||
id: get_repository_name
|
id: get_repository_name
|
||||||
@ -50,32 +46,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wuhb-binary
|
name: wuhb-binary
|
||||||
path: wiiu/apps/wudd
|
path: wiiu/apps/wudd
|
||||||
- uses: actions/download-artifact@master
|
|
||||||
with:
|
|
||||||
name: rpx-binary
|
|
||||||
path: wiiu/apps/wudd
|
|
||||||
- name: zip artifact
|
- name: zip artifact
|
||||||
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip wiiu
|
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip wiiu
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
uses: "softprops/action-gh-release@v1"
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||||
release_name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: true
|
prerelease: true
|
||||||
body: |
|
generate_release_notes: true
|
||||||
Not a stable release:
|
name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||||
${{ github.event.head_commit.message }}
|
files: |
|
||||||
- name: Upload Release Asset
|
./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
||||||
id: upload-release-asset
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
|
||||||
asset_path: ./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
|
||||||
asset_name: ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
|
||||||
asset_content_type: application/zip
|
|
39
.github/workflows/pr.yml
vendored
39
.github/workflows/pr.yml
vendored
@ -4,29 +4,40 @@ on: [pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
run: |
|
run: |
|
||||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source
|
||||||
build-binary:
|
check-build-with-logging:
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-22.04
|
||||||
needs: clang-format
|
needs: clang-format
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Checkout submodules using a PAT
|
- name: build binary with logging
|
||||||
|
run: |
|
||||||
|
docker build . -t builder
|
||||||
|
docker run --rm -v ${PWD}:/project builder make DEBUG=VERBOSE
|
||||||
|
docker run --rm -v ${PWD}:/project builder make clean
|
||||||
|
docker run --rm -v ${PWD}:/project builder make DEBUG=1
|
||||||
|
build-binary:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
needs: clang-format
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: create version.h
|
||||||
run: |
|
run: |
|
||||||
git config --file .gitmodules --get-regexp url | while read url; do
|
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
||||||
git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
|
cat <<EOF > ./source/version.h
|
||||||
done
|
#pragma once
|
||||||
git submodule sync
|
#define VERSION_EXTRA " (nightly-$git_hash)"
|
||||||
git submodule update --init --recursive
|
EOF
|
||||||
- name: build binary
|
- name: build binary
|
||||||
run: |
|
run: |
|
||||||
docker build . -t builder
|
docker build . -t builder
|
||||||
docker run --rm -v ${PWD}:/project builder make
|
docker run --rm -v ${PWD}:/project builder make
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
with:
|
with:
|
||||||
name: binary
|
name: binary
|
||||||
path: "*.rpx"
|
path: "*.wuhb"
|
@ -1,6 +1,6 @@
|
|||||||
FROM wiiuenv/devkitppc:20220724
|
FROM ghcr.io/wiiu-env/devkitppc:20230621
|
||||||
|
|
||||||
COPY --from=wiiuenv/libntfs:20220726 /artifacts $DEVKITPRO
|
COPY --from=ghcr.io/wiiu-env/libntfs:20220726 /artifacts $DEVKITPRO
|
||||||
COPY --from=wiiuenv/libmocha:20220726 /artifacts $DEVKITPRO
|
COPY --from=ghcr.io/wiiu-env/libmocha:20220919 /artifacts $DEVKITPRO
|
||||||
|
|
||||||
WORKDIR project
|
WORKDIR project
|
||||||
|
3
Makefile
3
Makefile
@ -52,6 +52,7 @@ SOURCES := source \
|
|||||||
|
|
||||||
DATA := data
|
DATA := data
|
||||||
INCLUDES := source
|
INCLUDES := source
|
||||||
|
ICON := data/icon.png
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
@ -164,7 +165,7 @@ endif
|
|||||||
all: $(BUILD)
|
all: $(BUILD)
|
||||||
|
|
||||||
$(BUILD):
|
$(BUILD):
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
@ -9,6 +9,8 @@ Features:
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
If you want to create a partial dump (skipped sectors represented by 00 bytes) for discs with unreadable sectors, you can avoid the need to manually choose the skip sectors option on each error, by pressing Y at the error message to activate auto skip mode
|
||||||
|
|
||||||
## How to merge splitted files
|
## How to merge splitted files
|
||||||
|
|
||||||
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.
|
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.
|
||||||
@ -51,4 +53,4 @@ docker run -it --rm -v ${PWD}:/project wudd-builder make clean
|
|||||||
|
|
||||||
## Format the code via docker
|
## Format the code via docker
|
||||||
|
|
||||||
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source -i`
|
`docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source -i`
|
||||||
|
BIN
data/icon.png
Normal file
BIN
data/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
@ -4,6 +4,7 @@
|
|||||||
#include "input/Input.h"
|
#include "input/Input.h"
|
||||||
#include "utils/ScreenUtils.h"
|
#include "utils/ScreenUtils.h"
|
||||||
#include "utils/WiiUScreen.h"
|
#include "utils/WiiUScreen.h"
|
||||||
|
#include "version.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
class ApplicationState {
|
class ApplicationState {
|
||||||
@ -55,7 +56,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void printHeader() {
|
virtual void printHeader() {
|
||||||
WiiUScreen::drawLine("WUDD - Wii U Disc Dumper");
|
WiiUScreen::drawLine("WUDD - Wii U Disc Dumper v1.2.2" VERSION_EXTRA);
|
||||||
WiiUScreen::drawLine("==================");
|
WiiUScreen::drawLine("==================");
|
||||||
WiiUScreen::drawLine("");
|
WiiUScreen::drawLine("");
|
||||||
}
|
}
|
||||||
@ -76,4 +77,4 @@ public:
|
|||||||
|
|
||||||
int selectedOptionY = 0;
|
int selectedOptionY = 0;
|
||||||
int selectedOptionX = 0;
|
int selectedOptionX = 0;
|
||||||
};
|
};
|
||||||
|
@ -36,6 +36,10 @@ GMPartitionsDumperState::GMPartitionsDumperState(eDumpTarget pTargetDevice) : ta
|
|||||||
}
|
}
|
||||||
|
|
||||||
GMPartitionsDumperState::~GMPartitionsDumperState() {
|
GMPartitionsDumperState::~GMPartitionsDumperState() {
|
||||||
|
if (this->oddFd != -1) {
|
||||||
|
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
|
||||||
|
this->oddFd = -1;
|
||||||
|
}
|
||||||
free(this->sectorBuf);
|
free(this->sectorBuf);
|
||||||
this->sectorBuf = nullptr;
|
this->sectorBuf = nullptr;
|
||||||
free(this->readBuffer);
|
free(this->readBuffer);
|
||||||
@ -178,7 +182,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->state == STATE_OPEN_ODD1) {
|
if (this->state == STATE_OPEN_ODD1) {
|
||||||
auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &(this->oddFd));
|
auto ret = FSAEx_RawOpenEx(gFSAClientHandle, "/dev/odd01", &(this->oddFd));
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
if (this->sectorBuf == nullptr) {
|
if (this->sectorBuf == nullptr) {
|
||||||
this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize);
|
this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize);
|
||||||
@ -196,13 +200,13 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
|
|||||||
return ApplicationState::SUBSTATE_RETURN;
|
return ApplicationState::SUBSTATE_RETURN;
|
||||||
}
|
}
|
||||||
} else if (this->state == STATE_READ_DISC_INFO) {
|
} else if (this->state == STATE_READ_DISC_INFO) {
|
||||||
if (FSAEx_RawRead(__wut_devoptab_fs_client, this->sectorBuf, READ_SECTOR_SIZE, 1, 0, this->oddFd) >= 0) {
|
if (FSAEx_RawReadEx(gFSAClientHandle, 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);
|
||||||
this->state = STATE_READ_DISC_INFO_DONE;
|
this->state = STATE_READ_DISC_INFO_DONE;
|
||||||
return ApplicationState::SUBSTATE_RUNNING;
|
return ApplicationState::SUBSTATE_RUNNING;
|
||||||
}
|
}
|
||||||
FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd);
|
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
|
||||||
this->oddFd = -1;
|
this->oddFd = -1;
|
||||||
|
|
||||||
this->setError(ERROR_READ_FIRST_SECTOR);
|
this->setError(ERROR_READ_FIRST_SECTOR);
|
||||||
@ -226,7 +230,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
|
|||||||
auto discHeaderOpt = WiiUDiscHeader::make_unique(discReader);
|
auto discHeaderOpt = WiiUDiscHeader::make_unique(discReader);
|
||||||
if (!discHeaderOpt.has_value()) {
|
if (!discHeaderOpt.has_value()) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to read DiscHeader");
|
DEBUG_FUNCTION_LINE_ERR("Failed to read DiscHeader");
|
||||||
this->setError(ERROR_PARSE_DISCHEADER);
|
this->setError(ERROR_PARSE_DISC_HEADER);
|
||||||
return SUBSTATE_RUNNING;
|
return SUBSTATE_RUNNING;
|
||||||
}
|
}
|
||||||
this->discHeader = std::move(discHeaderOpt.value());
|
this->discHeader = std::move(discHeaderOpt.value());
|
||||||
@ -269,7 +273,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
|
|||||||
this->curNUSTitle = gmPartitionPair.second;
|
this->curNUSTitle = gmPartitionPair.second;
|
||||||
this->dataProvider = this->curNUSTitle->dataProcessor->getDataProvider();
|
this->dataProvider = this->curNUSTitle->dataProcessor->getDataProvider();
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("Failed to find a GM partition");
|
DEBUG_FUNCTION_LINE_ERR("Failed to find a GM partition");
|
||||||
this->setError(ERROR_NO_GM_PARTITION);
|
this->setError(ERROR_NO_GM_PARTITION);
|
||||||
return SUBSTATE_RUNNING;
|
return SUBSTATE_RUNNING;
|
||||||
}
|
}
|
||||||
@ -448,108 +452,77 @@ std::string GMPartitionsDumperState::getPathForDevice(eDumpTarget target) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GMPartitionsDumperState::ErrorMessage() const {
|
std::string GMPartitionsDumperState::ErrorMessage() const {
|
||||||
if (this->errorState == ERROR_MALLOC_FAILED) {
|
switch (this->errorState) {
|
||||||
return "ERROR_MALLOC_FAILED";
|
case ERROR_NONE:
|
||||||
}
|
return "ERROR_NONE";
|
||||||
if (this->errorState == ERROR_NO_DISC_ID) {
|
case ERROR_MALLOC_FAILED:
|
||||||
return "ERROR_NO_DISC_ID";
|
return "ERROR_MALLOC_FAILED";
|
||||||
}
|
case ERROR_READ_FIRST_SECTOR:
|
||||||
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
|
return "ERROR_READ_FIRST_SECTOR";
|
||||||
return "ERROR_READ_FIRST_SECTOR";
|
case ERROR_OPEN_ODD1:
|
||||||
}
|
return "ERROR_OPEN_ODD1";
|
||||||
if (this->errorState == ERROR_OPEN_ODD1) {
|
case ERROR_PARSE_DISC_HEADER:
|
||||||
return "ERROR_OPEN_ODD1";
|
return "ERROR_PARSE_DISC_HEADER";
|
||||||
}
|
case ERROR_NO_GM_PARTITION:
|
||||||
if (this->errorState == ERROR_PARSE_DISCHEADER) {
|
return "ERROR_NO_GM_PARTITION";
|
||||||
return "ERROR_PARSE_DISCHEADER";
|
case ERROR_CREATE_DIR:
|
||||||
}
|
return "ERROR_CREATE_DIR";
|
||||||
if (this->errorState == ERROR_NO_GM_PARTITION) {
|
case ERROR_FAILED_TO_GET_NUSTITLE:
|
||||||
return "ERROR_NO_GM_PARTITION";
|
return "ERROR_FAILED_TO_GET_NUSTITLE";
|
||||||
}
|
case ERROR_FAILED_WRITE_TMD:
|
||||||
if (this->errorState == ERROR_CREATE_DIR) {
|
return "ERROR_FAILED_WRITE_TMD";
|
||||||
return "ERROR_CREATE_DIR";
|
case ERROR_FAILED_WRITE_TICKET:
|
||||||
}
|
return "ERROR_FAILED_WRITE_TICKET";
|
||||||
if (this->errorState == ERROR_FAILED_TO_GET_NUSTITLE) {
|
case ERROR_FAILED_WRITE_CERT:
|
||||||
return "ERROR_FAILED_TO_GET_NUSTITLE";
|
return "ERROR_FAILED_WRITE_CERT";
|
||||||
}
|
case ERROR_FIND_CONTENT_BY_INDEX:
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_TMD) {
|
return "ERROR_FIND_CONTENT_BY_INDEX";
|
||||||
return "ERROR_FAILED_WRITE_TMD";
|
case ERROR_FAILED_CREATE_FILE:
|
||||||
}
|
return "ERROR_FAILED_CREATE_FILE";
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_TICKET) {
|
case ERROR_FAILED_WRITE_H3:
|
||||||
return "ERROR_FAILED_WRITE_TICKET";
|
return "ERROR_FAILED_WRITE_H3";
|
||||||
}
|
case ERROR_READ_CONTENT:
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_CERT) {
|
return "ERROR_READ_CONTENT";
|
||||||
return "ERROR_FAILED_WRITE_CERT";
|
case ERROR_WRITE_CONTENT:
|
||||||
}
|
return "ERROR_WRITE_CONTENT";
|
||||||
if (this->errorState == ERROR_FIND_CONTENT_BY_INDEX) {
|
|
||||||
return "ERROR_FIND_CONTENT_BY_INDEX";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_FAILED_CREATE_FILE) {
|
|
||||||
return "ERROR_FAILED_CREATE_FILE";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_H3) {
|
|
||||||
return "ERROR_FAILED_WRITE_H3";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_READ_CONTENT) {
|
|
||||||
return "ERROR_READ_CONTENT";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_WRITE_CONTENT) {
|
|
||||||
return "ERROR_WRITE_CONTENT";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_MALLOC_FAILED) {
|
|
||||||
return "ERROR_MALLOC_FAILED";
|
|
||||||
}
|
}
|
||||||
return "UNKNOWN_ERROR";
|
return "UNKNOWN_ERROR";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GMPartitionsDumperState::ErrorDescription() const {
|
std::string GMPartitionsDumperState::ErrorDescription() const {
|
||||||
if (this->errorState == ERROR_MALLOC_FAILED) {
|
switch (this->errorState) {
|
||||||
return "ERROR_MALLOC_FAILED";
|
case ERROR_NONE:
|
||||||
}
|
break;
|
||||||
if (this->errorState == ERROR_NO_DISC_ID) {
|
case ERROR_MALLOC_FAILED:
|
||||||
return "ERROR_NO_DISC_ID";
|
return "Failed to allocate memory.";
|
||||||
}
|
case ERROR_READ_FIRST_SECTOR:
|
||||||
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
|
return "Failed to read first sector.";
|
||||||
return "ERROR_READ_FIRST_SECTOR";
|
case ERROR_OPEN_ODD1:
|
||||||
}
|
return "Failed to read from disc.";
|
||||||
if (this->errorState == ERROR_OPEN_ODD1) {
|
case ERROR_PARSE_DISC_HEADER:
|
||||||
return "ERROR_OPEN_ODD1";
|
return "Failed to parse the disc header.";
|
||||||
}
|
case ERROR_NO_GM_PARTITION:
|
||||||
if (this->errorState == ERROR_PARSE_DISCHEADER) {
|
return "No games were found on this disc.";
|
||||||
return "ERROR_PARSE_DISCHEADER";
|
case ERROR_CREATE_DIR:
|
||||||
}
|
return "Failed to create a directory. \nMake sure to have enough space on the storage device.";
|
||||||
if (this->errorState == ERROR_NO_GM_PARTITION) {
|
case ERROR_FAILED_TO_GET_NUSTITLE:
|
||||||
return "ERROR_NO_GM_PARTITION";
|
return "Failed to parse partition as NUSTitle";
|
||||||
}
|
case ERROR_FAILED_WRITE_TMD:
|
||||||
if (this->errorState == ERROR_FAILED_TO_GET_NUSTITLE) {
|
return "Failed to dump the title.tmd";
|
||||||
return "ERROR_FAILED_TO_GET_NUSTITLE";
|
case ERROR_FAILED_WRITE_TICKET:
|
||||||
}
|
return "Failed to dump the title.tik";
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_TMD) {
|
case ERROR_FAILED_WRITE_CERT:
|
||||||
return "ERROR_FAILED_WRITE_TMD";
|
return "Failed to dump the title.cert";
|
||||||
}
|
case ERROR_FIND_CONTENT_BY_INDEX:
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_TICKET) {
|
return "Failed to find requested index";
|
||||||
return "ERROR_FAILED_WRITE_TICKET";
|
case ERROR_FAILED_CREATE_FILE:
|
||||||
}
|
return "Failed to create a file. \nMake sure to have enough space on the storage device.";
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_CERT) {
|
case ERROR_FAILED_WRITE_H3:
|
||||||
return "ERROR_FAILED_WRITE_CERT";
|
return "Failed to dump the a .h3 file";
|
||||||
}
|
case ERROR_READ_CONTENT:
|
||||||
if (this->errorState == ERROR_FIND_CONTENT_BY_INDEX) {
|
return "Failed to read the a .app file from disc";
|
||||||
return "ERROR_FIND_CONTENT_BY_INDEX";
|
case ERROR_WRITE_CONTENT:
|
||||||
}
|
return "Failed to dump a .app. \nMake sure to have enough space on the storage device.";
|
||||||
if (this->errorState == ERROR_FAILED_CREATE_FILE) {
|
|
||||||
return "ERROR_FAILED_CREATE_FILE";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_FAILED_WRITE_H3) {
|
|
||||||
return "ERROR_FAILED_WRITE_H3";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_READ_CONTENT) {
|
|
||||||
return "ERROR_READ_CONTENT";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_WRITE_CONTENT) {
|
|
||||||
return "ERROR_WRITE_CONTENT";
|
|
||||||
}
|
|
||||||
if (this->errorState == ERROR_MALLOC_FAILED) {
|
|
||||||
return "ERROR_MALLOC_FAILED";
|
|
||||||
}
|
}
|
||||||
return "UNKNOWN_ERROR";
|
return "UNKNOWN_ERROR";
|
||||||
}
|
}
|
||||||
|
@ -55,10 +55,9 @@ public:
|
|||||||
enum eErrorState {
|
enum eErrorState {
|
||||||
ERROR_NONE,
|
ERROR_NONE,
|
||||||
ERROR_MALLOC_FAILED,
|
ERROR_MALLOC_FAILED,
|
||||||
ERROR_NO_DISC_ID,
|
|
||||||
ERROR_READ_FIRST_SECTOR,
|
ERROR_READ_FIRST_SECTOR,
|
||||||
ERROR_OPEN_ODD1,
|
ERROR_OPEN_ODD1,
|
||||||
ERROR_PARSE_DISCHEADER,
|
ERROR_PARSE_DISC_HEADER,
|
||||||
ERROR_NO_GM_PARTITION,
|
ERROR_NO_GM_PARTITION,
|
||||||
ERROR_CREATE_DIR,
|
ERROR_CREATE_DIR,
|
||||||
ERROR_FAILED_TO_GET_NUSTITLE,
|
ERROR_FAILED_TO_GET_NUSTITLE,
|
||||||
|
@ -88,7 +88,7 @@ ApplicationState::eSubState MainApplicationState::update(Input *input) {
|
|||||||
} else if (this->selectedOptionY == 3) {
|
} else if (this->selectedOptionY == 3) {
|
||||||
//
|
//
|
||||||
} else {
|
} else {
|
||||||
if (gRunFromHBL) {
|
if (!gRunFromHBL) {
|
||||||
SYSLaunchMenu();
|
SYSLaunchMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ bool DiscReader::readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint
|
|||||||
uint32_t blockNumber = (totalOffset / BLOCK_SIZE);
|
uint32_t blockNumber = (totalOffset / BLOCK_SIZE);
|
||||||
uint32_t blockOffset = (totalOffset % BLOCK_SIZE);
|
uint32_t blockOffset = (totalOffset % BLOCK_SIZE);
|
||||||
|
|
||||||
readOffset = (blockNumber * BLOCK_SIZE);
|
readOffset = ((uint64_t) blockNumber * BLOCK_SIZE);
|
||||||
if (!useFixedIV) {
|
if (!useFixedIV) {
|
||||||
memset(usedIV, 0, 16);
|
memset(usedIV, 0, 16);
|
||||||
uint64_t ivTemp = usedFileOffset >> 16;
|
uint64_t ivTemp = usedFileOffset >> 16;
|
||||||
|
@ -31,13 +31,13 @@ DiscReaderDiscDrive::DiscReaderDiscDrive() : DiscReader() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &device_handle);
|
auto ret = FSAEx_RawOpenEx(gFSAClientHandle, "/dev/odd01", &device_handle);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
free(sector_buf);
|
free(sector_buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = FSAEx_RawRead(__wut_devoptab_fs_client, sector_buf, READ_SECTOR_SIZE, 1, 3, device_handle);
|
auto res = FSAEx_RawReadEx(gFSAClientHandle, sector_buf, READ_SECTOR_SIZE, 1, 3, device_handle);
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
if (((uint32_t *) sector_buf)[0] != WiiUDiscContentsHeader::MAGIC) {
|
if (((uint32_t *) sector_buf)[0] != WiiUDiscContentsHeader::MAGIC) {
|
||||||
uint8_t iv[16];
|
uint8_t iv[16];
|
||||||
@ -75,7 +75,7 @@ DiscReaderDiscDrive::DiscReaderDiscDrive() : DiscReader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DiscReaderDiscDrive::readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint32_t block_offset) const {
|
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) {
|
if (FSAEx_RawReadEx(gFSAClientHandle, buffer, READ_SECTOR_SIZE, block_cnt, block_offset, device_handle) < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -87,7 +87,7 @@ bool DiscReaderDiscDrive::IsReady() {
|
|||||||
|
|
||||||
DiscReaderDiscDrive::~DiscReaderDiscDrive() {
|
DiscReaderDiscDrive::~DiscReaderDiscDrive() {
|
||||||
if (device_handle != -1) {
|
if (device_handle != -1) {
|
||||||
FSAEx_RawClose(__wut_devoptab_fs_client, device_handle);
|
FSAEx_RawCloseEx(gFSAClientHandle, device_handle);
|
||||||
device_handle = -1;
|
device_handle = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,8 +102,8 @@ bool DiscReaderDiscDrive::readEncrypted(uint8_t *buf, uint64_t offset, uint32_t
|
|||||||
}
|
}
|
||||||
uint32_t block_cnt = size >> 15;
|
uint32_t block_cnt = size >> 15;
|
||||||
uint32_t offset_in_sectors = offset >> 15;
|
uint32_t offset_in_sectors = offset >> 15;
|
||||||
if (FSAEx_RawRead(__wut_devoptab_fs_client, buf, 0x8000, block_cnt, offset_in_sectors, device_handle) < 0) {
|
if (FSAEx_RawReadEx(gFSAClientHandle, buf, 0x8000, block_cnt, offset_in_sectors, device_handle) < 0) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to read from Disc");
|
DEBUG_FUNCTION_LINE_ERR("Failed to read from Disc");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -26,7 +26,6 @@ std::optional<std::unique_ptr<WiiUDiscContentsHeader>> WiiUDiscContentsHeader::m
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (!discReader->hasDiscKey) {
|
if (!discReader->hasDiscKey) {
|
||||||
DEBUG_FUNCTION_LINE_ERR();
|
|
||||||
if (!discReader->readEncrypted(buffer.get(), offset, LENGTH)) {
|
if (!discReader->readEncrypted(buffer.get(), offset, LENGTH)) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to read data");
|
DEBUG_FUNCTION_LINE_ERR("Failed to read data");
|
||||||
return {};
|
return {};
|
||||||
|
@ -28,5 +28,5 @@ public:
|
|||||||
~H3HashArray();
|
~H3HashArray();
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> data;
|
std::unique_ptr<uint8_t[]> data;
|
||||||
uint8_t size;
|
uint32_t size;
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ WUDDumperState::WUDDumperState(WUDDumperState::eDumpTargetFormat pTargetFormat,
|
|||||||
|
|
||||||
WUDDumperState::~WUDDumperState() {
|
WUDDumperState::~WUDDumperState() {
|
||||||
if (this->oddFd >= 0) {
|
if (this->oddFd >= 0) {
|
||||||
FSAEx_RawClose(__wut_devoptab_fs_client, oddFd);
|
FSAEx_RawCloseEx(gFSAClientHandle, oddFd);
|
||||||
}
|
}
|
||||||
free(sectorBuf);
|
free(sectorBuf);
|
||||||
free(emptySector);
|
free(emptySector);
|
||||||
@ -51,7 +51,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
}
|
}
|
||||||
if (this->state == STATE_OPEN_ODD1) {
|
if (this->state == STATE_OPEN_ODD1) {
|
||||||
if (this->currentSector > 0) {
|
if (this->currentSector > 0) {
|
||||||
auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &(this->oddFd));
|
auto ret = FSAEx_RawOpenEx(gFSAClientHandle, "/dev/odd01", &(this->oddFd));
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
// continue!
|
// continue!
|
||||||
this->state = STATE_DUMP_DISC;
|
this->state = STATE_DUMP_DISC;
|
||||||
@ -65,12 +65,12 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
this->state = STATE_PLEASE_INSERT_DISC;
|
this->state = STATE_PLEASE_INSERT_DISC;
|
||||||
return ApplicationState::SUBSTATE_RUNNING;
|
return ApplicationState::SUBSTATE_RUNNING;
|
||||||
}
|
}
|
||||||
auto ret = FSAEx_RawOpen(__wut_devoptab_fs_client, "/dev/odd01", &(this->oddFd));
|
auto ret = FSAEx_RawOpenEx(gFSAClientHandle, "/dev/odd01", &(this->oddFd));
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
if (this->sectorBuf == nullptr) {
|
if (this->sectorBuf == nullptr) {
|
||||||
this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize);
|
this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize);
|
||||||
if (this->sectorBuf == nullptr) {
|
if (this->sectorBuf == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("ERROR_MALLOC_FAILED");
|
DEBUG_FUNCTION_LINE_ERR("ERROR_MALLOC_FAILED");
|
||||||
this->setError(ERROR_MALLOC_FAILED);
|
this->setError(ERROR_MALLOC_FAILED);
|
||||||
return ApplicationState::SUBSTATE_RUNNING;
|
return ApplicationState::SUBSTATE_RUNNING;
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
return SUBSTATE_RETURN;
|
return SUBSTATE_RETURN;
|
||||||
}
|
}
|
||||||
} else if (this->state == STATE_READ_DISC_INFO) {
|
} else if (this->state == STATE_READ_DISC_INFO) {
|
||||||
if (FSAEx_RawRead(__wut_devoptab_fs_client, this->sectorBuf, READ_SECTOR_SIZE, 1, 0, this->oddFd) >= 0) {
|
if (FSAEx_RawReadEx(gFSAClientHandle, 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);
|
||||||
this->state = STATE_READ_DISC_INFO_DONE;
|
this->state = STATE_READ_DISC_INFO_DONE;
|
||||||
@ -96,7 +96,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
this->state = STATE_DUMP_DISC_KEY;
|
this->state = STATE_DUMP_DISC_KEY;
|
||||||
} else if (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.
|
// Read the WiiUDiscContentsHeader to determine if we need disckey and if it's the correct one.
|
||||||
auto res = FSAEx_RawRead(__wut_devoptab_fs_client, this->sectorBuf, READ_SECTOR_SIZE, 1, 3, this->oddFd);
|
auto res = FSAEx_RawReadEx(gFSAClientHandle, this->sectorBuf, READ_SECTOR_SIZE, 1, 3, this->oddFd);
|
||||||
WUDDiscKey discKey;
|
WUDDiscKey discKey;
|
||||||
bool hasDiscKey = false;
|
bool hasDiscKey = false;
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
@ -132,7 +132,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
SECTOR_SIZE, targetDevice == TARGET_SD);
|
SECTOR_SIZE, targetDevice == TARGET_SD);
|
||||||
}
|
}
|
||||||
if (!this->fileHandle->isOpen()) {
|
if (!this->fileHandle->isOpen()) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to open file");
|
DEBUG_FUNCTION_LINE_ERR("Failed to open file.");
|
||||||
this->setError(ERROR_FILE_OPEN_FAILED);
|
this->setError(ERROR_FILE_OPEN_FAILED);
|
||||||
return ApplicationState::SUBSTATE_RUNNING;
|
return ApplicationState::SUBSTATE_RUNNING;
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t numSectors = this->currentSector + READ_NUM_SECTORS > this->totalSectorCount ? this->totalSectorCount - this->currentSector : READ_NUM_SECTORS;
|
size_t numSectors = this->currentSector + READ_NUM_SECTORS > this->totalSectorCount ? this->totalSectorCount - this->currentSector : READ_NUM_SECTORS;
|
||||||
if ((this->readResult = FSAEx_RawRead(__wut_devoptab_fs_client, sectorBuf, READ_SECTOR_SIZE, numSectors, this->currentSector, this->oddFd)) >= 0) {
|
if ((this->readResult = FSAEx_RawReadEx(gFSAClientHandle, sectorBuf, READ_SECTOR_SIZE, numSectors, this->currentSector, this->oddFd)) >= 0) {
|
||||||
auto curWrittenSectors = fileHandle->writeSector((const uint8_t *) this->sectorBuf, numSectors);
|
auto curWrittenSectors = fileHandle->writeSector((const uint8_t *) this->sectorBuf, numSectors);
|
||||||
if (curWrittenSectors < 0) {
|
if (curWrittenSectors < 0) {
|
||||||
this->setError(ERROR_WRITE_FAILED);
|
this->setError(ERROR_WRITE_FAILED);
|
||||||
@ -165,18 +165,22 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
this->state = STATE_DUMP_DISC_DONE;
|
this->state = STATE_DUMP_DISC_DONE;
|
||||||
if (this->fileHandle->isOpen()) {
|
if (this->fileHandle->isOpen()) {
|
||||||
if (!this->fileHandle->flush()) {
|
if (!this->fileHandle->flush()) {
|
||||||
DEBUG_FUNCTION_LINE("Flush failed");
|
DEBUG_FUNCTION_LINE_ERR("Final flush failed");
|
||||||
|
this->setError(ERROR_WRITE_FAILED);
|
||||||
|
return ApplicationState::SUBSTATE_RUNNING;
|
||||||
|
}
|
||||||
|
if (!this->fileHandle->finalize()) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Finalize failed");
|
||||||
this->setError(ERROR_WRITE_FAILED);
|
this->setError(ERROR_WRITE_FAILED);
|
||||||
return ApplicationState::SUBSTATE_RUNNING;
|
return ApplicationState::SUBSTATE_RUNNING;
|
||||||
}
|
}
|
||||||
this->fileHandle->finalize();
|
|
||||||
this->fileHandle->close();
|
this->fileHandle->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this->state = STATE_WAIT_USER_ERROR_CONFIRM;
|
this->state = STATE_WAIT_USER_ERROR_CONFIRM;
|
||||||
if (this->oddFd >= 0) {
|
if (this->oddFd >= 0) {
|
||||||
FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd);
|
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
|
||||||
this->oddFd = -1;
|
this->oddFd = -1;
|
||||||
}
|
}
|
||||||
return ApplicationState::SUBSTATE_RUNNING;
|
return ApplicationState::SUBSTATE_RUNNING;
|
||||||
@ -199,7 +203,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
|
|||||||
} else if (this->state == STATE_WAIT_USER_ERROR_CONFIRM) {
|
} else if (this->state == STATE_WAIT_USER_ERROR_CONFIRM) {
|
||||||
if (this->autoSkipOnError) {
|
if (this->autoSkipOnError) {
|
||||||
if (this->oddFd >= 0) {
|
if (this->oddFd >= 0) {
|
||||||
FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd);
|
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
|
||||||
this->oddFd = -1;
|
this->oddFd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,6 +255,7 @@ void WUDDumperState::render() {
|
|||||||
WiiUScreen::drawLinef("Error: %s", ErrorMessage().c_str());
|
WiiUScreen::drawLinef("Error: %s", ErrorMessage().c_str());
|
||||||
WiiUScreen::drawLinef("Description: %s", ErrorDescription().c_str());
|
WiiUScreen::drawLinef("Description: %s", ErrorDescription().c_str());
|
||||||
WiiUScreen::drawLine();
|
WiiUScreen::drawLine();
|
||||||
|
WiiUScreen::drawLine();
|
||||||
WiiUScreen::drawLine("Press A to return.");
|
WiiUScreen::drawLine("Press A to return.");
|
||||||
} else if (this->state == STATE_OPEN_ODD1) {
|
} else if (this->state == STATE_OPEN_ODD1) {
|
||||||
WiiUScreen::drawLine("Open /dev/odd01");
|
WiiUScreen::drawLine("Open /dev/odd01");
|
||||||
@ -324,31 +329,37 @@ void WUDDumperState::setError(WUDDumperState::eErrorState err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string WUDDumperState::ErrorMessage() const {
|
std::string WUDDumperState::ErrorMessage() const {
|
||||||
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
|
switch (this->errorState) {
|
||||||
return "ERROR_READ_FIRST_SECTOR";
|
case ERROR_READ_FIRST_SECTOR:
|
||||||
} else if (this->errorState == ERROR_FILE_OPEN_FAILED) {
|
return "ERROR_READ_FIRST_SECTOR";
|
||||||
return "ERROR_FILE_OPEN_FAILED";
|
case ERROR_NONE:
|
||||||
} else if (this->errorState == ERROR_MALLOC_FAILED) {
|
return "ERROR_NONE";
|
||||||
return "ERROR_MALLOC_FAILED";
|
case ERROR_FILE_OPEN_FAILED:
|
||||||
} else if (this->errorState == ERROR_NO_DISC_ID) {
|
return "ERROR_FILE_OPEN_FAILED";
|
||||||
return "ERROR_NO_DISC_ID";
|
case ERROR_MALLOC_FAILED:
|
||||||
} else if (this->errorState == ERROR_WRITE_FAILED) {
|
return "ERROR_MALLOC_FAILED";
|
||||||
return "ERROR_WRITE_FAILED";
|
case ERROR_WRITE_FAILED:
|
||||||
|
return "ERROR_WRITE_FAILED";
|
||||||
|
case ERROR_NO_DISC_FOUND:
|
||||||
|
return "ERROR_NO_DISC_FOUND";
|
||||||
}
|
}
|
||||||
return "UNKNOWN_ERROR";
|
return "UNKNOWN_ERROR";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string WUDDumperState::ErrorDescription() const {
|
std::string WUDDumperState::ErrorDescription() const {
|
||||||
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
|
switch (this->errorState) {
|
||||||
return "Failed to read first sector.";
|
case ERROR_READ_FIRST_SECTOR:
|
||||||
} else if (this->errorState == ERROR_MALLOC_FAILED) {
|
return "Failed to read first sector.";
|
||||||
return "Failed to allocate data.";
|
case ERROR_NONE:
|
||||||
} else if (this->errorState == ERROR_FILE_OPEN_FAILED) {
|
return "ERROR_NONE";
|
||||||
return "Failed to create file";
|
case ERROR_FILE_OPEN_FAILED:
|
||||||
} else if (this->errorState == ERROR_NO_DISC_ID) {
|
return "Failed to create file \nMake sure to have enough space on the storage device.";
|
||||||
return "Failed to get the disc id";
|
case ERROR_MALLOC_FAILED:
|
||||||
} else if (this->errorState == ERROR_WRITE_FAILED) {
|
return "Failed to allocate data.";
|
||||||
return "Failed to write the file. \nMake sure to have enough space on the storage";
|
case ERROR_WRITE_FAILED:
|
||||||
|
return "Failed to write the file. \nMake sure to have enough space on the storage device.";
|
||||||
|
case ERROR_NO_DISC_FOUND:
|
||||||
|
return "Please insert a Wii U disc.";
|
||||||
}
|
}
|
||||||
return "UNKNOWN_ERROR";
|
return "UNKNOWN_ERROR";
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,6 @@ public:
|
|||||||
ERROR_READ_FIRST_SECTOR,
|
ERROR_READ_FIRST_SECTOR,
|
||||||
ERROR_FILE_OPEN_FAILED,
|
ERROR_FILE_OPEN_FAILED,
|
||||||
ERROR_MALLOC_FAILED,
|
ERROR_MALLOC_FAILED,
|
||||||
ERROR_NO_DISC_ID,
|
|
||||||
ERROR_WRITE_FAILED,
|
ERROR_WRITE_FAILED,
|
||||||
ERROR_NO_DISC_FOUND
|
ERROR_NO_DISC_FOUND
|
||||||
};
|
};
|
||||||
|
@ -4,3 +4,4 @@ int ntfs_mount_count = 0;
|
|||||||
BOOL gRunFromHBL = false;
|
BOOL gRunFromHBL = false;
|
||||||
BOOL gBlockHomeButton = false;
|
BOOL gBlockHomeButton = false;
|
||||||
uint32_t gBlockHomeButtonCooldown = 0;
|
uint32_t gBlockHomeButtonCooldown = 0;
|
||||||
|
FSAClientHandle gFSAClientHandle = 0;
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <coreinit/filesystem_fsa.h>
|
||||||
#include <ntfs.h>
|
#include <ntfs.h>
|
||||||
#include <wut.h>
|
#include <wut.h>
|
||||||
|
|
||||||
@ -9,12 +10,13 @@
|
|||||||
extern ntfs_md *ntfs_mounts;
|
extern ntfs_md *ntfs_mounts;
|
||||||
extern int ntfs_mount_count;
|
extern int ntfs_mount_count;
|
||||||
|
|
||||||
extern "C" FSClient *__wut_devoptab_fs_client;
|
extern FSAClientHandle gFSAClientHandle;
|
||||||
|
|
||||||
extern BOOL gRunFromHBL;
|
extern BOOL gRunFromHBL;
|
||||||
extern BOOL gBlockHomeButton;
|
extern BOOL gBlockHomeButton;
|
||||||
extern uint32_t gBlockHomeButtonCooldown;
|
extern uint32_t gBlockHomeButtonCooldown;
|
||||||
|
|
||||||
|
|
||||||
enum eDumpTarget {
|
enum eDumpTarget {
|
||||||
TARGET_SD,
|
TARGET_SD,
|
||||||
TARGET_NTFS
|
TARGET_NTFS
|
||||||
|
@ -1,64 +1,10 @@
|
|||||||
#include "FSUtils.h"
|
#include "FSUtils.h"
|
||||||
#include "CFile.hpp"
|
#include "CFile.hpp"
|
||||||
#include "utils/logger.h"
|
#include <cstdio>
|
||||||
#include "utils/utils.h"
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <malloc.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) {
|
|
||||||
//! always initialze input
|
|
||||||
*inbuffer = nullptr;
|
|
||||||
if (size)
|
|
||||||
*size = 0;
|
|
||||||
|
|
||||||
int32_t iFd = open(filepath, O_RDONLY);
|
|
||||||
if (iFd < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
uint32_t filesize = lseek(iFd, 0, SEEK_END);
|
|
||||||
lseek(iFd, 0, SEEK_SET);
|
|
||||||
|
|
||||||
auto *buffer = (uint8_t *) memalign(0x40, ROUNDUP(filesize, 0x40));
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
close(iFd);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t blocksize = 0x4000;
|
|
||||||
uint32_t done = 0;
|
|
||||||
int32_t readBytes = 0;
|
|
||||||
|
|
||||||
while (done < filesize) {
|
|
||||||
if (done + blocksize > filesize) {
|
|
||||||
blocksize = filesize - done;
|
|
||||||
}
|
|
||||||
readBytes = read(iFd, buffer + done, blocksize);
|
|
||||||
if (readBytes <= 0)
|
|
||||||
break;
|
|
||||||
done += readBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(iFd);
|
|
||||||
|
|
||||||
if (done != filesize) {
|
|
||||||
free(buffer);
|
|
||||||
buffer = nullptr;
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
*inbuffer = buffer;
|
|
||||||
|
|
||||||
//! sign is optional input
|
|
||||||
if (size) {
|
|
||||||
*size = filesize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return filesize;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FSUtils::CheckFile(const char *filepath) {
|
int32_t FSUtils::CheckFile(const char *filepath) {
|
||||||
if (!filepath)
|
if (!filepath)
|
||||||
return 0;
|
return 0;
|
||||||
@ -130,39 +76,6 @@ int32_t FSUtils::CreateSubfolder(const char *fullpath) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FSUtils::copyFile(const std::string &in, const std::string &out) {
|
|
||||||
// Using C++ buffers is **really** slow. Copying in 1023 byte chunks.
|
|
||||||
// Let's do it the old way.
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
int source = open(in.c_str(), O_RDONLY, 0);
|
|
||||||
int dest = open(out.c_str(), 0x602, 0644);
|
|
||||||
if (source < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (dest < 0) {
|
|
||||||
close(source);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bufferSize = 1024 * 1024;
|
|
||||||
char *buf = (char *) memalign(0x40, ROUNDUP(bufferSize, 0x40));
|
|
||||||
if (buf == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((size = read(source, buf, bufferSize)) > 0) {
|
|
||||||
write(dest, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
close(source);
|
|
||||||
close(dest);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) {
|
int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) {
|
||||||
CFile file(path, CFile::WriteOnly);
|
CFile file(path, CFile::WriteOnly);
|
||||||
if (!file.isOpen()) {
|
if (!file.isOpen()) {
|
||||||
|
@ -5,13 +5,9 @@
|
|||||||
|
|
||||||
class FSUtils {
|
class FSUtils {
|
||||||
public:
|
public:
|
||||||
static int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size);
|
|
||||||
|
|
||||||
static int32_t CreateSubfolder(const char *fullpath);
|
static int32_t CreateSubfolder(const char *fullpath);
|
||||||
|
|
||||||
static int32_t CheckFile(const char *filepath);
|
static int32_t CheckFile(const char *filepath);
|
||||||
|
|
||||||
static bool copyFile(const std::string &in, const std::string &out);
|
|
||||||
|
|
||||||
static int32_t saveBufferToFile(const char *path, void *buffer, uint32_t size);
|
static int32_t saveBufferToFile(const char *path, void *buffer, uint32_t size);
|
||||||
};
|
};
|
@ -29,5 +29,6 @@ int32_t WUDFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSecto
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WUDFileWriter::finalize() {
|
bool WUDFileWriter::finalize() {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
|
|
||||||
virtual int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors);
|
virtual int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors);
|
||||||
|
|
||||||
virtual void finalize();
|
virtual bool finalize();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int32_t sectorSize;
|
int32_t sectorSize;
|
||||||
|
@ -27,19 +27,24 @@ WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sector
|
|||||||
wuxHeader.uncompressedSize = swap_uint64(WUD_FILE_SIZE);
|
wuxHeader.uncompressedSize = swap_uint64(WUD_FILE_SIZE);
|
||||||
wuxHeader.flags = 0;
|
wuxHeader.flags = 0;
|
||||||
|
|
||||||
this->write((uint8_t *) &wuxHeader, sizeof(wuxHeader_t));
|
if (this->write((uint8_t *) &wuxHeader, sizeof(wuxHeader_t)) != sizeof(wuxHeader_t)) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to write header");
|
||||||
|
WUDFileWriter::close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->sectorTableStart = this->tell();
|
this->sectorTableStart = this->tell();
|
||||||
this->totalSectorCount = WUD_FILE_SIZE / this->sectorSize;
|
this->totalSectorCount = WUD_FILE_SIZE / this->sectorSize;
|
||||||
|
|
||||||
this->sectorIndexTable = (void *) memalign(0x40, ROUNDUP(totalSectorCount * 4, 0x40));
|
this->sectorIndexTable = (void *) memalign(0x40, ROUNDUP(totalSectorCount * 4, 0x40));
|
||||||
if (sectorIndexTable == nullptr) {
|
if (sectorIndexTable == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to alloc");
|
DEBUG_FUNCTION_LINE_ERR("Failed to alloc");
|
||||||
WUDFileWriter::close();
|
WUDFileWriter::close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memset(this->sectorIndexTable, 0, totalSectorCount * 4);
|
memset(this->sectorIndexTable, 0, totalSectorCount * 4);
|
||||||
|
|
||||||
if (this->write((uint8_t *) this->sectorIndexTable, totalSectorCount * 4) < 0) {
|
if (this->write((uint8_t *) this->sectorIndexTable, totalSectorCount * 4) != (int32_t) ((uint32_t) totalSectorCount * 4)) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to write initial sector index table");
|
||||||
WUDFileWriter::close();
|
WUDFileWriter::close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,14 +58,24 @@ WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sector
|
|||||||
uint64_t padding = this->sectorTableEnd - tableEnd;
|
uint64_t padding = this->sectorTableEnd - tableEnd;
|
||||||
auto *paddingData = (uint8_t *) memalign(0x40, ROUNDUP(padding, 0x40));
|
auto *paddingData = (uint8_t *) memalign(0x40, ROUNDUP(padding, 0x40));
|
||||||
memset(paddingData, 0, padding);
|
memset(paddingData, 0, padding);
|
||||||
this->write(reinterpret_cast<const uint8_t *>(paddingData), padding);
|
if (this->write(reinterpret_cast<const uint8_t *>(paddingData), padding) != (int32_t) padding) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to write padding.");
|
||||||
|
WUDFileWriter::close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
free(paddingData);
|
free(paddingData);
|
||||||
this->hashMap.clear();
|
this->hashMap.clear();
|
||||||
flush();
|
if (!flush()) {
|
||||||
|
WUXFileWriter::close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSectors) {
|
int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSectors) {
|
||||||
|
if (!isOpen()) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to write sector, file is not open");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
int32_t curWrittenSectors = 0;
|
int32_t curWrittenSectors = 0;
|
||||||
for (uint32_t i = 0; i < numberOfSectors; i++) {
|
for (uint32_t i = 0; i < numberOfSectors; i++) {
|
||||||
uint32_t addr = ((uint32_t) buffer) + (i * this->sectorSize);
|
uint32_t addr = ((uint32_t) buffer) + (i * this->sectorSize);
|
||||||
@ -76,8 +91,8 @@ int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSecto
|
|||||||
indexTable[this->currentSector] = swap_uint32(this->writtenSector);
|
indexTable[this->currentSector] = swap_uint32(this->writtenSector);
|
||||||
hashMap[hashOut] = writtenSector;
|
hashMap[hashOut] = writtenSector;
|
||||||
if (isOpen()) {
|
if (isOpen()) {
|
||||||
if (!write((uint8_t *) addr, this->sectorSize)) {
|
if (write((uint8_t *) addr, this->sectorSize) != this->sectorSize) {
|
||||||
DEBUG_FUNCTION_LINE("Write failed");
|
DEBUG_FUNCTION_LINE_ERR("Write failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,23 +104,36 @@ int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSecto
|
|||||||
return curWrittenSectors;
|
return curWrittenSectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WUXFileWriter::writeSectorIndexTable() {
|
bool WUXFileWriter::writeSectorIndexTable() {
|
||||||
if (this->isOpen()) {
|
if (this->isOpen()) {
|
||||||
flush();
|
if (!flush()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// We need to make sure to call CFile::seek!
|
// We need to make sure to call CFile::seek!
|
||||||
seek((int64_t) sectorTableStart, SEEK_SET_BASE_CLASS);
|
if (seek((int64_t) sectorTableStart, SEEK_SET_BASE_CLASS) < 0) {
|
||||||
write((uint8_t *) sectorIndexTable, totalSectorCount * 4);
|
DEBUG_FUNCTION_LINE_ERR("Seek failed");
|
||||||
flush();
|
return false;
|
||||||
|
}
|
||||||
|
if (write((uint8_t *) sectorIndexTable, totalSectorCount * 4) != (int32_t) ((uint32_t) totalSectorCount * 4)) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to write sector index table");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!flush()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WUXFileWriter::~WUXFileWriter() {
|
WUXFileWriter::~WUXFileWriter() {
|
||||||
|
WUXFileWriter::flush();
|
||||||
WUXFileWriter::close();
|
WUXFileWriter::close();
|
||||||
free(sectorIndexTable);
|
free(sectorIndexTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WUXFileWriter::finalize() {
|
bool WUXFileWriter::finalize() {
|
||||||
WUDFileWriter::finalize();
|
WUDFileWriter::finalize();
|
||||||
writeSectorIndexTable();
|
bool res = writeSectorIndexTable();
|
||||||
WUXFileWriter::close();
|
WUXFileWriter::close();
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,10 @@ public:
|
|||||||
|
|
||||||
int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors) override;
|
int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors) override;
|
||||||
|
|
||||||
void finalize() override;
|
bool finalize() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeSectorIndexTable();
|
bool writeSectorIndexTable();
|
||||||
|
|
||||||
uint64_t totalSectorCount;
|
uint64_t totalSectorCount;
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ WriteOnlyFileWithCache::~WriteOnlyFileWithCache() {
|
|||||||
bool WriteOnlyFileWithCache::flush() {
|
bool WriteOnlyFileWithCache::flush() {
|
||||||
if (this->writeBufferPos > 0) {
|
if (this->writeBufferPos > 0) {
|
||||||
int32_t res = CFile::write(static_cast<const uint8_t *>(this->writeBuffer), this->writeBufferPos);
|
int32_t res = CFile::write(static_cast<const uint8_t *>(this->writeBuffer), this->writeBufferPos);
|
||||||
if (res < 0) {
|
if (res != (int32_t) this->writeBufferPos) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to flush cache, write failed: %d", res);
|
DEBUG_FUNCTION_LINE_ERR("Failed to flush cache, write failed: %d (expected %d)", res, this->writeBufferPos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this->writeBufferPos = 0;
|
this->writeBufferPos = 0;
|
||||||
@ -58,8 +58,8 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
|
|||||||
auto finalAddr = addr;
|
auto finalAddr = addr;
|
||||||
size_t finalWriteSize = writeSize;
|
size_t finalWriteSize = writeSize;
|
||||||
if (splitFile) {
|
if (splitFile) {
|
||||||
if (pos + writeBufferPos + finalWriteSize >= SPLIT_SIZE) {
|
if (pos + writeBufferPos + finalWriteSize >= (uint64_t) SPLIT_SIZE) {
|
||||||
DEBUG_FUNCTION_LINE("We need to split");
|
DEBUG_FUNCTION_LINE("We need to split files");
|
||||||
if (!flush()) {
|
if (!flush()) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
|
|||||||
uint32_t realWriteSize = SPLIT_SIZE - pos;
|
uint32_t realWriteSize = SPLIT_SIZE - pos;
|
||||||
|
|
||||||
if (realWriteSize > 0) {
|
if (realWriteSize > 0) {
|
||||||
DEBUG_FUNCTION_LINE("Write remaining %8d bytes", realWriteSize);
|
DEBUG_FUNCTION_LINE_VERBOSE("Write remaining %8d bytes", realWriteSize);
|
||||||
if (CFile::write(reinterpret_cast<const uint8_t *>(addr), realWriteSize) != (int32_t) realWriteSize) {
|
if (CFile::write(reinterpret_cast<const uint8_t *>(addr), realWriteSize) != (int32_t) realWriteSize) {
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
|
|||||||
|
|
||||||
if (finalWriteSize == this->writeBufferSize) {
|
if (finalWriteSize == this->writeBufferSize) {
|
||||||
if (!this->flush()) {
|
if (!this->flush()) {
|
||||||
DEBUG_FUNCTION_LINE("Flush failed");
|
DEBUG_FUNCTION_LINE_ERR("Flush failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return CFile::write(reinterpret_cast<const uint8_t *>(addr), finalWriteSize);
|
return CFile::write(reinterpret_cast<const uint8_t *>(addr), finalWriteSize);
|
||||||
@ -115,7 +115,7 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
|
|||||||
|
|
||||||
if (this->writeBufferPos == this->writeBufferSize) {
|
if (this->writeBufferPos == this->writeBufferSize) {
|
||||||
if (!this->flush()) {
|
if (!this->flush()) {
|
||||||
DEBUG_FUNCTION_LINE("Flush failed");
|
DEBUG_FUNCTION_LINE_ERR("Flush failed");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <mocha/mocha.h>
|
#include <mocha/mocha.h>
|
||||||
#include <ntfs.h>
|
#include <ntfs.h>
|
||||||
#include <padscore/kpad.h>
|
#include <padscore/kpad.h>
|
||||||
|
#include <sndcore2/core.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <whb/log.h>
|
#include <whb/log.h>
|
||||||
#include <whb/proc.h>
|
#include <whb/proc.h>
|
||||||
@ -37,7 +38,7 @@ procHomeButtonDeniedCustom(void *context) {
|
|||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
initLogging();
|
initLogging();
|
||||||
DEBUG_FUNCTION_LINE("Hello from wudump!");
|
AXInit();
|
||||||
WHBProcInit();
|
WHBProcInit();
|
||||||
WiiUScreen::Init();
|
WiiUScreen::Init();
|
||||||
|
|
||||||
@ -53,9 +54,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
ProcUIClearCallbacks();
|
ProcUIClearCallbacks();
|
||||||
ProcUIRegisterCallback(PROCUI_CALLBACK_HOME_BUTTON_DENIED,
|
ProcUIRegisterCallback(PROCUI_CALLBACK_HOME_BUTTON_DENIED,
|
||||||
&procHomeButtonDeniedCustom, NULL, 100);
|
&procHomeButtonDeniedCustom, nullptr, 100);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
gRunFromHBL = false;
|
gRunFromHBL = false;
|
||||||
}
|
}
|
||||||
@ -64,7 +63,7 @@ int main(int argc, char **argv) {
|
|||||||
IMIsAPDEnabled(&isAPDEnabled);
|
IMIsAPDEnabled(&isAPDEnabled);
|
||||||
|
|
||||||
if (isAPDEnabled) {
|
if (isAPDEnabled) {
|
||||||
DEBUG_FUNCTION_LINE("Disable auto shutdown");
|
DEBUG_FUNCTION_LINE_VERBOSE("Disable auto shutdown");
|
||||||
IMDisableAPD();
|
IMDisableAPD();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +75,19 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
WPADInput::init();
|
WPADInput::init();
|
||||||
|
|
||||||
|
gFSAClientHandle = FSAAddClient(nullptr);
|
||||||
|
if (!gFSAClientHandle) {
|
||||||
|
OSFatal("FSAAddClient failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mocha_UnlockFSClientEx(gFSAClientHandle) != MOCHA_RESULT_SUCCESS) {
|
||||||
|
OSFatal("Failed to unlock FSAClientHandle");
|
||||||
|
}
|
||||||
|
|
||||||
main_loop();
|
main_loop();
|
||||||
|
|
||||||
|
FSADelClient(gFSAClientHandle);
|
||||||
|
|
||||||
WPADInput::close();
|
WPADInput::close();
|
||||||
|
|
||||||
if (ntfs_mounts != nullptr) {
|
if (ntfs_mounts != nullptr) {
|
||||||
@ -89,7 +99,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isAPDEnabled) {
|
if (isAPDEnabled) {
|
||||||
DEBUG_FUNCTION_LINE("Enable auto shutdown");
|
DEBUG_FUNCTION_LINE_VERBOSE("Enable auto shutdown");
|
||||||
IMEnableAPD();
|
IMEnableAPD();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,12 +107,13 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
WiiUScreen::DeInit();
|
WiiUScreen::DeInit();
|
||||||
WHBProcShutdown();
|
WHBProcShutdown();
|
||||||
|
AXQuit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_loop() {
|
void main_loop() {
|
||||||
DEBUG_FUNCTION_LINE("Creating state");
|
DEBUG_FUNCTION_LINE_VERBOSE("Creating state");
|
||||||
std::unique_ptr<MainApplicationState> state = std::make_unique<MainApplicationState>();
|
std::unique_ptr<MainApplicationState> state = std::make_unique<MainApplicationState>();
|
||||||
CombinedInput baseInput;
|
CombinedInput baseInput;
|
||||||
VPadInput vpadInput;
|
VPadInput vpadInput;
|
||||||
@ -112,7 +123,7 @@ void main_loop() {
|
|||||||
WPAD_CHAN_2,
|
WPAD_CHAN_2,
|
||||||
WPAD_CHAN_3};
|
WPAD_CHAN_3};
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Entering main loop");
|
DEBUG_FUNCTION_LINE_VERBOSE("Entering main loop");
|
||||||
while (WHBProcIsRunning()) {
|
while (WHBProcIsRunning()) {
|
||||||
baseInput.reset();
|
baseInput.reset();
|
||||||
if (vpadInput.update(1280, 720)) {
|
if (vpadInput.update(1280, 720)) {
|
||||||
@ -142,7 +153,7 @@ void initMochaLib() {
|
|||||||
|
|
||||||
void deInitMochaLib() {
|
void deInitMochaLib() {
|
||||||
if (slibMochaMount) {
|
if (slibMochaMount) {
|
||||||
Mocha_DeinitLibrary();
|
Mocha_DeInitLibrary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Mocha_sdio_disc_interface.shutdown();
|
Mocha_sdio_disc_interface.shutdown();
|
||||||
|
@ -1,197 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based
|
|
||||||
* on the implementation in boost::uuid::details.
|
|
||||||
*
|
|
||||||
* SHA1 Wikipedia Page: http://en.wikipedia.org/wiki/SHA-1
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012-22 SAURAV MOHAPATRA <mohaps@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef _TINY_SHA1_HPP_
|
|
||||||
#define _TINY_SHA1_HPP_
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <stdint.h>
|
|
||||||
namespace sha1
|
|
||||||
{
|
|
||||||
class SHA1
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef uint32_t digest32_t[5];
|
|
||||||
typedef uint8_t digest8_t[20];
|
|
||||||
inline static uint32_t LeftRotate(uint32_t value, size_t count) {
|
|
||||||
return (value << count) ^ (value >> (32-count));
|
|
||||||
}
|
|
||||||
SHA1(){ reset(); }
|
|
||||||
virtual ~SHA1() {}
|
|
||||||
SHA1(const SHA1& s) { *this = s; }
|
|
||||||
const SHA1& operator = (const SHA1& s) {
|
|
||||||
memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
|
|
||||||
memcpy(m_block, s.m_block, 64);
|
|
||||||
m_blockByteIndex = s.m_blockByteIndex;
|
|
||||||
m_byteCount = s.m_byteCount;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
SHA1& reset() {
|
|
||||||
m_digest[0] = 0x67452301;
|
|
||||||
m_digest[1] = 0xEFCDAB89;
|
|
||||||
m_digest[2] = 0x98BADCFE;
|
|
||||||
m_digest[3] = 0x10325476;
|
|
||||||
m_digest[4] = 0xC3D2E1F0;
|
|
||||||
m_blockByteIndex = 0;
|
|
||||||
m_byteCount = 0;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
SHA1& processByte(uint8_t octet) {
|
|
||||||
this->m_block[this->m_blockByteIndex++] = octet;
|
|
||||||
++this->m_byteCount;
|
|
||||||
if(m_blockByteIndex == 64) {
|
|
||||||
this->m_blockByteIndex = 0;
|
|
||||||
processBlock();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
SHA1& processBlock(const void* const start, const void* const end) {
|
|
||||||
const uint8_t* begin = static_cast<const uint8_t*>(start);
|
|
||||||
const uint8_t* finish = static_cast<const uint8_t*>(end);
|
|
||||||
while(begin != finish) {
|
|
||||||
processByte(*begin);
|
|
||||||
begin++;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
SHA1& processBytes(const void* const data, size_t len) {
|
|
||||||
const uint8_t* block = static_cast<const uint8_t*>(data);
|
|
||||||
processBlock(block, block + len);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
const uint32_t* getDigest(digest32_t digest) {
|
|
||||||
size_t bitCount = this->m_byteCount * 8;
|
|
||||||
processByte(0x80);
|
|
||||||
if (this->m_blockByteIndex > 56) {
|
|
||||||
while (m_blockByteIndex != 0) {
|
|
||||||
processByte(0);
|
|
||||||
}
|
|
||||||
while (m_blockByteIndex < 56) {
|
|
||||||
processByte(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (m_blockByteIndex < 56) {
|
|
||||||
processByte(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
processByte(0);
|
|
||||||
processByte(0);
|
|
||||||
processByte(0);
|
|
||||||
processByte(0);
|
|
||||||
processByte( static_cast<unsigned char>((bitCount>>24) & 0xFF));
|
|
||||||
processByte( static_cast<unsigned char>((bitCount>>16) & 0xFF));
|
|
||||||
processByte( static_cast<unsigned char>((bitCount>>8 ) & 0xFF));
|
|
||||||
processByte( static_cast<unsigned char>((bitCount) & 0xFF));
|
|
||||||
|
|
||||||
memcpy(digest, m_digest, 5 * sizeof(uint32_t));
|
|
||||||
return digest;
|
|
||||||
}
|
|
||||||
const uint8_t* getDigestBytes(digest8_t digest) {
|
|
||||||
digest32_t d32;
|
|
||||||
getDigest(d32);
|
|
||||||
size_t di = 0;
|
|
||||||
digest[di++] = ((d32[0] >> 24) & 0xFF);
|
|
||||||
digest[di++] = ((d32[0] >> 16) & 0xFF);
|
|
||||||
digest[di++] = ((d32[0] >> 8) & 0xFF);
|
|
||||||
digest[di++] = ((d32[0]) & 0xFF);
|
|
||||||
|
|
||||||
digest[di++] = ((d32[1] >> 24) & 0xFF);
|
|
||||||
digest[di++] = ((d32[1] >> 16) & 0xFF);
|
|
||||||
digest[di++] = ((d32[1] >> 8) & 0xFF);
|
|
||||||
digest[di++] = ((d32[1]) & 0xFF);
|
|
||||||
|
|
||||||
digest[di++] = ((d32[2] >> 24) & 0xFF);
|
|
||||||
digest[di++] = ((d32[2] >> 16) & 0xFF);
|
|
||||||
digest[di++] = ((d32[2] >> 8) & 0xFF);
|
|
||||||
digest[di++] = ((d32[2]) & 0xFF);
|
|
||||||
|
|
||||||
digest[di++] = ((d32[3] >> 24) & 0xFF);
|
|
||||||
digest[di++] = ((d32[3] >> 16) & 0xFF);
|
|
||||||
digest[di++] = ((d32[3] >> 8) & 0xFF);
|
|
||||||
digest[di++] = ((d32[3]) & 0xFF);
|
|
||||||
|
|
||||||
digest[di++] = ((d32[4] >> 24) & 0xFF);
|
|
||||||
digest[di++] = ((d32[4] >> 16) & 0xFF);
|
|
||||||
digest[di++] = ((d32[4] >> 8) & 0xFF);
|
|
||||||
digest[di++] = ((d32[4]) & 0xFF);
|
|
||||||
return digest;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void processBlock() {
|
|
||||||
uint32_t w[80];
|
|
||||||
for (size_t i = 0; i < 16; i++) {
|
|
||||||
w[i] = (m_block[i*4 + 0] << 24);
|
|
||||||
w[i] |= (m_block[i*4 + 1] << 16);
|
|
||||||
w[i] |= (m_block[i*4 + 2] << 8);
|
|
||||||
w[i] |= (m_block[i*4 + 3]);
|
|
||||||
}
|
|
||||||
for (size_t i = 16; i < 80; i++) {
|
|
||||||
w[i] = LeftRotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t a = m_digest[0];
|
|
||||||
uint32_t b = m_digest[1];
|
|
||||||
uint32_t c = m_digest[2];
|
|
||||||
uint32_t d = m_digest[3];
|
|
||||||
uint32_t e = m_digest[4];
|
|
||||||
|
|
||||||
for (std::size_t i=0; i<80; ++i) {
|
|
||||||
uint32_t f = 0;
|
|
||||||
uint32_t k = 0;
|
|
||||||
|
|
||||||
if (i<20) {
|
|
||||||
f = (b & c) | (~b & d);
|
|
||||||
k = 0x5A827999;
|
|
||||||
} else if (i<40) {
|
|
||||||
f = b ^ c ^ d;
|
|
||||||
k = 0x6ED9EBA1;
|
|
||||||
} else if (i<60) {
|
|
||||||
f = (b & c) | (b & d) | (c & d);
|
|
||||||
k = 0x8F1BBCDC;
|
|
||||||
} else {
|
|
||||||
f = b ^ c ^ d;
|
|
||||||
k = 0xCA62C1D6;
|
|
||||||
}
|
|
||||||
uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
|
|
||||||
e = d;
|
|
||||||
d = c;
|
|
||||||
c = LeftRotate(b, 30);
|
|
||||||
b = a;
|
|
||||||
a = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_digest[0] += a;
|
|
||||||
m_digest[1] += b;
|
|
||||||
m_digest[2] += c;
|
|
||||||
m_digest[3] += d;
|
|
||||||
m_digest[4] += e;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
digest32_t m_digest;
|
|
||||||
uint8_t m_block[64];
|
|
||||||
size_t m_blockByteIndex;
|
|
||||||
size_t m_byteCount;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,6 +1,4 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "../fs/FSUtils.h"
|
|
||||||
#include "TinySHA1.hpp"
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -40,29 +38,6 @@ void Utils::dumpHex(const void *data, size_t size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Utils::calculateSHA1(const char *buffer, size_t size) {
|
|
||||||
sha1::SHA1 s;
|
|
||||||
s.processBytes(buffer, size);
|
|
||||||
uint32_t digest[5];
|
|
||||||
s.getDigest(digest);
|
|
||||||
char tmp[48];
|
|
||||||
snprintf(tmp, 45, "%08X%08X%08X%08X%08X", digest[0], digest[1], digest[2], digest[3], digest[4]);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Utils::hashFile(const std::string &path) {
|
|
||||||
uint8_t *data = NULL;
|
|
||||||
uint32_t size = 0;
|
|
||||||
FSUtils::LoadFileToMem(path.c_str(), &data, &size);
|
|
||||||
if (data == NULL) {
|
|
||||||
return calculateSHA1(NULL, 0);
|
|
||||||
}
|
|
||||||
std::string result = calculateSHA1(reinterpret_cast<const char *>(data), size);
|
|
||||||
free(data);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int swap_uint32(unsigned int val) {
|
unsigned int swap_uint32(unsigned int val) {
|
||||||
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
|
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
|
||||||
return (val << 16) | (val >> 16);
|
return (val << 16) | (val >> 16);
|
||||||
|
2
source/version.h
Normal file
2
source/version.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#define VERSION_EXTRA ""
|
Loading…
x
Reference in New Issue
Block a user