From b74f7c6e3ade48932f0ff15b761b85d70c3622fa Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sat, 4 Nov 2023 22:11:54 +0000 Subject: [PATCH] Add DEBUG_ENGINE as compile definition instead of using build_config --- CMakeLists.txt | 7 +- engine_build_config.h.in | 1 - include/AssetManager.h | 3 +- include/ObjectStore.h | 1 - include/Renderer.h | 10 ++ src/AssetManager.c | 257 ++++++++++++++++++++++++++++----------- src/GameEngine.c | 27 ++-- src/ObjectStore.c | 5 +- src/Renderer.c | 19 ++- src/Window.c | 7 +- 10 files changed, 233 insertions(+), 104 deletions(-) delete mode 100644 engine_build_config.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index bbca79d..31f8dfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,11 +3,11 @@ cmake_minimum_required(VERSION 3.10) project(Punchie) if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") - set(DEBUG_ENGINE ON) + add_compile_definitions("DEBUG_ENGINE=1") +else() + add_compile_definitions("DEBUG_ENGINE=0") endif() -configure_file(engine_build_config.h.in engine_build_config.h) - # VARIABLES set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -53,7 +53,6 @@ target_link_libraries(${PROJECT_NAME} PUBLIC ) install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/engine_build_config.h include/aliases.h include/constants.h include/GameEngine.h diff --git a/engine_build_config.h.in b/engine_build_config.h.in deleted file mode 100644 index 3c2da52..0000000 --- a/engine_build_config.h.in +++ /dev/null @@ -1 +0,0 @@ -#cmakedefine DEBUG_ENGINE diff --git a/include/AssetManager.h b/include/AssetManager.h index b640ae4..c48fd08 100644 --- a/include/AssetManager.h +++ b/include/AssetManager.h @@ -35,7 +35,8 @@ AssetManager *create_asset_manager(); * Returns the AssetID on success or an INVALID_ID in the case of failure. */ AssetID load_asset_to_manager(AssetManager *am, const char *path, - AssetType type, const Renderer *renderer); + AssetType type, const Renderer *renderer, + asset_pack_t *pack); /** * Removes an asset from the manager using its ID. diff --git a/include/ObjectStore.h b/include/ObjectStore.h index 656ac98..a567f6a 100644 --- a/include/ObjectStore.h +++ b/include/ObjectStore.h @@ -4,7 +4,6 @@ #include "Renderer.h" #include "SDL_events.h" #include "aliases.h" -#include "engine_build_config.h" #include "reusable_ids.h" #ifdef __cplusplus diff --git a/include/Renderer.h b/include/Renderer.h index ab0d2d3..f7814ad 100644 --- a/include/Renderer.h +++ b/include/Renderer.h @@ -4,10 +4,12 @@ #include "SDL.h" #include "SDL_pixels.h" #include "SDL_render.h" +#include "SDL_rwops.h" #include "SDL_surface.h" #include "SDL_ttf.h" #include "SDL_video.h" #include "aliases.h" +#include "pak.h" #include #ifdef __cplusplus @@ -71,6 +73,14 @@ void swap_buffers(const Renderer *renderer); */ SDL_Texture *load_texture(const Renderer *renderer, const char *path); +/** + * Attempts to load an SDL_Texture from an SDL_RWops context. + * + * Returns a pointer to the object if it succeeds or NULL when it fails. + */ +SDL_Texture *load_texture_from_rwops(const Renderer *renderer, SDL_RWops *ctx, + i32 freesrc); + /** * Frees the memory allocated to the Renderer object and performs the * necessary cleanup. diff --git a/src/AssetManager.c b/src/AssetManager.c index 5aef062..9fc3bc2 100644 --- a/src/AssetManager.c +++ b/src/AssetManager.c @@ -7,6 +7,7 @@ #include "SDL_ttf.h" #include "aliases.h" #include "constants.h" +#include "pak.h" #include "reusable_ids.h" #include #include @@ -14,6 +15,9 @@ #include #include +#define RWOPS_FREE_SRC 1 +#define DEFAULT_FONT_PTSIZE 32 + typedef struct asset { AssetType type; char *path; @@ -36,6 +40,16 @@ typedef struct id_node_list { u64 node_count; } IDNodeList; +typedef struct { + Asset asset; + bool loaded; +} AssetLoadResult; + +typedef enum { + ASSET_SOURCE_FILE, + ASSET_SOURCE_PACK, +} AssetSource; + struct asset_manager { u64 count; u64 deleted_count; @@ -51,9 +65,20 @@ void insert_id_node(IDNodeList *node_list, AssetID id); void remove_id_node(IDNodeList *node_list, AssetID id); +void *get_asset_from_pack(asset_pack_t *pack, const char *path, AssetType type, + const Renderer *renderer); + +AssetLoadResult asset_load(const char *path, AssetType type, AssetSource source, + const Renderer *renderer, asset_pack_t *pack); + +AssetID get_new_id(AssetManager *am); + AssetID get_asset_id_from_id_node(AssetManager *am, IDNodeList *node_list, const char *path); +AssetID get_valid_type_id_if_exists(AssetManager *am, const char *path, + u64 hash_index, AssetType type); + AssetManager *create_asset_manager() { AssetManager *am = (AssetManager *)malloc(sizeof(AssetManager)); if (!am) { @@ -71,27 +96,16 @@ AssetManager *create_asset_manager() { } AssetID load_asset_to_manager(AssetManager *am, const char *path, - AssetType type, const Renderer *renderer) { + AssetType type, const Renderer *renderer, + asset_pack_t *pack) { if (!am || type == ASSET_TYPE_COUNT) { return INVALID_ID; } u64 hash_index = hash_path(path); - AssetID existing_id = - get_asset_id_from_id_node(am, &(am->hashed_path_ids[hash_index]), path); - + AssetID existing_id = get_valid_type_id_if_exists(am, path, hash_index, type); if (existing_id != INVALID_ID) { - if (am->assets[existing_id].type != type) { - // If the user tries to load an asset that is already loaded, but they - // try to load it as a type that doesn't match the asset's actual type, - // we return an INVALID_ID to ensure that the user doesn't try using the - // asset with functions that work on the wrong type - return INVALID_ID; - } - - ++(am->user_counter[existing_id]); - return existing_id; } @@ -99,66 +113,16 @@ AssetID load_asset_to_manager(AssetManager *am, const char *path, return INVALID_ID; } - Asset asset = {}; - bool loaded = true; + AssetSource source = pack ? ASSET_SOURCE_PACK : ASSET_SOURCE_FILE; - switch (type) { - case ASSET_TYPE_IMAGE: - if (!renderer) { - loaded = false; - break; - } + AssetLoadResult result = asset_load(path, type, source, renderer, pack); - asset.data.texture = load_texture(renderer, path); - - if (!(asset.data.texture)) { - loaded = false; - } - - break; - case ASSET_TYPE_AUDIO_FX: - asset.data.chunk = Mix_LoadWAV(path); - - if (!(asset.data.chunk)) { - loaded = false; - } - - break; - case ASSET_TYPE_MUSIC: - asset.data.music = Mix_LoadMUS(path); - - if (!(asset.data.music)) { - loaded = false; - } - - break; - case ASSET_TYPE_FONT: - asset.data.font = TTF_OpenFont(path, 32); - - if (!(asset.data.font)) { - loaded = false; - } - - break; - default: - loaded = false; - break; - } - - if (!loaded) { + if (!result.loaded) { printf("Error loading %s: %s\n", path, SDL_GetError()); return INVALID_ID; } - AssetID id; - - if (am->deleted_count > 0) { - id = (AssetID)reuse_id((i32 *)am->reusable_ids, am->deleted_count); - am->deleted_count -= 1; - am->count += 1; - } else { - id = (am->count)++; - } + AssetID id = get_new_id(am); insert_id_node(&(am->hashed_path_ids[hash_index]), id); @@ -169,20 +133,20 @@ AssetID load_asset_to_manager(AssetManager *am, const char *path, am->assets[id].path = (char *)malloc(strlen(path) + 1); strcpy(am->assets[id].path, path); - am->assets[id].data = asset.data; + am->assets[id].data = result.asset.data; switch (type) { case ASSET_TYPE_IMAGE: - asset.data.texture = NULL; + result.asset.data.texture = NULL; break; case ASSET_TYPE_AUDIO_FX: - asset.data.chunk = NULL; + result.asset.data.chunk = NULL; break; case ASSET_TYPE_MUSIC: - asset.data.music = NULL; + result.asset.data.music = NULL; break; case ASSET_TYPE_FONT: - asset.data.font = NULL; + result.asset.data.font = NULL; break; default: break; @@ -402,6 +366,139 @@ void remove_id_node(IDNodeList *node_list, AssetID id) { } } +void *get_asset_from_pack(asset_pack_t *pack, const char *path, AssetType type, + const Renderer *renderer) { + if (!pack || !path) { + return NULL; + } + + void *output = NULL; + + buf_t *asset = read_file_from_pack(pack, path); + if (!asset) { + return NULL; + } + + SDL_RWops *ctx = SDL_RWFromMem(asset->data, asset->size); + if (!ctx) { + return NULL; + } + + switch (type) { + case ASSET_TYPE_IMAGE: + if (!renderer) { + break; + } + + output = (void *)load_texture_from_rwops(renderer, ctx, RWOPS_FREE_SRC); + + break; + case ASSET_TYPE_AUDIO_FX: + output = (void *)Mix_LoadWAV_RW(ctx, RWOPS_FREE_SRC); + + break; + case ASSET_TYPE_MUSIC: + output = (void *)Mix_LoadMUS_RW(ctx, RWOPS_FREE_SRC); + + break; + case ASSET_TYPE_FONT: + output = (void *)TTF_OpenFontRW(ctx, RWOPS_FREE_SRC, DEFAULT_FONT_PTSIZE); + + break; + default: + break; + } + + close_pack_file(&asset); + + return output; +} + +AssetLoadResult asset_load(const char *path, AssetType type, AssetSource source, + const Renderer *renderer, asset_pack_t *pack) { + AssetLoadResult result = (AssetLoadResult){ + .asset = (Asset){}, + .loaded = true, + }; + + if (source == ASSET_SOURCE_PACK && !(pack)) { + result.loaded = false; + + return result; + } + + switch (type) { + case ASSET_TYPE_IMAGE: + if (!renderer) { + result.loaded = false; + break; + } + + result.asset.data.texture = + source == ASSET_SOURCE_FILE + ? load_texture(renderer, path) + : (SDL_Texture *)get_asset_from_pack(pack, path, type, renderer); + + if (!(result.asset.data.texture)) { + result.loaded = false; + } + + break; + case ASSET_TYPE_AUDIO_FX: + result.asset.data.chunk = + source == ASSET_SOURCE_FILE + ? Mix_LoadWAV(path) + : (Mix_Chunk *)get_asset_from_pack(pack, path, type, renderer); + + if (!(result.asset.data.chunk)) { + result.loaded = false; + } + + break; + case ASSET_TYPE_MUSIC: + result.asset.data.music = + source == ASSET_SOURCE_FILE + ? Mix_LoadMUS(path) + : (Mix_Music *)get_asset_from_pack(pack, path, type, renderer); + + if (!(result.asset.data.music)) { + result.loaded = false; + } + + break; + case ASSET_TYPE_FONT: + result.asset.data.font = + source == ASSET_SOURCE_FILE + ? TTF_OpenFont(path, DEFAULT_FONT_PTSIZE) + : (TTF_Font *)get_asset_from_pack(pack, path, type, renderer); + + if (!(result.asset.data.font)) { + result.loaded = false; + } + + break; + default: + result.loaded = false; + break; + } + + return result; +} + +AssetID get_new_id(AssetManager *am) { + AssetID id; + + if (am->deleted_count > 0) { + id = (AssetID)reuse_id((i32 *)am->reusable_ids, am->deleted_count); + am->deleted_count -= 1; + am->count += 1; + } else { + id = (am->count)++; + } + + return id; +} + AssetID get_asset_id_from_id_node(AssetManager *am, IDNodeList *node_list, const char *path) { /** @@ -430,3 +527,17 @@ AssetID get_asset_id_from_id_node(AssetManager *am, IDNodeList *node_list, return INVALID_ID; } + +AssetID get_valid_type_id_if_exists(AssetManager *am, const char *path, + u64 hash_index, AssetType type) { + AssetID existing_id = + get_asset_id_from_id_node(am, &(am->hashed_path_ids[hash_index]), path); + + if (existing_id == INVALID_ID || am->assets[existing_id].type != type) { + return INVALID_ID; + } + + ++(am->user_counter[existing_id]); + + return existing_id; +} diff --git a/src/GameEngine.c b/src/GameEngine.c index 31685fa..be8334d 100644 --- a/src/GameEngine.c +++ b/src/GameEngine.c @@ -22,14 +22,13 @@ #include "Window.h" #include "aliases.h" #include "constants.h" -#include "engine_build_config.h" #include "reusable_ids.h" #include #include #include #include -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE #include #endif /* DEBUG_ENGINE */ @@ -54,7 +53,7 @@ bool init_engine(const char *game_name, WindowSize window_size, } if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to initialise SDL. Error: %s\n", SDL_GetError()); #endif /* DEBUG_ENGINE */ @@ -71,14 +70,14 @@ bool init_engine(const char *game_name, WindowSize window_size, } if ((IMG_Init(img_flags) & img_flags) != img_flags) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to initialise SDL_image. Error: %s\n", IMG_GetError()); #endif /* DEBUG_ENGINE */ initialisation_complete = false; } if (TTF_Init() < 0) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to initialise SDL_ttf. Error: %s\n", TTF_GetError()); #endif /* DEBUG_ENGINE */ initialisation_complete = false; @@ -87,14 +86,14 @@ bool init_engine(const char *game_name, WindowSize window_size, // We're only interested in initialising SDL_mixer with WAVE files, so no // need to pass any flags if (Mix_Init(0) != 0) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to initialise SDL_mixer. Error: %s\n", Mix_GetError()); #endif /* DEBUG_ENGINE */ initialisation_complete = false; } if (Mix_OpenAudio(48000, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to open audio device. Error: %s\n", Mix_GetError()); #endif /* DEBUG_ENGINE */ initialisation_complete = false; @@ -102,7 +101,7 @@ bool init_engine(const char *game_name, WindowSize window_size, if (audio_tracks > 0) { if (Mix_AllocateChannels(audio_tracks) != audio_tracks) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to allocate the required tracks.\n"); #endif /* DEBUG_ENGINE */ initialisation_complete = false; @@ -111,7 +110,7 @@ bool init_engine(const char *game_name, WindowSize window_size, if (!init_window(&(GameEngine.window), game_name, window_size, window_background_color, full_screen)) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to initialise window\n"); #endif /* DEBUG_ENGINE */ @@ -138,11 +137,11 @@ bool init_engine(const char *game_name, WindowSize window_size, GameEngine.delta = 0.0f; GameEngine.last_time = SDL_GetTicks64(); -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE GameEngine.delta = 1.0f / 60.0f; #endif /* DEBUG_ENGINE */ -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Game initialised successfully\n"); #endif /* DEBUG_ENGINE */ @@ -176,7 +175,7 @@ void close_engine() { SDL_Quit(); -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Game closed successfully\n"); #endif /* DEBUG_ENGINE */ } @@ -210,8 +209,8 @@ void remove_object(ObjectID *id) { AssetID load_asset(const char *path, AssetType type) { return type == ASSET_TYPE_IMAGE ? load_asset_to_manager(GameEngine.asset_manager, path, type, - GameEngine.window.renderer) - : load_asset_to_manager(GameEngine.asset_manager, path, type, + GameEngine.window.renderer, NULL) + : load_asset_to_manager(GameEngine.asset_manager, path, type, NULL, NULL); } diff --git a/src/ObjectStore.c b/src/ObjectStore.c index 71074f2..ede55c9 100644 --- a/src/ObjectStore.c +++ b/src/ObjectStore.c @@ -1,7 +1,6 @@ #include "ObjectStore.h" #include "aliases.h" #include "constants.h" -#include "engine_build_config.h" #include "reusable_ids.h" #include #include @@ -9,7 +8,7 @@ #include #include -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE #include #endif /* DEBUG_ENGINE */ @@ -52,7 +51,7 @@ ObjectID add_object_to_store(ObjectStore *os, void *object, EventHandlerPtr eh, if (!os || !object || object_exists(os, object) || no_funcs_passed || (os->count + 1 == MAX_OBJ_COUNT && os->deleted_count == 0)) { -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Failed to add object\n"); #endif /* DEBUG_ENGINE */ diff --git a/src/Renderer.c b/src/Renderer.c index e985055..d511e2b 100644 --- a/src/Renderer.c +++ b/src/Renderer.c @@ -8,11 +8,11 @@ #include "SDL_surface.h" #include "SDL_video.h" #include "aliases.h" -#include "engine_build_config.h" +#include "pak.h" #include #include -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE #include #endif /* DEBUG_ENGINE */ @@ -131,9 +131,22 @@ void swap_buffers(const Renderer *renderer) { } SDL_Texture *load_texture(const Renderer *renderer, const char *path) { + if (!renderer || !path) { + return NULL; + } + return IMG_LoadTexture(renderer->SDL_base_renderer, path); } +SDL_Texture *load_texture_from_rwops(const Renderer *renderer, SDL_RWops *ctx, + i32 freesrc) { + if (!renderer || !ctx) { + return NULL; + } + + return IMG_LoadTexture_RW(renderer->SDL_base_renderer, ctx, freesrc); +} + void destroy_renderer(Renderer **renderer) { if (*renderer) { if ((*renderer)->SDL_base_renderer) { @@ -144,7 +157,7 @@ void destroy_renderer(Renderer **renderer) { free(*renderer); *renderer = NULL; -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Renderer destroyed successfully\n"); #endif /* DEBUG_ENGINE */ } diff --git a/src/Window.c b/src/Window.c index b04a1d5..a71390c 100644 --- a/src/Window.c +++ b/src/Window.c @@ -4,13 +4,12 @@ #include "SDL_platform.h" #include "SDL_video.h" #include "aliases.h" -#include "engine_build_config.h" #include "math_utils.h" #include #include #include -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE #include #endif /* DEBUG_ENGINE */ @@ -136,7 +135,7 @@ bool init_window(Window *wnd, const char *title, WindowSize size, wnd->real_size.height = wnd->drawing_area.height = wnd->defined_size.height; } -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Renderer initialised successfully\n"); printf("Window initialised successfully with width %d and height %d\n", wnd->real_size.width, wnd->real_size.height); @@ -194,7 +193,7 @@ void destroy_window(Window *wnd) { wnd->drawing_area = (WindowDrawingArea){0.0f, 0.0f, 0.0f, 0.0f}; wnd->background_color = (SDL_Color){0, 0, 0, 255}; -#ifdef DEBUG_ENGINE +#if DEBUG_ENGINE printf("Window destroyed successfully\n"); #endif /* DEBUG_ENGINE */ }