diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index c0b532b10..59c0e2bbd 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -11616,6 +11616,23 @@ function smlua_text_utils_castle_secret_stars_replace(name) -- ... end +--- @return string +--- Gets the castle secret stars text +function smlua_text_utils_castle_secret_stars_get() + -- ... +end + +--- @return integer +--- Gets the index of the mod that replaced the castle secret stars text +function smlua_text_utils_castle_secret_stars_mod_index() + -- ... +end + +--- Resets the castle secret stars text +function smlua_text_utils_castle_secret_stars_reset() + -- ... +end + --- @param index integer --- @param text string --- Replace extra text (e.g. one of the castle's secret stars) with `text` @@ -11623,6 +11640,26 @@ function smlua_text_utils_extra_text_replace(index, text) -- ... end +--- @param index integer +--- @return string +--- Gets the extra text at `index` +function smlua_text_utils_extra_text_get(index) + -- ... +end + +--- @param index integer +--- @return integer +--- Gets the index of the mod that replaced the extra text at `index` +function smlua_text_utils_extra_text_mod_index(index) + -- ... +end + +--- @param index integer +--- Resets the extra text at `index` +function smlua_text_utils_extra_text_reset(index) + -- ... +end + --- @return string --- Gets the current language function smlua_text_utils_get_language() diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md index 46f2aef50..6883780e3 100644 --- a/docs/lua/functions-6.md +++ b/docs/lua/functions-6.md @@ -6724,6 +6724,69 @@ Replaces the castle secret stars text with `name`
+## [smlua_text_utils_castle_secret_stars_get](#smlua_text_utils_castle_secret_stars_get) + +### Description +Gets the castle secret stars text + +### Lua Example +`local stringValue = smlua_text_utils_castle_secret_stars_get()` + +### Parameters +- None + +### Returns +- `string` + +### C Prototype +`const char* smlua_text_utils_castle_secret_stars_get();` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_castle_secret_stars_mod_index](#smlua_text_utils_castle_secret_stars_mod_index) + +### Description +Gets the index of the mod that replaced the castle secret stars text + +### Lua Example +`local integerValue = smlua_text_utils_castle_secret_stars_mod_index()` + +### Parameters +- None + +### Returns +- `integer` + +### C Prototype +`s32 smlua_text_utils_castle_secret_stars_mod_index();` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_castle_secret_stars_reset](#smlua_text_utils_castle_secret_stars_reset) + +### Description +Resets the castle secret stars text + +### Lua Example +`smlua_text_utils_castle_secret_stars_reset()` + +### Parameters +- None + +### Returns +- None + +### C Prototype +`void smlua_text_utils_castle_secret_stars_reset();` + +[:arrow_up_small:](#) + +
+ ## [smlua_text_utils_extra_text_replace](#smlua_text_utils_extra_text_replace) ### Description @@ -6748,6 +6811,75 @@ Replace extra text (e.g. one of the castle's secret stars) with `text`
+## [smlua_text_utils_extra_text_get](#smlua_text_utils_extra_text_get) + +### Description +Gets the extra text at `index` + +### Lua Example +`local stringValue = smlua_text_utils_extra_text_get(index)` + +### Parameters +| Field | Type | +| ----- | ---- | +| index | `integer` | + +### Returns +- `string` + +### C Prototype +`const char* smlua_text_utils_extra_text_get(s16 index);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_extra_text_mod_index](#smlua_text_utils_extra_text_mod_index) + +### Description +Gets the index of the mod that replaced the extra text at `index` + +### Lua Example +`local integerValue = smlua_text_utils_extra_text_mod_index(index)` + +### Parameters +| Field | Type | +| ----- | ---- | +| index | `integer` | + +### Returns +- `integer` + +### C Prototype +`s32 smlua_text_utils_extra_text_mod_index(s16 index);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_extra_text_reset](#smlua_text_utils_extra_text_reset) + +### Description +Resets the extra text at `index` + +### Lua Example +`smlua_text_utils_extra_text_reset(index)` + +### Parameters +| Field | Type | +| ----- | ---- | +| index | `integer` | + +### Returns +- None + +### C Prototype +`void smlua_text_utils_extra_text_reset(s16 index);` + +[:arrow_up_small:](#) + +
+ ## [smlua_text_utils_get_language](#smlua_text_utils_get_language) ### Description diff --git a/docs/lua/functions.md b/docs/lua/functions.md index bbef2c349..2f17aca04 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -2069,7 +2069,13 @@ - [smlua_text_utils_act_name_mod_index](functions-6.md#smlua_text_utils_act_name_mod_index) - [smlua_text_utils_act_name_reset](functions-6.md#smlua_text_utils_act_name_reset) - [smlua_text_utils_castle_secret_stars_replace](functions-6.md#smlua_text_utils_castle_secret_stars_replace) + - [smlua_text_utils_castle_secret_stars_get](functions-6.md#smlua_text_utils_castle_secret_stars_get) + - [smlua_text_utils_castle_secret_stars_mod_index](functions-6.md#smlua_text_utils_castle_secret_stars_mod_index) + - [smlua_text_utils_castle_secret_stars_reset](functions-6.md#smlua_text_utils_castle_secret_stars_reset) - [smlua_text_utils_extra_text_replace](functions-6.md#smlua_text_utils_extra_text_replace) + - [smlua_text_utils_extra_text_get](functions-6.md#smlua_text_utils_extra_text_get) + - [smlua_text_utils_extra_text_mod_index](functions-6.md#smlua_text_utils_extra_text_mod_index) + - [smlua_text_utils_extra_text_reset](functions-6.md#smlua_text_utils_extra_text_reset) - [smlua_text_utils_get_language](functions-6.md#smlua_text_utils_get_language)
diff --git a/src/game/level_info.c b/src/game/level_info.c index f7a467c30..835ceca31 100644 --- a/src/game/level_info.c +++ b/src/game/level_info.c @@ -4,6 +4,7 @@ #include "course_table.h" #include "game/hardcoded.h" #include "game/memory.h" +#include "game/segment2.h" #include "level_info.h" #include "level_table.h" #include "save_file.h" @@ -14,9 +15,6 @@ #ifdef VERSION_EU extern s32 gInGameLanguage; #include "eu_translation.h" -#else -extern u8 *seg2_course_name_table[]; -extern u8 *seg2_act_name_table[]; #endif static const struct { const char *str; u8 c; u8 menu; } sSm64CharMap[] = { @@ -160,7 +158,7 @@ static void decapitalize_string_sm64(u8 *str64) { } } -void *get_course_name_table(void) { +void **get_course_name_table(void) { void **courseNameTbl = segmented_to_virtual(seg2_course_name_table); #ifdef VERSION_EU @@ -174,7 +172,21 @@ void *get_course_name_table(void) { return courseNameTbl; } -void *get_act_name_table(void) { +void **get_course_name_table_original(void) { + void **courseNameTblOrig = segmented_to_virtual(seg2_course_name_table_original); + +#ifdef VERSION_EU + switch (gInGameLanguage) { + case LANGUAGE_ENGLISH: courseNameTblOrig = segmented_to_virtual(course_name_table_eu_en_original); break; + case LANGUAGE_FRENCH: courseNameTblOrig = segmented_to_virtual(course_name_table_eu_fr_original); break; + case LANGUAGE_GERMAN: courseNameTblOrig = segmented_to_virtual(course_name_table_eu_de_original); break; + } +#endif + + return courseNameTblOrig; +} + +void **get_act_name_table(void) { void **actNameTbl = segmented_to_virtual(seg2_act_name_table); #ifdef VERSION_EU @@ -188,6 +200,20 @@ void *get_act_name_table(void) { return actNameTbl; } +void **get_act_name_table_original(void) { + void **actNameTblOrig = segmented_to_virtual(seg2_act_name_table_original); + +#ifdef VERSION_EU + switch (gInGameLanguage) { + case LANGUAGE_ENGLISH: actNameTblOrig = segmented_to_virtual(act_name_table_eu_en_original); break; + case LANGUAGE_FRENCH: actNameTblOrig = segmented_to_virtual(act_name_table_eu_fr_original); break; + case LANGUAGE_GERMAN: actNameTblOrig = segmented_to_virtual(act_name_table_eu_de_original); break; + } +#endif + + return actNameTblOrig; +} + const char *get_level_name_ascii(s16 courseNum, s16 levelNum, s16 areaIndex, s16 charCase) { static char output[256]; @@ -201,8 +227,8 @@ const char *get_level_name_ascii(s16 courseNum, s16 levelNum, s16 areaIndex, s16 } } - if (courseNum >= 0 && courseNum <= COURSE_MAX && gReplacedActNameTable[courseNum]->modIndex != -1) { - snprintf(output, 256, "%s", gReplacedActNameTable[courseNum]->name); + if (courseNum >= 0 && courseNum <= COURSE_MAX && gReplacedCourseActNameTable[courseNum].courseName.modNum != 0) { + snprintf(output, 256, "%s", gReplacedCourseActNameTable[courseNum].courseName.name.value); } else if (!hasCustomName) { @@ -266,9 +292,9 @@ const char *get_star_name_ascii(s16 courseNum, s16 starNum, s16 charCase) { s16 starIndex = starNum - 1; if (starIndex >= 0 && starIndex < MAX_ACTS_AND_100_COINS && - courseNum >= 0 && courseNum < COURSE_END && - gReplacedActNameTable[courseNum]->actName && gReplacedActNameTable[courseNum]->actName[starIndex].modIndex != -1) { - snprintf(output, 256, "%s", gReplacedActNameTable[courseNum]->actName[starIndex].name); + courseNum >= 0 && courseNum <= COURSE_MAX && + gReplacedCourseActNameTable[courseNum].actName[starIndex].modNum != 0) { + snprintf(output, 256, "%s", gReplacedCourseActNameTable[courseNum].actName[starIndex].name.value); } // Main courses: BOB to RR diff --git a/src/game/level_info.h b/src/game/level_info.h index 49b760f87..9ffb3afe9 100644 --- a/src/game/level_info.h +++ b/src/game/level_info.h @@ -3,8 +3,10 @@ #include -void *get_course_name_table(void); -void *get_act_name_table(void); +void **get_course_name_table(void); +void **get_course_name_table_original(void); +void **get_act_name_table(void); +void **get_act_name_table_original(void); /* |description| Returns the name of the level corresponding to `courseNum`, `levelNum` and `areaIndex` as an ASCII (human readable) string. Set `charCase` to 1 to capitalize or -1 to decapitalize the returned string diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 16f3e16d5..f02fa04d6 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -34564,6 +34564,51 @@ int smlua_func_smlua_text_utils_castle_secret_stars_replace(lua_State* L) { return 1; } +int smlua_func_smlua_text_utils_castle_secret_stars_get(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_castle_secret_stars_get", 0, top); + return 0; + } + + + lua_pushstring(L, smlua_text_utils_castle_secret_stars_get()); + + return 1; +} + +int smlua_func_smlua_text_utils_castle_secret_stars_mod_index(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_castle_secret_stars_mod_index", 0, top); + return 0; + } + + + lua_pushinteger(L, smlua_text_utils_castle_secret_stars_mod_index()); + + return 1; +} + +int smlua_func_smlua_text_utils_castle_secret_stars_reset(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_castle_secret_stars_reset", 0, top); + return 0; + } + + + smlua_text_utils_castle_secret_stars_reset(); + + return 1; +} + int smlua_func_smlua_text_utils_extra_text_replace(lua_State* L) { if (L == NULL) { return 0; } @@ -34583,6 +34628,57 @@ int smlua_func_smlua_text_utils_extra_text_replace(lua_State* L) { return 1; } +int smlua_func_smlua_text_utils_extra_text_get(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_extra_text_get", 1, top); + return 0; + } + + s16 index = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_extra_text_get"); return 0; } + + lua_pushstring(L, smlua_text_utils_extra_text_get(index)); + + return 1; +} + +int smlua_func_smlua_text_utils_extra_text_mod_index(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_extra_text_mod_index", 1, top); + return 0; + } + + s16 index = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_extra_text_mod_index"); return 0; } + + lua_pushinteger(L, smlua_text_utils_extra_text_mod_index(index)); + + return 1; +} + +int smlua_func_smlua_text_utils_extra_text_reset(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_extra_text_reset", 1, top); + return 0; + } + + s16 index = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_extra_text_reset"); return 0; } + + smlua_text_utils_extra_text_reset(index); + + return 1; +} + int smlua_func_smlua_text_utils_get_language(UNUSED lua_State* L) { if (L == NULL) { return 0; } @@ -37302,7 +37398,13 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "smlua_text_utils_act_name_mod_index", smlua_func_smlua_text_utils_act_name_mod_index); smlua_bind_function(L, "smlua_text_utils_act_name_reset", smlua_func_smlua_text_utils_act_name_reset); smlua_bind_function(L, "smlua_text_utils_castle_secret_stars_replace", smlua_func_smlua_text_utils_castle_secret_stars_replace); + smlua_bind_function(L, "smlua_text_utils_castle_secret_stars_get", smlua_func_smlua_text_utils_castle_secret_stars_get); + smlua_bind_function(L, "smlua_text_utils_castle_secret_stars_mod_index", smlua_func_smlua_text_utils_castle_secret_stars_mod_index); + smlua_bind_function(L, "smlua_text_utils_castle_secret_stars_reset", smlua_func_smlua_text_utils_castle_secret_stars_reset); smlua_bind_function(L, "smlua_text_utils_extra_text_replace", smlua_func_smlua_text_utils_extra_text_replace); + smlua_bind_function(L, "smlua_text_utils_extra_text_get", smlua_func_smlua_text_utils_extra_text_get); + smlua_bind_function(L, "smlua_text_utils_extra_text_mod_index", smlua_func_smlua_text_utils_extra_text_mod_index); + smlua_bind_function(L, "smlua_text_utils_extra_text_reset", smlua_func_smlua_text_utils_extra_text_reset); smlua_bind_function(L, "smlua_text_utils_get_language", smlua_func_smlua_text_utils_get_language); // sound_init.h diff --git a/src/pc/lua/utils/smlua_text_utils.c b/src/pc/lua/utils/smlua_text_utils.c index 573c9b0b3..89d525f9c 100644 --- a/src/pc/lua/utils/smlua_text_utils.c +++ b/src/pc/lua/utils/smlua_text_utils.c @@ -17,55 +17,90 @@ extern s32 gInGameLanguage; #endif static bool sReplacedDialog[DIALOG_COUNT] = { 0 }; -static bool sReplacedCourseName[COURSE_COUNT+2] = { 0 }; -static bool sReplacedActName[(COURSE_RR+2)*6] = { 0 }; - -#define INVALID_COURSE_NUM(courseNum) (smlua_level_util_get_info_from_course_num(courseNum) == NULL && !COURSE_IS_VALID_COURSE(courseNum)) void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64); -struct CourseName *gReplacedActNameTable[COURSE_END]; +/* +--------------------------------------------------- +Mapping gReplacedCourseActNameTable <-> seg2 tables +--------------------------------------------------- + +For courseNum from COURSE_BOB to COURSE_RR: +- gReplacedCourseActNameTable[courseNum].courseName <-> seg2_course_name_table[courseNum - 1] +- gReplacedCourseActNameTable[courseNum].actName[0..5] <-> seg2_act_name_table[(courseNum - 1) * 6 + (0..5)] + (7th act name doesn't map to anything, but can be retrieved with `smlua_text_utils_act_name_get`) + +For courseNum from COURSE_BITDW to COURSE_CAKE_END: +- gReplacedCourseActNameTable[courseNum].courseName <-> seg2_course_name_table[courseNum - 1] +- gReplacedCourseActNameTable[courseNum].actName[0..6] don't map to anything, but they can be retrieved with `smlua_text_utils_act_name_get` + +For castle secret stars and extra text: +- gReplacedCourseActNameTable[COURSE_END].courseName <-> seg2_course_name_table[COURSE_MAX] (which is seg2_course_name_table_castle_secret_stars) +- gReplacedCourseActNameTable[COURSE_END].actName[0..6] <-> seg2_act_name_table[COURSE_STAGES_MAX * 6 + (0..6)] (which are extra_text_0~6) +*/ +struct CourseActNames gReplacedCourseActNameTable[COURSE_END + 1] = { 0 }; static bool sSmluaTextUtilsInited = false; +#define smlua_text_utils_init_from_vanilla(obj, tableFunc, tableOrigFunc, tableOffset) { \ + char buffer[50]; \ + convert_string_sm64_to_ascii(buffer, tableOrigFunc()[tableOffset]); \ + snprintf(obj.name.value, sizeof(obj.name.value), "%s", buffer); \ + obj.name.get_table = tableFunc; \ + obj.name.offset = tableOffset; \ + snprintf(obj.orig.value, sizeof(obj.orig.value), "%s", buffer); \ + obj.orig.get_table = tableOrigFunc; \ + obj.orig.offset = tableOffset; \ + tableFunc()[tableOffset] = tableOrigFunc()[tableOffset]; \ +} + // Save all vanilla act names and course names void smlua_text_utils_init(void) { - void **actNameTbl = get_act_name_table(); - void **courseNameTbl = get_course_name_table(); - char courseBuffer[50]; - char actBuffer[50]; + memset(gReplacedCourseActNameTable, 0, sizeof(gReplacedCourseActNameTable)); - // Course/Star names - for (s16 courseNum = 0; courseNum < COURSE_END; courseNum++) { - gReplacedActNameTable[courseNum] = calloc(1, sizeof(struct CourseName)); - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - convert_string_sm64_to_ascii(courseBuffer, segmented_to_virtual(courseNameTbl[courseNum])); - snprintf(courseActNames->name, 50, "%s", courseBuffer); - snprintf(courseActNames->orig, 50, "%s", courseBuffer); - courseActNames->modIndex = -1; - courseActNames->actName = NULL; + // Vanilla courses + for (s16 courseNum = COURSE_MIN; courseNum <= COURSE_MAX; ++courseNum) { + smlua_text_utils_init_from_vanilla( + gReplacedCourseActNameTable[courseNum].courseName, + get_course_name_table, + get_course_name_table_original, + courseNum - 1 + ); - // Individual acts + // Vanilla acts if (COURSE_IS_MAIN_COURSE(courseNum)) { - courseActNames->actName = calloc(MAX_ACTS_AND_100_COINS, sizeof(struct ActName)); - for (s16 actNum = 0; actNum < MAX_ACTS; actNum++) { - convert_string_sm64_to_ascii(actBuffer, segmented_to_virtual(actNameTbl[courseNum * MAX_ACTS + actNum])); - snprintf(courseActNames->actName[actNum].name, 50, "%s", actBuffer); - snprintf(courseActNames->actName[actNum].orig, 50, "%s", actBuffer); - courseActNames->actName[actNum].modIndex = -1; + for (s16 actIndex = 0; actIndex < MAX_ACTS; ++actIndex) { + smlua_text_utils_init_from_vanilla( + gReplacedCourseActNameTable[courseNum].actName[actIndex], + get_act_name_table, + get_act_name_table_original, + (courseNum - 1) * MAX_ACTS + actIndex + ); } - courseActNames->actName[MAX_ACTS_AND_100_COINS - 1].modIndex = -1; } } + + // Vanilla castle secrets and extras + smlua_text_utils_init_from_vanilla( + gReplacedCourseActNameTable[COURSE_END].courseName, + get_course_name_table, + get_course_name_table_original, + COURSE_MAX + ); + for (s16 actIndex = 0; actIndex < MAX_ACTS_AND_100_COINS; ++actIndex) { + smlua_text_utils_init_from_vanilla( + gReplacedCourseActNameTable[COURSE_END].actName[actIndex], + get_act_name_table, + get_act_name_table_original, + COURSE_STAGES_MAX * MAX_ACTS + actIndex + ); + } + sSmluaTextUtilsInited = true; } void smlua_text_utils_shutdown(void) { if (sSmluaTextUtilsInited) { - for (s16 courseNum = 0; courseNum < COURSE_END; courseNum++) { - free(gReplacedActNameTable[courseNum]->actName); - free(gReplacedActNameTable[courseNum]); - } sSmluaTextUtilsInited = false; } } @@ -85,48 +120,55 @@ static bool str_starts_with_spaces(const char* str) { return true; } +static void smlua_text_utils_reset_course_or_act_name(struct ReplacedName *name) { + if (name->name.get_table && name->orig.get_table) { + void **tblName = name->name.get_table() + name->name.offset; + void **tblOrig = name->orig.get_table() + name->orig.offset; + if (*tblName != *tblOrig) { + free(*tblName); + *tblName = *tblOrig; + } + } + memcpy(name->name.value, name->orig.value, sizeof(name->name.value)); + name->modNum = 0; +} + +static void smlua_text_utils_replace_course_or_act_name(struct ReplacedName *name, const char *replacement, s32 modIndex) { + replacement += 3 * str_starts_with_spaces(replacement); + if (name->name.get_table && name->orig.get_table) { + void **tblName = name->name.get_table() + name->name.offset; + void **tblOrig = name->orig.get_table() + name->orig.offset; + if (*tblName != *tblOrig) { + free(*tblName); + } + *tblName = smlua_text_utils_convert(replacement); + } + snprintf(name->name.value, sizeof(name->name.value), "%s", replacement); + name->modNum = modIndex + 1; +} + void smlua_text_utils_reset_all(void) { void **dialogTable = NULL; - void **actNameTbl = NULL; - void **courseNameTbl = NULL; void **dialogTableOrg = NULL; - void **actNameTblOrg = NULL; - void **courseNameTblOrg = NULL; #ifdef VERSION_EU switch (gInGameLanguage) { case LANGUAGE_ENGLISH: dialogTable = segmented_to_virtual(dialog_table_eu_en); - actNameTbl = segmented_to_virtual(act_name_table_eu_en); - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); dialogTableOrg = segmented_to_virtual(dialog_table_eu_en_original); - actNameTblOrg = segmented_to_virtual(act_name_table_eu_en_original); - courseNameTblOrg = segmented_to_virtual(course_name_table_eu_en_original); break; case LANGUAGE_FRENCH: dialogTable = segmented_to_virtual(dialog_table_eu_fr); - actNameTbl = segmented_to_virtual(act_name_table_eu_fr); - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); dialogTableOrg = segmented_to_virtual(dialog_table_eu_fr_original); - actNameTblOrg = segmented_to_virtual(act_name_table_eu_fr_original); - courseNameTblOrg = segmented_to_virtual(course_name_table_eu_fr_original); break; case LANGUAGE_GERMAN: dialogTable = segmented_to_virtual(dialog_table_eu_de); - actNameTbl = segmented_to_virtual(act_name_table_eu_de); - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); dialogTableOrg = segmented_to_virtual(dialog_table_eu_de_original); - actNameTblOrg = segmented_to_virtual(act_name_table_eu_de_original); - courseNameTblOrg = segmented_to_virtual(course_name_table_eu_de_original); break; } #else dialogTable = segmented_to_virtual(seg2_dialog_table); - actNameTbl = segmented_to_virtual(seg2_act_name_table); - courseNameTbl = segmented_to_virtual(seg2_course_name_table); dialogTableOrg = segmented_to_virtual(seg2_dialog_original); - actNameTblOrg = segmented_to_virtual(seg2_act_name_table_original); - courseNameTblOrg = segmented_to_virtual(seg2_course_name_table_original); #endif for (s32 i = 0; i < DIALOG_COUNT; i++) { @@ -138,32 +180,17 @@ void smlua_text_utils_reset_all(void) { sReplacedDialog[i] = false; } - for (s32 i = 0; i < COURSE_COUNT+2; i++) { - if (!sReplacedCourseName[i]) { continue; } - free((u8*)courseNameTbl[i]); - courseNameTbl[i] = segmented_to_virtual(courseNameTblOrg[i]); - sReplacedCourseName[i] = false; - } - - for (s32 i = 0; i < (COURSE_RR+2)*6; i++) { - if (!sReplacedActName[i]) { continue; } - free((u8*)actNameTbl[i]); - actNameTbl[i] = segmented_to_virtual(actNameTblOrg[i]); - sReplacedActName[i] = false; - } - if (sSmluaTextUtilsInited) { - for (s32 courseNum = 0; courseNum < COURSE_COUNT; courseNum++) { - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - snprintf(courseActNames->name, 50, "%s", courseActNames->orig); - courseActNames->modIndex = -1; + for (s16 courseNum = 0; courseNum < COURSE_END; courseNum++) { - // Individual acts - if (COURSE_IS_MAIN_COURSE(courseNum)) { - for (s16 actNum = 0; actNum < MAX_ACTS_AND_100_COINS; actNum++) { - snprintf(courseActNames->actName[actNum].name, 50, "%s", courseActNames->actName[actNum].orig); - courseActNames->actName[actNum].modIndex = -1; - } + // Restore vanilla course names + struct ReplacedName *courseName = &gReplacedCourseActNameTable[courseNum].courseName; + smlua_text_utils_reset_course_or_act_name(courseName); + + // Restore vanilla act names + for (s16 actIndex = 0; actIndex < MAX_ACTS_AND_100_COINS; actIndex++) { + struct ReplacedName *actName = &gReplacedCourseActNameTable[courseNum].actName[actIndex]; + smlua_text_utils_reset_course_or_act_name(actName); } } } @@ -205,14 +232,13 @@ void smlua_text_utils_dialog_replace(enum DialogId dialogId, UNUSED u32 unused, } void smlua_text_utils_course_acts_replace(s16 courseNum, const char* courseName, const char* act1, const char* act2, const char* act3, const char* act4, const char* act5, const char* act6) { - if (courseNum <= 0 || courseNum > COURSE_RR) { return; } - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - snprintf(courseActNames->name, 256, "%s", courseName + (3 * (strlen(courseName) > 3))); - courseActNames->modIndex = gLuaActiveMod->index; + if (!COURSE_IS_VALID_COURSE(courseNum)) { return; } + + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum]; + smlua_text_utils_replace_course_or_act_name(&courseActNames->courseName, courseName, gLuaActiveMod->index); #define REPLACE_ACT_NAME(i) { \ - snprintf(courseActNames->actName[i-1].name, 256, "%s", act##i); \ - courseActNames->actName[i-1].modIndex = gLuaActiveMod->index; \ + smlua_text_utils_replace_course_or_act_name(&courseActNames->actName[i - 1], act##i, gLuaActiveMod->index); \ } REPLACE_ACT_NAME(1); @@ -224,107 +250,109 @@ void smlua_text_utils_course_acts_replace(s16 courseNum, const char* courseName, } void smlua_text_utils_course_name_replace(s16 courseNum, const char* name) { - if (INVALID_COURSE_NUM(courseNum)) { return; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return; } - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - snprintf(courseActNames->name, 256, "%s", name); - courseActNames->modIndex = gLuaActiveMod->index; + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum]; + smlua_text_utils_replace_course_or_act_name(&courseActNames->courseName, name, gLuaActiveMod->index); } const char* smlua_text_utils_course_name_get(s16 courseNum) { - if (INVALID_COURSE_NUM(courseNum)) { return NULL; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return NULL; } - return gReplacedActNameTable[courseNum]->name; + return gReplacedCourseActNameTable[courseNum].courseName.name.value; } s32 smlua_text_utils_course_name_mod_index(s16 courseNum) { - if (INVALID_COURSE_NUM(courseNum)) { return -1; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return -1; } - return gReplacedActNameTable[courseNum]->modIndex; + return (s32) gReplacedCourseActNameTable[courseNum].courseName.modNum - 1; } void smlua_text_utils_course_name_reset(s16 courseNum) { - if (INVALID_COURSE_NUM(courseNum)) { return; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return; } - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - snprintf(courseActNames->name, 50, "%s", courseActNames->orig); - courseActNames->modIndex = -1; + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum]; + smlua_text_utils_reset_course_or_act_name(&courseActNames->courseName); } void smlua_text_utils_act_name_replace(s16 courseNum, u8 actNum, const char* name) { - if (INVALID_COURSE_NUM(courseNum) || actNum >= MAX_ACTS_AND_100_COINS) { return; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return; } + if (actNum < 1 || actNum > MAX_ACTS_AND_100_COINS) { return; } - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - - snprintf(courseActNames->actName[actNum].name, 256, "%s", name); - courseActNames->actName[actNum].modIndex = gLuaActiveMod->index; + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum]; + smlua_text_utils_replace_course_or_act_name(&courseActNames->actName[actNum - 1], name, gLuaActiveMod->index); } const char* smlua_text_utils_act_name_get(s16 courseNum, u8 actNum) { - if (INVALID_COURSE_NUM(courseNum) || actNum >= MAX_ACTS_AND_100_COINS) { return NULL; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return NULL; } + if (actNum < 1 || actNum > MAX_ACTS_AND_100_COINS) { return NULL; } - return gReplacedActNameTable[courseNum]->actName[actNum].name; + return gReplacedCourseActNameTable[courseNum].actName[actNum - 1].name.value; } s32 smlua_text_utils_act_name_mod_index(s16 courseNum, u8 actNum) { - if (INVALID_COURSE_NUM(courseNum) || actNum >= MAX_ACTS_AND_100_COINS) { return false; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return -1; } + if (actNum < 1 || actNum > MAX_ACTS_AND_100_COINS) { return -1; } - return gReplacedActNameTable[courseNum]->actName[actNum].modIndex; + return (s32) gReplacedCourseActNameTable[courseNum].actName[actNum - 1].modNum - 1; } void smlua_text_utils_act_name_reset(s16 courseNum, u8 actNum) { - if (INVALID_COURSE_NUM(courseNum) || actNum >= MAX_ACTS_AND_100_COINS) { return; } + if (!COURSE_IS_VALID_COURSE(courseNum)) { return; } + if (actNum < 1 || actNum > MAX_ACTS_AND_100_COINS) { return; } - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - snprintf(courseActNames->actName[actNum].name, 50, "%s", courseActNames->actName[actNum].orig); - courseActNames->actName[actNum].modIndex = gLuaActiveMod->index; + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum]; + smlua_text_utils_reset_course_or_act_name(&courseActNames->actName[actNum - 1]); } void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName) { - if (courseNum <= COURSE_RR || courseNum > COURSE_COUNT) { return; } - /* - s16 courseOffset = courseNum - 1; + if (courseNum <= COURSE_STAGES_MAX || courseNum > COURSE_MAX) { return; } - void **courseNameTbl = get_course_name_table(); - - if (sReplacedCourseName[courseOffset]) { - free(courseNameTbl[courseOffset]); - } - - courseNameTbl[courseOffset] = smlua_text_utils_convert(courseName); - sReplacedCourseName[courseOffset] = true; - */ - - struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; - snprintf(courseActNames->name, 256, "%s", courseName + (3 * str_starts_with_spaces(courseName))); - courseActNames->modIndex = gLuaActiveMod->index; + smlua_text_utils_course_name_replace(courseNum, courseName); } void smlua_text_utils_castle_secret_stars_replace(const char* name) { - s16 courseOffset = COURSE_COUNT; + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[COURSE_END]; + smlua_text_utils_replace_course_or_act_name(&courseActNames->courseName, name, gLuaActiveMod->index); +} - void **courseNameTbl = get_course_name_table(); +const char* smlua_text_utils_castle_secret_stars_get() { + return gReplacedCourseActNameTable[COURSE_END].courseName.name.value; +} - if (sReplacedCourseName[courseOffset]) { - free(courseNameTbl[courseOffset]); - } +s32 smlua_text_utils_castle_secret_stars_mod_index() { + return (s32) gReplacedCourseActNameTable[COURSE_END].courseName.modNum - 1; +} - courseNameTbl[courseOffset] = smlua_text_utils_convert(name); - sReplacedCourseName[courseOffset] = true; +void smlua_text_utils_castle_secret_stars_reset() { + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[COURSE_END]; + smlua_text_utils_reset_course_or_act_name(&courseActNames->courseName); } void smlua_text_utils_extra_text_replace(s16 index, const char* text) { - if (index < 0 || index > 6) { return; } - index = (COURSE_RR * 6 + index); + if (index < 0 || index > MAX_ACTS_AND_100_COINS) { return; } - void **actNameTbl = get_act_name_table(); + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[COURSE_END]; + smlua_text_utils_replace_course_or_act_name(&courseActNames->actName[index], text, gLuaActiveMod->index); +} - if (sReplacedActName[index]) { - free(actNameTbl[index]); - } +const char* smlua_text_utils_extra_text_get(s16 index) { + if (index < 0 || index > MAX_ACTS_AND_100_COINS) { return NULL; } - actNameTbl[index] = smlua_text_utils_convert(text); - sReplacedActName[index] = true; + return gReplacedCourseActNameTable[COURSE_END].actName[index].name.value; +} + +s32 smlua_text_utils_extra_text_mod_index(s16 index) { + if (index < 0 || index > MAX_ACTS_AND_100_COINS) { return -1; } + + return (s32) gReplacedCourseActNameTable[COURSE_END].actName[index].modNum - 1; +} + +void smlua_text_utils_extra_text_reset(s16 index) { + if (index < 0 || index > MAX_ACTS_AND_100_COINS) { return; } + + struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[COURSE_END]; + smlua_text_utils_reset_course_or_act_name(&courseActNames->actName[index]); } const char* smlua_text_utils_get_language(void) { diff --git a/src/pc/lua/utils/smlua_text_utils.h b/src/pc/lua/utils/smlua_text_utils.h index b2a61e0f1..f6cc69901 100644 --- a/src/pc/lua/utils/smlua_text_utils.h +++ b/src/pc/lua/utils/smlua_text_utils.h @@ -7,20 +7,24 @@ #define MAX_ACTS 6 #define MAX_ACTS_AND_100_COINS 7 -struct ActName { - char name[256]; - char orig[256]; - s32 modIndex; +struct NameTable { + char value[256]; + void **(*get_table)(void); + u32 offset; }; -struct CourseName { - struct ActName *actName; - char name[256]; - char orig[256]; - s32 modIndex; +struct ReplacedName { + struct NameTable name; + struct NameTable orig; + u32 modNum; // modIndex + 1 (default value of 0 is more convenient than -1) }; -extern struct CourseName *gReplacedActNameTable[]; +struct CourseActNames { + struct ReplacedName courseName; + struct ReplacedName actName[MAX_ACTS_AND_100_COINS]; // indexed by actIndex (actNum - 1) +}; + +extern struct CourseActNames gReplacedCourseActNameTable[]; // indexed by COURSE_* constants void smlua_text_utils_init(void); void smlua_text_utils_shutdown(void); @@ -50,8 +54,20 @@ s32 smlua_text_utils_act_name_mod_index(s16 courseNum, u8 actNum); void smlua_text_utils_act_name_reset(s16 courseNum, u8 actNum); /* |description|Replaces the castle secret stars text with `name`|descriptionEnd| */ void smlua_text_utils_castle_secret_stars_replace(const char* name); +/* |description|Gets the castle secret stars text|descriptionEnd| */ +const char* smlua_text_utils_castle_secret_stars_get(); +/* |description|Gets the index of the mod that replaced the castle secret stars text|descriptionEnd| */ +s32 smlua_text_utils_castle_secret_stars_mod_index(); +/* |description|Resets the castle secret stars text|descriptionEnd| */ +void smlua_text_utils_castle_secret_stars_reset(); /* |description|Replace extra text (e.g. one of the castle's secret stars) with `text`|descriptionEnd| */ void smlua_text_utils_extra_text_replace(s16 index, const char* text); +/* |description|Gets the extra text at `index`|descriptionEnd| */ +const char* smlua_text_utils_extra_text_get(s16 index); +/* |description|Gets the index of the mod that replaced the extra text at `index`|descriptionEnd| */ +s32 smlua_text_utils_extra_text_mod_index(s16 index); +/* |description|Resets the extra text at `index`|descriptionEnd| */ +void smlua_text_utils_extra_text_reset(s16 index); /* |description|Gets the current language|descriptionEnd| */ const char* smlua_text_utils_get_language(void);