From 9daf010774b2897f1efcc2e7124863476131244a Mon Sep 17 00:00:00 2001 From: jaburns Date: Wed, 28 Oct 2020 13:51:03 -0600 Subject: [PATCH] Finished memory management of multiple marios --- src/decomp/global_state.c | 2 +- src/decomp/global_state.h | 2 +- src/libsm64.c | 91 ++++++++++++++++++++++++--------------- src/obj_pool.c | 37 ++++++++++++++++ src/obj_pool.h | 14 ++++++ 5 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 src/obj_pool.c create mode 100644 src/obj_pool.h diff --git a/src/decomp/global_state.c b/src/decomp/global_state.c index 3e35589..5d9bc6c 100644 --- a/src/decomp/global_state.c +++ b/src/decomp/global_state.c @@ -18,7 +18,7 @@ void global_state_bind(struct GlobalState *state) g_state = state; } -void global_state_destroy(struct GlobalState *state) +void global_state_delete(struct GlobalState *state) { free( state ); } \ No newline at end of file diff --git a/src/decomp/global_state.h b/src/decomp/global_state.h index 84d1ee8..15c2ed9 100644 --- a/src/decomp/global_state.h +++ b/src/decomp/global_state.h @@ -53,4 +53,4 @@ extern struct GlobalState *g_state; extern struct GlobalState *global_state_create(void); extern void global_state_bind(struct GlobalState *state); -extern void global_state_destroy(struct GlobalState *state); \ No newline at end of file +extern void global_state_delete(struct GlobalState *state); \ No newline at end of file diff --git a/src/libsm64.c b/src/libsm64.c index 3d2f3cb..e4f58fd 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -27,12 +27,19 @@ #include "gfx_adapter.h" #include "load_anim_data.h" #include "load_tex_data.h" +#include "obj_pool.h" -static struct AllocOnlyPool *s_mario_geo_pool; -static struct GraphNode *s_mario_graph_node; -static uint32_t s_last_colors_hash; -static bool s_is_init = false; -static struct GlobalState *s_global_state; +static struct AllocOnlyPool *s_mario_geo_pool = NULL; +static struct GraphNode *s_mario_graph_node = NULL; + +static bool s_init_global = false; +static bool s_init_one_mario = false; + +struct MarioInstance +{ + struct GlobalState *globalState; +}; +struct ObjPool s_mario_instance_pool = { 0, 0 }; static void update_button( bool on, u16 button ) { @@ -92,48 +99,37 @@ static void update_objects( void ) SM64_LIB_FN void sm64_global_init( uint8_t *rom, uint8_t *outTexture, SM64DebugPrintFunctionPtr debugPrintFunction ) { - if( s_is_init ) + if( s_init_global ) sm64_global_terminate(); - s_is_init = true; - - s_last_colors_hash = 0; + s_init_global = true; g_debug_print_func = debugPrintFunction; load_mario_textures_from_rom( rom, outTexture ); load_mario_anims_from_rom( rom ); memory_init(); - s_global_state = global_state_create(); - global_state_bind( s_global_state ); - - gCurrSaveFileNum = 1; - gMarioObject = hack_allocate_mario(); - gCurrentArea = allocate_area(); - gCurrentObject = gMarioObject; - - s_mario_geo_pool = alloc_only_pool_init(); - s_mario_graph_node = process_geo_layout( s_mario_geo_pool, mario_geo_ptr ); - - D_80339D10.animDmaTable = NULL; - D_80339D10.currentAnimAddr = NULL; - D_80339D10.targetAnim = NULL; } SM64_LIB_FN void sm64_global_terminate( void ) { - if( !s_is_init ) - return; - - s_is_init = false; - - free( gMarioObject ); - free_area( gCurrentArea ); + if( !s_init_global ) return; global_state_bind( NULL ); - global_state_destroy( s_global_state ); - s_global_state = NULL; + + if( s_init_one_mario ) + { + for( int i = 0; i < s_mario_instance_pool.size; ++i ) + if( s_mario_instance_pool.objects[i] != NULL ) + global_state_delete( ((struct MarioInstance *)s_mario_instance_pool.objects[ i ])->globalState ); + obj_pool_free_all( &s_mario_instance_pool ); + } + + s_init_global = false; + s_init_one_mario = false; + + alloc_only_pool_free( s_mario_geo_pool ); surfaces_unload_all(); unload_mario_anims(); memory_terminate(); @@ -146,6 +142,24 @@ SM64_LIB_FN void sm64_static_surfaces_load( const struct SM64Surface *surfaceArr SM64_LIB_FN uint32_t sm64_mario_create( int16_t x, int16_t y, int16_t z ) { + uint32_t marioIndex = obj_pool_alloc_index( &s_mario_instance_pool, sizeof( struct MarioInstance )); + struct MarioInstance *newInstance = s_mario_instance_pool.objects[marioIndex]; + + newInstance->globalState = global_state_create(); + global_state_bind( newInstance->globalState ); + + if( !s_init_one_mario ) + { + s_init_one_mario = true; + s_mario_geo_pool = alloc_only_pool_init(); + s_mario_graph_node = process_geo_layout( s_mario_geo_pool, mario_geo_ptr ); + } + + gCurrSaveFileNum = 1; + gMarioObject = hack_allocate_mario(); + gCurrentArea = allocate_area(); + gCurrentObject = gMarioObject; + gMarioSpawnInfoVal.startPos[0] = x; gMarioSpawnInfoVal.startPos[1] = y; gMarioSpawnInfoVal.startPos[2] = z; @@ -166,11 +180,13 @@ SM64_LIB_FN uint32_t sm64_mario_create( int16_t x, int16_t y, int16_t z ) set_mario_action( gMarioState, ACT_SPAWN_SPIN_AIRBORNE, 0); find_floor( x, y, z, &gMarioState->floor ); - return 1; + return marioIndex; } SM64_LIB_FN void sm64_mario_tick( uint32_t marioId, const struct SM64MarioInputs *inputs, struct SM64MarioState *outState, struct SM64MarioGeometryBuffers *outBuffers ) { + global_state_bind( ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState ); + update_button( inputs->buttonA, A_BUTTON ); update_button( inputs->buttonB, B_BUTTON ); update_button( inputs->buttonZ, Z_TRIG ); @@ -197,7 +213,14 @@ SM64_LIB_FN void sm64_mario_tick( uint32_t marioId, const struct SM64MarioInputs SM64_LIB_FN void sm64_mario_delete( uint32_t marioId ) { - // TODO + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + free( gMarioObject ); + free_area( gCurrentArea ); + + global_state_delete( globalState ); + obj_pool_free_index( &s_mario_instance_pool, marioId ); } SM64_LIB_FN uint32_t sm64_surface_object_create( const struct SM64SurfaceObject *surfaceObject ) diff --git a/src/obj_pool.c b/src/obj_pool.c new file mode 100644 index 0000000..d771b26 --- /dev/null +++ b/src/obj_pool.c @@ -0,0 +1,37 @@ +#include "obj_pool.h" + +#include + +uint32_t obj_pool_alloc_index( struct ObjPool *pool, size_t size ) +{ + for( uint32_t i = 0; i < pool->size; ++i ) + { + if( pool->objects[i] == NULL ) + { + pool->objects[i] = malloc( size ); + return i; + } + } + + uint32_t i = pool->size; + pool->size++; + pool->objects = realloc( pool->objects, pool->size * sizeof( void * )); + pool->objects[i] = malloc( size ); + return i; +} + +void obj_pool_free_index( struct ObjPool *pool, uint32_t index ) +{ + free( pool->objects[index] ); + pool->objects[index] = NULL; +} + +void obj_pool_free_all( struct ObjPool *pool ) +{ + for( uint32_t i = 0; i < pool->size; ++i ) + free( pool->objects[i] ); + free( pool->objects ); + + pool->size = 0; + pool->objects = NULL; +} \ No newline at end of file diff --git a/src/obj_pool.h b/src/obj_pool.h new file mode 100644 index 0000000..e981791 --- /dev/null +++ b/src/obj_pool.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +struct ObjPool +{ + size_t size; + void **objects; +}; + +extern uint32_t obj_pool_alloc_index( struct ObjPool *pool, size_t size ); +extern void obj_pool_free_index( struct ObjPool *pool, uint32_t index ); +extern void obj_pool_free_all( struct ObjPool *pool ); \ No newline at end of file