From 94d5dfcf10b074db0a2270ccd83fa42a55b4003e Mon Sep 17 00:00:00 2001 From: wRadion Date: Tue, 13 Sep 2022 04:57:28 +0200 Subject: [PATCH] Scrolling textures (continued) (#175) * Handle scroll targets as dynamic array + some error handling * Remove the need to call init (clean automatically scroll targets) * Free iteratively instead of recursive * Added comments + handled some potential errors * Completed comments * Remove debug print --- autogen/lua_definitions/functions.lua | 5 -- data/dynos.c.h | 1 - data/dynos.cpp.h | 1 - data/dynos_c.cpp | 4 - data/dynos_misc.cpp | 4 - docs/lua/functions-4.md | 18 ---- docs/lua/functions.md | 1 - src/game/behaviors/texscroll.inc.c | 40 +++++++-- src/game/scroll_targets.c | 119 +++++++++++++++++++++++--- src/game/scroll_targets.h | 7 +- src/pc/lua/smlua_functions_autogen.c | 10 --- src/pc/lua/utils/smlua_misc_utils.c | 4 - src/pc/lua/utils/smlua_misc_utils.h | 1 - src/pc/network/network.c | 6 +- 14 files changed, 145 insertions(+), 76 deletions(-) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 8dfca5f9c..d9ae5c46c 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -7759,11 +7759,6 @@ function hud_show() -- ... end ---- @return nil -function init_scroll_targets() - -- ... -end - --- @return boolean function is_game_paused() -- ... diff --git a/data/dynos.c.h b/data/dynos.c.h index d3fa1225b..25e61a251 100644 --- a/data/dynos.c.h +++ b/data/dynos.c.h @@ -66,7 +66,6 @@ void dynos_behavior_hook_all_custom_behaviors(void); // -- other -- // void dynos_mod_shutdown(void); void dynos_add_scroll_target(u32 index, const char *name, u32 offset, u32 size); -void dynos_init_scroll_targets(void); #endif #endif diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 7b5d0bc22..b165e70ba 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -1065,7 +1065,6 @@ bool DynOS_Bin_Compress(const SysPath &aFilename); BinFile *DynOS_Bin_Decompress(const SysPath &aFilename); void DynOS_Add_Scroll_Target(u32 index, const char *name, u32 offset, u32 size); -void DynOS_Init_Scroll_Targets(void); #endif #endif diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp index 3adc2df6b..25eedf6ad 100644 --- a/data/dynos_c.cpp +++ b/data/dynos_c.cpp @@ -202,8 +202,4 @@ void dynos_add_scroll_target(u32 index, const char *name, u32 offset, u32 size) DynOS_Add_Scroll_Target(index, name, offset, size); } -void dynos_init_scroll_targets(void) { - DynOS_Init_Scroll_Targets(); -} - } diff --git a/data/dynos_misc.cpp b/data/dynos_misc.cpp index 3c99d6a42..a1bb0ec43 100644 --- a/data/dynos_misc.cpp +++ b/data/dynos_misc.cpp @@ -189,7 +189,3 @@ void DynOS_Add_Scroll_Target(u32 index, const char* name, u32 offset, u32 size) } } } - -void DynOS_Init_Scroll_Targets(void) { - init_vtx_scroll_targets(); -} diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md index 61d8eb8a1..55f559911 100644 --- a/docs/lua/functions-4.md +++ b/docs/lua/functions-4.md @@ -7047,24 +7047,6 @@
-## [init_scroll_targets](#init_scroll_targets) - -### Lua Example -`init_scroll_targets()` - -### Parameters -- None - -### Returns -- None - -### C Prototype -`void init_scroll_targets(void);` - -[:arrow_up_small:](#) - -
- ## [is_game_paused](#is_game_paused) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index d8d9cb142..6774e03cd 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1444,7 +1444,6 @@ - [hud_render_power_meter](functions-4.md#hud_render_power_meter) - [hud_set_value](functions-4.md#hud_set_value) - [hud_show](functions-4.md#hud_show) - - [init_scroll_targets](functions-4.md#init_scroll_targets) - [is_game_paused](functions-4.md#is_game_paused) - [is_transition_playing](functions-4.md#is_transition_playing) - [movtexqc_register](functions-4.md#movtexqc_register) diff --git a/src/game/behaviors/texscroll.inc.c b/src/game/behaviors/texscroll.inc.c index b135469c0..7a006b3b4 100644 --- a/src/game/behaviors/texscroll.inc.c +++ b/src/game/behaviors/texscroll.inc.c @@ -20,8 +20,8 @@ /* SCROLLING TYPES */ #define MODE_SCROLL_UV 0 -#define MODE_SCROLL_SINE 182 // 1 -#define MODE_SCROLL_JUMP 108 // 2 +#define MODE_SCROLL_SINE 1 +#define MODE_SCROLL_JUMP 2 // typedef struct { // float ob[3]; /* x, y, z */ @@ -36,13 +36,15 @@ // Vtx_tn n; /* Use this one for normals */ // long long int force_structure_alignment; // } Vtx; -extern Vtx *gScrollTargets[]; -extern f32 gRenderingDelta; static void shift_UV_JUMP(s32 vtxIndex, u16 vertcount, s16 speed, u16 bhv, u16 cycle) { Vtx* *verts = get_scroll_targets(vtxIndex); u16 i; + if (verts == NULL) { + return; + } + if (verts[0]->n.flag++ <= cycle) { return; } @@ -66,6 +68,10 @@ static void shift_UV_NORMAL(u32 vtxIndex, u16 vertcount, s16 speed, u16 bhv, u16 u16 correction = 0; u16 i; + if (verts == NULL) { + return; + } + if (bhv < SCROLL_UV_X) { if (verts[0]->n.flag >= cycle) { correction = verts[0]->n.flag * speed; @@ -103,6 +109,10 @@ static void shift_UV_SINE(u32 vtxIndex, u16 vertcount, s16 speed, u16 bhv, u16 c Vtx* *verts = get_scroll_targets(vtxIndex); u32 i; + if (verts == NULL) { + return; + } + if (bhv < SCROLL_UV_X) { for (i = 0; i < vertcount; i++) { verts[i]->n.ob[bhv] += sins(verts[0]->n.flag) * speed; @@ -115,15 +125,29 @@ static void shift_UV_SINE(u32 vtxIndex, u16 vertcount, s16 speed, u16 bhv, u16 c verts[0]->n.flag += cycle * 0x23; } -// format I will use is x=spd, y=bhv, z=vert amount, rx=offset, ry=scrollType, rz=cycle, bparam=addr +/* + * Scroll parameters are took from the object's properties: + * Xpos = speed + * Ypos = scrolling behavior/axis + * Zpos = vertices amount + * Xrot = offset (unused) + * Yrot = scrolling type + * Zrot = cycle + * Behavior param = scroll target index + */ void uv_update_scroll(void) { s16 speed = (s16) o->oPosX; u16 bhv = (u16) o->oPosY; u16 vertCount = (u16) o->oPosZ; - u8 scrollType = (u8) o->oFaceAngleYaw; - u16 cycle = (u16) o->oFaceAngleRoll * 180 / 0x8000; + u16 scrollType = (u16) round(o->oFaceAngleYaw * 180.0 / 0x8000); + u16 cycle = (u16) round(o->oFaceAngleRoll * 180.0 / 0x8000); u32 vtxIndex = (u32) o->oBehParams; + // Check for invalid scrolling behavior + if (bhv == 3 || bhv > SCROLL_UV_Y) { + return; + } + switch (scrollType) { case MODE_SCROLL_UV: shift_UV_NORMAL(vtxIndex, vertCount, speed, bhv, cycle); @@ -134,5 +158,7 @@ void uv_update_scroll(void) { case MODE_SCROLL_JUMP: shift_UV_JUMP(vtxIndex, vertCount, speed, bhv, cycle); break; + default: + break; } } diff --git a/src/game/scroll_targets.c b/src/game/scroll_targets.c index 1e1c023a1..f67f61a03 100644 --- a/src/game/scroll_targets.c +++ b/src/game/scroll_targets.c @@ -1,27 +1,122 @@ #include "scroll_targets.h" -Vtx *gScrollTargets[1024]; +/* + * A scroll target is basically just a bunch of Vtx to + * apply a movement to. Each scroll targets have an id. + * The id is what the behavior is using to know which + * vertices to move. + */ +struct ScrollTarget { + u32 id; + u32 size; + Vtx* *vertices; + struct ScrollTarget *next; +}; -static int startIndex[128]; -static int lastIndex = 0; +static struct ScrollTarget *sScrollTargets = NULL; +/* + * Gets the scroll targets identified by the given id + * and returns the vertices. + * Returns NULL if not found. + */ Vtx* *get_scroll_targets(u32 id) { - return &gScrollTargets[startIndex[id]]; + struct ScrollTarget *scroll = sScrollTargets; + + while (scroll) { + if (scroll->id == id) { + break; + } + scroll = scroll->next; + } + + if (scroll) { + return scroll->vertices; + } + return NULL; } -void add_vtx_scroll_target(u32 id, Vtx *vtx, u32 size) { - if (startIndex[id] == -1) { - startIndex[id] = lastIndex; +/* + * Finds the scroll targets identified by the given id and + * returns it. + * If it doesn't find it, create one and returns an allocated + * pointer to it. + * Also sets up the static sScrollTargets variable if there + * isn't any scroll targets. + */ +struct ScrollTarget* find_or_create_scroll_targets(u32 id) { + struct ScrollTarget *scroll = sScrollTargets; + struct ScrollTarget *lastScroll = NULL; + + while (scroll) { + if (scroll->id == id) { + break; + } + + lastScroll = scroll; + scroll = scroll->next; } + if (scroll == NULL) { + scroll = malloc(sizeof(struct ScrollTarget)); + scroll->id = id; + scroll->size = 0; + scroll->vertices = NULL; + scroll->next = NULL; + if (lastScroll) { + lastScroll->next = scroll; + } else { + sScrollTargets = scroll; + } + } + + return scroll; +} + +/* + * Adds the given vertices to the scroll targets with the + * given id. + * Mods have to use the lua binding of this function to + * make the scrolling textures work. + */ +void add_vtx_scroll_target(u32 id, Vtx *vtx, u32 size) { + struct ScrollTarget *scroll = find_or_create_scroll_targets(id); + Vtx* *newArray; + u32 oldSize = sizeof(void*) * scroll->size; + u32 newSize = oldSize + (sizeof(void*) * size); + + newArray = realloc(scroll->vertices, newSize); + + if (!newArray) { + newArray = malloc(newSize); + memcpy(newArray, scroll->vertices, oldSize); + free(scroll->vertices); + } + + scroll->vertices = newArray; + for (u32 i = 0; i < size; ++i) { - gScrollTargets[lastIndex++] = &vtx[i]; + scroll->vertices[scroll->size++] = &vtx[i]; } } -void init_vtx_scroll_targets(void) { - for (int i = 0; i < 128; ++i) { - startIndex[i] = -1; +/* + * Free the static sScrollTargets variable and + * all its content that was allocated by + * find_or_create_scroll_targets(id) + * and + * add_vtx_scroll_targets(id, vtx, size) + */ +void free_vtx_scroll_targets() { + struct ScrollTarget* scroll = sScrollTargets; + struct ScrollTarget* nextScroll; + + while (scroll) { + nextScroll = scroll->next; + free(scroll->vertices); + free(scroll); + scroll = nextScroll; } - lastIndex = 0; + + sScrollTargets = NULL; } diff --git a/src/game/scroll_targets.h b/src/game/scroll_targets.h index ede2b4e70..86bac2d0a 100644 --- a/src/game/scroll_targets.h +++ b/src/game/scroll_targets.h @@ -9,11 +9,6 @@ #include "sm64.h" #include "types.h" -//Q. Why does this exist instead of just directly referencing VBs? -//A. Because gcc is dumb and will seg fault if you reference a VB by abstracting it through a bparam -//instead of directly refencing it, causing this horrible shit. -extern Vtx *gScrollTargets[]; - Vtx* *get_scroll_targets(u32 id); void add_vtx_scroll_target(u32 id, Vtx *vtx, u32 size); -void init_vtx_scroll_targets(void); +void free_vtx_scroll_targets(void); diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 7c4071fa8..805699db2 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -17063,15 +17063,6 @@ int smlua_func_hud_show(UNUSED lua_State* L) { return 1; } -int smlua_func_init_scroll_targets(UNUSED lua_State* L) { - if(!smlua_functions_valid_param_count(L, 0)) { return 0; } - - - init_scroll_targets(); - - return 1; -} - int smlua_func_is_game_paused(UNUSED lua_State* L) { if(!smlua_functions_valid_param_count(L, 0)) { return 0; } @@ -19521,7 +19512,6 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "hud_render_power_meter", smlua_func_hud_render_power_meter); smlua_bind_function(L, "hud_set_value", smlua_func_hud_set_value); smlua_bind_function(L, "hud_show", smlua_func_hud_show); - smlua_bind_function(L, "init_scroll_targets", smlua_func_init_scroll_targets); smlua_bind_function(L, "is_game_paused", smlua_func_is_game_paused); smlua_bind_function(L, "is_transition_playing", smlua_func_is_transition_playing); smlua_bind_function(L, "movtexqc_register", smlua_func_movtexqc_register); diff --git a/src/pc/lua/utils/smlua_misc_utils.c b/src/pc/lua/utils/smlua_misc_utils.c index 5097140c0..1cd8ef405 100644 --- a/src/pc/lua/utils/smlua_misc_utils.c +++ b/src/pc/lua/utils/smlua_misc_utils.c @@ -359,7 +359,3 @@ void set_override_far(f32 far) { void add_scroll_target(u32 index, const char* name, u32 offset, u32 size) { dynos_add_scroll_target(index, name, offset, size); } - -void init_scroll_targets(void) { - dynos_init_scroll_targets(); -} diff --git a/src/pc/lua/utils/smlua_misc_utils.h b/src/pc/lua/utils/smlua_misc_utils.h index e29929bd1..7615f7f1a 100644 --- a/src/pc/lua/utils/smlua_misc_utils.h +++ b/src/pc/lua/utils/smlua_misc_utils.h @@ -84,7 +84,6 @@ void set_override_near(f32 near); void set_override_far(f32 far); void add_scroll_target(u32 index, const char* name, u32 offset, u32 size); -void init_scroll_targets(void); void play_transition(s16 transType, s16 time, u8 red, u8 green, u8 blue); diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 2ab06e819..59debee28 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -5,6 +5,7 @@ #include "object_constants.h" #include "behavior_table.h" #include "src/game/hardcoded.h" +#include "src/game/scroll_targets.h" #ifdef DISCORD_SDK #include "discord/discord.h" #endif @@ -124,7 +125,7 @@ bool network_init(enum NetworkType inNetworkType) { mods_activate(&gLocalMods); smlua_init(); - + dynos_behavior_hook_all_custom_behaviors(); network_player_connected(NPT_LOCAL, 0, configPlayerModel, &configPlayerPalette, configPlayerName); @@ -504,7 +505,7 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup) { gNetworkServerAddr = NULL; } gNetworkPlayerServer = NULL; - + gNetworkType = NT_NONE; @@ -530,6 +531,7 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup) { extern s16 gChangeLevel; gChangeLevel = LEVEL_CASTLE_GROUNDS; network_player_init(); + free_vtx_scroll_targets(); struct Controller* cnt = gMarioStates[0].controller; cnt->rawStickX = 0;