rtengine/src/runtime/asset_loading.c
2024-01-16 16:10:56 +01:00

74 lines
2.3 KiB
C

#include "assets.h"
#include "uidtab.h"
#include "aio.h"
#include "buffer_manager.h"
#define RT_DEFINE_PACKAGE_FILE_STRUCTURES
#include "packages.h"
#include "lz4/lz4.h"
rt_result DecompressAsset(void *compressed_buffer,
size_t compressed_buffer_size,
void **p_decompressed,
size_t *p_decompressed_size) {
const rt_package_asset_header *header = compressed_buffer;
size_t compressed_size = (compressed_buffer_size) - sizeof(*header);
XXH64_hash_t calculated_hash = XXH3_64bits((header + 1), compressed_size);
XXH64_hash_t file_hash = XXH64_hashFromCanonical(&header->checksum);
if (calculated_hash != file_hash) {
rtLog("core", "Checksum mismatch for asset");
return RT_LOAD_FAILED;
}
size_t size = (size_t)header->decompressed_size;
void *decompressed_buffer = rtAllocBuffer(size);
if (!decompressed_buffer) {
return RT_BUFFER_ALLOC_FAILED;
}
if (LZ4_decompress_safe((const char *)(header + 1),
(char *)decompressed_buffer,
(int)compressed_size,
(int)size) < 0) {
return RT_UNKNOWN_ERROR;
}
*p_decompressed = decompressed_buffer;
*p_decompressed_size = size;
return RT_SUCCESS;
}
RT_DLLEXPORT rt_result rtLoadAssetDirect(rt_uid uid, void **p_buffer, size_t *p_size) {
const rt_uid_data *data = rtGetUIDData(uid);
if (!data)
return RT_UNKNOWN_ASSET;
void *compressed_buffer = rtAllocBuffer(data->size);
if (!compressed_buffer) {
return RT_BUFFER_ALLOC_FAILED;
}
if (rtSubmitSingleLoadSync((rt_file_load) {
.file = data->pkg_file,
.offset = data->offset,
.num_bytes = data->size,
.dest = compressed_buffer,
}) != RT_AIO_STATE_FINISHED) {
rtReleaseBuffer(compressed_buffer, data->size);
return RT_LOAD_FAILED;
}
void *decompressed_buffer;
size_t decompressed_size;
rt_result res = DecompressAsset(compressed_buffer, data->size, &decompressed_buffer, &decompressed_size);
rtReleaseBuffer(compressed_buffer, data->size);
*p_buffer = decompressed_buffer;
*p_size = decompressed_size;
return res;
}