Integrate ZSTD decompression to load level
parent
3ab442169a
commit
044a5831ff
|
@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 3.22.1)
|
||||||
project(${PROJECT_NAME} C)
|
project(${PROJECT_NAME} C)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
set(RAYLIB_DIR /usr/local/lib CACHE FILEPATH "directory to Raylib")
|
set(RAYLIB_DIR /usr/local/lib CACHE FILEPATH "directory to Raylib")
|
||||||
|
set(LIBZSTD_DIR /usr/local/lib CACHE FILEPATH "directory to zstd")
|
||||||
|
|
||||||
if (EMSCRIPTEN)
|
if (EMSCRIPTEN)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY")
|
||||||
|
|
|
@ -97,7 +97,8 @@ bool load_from_infofile(const char* file, Assets_t* assets)
|
||||||
break;
|
break;
|
||||||
case LEVELPACK_INFO:
|
case LEVELPACK_INFO:
|
||||||
{
|
{
|
||||||
if (add_level_pack(assets, name, info_str) == NULL)
|
//if (add_level_pack(assets, name, info_str) == NULL)
|
||||||
|
if (uncompress_level_pack(assets, name, info_str) == NULL)
|
||||||
{
|
{
|
||||||
printf("Unable to add level pack at line %lu\n", line_num);
|
printf("Unable to add level pack at line %lu\n", line_num);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5,12 +5,16 @@ add_library(lib_engine STATIC
|
||||||
gui.c
|
gui.c
|
||||||
engine.c
|
engine.c
|
||||||
collisions.c
|
collisions.c
|
||||||
|
${LIBZSTD_DIR}/lib/libzstd.a
|
||||||
)
|
)
|
||||||
target_include_directories(lib_engine
|
target_include_directories(lib_engine
|
||||||
|
PRIVATE
|
||||||
|
${LIBZSTD_DIR}/include
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(lib_engine
|
target_link_libraries(lib_engine
|
||||||
PUBLIC
|
PUBLIC
|
||||||
lib_EC
|
lib_EC
|
||||||
|
zstd
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "assets.h"
|
#include "assets.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
|
#include "zstd.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define MAX_TEXTURES 16
|
#define MAX_TEXTURES 16
|
||||||
|
@ -45,6 +46,15 @@ static SoundData_t sfx[MAX_SOUNDS];
|
||||||
static SpriteData_t sprites[MAX_SPRITES];
|
static SpriteData_t sprites[MAX_SPRITES];
|
||||||
static LevelPackData_t levelpacks[MAX_LEVEL_PACK];
|
static LevelPackData_t levelpacks[MAX_LEVEL_PACK];
|
||||||
|
|
||||||
|
#define DECOMPRESSOR_INBUF_LEN 4096
|
||||||
|
#define DECOMPRESSOR_OUTBUF_LEN 4096
|
||||||
|
static struct ZstdDecompressor
|
||||||
|
{
|
||||||
|
ZSTD_DCtx* ctx;
|
||||||
|
uint8_t in_buffer[DECOMPRESSOR_INBUF_LEN];
|
||||||
|
uint8_t out_buffer[DECOMPRESSOR_OUTBUF_LEN];
|
||||||
|
}level_decompressor;
|
||||||
|
|
||||||
static void unload_level_pack(LevelPack_t pack)
|
static void unload_level_pack(LevelPack_t pack)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < pack.n_levels; ++i)
|
for (uint8_t i = 0; i < pack.n_levels; ++i)
|
||||||
|
@ -132,6 +142,144 @@ LevelPack_t* add_level_pack(Assets_t* assets, const char* name, const char* path
|
||||||
return &levelpacks[pack_idx].pack;
|
return &levelpacks[pack_idx].pack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LevelPack_t* uncompress_level_pack(Assets_t* assets, const char* name, const char* path)
|
||||||
|
{
|
||||||
|
FILE* file = fopen(path, "rb");
|
||||||
|
if (file == NULL) return NULL;
|
||||||
|
|
||||||
|
LevelPackData_t* pack_info = levelpacks + n_loaded[4];
|
||||||
|
size_t read = 0;
|
||||||
|
|
||||||
|
ZSTD_inBuffer input = { level_decompressor.in_buffer, read, 0 };
|
||||||
|
ZSTD_outBuffer output = { level_decompressor.out_buffer, 4, 0 };
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (input.pos == input.size)
|
||||||
|
{
|
||||||
|
puts("Read more");
|
||||||
|
read = fread(level_decompressor.in_buffer, 1, DECOMPRESSOR_INBUF_LEN, file);
|
||||||
|
if (read == 0) break;
|
||||||
|
input.size = read;
|
||||||
|
input.pos = 0;
|
||||||
|
}
|
||||||
|
size_t const ret = ZSTD_decompressStream(level_decompressor.ctx, &output , &input);
|
||||||
|
if (ZSTD_isError(ret))
|
||||||
|
{
|
||||||
|
printf("Decompression Error: %s\n", ZSTD_getErrorName(ret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (output.pos == 0);
|
||||||
|
|
||||||
|
if (output.pos == 0)
|
||||||
|
{
|
||||||
|
perror("Could not read number of levels");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read number of levels and alloc the memory for the levels
|
||||||
|
uint32_t n_levels = 0;
|
||||||
|
uint8_t lvls = 0;
|
||||||
|
bool err = false;
|
||||||
|
memcpy(&n_levels, level_decompressor.out_buffer, 4);
|
||||||
|
pack_info->pack.levels = calloc(n_levels, sizeof(LevelMap_t));
|
||||||
|
|
||||||
|
for (lvls = 0; lvls < n_levels; ++lvls)
|
||||||
|
{
|
||||||
|
printf("Parsing level %u\n", lvls);
|
||||||
|
output.size = 36;
|
||||||
|
output.pos = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (input.pos == input.size)
|
||||||
|
{
|
||||||
|
read = fread(level_decompressor.in_buffer, 1, DECOMPRESSOR_INBUF_LEN, file);
|
||||||
|
if (read == 0) break;
|
||||||
|
input.size = read;
|
||||||
|
input.pos = 0;
|
||||||
|
}
|
||||||
|
size_t const ret = ZSTD_decompressStream(level_decompressor.ctx, &output , &input);
|
||||||
|
if (ZSTD_isError(ret))
|
||||||
|
{
|
||||||
|
printf("Decompression Error: %s\n", ZSTD_getErrorName(ret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("Compare %lu to %lu\n", output.pos, output.size);
|
||||||
|
}
|
||||||
|
while (output.pos != output.size);
|
||||||
|
|
||||||
|
if (output.pos != output.size)
|
||||||
|
{
|
||||||
|
perror("Could not read level");
|
||||||
|
err = true;
|
||||||
|
goto load_end;
|
||||||
|
}
|
||||||
|
memcpy(pack_info->pack.levels[lvls].level_name, level_decompressor.out_buffer, 32);
|
||||||
|
memcpy(&pack_info->pack.levels[lvls].width, level_decompressor.out_buffer + 32, 2);
|
||||||
|
memcpy(&pack_info->pack.levels[lvls].height, level_decompressor.out_buffer + 34, 2);
|
||||||
|
pack_info->pack.levels[lvls].level_name[31] = '\0';
|
||||||
|
printf("Level name: %s\n", pack_info->pack.levels[lvls].level_name);
|
||||||
|
printf("WxH: %u %u\n", pack_info->pack.levels[lvls].width, pack_info->pack.levels[lvls].height);
|
||||||
|
|
||||||
|
uint32_t n_tiles = pack_info->pack.levels[lvls].width * pack_info->pack.levels[lvls].height;
|
||||||
|
|
||||||
|
uint32_t remaining_len = n_tiles * 4;
|
||||||
|
pack_info->pack.levels[lvls].tiles = calloc(n_tiles, sizeof(LevelTileInfo_t));
|
||||||
|
output.size = DECOMPRESSOR_OUTBUF_LEN;
|
||||||
|
output.pos = 0;
|
||||||
|
uint8_t* data_ptr = (uint8_t*)pack_info->pack.levels[lvls].tiles;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (input.pos == input.size)
|
||||||
|
{
|
||||||
|
read = fread(level_decompressor.in_buffer, 1, DECOMPRESSOR_INBUF_LEN, file);
|
||||||
|
if (read == 0) break;
|
||||||
|
input.size = read;
|
||||||
|
input.pos = 0;
|
||||||
|
}
|
||||||
|
size_t to_read = (remaining_len > DECOMPRESSOR_OUTBUF_LEN) ? DECOMPRESSOR_OUTBUF_LEN : remaining_len;
|
||||||
|
output.size = to_read;
|
||||||
|
output.pos = 0;
|
||||||
|
size_t const ret = ZSTD_decompressStream(level_decompressor.ctx, &output , &input);
|
||||||
|
if (ZSTD_isError(ret))
|
||||||
|
{
|
||||||
|
printf("Decompression Error: %s\n", ZSTD_getErrorName(ret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(data_ptr, level_decompressor.out_buffer, output.pos);
|
||||||
|
data_ptr += output.pos;
|
||||||
|
remaining_len -= output.pos;
|
||||||
|
}
|
||||||
|
while (remaining_len > 0);
|
||||||
|
|
||||||
|
if (remaining_len > 0)
|
||||||
|
{
|
||||||
|
free(pack_info->pack.levels[lvls].tiles);
|
||||||
|
perror("Could not read level tiles");
|
||||||
|
err = true;
|
||||||
|
goto load_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
load_end:
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
unload_level_pack(pack_info->pack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pack_info->pack.n_levels = lvls;
|
||||||
|
uint8_t pack_idx = n_loaded[4];
|
||||||
|
strncpy(pack_info->name, name, MAX_NAME_LEN);
|
||||||
|
sc_map_put_s64(&assets->m_levelpacks, levelpacks[pack_idx].name, pack_idx);
|
||||||
|
n_loaded[4]++;
|
||||||
|
|
||||||
|
return &levelpacks[pack_idx].pack;
|
||||||
|
}
|
||||||
|
|
||||||
void init_assets(Assets_t* assets)
|
void init_assets(Assets_t* assets)
|
||||||
{
|
{
|
||||||
sc_map_init_s64(&assets->m_fonts, MAX_FONTS, 0);
|
sc_map_init_s64(&assets->m_fonts, MAX_FONTS, 0);
|
||||||
|
@ -139,6 +287,7 @@ void init_assets(Assets_t* assets)
|
||||||
sc_map_init_s64(&assets->m_textures, MAX_TEXTURES, 0);
|
sc_map_init_s64(&assets->m_textures, MAX_TEXTURES, 0);
|
||||||
sc_map_init_s64(&assets->m_sounds, MAX_SOUNDS, 0);
|
sc_map_init_s64(&assets->m_sounds, MAX_SOUNDS, 0);
|
||||||
sc_map_init_s64(&assets->m_levelpacks, MAX_LEVEL_PACK, 0);
|
sc_map_init_s64(&assets->m_levelpacks, MAX_LEVEL_PACK, 0);
|
||||||
|
level_decompressor.ctx = ZSTD_createDCtx();
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_all_assets(Assets_t* assets)
|
void free_all_assets(Assets_t* assets)
|
||||||
|
@ -176,6 +325,7 @@ void term_assets(Assets_t* assets)
|
||||||
sc_map_term_s64(&assets->m_sounds);
|
sc_map_term_s64(&assets->m_sounds);
|
||||||
sc_map_term_s64(&assets->m_sprites);
|
sc_map_term_s64(&assets->m_sprites);
|
||||||
sc_map_term_s64(&assets->m_levelpacks);
|
sc_map_term_s64(&assets->m_levelpacks);
|
||||||
|
ZSTD_freeDCtx(level_decompressor.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture2D* get_texture(Assets_t* assets, const char* name)
|
Texture2D* get_texture(Assets_t* assets, const char* name)
|
||||||
|
|
|
@ -44,6 +44,7 @@ Sprite_t* add_sprite(Assets_t* assets, const char* name, Texture2D* texture);
|
||||||
Sound* add_sound(Assets_t * assets, const char* name, const char* path);
|
Sound* add_sound(Assets_t * assets, const char* name, const char* path);
|
||||||
Font* add_font(Assets_t* assets, const char* name, const char* path);
|
Font* add_font(Assets_t* assets, const char* name, const char* path);
|
||||||
LevelPack_t* add_level_pack(Assets_t* assets, const char* name, const char* path);
|
LevelPack_t* add_level_pack(Assets_t* assets, const char* name, const char* path);
|
||||||
|
LevelPack_t* uncompress_level_pack(Assets_t* assets, const char* name, const char* path);
|
||||||
|
|
||||||
Texture2D* get_texture(Assets_t* assets, const char* name);
|
Texture2D* get_texture(Assets_t* assets, const char* name);
|
||||||
Sprite_t* get_sprite(Assets_t* assets, const char* name);
|
Sprite_t* get_sprite(Assets_t* assets, const char* name);
|
||||||
|
|
Loading…
Reference in New Issue