Use hashtables for resource management

This commit is contained in:
Andrei "Akari" Alexeyev 2017-02-28 19:47:47 +02:00
parent fdd4633e19
commit 18652576d6
19 changed files with 243 additions and 241 deletions

View file

@ -12,6 +12,7 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <zlib.h> #include <zlib.h>
#include <stdio.h>
typedef struct HashtableElement { typedef struct HashtableElement {
void *next; void *next;
@ -59,11 +60,18 @@ static void hashtable_delete_callback(void **vlist, void *velem, void *vht) {
delete_element(vlist, velem); delete_element(vlist, velem);
} }
void hashtable_free(Hashtable *ht) { void hashtable_unset_all(Hashtable *ht) {
for(size_t i = 0; i < ht->table_size; ++i) { for(size_t i = 0; i < ht->table_size; ++i) {
delete_all_elements_witharg((void**)(ht->table + i), hashtable_delete_callback, ht); delete_all_elements_witharg((void**)(ht->table + i), hashtable_delete_callback, ht);
} }
}
void hashtable_free(Hashtable *ht) {
if(!ht) {
return;
}
hashtable_unset_all(ht);
free(ht->table); free(ht->table);
free(ht); free(ht);
} }
@ -180,6 +188,28 @@ void hashtable_unset_string(Hashtable *ht, const char *key) {
hashtable_unset(ht, (void*)key); hashtable_unset(ht, (void*)key);
} }
/*
* Misc convenience functions
*/
void* hashtable_iter_free_data(void *key, void *data, void *arg) {
free(data);
return NULL;
}
void hashtable_print_stringkeys(Hashtable *ht) {
printf("------ %p:\n", (void*)ht);
for(size_t i = 0; i < ht->table_size; ++i) {
for(HashtableElement *e = ht->table[i]; e; e = e->next) {
printf("[HT %lu] %s (%lu): %p\n", (unsigned long)i, (char*)e->key, e->hash, e->data);
}
}
}
/*
* Misc convenience functions
*/
// #define HASHTABLE_TEST // #define HASHTABLE_TEST
#ifdef HASHTABLE_TEST #ifdef HASHTABLE_TEST

View file

@ -27,6 +27,7 @@ void hashtable_free(Hashtable *ht);
void* hashtable_get(Hashtable *ht, void *key); void* hashtable_get(Hashtable *ht, void *key);
void hashtable_set(Hashtable *ht, void *key, void *data); void hashtable_set(Hashtable *ht, void *key, void *data);
void hashtable_unset(Hashtable *ht, void *key); void hashtable_unset(Hashtable *ht, void *key);
void hashtable_unset_all(Hashtable *ht);
void* hashtable_foreach(Hashtable *ht, HTIterCallback callback, void *arg); void* hashtable_foreach(Hashtable *ht, HTIterCallback callback, void *arg);
bool hashtable_cmpfunc_string(void *str1, void *str2); bool hashtable_cmpfunc_string(void *str1, void *str2);
@ -39,6 +40,10 @@ void* hashtable_get_string(Hashtable *ht, const char *key);
void hashtable_set_string(Hashtable *ht, const char *key, void *data); void hashtable_set_string(Hashtable *ht, const char *key, void *data);
void hashtable_unset_string(Hashtable *ht, const char *key); void hashtable_unset_string(Hashtable *ht, const char *key);
void* hashtable_iter_free_data(void *key, void *data, void *arg);
int hashtable_test(void); int hashtable_test(void);
void hashtable_print_stringkeys(Hashtable *ht);
#endif #endif

View file

@ -142,6 +142,7 @@ int main(int argc, char **argv) {
video_init(); video_init();
printf("-- Video and OpenGL\n"); printf("-- Video and OpenGL\n");
init_resources();
draw_loading_screen(); draw_loading_screen();
gamepad_init(); gamepad_init();

View file

@ -12,14 +12,14 @@
#include "taisei_err.h" #include "taisei_err.h"
Animation *init_animation(char *filename) { Animation *init_animation(const char *filename) {
Animation *buf = create_element((void **)&resources.animations, sizeof(Animation)); Animation *buf = malloc(sizeof(Animation));
char *beg = strstr(filename, "gfx/") + 4; char *beg = strstr(filename, "gfx/") + 4;
char *end = strrchr(filename, '.'); char *end = strrchr(filename, '.');
int sz = end - beg + 1; int sz = end - beg + 1;
char *name = malloc(sz); char name[end - beg + 1];
strlcpy(name, beg, sz); strlcpy(name, beg, sz);
char* tok; char* tok;
@ -35,31 +35,28 @@ Animation *init_animation(char *filename) {
errx(-1, "init_animation():\n!- bad 'speed' in filename '%s'", name); errx(-1, "init_animation():\n!- bad 'speed' in filename '%s'", name);
buf->speed = atoi(tok); buf->speed = atoi(tok);
if(buf->speed == 0)
errx(-1, "animation speed of %s == 0. relativity?", name);
if((tok = strtok(NULL, "_")) == NULL) if((tok = strtok(NULL, "_")) == NULL)
errx(-1, "init_animation():\n!- bad 'name' in filename '%s'", name); errx(-1, "init_animation():\n!- bad 'name' in filename '%s'", name);
char refname[strlen(tok)+1];
buf->name = malloc(strlen(tok)+1); memset(refname, 0, strlen(tok)+1);
memset(buf->name, 0, strlen(tok)+1); strcpy(refname, tok);
strcpy(buf->name, tok);
buf->tex = load_texture(filename); buf->tex = load_texture(filename);
buf->w = buf->tex->w/buf->cols; buf->w = buf->tex->w/buf->cols;
buf->h = buf->tex->h/buf->rows; buf->h = buf->tex->h/buf->rows;
free(name); hashtable_set_string(resources.animations, refname, buf);
printf("-- initialized animation '%s'\n", buf->name);
printf("-- initialized animation '%s'\n", name);
return buf; return buf;
} }
Animation *get_ani(char *name) { Animation *get_ani(const char *name) {
Animation *a; Animation *res = hashtable_get_string(resources.animations, name);
Animation *res = NULL;
for(a = resources.animations; a; a = a->next) {
if(strcmp(a->name, name) == 0) {
res = a;
}
}
if(res == NULL) if(res == NULL)
errx(-1,"get_ani():\n!- cannot load animation '%s'", name); errx(-1,"get_ani():\n!- cannot load animation '%s'", name);
@ -67,16 +64,11 @@ Animation *get_ani(char *name) {
return res; return res;
} }
void delete_animation(void **anis, void *ani) {
free(((Animation *)ani)->name);
delete_element(anis, ani);
}
void delete_animations(void) { void delete_animations(void) {
delete_all_elements((void **)&resources.animations, delete_animation); resources_delete_and_unset_all(resources.animations, hashtable_iter_free_data, NULL);
} }
void draw_animation(float x, float y, int row, char *name) { void draw_animation(float x, float y, int row, const char *name) {
draw_animation_p(x, y, row, get_ani(name)); draw_animation_p(x, y, row, get_ani(name));
} }
@ -87,9 +79,6 @@ void draw_animation_p(float x, float y, int row, Animation *ani) {
float s = (float)ani->tex->w/ani->cols/ani->tex->truew; float s = (float)ani->tex->w/ani->cols/ani->tex->truew;
float t = ((float)ani->tex->h)/ani->tex->trueh/(float)ani->rows; float t = ((float)ani->tex->h)/ani->tex->trueh/(float)ani->rows;
if(ani->speed == 0)
errx(-1, "animation speed of %s == 0. relativity?", ani->name);
glPushMatrix(); glPushMatrix();
if(x || y) if(x || y)
glTranslatef(x,y,0); glTranslatef(x,y,0);

View file

@ -13,24 +13,21 @@
struct Animation; struct Animation;
typedef struct Animation { typedef struct Animation {
struct Animation *next;
struct Animation *prev;
int rows; int rows;
int cols; int cols;
int w,h; int w;
int h;
int speed; int speed;
char *name;
Texture *tex; Texture *tex;
} Animation; } Animation;
Animation *init_animation(char *filename); Animation *init_animation(const char *filename);
Animation *get_ani(char *name); Animation *get_ani(const char *name);
void delete_animations(void); void delete_animations(void);
void draw_animation(float x, float y, int row, char *name); void draw_animation(float x, float y, int row, const char *name);
void draw_animation_p(float x, float y, int row, Animation *ani); void draw_animation_p(float x, float y, int row, Animation *ani);
#endif #endif

View file

@ -114,7 +114,7 @@ void shutdown_sfx(void)
unload_mixer_if_needed(); unload_mixer_if_needed();
} }
Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) { Sound *load_sound_or_bgm(const char *filename, Hashtable *ht, sound_type_t type) {
Mix_Chunk *sound = NULL; Mix_Chunk *sound = NULL;
Mix_Music *music = NULL; Mix_Music *music = NULL;
@ -138,7 +138,7 @@ Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) {
errx(-1,"load_sound_or_bgm():\n!- incorrect sound type specified"); errx(-1,"load_sound_or_bgm():\n!- incorrect sound type specified");
} }
Sound *snd = create_element((void **)dest, sizeof(Sound)); Sound *snd = malloc(sizeof(Sound));
snd->type = type; snd->type = type;
if (sound) if (sound)
@ -154,26 +154,22 @@ Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) {
++beg; // skip '/' between last path element and file name ++beg; // skip '/' between last path element and file name
int sz = end - beg + 1; int sz = end - beg + 1;
snd->name = malloc(sz); char name[sz];
if (!snd->name) strlcpy(name, beg, sz);
errx(-1,"load_sound_or_bgm():\n!- failed to allocate memory for sound name (is it empty?)");
strlcpy(snd->name, beg, sz);
printf("-- loaded '%s' as %s '%s'\n", filename, ((type==ST_SOUND) ? "SFX" : "BGM"), snd->name); hashtable_set_string(ht, name, snd);
printf("-- loaded '%s' as %s '%s'\n", filename, ((type==ST_SOUND) ? "SFX" : "BGM"), name);
return snd; return snd;
} }
Sound *load_sound(char *filename) { Sound *load_sound(const char *filename) {
return load_sound_or_bgm(filename, &resources.sounds, ST_SOUND); return load_sound_or_bgm(filename, resources.sounds, ST_SOUND);
} }
Sound *get_snd(Sound *source, char *name) { Sound *get_snd(Hashtable *source, const char *name) {
Sound *s, *res = NULL; Sound *res = hashtable_get_string(resources.sounds, name);
for(s = source; s; s = s->next) {
if(strcmp(s->name, name) == 0)
res = s;
}
if(res == NULL) if(res == NULL)
warnx("get_snd():\n!- cannot find sound '%s'", name); warnx("get_snd():\n!- cannot find sound '%s'", name);
@ -181,7 +177,7 @@ Sound *get_snd(Sound *source, char *name) {
return res; return res;
} }
void play_sound_p(char *name, int unconditional) void play_sound_p(const char *name, int unconditional)
{ {
if(config_get_int(CONFIG_NO_AUDIO) || global.frameskip) return; if(config_get_int(CONFIG_NO_AUDIO) || global.frameskip) return;
@ -205,14 +201,21 @@ void set_sfx_volume(float gain)
Mix_Volume(-1, gain * MIX_MAX_VOLUME); Mix_Volume(-1, gain * MIX_MAX_VOLUME);
} }
void delete_sound(void **snds, void *snd) { #include <assert.h>
void* delete_sound(void *name, void *snd, void *arg) {
Sound *ssnd = (Sound *)snd; Sound *ssnd = (Sound *)snd;
free(ssnd->name);
if(ssnd->type == ST_MUSIC) Mix_FreeMusic(ssnd->music); if(ssnd->type == ST_MUSIC) {
else Mix_FreeChunk(ssnd->sound); Mix_FreeMusic(ssnd->music);
delete_element(snds, snd); } else if(ssnd->type == ST_SOUND) {
Mix_FreeChunk(ssnd->sound);
}
free(snd);
return NULL;
} }
void delete_sounds(void) { void delete_sounds(void) {
delete_all_elements((void **)&resources.sounds, delete_sound); resources_delete_and_unset_all(resources.sounds, delete_sound, NULL);
} }

View file

@ -8,6 +8,9 @@
#ifndef AUDIO_H #ifndef AUDIO_H
#define AUDIO_H #define AUDIO_H
#undef HAVE_MIXER
#define HAVE_MIXER
#ifdef HAVE_MIXER #ifdef HAVE_MIXER
#include <SDL_mixer.h> #include <SDL_mixer.h>
#else #else
@ -15,6 +18,8 @@ typedef void Mix_Chunk;
typedef void Mix_Music; typedef void Mix_Music;
#endif #endif
#include "hashtable.h"
#define SNDCHAN_COUNT 100 #define SNDCHAN_COUNT 100
typedef enum { typedef enum {
@ -25,29 +30,25 @@ typedef enum {
struct Sound; struct Sound;
typedef struct Sound { typedef struct Sound {
struct Sound *next;
struct Sound *prev;
int lastplayframe; int lastplayframe;
sound_type_t type; sound_type_t type;
union { union {
Mix_Chunk *sound; Mix_Chunk *sound;
Mix_Music *music; Mix_Music *music;
}; };
char *name;
} Sound; } Sound;
Sound *load_sound(char *filename); Sound *load_sound(const char *filename);
Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type); Sound *load_sound_or_bgm(const char *filename, Hashtable *ht, sound_type_t type);
#define play_sound(name) play_sound_p(name, 0); #define play_sound(name) play_sound_p(name, 0);
#define play_ui_sound(name) play_sound_p(name, 1); #define play_ui_sound(name) play_sound_p(name, 1);
void play_sound_p(char *name, int unconditional); void play_sound_p(const char *name, int unconditional);
Sound *get_snd(Sound *source, char *name); Sound *get_snd(Hashtable *source, const char *name);
void delete_sound(void **snds, void *snd); void* delete_sound(void *name, void *snd, void *arg);
void delete_sounds(void); void delete_sounds(void);
void set_sfx_volume(float gain); void set_sfx_volume(float gain);

View file

@ -2,24 +2,24 @@
#include <stdlib.h> #include <stdlib.h>
#include "audio.h" #include "audio.h"
Sound* load_sound(char *filename) { Sound* load_sound(const char *filename) {
return NULL; return NULL;
} }
Sound* load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) { Sound* load_sound_or_bgm(const char *filename, Hashtable *ht, sound_type_t type) {
return NULL; return NULL;
} }
void play_sound_p(char *name, int unconditional) { void play_sound_p(const char *name, int unconditional) {
return; return;
} }
Sound* get_snd(Sound *source, char *name) { Sound* get_snd(Hashtable *source, const char *name) {
return NULL; return NULL;
} }
void delete_sound(void **snds, void *snd) { void* delete_sound(void *name, void *snd, void *arg) {
return; return NULL;
} }
void delete_sounds(void) { void delete_sounds(void) {

View file

@ -65,17 +65,8 @@ void shutdown_bgm(void)
unload_mixer_if_needed(); unload_mixer_if_needed();
} }
char *get_bgm_desc(Bgm_desc *source, char *name) { char *get_bgm_desc(char *name) {
for(; source; source = source->next) return (char*)hashtable_get_string(resources.bgm_descriptions, name);
if(strcmp(source->name, name) == 0)
return source->value;
return NULL;
}
void delete_bgm_description(void **descs, void *desc) {
free(((Bgm_desc *)desc)->name);
free(((Bgm_desc *)desc)->value);
delete_element(descs, desc);
} }
void load_bgm_descriptions(const char *path) { void load_bgm_descriptions(const char *path) {
@ -105,31 +96,25 @@ void load_bgm_descriptions(const char *path) {
} }
*(rem++)='\0'; *(rem++)='\0';
Bgm_desc *desc = create_element((void **)&resources.bgm_descriptions, sizeof(Bgm_desc));
desc->name = NULL; char *value = malloc(strlen(rem) + 6);
stralloc(&desc->name, line); strcpy(value, "BGM: ");
desc->value = malloc(strlen(rem) + 6); strcat(value, rem);
if (!desc->name || !desc->value)
{ hashtable_set_string(resources.bgm_descriptions, line, value);
delete_bgm_description((void**)resources.bgm_descriptions, desc);
warnx("load_bgm_description():\n!- strdup() failed"); printf("Music %s is now known as \"%s\".\n", line, value);
continue;
}
strcpy(desc->value, "BGM: ");
strcat(desc->value, rem);
printf ("Music %s is now known as \"%s\".\n", desc->name, desc->value);
} }
fclose(fp); fclose(fp);
return; return;
} }
Sound *load_bgm(char *filename) { Sound *load_bgm(const char *filename) {
return load_sound_or_bgm(filename, &resources.music, ST_MUSIC); return load_sound_or_bgm(filename, resources.music, ST_MUSIC);
} }
void start_bgm(char *name) { void start_bgm(const char *name) {
if(config_get_int(CONFIG_NO_MUSIC)) return; if(config_get_int(CONFIG_NO_MUSIC)) return;
// start_bgm(NULL) or start_bgm("") would be equivalent to stop_bgm(). // start_bgm(NULL) or start_bgm("") would be equivalent to stop_bgm().
@ -164,7 +149,7 @@ void start_bgm(char *name) {
if(Mix_PlayMusic(current_bgm.data->music, -1) == -1) // Start playing otherwise if(Mix_PlayMusic(current_bgm.data->music, -1) == -1) // Start playing otherwise
printf("Failed starting BGM %s: %s.\n", current_bgm.name, Mix_GetError()); printf("Failed starting BGM %s: %s.\n", current_bgm.name, Mix_GetError());
// Support drawing BGM title in game loop (only when music changed!) // Support drawing BGM title in game loop (only when music changed!)
if ((current_bgm.title = get_bgm_desc(resources.bgm_descriptions, current_bgm.name)) != NULL) if ((current_bgm.title = get_bgm_desc(current_bgm.name)) != NULL)
{ {
current_bgm.started_at = global.frames; current_bgm.started_at = global.frames;
// Boss BGM title color may differ from the one at beginning of stage // Boss BGM title color may differ from the one at beginning of stage
@ -218,6 +203,6 @@ void set_bgm_volume(float gain)
} }
void delete_music(void) { void delete_music(void) {
delete_all_elements((void **)&resources.bgm_descriptions, delete_bgm_description); resources_delete_and_unset_all(resources.bgm_descriptions, hashtable_iter_free_data, NULL);
delete_all_elements((void **)&resources.music, delete_sound); resources_delete_and_unset_all(resources.music, delete_sound, NULL);
} }

View file

@ -10,14 +10,6 @@
#include "audio.h" #include "audio.h"
typedef struct Bgm_desc {
struct Bgm_desc *next;
struct Bgm_desc *prev;
char *name;
char *value;
} Bgm_desc;
struct current_bgm_t { struct current_bgm_t {
char *name; char *name;
char *title; char *title;
@ -28,9 +20,9 @@ struct current_bgm_t {
extern struct current_bgm_t current_bgm; extern struct current_bgm_t current_bgm;
Sound *load_bgm(char *filename); Sound *load_bgm(const char *filename);
void start_bgm(char *name); void start_bgm(const char *name);
void stop_bgm(void); void stop_bgm(void);
void continue_bgm(void); void continue_bgm(void);
void save_bgm(void); void save_bgm(void);

View file

@ -5,11 +5,11 @@
struct current_bgm_t current_bgm; struct current_bgm_t current_bgm;
Sound *load_bgm(char *filename) { Sound *load_bgm(const char *filename) {
return NULL; return NULL;
} }
void start_bgm(char *name) { void start_bgm(const char *name) {
return; return;
} }

View file

@ -13,7 +13,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
void parse_obj(char *filename, ObjFileData *data) { static void parse_obj(const char *filename, ObjFileData *data) {
FILE *fp = fopen(filename, "rb"); FILE *fp = fopen(filename, "rb");
char line[256]; char line[256];
@ -109,12 +109,12 @@ void parse_obj(char *filename, ObjFileData *data) {
fclose(fp); fclose(fp);
} }
static void bad_reference_error(char *filename, char *aux, int n) { static void bad_reference_error(const char *filename, const char *aux, int n) {
errx(-1, "load_model():\n!- OBJ file '%s': Index %d: bad %s index reference\n", filename, n, aux); errx(-1, "load_model():\n!- OBJ file '%s': Index %d: bad %s index reference\n", filename, n, aux);
} }
Model *load_model(char *filename) { Model *load_model(const char *filename) {
Model *m = create_element((void **)&resources.models, sizeof(Model)); Model *m = malloc(sizeof(Model));
ObjFileData data; ObjFileData data;
unsigned int i; unsigned int i;
@ -126,8 +126,8 @@ Model *load_model(char *filename) {
char *end = strrchr(filename, '.'); char *end = strrchr(filename, '.');
int sz = end - beg + 1; int sz = end - beg + 1;
m->name = malloc(sz); char name[sz];
strlcpy(m->name, beg, sz); strlcpy(name, beg, sz);
parse_obj(filename, &data); parse_obj(filename, &data);
@ -170,7 +170,9 @@ Model *load_model(char *filename) {
vbo_add_verts(&_vbo, verts, data.icount); vbo_add_verts(&_vbo, verts, data.icount);
printf("-- loaded '%s' as '%s'\n", filename, m->name); hashtable_set_string(resources.models, name, m);
printf("-- loaded '%s' as '%s'\n", filename, name);
free(verts); free(verts);
free(data.xs); free(data.xs);
@ -180,12 +182,8 @@ Model *load_model(char *filename) {
return m; return m;
} }
Model *get_model(char *name) { Model *get_model(const char *name) {
Model *m, *res = NULL; Model *res = hashtable_get_string(resources.models, name);
for(m = resources.models; m; m = m->next) {
if(strcmp(m->name, name) == 0)
res = m;
}
if(res == NULL) if(res == NULL)
errx(-1,"get_model():\n!- cannot load model '%s'", name); errx(-1,"get_model():\n!- cannot load model '%s'", name);
@ -215,17 +213,16 @@ void draw_model_p(Model *model) {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
} }
void draw_model(char *name) { void draw_model(const char *name) {
draw_model_p(get_model(name)); draw_model_p(get_model(name));
} }
void delete_model(void **models, void *model) { void* delete_model(void *name, void *model, void *arg) {
free(((Model *)model)->name);
free(((Model *)model)->indices); free(((Model *)model)->indices);
free(model);
delete_element(models, model); return NULL;
} }
void delete_models(void) { // Does not delete elements from the VBO, so doing this at runtime is leaking VBO space void delete_models(void) { // Does not delete elements from the VBO, so doing this at runtime is leaking VBO spac
delete_all_elements((void **)&resources.models, delete_model); resources_delete_and_unset_all(resources.models, delete_model, NULL);
} }

View file

@ -12,8 +12,7 @@
typedef int IVector[3]; typedef int IVector[3];
typedef struct ObjFileData ObjFileData; typedef struct ObjFileData {
struct ObjFileData {
Vector *xs; Vector *xs;
int xcount; int xcount;
@ -27,27 +26,19 @@ struct ObjFileData {
int icount; int icount;
int fverts; int fverts;
}; } ObjFileData;
typedef struct Model Model;
struct Model {
struct Model *next;
struct Model *prev;
char *name;
typedef struct Model {
unsigned int *indices; unsigned int *indices;
int icount; int icount;
int fverts; int fverts;
}; } Model;
Model *load_model(char *filename); Model *load_model(const char *filename);
Model *get_model(const char *name);
Model *get_model(char *name);
void draw_model_p(Model *model); void draw_model_p(Model *model);
void draw_model(char *name); void draw_model(const char *name);
void delete_models(void); // Does not delete elements from the VBO, so doing this at runtime is leaking VBO space void delete_models(void); // Does not delete elements from the VBO, so doing this at runtime is leaking VBO space
#endif #endif

View file

@ -76,14 +76,32 @@ static void resources_cfg_noshader_callback(ConfigIndex idx, ConfigValue v) {
} }
} }
static void init_hashtables(void) {
resources.textures = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.animations = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.sounds = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.music = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.shaders = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.models = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.bgm_descriptions = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
}
static void free_hashtables(void) {
hashtable_free(resources.textures);
hashtable_free(resources.animations);
hashtable_free(resources.sounds);
hashtable_free(resources.music);
hashtable_free(resources.shaders);
hashtable_free(resources.models);
hashtable_free(resources.bgm_descriptions);
}
void init_resources(void) {
init_hashtables();
config_set_callback(CONFIG_NO_SHADER, resources_cfg_noshader_callback);
}
void load_resources(void) { void load_resources(void) {
static bool callbacks_set_up = false;
if(!callbacks_set_up) {
config_set_callback(CONFIG_NO_SHADER, resources_cfg_noshader_callback);
callbacks_set_up = true;
}
printf("load_resources():\n"); printf("load_resources():\n");
char *path = malloc(strlen(get_prefix())+32); char *path = malloc(strlen(get_prefix())+32);
@ -177,6 +195,13 @@ void free_resources(void) {
printf("-- freeing shaders\n"); printf("-- freeing shaders\n");
delete_shaders(); delete_shaders();
} }
free_hashtables();
}
void resources_delete_and_unset_all(Hashtable *ht, HTIterCallback ifunc, void *arg) {
hashtable_foreach(ht, ifunc, arg);
hashtable_unset_all(ht);
} }
void draw_loading_screen(void) { void draw_loading_screen(void) {

View file

@ -17,9 +17,12 @@
#include "shader.h" #include "shader.h"
#include "font.h" #include "font.h"
#include "model.h" #include "model.h"
#include "hashtable.h"
typedef struct Resources Resources; typedef struct Resources Resources;
#define RES_HASHTABLE_SIZE 64
typedef enum ResourceState { typedef enum ResourceState {
RS_GfxLoaded = 1, RS_GfxLoaded = 1,
RS_SfxLoaded = 2, RS_SfxLoaded = 2,
@ -32,13 +35,13 @@ typedef enum ResourceState {
struct Resources { struct Resources {
ResourceState state; ResourceState state;
Texture *textures; Hashtable *textures;
Animation *animations; Hashtable *animations;
Sound *sounds; Hashtable *sounds;
Sound *music; Hashtable *music;
Shader *shaders; Hashtable *shaders;
Model *models; Hashtable *models;
Bgm_desc *bgm_descriptions; Hashtable *bgm_descriptions;
FBO fbg[2]; FBO fbg[2];
FBO fsec; FBO fsec;
@ -46,8 +49,12 @@ struct Resources {
extern Resources resources; extern Resources resources;
void init_resources(void);
void load_resources(void); void load_resources(void);
void free_resources(void); void free_resources(void);
void draw_loading_screen(void); void draw_loading_screen(void);
void resources_delete_and_unset_all(Hashtable *ht, HTIterCallback ifunc, void *arg);
#endif #endif

View file

@ -70,7 +70,7 @@ void print_program_info_log(GLuint program) {
} }
} }
char *read_all(char *filename, int *size) { char *read_all(const char *filename, int *size) {
char *text; char *text;
FILE *file = fopen(filename, "r"); FILE *file = fopen(filename, "r");
if(file == NULL) if(file == NULL)
@ -92,7 +92,7 @@ char *read_all(char *filename, int *size) {
return text; return text;
} }
char *copy_segment(char *text, char *delim, int *size) { char *copy_segment(const char *text, const char *delim, int *size) {
char *seg, *beg, *end; char *seg, *beg, *end;
beg = strstr(text, delim); beg = strstr(text, delim);
@ -111,7 +111,7 @@ char *copy_segment(char *text, char *delim, int *size) {
return seg; return seg;
} }
void load_shader_snippets(char *filename, char *prefix) { void load_shader_snippets(const char *filename, const char *prefix) {
int size, vhsize = 0, vfsize = 0, fhsize = 0, ffsize = 0, ssize, prefixlen; int size, vhsize = 0, vfsize = 0, fhsize = 0, ffsize = 0, ssize, prefixlen;
char *text, *vhead, *vfoot, *fhead, *ffoot; char *text, *vhead, *vfoot, *fhead, *ffoot;
char *sec, *name, *nend, *send; char *sec, *name, *nend, *send;
@ -204,7 +204,7 @@ void load_shader_snippets(char *filename, char *prefix) {
free(text); free(text);
} }
void load_shader_file(char *filename) { void load_shader_file(const char *filename) {
int size; int size;
char *text, *vtext, *ftext, *delim; char *text, *vtext, *ftext, *delim;
char *beg, *end, *name; char *beg, *end, *name;
@ -234,8 +234,8 @@ void load_shader_file(char *filename) {
free(text); free(text);
} }
void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *name, int nsize) { void load_shader(const char *vheader, const char *fheader, const char *vtext, const char *ftext, const char *name, int nsize) {
Shader *sha = create_element((void **)&resources.shaders, sizeof(Shader)); Shader *sha = malloc(sizeof(Shader));
GLuint vshaderobj; GLuint vshaderobj;
GLuint fshaderobj; GLuint fshaderobj;
@ -251,8 +251,8 @@ void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *n
fheader = ""; fheader = "";
} }
GLchar *v_sources[] = { vheader, vtext }; const GLchar *v_sources[] = { vheader, vtext };
GLchar *f_sources[] = { fheader, ftext }; const GLchar *f_sources[] = { fheader, ftext };
GLint lengths[] = { -1, -1 }; GLint lengths[] = { -1, -1 };
glShaderSource(vshaderobj, 2, (const GLchar**)v_sources, lengths); glShaderSource(vshaderobj, 2, (const GLchar**)v_sources, lengths);
@ -274,10 +274,9 @@ void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *n
print_program_info_log(sha->prog); print_program_info_log(sha->prog);
sha->name = malloc(nsize);
strlcpy(sha->name, name, nsize);
cache_uniforms(sha); cache_uniforms(sha);
hashtable_set_string(resources.shaders, name, sha);
} }
void cache_uniforms(Shader *sha) { void cache_uniforms(Shader *sha) {
@ -299,7 +298,7 @@ void cache_uniforms(Shader *sha) {
} }
} }
int uniloc(Shader *sha, char *name) { int uniloc(Shader *sha, const char *name) {
int i; int i;
for(i = 0; i < sha->unicount; i++) for(i = 0; i < sha->unicount; i++)
if(strcmp(sha->uniforms[i].name, name) == 0) if(strcmp(sha->uniforms[i].name, name) == 0)
@ -309,33 +308,24 @@ int uniloc(Shader *sha, char *name) {
} }
Shader *get_shader(const char *name) { Shader *get_shader(const char *name) {
Shader *s, *res = NULL;
if(config_get_int(CONFIG_NO_SHADER)) if(config_get_int(CONFIG_NO_SHADER))
return NULL; return NULL;
for(s = resources.shaders; s; s = s->next) { return hashtable_get_string(resources.shaders, name);
if(strcmp(s->name, name) == 0)
res = s;
}
return res;
} }
void delete_shader(void **shas, void *sha) { void* delete_shader(void *name, void *vsha, void *arg) {
free(((Shader *)sha)->name); Shader *sha = vsha;
glDeleteProgram(((Shader*)sha)->prog); glDeleteProgram((sha)->prog);
int i; for(int i = 0; i < sha->unicount; i++)
for(i = 0; i < ((Shader *)sha)->unicount; i++) free(sha->uniforms[i].name);
free(((Shader *)sha)->uniforms[i].name); free(sha->uniforms);
if(((Shader *)sha)->uniforms) free(sha);
free(((Shader *)sha)->uniforms); return NULL;
delete_element(shas, sha);
} }
void delete_shaders(void) { void delete_shaders(void) {
delete_all_elements((void **)&resources.shaders, delete_shader); resources_delete_and_unset_all(resources.shaders, delete_shader, NULL);
} }

View file

@ -25,22 +25,17 @@ typedef struct Uniform {
struct Shader; struct Shader;
typedef struct Shader { typedef struct Shader {
struct Shader *next;
struct Shader *prev;
char *name;
GLuint prog; GLuint prog;
int unicount; int unicount;
Uniform *uniforms; Uniform *uniforms;
} Shader; } Shader;
void load_shader_snippets(char *filename, char *prefix); void load_shader_snippets(const char *filename, const char *prefix);
void load_shader_file(char *filename); void load_shader_file(const char *filename);
void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *name, int nsize); void load_shader(const char *vheader, const char *fheader, const char *vtext, const char *ftext, const char *name, int nsize);
Shader *get_shader(const char *name); Shader *get_shader(const char *name);
void delete_shaders(void); void delete_shaders(void);
void cache_uniforms(Shader *sha); void cache_uniforms(Shader *sha);
int uniloc(Shader *sha, char *name); int uniloc(Shader *sha, const char *name);
#endif #endif

View file

@ -6,21 +6,17 @@
*/ */
#include <png.h> #include <png.h>
#include <assert.h>
#include "texture.h" #include "texture.h"
#include "resource.h" #include "resource.h"
#include "global.h" #include "global.h"
#include "paths/native.h" #include "paths/native.h"
#include "taisei_err.h" #include "taisei_err.h"
#include "list.h"
#include "vbo.h" #include "vbo.h"
Texture *get_tex(char *name) { Texture *get_tex(const char *name) {
Texture *t, *res = NULL; Texture *res = hashtable_get_string(resources.textures, name);
for(t = resources.textures; t; t = t->next) {
if(strcmp(t->name, name) == 0)
res = t;
}
if(res == NULL) if(res == NULL)
errx(-1,"get_tex():\n!- cannot load texture '%s'", name); errx(-1,"get_tex():\n!- cannot load texture '%s'", name);
@ -28,43 +24,44 @@ Texture *get_tex(char *name) {
return res; return res;
} }
Texture *prefix_get_tex(char *name, char *prefix) { Texture *prefix_get_tex(const char *name, const char *prefix) {
char *src; const char *src;
if((src = strrchr(name, '/'))) if((src = strrchr(name, '/')))
src++; src++;
else else
src = name; src = name;
char *buf = malloc(strlen(src) + strlen(prefix) + 1); char buf[strlen(src) + strlen(prefix) + 1];
strcpy(buf, prefix); strcpy(buf, prefix);
strcat(buf, src); strcat(buf, src);
Texture *tex = get_tex(buf); return get_tex(buf);
free(buf);
return tex;
} }
void delete_texture(void **texs, void *tex) { static void* delete_texture(void *name, void *tex, void *arg) {
Texture *t = (Texture *)tex; free_texture((Texture*)tex);
free(t->name); return NULL;
glDeleteTextures(1, &t->gltex);
delete_element((void **)texs, tex);
} }
void delete_textures(void) { void delete_textures(void) {
delete_all_elements((void **)&resources.textures, delete_texture); resources_delete_and_unset_all(resources.textures, delete_texture, NULL);
} }
Texture *load_texture(const char *filename) { Texture *load_texture(const char *filename) {
Texture *texture = hashtable_get_string(resources.textures, filename);
// FIXME: this is for the loading screen
if(texture) {
return texture;
}
SDL_Surface *surface = load_png(filename); SDL_Surface *surface = load_png(filename);
if(surface == NULL) if(surface == NULL)
errx(-1,"load_texture():\n!- cannot load '%s'", filename); errx(-1,"load_texture():\n!- cannot load '%s'", filename);
Texture *texture = create_element((void **)&resources.textures, sizeof(Texture)); texture = malloc(sizeof(Texture));
load_sdl_surf(surface, texture); load_sdl_surf(surface, texture);
free(surface->pixels); free(surface->pixels);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
@ -73,10 +70,12 @@ Texture *load_texture(const char *filename) {
char *end = strrchr(filename, '.'); char *end = strrchr(filename, '.');
int sz = end - beg + 1; int sz = end - beg + 1;
texture->name = malloc(sz); char name[sz];
strlcpy(texture->name, beg, sz); strlcpy(name, beg, sz);
printf("-- loaded '%s' as '%s'\n", filename, texture->name); hashtable_set_string(resources.textures, name, (void*)texture);
printf("-- loaded '%s' as '%s'\n", filename, name);
return texture; return texture;
} }
@ -188,7 +187,7 @@ void free_texture(Texture *tex) {
free(tex); free(tex);
} }
void draw_texture(float x, float y, char *name) { void draw_texture(float x, float y, const char *name) {
draw_texture_p(x, y, get_tex(name)); draw_texture_p(x, y, get_tex(name));
} }
@ -222,7 +221,7 @@ void draw_texture_p(float x, float y, Texture *tex) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
void fill_screen(float xoff, float yoff, float ratio, char *name) { void fill_screen(float xoff, float yoff, float ratio, const char *name) {
fill_screen_p(xoff, yoff, ratio, get_tex(name)); fill_screen_p(xoff, yoff, ratio, get_tex(name));
} }

View file

@ -15,32 +15,27 @@
typedef struct Texture Texture; typedef struct Texture Texture;
struct Texture { struct Texture {
Texture *next;
Texture *prev;
int w, h; int w, h;
int truew, trueh; int truew, trueh;
char *name;
GLuint gltex; GLuint gltex;
}; };
Texture *get_tex(char *name); Texture *get_tex(const char *name);
Texture *prefix_get_tex(char *name, char *prefix); Texture *prefix_get_tex(const char *name, const char *prefix);
SDL_Surface *load_png(const char *filename); SDL_Surface *load_png(const char *filename);
void delete_texture(void **texs, void *tex);
void delete_textures(void); void delete_textures(void);
Texture *load_texture(const char *filename); Texture *load_texture(const char *filename);
void load_sdl_surf(SDL_Surface *surface, Texture *texture); void load_sdl_surf(SDL_Surface *surface, Texture *texture);
void free_texture(Texture *tex); void free_texture(Texture *tex);
void draw_texture(float x, float y, char *name); void draw_texture(float x, float y, const char *name);
void draw_texture_p(float x, float y, Texture *tex); void draw_texture_p(float x, float y, Texture *tex);
void fill_screen(float xoff, float yoff, float ratio, char *name); void fill_screen(float xoff, float yoff, float ratio, const char *name);
void fill_screen_p(float xoff, float yoff, float ratio, Texture *tex); void fill_screen_p(float xoff, float yoff, float ratio, Texture *tex);
#endif #endif