Compare commits

..

31 Commits

Author SHA1 Message Date
mariomadproductions
04872a3e83 README.md: documented autoskip mode 2023-12-26 13:19:29 +01:00
dependabot[bot]
498696953a Bump wiiu-env/devkitppc from 20221228 to 20230621
Bumps wiiu-env/devkitppc from 20221228 to 20230621.

---
updated-dependencies:
- dependency-name: wiiu-env/devkitppc
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 13:19:31 +02:00
Maschell
86815beb77 Create dependabot.yml 2023-07-23 10:39:36 +02:00
Maschell
c3dfb55869 Change docker registry to ghcr.io 2023-03-18 16:33:40 +01:00
Maschell
57f823a5de Improve logging 2023-01-10 16:45:57 +01:00
Maschell
0da71f9420 Init AX to stop boot sound while running WUDD 2023-01-10 16:45:57 +01:00
Maschell
60688c0663 Use latest libmocha 2023-01-10 16:45:57 +01:00
Maschell
8a61dda7df Update the CI to use a non-deprecated release action 2023-01-10 16:45:57 +01:00
Maschell
eab18ef051 Bump version to v1.2.2 2023-01-10 16:45:57 +01:00
Maschell
2b46671df6 Store the size of H3HashArray in a uint32_t instead of int8_t to avoid an overflow of the size. 2023-01-02 17:14:49 +01:00
Maschell
cda26ddfd4 Update CI to use actions/checkout@v3 2023-01-02 17:14:49 +01:00
Maschell
5462d030d5 Update Makefile to be compatible with CLion 2023-01-02 17:14:49 +01:00
Maschell
16496baa65 Bump version to v1.2.1 2022-09-20 20:40:46 +02:00
Maschell
359d2e1450 Use ubuntu-22.04 for the CI 2022-09-20 20:40:46 +02:00
Maschell
84a32a5142 Only distribute WUDD as .wuhb 2022-09-20 20:40:46 +02:00
Maschell
bb559cb904 Add a icon to the WUHB 2022-09-20 20:40:46 +02:00
Maschell
6e3cea9b93 Bump version 2022-08-06 22:11:31 +02:00
Maschell
6899987864 Fix decrypted reading with the offset is bigger than UINT32_MAX 2022-08-05 18:48:42 +02:00
Maschell
f09f8f2b29 Use a dedicated FSAClient instead of the wut_devoptab_fs_client. 2022-08-03 22:31:30 +02:00
Maschell
c8a687950f Close raw odd handle in GMPartitionsState constructor 2022-08-03 22:31:30 +02:00
Maschell
2d2267807b Update Dockerfile 2022-08-01 06:10:53 -07:00
Maschell
d6e6b9165d Display the version in the menu 2022-07-28 08:43:42 -07:00
Maschell
a53b47f2b8 Update workflows to not pull submodules anymore 2022-07-28 08:43:42 -07:00
Maschell
4b5a1eca5f Update Dockerfile to use latest wut version 2022-07-28 08:43:42 -07:00
Maschell
26f69ca852 Update github action to build PRs will all logs levels 2022-07-28 08:43:42 -07:00
Maschell
8ece8d1886 Improve displayed error messages 2022-07-28 08:43:42 -07:00
Maschell
bb6734a499 Improve write error handling 2022-07-28 08:43:42 -07:00
Maschell
bc74da90dc Properly check write results 2022-07-28 08:43:42 -07:00
Maschell
4a6269a8e5 Fix exiting via the menu when not running from HBL 2022-07-28 08:43:42 -07:00
Maschell
5a4f9484c3 Adjust debug levels to always log errors 2022-07-28 08:43:42 -07:00
Maschell
d58486e9c6 Remove unused functions / files 2022-07-28 08:43:42 -07:00
30 changed files with 275 additions and 558 deletions

10
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

View File

@ -7,39 +7,35 @@ on:
jobs:
clang-format:
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: clang-format
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:
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
needs: clang-format
steps:
- uses: actions/checkout@v2
- name: Checkout submodules using a PAT
- uses: actions/checkout@v3
- name: create version.h
run: |
git config --file .gitmodules --get-regexp url | while read url; do
git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
done
git submodule sync
git submodule update --init --recursive
git_hash=$(git rev-parse --short "$GITHUB_SHA")
cat <<EOF > ./source/version.h
#pragma once
#define VERSION_EXTRA " (nightly-$git_hash)"
EOF
- name: build binary
run: |
docker build . -t builder
docker build . -t builder
docker run --rm -v ${PWD}:/project builder make
- uses: actions/upload-artifact@master
with:
name: wuhb-binary
path: "*.wuhb"
- uses: actions/upload-artifact@master
with:
name: rpx-binary
path: "*.rpx"
deploy-binary:
needs: build-binary
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
steps:
- name: Get environment variables
id: get_repository_name
@ -50,32 +46,15 @@ jobs:
with:
name: wuhb-binary
path: wiiu/apps/wudd
- uses: actions/download-artifact@master
with:
name: rpx-binary
path: wiiu/apps/wudd
- name: zip artifact
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip wiiu
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: "softprops/action-gh-release@v1"
with:
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
release_name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
draft: false
prerelease: true
body: |
Not a stable release:
${{ github.event.head_commit.message }}
- name: Upload Release Asset
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
generate_release_notes: true
name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
files: |
./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip

View File

@ -4,29 +4,40 @@ on: [pull_request]
jobs:
clang-format:
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: clang-format
run: |
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
build-binary:
runs-on: ubuntu-18.04
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source
check-build-with-logging:
runs-on: ubuntu-22.04
needs: clang-format
steps:
- uses: actions/checkout@v2
- name: Checkout submodules using a PAT
- uses: actions/checkout@v3
- 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: |
git config --file .gitmodules --get-regexp url | while read url; do
git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
done
git submodule sync
git submodule update --init --recursive
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
cat <<EOF > ./source/version.h
#pragma once
#define VERSION_EXTRA " (nightly-$git_hash)"
EOF
- name: build binary
run: |
docker build . -t builder
docker build . -t builder
docker run --rm -v ${PWD}:/project builder make
- uses: actions/upload-artifact@master
with:
name: binary
path: "*.rpx"
path: "*.wuhb"

View File

@ -1,6 +1,6 @@
FROM wiiuenv/devkitppc:20220724
FROM ghcr.io/wiiu-env/devkitppc:20230621
COPY --from=wiiuenv/libntfs:20220726 /artifacts $DEVKITPRO
COPY --from=wiiuenv/libmocha:20220726 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libntfs:20220726 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libmocha:20220919 /artifacts $DEVKITPRO
WORKDIR project
WORKDIR project

View File

@ -52,6 +52,7 @@ SOURCES := source \
DATA := data
INCLUDES := source
ICON := data/icon.png
#-------------------------------------------------------------------------------
# options for code generation
@ -164,7 +165,7 @@ endif
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#-------------------------------------------------------------------------------

View File

@ -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.
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
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
`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

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -4,6 +4,7 @@
#include "input/Input.h"
#include "utils/ScreenUtils.h"
#include "utils/WiiUScreen.h"
#include "version.h"
#include <stdint.h>
class ApplicationState {
@ -55,7 +56,7 @@ public:
}
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("");
}
@ -76,4 +77,4 @@ public:
int selectedOptionY = 0;
int selectedOptionX = 0;
};
};

View File

@ -36,6 +36,10 @@ GMPartitionsDumperState::GMPartitionsDumperState(eDumpTarget pTargetDevice) : ta
}
GMPartitionsDumperState::~GMPartitionsDumperState() {
if (this->oddFd != -1) {
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
this->oddFd = -1;
}
free(this->sectorBuf);
this->sectorBuf = nullptr;
free(this->readBuffer);
@ -178,7 +182,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
}
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 (this->sectorBuf == nullptr) {
this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize);
@ -196,13 +200,13 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
return ApplicationState::SUBSTATE_RETURN;
}
} 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';
memcpy(this->discId.data(), sectorBuf, 10);
this->state = STATE_READ_DISC_INFO_DONE;
return ApplicationState::SUBSTATE_RUNNING;
}
FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd);
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
this->oddFd = -1;
this->setError(ERROR_READ_FIRST_SECTOR);
@ -226,7 +230,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
auto discHeaderOpt = WiiUDiscHeader::make_unique(discReader);
if (!discHeaderOpt.has_value()) {
DEBUG_FUNCTION_LINE_ERR("Failed to read DiscHeader");
this->setError(ERROR_PARSE_DISCHEADER);
this->setError(ERROR_PARSE_DISC_HEADER);
return SUBSTATE_RUNNING;
}
this->discHeader = std::move(discHeaderOpt.value());
@ -269,7 +273,7 @@ ApplicationState::eSubState GMPartitionsDumperState::update(Input *input) {
this->curNUSTitle = gmPartitionPair.second;
this->dataProvider = this->curNUSTitle->dataProcessor->getDataProvider();
} 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);
return SUBSTATE_RUNNING;
}
@ -448,108 +452,77 @@ std::string GMPartitionsDumperState::getPathForDevice(eDumpTarget target) const
}
std::string GMPartitionsDumperState::ErrorMessage() const {
if (this->errorState == ERROR_MALLOC_FAILED) {
return "ERROR_MALLOC_FAILED";
}
if (this->errorState == ERROR_NO_DISC_ID) {
return "ERROR_NO_DISC_ID";
}
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
return "ERROR_READ_FIRST_SECTOR";
}
if (this->errorState == ERROR_OPEN_ODD1) {
return "ERROR_OPEN_ODD1";
}
if (this->errorState == ERROR_PARSE_DISCHEADER) {
return "ERROR_PARSE_DISCHEADER";
}
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";
}
if (this->errorState == ERROR_FAILED_WRITE_TMD) {
return "ERROR_FAILED_WRITE_TMD";
}
if (this->errorState == ERROR_FAILED_WRITE_TICKET) {
return "ERROR_FAILED_WRITE_TICKET";
}
if (this->errorState == ERROR_FAILED_WRITE_CERT) {
return "ERROR_FAILED_WRITE_CERT";
}
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";
switch (this->errorState) {
case ERROR_NONE:
return "ERROR_NONE";
case ERROR_MALLOC_FAILED:
return "ERROR_MALLOC_FAILED";
case ERROR_READ_FIRST_SECTOR:
return "ERROR_READ_FIRST_SECTOR";
case ERROR_OPEN_ODD1:
return "ERROR_OPEN_ODD1";
case ERROR_PARSE_DISC_HEADER:
return "ERROR_PARSE_DISC_HEADER";
case ERROR_NO_GM_PARTITION:
return "ERROR_NO_GM_PARTITION";
case ERROR_CREATE_DIR:
return "ERROR_CREATE_DIR";
case ERROR_FAILED_TO_GET_NUSTITLE:
return "ERROR_FAILED_TO_GET_NUSTITLE";
case ERROR_FAILED_WRITE_TMD:
return "ERROR_FAILED_WRITE_TMD";
case ERROR_FAILED_WRITE_TICKET:
return "ERROR_FAILED_WRITE_TICKET";
case ERROR_FAILED_WRITE_CERT:
return "ERROR_FAILED_WRITE_CERT";
case ERROR_FIND_CONTENT_BY_INDEX:
return "ERROR_FIND_CONTENT_BY_INDEX";
case ERROR_FAILED_CREATE_FILE:
return "ERROR_FAILED_CREATE_FILE";
case ERROR_FAILED_WRITE_H3:
return "ERROR_FAILED_WRITE_H3";
case ERROR_READ_CONTENT:
return "ERROR_READ_CONTENT";
case ERROR_WRITE_CONTENT:
return "ERROR_WRITE_CONTENT";
}
return "UNKNOWN_ERROR";
}
std::string GMPartitionsDumperState::ErrorDescription() const {
if (this->errorState == ERROR_MALLOC_FAILED) {
return "ERROR_MALLOC_FAILED";
}
if (this->errorState == ERROR_NO_DISC_ID) {
return "ERROR_NO_DISC_ID";
}
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
return "ERROR_READ_FIRST_SECTOR";
}
if (this->errorState == ERROR_OPEN_ODD1) {
return "ERROR_OPEN_ODD1";
}
if (this->errorState == ERROR_PARSE_DISCHEADER) {
return "ERROR_PARSE_DISCHEADER";
}
if (this->errorState == ERROR_NO_GM_PARTITION) {
return "ERROR_NO_GM_PARTITION";
}
if (this->errorState == ERROR_FAILED_TO_GET_NUSTITLE) {
return "ERROR_FAILED_TO_GET_NUSTITLE";
}
if (this->errorState == ERROR_FAILED_WRITE_TMD) {
return "ERROR_FAILED_WRITE_TMD";
}
if (this->errorState == ERROR_FAILED_WRITE_TICKET) {
return "ERROR_FAILED_WRITE_TICKET";
}
if (this->errorState == ERROR_FAILED_WRITE_CERT) {
return "ERROR_FAILED_WRITE_CERT";
}
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";
switch (this->errorState) {
case ERROR_NONE:
break;
case ERROR_MALLOC_FAILED:
return "Failed to allocate memory.";
case ERROR_READ_FIRST_SECTOR:
return "Failed to read first sector.";
case ERROR_OPEN_ODD1:
return "Failed to read from disc.";
case ERROR_PARSE_DISC_HEADER:
return "Failed to parse the disc header.";
case ERROR_NO_GM_PARTITION:
return "No games were found on this disc.";
case ERROR_CREATE_DIR:
return "Failed to create a directory. \nMake sure to have enough space on the storage device.";
case ERROR_FAILED_TO_GET_NUSTITLE:
return "Failed to parse partition as NUSTitle";
case ERROR_FAILED_WRITE_TMD:
return "Failed to dump the title.tmd";
case ERROR_FAILED_WRITE_TICKET:
return "Failed to dump the title.tik";
case ERROR_FAILED_WRITE_CERT:
return "Failed to dump the title.cert";
case ERROR_FIND_CONTENT_BY_INDEX:
return "Failed to find requested index";
case ERROR_FAILED_CREATE_FILE:
return "Failed to create a file. \nMake sure to have enough space on the storage device.";
case ERROR_FAILED_WRITE_H3:
return "Failed to dump the a .h3 file";
case ERROR_READ_CONTENT:
return "Failed to read the a .app file from disc";
case ERROR_WRITE_CONTENT:
return "Failed to dump a .app. \nMake sure to have enough space on the storage device.";
}
return "UNKNOWN_ERROR";
}

View File

@ -55,10 +55,9 @@ public:
enum eErrorState {
ERROR_NONE,
ERROR_MALLOC_FAILED,
ERROR_NO_DISC_ID,
ERROR_READ_FIRST_SECTOR,
ERROR_OPEN_ODD1,
ERROR_PARSE_DISCHEADER,
ERROR_PARSE_DISC_HEADER,
ERROR_NO_GM_PARTITION,
ERROR_CREATE_DIR,
ERROR_FAILED_TO_GET_NUSTITLE,

View File

@ -88,7 +88,7 @@ ApplicationState::eSubState MainApplicationState::update(Input *input) {
} else if (this->selectedOptionY == 3) {
//
} else {
if (gRunFromHBL) {
if (!gRunFromHBL) {
SYSLaunchMenu();
}
}

View File

@ -81,7 +81,7 @@ bool DiscReader::readDecrypted(uint8_t *out_buffer, uint64_t clusterOffset, uint
uint32_t blockNumber = (totalOffset / BLOCK_SIZE);
uint32_t blockOffset = (totalOffset % BLOCK_SIZE);
readOffset = (blockNumber * BLOCK_SIZE);
readOffset = ((uint64_t) blockNumber * BLOCK_SIZE);
if (!useFixedIV) {
memset(usedIV, 0, 16);
uint64_t ivTemp = usedFileOffset >> 16;

View File

@ -31,13 +31,13 @@ DiscReaderDiscDrive::DiscReaderDiscDrive() : DiscReader() {
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) {
free(sector_buf);
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 (((uint32_t *) sector_buf)[0] != WiiUDiscContentsHeader::MAGIC) {
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 {
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 true;
@ -87,7 +87,7 @@ bool DiscReaderDiscDrive::IsReady() {
DiscReaderDiscDrive::~DiscReaderDiscDrive() {
if (device_handle != -1) {
FSAEx_RawClose(__wut_devoptab_fs_client, device_handle);
FSAEx_RawCloseEx(gFSAClientHandle, device_handle);
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 offset_in_sectors = offset >> 15;
if (FSAEx_RawRead(__wut_devoptab_fs_client, buf, 0x8000, block_cnt, offset_in_sectors, device_handle) < 0) {
DEBUG_FUNCTION_LINE("Failed to read from Disc");
if (FSAEx_RawReadEx(gFSAClientHandle, buf, 0x8000, block_cnt, offset_in_sectors, device_handle) < 0) {
DEBUG_FUNCTION_LINE_ERR("Failed to read from Disc");
return false;
}
return true;

View File

@ -26,7 +26,6 @@ std::optional<std::unique_ptr<WiiUDiscContentsHeader>> WiiUDiscContentsHeader::m
return {};
}
if (!discReader->hasDiscKey) {
DEBUG_FUNCTION_LINE_ERR();
if (!discReader->readEncrypted(buffer.get(), offset, LENGTH)) {
DEBUG_FUNCTION_LINE_ERR("Failed to read data");
return {};

View File

@ -28,5 +28,5 @@ public:
~H3HashArray();
std::unique_ptr<uint8_t[]> data;
uint8_t size;
uint32_t size;
};

View File

@ -35,7 +35,7 @@ WUDDumperState::WUDDumperState(WUDDumperState::eDumpTargetFormat pTargetFormat,
WUDDumperState::~WUDDumperState() {
if (this->oddFd >= 0) {
FSAEx_RawClose(__wut_devoptab_fs_client, oddFd);
FSAEx_RawCloseEx(gFSAClientHandle, oddFd);
}
free(sectorBuf);
free(emptySector);
@ -51,7 +51,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
}
if (this->state == STATE_OPEN_ODD1) {
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) {
// continue!
this->state = STATE_DUMP_DISC;
@ -65,12 +65,12 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
this->state = STATE_PLEASE_INSERT_DISC;
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 (this->sectorBuf == nullptr) {
this->sectorBuf = (void *) memalign(0x100, this->sectorBufSize);
if (this->sectorBuf == nullptr) {
DEBUG_FUNCTION_LINE("ERROR_MALLOC_FAILED");
DEBUG_FUNCTION_LINE_ERR("ERROR_MALLOC_FAILED");
this->setError(ERROR_MALLOC_FAILED);
return ApplicationState::SUBSTATE_RUNNING;
}
@ -83,7 +83,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
return SUBSTATE_RETURN;
}
} 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';
memcpy(this->discId.data(), sectorBuf, 10);
this->state = STATE_READ_DISC_INFO_DONE;
@ -96,7 +96,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
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.
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;
bool hasDiscKey = false;
if (res >= 0) {
@ -132,7 +132,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
SECTOR_SIZE, targetDevice == TARGET_SD);
}
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);
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;
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);
if (curWrittenSectors < 0) {
this->setError(ERROR_WRITE_FAILED);
@ -165,18 +165,22 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
this->state = STATE_DUMP_DISC_DONE;
if (this->fileHandle->isOpen()) {
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);
return ApplicationState::SUBSTATE_RUNNING;
}
this->fileHandle->finalize();
this->fileHandle->close();
}
}
} else {
this->state = STATE_WAIT_USER_ERROR_CONFIRM;
if (this->oddFd >= 0) {
FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd);
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
this->oddFd = -1;
}
return ApplicationState::SUBSTATE_RUNNING;
@ -199,7 +203,7 @@ ApplicationState::eSubState WUDDumperState::update(Input *input) {
} else if (this->state == STATE_WAIT_USER_ERROR_CONFIRM) {
if (this->autoSkipOnError) {
if (this->oddFd >= 0) {
FSAEx_RawClose(__wut_devoptab_fs_client, this->oddFd);
FSAEx_RawCloseEx(gFSAClientHandle, this->oddFd);
this->oddFd = -1;
}
}
@ -251,6 +255,7 @@ void WUDDumperState::render() {
WiiUScreen::drawLinef("Error: %s", ErrorMessage().c_str());
WiiUScreen::drawLinef("Description: %s", ErrorDescription().c_str());
WiiUScreen::drawLine();
WiiUScreen::drawLine();
WiiUScreen::drawLine("Press A to return.");
} else if (this->state == STATE_OPEN_ODD1) {
WiiUScreen::drawLine("Open /dev/odd01");
@ -324,31 +329,37 @@ void WUDDumperState::setError(WUDDumperState::eErrorState err) {
}
std::string WUDDumperState::ErrorMessage() const {
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
return "ERROR_READ_FIRST_SECTOR";
} else if (this->errorState == ERROR_FILE_OPEN_FAILED) {
return "ERROR_FILE_OPEN_FAILED";
} else if (this->errorState == ERROR_MALLOC_FAILED) {
return "ERROR_MALLOC_FAILED";
} else if (this->errorState == ERROR_NO_DISC_ID) {
return "ERROR_NO_DISC_ID";
} else if (this->errorState == ERROR_WRITE_FAILED) {
return "ERROR_WRITE_FAILED";
switch (this->errorState) {
case ERROR_READ_FIRST_SECTOR:
return "ERROR_READ_FIRST_SECTOR";
case ERROR_NONE:
return "ERROR_NONE";
case ERROR_FILE_OPEN_FAILED:
return "ERROR_FILE_OPEN_FAILED";
case ERROR_MALLOC_FAILED:
return "ERROR_MALLOC_FAILED";
case ERROR_WRITE_FAILED:
return "ERROR_WRITE_FAILED";
case ERROR_NO_DISC_FOUND:
return "ERROR_NO_DISC_FOUND";
}
return "UNKNOWN_ERROR";
}
std::string WUDDumperState::ErrorDescription() const {
if (this->errorState == ERROR_READ_FIRST_SECTOR) {
return "Failed to read first sector.";
} else if (this->errorState == ERROR_MALLOC_FAILED) {
return "Failed to allocate data.";
} else if (this->errorState == ERROR_FILE_OPEN_FAILED) {
return "Failed to create file";
} else if (this->errorState == ERROR_NO_DISC_ID) {
return "Failed to get the disc id";
} else if (this->errorState == ERROR_WRITE_FAILED) {
return "Failed to write the file. \nMake sure to have enough space on the storage";
switch (this->errorState) {
case ERROR_READ_FIRST_SECTOR:
return "Failed to read first sector.";
case ERROR_NONE:
return "ERROR_NONE";
case ERROR_FILE_OPEN_FAILED:
return "Failed to create file \nMake sure to have enough space on the storage device.";
case ERROR_MALLOC_FAILED:
return "Failed to allocate data.";
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";
}

View File

@ -57,7 +57,6 @@ public:
ERROR_READ_FIRST_SECTOR,
ERROR_FILE_OPEN_FAILED,
ERROR_MALLOC_FAILED,
ERROR_NO_DISC_ID,
ERROR_WRITE_FAILED,
ERROR_NO_DISC_FOUND
};

View File

@ -4,3 +4,4 @@ int ntfs_mount_count = 0;
BOOL gRunFromHBL = false;
BOOL gBlockHomeButton = false;
uint32_t gBlockHomeButtonCooldown = 0;
FSAClientHandle gFSAClientHandle = 0;

View File

@ -1,5 +1,6 @@
#pragma once
#include <coreinit/filesystem_fsa.h>
#include <ntfs.h>
#include <wut.h>
@ -9,12 +10,13 @@
extern ntfs_md *ntfs_mounts;
extern int ntfs_mount_count;
extern "C" FSClient *__wut_devoptab_fs_client;
extern FSAClientHandle gFSAClientHandle;
extern BOOL gRunFromHBL;
extern BOOL gBlockHomeButton;
extern uint32_t gBlockHomeButtonCooldown;
enum eDumpTarget {
TARGET_SD,
TARGET_NTFS

View File

@ -1,64 +1,10 @@
#include "FSUtils.h"
#include "CFile.hpp"
#include "utils/logger.h"
#include "utils/utils.h"
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <malloc.h>
#include <stdio.h>
#include <string.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) {
if (!filepath)
return 0;
@ -130,39 +76,6 @@ int32_t FSUtils::CreateSubfolder(const char *fullpath) {
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) {
CFile file(path, CFile::WriteOnly);
if (!file.isOpen()) {

View File

@ -5,13 +5,9 @@
class FSUtils {
public:
static int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size);
static int32_t CreateSubfolder(const char *fullpath);
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);
};

View File

@ -29,5 +29,6 @@ int32_t WUDFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSecto
return -1;
}
void WUDFileWriter::finalize() {
bool WUDFileWriter::finalize() {
return true;
}

View File

@ -24,7 +24,7 @@ public:
virtual int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors);
virtual void finalize();
virtual bool finalize();
protected:
int32_t sectorSize;

View File

@ -27,19 +27,24 @@ WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sector
wuxHeader.uncompressedSize = swap_uint64(WUD_FILE_SIZE);
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->totalSectorCount = WUD_FILE_SIZE / this->sectorSize;
this->sectorIndexTable = (void *) memalign(0x40, ROUNDUP(totalSectorCount * 4, 0x40));
if (sectorIndexTable == nullptr) {
DEBUG_FUNCTION_LINE("Failed to alloc");
DEBUG_FUNCTION_LINE_ERR("Failed to alloc");
WUDFileWriter::close();
return;
}
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();
return;
}
@ -53,14 +58,24 @@ WUXFileWriter::WUXFileWriter(const char *path, int32_t cacheSize, int32_t sector
uint64_t padding = this->sectorTableEnd - tableEnd;
auto *paddingData = (uint8_t *) memalign(0x40, ROUNDUP(padding, 0x40));
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);
this->hashMap.clear();
flush();
if (!flush()) {
WUXFileWriter::close();
}
}
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;
for (uint32_t i = 0; i < numberOfSectors; i++) {
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);
hashMap[hashOut] = writtenSector;
if (isOpen()) {
if (!write((uint8_t *) addr, this->sectorSize)) {
DEBUG_FUNCTION_LINE("Write failed");
if (write((uint8_t *) addr, this->sectorSize) != this->sectorSize) {
DEBUG_FUNCTION_LINE_ERR("Write failed");
return -1;
}
}
@ -89,23 +104,36 @@ int32_t WUXFileWriter::writeSector(const uint8_t *buffer, uint32_t numberOfSecto
return curWrittenSectors;
}
void WUXFileWriter::writeSectorIndexTable() {
bool WUXFileWriter::writeSectorIndexTable() {
if (this->isOpen()) {
flush();
if (!flush()) {
return false;
}
// We need to make sure to call CFile::seek!
seek((int64_t) sectorTableStart, SEEK_SET_BASE_CLASS);
write((uint8_t *) sectorIndexTable, totalSectorCount * 4);
flush();
if (seek((int64_t) sectorTableStart, SEEK_SET_BASE_CLASS) < 0) {
DEBUG_FUNCTION_LINE_ERR("Seek failed");
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::flush();
WUXFileWriter::close();
free(sectorIndexTable);
}
void WUXFileWriter::finalize() {
bool WUXFileWriter::finalize() {
WUDFileWriter::finalize();
writeSectorIndexTable();
bool res = writeSectorIndexTable();
WUXFileWriter::close();
return res;
}

View File

@ -39,10 +39,10 @@ public:
int32_t writeSector(const uint8_t *buffer, uint32_t numberOfSectors) override;
void finalize() override;
bool finalize() override;
private:
void writeSectorIndexTable();
bool writeSectorIndexTable();
uint64_t totalSectorCount;

View File

@ -45,8 +45,8 @@ WriteOnlyFileWithCache::~WriteOnlyFileWithCache() {
bool WriteOnlyFileWithCache::flush() {
if (this->writeBufferPos > 0) {
int32_t res = CFile::write(static_cast<const uint8_t *>(this->writeBuffer), this->writeBufferPos);
if (res < 0) {
DEBUG_FUNCTION_LINE("Failed to flush cache, write failed: %d", res);
if (res != (int32_t) this->writeBufferPos) {
DEBUG_FUNCTION_LINE_ERR("Failed to flush cache, write failed: %d (expected %d)", res, this->writeBufferPos);
return false;
}
this->writeBufferPos = 0;
@ -58,8 +58,8 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
auto finalAddr = addr;
size_t finalWriteSize = writeSize;
if (splitFile) {
if (pos + writeBufferPos + finalWriteSize >= SPLIT_SIZE) {
DEBUG_FUNCTION_LINE("We need to split");
if (pos + writeBufferPos + finalWriteSize >= (uint64_t) SPLIT_SIZE) {
DEBUG_FUNCTION_LINE("We need to split files");
if (!flush()) {
return -2;
}
@ -67,7 +67,7 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
uint32_t realWriteSize = SPLIT_SIZE - pos;
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) {
return -3;
}
@ -91,7 +91,7 @@ int32_t WriteOnlyFileWithCache::write(const uint8_t *addr, size_t writeSize) {
if (finalWriteSize == this->writeBufferSize) {
if (!this->flush()) {
DEBUG_FUNCTION_LINE("Flush failed");
DEBUG_FUNCTION_LINE_ERR("Flush failed");
return -1;
}
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->flush()) {
DEBUG_FUNCTION_LINE("Flush failed");
DEBUG_FUNCTION_LINE_ERR("Flush failed");
return -2;
}
}

View File

@ -11,6 +11,7 @@
#include <mocha/mocha.h>
#include <ntfs.h>
#include <padscore/kpad.h>
#include <sndcore2/core.h>
#include <thread>
#include <whb/log.h>
#include <whb/proc.h>
@ -37,7 +38,7 @@ procHomeButtonDeniedCustom(void *context) {
int main(int argc, char **argv) {
initLogging();
DEBUG_FUNCTION_LINE("Hello from wudump!");
AXInit();
WHBProcInit();
WiiUScreen::Init();
@ -53,9 +54,7 @@ int main(int argc, char **argv) {
ProcUIClearCallbacks();
ProcUIRegisterCallback(PROCUI_CALLBACK_HOME_BUTTON_DENIED,
&procHomeButtonDeniedCustom, NULL, 100);
&procHomeButtonDeniedCustom, nullptr, 100);
} else {
gRunFromHBL = false;
}
@ -64,7 +63,7 @@ int main(int argc, char **argv) {
IMIsAPDEnabled(&isAPDEnabled);
if (isAPDEnabled) {
DEBUG_FUNCTION_LINE("Disable auto shutdown");
DEBUG_FUNCTION_LINE_VERBOSE("Disable auto shutdown");
IMDisableAPD();
}
@ -76,8 +75,19 @@ int main(int argc, char **argv) {
WPADInput::init();
gFSAClientHandle = FSAAddClient(nullptr);
if (!gFSAClientHandle) {
OSFatal("FSAAddClient failed");
}
if (Mocha_UnlockFSClientEx(gFSAClientHandle) != MOCHA_RESULT_SUCCESS) {
OSFatal("Failed to unlock FSAClientHandle");
}
main_loop();
FSADelClient(gFSAClientHandle);
WPADInput::close();
if (ntfs_mounts != nullptr) {
@ -89,7 +99,7 @@ int main(int argc, char **argv) {
}
if (isAPDEnabled) {
DEBUG_FUNCTION_LINE("Enable auto shutdown");
DEBUG_FUNCTION_LINE_VERBOSE("Enable auto shutdown");
IMEnableAPD();
}
@ -97,12 +107,13 @@ int main(int argc, char **argv) {
WiiUScreen::DeInit();
WHBProcShutdown();
AXQuit();
return 0;
}
void main_loop() {
DEBUG_FUNCTION_LINE("Creating state");
DEBUG_FUNCTION_LINE_VERBOSE("Creating state");
std::unique_ptr<MainApplicationState> state = std::make_unique<MainApplicationState>();
CombinedInput baseInput;
VPadInput vpadInput;
@ -112,7 +123,7 @@ void main_loop() {
WPAD_CHAN_2,
WPAD_CHAN_3};
DEBUG_FUNCTION_LINE("Entering main loop");
DEBUG_FUNCTION_LINE_VERBOSE("Entering main loop");
while (WHBProcIsRunning()) {
baseInput.reset();
if (vpadInput.update(1280, 720)) {
@ -142,7 +153,7 @@ void initMochaLib() {
void deInitMochaLib() {
if (slibMochaMount) {
Mocha_DeinitLibrary();
Mocha_DeInitLibrary();
}
Mocha_sdio_disc_interface.shutdown();

View File

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

View File

@ -1,6 +1,4 @@
#include "utils.h"
#include "../fs/FSUtils.h"
#include "TinySHA1.hpp"
#include "logger.h"
#include <cstddef>
#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) {
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
return (val << 16) | (val >> 16);

2
source/version.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once
#define VERSION_EXTRA ""