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
--- @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()

View file

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

View file

@ -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

View file

@ -3,8 +3,10 @@
#include <PR/ultratypes.h>
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

View file

@ -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

View file

@ -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) {

View file

@ -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);