Implemented file copy, delete operations and dll reloading workaround for windows

dev
Shariq Shah 8 years ago
parent 3357284b24
commit 868b160930
  1. 8
      README.md
  2. 6
      src/common/common.h
  3. 82
      src/game/file_io.c
  4. 4
      src/game/file_io.h
  5. 24
      src/game/main.c
  6. 2
      src/game/sound.c
  7. 2
      src/libsymmetry/editor.c
  8. 2
      src/libsymmetry/geometry.c
  9. 2
      src/libsymmetry/gui.c
  10. 6
      src/libsymmetry/input.c
  11. 6
      src/libsymmetry/shader.c
  12. 2
      src/libsymmetry/texture.c

@ -149,9 +149,8 @@
- ## TODO - ## TODO
- Implement file copy and file delete on windows and linux. - Add file copy and delete to platform api
- Implement a work-around for dll locking on windows by creating a copy of the game lib at launch and when reloading, - Make dll reloading workaround compatilble on linux
unload the current dll, delete it and create new copy of the updated dll and load that.
- Find a solution for the asset import/export situation by either updating the blender exporter or adding assimp as dependancy - 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 - Fix bugs with sound sources not updating
- Add creating distributable build and uploading to itch.io account support to GENie under windows and linux. - 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. * 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. * 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 * 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

@ -26,8 +26,10 @@ typedef void (*Textinput_Event_Func) (const char* text);
enum Directory_Type enum Directory_Type
{ {
DT_USER, /* User directory or preferences directory */ DIRT_USER, /* User directory or preferences directory */
DT_INSTALL /* Directory where the game's executable is, usually where the game is installed */ 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 struct Sound_Api

@ -5,11 +5,15 @@
#include "../common/log.h" #include "../common/log.h"
#include "../common/string_utils.h" #include "../common/string_utils.h"
static char* executable_directory = NULL;
static char* install_directory = NULL; static char* install_directory = NULL;
static char* user_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) void io_file_init(const char* install_dir, const char* user_dir)
{ {
executable_directory = str_new("%s", install_dir);
install_directory = str_new("%s/assets/", install_dir); install_directory = str_new("%s/assets/", install_dir);
user_directory = str_new("%s/", user_dir); user_directory = str_new("%s/", user_dir);
} }
@ -17,6 +21,7 @@ void io_file_init(const char* install_dir, const char* user_dir)
void io_file_cleanup(void) void io_file_cleanup(void)
{ {
if(install_directory) free(install_directory); if(install_directory) free(install_directory);
if(executable_directory) free(executable_directory);
if(user_directory) free(user_directory); if(user_directory) free(user_directory);
install_directory = NULL; install_directory = NULL;
user_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) 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); relative_path = str_concat(relative_path, path);
FILE* file = fopen(relative_path, mode); 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); free(relative_path);
return file; 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;
}

@ -4,8 +4,10 @@
#include "../common/common.h" #include "../common/common.h"
void io_file_init(const char* install_dir, const char* user_dir); 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); 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); 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 #endif

@ -9,11 +9,14 @@
#include "../common/hashmap.h" #include "../common/hashmap.h"
#include "../common/common.h" #include "../common/common.h"
static struct Window* window = NULL;
static struct Platform_Api platform_api; static struct Platform_Api platform_api;
static struct Window* window = NULL;
static bool reload_game = false; static bool reload_game = false;
struct Game_Api game; static const char* lib_name = "libSymmetry.dll";
static const char* lib_copy_name = "libSymmetry.copy.dll";
void* game_lib_handle = NULL; void* game_lib_handle = NULL;
struct Game_Api game;
bool init(void); bool init(void);
void cleanup(void); void cleanup(void);
@ -123,6 +126,11 @@ int main(int argc, char** args)
game_lib_handle = NULL; game_lib_handle = NULL;
game.cleanup = 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()) if(!game_lib_load())
@ -159,10 +167,10 @@ bool init(void)
io_file_init(install_path, user_path); io_file_init(install_path, user_path);
free(install_path); free(install_path);
free(user_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"); 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; if(!platform_init_video()) return false;
@ -215,7 +223,13 @@ void game_lib_reload(void)
bool game_lib_load(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) if(!game_lib_handle)
{ {
log_error("main:game_lib_load", "Failed to load game library"); log_error("main:game_lib_load", "Failed to load game library");

@ -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); 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); free(full_path);
if(!wav_file) if(!wav_file)
{ {

@ -187,7 +187,7 @@ void editor_update(float dt)
if(nk_button_label(context, "Render Settings")) if(nk_button_label(context, "Render Settings"))
editor_state.renderer_settings_window = !editor_state.renderer_settings_window; editor_state.renderer_settings_window = !editor_state.renderer_settings_window;
if(nk_button_label(context, "Save config")) 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_spacing(context, 1);
nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps); nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps);
nk_group_end(context); nk_group_end(context);

@ -214,7 +214,7 @@ static int load_from_file(struct Geometry* geometry, const char* filename)
int success = 1; int success = 1;
char* full_path = str_new("models/%s", filename); 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); free(full_path);
if(file) if(file)
{ {

@ -372,7 +372,7 @@ void gui_font_set(const char* font_name, float font_size)
struct nk_font_atlas* atlas = &gui_state->atlas; struct nk_font_atlas* atlas = &gui_state->atlas;
long size = 0; long size = 0;
char* font_file_name = str_new("fonts/%s", font_name); 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); free(font_file_name);
if(!font_data) if(!font_data)
{ {

@ -31,11 +31,11 @@ void input_init(void)
platform->mousewheel_callback_set(&input_on_mousewheel); platform->mousewheel_callback_set(&input_on_mousewheel);
input_map_list = array_new(struct Input_Map); 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_error("input:init", "Failed to load keybindings");
log_message("Reverting to default 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"); log_error("input:init", "Failed to load default keybindings");
} }
@ -208,7 +208,7 @@ bool input_keybinds_save(const char* filename)
{ {
bool success = false; 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) if(!config_file)
{ {
log_error("input:keybinds_save", "Could not open %s", filename); log_error("input:keybinds_save", "Could not open %s", filename);

@ -56,7 +56,7 @@ char* run_preprocessor(char* shader_text)
{ {
char* path = str_new("shaders/"); char* path = str_new("shaders/");
path = str_concat(path, filename); 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* shader_copy = str_new(shader_text);
char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2)); char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2));
if(temp) 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 vert_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER); GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
char* vert_source = platform->file.read(DT_INSTALL, vs_path, "r", NULL); char* vert_source = platform->file.read(DIRT_INSTALL, vs_path, "r", NULL);
char* frag_source = platform->file.read(DT_INSTALL, fs_path, "r", NULL); char* frag_source = platform->file.read(DIRT_INSTALL, fs_path, "r", NULL);
assert(vert_source != NULL); assert(vert_source != NULL);
assert(frag_source != NULL); assert(frag_source != NULL);

@ -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 */ /* If texture not already loaded then try to load it */
char* full_path = str_new("textures/%s", filename); 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; int img_load_success = -1;
if(file) if(file)

Loading…
Cancel
Save