mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 04:41:39 +00:00
Implement ZSTD compression in file_to_c.
This commit is contained in:
parent
1a794ef9ee
commit
0a588949a7
7 changed files with 70 additions and 20 deletions
|
|
@ -4,7 +4,7 @@ set(TARGET_NAME "SWA")
|
|||
option(SWA_XAUDIO2 "Use XAudio2 for audio playback" OFF)
|
||||
|
||||
function(BIN2C)
|
||||
cmake_parse_arguments(BIN2C_ARGS "" "TARGET_OBJ;SOURCE_FILE;DEST_FILE;ARRAY_TYPE;ARRAY_NAME" "" ${ARGN})
|
||||
cmake_parse_arguments(BIN2C_ARGS "" "TARGET_OBJ;SOURCE_FILE;DEST_FILE;ARRAY_NAME;COMPRESSION_TYPE" "" ${ARGN})
|
||||
|
||||
if(NOT BIN2C_ARGS_TARGET_OBJ)
|
||||
message(FATAL_ERROR "TARGET_OBJ not specified.")
|
||||
|
|
@ -18,8 +18,12 @@ function(BIN2C)
|
|||
set(BIN2C_ARGS_DEST_FILE "${BIN2C_ARGS_SOURCE_FILE}")
|
||||
endif()
|
||||
|
||||
if(NOT BIN2C_ARGS_COMPRESSION_TYPE)
|
||||
set(BIN2C_ARGS_COMPRESSION_TYPE "none")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
|
||||
COMMAND file_to_c "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_ARRAY_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
|
||||
COMMAND 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"
|
||||
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}" file_to_c
|
||||
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
|
||||
COMMENT "Generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
|
||||
|
|
@ -313,9 +317,9 @@ generate_aggregate_header(
|
|||
set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources")
|
||||
set(RESOURCES_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/res")
|
||||
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/achievements_menu/trophy.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/achievements_menu/trophy.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_trophy")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/general_window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/general_window.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_general_window")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fade.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fade.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_select_fade")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fill.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_select_fill")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon.bmp" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_game_icon")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_game_icon_night")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/achievements_menu/trophy.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/achievements_menu/trophy.dds" ARRAY_NAME "g_trophy" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/general_window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/general_window.dds" ARRAY_NAME "g_general_window" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fade.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fade.dds" ARRAY_NAME "g_select_fade" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fill.dds" ARRAY_NAME "g_select_fill" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon.bmp" ARRAY_NAME "g_game_icon")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_NAME "g_game_icon_night")
|
||||
|
|
|
|||
9
UnleashedRecomp/decompressor.h
Normal file
9
UnleashedRecomp/decompressor.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
template<size_t N>
|
||||
static std::unique_ptr<uint8_t[]> decompressZstd(const uint8_t(&data)[N], size_t decompressedSize)
|
||||
{
|
||||
auto decompressedData = std::make_unique<uint8_t[]>(decompressedSize);
|
||||
ZSTD_decompress(decompressedData.get(), decompressedSize, data, N);
|
||||
return decompressedData;
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
#include <user/config.h>
|
||||
#include <app.h>
|
||||
#include <exports.h>
|
||||
#include <decompressor.h>
|
||||
#include <res/images/achievements_menu/trophy.dds.h>
|
||||
#include <res/images/common/general_window.dds.h>
|
||||
#include <res/images/common/select_fill.dds.h>
|
||||
|
|
@ -624,9 +625,9 @@ void AchievementMenu::Init()
|
|||
g_fntNewRodinDB = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
||||
g_fntNewRodinUB = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-UB.otf", 20.0f * FONT_SCALE);
|
||||
|
||||
g_upTrophyIcon = LoadTexture(g_trophy, sizeof(g_trophy));
|
||||
g_upSelectionCursor = LoadTexture(g_select_fill, sizeof(g_select_fill));
|
||||
g_upWindow = LoadTexture(g_general_window, sizeof(g_general_window));
|
||||
g_upTrophyIcon = LoadTexture(decompressZstd(g_trophy, g_trophy_uncompressed_size).get(), g_trophy_uncompressed_size);
|
||||
g_upSelectionCursor = LoadTexture(decompressZstd(g_select_fill, g_select_fill_uncompressed_size).get(), g_select_fill_uncompressed_size);
|
||||
g_upWindow = LoadTexture(decompressZstd(g_general_window, g_general_window_uncompressed_size).get(), g_general_window_uncompressed_size);
|
||||
}
|
||||
|
||||
void AchievementMenu::Draw()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <user/achievement_data.h>
|
||||
#include <app.h>
|
||||
#include <exports.h>
|
||||
#include <decompressor.h>
|
||||
#include <res/images/common/general_window.dds.h>
|
||||
|
||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
||||
|
|
@ -78,7 +79,7 @@ void AchievementOverlay::Init()
|
|||
|
||||
g_fntSeurat = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||
|
||||
g_upWindow = LoadTexture(g_general_window, sizeof(g_general_window));
|
||||
g_upWindow = LoadTexture(decompressZstd(g_general_window, g_general_window_uncompressed_size).get(), g_general_window_uncompressed_size);
|
||||
}
|
||||
|
||||
void AchievementOverlay::Draw()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <api/SWA.h>
|
||||
#include <gpu/video.h>
|
||||
#include <exports.h>
|
||||
#include <decompressor.h>
|
||||
#include <res/images/common/select_fade.dds.h>
|
||||
|
||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
||||
|
|
@ -176,7 +177,7 @@ void MessageWindow::Init()
|
|||
|
||||
g_fntSeurat = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 28.0f * FONT_SCALE);
|
||||
|
||||
g_upSelectionCursor = LoadTexture(g_select_fade, sizeof(g_select_fade));
|
||||
g_upSelectionCursor = LoadTexture(decompressZstd(g_select_fade, g_select_fade_uncompressed_size).get(), g_select_fade_uncompressed_size);
|
||||
}
|
||||
|
||||
void MessageWindow::Draw()
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@ project("file_to_c")
|
|||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_executable(file_to_c "file_to_c.cpp")
|
||||
|
||||
find_package(zstd CONFIG REQUIRED)
|
||||
target_link_libraries(file_to_c PRIVATE $<IF:$<TARGET_EXISTS:zstd::libzstd_static>,zstd::libzstd_static,zstd::libzstd>)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <zstd.h>
|
||||
|
||||
std::vector<char> read_file(const char* path) {
|
||||
std::ifstream input_file{path, std::ios::binary};
|
||||
|
|
@ -55,13 +56,13 @@ void create_parent_if_needed(const char* path) {
|
|||
|
||||
int main(int argc, const char** argv) {
|
||||
if (argc != 6) {
|
||||
printf("Usage: %s [input file] [array name] [array type] [output C file] [output C header]\n", argv[0]);
|
||||
printf("Usage: %s [input file] [array name] [compression type] [output C file] [output C header]\n", argv[0]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
const char* input_path = argv[1];
|
||||
const char* array_name = argv[2];
|
||||
const char* array_type = argv[3];
|
||||
std::string compression_type = argv[3];
|
||||
const char* output_c_path = argv[4];
|
||||
const char* output_h_path = argv[5];
|
||||
|
||||
|
|
@ -73,21 +74,44 @@ int main(int argc, const char** argv) {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Compress if requested.
|
||||
std::vector<char> compressed_contents;
|
||||
std::transform(compression_type.begin(), compression_type.end(), compression_type.begin(), tolower);
|
||||
|
||||
if (compression_type == "zstd") {
|
||||
size_t bound_size = ZSTD_compressBound(contents.size());
|
||||
compressed_contents.resize(bound_size);
|
||||
|
||||
size_t compressed_size = ZSTD_compress(compressed_contents.data(), bound_size, contents.data(), contents.size(), ZSTD_maxCLevel());
|
||||
compressed_contents.resize(compressed_size);
|
||||
}
|
||||
else if (compression_type != "none") {
|
||||
fprintf(stderr, "Unknown compression type %s!", compression_type.c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Create the output directories if they don't exist
|
||||
create_parent_if_needed(output_c_path);
|
||||
create_parent_if_needed(output_h_path);
|
||||
|
||||
// Write the C file with the array
|
||||
std::vector<char>& contents_to_write = !compressed_contents.empty() ? compressed_contents : contents;
|
||||
{
|
||||
std::ofstream output_c_file{output_c_path};
|
||||
output_c_file << "extern " << array_type << " " << array_name << "[" << contents.size() << "];\n";
|
||||
output_c_file << array_type << " " << array_name << "[" << contents.size() << "] = {";
|
||||
output_c_file << "extern unsigned char " << array_name << "[" << contents_to_write.size() << "];\n";
|
||||
output_c_file << "unsigned char " << array_name << "[" << contents_to_write.size() << "] = {";
|
||||
|
||||
for (char x : contents) {
|
||||
output_c_file << (int)x << ", ";
|
||||
for (char x : contents_to_write) {
|
||||
output_c_file << (int)(unsigned char)x << ", ";
|
||||
}
|
||||
|
||||
output_c_file << "};\n";
|
||||
|
||||
// Write decompressed size.
|
||||
if (!compressed_contents.empty()) {
|
||||
output_c_file << "extern size_t " << array_name << "_uncompressed_size;\n";
|
||||
output_c_file << "size_t " << array_name << "_uncompressed_size = " << contents.size() << ";\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Write the header file with the extern array
|
||||
|
|
@ -97,7 +121,14 @@ int main(int argc, const char** argv) {
|
|||
"#ifdef __cplusplus\n"
|
||||
" extern \"C\" {\n"
|
||||
"#endif\n"
|
||||
"extern " << array_type << " " << array_name << "[" << contents.size() << "];\n"
|
||||
"extern unsigned char " << array_name << "[" << contents_to_write.size() << "];\n";
|
||||
|
||||
// Write decompressed size.
|
||||
if (!compressed_contents.empty()) {
|
||||
output_h_file << "extern size_t " << array_name << "_uncompressed_size;\n";
|
||||
}
|
||||
|
||||
output_h_file <<
|
||||
"#ifdef __cplusplus\n"
|
||||
" }\n"
|
||||
"#endif\n";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue