diff --git a/README.md b/README.md index 6ae2a35..11d32a8 100644 --- a/README.md +++ b/README.md @@ -149,9 +149,8 @@ - ## TODO - - Implement file copy and file delete on windows and linux. - - Implement a work-around for dll locking on windows by creating a copy of the game lib at launch and when reloading, - unload the current dll, delete it and create new copy of the updated dll and load that. + - Add file copy and delete to platform api + - Make dll reloading workaround compatilble on linux - Find a solution for the asset import/export situation by either updating the blender exporter or adding assimp as dependancy - Fix bugs with sound sources not updating - Add creating distributable build and uploading to itch.io account support to GENie under windows and linux. @@ -306,3 +305,6 @@ * Move game, common and game library related code into separate folders. * Fixed game crashing on exit after game library has been reloaded more than once. * Made game compile and run under windows with visual studio 2017 using GENie + * Implemented file copy and file delete on windows and linux. + * Implemented a work-around for dll locking on windows by creating a copy of the game lib at launch and when reloading, + unloading the current dll, deleting it and creating new copy of the updated dll and loading that diff --git a/src/common/common.h b/src/common/common.h index 40ca3fa..910aec3 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -26,8 +26,10 @@ typedef void (*Textinput_Event_Func) (const char* text); enum Directory_Type { - DT_USER, /* User directory or preferences directory */ - DT_INSTALL /* Directory where the game's executable is, usually where the game is installed */ + DIRT_USER, /* User directory or preferences directory */ + DIRT_INSTALL, /* Directory where the game's assets are, usually alongside the game's executable where the game is installed */ + DIRT_EXECUTABLE, /* Directory where the game's executable is located */ + DIRT_COUNT }; struct Sound_Api diff --git a/src/game/file_io.c b/src/game/file_io.c index cf9e4d3..7b0df1c 100644 --- a/src/game/file_io.c +++ b/src/game/file_io.c @@ -5,19 +5,24 @@ #include "../common/log.h" #include "../common/string_utils.h" +static char* executable_directory = NULL; static char* install_directory = NULL; static char* user_directory = NULL; +static char* relative_path_get(const int directory_type); + void io_file_init(const char* install_dir, const char* user_dir) { - install_directory = str_new("%s/assets/", install_dir); - user_directory = str_new("%s/", user_dir); + executable_directory = str_new("%s", install_dir); + install_directory = str_new("%s/assets/", install_dir); + user_directory = str_new("%s/", user_dir); } void io_file_cleanup(void) { - if(install_directory) free(install_directory); - if(user_directory) free(user_directory); + if(install_directory) free(install_directory); + if(executable_directory) free(executable_directory); + if(user_directory) free(user_directory); install_directory = NULL; user_directory = NULL; } @@ -61,12 +66,83 @@ char* io_file_read(const int directory_type, const char* path, const char* mode, FILE* io_file_open(const int directory_type, const char* path, const char* mode) { - assert(directory_type >= 0 && directory_type <= DT_INSTALL); + assert(directory_type >= 0 && directory_type < DIRT_COUNT); + + char* relative_path = relative_path_get(directory_type); + if(!relative_path) + { + log_error("io:file_open", "Failed to get relative path for '%s'", path); + return NULL; + } - char* relative_path = str_new(directory_type == DT_INSTALL ? install_directory : user_directory); relative_path = str_concat(relative_path, path); FILE* file = fopen(relative_path, mode); - if(!file) log_error("io:file", "Failed to open file '%s'", relative_path); + if(!file) + log_error("io:file_open", "Failed to open file '%s'", relative_path); free(relative_path); return file; } + +bool io_file_copy(const int directory_type, const char* source, const char* destination) +{ + bool success = true; + long source_size = 0; + char* source_contents = io_file_read(directory_type, source, "rb", &source_size); + if(!source_contents) + { + log_error("io:file_copy", "Failed to read source file '%s'", source); + return false; + } + + FILE* dest_file = io_file_open(directory_type, destination, "wb"); + if(!dest_file) + { + log_error("io:file_copy", "Failed to open destination file '%s'", destination); + return false; + } + + if(fwrite(source_contents, (size_t)source_size, 1, dest_file) != 1) + { + log_error("io:file_copy", "Failed to copy source_contents into destination file '%s'", destination); + success = false; + } + + log_message("'%s' copied to '%s'", source, destination); + free(source_contents); + fclose(dest_file); + + return success; +} + +bool io_file_delete(const int directory_type, const char* filename) +{ + char* relative_path = relative_path_get(directory_type); + relative_path = str_concat(relative_path, filename); + + if(remove(relative_path) != 0) + { + log_error("io:file_delete", "Failed to delete '%s'", filename); + return false; + } + else + { + log_message("'%s' deleted", filename); + } + + free(relative_path); + return true; +} + +static char* relative_path_get(const int directory_type) +{ + char* relative_path = NULL; + switch(directory_type) + { + case DIRT_USER: relative_path = str_new(user_directory); break; + case DIRT_INSTALL: relative_path = str_new(install_directory); break; + case DIRT_EXECUTABLE: relative_path = str_new(executable_directory); break; + default: log_error("io:relative_path_get", "Invalid directory type!"); break; + }; + return relative_path; +} + diff --git a/src/game/file_io.h b/src/game/file_io.h index e175a6b..2ec46ef 100644 --- a/src/game/file_io.h +++ b/src/game/file_io.h @@ -4,8 +4,10 @@ #include "../common/common.h" void io_file_init(const char* install_dir, const char* user_dir); +void io_file_cleanup(void); char* io_file_read(const int directory_type, const char* path, const char* mode, long* file_size); FILE* io_file_open(const int directory_type, const char* path, const char* mode); -void io_file_cleanup(void); +bool io_file_copy(const int directory_type, const char* source, const char* destination); +bool io_file_delete(const int directory_type, const char* filename); #endif diff --git a/src/game/main.c b/src/game/main.c index e634580..ce91c16 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -9,11 +9,14 @@ #include "../common/hashmap.h" #include "../common/common.h" -static struct Window* window = NULL; static struct Platform_Api platform_api; -static bool reload_game = false; -struct Game_Api game; -void* game_lib_handle = NULL; +static struct Window* window = NULL; +static bool reload_game = false; +static const char* lib_name = "libSymmetry.dll"; +static const char* lib_copy_name = "libSymmetry.copy.dll"; + +void* game_lib_handle = NULL; +struct Game_Api game; bool init(void); void cleanup(void); @@ -122,7 +125,12 @@ int main(int argc, char** args) platform_unload_library(game_lib_handle); game_lib_handle = NULL; game.cleanup = NULL; - game.init = NULL; + game.init = NULL; + if(!io_file_delete(DIRT_EXECUTABLE, lib_copy_name)) + { + done = true; + continue; + } } if(!game_lib_load()) @@ -159,10 +167,10 @@ bool init(void) io_file_init(install_path, user_path); free(install_path); free(user_path); - if(!config_vars_load("config.cfg", DT_USER)) + if(!config_vars_load("config.cfg", DIRT_USER)) { log_error("main:init", "Could not load config, reverting to defaults"); - config_vars_save("config.cfg", DT_USER); + config_vars_save("config.cfg", DIRT_USER); } if(!platform_init_video()) return false; @@ -215,7 +223,13 @@ void game_lib_reload(void) bool game_lib_load(void) { - game_lib_handle = platform_load_library("libSymmetry"); + if(!io_file_copy(DIRT_EXECUTABLE, lib_name, lib_copy_name)) + { + log_error("main:game_lib_load", "Failed to copy dll"); + return false; + } + + game_lib_handle = platform_load_library("libSymmetry.copy"); if(!game_lib_handle) { log_error("main:game_lib_load", "Failed to load game library"); diff --git a/src/game/sound.c b/src/game/sound.c index 345cd67..b02ec13 100644 --- a/src/game/sound.c +++ b/src/game/sound.c @@ -181,7 +181,7 @@ void sound_source_load_wav(uint source_handle, uint buffer_handle, const char* f } char* full_path = str_new("sounds/%s", file_name); - FILE* wav_file = io_file_open(DT_INSTALL, full_path, "rb"); + FILE* wav_file = io_file_open(DIRT_INSTALL, full_path, "rb"); free(full_path); if(!wav_file) { diff --git a/src/libsymmetry/editor.c b/src/libsymmetry/editor.c index f145c2c..58c6224 100644 --- a/src/libsymmetry/editor.c +++ b/src/libsymmetry/editor.c @@ -187,7 +187,7 @@ void editor_update(float dt) if(nk_button_label(context, "Render Settings")) editor_state.renderer_settings_window = !editor_state.renderer_settings_window; if(nk_button_label(context, "Save config")) - platform->config.save("config.cfg", DT_USER); + platform->config.save("config.cfg", DIRT_USER); nk_spacing(context, 1); nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps); nk_group_end(context); diff --git a/src/libsymmetry/geometry.c b/src/libsymmetry/geometry.c index 6842607..7aedcb5 100644 --- a/src/libsymmetry/geometry.c +++ b/src/libsymmetry/geometry.c @@ -214,7 +214,7 @@ static int load_from_file(struct Geometry* geometry, const char* filename) int success = 1; char* full_path = str_new("models/%s", filename); - FILE* file = platform->file.open(DT_INSTALL, full_path, "rb"); + FILE* file = platform->file.open(DIRT_INSTALL, full_path, "rb"); free(full_path); if(file) { diff --git a/src/libsymmetry/gui.c b/src/libsymmetry/gui.c index 5c405e2..7cde34e 100644 --- a/src/libsymmetry/gui.c +++ b/src/libsymmetry/gui.c @@ -372,7 +372,7 @@ void gui_font_set(const char* font_name, float font_size) struct nk_font_atlas* atlas = &gui_state->atlas; long size = 0; char* font_file_name = str_new("fonts/%s", font_name); - char* font_data = platform->file.read(DT_INSTALL, font_file_name, "rb", &size); + char* font_data = platform->file.read(DIRT_INSTALL, font_file_name, "rb", &size); free(font_file_name); if(!font_data) { diff --git a/src/libsymmetry/input.c b/src/libsymmetry/input.c index 10bcc15..bde6d72 100644 --- a/src/libsymmetry/input.c +++ b/src/libsymmetry/input.c @@ -31,11 +31,11 @@ void input_init(void) platform->mousewheel_callback_set(&input_on_mousewheel); input_map_list = array_new(struct Input_Map); - if(!input_keybinds_load("keybindings.cfg", DT_USER)) + if(!input_keybinds_load("keybindings.cfg", DIRT_USER)) { log_error("input:init", "Failed to load keybindings"); log_message("Reverting to default keybindings"); - if(!input_keybinds_load("keybindings.cfg", DT_INSTALL)) + if(!input_keybinds_load("keybindings.cfg", DIRT_INSTALL)) { log_error("input:init", "Failed to load default keybindings"); } @@ -208,7 +208,7 @@ bool input_keybinds_save(const char* filename) { bool success = false; - FILE* config_file = platform->file.open(DT_USER, filename, "w"); + FILE* config_file = platform->file.open(DIRT_USER, filename, "w"); if(!config_file) { log_error("input:keybinds_save", "Could not open %s", filename); diff --git a/src/libsymmetry/shader.c b/src/libsymmetry/shader.c index e901bb3..4568424 100644 --- a/src/libsymmetry/shader.c +++ b/src/libsymmetry/shader.c @@ -56,7 +56,7 @@ char* run_preprocessor(char* shader_text) { char* path = str_new("shaders/"); path = str_concat(path, filename); - char* file = platform->file.read(DT_INSTALL, path, "r", NULL); + char* file = platform->file.read(DIRT_INSTALL, path, "r", NULL); char* shader_copy = str_new(shader_text); char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2)); if(temp) @@ -96,8 +96,8 @@ int shader_create(const char* vert_shader_name, const char* frag_shader_name) GLuint vert_shader = glCreateShader(GL_VERTEX_SHADER); GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER); - char* vert_source = platform->file.read(DT_INSTALL, vs_path, "r", NULL); - char* frag_source = platform->file.read(DT_INSTALL, fs_path, "r", NULL); + char* vert_source = platform->file.read(DIRT_INSTALL, vs_path, "r", NULL); + char* frag_source = platform->file.read(DIRT_INSTALL, fs_path, "r", NULL); assert(vert_source != NULL); assert(frag_source != NULL); diff --git a/src/libsymmetry/texture.c b/src/libsymmetry/texture.c index 15c104c..28c1e56 100644 --- a/src/libsymmetry/texture.c +++ b/src/libsymmetry/texture.c @@ -68,7 +68,7 @@ int texture_create_from_file(const char* filename, int texture_unit) } /* If texture not already loaded then try to load it */ char* full_path = str_new("textures/%s", filename); - FILE* file = platform->file.open(DT_INSTALL, full_path, "rb"); + FILE* file = platform->file.open(DIRT_INSTALL, full_path, "rb"); int img_load_success = -1; if(file)