Files
drippu/tools-local/hactoolnet-src/nax0.c
suyu teamandcopilot-swe-agent[bot] 24c562379b Fix building (#79)
* vcpkg overlay: remove vendored xbyak, disable warnings-as-errors; CI: ensure MSVC env is initialized before CMake and cleanup debug/share

* CI: setup MSVC env + disable tests; vcpkg: add glslang tools

* CI: disable Qt in main Windows job to avoid missing Qt dependency; keep MSVC env setup

* DownloadExternals: don't claim bundled binaries when archive missing; add mcl overlay with versioned config; add sdl2 to manifest

* Update cpp-httplib submodule to latest commit

* Initial plan

* Fix build: switch to Conan, add missing workflow files, fix Vulkan SDK hang

* Fix codespell: skip vcpkg_installed directory

* Initial plan

* Address reviewer comments: fix find_program NAMES, mcl portfile REF/install/config, workflow CONAN_HOME and -UseBasicParsing, toJson log injection

* Add Linux (GCC) and macOS (Apple Clang) build jobs to cmake-multi-platform.yml

* Fix workflow cache variable names and document agentic workflows in README

* Initial plan

* fix: update auto-fix-workflows trigger branches and permissions for changed base branch

* Initial plan

* Fix workflow triggers, Conan 2.x cache variable, and agentic bot permissions

* Add fix/dynarmic-vcpkg-msvc-ci to suyu-ci and suyu verify PR triggers

* Fix duplicate shell key in cmake Configure CMake step, add Android build PR triggers

* Fix cpp-httplib submodule, codespell infP false positive, and REUSE compliance for all 108 missing files

* Fix Linux Conan xorg/system missing X11 dev packages and verify.yml container EACCES permission error

* Fix Android duplicate drawable resources and macOS missing FFmpeg dependency

* Add FFmpeg dev packages to Linux apt-get install for CMake FindFFmpeg

* Switch Windows Vulkan SDK install from direct download (hangs) to chocolatey

* Fix remaining workflow failures: Linux xcb-util pkgs, CMake policy compat, Vulkan SDK fallback, verify git safe.directory, Android layout root ID mismatch

* Address code review: extract Vulkan SDK version to env var, add timeout comment

* Strip trailing whitespace from 28 files to pass suyu verify format check

* Remove src.bak.20251103_153257 backup dir (36MB) and eden_conflicts artifact

* Fix Linux libudev-dev, autoupdate.yml missing run key, Android missing styles/strings, review feedback

* Initial plan

* Fix workflow bugs: runner labels, deprecated actions, broken step IDs, package names

Agent-Logs-Url: https://github.com/suyu-emu/SuyuEclipse/sessions/b6faad50-85a4-4c00-b095-a13021d141ff

* Remove vk_texture_manager stub, restore vcpkg.json, remove autoupdate no-op stub step

Agent-Logs-Url: https://github.com/suyu-emu/SuyuEclipse/sessions/88f79c2b-e2ef-439f-bcc5-4d41f2eb80ab

* Fix CI failures: conanfile sdl2→sdl, vcpkg remove boost-headers, clang-format fixes

Agent-Logs-Url: https://github.com/suyu-emu/SuyuEclipse/sessions/4f31b9e3-cd49-438e-9c3a-18706b1838c3

* Fix CI: clang-format files, CMake duplicate subdirs, libglu, glslangValidator PATH, macOS zstd conflict, Android SUYU_TESTS

Agent-Logs-Url: https://github.com/suyu-emu/SuyuEclipse/sessions/1af86774-b1eb-42e9-a1ee-09297035f409

* Fix CI: mesa-common-dev, ENABLE_QT=OFF all platforms, zstd 1.5.6, brew unlink zstd, clang-format 4 files, Android multiplayer strings from Eden

Agent-Logs-Url: https://github.com/suyu-emu/SuyuEclipse/sessions/34369fa5-d1b3-48e1-b0b5-b95bc4a5470c

* Update cpp-httplib

* Enhance CMake configuration: update C++ standard to C++20, add platform and architecture detection modules, and improve build presets for optimized architecture targeting.

* Add ModeSelector dialog for user mode selection with descriptions and settings persistence

* Add new UI components: DecryptionFlowWidget, EmulatorCoreManager, McpServer, ProgrammerEnvironment, SocialSidebar, SteamIntegration, and UserManualWidget

* Add new components: DecryptionFlowWidget, EmulatorCoreManager, McpServer, ProgrammerEnvironment, SocialSidebar, SteamIntegration, and UserManualWidget

* Refactor firmware installation and decryption key handling: remove deprecated checks and update user prompts

* Implement mode-specific UI adjustments: add ApplyAppMode function to manage visibility of UI components based on user mode selection.

* Refactor code structure for improved readability and maintainability

* Add CMake build scripts for MSVC configuration and logging

* Enhance CMake configuration: add support for additional tests and features, handle missing dependencies, and improve error messaging for external downloads

* Add SDL2 and FFmpeg support in CMake configuration and improve build scripts

* Add build script for MSVC using CMake

- Created a new batch file `run_build.bat` to automate the build process.
- The script sets up the Visual Studio environment and navigates to the project directory.
- It executes the CMake build command targeting the 'suyu' project.
- Captures and displays the exit code of the build process.

* update

* Fix dynamic vcpkg integration for MSVC CI

* Enhance CMake configuration and add compatibility files for improved build support

* Add interface mode change action and update UI components

* Add interface mode change handler to GMainWindow

* Add build configuration scripts for MSVC integration

* Add build script for MSVC4 configuration and test files

- Created `build-msvc4-config2.cmd` to automate the build configuration process using CMake with specified options.
- Added `build-msvc4-test.txt` as a placeholder for test output verification.
- Introduced `testout2c.txt` for additional test output, currently containing binary data.

* Add build script for MSVC4 configuration and test files

- Created a new batch script `build-msvc4-config2.cmd` to automate the build configuration process for MSVC4, including setting up the environment and invoking CMake with specified options.
- Added a test file `build-msvc4-test.txt` containing a simple "ok" message for verification purposes.
- Introduced `testout2c.txt` with binary content for further testing.

* Add ProcDump output files for process monitoring

- Created procdump_output.txt to capture the output when no matching process is found.
- Created procdump_output2.txt to log details of the monitored process 'suyu.exe', including exit information and dump settings.

* Add new PNG image file win_0_12257664.png

* Update subproject commit and adjust widget initialization in GMainWindow

* Add GamerEnvironment and related UI components for enhanced gaming experience

- Introduced GamerEnvironment class to manage the new gaming interface.
- Implemented GameCardDelegate for rendering game cards with cover art and information.
- Added UI elements including a sidebar for navigation and a main content area for game display.
- Integrated functionality for searching games, adding directories, and loading games.
- Restored ApplyAppMode function in main.cpp to handle switching between different application modes.
- Updated main.h to include GamerEnvironment and its associated members.
- Created fix_main.py script to automate the restoration of the ApplyAppMode function.

* Enhance ModeSelector UI and functionality with improved layout and styling

* Refactor code structure for improved readability and maintainability

* Add automated tests for menu interactions and MCP server functionality

- Created test_all_menus.ps1 to automate menu item interactions and capture dialog screenshots.
- Implemented test_mcp.ps1 for testing JSON-RPC 2.0 protocol over TCP with various method calls.
- Added test_mcp2.ps1 for additional MCP tool tests, including error handling for unknown methods and malformed JSON.
- Introduced test_menu_async.ps1 to test menu interactions asynchronously and capture dialog outputs.
- Developed test_single_menu.ps1 for single menu item invocation and dialog handling.
- Created verify_menus.ps1 to verify the presence and state of menu items in the application.

* Update URLs to new website domain for localization and application settings

- Changed app disclaimer and help links in Vietnamese, Simplified Chinese, Traditional Chinese, and English strings to point to the new website domain.
- Updated web API URL in settings to reflect the new domain.
- Modified TAS configuration help link to use the new website.
- Adjusted various navigation links in the gamer environment and main application to direct users to the new website.

* Add multiplayer server management features and settings

* Add ModBrowserDialog for mod management and update multiplayer connection handling

* Add 'Add to Steam' option in game context menu and implement shortcut creation

* Enhance loading screen UI and add agentic workflow documentation for GitHub Actions

* Refactor library page layout and enhance UI components for better user experience

* Enhance button styling in GamerEnvironment for improved UI responsiveness

* Enhance loading screen with spinner animation and artwork type selection for Steam integration

* build

* Add game overlay feature with F1 shortcut and corresponding UI integration

* Refactor Steam integration to use public Steam Store endpoints for artwork fetching and update related UI components for improved user experience

* fix dlls

* Add support for Hacker and Gamer modes in application startup and enhance MCP server tool registration

* Refactor web service settings and UI components for Eden integration

* Refactor settings and authentication to replace 'suyu' references with 'eden' for improved account integration

* Fix build issues and warnings in Suyu project

- Added missing Q_OBJECT macro in game_card.cpp and game_library.cpp to resolve AutoMoc warnings.
- Addressed warning C4267 in configure_web.cpp regarding conversion from 'size_t' to 'int' by ensuring proper type handling.
- Updated build output to reflect successful compilation of additional source files and linking of the executable.

* better steam

* Fix room creation logic by removing unused parameter and add include test file

* Update archived About/Workflow links and apply current tracked changes

* Refactor GMainWindow to support multiple application modes and improve MCP server handling

- Updated OnEmulationStopped to show appropriate environment based on current mode (Gamer, Programmer).
- Removed unnecessary checks in OnGameListShowList for Hacker mode.
- Enhanced ToggleWindowMode to display the correct environment for Gamer and Programmer modes.
- Refactored MCP server initialization to be available in all modes, ensuring correct state reporting for Gamer and Hacker environments.
- Improved handling of game directory addition and listing in MCP server.
- Added HactoolIntegration class for managing external decryption tools, including scanning for tools, extracting NCA, NSP, and XCI files, and detecting extracted content.
- Implemented file and directory existence checks to ensure robust tool management.
- Introduced progress callbacks for extraction operations to provide user feedback.
- Enhanced Vulkan graphics pipeline to improve image handling and resource management.
- Updated texture cache to synchronize aliases only when necessary, optimizing performance.

* Implement random number generation utilities and refactor UUID and network components to use them

* Refactor hactool integration to use pointer for VFS operations and clean up game list header includes

* Add screenshot functionality for 'suyu' application using PowerShell

- Created 'take_screenshot.ps1' to capture a screenshot of the 'suyu' window.
- Utilized user32.dll for window manipulation and System.Drawing for image processing.
- Implemented a delay before capturing the screenshot to ensure the window is fully rendered.

Add UI Automation click functionality for 'suyu' application

- Created 'uia_click.ps1' to find and invoke a button in the 'suyu' window using UI Automation.
- Captured the window's screenshot after attempting to click the button.
- Enumerated all UI elements to provide feedback if the target button is not found.

* Add PowerShell script for UI flow verification and screenshot capture

- Introduced `verify_ui_flows.ps1` to automate the verification of UI flows in the 'suyu' application.
- Utilized UI Automation to interact with application windows and controls.
- Implemented functionality to capture screenshots of the Social view, Multiplayer lobby, and Export dialog.
- Added error handling and logging for invoked controls.

* Add screenshot for public room verification and PowerShell script to set dialog text and click button

- Added a PNG screenshot for verifying public rooms.
- Created a PowerShell script `set_dialog_text_and_click.ps1` to automate setting text in a dialog and clicking a button using Windows API calls.

* fix: update CPU configuration handling for improved compatibility with MSVC

* Add PowerShell script for MCP UI testing and automation

- Implement Send-McpRequest function to handle JSON-RPC requests over TCP.
- Establish TCP connection to the MCP server on localhost at port 9742.
- Send initialization and notification requests to the MCP server.
- Create a series of tool calls to interact with the MCP UI, including setting app mode, navigating views, refreshing feeds, and capturing screenshots.
- Output responses from the MCP server for each request.

* feat: implement real ARM64 AOT basic block analysis in game_export

Replace stub RunAotPrecompile() with real implementation that:
- Opens ROM files via VFS (NSP/XCI/NCA container support)
- Parses NSOHeader structs and decompresses .text segments via LZ4
- Performs two-pass ARM64 linear sweep basic block analysis
- Detects all branch types: B, BL, BR, BLR, RET, CBZ/CBNZ, TBZ/TBNZ, B.cond, SVC
- Extracts direct branch targets for block boundary discovery
- Writes binary .blockmap files (AOTB format) for runtime JIT pre-warming
- Generates JSON manifest v2 with real module data: build IDs, segment
  addresses, block counts, instruction counts
- Falls back to disk-based ExeFS reading when VFS extraction unavailable
- Saves extracted ExeFS content to cache for standalone packaging

This enables the AOT export pipeline to produce real block maps that
the runtime can use to pre-compile ARM64 code blocks on startup instead
of lazily JIT-compiling on first execution.

* feat: replace built-in decryption with external tool hook system

- Add ExternalDecryptionTool class (external_decryption_tool.h/.cpp)
  supporting hactool, Ryujinx, Eden, Yuzu, and custom tools
- QSettings persistence for tool selection and path
- QProcess-based tool invocation with timeout and error handling
- Auto-detect tools on PATH via QStandardPaths::findExecutable
- Full dialog UI with tool picker, path editor, browse, status indicator
- Hide action_Install_Keys in UI, add action_Configure_External_Decryption
- Replace OnInstallDecryptionKeys body to redirect to external tool dialog
- Add OnConfigureExternalDecryption to main.cpp/main.h
- Update game launch warning to mention external tool option
- Soften OnCheckFirmwareDecryption to INFO level
- Update MCP get_keys_status to report external tool configuration
- Disable old DecryptionFlowWidget via #if 0 in decryption_flow.h/.cpp
- Remove decryption_flow from CMakeLists.txt, add external_decryption_tool

* feat: update game export dialog for native export artifacts and improve user manual instructions

* fix: reorder includes in game_export.cpp to resolve macro conflicts

* fix(suyu): resolve C4458/C4005 in game_export.cpp + add mcl include path

- Add explicit #include common/assert.h before #undef guards so #pragma once
  is set before Dynarmic/mcl headers are included (works with or without PCH)
- Rename local var 'data' -> 'nso_bytes' to fix C4458 hiding QWidget::data
- Add externals/dynarmic/externals/mcl/include to suyu target_include_directories
  since merry::mcl is LINK_ONLY in dynarmic's export, so its include path
  does not propagate to consumers like suyu

* feat: add build script for MSVC using subprocess to automate build process

* feat: enhance external decryption tool integration and improve UI feedback for SSL status

* Remove obsolete scripts and logs; add build script for CMake configuration and Ninja build

* conan

* Refactor key management and enhance decryption flow

- Updated KeyManager to support additional key types and improved key loading mechanism.
- Removed legacy key file handling in ReloadKeys and integrated external content pipeline.
- Enhanced LoadFromFile to handle key parsing more robustly.
- Modified DecryptionFlowWidget to reflect changes in key management and provide clearer instructions for external decryption tools.
- Updated main application logic to accommodate external decryption configurations and removed local key installation functionality.
- Added new NAX0 processing functionality to handle encrypted content extraction.
- Introduced new test data files for cryptographic operations.

* fix: improve error logging for ROM loading and enhance key area key validation

* feat: add logging for key presence during key reload

* feat: implement PowerShell fallback for Reddit feed loading in social sidebar

* fix: handle exceptions during disk shader cache loading

* Refactor code structure for improved readability and maintainability

* Add logging functionality and PowerShell script for MCP testing

- Created a new log file 'suyu_combined.log' to capture application logs.
- Implemented a PowerShell script 'test_mcp.ps1' to automate testing of the MCP interface.
- The script initializes the MCP, captures screenshots in different modes, and outputs the results.

* style: update loading screen UI and progress bar aesthetics; enhance error handling in game boot and command line

* fix: add exception handling for emulation thread and game export; improve error reporting

* fix: add exception handling for disk shader cache loading; ensure proper emulation thread management

* fix: add exception handling and logging for time synchronization; implement game list population cancellation

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-04-26 18:38:38 +01:00

174 lines
6.0 KiB
C

#include <string.h>
#include "aes.h"
#include "sha.h"
#include "nax0.h"
static size_t nax0_read(nax0_ctx_t *ctx, uint64_t offset, void *dst, size_t size) {
if (ctx->num_files == 1) {
fseeko64(ctx->files[0], offset, SEEK_SET);
return fread(dst, 1, size, ctx->files[0]);
}
FILE *which = ctx->files[offset / 0xFFFF0000ULL];
uint64_t offset_in_file = offset % 0xFFFF0000ULL;
fseeko64(which, offset_in_file, SEEK_SET);
uint64_t left_in_file = 0xFFFF0000ULL - offset_in_file;
if (size > left_in_file) {
return fread(dst, 1, left_in_file, which) + nax0_read(ctx, offset + left_in_file, (unsigned char *)dst + left_in_file, size - left_in_file);
} else {
return fread(dst, 1, size, which);
}
}
void nax0_process(nax0_ctx_t *ctx) {
/* First things first... */
FILE *f_temp;
if ((f_temp = os_fopen(ctx->base_path.os_path, OS_MODE_READ)) != NULL) {
ctx->num_files = 1;
ctx->files = calloc(1, sizeof(FILE *));
if (ctx->files == NULL) {
fprintf(stderr, "Failed to allocate NAX0 file holder!\n");
exit(EXIT_FAILURE);
}
ctx->files[0] = f_temp;
} else {
ctx->num_files = 0;
filepath_t temp_path;
while (1) {
filepath_copy(&temp_path, &ctx->base_path);
filepath_append(&temp_path, "%02"PRIu32, ctx->num_files);
if ((f_temp = os_fopen(temp_path.os_path, OS_MODE_READ)) == NULL) {
break;
}
ctx->num_files++;
fclose(f_temp);
}
if (ctx->num_files == 0) {
fprintf(stderr, "Input path appears to neither be a NAX0, nor a NAX0 directory!\n");
exit(EXIT_FAILURE);
}
ctx->files = calloc(ctx->num_files, sizeof(FILE *));
if (ctx->files == NULL) {
fprintf(stderr, "Failed to allocate NAX0 file holder!\n");
exit(EXIT_FAILURE);
}
for (unsigned int i = 0; i < ctx->num_files; i++) {
filepath_copy(&temp_path, &ctx->base_path);
filepath_append(&temp_path, "%02"PRIu32, i);
if ((ctx->files[i] = os_fopen(temp_path.os_path, OS_MODE_READ)) == NULL) {
fprintf(stderr, "Failed to open %s!\n", temp_path.char_path);
exit(EXIT_FAILURE);
}
}
}
nax0_read(ctx, 0, &ctx->header, sizeof(ctx->header));
if (ctx->header.magic != MAGIC_NAX0) {
printf("Error: File has invalid NAX0 magic!\n");
return;
}
memcpy(ctx->encrypted_keys, ctx->header.keys, sizeof(ctx->header.keys));
int found = 0;
for (ctx->k = 0; ctx->k < 2; ctx->k++) {
unsigned char nax_specific_keys[2][0x10];
sha256_get_buffer_hmac(nax_specific_keys, ctx->tool_ctx->settings.keyset.sd_card_keys[ctx->k], 0x10, ctx->tool_ctx->settings.nax0_sd_path.char_path, strlen(ctx->tool_ctx->settings.nax0_sd_path.char_path));
for (unsigned int i = 0; i < 2; i++) {
aes_ctx_t *nax_k_ctx = new_aes_ctx(nax_specific_keys[i], 0x10, AES_MODE_ECB);
aes_decrypt(nax_k_ctx, ctx->header.keys[i], ctx->encrypted_keys[i], 0x10);
free_aes_ctx(nax_k_ctx);
}
unsigned char validation_mac[0x20];
sha256_get_buffer_hmac(validation_mac, &ctx->header.magic, 0x60, ctx->tool_ctx->settings.keyset.sd_card_keys[ctx->k] + 0x10, 0x10);
if (memcmp(ctx->header.hmac_header, validation_mac, 0x20) == 0) {
found = 1;
break;
}
}
if (!found) {
printf("Error: NAX0 key derivation failed. Check SD card seed and relative path?\n");
return;
}
ctx->aes_ctx = new_aes_ctx(ctx->header.keys, 0x20, AES_MODE_XTS);
if (ctx->tool_ctx->action & ACTION_INFO) {
nax0_print(ctx);
}
if (ctx->tool_ctx->action & ACTION_EXTRACT) {
nax0_save(ctx);
}
}
void nax0_save(nax0_ctx_t *ctx) {
/* Save Decrypted Contents. */
filepath_t *dec_path = &ctx->tool_ctx->settings.plaintext_path;
if (dec_path->valid != VALIDITY_VALID) {
return;
}
printf("Saving Decrypted NAX0 Content to %s...\n", dec_path->char_path);
FILE *f_dec = os_fopen(dec_path->os_path, OS_MODE_WRITE);
if (f_dec == NULL) {
fprintf(stderr, "Failed to open %s!\n", dec_path->char_path);
return;
}
uint64_t ofs = 0x4000;
uint64_t end_ofs = ofs + ctx->header.size;
unsigned char *buf = malloc(0x400000);
if (buf == NULL) {
fprintf(stderr, "Failed to allocate file-save buffer!\n");
exit(EXIT_FAILURE);
}
uint64_t read_size = 0x400000; /* 4 MB buffer. */
memset(buf, 0xCC, read_size); /* Debug in case I fuck this up somehow... */
while (ofs < end_ofs) {
if (ofs + read_size >= end_ofs) read_size = end_ofs - ofs;
if (nax0_read(ctx, ofs, buf, read_size) != read_size) {
fprintf(stderr, "Failed to read file!\n");
exit(EXIT_FAILURE);
}
uint64_t dec_size = (read_size + 0x3FFF) & ~0x3FFF;
aes_xts_decrypt(ctx->aes_ctx, buf, buf, dec_size, (ofs - 0x4000) >> 14, 0x4000);
if (fwrite(buf, 1, read_size, f_dec) != read_size) {
fprintf(stderr, "Failed to write file!\n");
exit(EXIT_FAILURE);
}
ofs += read_size;
}
fclose(f_dec);
free(buf);
}
static const char *nax0_get_key_summary(unsigned int k) {
switch (k) {
case 0:
return "Save";
case 1:
return "NCA";
default:
return "Unknown";
}
}
void nax0_print(nax0_ctx_t *ctx) {
printf("\nNAX0:\n");
print_magic(" Magic: ", ctx->header.magic);
printf(" Content Type: %s\n", nax0_get_key_summary(ctx->k));
printf(" Content Size: %012"PRIx64"\n", ctx->header.size);
memdump(stdout, " Header HMAC: ", ctx->header.hmac_header, 0x20);
memdump(stdout, " Encrypted Keys: ", ctx->encrypted_keys, 0x20);
memdump(stdout, " Decrypted Keys: ", ctx->header.keys, 0x20);
}