mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-06-10 18:21:11 +00:00
Complete iOS IPA packaging flow
This commit is contained in:
parent
4f9e6cf2ff
commit
ed6cd3cdab
13 changed files with 295 additions and 23 deletions
|
|
@ -177,6 +177,8 @@
|
|||
"CMAKE_OSX_SYSROOT": "iphonesimulator",
|
||||
"CMAKE_OSX_ARCHITECTURES": "arm64",
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"UNLEASHED_RECOMP_SKIP_TARGET_TOOL_EXECUTABLES": true,
|
||||
"UNLEASHED_RECOMP_HOST_TOOLS_DIR": "${sourceDir}/out/build/macos-release",
|
||||
"CMAKE_TOOLCHAIN_FILE": {
|
||||
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"type": "FILEPATH"
|
||||
|
|
@ -207,6 +209,8 @@
|
|||
"CMAKE_OSX_ARCHITECTURES": "arm64",
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true,
|
||||
"UNLEASHED_RECOMP_SKIP_TARGET_TOOL_EXECUTABLES": true,
|
||||
"UNLEASHED_RECOMP_HOST_TOOLS_DIR": "${sourceDir}/out/build/macos-release",
|
||||
"CMAKE_TOOLCHAIN_FILE": {
|
||||
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"type": "FILEPATH"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,18 @@
|
|||
project("UnleashedRecomp")
|
||||
project("UnleashedRecomp")
|
||||
|
||||
set(UNLEASHED_RECOMP_HOST_TOOLS_DIR "" CACHE PATH "Directory containing host-built recompilation tools.")
|
||||
|
||||
function(unleashed_recomp_resolve_tool OUT_VAR TARGET_NAME RELATIVE_PATH)
|
||||
if (UNLEASHED_RECOMP_HOST_TOOLS_DIR)
|
||||
set(${OUT_VAR} "${UNLEASHED_RECOMP_HOST_TOOLS_DIR}/${RELATIVE_PATH}" PARENT_SCOPE)
|
||||
elseif (TARGET ${TARGET_NAME})
|
||||
set(${OUT_VAR} "$<TARGET_FILE:${TARGET_NAME}>" PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Tool ${TARGET_NAME} is not available. Set UNLEASHED_RECOMP_HOST_TOOLS_DIR.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
unleashed_recomp_resolve_tool(UNLEASHED_RECOMP_FILE_TO_C_TOOL file_to_c "tools/file_to_c/file_to_c")
|
||||
|
||||
if (WIN32)
|
||||
option(UNLEASHED_RECOMP_D3D12 "Add D3D12 support for rendering" ON)
|
||||
|
|
@ -27,8 +41,8 @@ function(BIN2C)
|
|||
set(BIN2C_ARGS_COMPRESSION_TYPE "none")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
|
||||
COMMAND $<TARGET_FILE:file_to_c> "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_COMPRESSION_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
|
||||
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
|
||||
COMMAND "${UNLEASHED_RECOMP_FILE_TO_C_TOOL}" "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_COMPRESSION_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
|
||||
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}"
|
||||
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
|
||||
COMMENT "Generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
|
||||
|
|
|
|||
|
|
@ -166,9 +166,11 @@ void UpdateChecker::visitWebsite()
|
|||
#elif defined(__linux__)
|
||||
std::string command = "xdg-open " + std::string(VISIT_URL) + " &";
|
||||
std::system(command.c_str());
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) && !defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
|
||||
std::string command = "open " + std::string(VISIT_URL) + " &";
|
||||
std::system(command.c_str());
|
||||
#elif defined(__APPLE__)
|
||||
// iOS apps cannot spawn external commands; leave website navigation to platform UI.
|
||||
#else
|
||||
static_assert(false, "Visit website not implemented for this platform.");
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@
|
|||
#include "xcontent_file_system.h"
|
||||
|
||||
#include <bit>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <xbox.h>
|
||||
|
||||
enum class XContentPackageType
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,9 +10,27 @@ else()
|
|||
add_compile_options(-ffp-model=strict)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(XenonRecomp PRIVATE
|
||||
XENON_RECOMP_CONFIG_FILE_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml\"
|
||||
XENON_RECOMP_HEADER_FILE_PATH=\"${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/XenonUtils/ppc_context.h\")
|
||||
set(UNLEASHED_RECOMP_HOST_TOOLS_DIR "" CACHE PATH "Directory containing host-built recompilation tools.")
|
||||
|
||||
function(unleashed_recomp_resolve_tool OUT_VAR TARGET_NAME RELATIVE_PATH)
|
||||
if (UNLEASHED_RECOMP_HOST_TOOLS_DIR)
|
||||
set(${OUT_VAR} "${UNLEASHED_RECOMP_HOST_TOOLS_DIR}/${RELATIVE_PATH}" PARENT_SCOPE)
|
||||
elseif (TARGET ${TARGET_NAME})
|
||||
set(${OUT_VAR} "$<TARGET_FILE:${TARGET_NAME}>" PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Tool ${TARGET_NAME} is not available. Set UNLEASHED_RECOMP_HOST_TOOLS_DIR.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
unleashed_recomp_resolve_tool(UNLEASHED_RECOMP_XENON_RECOMP_TOOL XenonRecomp "tools/XenonRecomp/XenonRecomp/XenonRecomp")
|
||||
unleashed_recomp_resolve_tool(UNLEASHED_RECOMP_X_DECOMPRESS_TOOL x_decompress "tools/x_decompress/x_decompress")
|
||||
unleashed_recomp_resolve_tool(UNLEASHED_RECOMP_XENOS_RECOMP_TOOL XenosRecomp "tools/XenosRecomp/XenosRecomp/XenosRecomp")
|
||||
|
||||
if (TARGET XenonRecomp)
|
||||
target_compile_definitions(XenonRecomp PRIVATE
|
||||
XENON_RECOMP_CONFIG_FILE_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml\"
|
||||
XENON_RECOMP_HEADER_FILE_PATH=\"${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/XenonUtils/ppc_context.h\")
|
||||
endif()
|
||||
|
||||
set(UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ppc/ppc_config.h"
|
||||
|
|
@ -30,7 +48,7 @@ add_custom_command(
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/private/default_patched.xex"
|
||||
${UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES}
|
||||
COMMAND
|
||||
$<TARGET_FILE:XenonRecomp>
|
||||
"${UNLEASHED_RECOMP_XENON_RECOMP_TOOL}"
|
||||
DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/private/default.xex"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/private/default.xexp"
|
||||
|
|
@ -42,7 +60,7 @@ add_custom_command(
|
|||
OUTPUT
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
|
||||
COMMAND
|
||||
$<TARGET_FILE:x_decompress> "${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar" "${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
|
||||
"${UNLEASHED_RECOMP_X_DECOMPRESS_TOOL}" "${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar" "${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
|
||||
DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar"
|
||||
)
|
||||
|
|
@ -50,12 +68,14 @@ add_custom_command(
|
|||
set(XENOS_RECOMP_ROOT "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/XenosRecomp")
|
||||
set(XENOS_RECOMP_INCLUDE "${XENOS_RECOMP_ROOT}/shader_common.h")
|
||||
|
||||
target_compile_definitions(XenosRecomp PRIVATE
|
||||
XENOS_RECOMP_INPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/private\"
|
||||
XENOS_RECOMP_OUTPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp\"
|
||||
XENOS_RECOMP_INCLUDE_INPUT=\"${XENOS_RECOMP_INCLUDE}\"
|
||||
UNLEASHED_RECOMP
|
||||
)
|
||||
if (TARGET XenosRecomp)
|
||||
target_compile_definitions(XenosRecomp PRIVATE
|
||||
XENOS_RECOMP_INPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/private\"
|
||||
XENOS_RECOMP_OUTPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp\"
|
||||
XENOS_RECOMP_INCLUDE_INPUT=\"${XENOS_RECOMP_INCLUDE}\"
|
||||
UNLEASHED_RECOMP
|
||||
)
|
||||
endif()
|
||||
|
||||
file(GLOB XENOS_RECOMP_SOURCES
|
||||
"${XENOS_RECOMP_ROOT}/*.h"
|
||||
|
|
@ -66,7 +86,7 @@ add_custom_command(
|
|||
OUTPUT
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp"
|
||||
COMMAND
|
||||
$<TARGET_FILE:XenosRecomp>
|
||||
"${UNLEASHED_RECOMP_XENOS_RECOMP_TOOL}"
|
||||
DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/private/default_patched.xex"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
|
||||
|
|
|
|||
3
thirdparty/nfd_ios_stub.c
vendored
3
thirdparty/nfd_ios_stub.c
vendored
|
|
@ -6,6 +6,7 @@ static const char* g_nfd_ios_error = "Native file dialogs are not implemented fo
|
|||
nfdresult_t NFD_Init(void) { return NFD_OKAY; }
|
||||
void NFD_Quit(void) {}
|
||||
const char* NFD_GetError(void) { return g_nfd_ios_error; }
|
||||
void NFD_ClearError(void) {}
|
||||
|
||||
void NFD_FreePathN(nfdnchar_t* filePath) { free(filePath); }
|
||||
void NFD_FreePathU8(nfdu8char_t* filePath) { free(filePath); }
|
||||
|
|
@ -37,6 +38,6 @@ void NFD_PathSet_FreePathN(const nfdnchar_t* filePath) { free((void*)filePath);
|
|||
void NFD_PathSet_FreePathU8(const nfdu8char_t* filePath) { free((void*)filePath); }
|
||||
void NFD_PathSet_Free(const nfdpathset_t* pathSet) { (void)pathSet; }
|
||||
void NFD_PathSet_FreeEnum(nfdpathsetenum_t* enumerator) { (void)enumerator; }
|
||||
nfdresult_t NFD_PathSet_GetEnum(const nfdpathset_t* pathSet, nfdpathsetenum_t** outEnumerator) { (void)pathSet; (void)outEnumerator; return NFD_ERROR; }
|
||||
nfdresult_t NFD_PathSet_GetEnum(const nfdpathset_t* pathSet, nfdpathsetenum_t* outEnumerator) { (void)pathSet; (void)outEnumerator; return NFD_ERROR; }
|
||||
nfdresult_t NFD_PathSet_EnumNextN(nfdpathsetenum_t* enumerator, nfdnchar_t** outPath) { (void)enumerator; (void)outPath; return NFD_ERROR; }
|
||||
nfdresult_t NFD_PathSet_EnumNextU8(nfdpathsetenum_t* enumerator, nfdu8char_t** outPath) { (void)enumerator; (void)outPath; return NFD_ERROR; }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,20 @@
|
|||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/bc_diff)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/file_to_c)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/fshasher)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/x_decompress)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp)
|
||||
if (NOT UNLEASHED_RECOMP_SKIP_TARGET_TOOL_EXECUTABLES)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/file_to_c)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/x_decompress)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp)
|
||||
else()
|
||||
set(THIRDPARTY_ROOT ${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/thirdparty)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/thirdparty)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/XenonUtils)
|
||||
|
||||
if (NOT TARGET libzstd)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/thirdparty/zstd/build/cmake)
|
||||
endif()
|
||||
endif()
|
||||
if (NOT UNLEASHED_RECOMP_SKIP_TARGET_TOOL_EXECUTABLES)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/iso_extract)
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/xcontent_extract)
|
||||
endif()
|
||||
|
|
|
|||
13
tools/iso_extract/CMakeLists.txt
Normal file
13
tools/iso_extract/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
project("iso_extract")
|
||||
|
||||
add_executable(iso_extract
|
||||
"iso_extract.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/UnleashedRecomp/install/iso_file_system.cpp"
|
||||
)
|
||||
|
||||
target_include_directories(iso_extract PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}/UnleashedRecomp/install"
|
||||
"${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/XenonUtils"
|
||||
)
|
||||
|
||||
target_link_libraries(iso_extract PRIVATE XenonUtils)
|
||||
74
tools/iso_extract/iso_extract.cpp
Normal file
74
tools/iso_extract/iso_extract.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <iso_file_system.h>
|
||||
|
||||
static bool ExtractFile(const ISOFileSystem& iso, const std::string& sourcePath, const std::filesystem::path& outputPath)
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
size_t dataSize = iso.getSize(sourcePath);
|
||||
if (dataSize == 0)
|
||||
{
|
||||
std::cerr << "File not found in ISO: " << sourcePath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
data.resize(dataSize);
|
||||
if (!iso.load(sourcePath, data.data(), data.size()))
|
||||
{
|
||||
std::cerr << "File not found in ISO: " << sourcePath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(outputPath.parent_path(), ec);
|
||||
if (ec)
|
||||
{
|
||||
std::cerr << "Failed to create output directory: " << outputPath.parent_path() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ofstream output(outputPath, std::ios::binary);
|
||||
if (!output)
|
||||
{
|
||||
std::cerr << "Failed to open output file: " << outputPath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
output.write(reinterpret_cast<const char*>(data.data()), static_cast<std::streamsize>(data.size()));
|
||||
if (!output)
|
||||
{
|
||||
std::cerr << "Failed to write output file: " << outputPath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 4 || ((argc - 2) % 2) != 0)
|
||||
{
|
||||
std::cerr << "Usage: iso_extract <game.iso> <iso-path> <output-path> [<iso-path> <output-path> ...]\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
auto iso = ISOFileSystem::create(argv[1]);
|
||||
if (!iso)
|
||||
{
|
||||
std::cerr << "Failed to open Xbox 360 ISO: " << argv[1] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
for (int i = 2; i < argc; i += 2)
|
||||
{
|
||||
ok = ExtractFile(*iso, argv[i], argv[i + 1]) && ok;
|
||||
}
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
|
@ -3,14 +3,35 @@ set -euo pipefail
|
|||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
BUILD_DIR="$ROOT/out/build/ios-device-release"
|
||||
HOST_BUILD_DIR="$ROOT/out/build/macos-release"
|
||||
IPA_DIR="$ROOT/out/ipa"
|
||||
PAYLOAD_DIR="$IPA_DIR/Payload"
|
||||
APP_PATH="$BUILD_DIR/Unleashed Recompiled.app"
|
||||
APP_PATH="$BUILD_DIR/UnleashedRecomp/Unleashed Recompiled.app"
|
||||
IPA_PATH="$IPA_DIR/UnleashedRecompiled.ipa"
|
||||
DEFAULT_SIGNING_IDENTITY="Apple Development: aroblesalago@gmail.com (MK28YRUCCG)"
|
||||
|
||||
"$ROOT/tools/apply_ios_submodule_patches.sh"
|
||||
|
||||
if [[ -n "${ISO_PATH:-}" ]]; then
|
||||
cmake --preset macos-release
|
||||
cmake --build "$HOST_BUILD_DIR" --target iso_extract -j "${JOBS:-8}"
|
||||
"$HOST_BUILD_DIR/tools/iso_extract/iso_extract" "$ISO_PATH" \
|
||||
default.xex "$ROOT/UnleashedRecompLib/private/default.xex" \
|
||||
shader.ar "$ROOT/UnleashedRecompLib/private/shader.ar"
|
||||
fi
|
||||
|
||||
if [[ -n "${XEXP_PATH:-}" ]]; then
|
||||
mkdir -p "$ROOT/UnleashedRecompLib/private"
|
||||
cp "$XEXP_PATH" "$ROOT/UnleashedRecompLib/private/default.xexp"
|
||||
fi
|
||||
|
||||
if [[ -n "${UPDATE_PATH:-}" ]]; then
|
||||
cmake --preset macos-release
|
||||
cmake --build "$HOST_BUILD_DIR" --target xcontent_extract -j "${JOBS:-8}"
|
||||
"$HOST_BUILD_DIR/tools/xcontent_extract/xcontent_extract" "$UPDATE_PATH" \
|
||||
default.xexp "$ROOT/UnleashedRecompLib/private/default.xexp"
|
||||
fi
|
||||
|
||||
missing=0
|
||||
for file in \
|
||||
"$ROOT/UnleashedRecompLib/private/default.xex" \
|
||||
|
|
@ -27,6 +48,9 @@ if [[ "$missing" -ne 0 ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
cmake --preset macos-release
|
||||
cmake --build "$HOST_BUILD_DIR" --target XenonRecomp XenosRecomp x_decompress file_to_c -j "${JOBS:-8}"
|
||||
|
||||
cmake --preset ios-device-release
|
||||
cmake --build "$BUILD_DIR" --target UnleashedRecomp -j "${JOBS:-8}"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 6a7645a..bf336b9 100644
|
||||
index 6a7645a..6e6e887 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -8,10 +8,16 @@ if(APPLE)
|
||||
|
|
@ -20,6 +20,24 @@ index 6a7645a..bf336b9 100644
|
|||
cmake_dependent_option(D3D12_AGILITY_SDK_ENABLED "Enable D3D12 Agility SDK" OFF WIN32 OFF)
|
||||
option(PLUME_BUILD_EXAMPLES "Build example applications" OFF)
|
||||
|
||||
@@ -50,7 +56,7 @@ set(PLUME_SOURCES
|
||||
)
|
||||
|
||||
# Platform-specific files
|
||||
-if(APPLE)
|
||||
+if(APPLE AND NOT IS_IOS)
|
||||
list(APPEND PLUME_SOURCES
|
||||
plume_metal.cpp
|
||||
plume_metal.h
|
||||
@@ -94,7 +100,7 @@ if(D3D12_AGILITY_SDK_ENABLED)
|
||||
endif()
|
||||
|
||||
# Platform-specific includes
|
||||
-if(APPLE)
|
||||
+if(APPLE AND NOT IS_IOS)
|
||||
target_include_directories(plume PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/metal-cpp
|
||||
)
|
||||
diff --git a/plume_vulkan.cpp b/plume_vulkan.cpp
|
||||
index 9103ca8..02c3591 100644
|
||||
--- a/plume_vulkan.cpp
|
||||
|
|
|
|||
13
tools/xcontent_extract/CMakeLists.txt
Normal file
13
tools/xcontent_extract/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
project("xcontent_extract")
|
||||
|
||||
add_executable(xcontent_extract
|
||||
"xcontent_extract.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/UnleashedRecomp/install/xcontent_file_system.cpp"
|
||||
)
|
||||
|
||||
target_include_directories(xcontent_extract PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}/UnleashedRecomp/install"
|
||||
"${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/XenonUtils"
|
||||
)
|
||||
|
||||
target_link_libraries(xcontent_extract PRIVATE XenonUtils)
|
||||
73
tools/xcontent_extract/xcontent_extract.cpp
Normal file
73
tools/xcontent_extract/xcontent_extract.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <xcontent_file_system.h>
|
||||
|
||||
static bool ExtractFile(const XContentFileSystem& content, const std::string& sourcePath, const std::filesystem::path& outputPath)
|
||||
{
|
||||
size_t dataSize = content.getSize(sourcePath);
|
||||
if (dataSize == 0)
|
||||
{
|
||||
std::cerr << "File not found in XContent package: " << sourcePath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data(dataSize);
|
||||
if (!content.load(sourcePath, data.data(), data.size()))
|
||||
{
|
||||
std::cerr << "Failed to read XContent file: " << sourcePath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(outputPath.parent_path(), ec);
|
||||
if (ec)
|
||||
{
|
||||
std::cerr << "Failed to create output directory: " << outputPath.parent_path() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ofstream output(outputPath, std::ios::binary);
|
||||
if (!output)
|
||||
{
|
||||
std::cerr << "Failed to open output file: " << outputPath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
output.write(reinterpret_cast<const char*>(data.data()), static_cast<std::streamsize>(data.size()));
|
||||
if (!output)
|
||||
{
|
||||
std::cerr << "Failed to write output file: " << outputPath << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 4 || ((argc - 2) % 2) != 0)
|
||||
{
|
||||
std::cerr << "Usage: xcontent_extract <package> <package-path> <output-path> [<package-path> <output-path> ...]\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
auto content = XContentFileSystem::create(argv[1]);
|
||||
if (!content)
|
||||
{
|
||||
std::cerr << "Failed to open XContent package: " << argv[1] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
for (int i = 2; i < argc; i += 2)
|
||||
{
|
||||
ok = ExtractFile(*content, argv[i], argv[i + 1]) && ok;
|
||||
}
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue