From c270c11c9bee22a2c6fd9395f21f389e18c8afed Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sat, 3 Aug 2024 20:57:07 -0600 Subject: [PATCH] Lakitu fix (#35) * Fix menu bug * Fix undefined behaviour * Fix kart textures * Fix boost texture * Rename as per review * Fix buffer overflows * Fix lakitu progress * Fix race starter character --------- Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com> --- include/objects.h | 6 +-- src/code_80057C60.c | 4 +- src/code_80057C60.h | 4 +- src/racing/memory.c | 3 +- src/racing/memory.h | 1 + src/render_objects.c | 14 +++--- src/render_player.c | 4 +- src/update_objects.c | 103 +++++++++++++++++++++++-------------------- src/update_objects.h | 14 +++--- 9 files changed, 80 insertions(+), 73 deletions(-) diff --git a/include/objects.h b/include/objects.h index 91e5f4cb5..6a0a9b1ae 100644 --- a/include/objects.h +++ b/include/objects.h @@ -23,15 +23,15 @@ typedef struct /* 0x54 */ s32 status; /* 0x58 */ s32 unk_058; /* 0x5C */ s32 unk_05C; - /* 0x60 */ u8 *activeTLUT; - /* 0x64 */ u8 *activeTexture; + /* 0x60 */ const char *activeTLUT; + /* 0x64 */ const char *activeTexture; /** * "list" is something of a misnomer for the names here * they can be pointers to just 1 tlut/texture, but it is common for one or the other * to be a pointer to an array of tluts/textures. **/ /* 0x68 */ u8 *tlutList; // I feel like this should actually be `u8 (*tlutList)[512]`, but that causes mismatches - /* 0x6C */ u8 *textureList; + /* 0x6C */ const char **textureList; /* 0x70 */ Gfx *model; /* 0x74 */ Vtx *vertex; /* 0x78 */ s8 unk_078[0x04]; diff --git a/src/code_80057C60.c b/src/code_80057C60.c index ff56d0e90..cb8649fc2 100644 --- a/src/code_80057C60.c +++ b/src/code_80057C60.c @@ -287,14 +287,14 @@ s32 indexObjectList2[32]; * I'm also not certain about its dimensions * I think the entires in this array are way over-sized */ -u8 D_80183FA8[4][0x2000]; +const char *gLakituTextureBuffer[4][2]; /** * Boos in Banshee Boardwalk * Spawners for the 4 small fire breaths inside Bowser's Castle */ s32 indexObjectList3[32]; //! Seemingly a pointer to Lakitu texture(s) -u8 *D_8018C028; +const char **gLakituTexturePtr; /** * Unused list of object indices */ diff --git a/src/code_80057C60.h b/src/code_80057C60.h index 5c1455e08..cb027ec06 100644 --- a/src/code_80057C60.h +++ b/src/code_80057C60.h @@ -410,10 +410,10 @@ extern Vec3su D_80183E98; // extern s32 indexObjectList1[]; -> objects.h // extern s32 indexObjectList2[]; -> objects.h -extern u8 D_80183FA8[4][0x2000]; +extern const char *gLakituTextureBuffer[4][2]; // extern s32 indexObjectList3[]; -> objects.h -extern u8 *D_8018C028; +extern const char **gLakituTexturePtr; // extern s32 indexObjectList4[]; -> objects.h // extern Collision D_8018C0B0[]; -> objects.h // extern s32 gObjectParticle1[]; -> objects.h diff --git a/src/racing/memory.c b/src/racing/memory.c index d984d64a8..83c752d6c 100644 --- a/src/racing/memory.c +++ b/src/racing/memory.c @@ -1509,8 +1509,7 @@ NewCourseTable gNewCourseTable[] = { }; -/** Load Lakitu Textures **/ -u8 *load_lakitu_textures_x64(const char** textureList, size_t length) { +u8 *load_lakitu_tlut_x64(const char** textureList, size_t length) { // Calculate lakitu texture size to allocate size_t size = 0; for (size_t i = 0; i < length; i++) { diff --git a/src/racing/memory.h b/src/racing/memory.h index 8360224a8..13bcf949e 100644 --- a/src/racing/memory.h +++ b/src/racing/memory.h @@ -42,6 +42,7 @@ struct AllocOnlyPool { extern f32 vtxStretchY; u8 *load_lakitu_textures_x64(const char** textureList, size_t length); +u8 *load_lakitu_tlut_x64(const char**textureList, size_t length); void *get_next_available_memory_addr(uintptr_t); uintptr_t set_segment_base_addr(s32, void*); void *get_segment_base_addr(s32); diff --git a/src/render_objects.c b/src/render_objects.c index 6d454b508..411ce3008 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -612,17 +612,17 @@ void func_80047068(u8 *tlut, u8 *texture, Vtx *arg2, UNUSED s32 arg3, s32 arg4, gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF); } -void draw_rectangle_texture_overlap(u8 *tlut, u8 *texture, Vtx *arg2, UNUSED s32 arg3, s32 arg4, s32 width, s32 height) { +void draw_rectangle_texture_overlap(u8 *tlut, u8 *texture, Vtx *arg2, UNUSED s32 w, s32 height, s32 width, s32 heighthalf) { s32 heightIndex; s32 vertexIndex = 0; - u8 *img = texture; + u8 *img = (u8 *) LOAD_ASSET(texture); gDPLoadTLUT_pal256(gDisplayListHead++, tlut); - for (heightIndex = 0; heightIndex < arg4 / height; heightIndex++) { - rsp_load_texture(img, width, height); + for (heightIndex = 0; heightIndex < height / heighthalf; heightIndex++) { + rsp_load_texture(img, width, heighthalf); gSPVertex(gDisplayListHead++, &arg2[vertexIndex], 4, 0); gSPDisplayList(gDisplayListHead++, common_rectangle_display); - img += width * (height - 1); + img += width * (heighthalf - 1); vertexIndex += 4; } gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF); @@ -761,10 +761,10 @@ UNUSED void func_80048038(Vec3f arg0, Vec3su arg1, f32 arg2, u8 *tlut, u8 *textu func_80047068(tlut, texture, arg5, arg6, arg7, arg8, arg9); } -void draw_2d_texture_at(Vec3f arg0, Vec3su arg1, f32 arg2, u8 *tlut, u8 *texture, Vtx *arg5, s32 arg6, s32 arg7, s32 arg8, s32 arg9) { +void draw_2d_texture_at(Vec3f arg0, Vec3su arg1, f32 arg2, u8 *tlut, u8 *texture, Vtx *arg5, s32 width, s32 height, s32 width2, s32 height2) { rsp_set_matrix_transformation(arg0, arg1, arg2); gSPDisplayList(gDisplayListHead++, D_0D007D78); - draw_rectangle_texture_overlap(tlut, texture, arg5, arg6, arg7, arg8, arg9); + draw_rectangle_texture_overlap(tlut, texture, arg5, width, height, width2, height2); } void func_80048130(Vec3f arg0, Vec3su arg1, f32 arg2, u8 *tlut, u8 *texture, Vtx *arg5, s32 arg6, s32 arg7, s32 arg8, s32 arg9, s32 argA) { diff --git a/src/render_player.c b/src/render_player.c index 0517a50a7..52b78494e 100644 --- a/src/render_player.c +++ b/src/render_player.c @@ -1787,8 +1787,8 @@ void func_80026B4C(Player *player, s8 playerId, s8 screenId, s8 arg3) { s16 temp_t2 = player->unk_240; s16 temp_num = 0x40; // setting this as a variable gets rid of regalloc - u8 *wheel0 = LOAD_ASSET(D_800DDE34[player->characterId][temp_t1]); - u8 *wheel1 = LOAD_ASSET(D_800DDE54[player->characterId][temp_t1]); + u16 *wheel0 = (u16 *) LOAD_ASSET(D_800DDE34[player->characterId][temp_t1]); + u16 *wheel1 = (u16 *) LOAD_ASSET(D_800DDE54[player->characterId][temp_t1]); if (((player->effects & 0x4000) == 0x4000) && ((player->type & PLAYER_START_SEQUENCE) == 0)) { if (((player->effects & 0x80) != 0x80) && ((player->effects & 0x40) != 0x40) diff --git a/src/update_objects.c b/src/update_objects.c index ea7a66a7a..4dba217dc 100644 --- a/src/update_objects.c +++ b/src/update_objects.c @@ -730,7 +730,7 @@ void func_80073404(s32 objectIndex, u8 arg1, u8 arg2, Vtx *arg3) { gObjectList[objectIndex].status = 0; } -void init_texture_object(s32 objectIndex, u8 *texture, u8* arg2, u8 arg3, u16 arg4) { +void init_texture_object(s32 objectIndex, u8 *texture, const char **arg2, u8 arg3, u16 arg4) { gObjectList[objectIndex].tlutList = texture; gObjectList[objectIndex].textureList = arg2; gObjectList[objectIndex].textureWidth = arg3; @@ -762,7 +762,7 @@ void update_neon_texture(s32 objectIndex) { void func_80073514(s32 objectIndex) { gObjectList[objectIndex].activeTLUT = gObjectList[objectIndex].tlutList; - gObjectList[objectIndex].activeTexture = gObjectList[objectIndex].textureList + (gObjectList[objectIndex].textureWidth * gObjectList[objectIndex].textureHeight * gObjectList[objectIndex].itemDisplay); + gObjectList[objectIndex].activeTexture = gObjectList[objectIndex].textureList[gObjectList[objectIndex].itemDisplay]; } UNUSED void func_80073568() { @@ -1201,20 +1201,20 @@ void func_800744CC(void) { } } -void func_80074510(uintptr_t devAddr, void *vaddr, size_t nbytes) { - u8 *texture = (u8 *) LOAD_ASSET(devAddr); +uintptr_t devaddr2; + +void func_80074510(const char **lakituTexturePtr, const char* devAddr, size_t vaddr, size_t nbytes) { func_800744CC(); - //osPiStartDma(&gDmaIoMesg, OS_MESG_PRI_NORMAL, OS_READ, devAddr, vaddr, nbytes, &gDmaMesgQueue); - memcpy(vaddr, texture, nbytes); + lakituTexturePtr[vaddr] = devAddr; D_8018D224 = 1; } -void func_80074574(u8 *arg0, void *arg1, u16 arg2, u16 arg3) { - func_80074510((uintptr_t) (arg0), arg1, arg2 * arg3); +void func_80074574(const char **lakituTexturePtr, const char *devAddr, size_t vaddr, u16 width, u16 height) { + func_80074510(lakituTexturePtr, devAddr, vaddr, width * height); } //! @todo arg1 should likely be a u8 * -void func_800745C8(s32 objectIndex, uintptr_t arg1) { +void func_800745C8(s32 objectIndex, const char **lakituTexturePtr) { s32 phi_a1; if ((gObjectList[objectIndex].status & 1) != 0) { @@ -1228,28 +1228,28 @@ void func_800745C8(s32 objectIndex, uintptr_t arg1) { phi_a1 = 1; } - gObjectList[objectIndex].activeTexture = (u8 *) (gObjectList[objectIndex].textureWidth * gObjectList[objectIndex].textureHeight * phi_a1) + arg1; + gObjectList[objectIndex].activeTexture = lakituTexturePtr[phi_a1]; func_800744A0(objectIndex); } } -void func_8007466C(s32 objectIndex, uintptr_t arg1) { +void func_8007466C(s32 objectIndex, const char **lakituTexturePtr) { s32 phi_a1; if ((gObjectList[objectIndex].status & 1) != 0) { // I have no idea why this typecase works - gObjectList[objectIndex].activeTLUT = (u8*) ((u32*)gObjectList[objectIndex].tlutList + (gObjectList[objectIndex].unk_0D3 << 7)) ; + gObjectList[objectIndex].activeTLUT = (u8*) ((u32*)gObjectList[objectIndex].tlutList + (gObjectList[objectIndex].unk_0D3 << 7)); gObjectList[objectIndex].status ^= 2; phi_a1 = 0; if ((gObjectList[objectIndex].status & 2) != 0) { phi_a1 = 1; } - gObjectList[objectIndex].activeTexture = (u8 *) (gObjectList[objectIndex].textureWidth * gObjectList[objectIndex].textureHeight * phi_a1) + arg1; + gObjectList[objectIndex].activeTexture = lakituTexturePtr[phi_a1]; func_800744A0(objectIndex); } } -void func_80074704(s32 objectIndex, uintptr_t arg1) { +void func_80074704(s32 objectIndex, const char **lakituTexturePtr) { s32 phi_a1; if ((gObjectList[objectIndex].status & 1) != 0) { @@ -1259,12 +1259,13 @@ void func_80074704(s32 objectIndex, uintptr_t arg1) { if ((gObjectList[objectIndex].status & 2) != 0) { phi_a1 = 1; } - gObjectList[objectIndex].activeTexture = (u8 *) (gObjectList[objectIndex].textureWidth * gObjectList[objectIndex].textureHeight * phi_a1) + arg1; + gObjectList[objectIndex].activeTexture = lakituTexturePtr[phi_a1]; func_800744A0(objectIndex); } } -u8 *func_80074790(s32 objectIndex, u8 *arg1) { +// Since the buffer only holds two textures, phi_a2 chooses which spot to load into +size_t func_80074790(s32 objectIndex, const char **lakituTexturePtr) { s32 phi_a2; gObjectList[objectIndex].status ^= 4; @@ -1272,32 +1273,35 @@ u8 *func_80074790(s32 objectIndex, u8 *arg1) { if ((gObjectList[objectIndex].status & 4) != 0) { phi_a2 = 1; } - return (gObjectList[objectIndex].textureWidth * gObjectList[objectIndex].textureHeight * phi_a2) + arg1; + return phi_a2; } -void func_800747F0(s32 objectIndex, u8 *arg1) { - u8 *sp24; +void func_800747F0(s32 objectIndex, const char **lakituTexturePtr) { + const char *nextTexture = NULL; if (gObjectList[objectIndex].itemDisplay != gObjectList[objectIndex].unk_0D3) { - sp24 = gObjectList[objectIndex].textureList + (gObjectList[objectIndex].textureWidth * gObjectList[objectIndex].textureHeight * gObjectList[objectIndex].itemDisplay); - func_80074574(sp24, (void *) func_80074790(objectIndex, arg1), gObjectList[objectIndex].textureWidth, gObjectList[objectIndex].textureHeight); - gObjectList[objectIndex].unk_0D3 = gObjectList[objectIndex].itemDisplay; - func_80074478(objectIndex); + nextTexture = gObjectList[objectIndex].textureList[gObjectList[objectIndex].itemDisplay]; + + if (nextTexture != NULL) { + func_80074574(lakituTexturePtr, nextTexture, func_80074790(objectIndex, lakituTexturePtr), gObjectList[objectIndex].textureWidth, gObjectList[objectIndex].textureHeight); + gObjectList[objectIndex].unk_0D3 = gObjectList[objectIndex].itemDisplay; + func_80074478(objectIndex); + } } } -void func_80074894(s32 objectIndex, u8 *arg1) { - func_800747F0(objectIndex, arg1); - func_800745C8(objectIndex, (uintptr_t)arg1); +void func_80074894(s32 objectIndex, const char **lakituTexturePtr) { + func_800747F0(objectIndex, lakituTexturePtr); + func_800745C8(objectIndex, lakituTexturePtr); } -void func_800748C4(s32 objectIndex, u8 *arg1) { - func_800747F0(objectIndex, arg1); - func_8007466C(objectIndex, (uintptr_t)arg1); +void func_800748C4(s32 objectIndex, const char **lakituTexturePtr) { + func_800747F0(objectIndex, lakituTexturePtr); + func_8007466C(objectIndex, lakituTexturePtr); } -void func_800748F4(s32 objectIndex, u8 *arg1) { - func_800747F0(objectIndex, arg1); - func_80074704(objectIndex, (uintptr_t)arg1); +void func_800748F4(s32 objectIndex, const char **lakituTexturePtr) { + func_800747F0(objectIndex, lakituTexturePtr); + func_80074704(objectIndex, lakituTexturePtr); } void func_80074924(s32 objectIndex) { @@ -2921,7 +2925,7 @@ void func_80079114(s32 objectIndex, s32 playerId, s32 arg2) { if (gObjectList[objectIndex].state >= 2) { if ((u8)gObjectList[objectIndex].unk_0D8 == 1) { if (playerId == 0) { - func_80074894(objectIndex, D_8018C028); + func_80074894(objectIndex, gLakituTexturePtr); return; } a = gIndexLakituList[0]; @@ -2932,13 +2936,13 @@ void func_80079114(s32 objectIndex, s32 playerId, s32 arg2) { } switch (arg2) { case 0: - func_800748F4(objectIndex, D_8018C028); + func_800748F4(objectIndex, gLakituTexturePtr); break; case 1: - func_800748C4(objectIndex, D_8018C028); + func_800748C4(objectIndex, gLakituTexturePtr); break; case 2: - func_80074894(objectIndex, D_8018C028); + func_80074894(objectIndex, gLakituTexturePtr); break; } } @@ -2986,7 +2990,7 @@ void init_obj_lakitu_red_flag_countdown(s32 objectIndex, s32 playerId) { //u8 *tlut = (u8 *) LOAD_ASSET(common_tlut_lakitu_countdown); //u8 *lights = (u8 *) LOAD_ASSET(gTextureLakituNoLights1); - init_texture_object(objectIndex, (u8 *) load_lakitu_textures_x64(common_tlut_lakitu_countdown, ARRAY_COUNT(common_tlut_lakitu_countdown)), load_lakitu_textures_x64(sLakituTextures, ARRAY_COUNT(sLakituTextures)), 56, (u16) 72); + init_texture_object(objectIndex, (u8 *) load_lakitu_tlut_x64(common_tlut_lakitu_countdown, ARRAY_COUNT(common_tlut_lakitu_countdown)), sLakituTextures, 56, (u16) 72); Vtx *vtx = (Vtx *) LOAD_ASSET(common_vtx_lakitu); gObjectList[objectIndex].vertex = vtx; gObjectList[objectIndex].sizeScaling = 0.15f; @@ -3093,12 +3097,12 @@ void init_obj_lakitu_red_flag(s32 objectIndex, s32 playerIndex) { func_800791F0(objectIndex, playerIndex); - u8 *tlut = (u8 *) LOAD_ASSET(common_tlut_lakitu_checkered_flag); + u8 *tex = (u8 *) LOAD_ASSET(common_tlut_lakitu_checkered_flag); Vtx *vtx = (Vtx *) LOAD_ASSET(common_vtx_also_lakitu); - init_texture_object(objectIndex, (u8*) tlut, load_lakitu_textures_x64(sLakituCheckeredList, ARRAY_COUNT(sLakituCheckeredList)), 0x48U, (u16) 0x00000038); + init_texture_object(objectIndex, (u8*) tex, sLakituCheckeredList, 0x48U, (u16) 0x00000038); object = &gObjectList[objectIndex]; - object->activeTexture = D_8018C028; + object->activeTexture = *gObjectList[objectIndex].textureList; object->vertex = vtx; object->pos[2] = 5000.0f; object->pos[1] = 5000.0f; @@ -3181,7 +3185,7 @@ void init_obj_lakitu_red_flag_fishing(s32 objectIndex, s32 arg1) { Vtx *vtx = (Vtx *) LOAD_ASSET(D_0D005F30); func_800791F0(objectIndex, arg1); - init_texture_object(objectIndex, (u8*) tlut, load_lakitu_textures_x64(sLakituFishingTextures, ARRAY_COUNT(sLakituFishingTextures)), 0x38U, (u16) 0x00000048); + init_texture_object(objectIndex, tlut, sLakituFishingTextures, 0x38U, (u16) 0x00000048); gObjectList[objectIndex].vertex = vtx; gObjectList[objectIndex].sizeScaling = 0.15f; func_80086E70(objectIndex); @@ -3360,11 +3364,12 @@ void func_8007A060(s32 objectIndex, s32 playerIndex) { func_800791F0(objectIndex, playerIndex); + u8 *tlut = (u8 *) LOAD_ASSET(common_tlut_lakitu_second_lap); Vtx *vtx = (Vtx *) LOAD_ASSET(common_vtx_also_lakitu); - init_texture_object(objectIndex, (u8*) common_tlut_lakitu_second_lap, load_lakitu_textures_x64(sLakituSecondLapTextures, ARRAY_COUNT(sLakituSecondLapTextures)), 0x48U, (u16) 0x00000038); + init_texture_object(objectIndex, tlut, sLakituSecondLapTextures, 0x48U, (u16) 0x00000038); object = &gObjectList[objectIndex]; - object->activeTexture = D_8018C028; + object->activeTexture = *gObjectList[objectIndex].textureList; object->vertex = vtx; object->pos[2] = 5000.0f; object->pos[1] = 5000.0f; @@ -3418,11 +3423,12 @@ void func_8007A228(s32 objectIndex, s32 playerIndex) { func_800791F0(objectIndex, playerIndex); + u8 *tlut = (u8 *) LOAD_ASSET(common_tlut_lakitu_final_lap); Vtx *vtx = (Vtx *) LOAD_ASSET(common_vtx_also_lakitu); - init_texture_object(objectIndex, (u8*) common_tlut_lakitu_final_lap, load_lakitu_textures_x64(sLakituFinalLapTextures, ARRAY_COUNT(sLakituFinalLapTextures)), 0x48U, (u16) 0x00000038); + init_texture_object(objectIndex, tlut, sLakituFinalLapTextures, 0x48U, (u16) 0x00000038); object = &gObjectList[objectIndex]; - object->activeTexture = D_8018C028; + object->activeTexture = *gObjectList[objectIndex].textureList; object->vertex = vtx; object->pos[2] = 5000.0f; object->pos[1] = 5000.0f; @@ -3475,10 +3481,11 @@ void func_8007A3F0(s32 objectIndex, s32 arg1) { f32 var = 5000.0f; func_800791F0(objectIndex, arg1); + u8 *tlut = (u8 *) LOAD_ASSET(common_tlut_lakitu_reverse); Vtx *vtx = (Vtx *) LOAD_ASSET(common_vtx_also_lakitu); - init_texture_object(objectIndex, (u8*) common_tlut_lakitu_reverse, load_lakitu_textures_x64(sLakituReverseTextures, ARRAY_COUNT(sLakituReverseTextures)), 72, (u16) 56); - gObjectList[objectIndex].activeTexture = D_8018C028; + init_texture_object(objectIndex, tlut, sLakituReverseTextures, 72, (u16) 56); + gObjectList[objectIndex].activeTexture = *gObjectList[objectIndex].textureList; gObjectList[objectIndex].vertex = vtx; gObjectList[objectIndex].pos[2] = var; gObjectList[objectIndex].pos[1] = var; @@ -3614,7 +3621,7 @@ void func_8007AA44(s32 playerId) { func_8007A910(playerId); objectIndex = gIndexLakituList[playerId]; - D_8018C028 = D_80183FA8[playerId]; + gLakituTexturePtr = &gLakituTextureBuffer[playerId]; switch (gObjectList[objectIndex].unk_0D8) { case 1: func_80079114(objectIndex, playerId, 2); diff --git a/src/update_objects.h b/src/update_objects.h index 5ad12ad4a..5b286488c 100644 --- a/src/update_objects.h +++ b/src/update_objects.h @@ -59,7 +59,7 @@ bool func_80072F88(s32, s32, s32, s32, s32, s32); bool func_800730BC(s32, s32, s32, s32, s32, s32); s32 func_8007326C(s32, s32, s32, s32, s32, s32); void func_80073404(s32, u8, u8, Vtx*); -void init_texture_object(s32, u8*, u8*, u8, u16); +void init_texture_object(s32, u8*, const char**, u8, u16); void func_8007348C(s32, u8*, u8, u8, Vtx *); void func_800734D4(void); void update_neon_texture(s32); @@ -103,15 +103,15 @@ void func_80074344(s32, f32*, f32, f32, f32, s32, s32); void func_80074478(s32); void func_800744A0(s32); void func_800744CC(void); -void func_80074510(uintptr_t, void*, size_t); +void func_80074510(uintptr_t, void*, size_t, size_t); void func_800745C8(s32, uintptr_t); void func_8007466C(s32, uintptr_t); void func_80074704(s32, uintptr_t); -u8 *func_80074790(s32, u8*); -void func_800747F0(s32, u8*); -void func_80074894(s32, u8*); -void func_800748C4(s32, u8*); -void func_800748F4(s32, u8*); +size_t func_80074790(s32, const char**); +void func_800747F0(s32, const char**); +void func_80074894(s32, const char**); +void func_800748C4(s32, const char**); +void func_800748F4(s32, const char**); void func_80074924(s32); void func_80074D94(s32); void func_80074E28(s32);