fix custom course and act names (#869)
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run

This commit is contained in:
PeachyPeach 2025-06-27 19:00:58 +02:00 committed by GitHub
parent 2ae95808ee
commit 075e76b71a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 507 additions and 158 deletions

View file

@ -11616,6 +11616,23 @@ function smlua_text_utils_castle_secret_stars_replace(name)
-- ... -- ...
end 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 index integer
--- @param text string --- @param text string
--- Replace extra text (e.g. one of the castle's secret stars) with `text` --- 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 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 --- @return string
--- Gets the current language --- Gets the current language
function smlua_text_utils_get_language() function smlua_text_utils_get_language()

View file

@ -6724,6 +6724,69 @@ Replaces the castle secret stars text with `name`
<br /> <br />
## [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:](#)
<br />
## [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:](#)
<br />
## [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:](#)
<br />
## [smlua_text_utils_extra_text_replace](#smlua_text_utils_extra_text_replace) ## [smlua_text_utils_extra_text_replace](#smlua_text_utils_extra_text_replace)
### Description ### Description
@ -6748,6 +6811,75 @@ Replace extra text (e.g. one of the castle's secret stars) with `text`
<br /> <br />
## [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:](#)
<br />
## [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:](#)
<br />
## [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:](#)
<br />
## [smlua_text_utils_get_language](#smlua_text_utils_get_language) ## [smlua_text_utils_get_language](#smlua_text_utils_get_language)
### Description ### Description

View file

@ -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_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_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_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_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) - [smlua_text_utils_get_language](functions-6.md#smlua_text_utils_get_language)
<br /> <br />

View file

@ -4,6 +4,7 @@
#include "course_table.h" #include "course_table.h"
#include "game/hardcoded.h" #include "game/hardcoded.h"
#include "game/memory.h" #include "game/memory.h"
#include "game/segment2.h"
#include "level_info.h" #include "level_info.h"
#include "level_table.h" #include "level_table.h"
#include "save_file.h" #include "save_file.h"
@ -14,9 +15,6 @@
#ifdef VERSION_EU #ifdef VERSION_EU
extern s32 gInGameLanguage; extern s32 gInGameLanguage;
#include "eu_translation.h" #include "eu_translation.h"
#else
extern u8 *seg2_course_name_table[];
extern u8 *seg2_act_name_table[];
#endif #endif
static const struct { const char *str; u8 c; u8 menu; } sSm64CharMap[] = { 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); void **courseNameTbl = segmented_to_virtual(seg2_course_name_table);
#ifdef VERSION_EU #ifdef VERSION_EU
@ -174,7 +172,21 @@ void *get_course_name_table(void) {
return courseNameTbl; 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); void **actNameTbl = segmented_to_virtual(seg2_act_name_table);
#ifdef VERSION_EU #ifdef VERSION_EU
@ -188,6 +200,20 @@ void *get_act_name_table(void) {
return actNameTbl; 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) { const char *get_level_name_ascii(s16 courseNum, s16 levelNum, s16 areaIndex, s16 charCase) {
static char output[256]; 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) { if (courseNum >= 0 && courseNum <= COURSE_MAX && gReplacedCourseActNameTable[courseNum].courseName.modNum != 0) {
snprintf(output, 256, "%s", gReplacedActNameTable[courseNum]->name); snprintf(output, 256, "%s", gReplacedCourseActNameTable[courseNum].courseName.name.value);
} }
else if (!hasCustomName) { else if (!hasCustomName) {
@ -266,9 +292,9 @@ const char *get_star_name_ascii(s16 courseNum, s16 starNum, s16 charCase) {
s16 starIndex = starNum - 1; s16 starIndex = starNum - 1;
if (starIndex >= 0 && starIndex < MAX_ACTS_AND_100_COINS && if (starIndex >= 0 && starIndex < MAX_ACTS_AND_100_COINS &&
courseNum >= 0 && courseNum < COURSE_END && courseNum >= 0 && courseNum <= COURSE_MAX &&
gReplacedActNameTable[courseNum]->actName && gReplacedActNameTable[courseNum]->actName[starIndex].modIndex != -1) { gReplacedCourseActNameTable[courseNum].actName[starIndex].modNum != 0) {
snprintf(output, 256, "%s", gReplacedActNameTable[courseNum]->actName[starIndex].name); snprintf(output, 256, "%s", gReplacedCourseActNameTable[courseNum].actName[starIndex].name.value);
} }
// Main courses: BOB to RR // Main courses: BOB to RR

View file

@ -3,8 +3,10 @@
#include <PR/ultratypes.h> #include <PR/ultratypes.h>
void *get_course_name_table(void); void **get_course_name_table(void);
void *get_act_name_table(void); void **get_course_name_table_original(void);
void **get_act_name_table(void);
void **get_act_name_table_original(void);
/* |description| /* |description|
Returns the name of the level corresponding to `courseNum`, `levelNum` and `areaIndex` as an ASCII (human readable) string. 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 Set `charCase` to 1 to capitalize or -1 to decapitalize the returned string

View file

@ -34564,6 +34564,51 @@ int smlua_func_smlua_text_utils_castle_secret_stars_replace(lua_State* L) {
return 1; 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) { int smlua_func_smlua_text_utils_extra_text_replace(lua_State* L) {
if (L == NULL) { return 0; } if (L == NULL) { return 0; }
@ -34583,6 +34628,57 @@ int smlua_func_smlua_text_utils_extra_text_replace(lua_State* L) {
return 1; 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) { int smlua_func_smlua_text_utils_get_language(UNUSED lua_State* L) {
if (L == NULL) { return 0; } 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_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_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_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_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); smlua_bind_function(L, "smlua_text_utils_get_language", smlua_func_smlua_text_utils_get_language);
// sound_init.h // sound_init.h

View file

@ -17,55 +17,90 @@ extern s32 gInGameLanguage;
#endif #endif
static bool sReplacedDialog[DIALOG_COUNT] = { 0 }; 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); 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; 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 // Save all vanilla act names and course names
void smlua_text_utils_init(void) { void smlua_text_utils_init(void) {
void **actNameTbl = get_act_name_table(); memset(gReplacedCourseActNameTable, 0, sizeof(gReplacedCourseActNameTable));
void **courseNameTbl = get_course_name_table();
char courseBuffer[50];
char actBuffer[50];
// Course/Star names // Vanilla courses
for (s16 courseNum = 0; courseNum < COURSE_END; courseNum++) { for (s16 courseNum = COURSE_MIN; courseNum <= COURSE_MAX; ++courseNum) {
gReplacedActNameTable[courseNum] = calloc(1, sizeof(struct CourseName)); smlua_text_utils_init_from_vanilla(
struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; gReplacedCourseActNameTable[courseNum].courseName,
convert_string_sm64_to_ascii(courseBuffer, segmented_to_virtual(courseNameTbl[courseNum])); get_course_name_table,
snprintf(courseActNames->name, 50, "%s", courseBuffer); get_course_name_table_original,
snprintf(courseActNames->orig, 50, "%s", courseBuffer); courseNum - 1
courseActNames->modIndex = -1; );
courseActNames->actName = NULL;
// Individual acts // Vanilla acts
if (COURSE_IS_MAIN_COURSE(courseNum)) { if (COURSE_IS_MAIN_COURSE(courseNum)) {
courseActNames->actName = calloc(MAX_ACTS_AND_100_COINS, sizeof(struct ActName)); for (s16 actIndex = 0; actIndex < MAX_ACTS; ++actIndex) {
for (s16 actNum = 0; actNum < MAX_ACTS; actNum++) { smlua_text_utils_init_from_vanilla(
convert_string_sm64_to_ascii(actBuffer, segmented_to_virtual(actNameTbl[courseNum * MAX_ACTS + actNum])); gReplacedCourseActNameTable[courseNum].actName[actIndex],
snprintf(courseActNames->actName[actNum].name, 50, "%s", actBuffer); get_act_name_table,
snprintf(courseActNames->actName[actNum].orig, 50, "%s", actBuffer); get_act_name_table_original,
courseActNames->actName[actNum].modIndex = -1; (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; sSmluaTextUtilsInited = true;
} }
void smlua_text_utils_shutdown(void) { void smlua_text_utils_shutdown(void) {
if (sSmluaTextUtilsInited) { if (sSmluaTextUtilsInited) {
for (s16 courseNum = 0; courseNum < COURSE_END; courseNum++) {
free(gReplacedActNameTable[courseNum]->actName);
free(gReplacedActNameTable[courseNum]);
}
sSmluaTextUtilsInited = false; sSmluaTextUtilsInited = false;
} }
} }
@ -85,48 +120,55 @@ static bool str_starts_with_spaces(const char* str) {
return true; 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 smlua_text_utils_reset_all(void) {
void **dialogTable = NULL; void **dialogTable = NULL;
void **actNameTbl = NULL;
void **courseNameTbl = NULL;
void **dialogTableOrg = NULL; void **dialogTableOrg = NULL;
void **actNameTblOrg = NULL;
void **courseNameTblOrg = NULL;
#ifdef VERSION_EU #ifdef VERSION_EU
switch (gInGameLanguage) { switch (gInGameLanguage) {
case LANGUAGE_ENGLISH: case LANGUAGE_ENGLISH:
dialogTable = segmented_to_virtual(dialog_table_eu_en); 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); 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; break;
case LANGUAGE_FRENCH: case LANGUAGE_FRENCH:
dialogTable = segmented_to_virtual(dialog_table_eu_fr); 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); 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; break;
case LANGUAGE_GERMAN: case LANGUAGE_GERMAN:
dialogTable = segmented_to_virtual(dialog_table_eu_de); 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); 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; break;
} }
#else #else
dialogTable = segmented_to_virtual(seg2_dialog_table); 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); 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 #endif
for (s32 i = 0; i < DIALOG_COUNT; i++) { for (s32 i = 0; i < DIALOG_COUNT; i++) {
@ -138,32 +180,17 @@ void smlua_text_utils_reset_all(void) {
sReplacedDialog[i] = false; 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) { if (sSmluaTextUtilsInited) {
for (s32 courseNum = 0; courseNum < COURSE_COUNT; courseNum++) { for (s16 courseNum = 0; courseNum < COURSE_END; courseNum++) {
struct CourseName* courseActNames = gReplacedActNameTable[courseNum];
snprintf(courseActNames->name, 50, "%s", courseActNames->orig);
courseActNames->modIndex = -1;
// Individual acts // Restore vanilla course names
if (COURSE_IS_MAIN_COURSE(courseNum)) { struct ReplacedName *courseName = &gReplacedCourseActNameTable[courseNum].courseName;
for (s16 actNum = 0; actNum < MAX_ACTS_AND_100_COINS; actNum++) { smlua_text_utils_reset_course_or_act_name(courseName);
snprintf(courseActNames->actName[actNum].name, 50, "%s", courseActNames->actName[actNum].orig);
courseActNames->actName[actNum].modIndex = -1; // 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) { 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; } if (!COURSE_IS_VALID_COURSE(courseNum)) { return; }
struct CourseName* courseActNames = gReplacedActNameTable[courseNum];
snprintf(courseActNames->name, 256, "%s", courseName + (3 * (strlen(courseName) > 3))); struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum];
courseActNames->modIndex = gLuaActiveMod->index; smlua_text_utils_replace_course_or_act_name(&courseActNames->courseName, courseName, gLuaActiveMod->index);
#define REPLACE_ACT_NAME(i) { \ #define REPLACE_ACT_NAME(i) { \
snprintf(courseActNames->actName[i-1].name, 256, "%s", act##i); \ smlua_text_utils_replace_course_or_act_name(&courseActNames->actName[i - 1], act##i, gLuaActiveMod->index); \
courseActNames->actName[i-1].modIndex = gLuaActiveMod->index; \
} }
REPLACE_ACT_NAME(1); 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) { 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]; struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum];
snprintf(courseActNames->name, 256, "%s", name); smlua_text_utils_replace_course_or_act_name(&courseActNames->courseName, name, gLuaActiveMod->index);
courseActNames->modIndex = gLuaActiveMod->index;
} }
const char* smlua_text_utils_course_name_get(s16 courseNum) { 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) { 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) { 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]; struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum];
snprintf(courseActNames->name, 50, "%s", courseActNames->orig); smlua_text_utils_reset_course_or_act_name(&courseActNames->courseName);
courseActNames->modIndex = -1;
} }
void smlua_text_utils_act_name_replace(s16 courseNum, u8 actNum, const char* name) { 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]; struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum];
smlua_text_utils_replace_course_or_act_name(&courseActNames->actName[actNum - 1], name, gLuaActiveMod->index);
snprintf(courseActNames->actName[actNum].name, 256, "%s", name);
courseActNames->actName[actNum].modIndex = gLuaActiveMod->index;
} }
const char* smlua_text_utils_act_name_get(s16 courseNum, u8 actNum) { 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) { 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) { 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]; struct CourseActNames *courseActNames = &gReplacedCourseActNameTable[courseNum];
snprintf(courseActNames->actName[actNum].name, 50, "%s", courseActNames->actName[actNum].orig); smlua_text_utils_reset_course_or_act_name(&courseActNames->actName[actNum - 1]);
courseActNames->actName[actNum].modIndex = gLuaActiveMod->index;
} }
void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName) { void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName) {
if (courseNum <= COURSE_RR || courseNum > COURSE_COUNT) { return; } if (courseNum <= COURSE_STAGES_MAX || courseNum > COURSE_MAX) { return; }
/*
s16 courseOffset = courseNum - 1;
void **courseNameTbl = get_course_name_table(); smlua_text_utils_course_name_replace(courseNum, courseName);
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;
} }
void smlua_text_utils_castle_secret_stars_replace(const char* name) { 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]) { s32 smlua_text_utils_castle_secret_stars_mod_index() {
free(courseNameTbl[courseOffset]); return (s32) gReplacedCourseActNameTable[COURSE_END].courseName.modNum - 1;
} }
courseNameTbl[courseOffset] = smlua_text_utils_convert(name); void smlua_text_utils_castle_secret_stars_reset() {
sReplacedCourseName[courseOffset] = true; 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) { void smlua_text_utils_extra_text_replace(s16 index, const char* text) {
if (index < 0 || index > 6) { return; } if (index < 0 || index > MAX_ACTS_AND_100_COINS) { return; }
index = (COURSE_RR * 6 + index);
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]) { const char* smlua_text_utils_extra_text_get(s16 index) {
free(actNameTbl[index]); if (index < 0 || index > MAX_ACTS_AND_100_COINS) { return NULL; }
}
actNameTbl[index] = smlua_text_utils_convert(text); return gReplacedCourseActNameTable[COURSE_END].actName[index].name.value;
sReplacedActName[index] = true; }
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) { const char* smlua_text_utils_get_language(void) {

View file

@ -7,20 +7,24 @@
#define MAX_ACTS 6 #define MAX_ACTS 6
#define MAX_ACTS_AND_100_COINS 7 #define MAX_ACTS_AND_100_COINS 7
struct ActName { struct NameTable {
char name[256]; char value[256];
char orig[256]; void **(*get_table)(void);
s32 modIndex; u32 offset;
}; };
struct CourseName { struct ReplacedName {
struct ActName *actName; struct NameTable name;
char name[256]; struct NameTable orig;
char orig[256]; u32 modNum; // modIndex + 1 (default value of 0 is more convenient than -1)
s32 modIndex;
}; };
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_init(void);
void smlua_text_utils_shutdown(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); void smlua_text_utils_act_name_reset(s16 courseNum, u8 actNum);
/* |description|Replaces the castle secret stars text with `name`|descriptionEnd| */ /* |description|Replaces the castle secret stars text with `name`|descriptionEnd| */
void smlua_text_utils_castle_secret_stars_replace(const char* name); 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| */ /* |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); 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| */ /* |description|Gets the current language|descriptionEnd| */
const char* smlua_text_utils_get_language(void); const char* smlua_text_utils_get_language(void);