Use hashtables for resource management
This commit is contained in:
parent
fdd4633e19
commit
18652576d6
19 changed files with 243 additions and 241 deletions
|
@ -12,6 +12,7 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct HashtableElement {
|
||||
void *next;
|
||||
|
@ -59,11 +60,18 @@ static void hashtable_delete_callback(void **vlist, void *velem, void *vht) {
|
|||
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) {
|
||||
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);
|
||||
}
|
||||
|
@ -180,6 +188,28 @@ void hashtable_unset_string(Hashtable *ht, const char *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
|
||||
|
||||
#ifdef HASHTABLE_TEST
|
||||
|
|
|
@ -27,6 +27,7 @@ void hashtable_free(Hashtable *ht);
|
|||
void* hashtable_get(Hashtable *ht, void *key);
|
||||
void hashtable_set(Hashtable *ht, void *key, void *data);
|
||||
void hashtable_unset(Hashtable *ht, void *key);
|
||||
void hashtable_unset_all(Hashtable *ht);
|
||||
void* hashtable_foreach(Hashtable *ht, HTIterCallback callback, void *arg);
|
||||
|
||||
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_unset_string(Hashtable *ht, const char *key);
|
||||
|
||||
void* hashtable_iter_free_data(void *key, void *data, void *arg);
|
||||
|
||||
int hashtable_test(void);
|
||||
|
||||
void hashtable_print_stringkeys(Hashtable *ht);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -142,6 +142,7 @@ int main(int argc, char **argv) {
|
|||
video_init();
|
||||
printf("-- Video and OpenGL\n");
|
||||
|
||||
init_resources();
|
||||
draw_loading_screen();
|
||||
|
||||
gamepad_init();
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
|
||||
#include "taisei_err.h"
|
||||
|
||||
Animation *init_animation(char *filename) {
|
||||
Animation *buf = create_element((void **)&resources.animations, sizeof(Animation));
|
||||
Animation *init_animation(const char *filename) {
|
||||
Animation *buf = malloc(sizeof(Animation));
|
||||
|
||||
char *beg = strstr(filename, "gfx/") + 4;
|
||||
char *end = strrchr(filename, '.');
|
||||
|
||||
int sz = end - beg + 1;
|
||||
char *name = malloc(sz);
|
||||
char name[end - beg + 1];
|
||||
strlcpy(name, beg, sz);
|
||||
|
||||
char* tok;
|
||||
|
@ -35,31 +35,28 @@ Animation *init_animation(char *filename) {
|
|||
errx(-1, "init_animation():\n!- bad 'speed' in filename '%s'", name);
|
||||
buf->speed = atoi(tok);
|
||||
|
||||
if(buf->speed == 0)
|
||||
errx(-1, "animation speed of %s == 0. relativity?", name);
|
||||
|
||||
if((tok = strtok(NULL, "_")) == NULL)
|
||||
errx(-1, "init_animation():\n!- bad 'name' in filename '%s'", name);
|
||||
|
||||
|
||||
buf->name = malloc(strlen(tok)+1);
|
||||
memset(buf->name, 0, strlen(tok)+1);
|
||||
strcpy(buf->name, tok);
|
||||
char refname[strlen(tok)+1];
|
||||
memset(refname, 0, strlen(tok)+1);
|
||||
strcpy(refname, tok);
|
||||
|
||||
buf->tex = load_texture(filename);
|
||||
buf->w = buf->tex->w/buf->cols;
|
||||
buf->h = buf->tex->h/buf->rows;
|
||||
|
||||
free(name);
|
||||
printf("-- initialized animation '%s'\n", buf->name);
|
||||
hashtable_set_string(resources.animations, refname, buf);
|
||||
|
||||
printf("-- initialized animation '%s'\n", name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
Animation *get_ani(char *name) {
|
||||
Animation *a;
|
||||
Animation *res = NULL;
|
||||
for(a = resources.animations; a; a = a->next) {
|
||||
if(strcmp(a->name, name) == 0) {
|
||||
res = a;
|
||||
}
|
||||
}
|
||||
Animation *get_ani(const char *name) {
|
||||
Animation *res = hashtable_get_string(resources.animations, name);
|
||||
|
||||
if(res == NULL)
|
||||
errx(-1,"get_ani():\n!- cannot load animation '%s'", name);
|
||||
|
@ -67,16 +64,11 @@ Animation *get_ani(char *name) {
|
|||
return res;
|
||||
}
|
||||
|
||||
void delete_animation(void **anis, void *ani) {
|
||||
free(((Animation *)ani)->name);
|
||||
delete_element(anis, ani);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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 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();
|
||||
if(x || y)
|
||||
glTranslatef(x,y,0);
|
||||
|
|
|
@ -13,24 +13,21 @@
|
|||
struct Animation;
|
||||
|
||||
typedef struct Animation {
|
||||
struct Animation *next;
|
||||
struct Animation *prev;
|
||||
|
||||
int rows;
|
||||
int cols;
|
||||
|
||||
int w,h;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
int speed;
|
||||
|
||||
char *name;
|
||||
Texture *tex;
|
||||
} Animation;
|
||||
|
||||
Animation *init_animation(char *filename);
|
||||
Animation *get_ani(char *name);
|
||||
Animation *init_animation(const char *filename);
|
||||
Animation *get_ani(const char *name);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -114,7 +114,7 @@ void shutdown_sfx(void)
|
|||
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_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");
|
||||
}
|
||||
|
||||
Sound *snd = create_element((void **)dest, sizeof(Sound));
|
||||
Sound *snd = malloc(sizeof(Sound));
|
||||
|
||||
snd->type = type;
|
||||
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
|
||||
int sz = end - beg + 1;
|
||||
snd->name = malloc(sz);
|
||||
if (!snd->name)
|
||||
errx(-1,"load_sound_or_bgm():\n!- failed to allocate memory for sound name (is it empty?)");
|
||||
strlcpy(snd->name, beg, sz);
|
||||
char name[sz];
|
||||
strlcpy(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;
|
||||
}
|
||||
|
||||
Sound *load_sound(char *filename) {
|
||||
return load_sound_or_bgm(filename, &resources.sounds, ST_SOUND);
|
||||
Sound *load_sound(const char *filename) {
|
||||
return load_sound_or_bgm(filename, resources.sounds, ST_SOUND);
|
||||
}
|
||||
|
||||
Sound *get_snd(Sound *source, char *name) {
|
||||
Sound *s, *res = NULL;
|
||||
for(s = source; s; s = s->next) {
|
||||
if(strcmp(s->name, name) == 0)
|
||||
res = s;
|
||||
}
|
||||
Sound *get_snd(Hashtable *source, const char *name) {
|
||||
Sound *res = hashtable_get_string(resources.sounds, name);
|
||||
|
||||
if(res == NULL)
|
||||
warnx("get_snd():\n!- cannot find sound '%s'", name);
|
||||
|
@ -181,7 +177,7 @@ Sound *get_snd(Sound *source, char *name) {
|
|||
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;
|
||||
|
||||
|
@ -205,14 +201,21 @@ void set_sfx_volume(float gain)
|
|||
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;
|
||||
free(ssnd->name);
|
||||
if(ssnd->type == ST_MUSIC) Mix_FreeMusic(ssnd->music);
|
||||
else Mix_FreeChunk(ssnd->sound);
|
||||
delete_element(snds, snd);
|
||||
|
||||
if(ssnd->type == ST_MUSIC) {
|
||||
Mix_FreeMusic(ssnd->music);
|
||||
} else if(ssnd->type == ST_SOUND) {
|
||||
Mix_FreeChunk(ssnd->sound);
|
||||
}
|
||||
|
||||
free(snd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_sounds(void) {
|
||||
delete_all_elements((void **)&resources.sounds, delete_sound);
|
||||
resources_delete_and_unset_all(resources.sounds, delete_sound, NULL);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
#undef HAVE_MIXER
|
||||
#define HAVE_MIXER
|
||||
|
||||
#ifdef HAVE_MIXER
|
||||
#include <SDL_mixer.h>
|
||||
#else
|
||||
|
@ -15,6 +18,8 @@ typedef void Mix_Chunk;
|
|||
typedef void Mix_Music;
|
||||
#endif
|
||||
|
||||
#include "hashtable.h"
|
||||
|
||||
#define SNDCHAN_COUNT 100
|
||||
|
||||
typedef enum {
|
||||
|
@ -25,29 +30,25 @@ typedef enum {
|
|||
struct Sound;
|
||||
|
||||
typedef struct Sound {
|
||||
struct Sound *next;
|
||||
struct Sound *prev;
|
||||
|
||||
int lastplayframe;
|
||||
sound_type_t type;
|
||||
union {
|
||||
Mix_Chunk *sound;
|
||||
Mix_Music *music;
|
||||
};
|
||||
char *name;
|
||||
} Sound;
|
||||
|
||||
Sound *load_sound(char *filename);
|
||||
Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type);
|
||||
Sound *load_sound(const char *filename);
|
||||
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_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 set_sfx_volume(float gain);
|
||||
|
|
|
@ -2,24 +2,24 @@
|
|||
#include <stdlib.h>
|
||||
#include "audio.h"
|
||||
|
||||
Sound* load_sound(char *filename) {
|
||||
Sound* load_sound(const char *filename) {
|
||||
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;
|
||||
}
|
||||
|
||||
void play_sound_p(char *name, int unconditional) {
|
||||
void play_sound_p(const char *name, int unconditional) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sound* get_snd(Sound *source, char *name) {
|
||||
Sound* get_snd(Hashtable *source, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_sound(void **snds, void *snd) {
|
||||
return;
|
||||
void* delete_sound(void *name, void *snd, void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_sounds(void) {
|
||||
|
|
|
@ -65,17 +65,8 @@ void shutdown_bgm(void)
|
|||
unload_mixer_if_needed();
|
||||
}
|
||||
|
||||
char *get_bgm_desc(Bgm_desc *source, char *name) {
|
||||
for(; source; source = source->next)
|
||||
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);
|
||||
char *get_bgm_desc(char *name) {
|
||||
return (char*)hashtable_get_string(resources.bgm_descriptions, name);
|
||||
}
|
||||
|
||||
void load_bgm_descriptions(const char *path) {
|
||||
|
@ -105,31 +96,25 @@ void load_bgm_descriptions(const char *path) {
|
|||
}
|
||||
|
||||
*(rem++)='\0';
|
||||
Bgm_desc *desc = create_element((void **)&resources.bgm_descriptions, sizeof(Bgm_desc));
|
||||
|
||||
desc->name = NULL;
|
||||
stralloc(&desc->name, line);
|
||||
desc->value = malloc(strlen(rem) + 6);
|
||||
if (!desc->name || !desc->value)
|
||||
{
|
||||
delete_bgm_description((void**)resources.bgm_descriptions, desc);
|
||||
warnx("load_bgm_description():\n!- strdup() failed");
|
||||
continue;
|
||||
}
|
||||
strcpy(desc->value, "BGM: ");
|
||||
strcat(desc->value, rem);
|
||||
printf ("Music %s is now known as \"%s\".\n", desc->name, desc->value);
|
||||
char *value = malloc(strlen(rem) + 6);
|
||||
strcpy(value, "BGM: ");
|
||||
strcat(value, rem);
|
||||
|
||||
hashtable_set_string(resources.bgm_descriptions, line, value);
|
||||
|
||||
printf("Music %s is now known as \"%s\".\n", line, value);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
Sound *load_bgm(char *filename) {
|
||||
return load_sound_or_bgm(filename, &resources.music, ST_MUSIC);
|
||||
Sound *load_bgm(const char *filename) {
|
||||
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;
|
||||
|
||||
// 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
|
||||
printf("Failed starting BGM %s: %s.\n", current_bgm.name, Mix_GetError());
|
||||
// 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;
|
||||
// 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) {
|
||||
delete_all_elements((void **)&resources.bgm_descriptions, delete_bgm_description);
|
||||
delete_all_elements((void **)&resources.music, delete_sound);
|
||||
resources_delete_and_unset_all(resources.bgm_descriptions, hashtable_iter_free_data, NULL);
|
||||
resources_delete_and_unset_all(resources.music, delete_sound, NULL);
|
||||
}
|
||||
|
|
|
@ -10,14 +10,6 @@
|
|||
|
||||
#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 {
|
||||
char *name;
|
||||
char *title;
|
||||
|
@ -28,9 +20,9 @@ struct current_bgm_t {
|
|||
|
||||
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 continue_bgm(void);
|
||||
void save_bgm(void);
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
struct current_bgm_t current_bgm;
|
||||
|
||||
Sound *load_bgm(char *filename) {
|
||||
Sound *load_bgm(const char *filename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void start_bgm(char *name) {
|
||||
void start_bgm(const char *name) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <string.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");
|
||||
|
||||
char line[256];
|
||||
|
@ -109,12 +109,12 @@ void parse_obj(char *filename, ObjFileData *data) {
|
|||
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);
|
||||
}
|
||||
|
||||
Model *load_model(char *filename) {
|
||||
Model *m = create_element((void **)&resources.models, sizeof(Model));
|
||||
Model *load_model(const char *filename) {
|
||||
Model *m = malloc(sizeof(Model));
|
||||
|
||||
ObjFileData data;
|
||||
unsigned int i;
|
||||
|
@ -126,8 +126,8 @@ Model *load_model(char *filename) {
|
|||
char *end = strrchr(filename, '.');
|
||||
|
||||
int sz = end - beg + 1;
|
||||
m->name = malloc(sz);
|
||||
strlcpy(m->name, beg, sz);
|
||||
char name[sz];
|
||||
strlcpy(name, beg, sz);
|
||||
|
||||
parse_obj(filename, &data);
|
||||
|
||||
|
@ -170,7 +170,9 @@ Model *load_model(char *filename) {
|
|||
|
||||
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(data.xs);
|
||||
|
@ -180,12 +182,8 @@ Model *load_model(char *filename) {
|
|||
return m;
|
||||
}
|
||||
|
||||
Model *get_model(char *name) {
|
||||
Model *m, *res = NULL;
|
||||
for(m = resources.models; m; m = m->next) {
|
||||
if(strcmp(m->name, name) == 0)
|
||||
res = m;
|
||||
}
|
||||
Model *get_model(const char *name) {
|
||||
Model *res = hashtable_get_string(resources.models, name);
|
||||
|
||||
if(res == NULL)
|
||||
errx(-1,"get_model():\n!- cannot load model '%s'", name);
|
||||
|
@ -215,17 +213,16 @@ void draw_model_p(Model *model) {
|
|||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void draw_model(char *name) {
|
||||
void draw_model(const char *name) {
|
||||
draw_model_p(get_model(name));
|
||||
}
|
||||
|
||||
void delete_model(void **models, void *model) {
|
||||
free(((Model *)model)->name);
|
||||
void* delete_model(void *name, void *model, void *arg) {
|
||||
free(((Model *)model)->indices);
|
||||
|
||||
delete_element(models, model);
|
||||
free(model);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_models(void) { // Does not delete elements from the VBO, so doing this at runtime is leaking VBO space
|
||||
delete_all_elements((void **)&resources.models, delete_model);
|
||||
void delete_models(void) { // Does not delete elements from the VBO, so doing this at runtime is leaking VBO spac
|
||||
resources_delete_and_unset_all(resources.models, delete_model, NULL);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
|
||||
typedef int IVector[3];
|
||||
|
||||
typedef struct ObjFileData ObjFileData;
|
||||
struct ObjFileData {
|
||||
typedef struct ObjFileData {
|
||||
Vector *xs;
|
||||
int xcount;
|
||||
|
||||
|
@ -27,27 +26,19 @@ struct ObjFileData {
|
|||
int icount;
|
||||
|
||||
int fverts;
|
||||
};
|
||||
|
||||
typedef struct Model Model;
|
||||
struct Model {
|
||||
struct Model *next;
|
||||
struct Model *prev;
|
||||
|
||||
char *name;
|
||||
} ObjFileData;
|
||||
|
||||
typedef struct Model {
|
||||
unsigned int *indices;
|
||||
int icount;
|
||||
|
||||
int fverts;
|
||||
};
|
||||
} Model;
|
||||
|
||||
Model *load_model(char *filename);
|
||||
|
||||
Model *get_model(char *name);
|
||||
Model *load_model(const char *filename);
|
||||
Model *get_model(const char *name);
|
||||
|
||||
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
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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) {
|
||||
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");
|
||||
|
||||
char *path = malloc(strlen(get_prefix())+32);
|
||||
|
@ -177,6 +195,13 @@ void free_resources(void) {
|
|||
printf("-- freeing shaders\n");
|
||||
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) {
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
#include "shader.h"
|
||||
#include "font.h"
|
||||
#include "model.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
typedef struct Resources Resources;
|
||||
|
||||
#define RES_HASHTABLE_SIZE 64
|
||||
|
||||
typedef enum ResourceState {
|
||||
RS_GfxLoaded = 1,
|
||||
RS_SfxLoaded = 2,
|
||||
|
@ -32,13 +35,13 @@ typedef enum ResourceState {
|
|||
struct Resources {
|
||||
ResourceState state;
|
||||
|
||||
Texture *textures;
|
||||
Animation *animations;
|
||||
Sound *sounds;
|
||||
Sound *music;
|
||||
Shader *shaders;
|
||||
Model *models;
|
||||
Bgm_desc *bgm_descriptions;
|
||||
Hashtable *textures;
|
||||
Hashtable *animations;
|
||||
Hashtable *sounds;
|
||||
Hashtable *music;
|
||||
Hashtable *shaders;
|
||||
Hashtable *models;
|
||||
Hashtable *bgm_descriptions;
|
||||
|
||||
FBO fbg[2];
|
||||
FBO fsec;
|
||||
|
@ -46,8 +49,12 @@ struct Resources {
|
|||
|
||||
extern Resources resources;
|
||||
|
||||
void init_resources(void);
|
||||
void load_resources(void);
|
||||
void free_resources(void);
|
||||
|
||||
void draw_loading_screen(void);
|
||||
|
||||
void resources_delete_and_unset_all(Hashtable *ht, HTIterCallback ifunc, void *arg);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
FILE *file = fopen(filename, "r");
|
||||
if(file == NULL)
|
||||
|
@ -92,7 +92,7 @@ char *read_all(char *filename, int *size) {
|
|||
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;
|
||||
|
||||
beg = strstr(text, delim);
|
||||
|
@ -111,7 +111,7 @@ char *copy_segment(char *text, char *delim, int *size) {
|
|||
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;
|
||||
char *text, *vhead, *vfoot, *fhead, *ffoot;
|
||||
char *sec, *name, *nend, *send;
|
||||
|
@ -204,7 +204,7 @@ void load_shader_snippets(char *filename, char *prefix) {
|
|||
free(text);
|
||||
}
|
||||
|
||||
void load_shader_file(char *filename) {
|
||||
void load_shader_file(const char *filename) {
|
||||
int size;
|
||||
char *text, *vtext, *ftext, *delim;
|
||||
char *beg, *end, *name;
|
||||
|
@ -234,8 +234,8 @@ void load_shader_file(char *filename) {
|
|||
free(text);
|
||||
}
|
||||
|
||||
void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *name, int nsize) {
|
||||
Shader *sha = create_element((void **)&resources.shaders, sizeof(Shader));
|
||||
void load_shader(const char *vheader, const char *fheader, const char *vtext, const char *ftext, const char *name, int nsize) {
|
||||
Shader *sha = malloc(sizeof(Shader));
|
||||
GLuint vshaderobj;
|
||||
GLuint fshaderobj;
|
||||
|
||||
|
@ -251,8 +251,8 @@ void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *n
|
|||
fheader = "";
|
||||
}
|
||||
|
||||
GLchar *v_sources[] = { vheader, vtext };
|
||||
GLchar *f_sources[] = { fheader, ftext };
|
||||
const GLchar *v_sources[] = { vheader, vtext };
|
||||
const GLchar *f_sources[] = { fheader, ftext };
|
||||
GLint lengths[] = { -1, -1 };
|
||||
|
||||
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);
|
||||
|
||||
sha->name = malloc(nsize);
|
||||
strlcpy(sha->name, name, nsize);
|
||||
|
||||
cache_uniforms(sha);
|
||||
|
||||
hashtable_set_string(resources.shaders, name, 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;
|
||||
for(i = 0; i < sha->unicount; i++)
|
||||
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 *s, *res = NULL;
|
||||
|
||||
if(config_get_int(CONFIG_NO_SHADER))
|
||||
return NULL;
|
||||
|
||||
for(s = resources.shaders; s; s = s->next) {
|
||||
if(strcmp(s->name, name) == 0)
|
||||
res = s;
|
||||
}
|
||||
|
||||
return res;
|
||||
return hashtable_get_string(resources.shaders, name);
|
||||
}
|
||||
|
||||
void delete_shader(void **shas, void *sha) {
|
||||
free(((Shader *)sha)->name);
|
||||
glDeleteProgram(((Shader*)sha)->prog);
|
||||
void* delete_shader(void *name, void *vsha, void *arg) {
|
||||
Shader *sha = vsha;
|
||||
glDeleteProgram((sha)->prog);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < ((Shader *)sha)->unicount; i++)
|
||||
free(((Shader *)sha)->uniforms[i].name);
|
||||
for(int i = 0; i < sha->unicount; i++)
|
||||
free(sha->uniforms[i].name);
|
||||
free(sha->uniforms);
|
||||
|
||||
if(((Shader *)sha)->uniforms)
|
||||
free(((Shader *)sha)->uniforms);
|
||||
|
||||
delete_element(shas, sha);
|
||||
free(sha);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_shaders(void) {
|
||||
delete_all_elements((void **)&resources.shaders, delete_shader);
|
||||
resources_delete_and_unset_all(resources.shaders, delete_shader, NULL);
|
||||
}
|
||||
|
|
|
@ -25,22 +25,17 @@ typedef struct Uniform {
|
|||
|
||||
struct Shader;
|
||||
typedef struct Shader {
|
||||
struct Shader *next;
|
||||
struct Shader *prev;
|
||||
|
||||
char *name;
|
||||
GLuint prog;
|
||||
|
||||
int unicount;
|
||||
Uniform *uniforms;
|
||||
} Shader;
|
||||
|
||||
void load_shader_snippets(char *filename, char *prefix);
|
||||
void load_shader_file(char *filename);
|
||||
void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *name, int nsize);
|
||||
void load_shader_snippets(const char *filename, const char *prefix);
|
||||
void load_shader_file(const char *filename);
|
||||
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);
|
||||
void delete_shaders(void);
|
||||
|
||||
void cache_uniforms(Shader *sha);
|
||||
int uniloc(Shader *sha, char *name);
|
||||
int uniloc(Shader *sha, const char *name);
|
||||
#endif
|
||||
|
|
|
@ -6,21 +6,17 @@
|
|||
*/
|
||||
|
||||
#include <png.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "texture.h"
|
||||
#include "resource.h"
|
||||
#include "global.h"
|
||||
#include "paths/native.h"
|
||||
#include "taisei_err.h"
|
||||
#include "list.h"
|
||||
#include "vbo.h"
|
||||
|
||||
Texture *get_tex(char *name) {
|
||||
Texture *t, *res = NULL;
|
||||
for(t = resources.textures; t; t = t->next) {
|
||||
if(strcmp(t->name, name) == 0)
|
||||
res = t;
|
||||
}
|
||||
Texture *get_tex(const char *name) {
|
||||
Texture *res = hashtable_get_string(resources.textures, name);
|
||||
|
||||
if(res == NULL)
|
||||
errx(-1,"get_tex():\n!- cannot load texture '%s'", name);
|
||||
|
@ -28,43 +24,44 @@ Texture *get_tex(char *name) {
|
|||
return res;
|
||||
}
|
||||
|
||||
Texture *prefix_get_tex(char *name, char *prefix) {
|
||||
char *src;
|
||||
Texture *prefix_get_tex(const char *name, const char *prefix) {
|
||||
const char *src;
|
||||
|
||||
if((src = strrchr(name, '/')))
|
||||
src++;
|
||||
else
|
||||
src = name;
|
||||
|
||||
char *buf = malloc(strlen(src) + strlen(prefix) + 1);
|
||||
char buf[strlen(src) + strlen(prefix) + 1];
|
||||
strcpy(buf, prefix);
|
||||
strcat(buf, src);
|
||||
|
||||
Texture *tex = get_tex(buf);
|
||||
free(buf);
|
||||
|
||||
return tex;
|
||||
return get_tex(buf);
|
||||
}
|
||||
|
||||
void delete_texture(void **texs, void *tex) {
|
||||
Texture *t = (Texture *)tex;
|
||||
free(t->name);
|
||||
glDeleteTextures(1, &t->gltex);
|
||||
|
||||
delete_element((void **)texs, tex);
|
||||
static void* delete_texture(void *name, void *tex, void *arg) {
|
||||
free_texture((Texture*)tex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 *texture = hashtable_get_string(resources.textures, filename);
|
||||
|
||||
// FIXME: this is for the loading screen
|
||||
if(texture) {
|
||||
return texture;
|
||||
}
|
||||
|
||||
SDL_Surface *surface = load_png(filename);
|
||||
|
||||
if(surface == NULL)
|
||||
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);
|
||||
free(surface->pixels);
|
||||
SDL_FreeSurface(surface);
|
||||
|
@ -73,10 +70,12 @@ Texture *load_texture(const char *filename) {
|
|||
char *end = strrchr(filename, '.');
|
||||
|
||||
int sz = end - beg + 1;
|
||||
texture->name = malloc(sz);
|
||||
strlcpy(texture->name, beg, sz);
|
||||
char name[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;
|
||||
}
|
||||
|
@ -188,7 +187,7 @@ void free_texture(Texture *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));
|
||||
}
|
||||
|
||||
|
@ -222,7 +221,7 @@ void draw_texture_p(float x, float y, Texture *tex) {
|
|||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -15,32 +15,27 @@
|
|||
typedef struct Texture Texture;
|
||||
|
||||
struct Texture {
|
||||
Texture *next;
|
||||
Texture *prev;
|
||||
|
||||
int w, h;
|
||||
int truew, trueh;
|
||||
|
||||
char *name;
|
||||
GLuint gltex;
|
||||
};
|
||||
|
||||
Texture *get_tex(char *name);
|
||||
Texture *prefix_get_tex(char *name, char *prefix);
|
||||
Texture *get_tex(const char *name);
|
||||
Texture *prefix_get_tex(const char *name, const char *prefix);
|
||||
|
||||
SDL_Surface *load_png(const char *filename);
|
||||
|
||||
void delete_texture(void **texs, void *tex);
|
||||
void delete_textures(void);
|
||||
|
||||
Texture *load_texture(const char *filename);
|
||||
void load_sdl_surf(SDL_Surface *surface, Texture *texture);
|
||||
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 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);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue