diff --git a/include/dungeon/dungeon.h b/include/dungeon/dungeon.h index f8214fd..070c765 100644 --- a/include/dungeon/dungeon.h +++ b/include/dungeon/dungeon.h @@ -67,8 +67,7 @@ struct dungeon_context { GLuint depth_buffer; }; -struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int surface); -void dungeon_context_free(struct dungeon_context *ctx); +struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int width, int height); bool dungeon_load(struct dungeon_context *ctx, int num); void dungeon_set_camera(int surface, float x, float y, float z, float angle, float angle_p); void dungeon_set_walked(int surface, int x, int y, int z, int flag); diff --git a/include/plugin.h b/include/plugin.h index 26dcecf..baf6d64 100644 --- a/include/plugin.h +++ b/include/plugin.h @@ -24,6 +24,7 @@ struct sact_sprite; struct draw_plugin { const char *name; + void (*free)(struct draw_plugin *); void (*update)(struct sact_sprite *); void (*render)(struct sact_sprite *); // for custom sprites cJSON *(*to_json)(struct sact_sprite *, bool); diff --git a/src/dungeon/dungeon.c b/src/dungeon/dungeon.c index 7063b45..d7dc2e3 100644 --- a/src/dungeon/dungeon.c +++ b/src/dungeon/dungeon.c @@ -47,39 +47,42 @@ #define M_PI (3.14159265358979323846) #endif +static const char plugin_name[] = "DrawDungeon"; + static void dungeon_render(struct sact_sprite *sp); static cJSON *dungeon_to_json(struct sact_sprite *sp, bool verbose); +static void dungeon_context_free(struct draw_plugin *plugin); -struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int surface) +struct dungeon_context *dungeon_get_context(int surface) +{ + struct sact_sprite *sp = sact_try_get_sprite(surface); + if (!sp || !sp->plugin || sp->plugin->name != plugin_name) + return NULL; + return (struct dungeon_context *)sp->plugin; +} + +struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int width, int height) { struct dungeon_context *ctx = xcalloc(1, sizeof(struct dungeon_context)); - ctx->plugin.name = "DrawDungeon"; + ctx->plugin.name = plugin_name; + ctx->plugin.free = dungeon_context_free; ctx->plugin.update = dungeon_render; ctx->plugin.to_json = dungeon_to_json; ctx->version = version; - ctx->surface = surface; - struct sact_sprite *sp = sact_get_sprite(ctx->surface); - if (!sp) - VM_ERROR("DrawDungeon.Init: invalid surface %d", surface); - sprite_bind_plugin(sp, &ctx->plugin); - - gfx_init_texture_blank(&ctx->texture, sp->rect.w, sp->rect.h); + gfx_init_texture_blank(&ctx->texture, width, height); glGenRenderbuffers(1, &ctx->depth_buffer); glBindRenderbuffer(GL_RENDERBUFFER, ctx->depth_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, sp->rect.w, sp->rect.h); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); glBindRenderbuffer(GL_RENDERBUFFER, 0); ctx->map = dungeon_map_create(version); return ctx; } -void dungeon_context_free(struct dungeon_context *ctx) +static void dungeon_context_free(struct draw_plugin *plugin) { - struct sact_sprite *sp = sact_try_get_sprite(ctx->surface); - if (sp) - sprite_bind_plugin(sp, NULL); - + struct dungeon_context *ctx = (struct dungeon_context *)plugin; if (ctx->dgn) dgn_free(ctx->dgn); if (ctx->dtx) diff --git a/src/hll/DrawDungeon.c b/src/hll/DrawDungeon.c index e48211f..25164ae 100644 --- a/src/hll/DrawDungeon.c +++ b/src/hll/DrawDungeon.c @@ -25,25 +25,18 @@ #include "dungeon/map.h" #include "dungeon/renderer.h" #include "dungeon/tes.h" +#include "sact.h" #include "hll.h" -static struct dungeon_context *current_context = NULL; - static int dungeon_init(enum draw_dungeon_version version, int surface) { - if (current_context) - VM_ERROR("Dungeon is already associated with surface %d", current_context->surface); - if (surface < 0) + struct sact_sprite *sp = sact_get_sprite(surface); + if (!sp) return 0; - current_context = dungeon_context_create(version, surface); - return 1; -} -struct dungeon_context *dungeon_get_context(int surface) -{ - if (!current_context || surface != current_context->surface) - return NULL; - return current_context; + struct dungeon_context *ctx = dungeon_context_create(version, sp->rect.w, sp->rect.h); + sprite_bind_plugin(sp, &ctx->plugin); + return 1; } static struct dgn_cell *dungeon_get_cell(int surface, int x, int y, int z) @@ -54,14 +47,6 @@ static struct dgn_cell *dungeon_get_cell(int surface, int x, int y, int z) return dgn_cell_at(ctx->dgn, x, y, z); } -static void DrawDungeon_ModuleFini(void) -{ - if (current_context) { - dungeon_context_free(current_context); - current_context = NULL; - } -} - static int DrawDungeon_Init(int surface) { return dungeon_init(DRAW_DUNGEON_1, surface); @@ -74,11 +59,9 @@ static int DrawDungeon14_Init(int surface) static void DrawDungeon_Release(int surface) { - struct dungeon_context *ctx = dungeon_get_context(surface); - if (!ctx) + if (!dungeon_get_context(surface)) return; - dungeon_context_free(ctx); - current_context = NULL; + sprite_bind_plugin(sact_get_sprite(surface), NULL); } static void DrawDungeon_SetDrawFlag(int surface, int flag) @@ -284,7 +267,6 @@ HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, StopTimer, void); HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, RestartTimer, void); #define DRAW_DUNGEON_EXPORTS \ - HLL_EXPORT(_ModuleFini, DrawDungeon_ModuleFini), \ HLL_EXPORT(Release, DrawDungeon_Release), \ HLL_EXPORT(SetDrawFlag, DrawDungeon_SetDrawFlag), \ HLL_EXPORT(BeginLoad, DrawDungeon_BeginLoad), \ diff --git a/src/hll/DrawRain.c b/src/hll/DrawRain.c index 1f7c9e8..f50a9f1 100644 --- a/src/hll/DrawRain.c +++ b/src/hll/DrawRain.c @@ -45,6 +45,11 @@ static struct draw_rain_plugin *get_draw_rain_plugin(int surface) return (struct draw_rain_plugin *)sp->plugin; } +static void DrawRain_free(struct draw_plugin *plugin) +{ + free(plugin); +} + static void DrawRain_update(struct sact_sprite *sp) { struct draw_rain_plugin *plugin = (struct draw_rain_plugin *)sp->plugin; @@ -95,6 +100,7 @@ static int DrawRain_Init(int surface) } struct draw_rain_plugin *plugin = xcalloc(1, sizeof(struct draw_rain_plugin)); plugin->p.name = plugin_name; + plugin->p.free = DrawRain_free; plugin->p.update = DrawRain_update; plugin->p.to_json = DrawRain_to_json; plugin->nr_lines = 1000; @@ -107,11 +113,9 @@ static int DrawRain_Init(int surface) static void DrawRain_Release(int surface) { - struct draw_rain_plugin *plugin = get_draw_rain_plugin(surface); - if (!plugin) + if (!get_draw_rain_plugin(surface)) return; sprite_bind_plugin(sact_get_sprite(surface), NULL); - free(plugin); } static void DrawRain_SetNumofLine(int surface, int line) diff --git a/src/hll/DrawRipple.c b/src/hll/DrawRipple.c index 7f54eae..711e8b9 100644 --- a/src/hll/DrawRipple.c +++ b/src/hll/DrawRipple.c @@ -52,6 +52,13 @@ static struct draw_ripple_plugin *get_draw_ripple_plugin(int surface) return (struct draw_ripple_plugin *)sp->plugin; } +static void DrawRipple_free(struct draw_plugin *_plugin) +{ + struct draw_ripple_plugin *plugin = (struct draw_ripple_plugin *)_plugin; + free(plugin->ripples); + free(plugin); +} + static void draw_point(uint32_t *pixels, int w, int h, int x, int y) { if (x < 0 || x >= w || y < 0 || y >= h) @@ -163,6 +170,7 @@ static int DrawRipple_Init(int surface) } struct draw_ripple_plugin *plugin = xcalloc(1, sizeof(struct draw_ripple_plugin)); plugin->p.name = plugin_name; + plugin->p.free = DrawRipple_free; plugin->p.update = DrawRipple_update; plugin->p.to_json = DrawRipple_to_json; plugin->width = 6; @@ -175,12 +183,9 @@ static int DrawRipple_Init(int surface) static void DrawRipple_Release(int surface) { - struct draw_ripple_plugin *plugin = get_draw_ripple_plugin(surface); - if (!plugin) + if (!get_draw_ripple_plugin(surface)) return; sprite_bind_plugin(sact_get_sprite(surface), NULL); - free(plugin->ripples); - free(plugin); } static void DrawRipple_SetNumof(int surface, int numof) diff --git a/src/hll/DrawSnow.c b/src/hll/DrawSnow.c index 7ae3f17..9d2d266 100644 --- a/src/hll/DrawSnow.c +++ b/src/hll/DrawSnow.c @@ -70,6 +70,13 @@ static struct draw_snow_plugin *get_draw_snow_plugin(int sprite) return (struct draw_snow_plugin *)sp->plugin; } +static void DrawSnow_free(struct draw_plugin *_plugin) +{ + struct draw_snow_plugin *plugin = (struct draw_snow_plugin *)_plugin; + free(plugin->particles); + free(plugin); +} + static void DrawSnow_update(struct sact_sprite *sp) { struct draw_snow_plugin *plugin = (struct draw_snow_plugin *)sp->plugin; @@ -131,6 +138,7 @@ static void DrawSnow_Init(int sprite, int width, int height) { struct draw_snow_plugin *plugin = xcalloc(1, sizeof(struct draw_snow_plugin)); plugin->p.name = plugin_name; + plugin->p.free = DrawSnow_free; plugin->p.update = DrawSnow_update; plugin->p.render = DrawSnow_render; plugin->p.to_json = DrawSnow_to_json; @@ -147,12 +155,9 @@ static void DrawSnow_Init(int sprite, int width, int height) static void DrawSnow_Release(int sprite) { - struct draw_snow_plugin *plugin = get_draw_snow_plugin(sprite); - if (!plugin) + if (!get_draw_snow_plugin(sprite)) return; sprite_bind_plugin(sact_get_sprite(sprite), NULL); - free(plugin->particles); - free(plugin); } static void DrawSnow_Start(int sprite) diff --git a/src/sprite.c b/src/sprite.c index 6c98a8e..931d37e 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -54,8 +54,10 @@ void sprite_free(struct sact_sprite *sp) scene_unregister_sprite(&sp->sp); gfx_delete_texture(&sp->texture); gfx_delete_texture(&sp->text.texture); - if (sp->plugin) + if (sp->plugin && sp->plugin->free) { + sp->plugin->free(sp->plugin); LIST_REMOVE(sp, entry); + } // restore to initial state memset(sp, 0, sizeof(struct sact_sprite)); sprite_init(sp); @@ -470,6 +472,8 @@ void sprite_bind_plugin(struct sact_sprite *sp, struct draw_plugin *plugin) LIST_INSERT_HEAD(&sprites_with_plugins, sp, entry); else if (sp->plugin && !plugin) LIST_REMOVE(sp, entry); + if (sp->plugin != plugin && sp->plugin && sp->plugin->free) + sp->plugin->free(sp->plugin); sp->plugin = plugin; }