diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py index df0255d77..5e857ead2 100644 --- a/autogen/convert_constants.py +++ b/autogen/convert_constants.py @@ -202,6 +202,7 @@ def process_enum(filename, line, inIfBlock): constants = [] set_to = None + set_to_val = None index = 0 fields = val.split(',') for field in fields: @@ -210,14 +211,25 @@ def process_enum(filename, line, inIfBlock): continue if '=' in field: - ident, val = field.split('=', 2) - constants.append([ident.strip(), val.strip()]) + ident, val = field.split('=', 1) + ident = ident.strip() + val = val.strip() + + try: + set_to_val = int(eval(val, {}, {})) + except Exception: + set_to_val = None + + constants.append([ident, val]) set_to = ident index = 1 continue if set_to is not None: - constants.append([field, '((%s) + %d)' % (set_to, index)]) + if set_to_val is not None: + constants.append([field, str(set_to_val + index)]) + else: + constants.append([field, '((%s) + %d)' % (set_to, index)]) index += 1 continue diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 9e8ef5368..8f0e8758a 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -131,7 +131,7 @@ override_disallowed_functions = { "src/pc/lua/utils/smlua_audio_utils.h": [ "smlua_audio_utils_override", "audio_custom_shutdown", "smlua_audio_custom_deinit", "audio_sample_destroy_pending_copies", "audio_custom_update_volume" ], "src/pc/djui/djui_hud_utils.h": [ "djui_hud_render_texture_raw", "djui_hud_render_texture_tile_raw" ], "src/pc/lua/utils/smlua_level_utils.h": [ "smlua_level_util_reset" ], - "src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_init", "smlua_text_utils_shutdown" ], + "src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_init", "smlua_text_utils_shutdown", "get_dialog_text_ascii", "smlua_text_utils_dialog_get_unmodified"], "src/pc/lua/utils/smlua_anim_utils.h": [ "smlua_anim_util_reset", "smlua_anim_util_register_animation" ], "src/pc/lua/utils/smlua_gfx_utils.h": [ "gfx_allocate_internal", "vtx_allocate_internal", "gfx_get_length_no_sentinel" ], "src/pc/network/lag_compensation.h": [ "lag_compensation_clear" ], diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index a781e7ba0..0352b44f2 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -140,7 +140,7 @@ override_field_immutable = { "FirstPersonCamera": [ "enabled" ], "ModAudio": [ "isStream", "loaded" ], "Gfx": [ "w0", "w1" ], # to protect from invalid type conversions - "DialogEntry": [ "unused", "linesPerBox", "leftOffset", "width", "str", "text"], + "DialogEntry": [ "unused", "linesPerBox", "leftOffset", "width", "str", "text", "replaced"], "ModFsFile": [ "*" ], "ModFs": [ "*" ], } diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 9a03b12ba..4f814b1d4 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -2361,6 +2361,7 @@ M_MOUSE_BUTTON = MOUSE_BUTTON_2 --- @type integer R_MOUSE_BUTTON = MOUSE_BUTTON_3 +DIALOG_NONE = -1 --- @type DialogId DIALOG_000 = 0 --- @type DialogId DIALOG_001 = 1 --- @type DialogId DIALOG_002 = 2 --- @type DialogId @@ -2534,6 +2535,7 @@ DIALOG_169 = 169 --- @type DialogId DIALOG_COUNT = 170 --- @type DialogId --- @alias DialogId +--- | `DIALOG_NONE` --- | `DIALOG_000` --- | `DIALOG_001` --- | `DIALOG_002` @@ -3485,27 +3487,27 @@ SPECIAL_WARP_TITLE = -8 --- @type integer SPECIAL_WARP_LEVEL_SELECT = -9 -MARIO_SPAWN_NONE = 0 --- @type MarioSpawnType -MARIO_SPAWN_DOOR_WARP = 1 --- @type MarioSpawnType -MARIO_SPAWN_IDLE = 2 --- @type MarioSpawnType -MARIO_SPAWN_PIPE = 3 --- @type MarioSpawnType -MARIO_SPAWN_TELEPORT = 4 --- @type MarioSpawnType -MARIO_SPAWN_INSTANT_ACTIVE = 0x10 --- @type MarioSpawnType -MARIO_SPAWN_SWIMMING = ((MARIO_SPAWN_INSTANT_ACTIVE ) + 1) --- @type MarioSpawnType -MARIO_SPAWN_AIRBORNE = ((MARIO_SPAWN_INSTANT_ACTIVE ) + 2) --- @type MarioSpawnType -MARIO_SPAWN_HARD_AIR_KNOCKBACK = ((MARIO_SPAWN_INSTANT_ACTIVE ) + 3) --- @type MarioSpawnType -MARIO_SPAWN_SPIN_AIRBORNE_CIRCLE = ((MARIO_SPAWN_INSTANT_ACTIVE ) + 4) --- @type MarioSpawnType -MARIO_SPAWN_DEATH = ((MARIO_SPAWN_INSTANT_ACTIVE ) + 5) --- @type MarioSpawnType -MARIO_SPAWN_SPIN_AIRBORNE = ((MARIO_SPAWN_INSTANT_ACTIVE ) + 6) --- @type MarioSpawnType -MARIO_SPAWN_FLYING = ((MARIO_SPAWN_INSTANT_ACTIVE ) + 7) --- @type MarioSpawnType -MARIO_SPAWN_PAINTING_STAR_COLLECT = 0x20 --- @type MarioSpawnType -MARIO_SPAWN_PAINTING_DEATH = ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 1) --- @type MarioSpawnType -MARIO_SPAWN_AIRBORNE_STAR_COLLECT = ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 2) --- @type MarioSpawnType -MARIO_SPAWN_AIRBORNE_DEATH = ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 3) --- @type MarioSpawnType -MARIO_SPAWN_LAUNCH_STAR_COLLECT = ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 4) --- @type MarioSpawnType -MARIO_SPAWN_LAUNCH_DEATH = ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 5) --- @type MarioSpawnType -MARIO_SPAWN_UNUSED_38 = ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 6) --- @type MarioSpawnType -MARIO_SPAWN_FADE_FROM_BLACK = ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 7) --- @type MarioSpawnType +MARIO_SPAWN_NONE = 0 --- @type MarioSpawnType +MARIO_SPAWN_DOOR_WARP = 1 --- @type MarioSpawnType +MARIO_SPAWN_IDLE = 2 --- @type MarioSpawnType +MARIO_SPAWN_PIPE = 3 --- @type MarioSpawnType +MARIO_SPAWN_TELEPORT = 4 --- @type MarioSpawnType +MARIO_SPAWN_INSTANT_ACTIVE = 0x10 --- @type MarioSpawnType +MARIO_SPAWN_SWIMMING = 17 --- @type MarioSpawnType +MARIO_SPAWN_AIRBORNE = 18 --- @type MarioSpawnType +MARIO_SPAWN_HARD_AIR_KNOCKBACK = 19 --- @type MarioSpawnType +MARIO_SPAWN_SPIN_AIRBORNE_CIRCLE = 20 --- @type MarioSpawnType +MARIO_SPAWN_DEATH = 21 --- @type MarioSpawnType +MARIO_SPAWN_SPIN_AIRBORNE = 22 --- @type MarioSpawnType +MARIO_SPAWN_FLYING = 23 --- @type MarioSpawnType +MARIO_SPAWN_PAINTING_STAR_COLLECT = 0x20 --- @type MarioSpawnType +MARIO_SPAWN_PAINTING_DEATH = 33 --- @type MarioSpawnType +MARIO_SPAWN_AIRBORNE_STAR_COLLECT = 34 --- @type MarioSpawnType +MARIO_SPAWN_AIRBORNE_DEATH = 35 --- @type MarioSpawnType +MARIO_SPAWN_LAUNCH_STAR_COLLECT = 36 --- @type MarioSpawnType +MARIO_SPAWN_LAUNCH_DEATH = 37 --- @type MarioSpawnType +MARIO_SPAWN_UNUSED_38 = 38 --- @type MarioSpawnType +MARIO_SPAWN_FADE_FROM_BLACK = 39 --- @type MarioSpawnType --- @alias MarioSpawnType --- | `MARIO_SPAWN_NONE` diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 937a787c2..cca3e4ab6 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -11887,6 +11887,12 @@ function smlua_text_utils_dialog_replace(dialogId, unused, linesPerBox, leftOffs -- ... end +--- @param dialogId DialogId +--- Restores a replaced DialogEntry to its original state. +function smlua_text_utils_dialog_restore(dialogId) + -- ... +end + --- @param dialogId DialogId --- @return boolean --- Returns whether the dialog with the given ID has been replaced @@ -11894,6 +11900,12 @@ function smlua_text_utils_dialog_is_replaced(dialogId) -- ... end +--- @return integer +--- Allocates a new dialog entry +function smlua_text_utils_allocate_dialog() + -- ... +end + --- @param courseNum integer --- @param courseName string --- @param act1 string diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 944a33d07..7012bfe3a 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -595,6 +595,7 @@ --- @class DialogEntry --- @field public leftOffset integer --- @field public linesPerBox integer +--- @field public replaced boolean --- @field public text string --- @field public unused integer --- @field public width integer diff --git a/bin/eu/translation_de.c b/bin/eu/translation_de.c index ba232c0d1..d19dd930b 100644 --- a/bin/eu/translation_de.c +++ b/bin/eu/translation_de.c @@ -12,7 +12,6 @@ #define seg2_course_name_table_original course_name_table_eu_de_original #define seg2_act_name_table act_name_table_eu_de #define seg2_act_name_table_original act_name_table_eu_de_original -#define seg2_dialog_table dialog_table_eu_de #define seg2_dialog_original dialog_table_eu_de_original #include "text/de/define_text.inc.c" diff --git a/bin/eu/translation_en.c b/bin/eu/translation_en.c index 208e1b9a5..8f8452a69 100644 --- a/bin/eu/translation_en.c +++ b/bin/eu/translation_en.c @@ -12,7 +12,6 @@ #define seg2_course_name_table_original course_name_table_eu_en_original #define seg2_act_name_table act_name_table_eu_en #define seg2_act_name_table_original act_name_table_eu_en_original -#define seg2_dialog_table dialog_table_eu_en #define seg2_dialog_original dialog_table_eu_en_original #include "text/us/define_text.inc.c" diff --git a/bin/eu/translation_fr.c b/bin/eu/translation_fr.c index e7217e285..1a7b98fc6 100644 --- a/bin/eu/translation_fr.c +++ b/bin/eu/translation_fr.c @@ -12,7 +12,6 @@ #define seg2_course_name_table_original course_name_table_eu_fr_original #define seg2_act_name_table act_name_table_eu_fr #define seg2_act_name_table_original act_name_table_eu_fr_original -#define seg2_dialog_table dialog_table_eu_fr #define seg2_dialog_original dialog_table_eu_fr_original #include "text/fr/define_text.inc.c" diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 39eb819da..f91d7a48b 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -958,6 +958,7 @@ ### [enum DialogId](#DialogId) | Identifier | Value | | :--------- | :---- | +| DIALOG_NONE | -1 | | DIALOG_000 | 0 | | DIALOG_001 | 1 | | DIALOG_002 | 2 | @@ -1579,21 +1580,21 @@ | MARIO_SPAWN_PIPE | 3 | | MARIO_SPAWN_TELEPORT | 4 | | MARIO_SPAWN_INSTANT_ACTIVE | 0x10 | -| MARIO_SPAWN_SWIMMING | ((MARIO_SPAWN_INSTANT_ACTIVE ) + 1) | -| MARIO_SPAWN_AIRBORNE | ((MARIO_SPAWN_INSTANT_ACTIVE ) + 2) | -| MARIO_SPAWN_HARD_AIR_KNOCKBACK | ((MARIO_SPAWN_INSTANT_ACTIVE ) + 3) | -| MARIO_SPAWN_SPIN_AIRBORNE_CIRCLE | ((MARIO_SPAWN_INSTANT_ACTIVE ) + 4) | -| MARIO_SPAWN_DEATH | ((MARIO_SPAWN_INSTANT_ACTIVE ) + 5) | -| MARIO_SPAWN_SPIN_AIRBORNE | ((MARIO_SPAWN_INSTANT_ACTIVE ) + 6) | -| MARIO_SPAWN_FLYING | ((MARIO_SPAWN_INSTANT_ACTIVE ) + 7) | +| MARIO_SPAWN_SWIMMING | 17 | +| MARIO_SPAWN_AIRBORNE | 18 | +| MARIO_SPAWN_HARD_AIR_KNOCKBACK | 19 | +| MARIO_SPAWN_SPIN_AIRBORNE_CIRCLE | 20 | +| MARIO_SPAWN_DEATH | 21 | +| MARIO_SPAWN_SPIN_AIRBORNE | 22 | +| MARIO_SPAWN_FLYING | 23 | | MARIO_SPAWN_PAINTING_STAR_COLLECT | 0x20 | -| MARIO_SPAWN_PAINTING_DEATH | ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 1) | -| MARIO_SPAWN_AIRBORNE_STAR_COLLECT | ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 2) | -| MARIO_SPAWN_AIRBORNE_DEATH | ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 3) | -| MARIO_SPAWN_LAUNCH_STAR_COLLECT | ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 4) | -| MARIO_SPAWN_LAUNCH_DEATH | ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 5) | -| MARIO_SPAWN_UNUSED_38 | ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 6) | -| MARIO_SPAWN_FADE_FROM_BLACK | ((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 7) | +| MARIO_SPAWN_PAINTING_DEATH | 33 | +| MARIO_SPAWN_AIRBORNE_STAR_COLLECT | 34 | +| MARIO_SPAWN_AIRBORNE_DEATH | 35 | +| MARIO_SPAWN_LAUNCH_STAR_COLLECT | 36 | +| MARIO_SPAWN_LAUNCH_DEATH | 37 | +| MARIO_SPAWN_UNUSED_38 | 38 | +| MARIO_SPAWN_FADE_FROM_BLACK | 39 | - MARIO_SPAWN_UNKNOWN_02 - MARIO_SPAWN_UNKNOWN_03 - MARIO_SPAWN_UNKNOWN_27 diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md index 1839566f6..271479817 100644 --- a/docs/lua/functions-3.md +++ b/docs/lua/functions-3.md @@ -2186,7 +2186,7 @@ Starts a cutscene involving an object and displays dialog during the sequence. T - `integer` ### C Prototype -`s16 cutscene_object_with_dialog(u8 cutscene, struct Object *o, s16 dialogID);` +`s16 cutscene_object_with_dialog(u8 cutscene, struct Object *o, s32 dialogID);` [:arrow_up_small:](#) @@ -4056,7 +4056,7 @@ Plays a dialog sound corresponding to `dialogID` - None ### C Prototype -`void play_dialog_sound(u8 dialogID);` +`void play_dialog_sound(s32 dialogID);` [:arrow_up_small:](#) @@ -4692,7 +4692,7 @@ Creates a dialog box with a dialog ID that rotates into view - None ### C Prototype -`void create_dialog_box(s16 dialog);` +`void create_dialog_box(s32 dialog);` [:arrow_up_small:](#) @@ -4716,7 +4716,7 @@ Creates a dialog box with a dialog variable - None ### C Prototype -`void create_dialog_box_with_var(s16 dialog, s32 dialogVar);` +`void create_dialog_box_with_var(s32 dialog, s32 dialogVar);` [:arrow_up_small:](#) @@ -4739,7 +4739,7 @@ Creates a dialog box with a dialog ID that zooms into view - None ### C Prototype -`void create_dialog_inverted_box(s16 dialog);` +`void create_dialog_inverted_box(s32 dialog);` [:arrow_up_small:](#) @@ -4762,7 +4762,7 @@ Creates a dialog box with a response - None ### C Prototype -`void create_dialog_box_with_response(s16 dialog);` +`void create_dialog_box_with_response(s32 dialog);` [:arrow_up_small:](#) diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md index ebefc2e88..5ad76c5cb 100644 --- a/docs/lua/functions-6.md +++ b/docs/lua/functions-6.md @@ -4464,7 +4464,7 @@ Gets the current dialog box ID - `integer` ### C Prototype -`s16 get_dialog_id(void);` +`s32 get_dialog_id(void);` [:arrow_up_small:](#) @@ -7254,6 +7254,29 @@ Replaces `dialogId` with a custom one
+## [smlua_text_utils_dialog_restore](#smlua_text_utils_dialog_restore) + +### Description +Restores a replaced DialogEntry to its original state. + +### Lua Example +`smlua_text_utils_dialog_restore(dialogId)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dialogId | [enum DialogId](constants.md#enum-DialogId) | + +### Returns +- None + +### C Prototype +`void smlua_text_utils_dialog_restore(enum DialogId dialogId);` + +[:arrow_up_small:](#) + +
+ ## [smlua_text_utils_dialog_is_replaced](#smlua_text_utils_dialog_is_replaced) ### Description @@ -7277,6 +7300,27 @@ Returns whether the dialog with the given ID has been replaced
+## [smlua_text_utils_allocate_dialog](#smlua_text_utils_allocate_dialog) + +### Description +Allocates a new dialog entry + +### Lua Example +`local integerValue = smlua_text_utils_allocate_dialog()` + +### Parameters +- None + +### Returns +- `integer` + +### C Prototype +`s32 smlua_text_utils_allocate_dialog(void);` + +[:arrow_up_small:](#) + +
+ ## [smlua_text_utils_course_acts_replace](#smlua_text_utils_course_acts_replace) ### Description diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 8656b5289..f1e0ae3a1 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -2112,7 +2112,9 @@ - [smlua_text_utils_reset_all](functions-6.md#smlua_text_utils_reset_all) - [smlua_text_utils_dialog_get](functions-6.md#smlua_text_utils_dialog_get) - [smlua_text_utils_dialog_replace](functions-6.md#smlua_text_utils_dialog_replace) + - [smlua_text_utils_dialog_restore](functions-6.md#smlua_text_utils_dialog_restore) - [smlua_text_utils_dialog_is_replaced](functions-6.md#smlua_text_utils_dialog_is_replaced) + - [smlua_text_utils_allocate_dialog](functions-6.md#smlua_text_utils_allocate_dialog) - [smlua_text_utils_course_acts_replace](functions-6.md#smlua_text_utils_course_acts_replace) - [smlua_text_utils_secret_star_replace](functions-6.md#smlua_text_utils_secret_star_replace) - [smlua_text_utils_course_name_replace](functions-6.md#smlua_text_utils_course_name_replace) diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 81f13a28f..0c510030f 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -886,6 +886,7 @@ | ----- | ---- | ------ | | leftOffset | `integer` | read-only | | linesPerBox | `integer` | read-only | +| replaced | `boolean` | read-only | | text | `string` | read-only | | unused | `integer` | read-only | | width | `integer` | read-only | diff --git a/include/dialog_ids.h b/include/dialog_ids.h index 6feadafb2..2d9a24108 100644 --- a/include/dialog_ids.h +++ b/include/dialog_ids.h @@ -2,6 +2,7 @@ #define DIALOG_IDS_H enum DialogId { + DIALOG_NONE = -1, DIALOG_000, DIALOG_001, DIALOG_002, diff --git a/include/eu_translation.h b/include/eu_translation.h index 02611b37a..e61d7ddc8 100644 --- a/include/eu_translation.h +++ b/include/eu_translation.h @@ -11,21 +11,18 @@ #define LANGUAGE_ARRAY(cmd) cmd #endif -extern u8 *dialog_table_eu_en[]; extern u8 *course_name_table_eu_en[]; extern u8 *act_name_table_eu_en[]; extern u8 *dialog_table_eu_en_original[]; extern u8 *course_name_table_eu_en_original[]; extern u8 *act_name_table_eu_en_original[]; -extern u8 *dialog_table_eu_fr[]; extern u8 *course_name_table_eu_fr[]; extern u8 *act_name_table_eu_fr[]; extern u8 *dialog_table_eu_fr_original[]; extern u8 *course_name_table_eu_fr_original[]; extern u8 *act_name_table_eu_fr_original[]; -extern u8 *dialog_table_eu_de[]; extern u8 *course_name_table_eu_de[]; extern u8 *act_name_table_eu_de[]; extern u8 *dialog_table_eu_de_original[]; diff --git a/include/object_fields.h b/include/object_fields.h index 66ebdcc13..11f07257d 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -970,7 +970,7 @@ #define /*0x10C*/ oTiltingPyramidMarioOnPlatform OBJECT_FIELD_S32(0x21) /* Toad Message */ -#define /*0x108*/ oToadMessageDialogId OBJECT_FIELD_U32(0x20) +#define /*0x108*/ oToadMessageDialogId OBJECT_FIELD_S32(0x20) #define /*0x10C*/ oToadMessageRecentlyTalked OBJECT_FIELD_S32(0x21) #define /*0x110*/ oToadMessageState OBJECT_FIELD_S32(0x22) diff --git a/include/types.h b/include/types.h index dc20060b2..c5cecc02f 100644 --- a/include/types.h +++ b/include/types.h @@ -498,7 +498,7 @@ struct MarioState u8 visibleToEnemies; u8 wasNetworkVisible; - s16 dialogId; + s32 dialogId; s16 prevNumStarsForDialog; s16 unkB0; diff --git a/src/audio/external.c b/src/audio/external.c index 1d778db59..c411aee8b 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -18,6 +18,8 @@ #include "pc/debuglog.h" #include "pc/lua/utils/smlua_level_utils.h" #include "pc/lua/smlua_hooks.h" +#include "pc/dialog_table.h" +#include "dialog_ids.h" #if defined(VERSION_EU) || defined(VERSION_SH) #define EU_FLOAT(x) x##f @@ -2455,10 +2457,10 @@ void set_sound_moving_speed(u8 bank, u8 speed) { /** * Called from threads: thread5_game_loop */ -void play_dialog_sound(u8 dialogID) { +void play_dialog_sound(s32 dialogID) { s32 speaker; - if (dialogID >= DIALOG_COUNT) { + if (!IS_VALID_VANILLA_DIALOG(dialogID)) { dialogID = 0; } diff --git a/src/audio/external.h b/src/audio/external.h index e0381e2ae..ff6a41f47 100644 --- a/src/audio/external.h +++ b/src/audio/external.h @@ -4,6 +4,7 @@ #include #include "types.h" +#include "dialog_ids.h" #define MAX_AUDIO_OVERRIDE 128 @@ -87,7 +88,7 @@ void sound_banks_enable(u8 player, u16 bankMask); /* |description|Sets the `speed` of moving `bank`|descriptionEnd| */ void set_sound_moving_speed(u8 bank, u8 speed); /* |description|Plays a dialog sound corresponding to `dialogID`|descriptionEnd| */ -void play_dialog_sound(u8 dialogID); +void play_dialog_sound(s32 dialogID); /* |description|Sets the `volume` of `player`|descriptionEnd| */ void set_sequence_player_volume(s32 player, f32 volume); /* |description|Plays fading in music (`seqArgs`) on `player` over `fadeTimer`|descriptionEnd| */ diff --git a/src/game/behaviors/bobomb.inc.c b/src/game/behaviors/bobomb.inc.c index fc85b46c6..762eaabb6 100644 --- a/src/game/behaviors/bobomb.inc.c +++ b/src/game/behaviors/bobomb.inc.c @@ -337,7 +337,7 @@ void bobomb_buddy_act_idle(void) { * dialogSecondText is called after Bob-omb Buddy has the cannon(s) ready and * then tells Mario that is "Ready for blastoff". */ -void bobomb_buddy_cannon_dialog(s16 dialogFirstText, s16 dialogSecondText) { +void bobomb_buddy_cannon_dialog(s32 dialogFirstText, s32 dialogSecondText) { struct Object *cannonClosed; s16 buddyText, cutscene; diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index 754af163a..78a0daac8 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -38,10 +38,10 @@ s8 D_8032F4FC[] = { 7, 8, 9, 12, 13, 14, 15, 4, 3, 16, 17, 19, 3, 3, 3, 3 }; s16 D_8032F50C[] = { 60, 0 }; s16 D_8032F510[] = { 50, 0 }; s8 D_8032F514[] = { 24, 42, 60, -1 }; -s16* sBowserDefeatedDialogText[3] = { - (s16*) &gBehaviorValues.dialogs.Bowser1DefeatedDialog, - (s16*) &gBehaviorValues.dialogs.Bowser2DefeatedDialog, - (s16*) &gBehaviorValues.dialogs.Bowser3DefeatedDialog +enum DialogId* sBowserDefeatedDialogText[3] = { + &gBehaviorValues.dialogs.Bowser1DefeatedDialog, + &gBehaviorValues.dialogs.Bowser2DefeatedDialog, + &gBehaviorValues.dialogs.Bowser3DefeatedDialog }; s16 D_8032F520[][3] = { { 1, 10, 40 }, { 0, 0, 74 }, { -1, -10, 114 }, { 1, -20, 134 }, { -1, 20, 154 }, { 1, 40, 164 }, { -1, -40, 174 }, { 1, -80, 179 }, diff --git a/src/game/behaviors/intro_peach.inc.c b/src/game/behaviors/intro_peach.inc.c index 2838a9105..37b403010 100644 --- a/src/game/behaviors/intro_peach.inc.c +++ b/src/game/behaviors/intro_peach.inc.c @@ -40,7 +40,7 @@ void bhv_intro_peach_loop(void) { case 2: intro_peach_set_pos_and_opacity(gCurrentObject, 255.f, 3.f); - if ((gCurrentObject->oTimer > 100) && (get_dialog_id() == -1)) + if ((gCurrentObject->oTimer > 100) && (get_dialog_id() == DIALOG_NONE)) gCurrentObject->oAction += 1; break; case 3: diff --git a/src/game/behaviors/koopa.inc.c b/src/game/behaviors/koopa.inc.c index 924f50299..e7d79b8cc 100644 --- a/src/game/behaviors/koopa.inc.c +++ b/src/game/behaviors/koopa.inc.c @@ -50,16 +50,16 @@ static u8 sKoopaShelledAttackHandlers[] = { * Data to control the behavior of each instance of Koopa the Quick. */ struct KoopaTheQuickProperties { - s16* initText; - s16* winText; + enum DialogId* initText; + enum DialogId* winText; }; /** * Properties for the BoB race and the THI race. */ static struct KoopaTheQuickProperties sKoopaTheQuickProperties[] = { - { (s16*) &gBehaviorValues.dialogs.KoopaQuickBobStartDialog, (s16*) &gBehaviorValues.dialogs.KoopaQuickBobWinDialog }, - { (s16*) &gBehaviorValues.dialogs.KoopaQuickThiStartDialog, (s16*) &gBehaviorValues.dialogs.KoopaQuickThiWinDialog } + { &gBehaviorValues.dialogs.KoopaQuickBobStartDialog, &gBehaviorValues.dialogs.KoopaQuickBobWinDialog }, + { &gBehaviorValues.dialogs.KoopaQuickThiStartDialog, &gBehaviorValues.dialogs.KoopaQuickThiWinDialog } }; static u32 koopaPathedStartWaypoint = 0; @@ -872,7 +872,7 @@ static void koopa_the_quick_act_after_race(void) { if (marioState && should_start_or_continue_dialog(marioState, o)) { s32 dialogResponse = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, o->parentObj->oKoopaRaceEndpointUnk100, koopa_the_quick_act_after_race_continue_dialog); if (dialogResponse != 0) { - o->parentObj->oKoopaRaceEndpointUnk100 = -1; + o->parentObj->oKoopaRaceEndpointUnk100 = DIALOG_NONE; o->oTimer = 0; } } diff --git a/src/game/behaviors/mips.inc.c b/src/game/behaviors/mips.inc.c index aa60aaf32..451d1c8b7 100644 --- a/src/game/behaviors/mips.inc.c +++ b/src/game/behaviors/mips.inc.c @@ -265,7 +265,7 @@ static u8 bhv_mips_held_continue_dialog(void) { * Handles MIPS being held by Mario. */ void bhv_mips_held(void) { - s16 dialogID; + s32 dialogID; if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } struct Object* player = gMarioStates[o->heldByPlayerIndex].marioObj; diff --git a/src/game/behaviors/racing_penguin.inc.c b/src/game/behaviors/racing_penguin.inc.c index fd8d9cfad..28137e7b5 100644 --- a/src/game/behaviors/racing_penguin.inc.c +++ b/src/game/behaviors/racing_penguin.inc.c @@ -1,12 +1,12 @@ struct RacingPenguinData { - s16* text; + enum DialogId* text; f32* radius; f32* height; }; static struct RacingPenguinData sRacingPenguinData[] = { - { (s16*) &gBehaviorValues.dialogs.RacingPenguinStartDialog, &gBehaviorValues.RacingPenguinRadius, &gBehaviorValues.RacingPenguinHeight }, - { (s16*) &gBehaviorValues.dialogs.RacingPenguinBigStartDialog, &gBehaviorValues.RacingPenguinBigRadius, &gBehaviorValues.RacingPenguinBigHeight }, + { &gBehaviorValues.dialogs.RacingPenguinStartDialog, &gBehaviorValues.RacingPenguinRadius, &gBehaviorValues.RacingPenguinHeight }, + { &gBehaviorValues.dialogs.RacingPenguinBigStartDialog, &gBehaviorValues.RacingPenguinBigRadius, &gBehaviorValues.RacingPenguinBigHeight }, }; static u32 penguinPathedStartWaypoint = 0; diff --git a/src/game/behaviors/wiggler.inc.c b/src/game/behaviors/wiggler.inc.c index 531df5531..59a4ac9b1 100644 --- a/src/game/behaviors/wiggler.inc.c +++ b/src/game/behaviors/wiggler.inc.c @@ -300,10 +300,10 @@ static void wiggler_act_jumped_on(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); // Text to show on first, second, and third attack. - s32* attackText[3] = { - (s32*) &gBehaviorValues.dialogs.WigglerAttack1Dialog, - (s32*) &gBehaviorValues.dialogs.WigglerAttack2Dialog, - (s32*) &gBehaviorValues.dialogs.WigglerAttack3Dialog + enum DialogId* attackText[3] = { + &gBehaviorValues.dialogs.WigglerAttack1Dialog, + &gBehaviorValues.dialogs.WigglerAttack2Dialog, + &gBehaviorValues.dialogs.WigglerAttack3Dialog }; // Shrink until the squish speed becomes 0, then unisquish diff --git a/src/game/camera.c b/src/game/camera.c index 54f713d81..f18325c50 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -172,7 +172,7 @@ extern s16 s2ndRotateFlags; extern s16 unused8033B31A; extern s16 sCameraSoundFlags; extern u16 sCButtonsPressed; -extern s16 sCutsceneDialogID; +extern s32 sCutsceneDialogID; extern struct LakituState gLakituState; extern s16 unused8033B3E8; extern s16 sAreaYaw; @@ -304,7 +304,7 @@ u16 sCButtonsPressed; /** * A copy of gDialogID, the dialog displayed during the cutscene. */ -s16 sCutsceneDialogID; +s32 sCutsceneDialogID; /** * The currently playing shot in the cutscene. */ @@ -7271,16 +7271,16 @@ s32 unused_dialog_cutscene_response(u8 cutscene) { } } -s16 cutscene_object_with_dialog(u8 cutscene, struct Object *o, s16 dialogID) { +s16 cutscene_object_with_dialog(u8 cutscene, struct Object *o, s32 dialogID) { s16 response = 0; if ((gCamera->cutscene == 0) && (sObjectCutscene == 0)) { if (gRecentCutscene != cutscene) { start_object_cutscene(cutscene, o); - if (dialogID != -1) { + if (dialogID != DIALOG_NONE) { sCutsceneDialogID = dialogID; } else { - sCutsceneDialogID = (s16) gBehaviorValues.dialogs.DefaultCutsceneDialog; + sCutsceneDialogID = (s32) gBehaviorValues.dialogs.DefaultCutsceneDialog; } } else { response = sCutsceneDialogResponse; @@ -8586,7 +8586,7 @@ BAD_RETURN(s32) cutscene_bowser_arena_start(struct Camera *c) { * Create the dialog box depending on which bowser fight Mario is in. */ BAD_RETURN(s32) bowser_fight_intro_dialog(UNUSED struct Camera *c) { - s16 dialog; + s32 dialog; switch (gCurrLevelNum) { case LEVEL_BOWSER_1: @@ -8608,7 +8608,7 @@ BAD_RETURN(s32) bowser_fight_intro_dialog(UNUSED struct Camera *c) { BAD_RETURN(s32) cutscene_bowser_arena_dialog(struct Camera *c) { cutscene_event(bowser_fight_intro_dialog, c, 0, 0); - if (get_dialog_id() == -1) { + if (get_dialog_id() == DIALOG_NONE) { gCutsceneTimer = CUTSCENE_LOOP; } } @@ -9486,7 +9486,7 @@ BAD_RETURN(s32) cutscene_dialog(struct Camera *c) { sCutsceneDialogResponse = gDialogResponse; } - if ((get_dialog_id() == -1) && (sCutsceneVars[8].angle[0] != 0)) { + if ((get_dialog_id() == DIALOG_NONE) && (sCutsceneVars[8].angle[0] != 0)) { if (c->cutscene != CUTSCENE_RACE_DIALOG) { sCutsceneDialogResponse = 3; } @@ -9556,7 +9556,7 @@ BAD_RETURN(s32) cutscene_read_message(struct Camera *c) { switch (sCutsceneVars[0].angle[0]) { // Do nothing until message is gone. case 0: - if (get_dialog_id() != -1) { + if (get_dialog_id() != DIALOG_NONE) { sCutsceneVars[0].angle[0] += 1; //set_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_DIALOG); } @@ -9568,7 +9568,7 @@ BAD_RETURN(s32) cutscene_read_message(struct Camera *c) { // This could cause softlocks. If a message starts one frame after another one closes, the // cutscene will never end. - if (get_dialog_id() == -1) { + if (get_dialog_id() == DIALOG_NONE) { gCutsceneTimer = CUTSCENE_LOOP; retrieve_info_star(c); transition_next_state(c, 15); @@ -9926,7 +9926,7 @@ BAD_RETURN(s32) cutscene_cap_switch_press(struct Camera *c) { sCutsceneVars[4].angle[0] = gDialogResponse; } - if ((get_dialog_id() == -1) && (sCutsceneVars[4].angle[0] != 0)) { + if ((get_dialog_id() == DIALOG_NONE) && (sCutsceneVars[4].angle[0] != 0)) { sCutsceneDialogResponse = sCutsceneVars[4].angle[0]; if (sCutsceneVars[4].angle[0] == 1 && gCutsceneFocus) { cap_switch_save(gCutsceneFocus->oBehParams2ndByte); @@ -10066,7 +10066,7 @@ BAD_RETURN(s32) cutscene_intro_peach_start_to_pipe_spline(struct Camera *c) { */ BAD_RETURN(s32) cutscene_intro_peach_dialog(struct Camera *c) { if (!c) { return; } - if (get_dialog_id() == -1) { + if (get_dialog_id() == DIALOG_NONE) { vec3f_copy(gLakituState.goalPos, c->pos); vec3f_copy(gLakituState.goalFocus, c->focus); sStatusFlags |= (CAM_FLAG_SMOOTH_MOVEMENT | CAM_FLAG_UNUSED_CUTSCENE_ACTIVE); @@ -10195,7 +10195,7 @@ BAD_RETURN(s32) cutscene_intro_peach_letter(struct Camera *c) { cutscene_event(play_sound_peach_reading_letter, c, 83, 83); #endif - if ((gCutsceneTimer > 120) && (get_dialog_id() == -1)) { + if ((gCutsceneTimer > 120) && (get_dialog_id() == DIALOG_NONE)) { // Start the next scene gCutsceneTimer = CUTSCENE_LOOP; } diff --git a/src/game/camera.h b/src/game/camera.h index bf611d1d3..c4992e5e1 100644 --- a/src/game/camera.h +++ b/src/game/camera.h @@ -1203,7 +1203,7 @@ u8 start_object_cutscene_without_focus(u8 cutscene); Starts a cutscene involving an object and displays dialog during the sequence. The camera focuses on the object while synchronizing dialog with the scene |descriptionEnd| */ -s16 cutscene_object_with_dialog(u8 cutscene, struct Object *o, s16 dialogID); +s16 cutscene_object_with_dialog(u8 cutscene, struct Object *o, s32 dialogID); /* |description| Starts a cutscene involving an object without dialog. diff --git a/src/game/envfx_snow.c b/src/game/envfx_snow.c index 0807ff451..6921bcd6d 100644 --- a/src/game/envfx_snow.c +++ b/src/game/envfx_snow.c @@ -531,7 +531,7 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo) Gfx *envfx_update_particles(s32 mode, Vec3s marioPos, Vec3s camTo, Vec3s camFrom) { Gfx *gfx; - if (get_dialog_id() != -1) { + if (get_dialog_id() != DIALOG_NONE) { return NULL; } diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 637c099a2..3a555da56 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -38,6 +38,7 @@ #include "level_info.h" #include "pc/lua/utils/smlua_text_utils.h" #include "menu/ingame_text.h" +#include "pc/dialog_table.h" u16 gDialogColorFadeTimer; s8 gLastDialogLineNum; @@ -128,7 +129,7 @@ f32 gDialogBoxOpenTimer = DEFAULT_DIALOG_BOX_ANGLE; f32 gDialogBoxScale = DEFAULT_DIALOG_BOX_SCALE; s16 gDialogScrollOffsetY = 0; s8 gDialogBoxType = DIALOG_TYPE_ROTATE; -s16 gDialogID = -1; +s32 gDialogID = DIALOG_NONE; s16 gLastDialogPageStrPos = 0; s16 gDialogTextPos = 0; #ifdef VERSION_EU @@ -1025,24 +1026,24 @@ void int_to_str(s32 num, u8 *dst) { dst[pos] = DIALOG_CHAR_TERMINATOR; } -s16 get_dialog_id(void) { +s32 get_dialog_id(void) { return gDialogID; } -void handle_special_dialog_text(s16 dialogID) { // dialog ID tables, in order +void handle_special_dialog_text(s32 dialogID) { // dialog ID tables, in order // King Bob-omb (Start), Whomp (Start), King Bob-omb (throw him out), Eyerock (Start), Wiggler (Start) - s16 dialogBossStart[] = { 17, 114, 128, 117, 150 }; + enum DialogId dialogBossStart[] = { DIALOG_017, DIALOG_114, DIALOG_128, DIALOG_117, DIALOG_150 }; // Koopa the Quick (BOB), Koopa the Quick (THI), Penguin Race, Fat Penguin Race (120 stars) - s16 dialogRaceSound[] = { 5, 9, 55, 164 }; + enum DialogId dialogRaceSound[] = { DIALOG_005, DIALOG_009, DIALOG_055, DIALOG_164 }; // Red Switch, Green Switch, Blue Switch, 100 coins star, Bowser Red Coin Star - s16 dialogStarSound[] = { 10, 11, 12, 13, 14 }; + enum DialogId dialogStarSound[] = { DIALOG_010, DIALOG_011, DIALOG_012, DIALOG_013, DIALOG_014 }; // King Bob-omb (Start), Whomp (Defeated), King Bob-omb (Defeated, missing in JP), Eyerock (Defeated), Wiggler (Defeated) #if BUGFIX_KING_BOB_OMB_FADE_MUSIC - s16 dialogBossStop[] = { 17, 115, 116, 118, 152 }; + enum DialogId dialogBossStop[] = { DIALOG_017, DIALOG_115, DIALOG_116, DIALOG_118, DIALOG_152 }; #else //! @bug JP misses King Bob-omb defeated dialog "116", meaning that the boss music will still //! play after King Bob-omb is defeated until BOB loads it's music after the star cutscene - s16 dialogBossStop[] = { 17, 115, 118, 152 }; + enum DialogId dialogBossStop[] = { DIALOG_017, DIALOG_115, DIALOG_118, DIALOG_152 }; #endif s16 i; @@ -1079,7 +1080,7 @@ void handle_special_dialog_text(s16 dialogID) { // dialog ID tables, in order static u8 sHookString[255]; static bool sOverrideDialogString = false; void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu); -bool handle_dialog_hook(s16 dialogId) { +bool handle_dialog_hook(s32 dialogId) { bool openDialogBox = true; const char *dialogTextOverride = NULL; smlua_call_event_hooks(HOOK_ON_DIALOG, dialogId, &openDialogBox, &dialogTextOverride); @@ -1092,30 +1093,30 @@ bool handle_dialog_hook(s16 dialogId) { return true; } -void create_dialog_box(s16 dialog) { - if (handle_dialog_hook(dialog) && gDialogID == -1) { +void create_dialog_box(s32 dialog) { + if (handle_dialog_hook(dialog) && gDialogID == DIALOG_NONE) { gDialogID = dialog; gDialogBoxType = DIALOG_TYPE_ROTATE; } } -void create_dialog_box_with_var(s16 dialog, s32 dialogVar) { - if (handle_dialog_hook(dialog) && gDialogID == -1) { +void create_dialog_box_with_var(s32 dialog, s32 dialogVar) { + if (handle_dialog_hook(dialog) && gDialogID == DIALOG_NONE) { gDialogID = dialog; gDialogVariable = dialogVar; gDialogBoxType = DIALOG_TYPE_ROTATE; } } -void create_dialog_inverted_box(s16 dialog) { - if (handle_dialog_hook(dialog) && gDialogID == -1) { +void create_dialog_inverted_box(s32 dialog) { + if (handle_dialog_hook(dialog) && gDialogID == DIALOG_NONE) { gDialogID = dialog; gDialogBoxType = DIALOG_TYPE_ZOOM; } } -void create_dialog_box_with_response(s16 dialog) { - if (handle_dialog_hook(dialog) && gDialogID == -1) { +void create_dialog_box_with_response(s32 dialog) { + if (handle_dialog_hook(dialog) && gDialogID == DIALOG_NONE) { gDialogID = dialog; gDialogBoxType = DIALOG_TYPE_ROTATE; gLastDialogResponse = 1; @@ -1132,7 +1133,7 @@ void reset_dialog_render_state(void) { gDialogBoxScale = 19.0f; gDialogBoxOpenTimer = 90.0f; gDialogBoxState = DIALOG_STATE_OPENING; - gDialogID = -1; + gDialogID = DIALOG_NONE; gDialogTextPos = 0; gLastDialogResponse = 0; gLastDialogPageStrPos = 0; @@ -1877,36 +1878,14 @@ void render_dialog_entries(void) { #ifdef VERSION_EU s8 lowerBound = 0; #endif - void **dialogTable; - struct DialogEntry *dialog; + #if defined(VERSION_US) || defined(VERSION_SH) s8 lowerBound = 0; #endif -#ifdef VERSION_EU - gInGameLanguage = eu_get_language(); - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - dialogTable = segmented_to_virtual(dialog_table_eu_en); - break; - case LANGUAGE_FRENCH: - dialogTable = segmented_to_virtual(dialog_table_eu_fr); - break; - case LANGUAGE_GERMAN: - dialogTable = segmented_to_virtual(dialog_table_eu_de); - break; - } -#else - if (gDialogID >= DIALOG_COUNT || gDialogID < 0) { - gDialogID = -1; - return; - } - dialogTable = segmented_to_virtual(seg2_dialog_table); -#endif - dialog = segmented_to_virtual(dialogTable[gDialogID]); + struct DialogEntry *dialog = dialog_table_get(gDialogID); - // if the dialog entry is invalid, set the ID to -1. - if (segmented_to_virtual(NULL) == dialog) { - gDialogID = -1; + if (dialog == NULL) { + gDialogID = DIALOG_NONE; return; } @@ -1984,7 +1963,7 @@ void render_dialog_entries(void) { if (gDialogBoxOpenTimer == DEFAULT_DIALOG_BOX_ANGLE) { gDialogBoxState = DIALOG_STATE_OPENING; - gDialogID = -1; + gDialogID = DIALOG_NONE; gDialogTextPos = 0; gLastDialogResponse = 0; gLastDialogPageStrPos = 0; @@ -2198,28 +2177,9 @@ void do_cutscene_handler(void) { // "Dear Mario" message handler void print_peach_letter_message(void) { - void **dialogTable; - struct DialogEntry *dialog; - u8 *str; -#ifdef VERSION_EU - gInGameLanguage = eu_get_language(); - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - dialogTable = segmented_to_virtual(dialog_table_eu_en); - break; - case LANGUAGE_FRENCH: - dialogTable = segmented_to_virtual(dialog_table_eu_fr); - break; - case LANGUAGE_GERMAN: - dialogTable = segmented_to_virtual(dialog_table_eu_de); - break; - } -#else - dialogTable = segmented_to_virtual(seg2_dialog_table); -#endif - dialog = segmented_to_virtual(dialogTable[gDialogID]); + struct DialogEntry *dialog = dialog_table_get(gDialogID); - str = sOverrideDialogString ? sHookString : segmented_to_virtual(dialog->str); + const u8* str = sOverrideDialogString ? sHookString : dialog->str; create_dl_translation_matrix(MENU_MTX_PUSH, 97.0f, 118.0f, 0); @@ -2260,7 +2220,7 @@ void print_peach_letter_message(void) { if (gCutsceneMsgTimer > (PEACH_MESSAGE_TIMER + 20)) { gCutsceneMsgIndex = -1; gCutsceneMsgFade = 0; //! uselessly reset since the next execution will just set it to 0 again. - gDialogID = -1; + gDialogID = DIALOG_NONE; gCutsceneMsgTimer = 0; return; // return to avoid incrementing the timer } @@ -3472,9 +3432,9 @@ s16 render_menus_and_dialogs(void) { } gDialogColorFadeTimer = (s16) gDialogColorFadeTimer + 0x1000; - } else if (gDialogID != -1) { + } else if (gDialogID != DIALOG_NONE) { // The Peach "Dear Mario" message needs to be repositioned separately - if (gDialogID == 20) { + if (gDialogID == DIALOG_020) { print_peach_letter_message(); return mode; } diff --git a/src/game/ingame_menu.h b/src/game/ingame_menu.h index a3816fc6f..6748a81a0 100644 --- a/src/game/ingame_menu.h +++ b/src/game/ingame_menu.h @@ -2,6 +2,7 @@ #define INGAME_MENU_H #include +#include #define ASCII_TO_DIALOG(asc) \ (((asc) >= '0' && (asc) <= '9') ? ((asc) - '0') : \ @@ -39,12 +40,13 @@ extern s8 gHudFlash; struct DialogEntry { - u32 unused; /*0x00*/ - s8 linesPerBox; /*0x04*/ - s16 leftOffset; /*0x06*/ - s16 width; /*0x08*/ - const u8 *str; /*0x0C*/ + u32 unused; + s8 linesPerBox; + s16 leftOffset; + s16 width; + const u8 *str; char* text; + bool replaced; }; // EU only @@ -158,15 +160,15 @@ s16 get_str_x_pos_from_center_scale(s16 centerPos, u8 *str, f32 scale); #endif void print_hud_my_score_coins(s32 useCourseCoinScore, s8 fileNum, s8 courseNum, s16 x, s16 y); void int_to_str(s32 num, u8 *dst); -s16 get_dialog_id(void); +s32 get_dialog_id(void); /* |description|Creates a dialog box with a dialog ID that rotates into view|descriptionEnd| */ -void create_dialog_box(s16 dialog); +void create_dialog_box(s32 dialog); /* |description|Creates a dialog box with a dialog variable|descriptionEnd| */ -void create_dialog_box_with_var(s16 dialog, s32 dialogVar); +void create_dialog_box_with_var(s32 dialog, s32 dialogVar); /* |description|Creates a dialog box with a dialog ID that zooms into view|descriptionEnd| */ -void create_dialog_inverted_box(s16 dialog); +void create_dialog_inverted_box(s32 dialog); /* |description|Creates a dialog box with a response|descriptionEnd| */ -void create_dialog_box_with_response(s16 dialog); +void create_dialog_box_with_response(s32 dialog); /* |description|Resets the dialog box's state including dialog ID and open state|descriptionEnd| */ void reset_dialog_render_state(void); /* |description| diff --git a/src/game/level_update.c b/src/game/level_update.c index bccfeefaf..b9a828974 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -250,11 +250,11 @@ u16 level_control_timer(s32 timerOp) { u32 pressed_pause(void) { if (gServerSettings.pauseAnywhere) { - if (get_dialog_id() < 0 && sCurrPlayMode == PLAY_MODE_NORMAL && sDelayedWarpOp == WARP_OP_NONE) { + if (get_dialog_id() == DIALOG_NONE && sCurrPlayMode == PLAY_MODE_NORMAL && sDelayedWarpOp == WARP_OP_NONE) { return gPlayer1Controller->buttonPressed & START_BUTTON; } } else { - u32 dialogActive = get_dialog_id() >= 0; + u32 dialogActive = get_dialog_id() != DIALOG_NONE; u32 intangible = (gMarioState->action & ACT_FLAG_INTANGIBLE) != 0; u32 firstPerson = gMarioState->action == ACT_FIRST_PERSON; @@ -299,7 +299,7 @@ void stub_level_update_1(void) { void load_level_init_text(u32 arg) { s32 gotAchievement; - u32 dialogID = gCurrentArea->dialog[arg]; + s32 dialogID = gCurrentArea->dialog[arg]; if (dialogID == gBehaviorValues.dialogs.VanishCourseDialog) { gotAchievement = save_file_get_flags() & SAVE_FLAG_HAVE_VANISH_CAP; diff --git a/src/game/mario.c b/src/game/mario.c index 7d0b3e69c..4dbd5b0e6 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -2063,9 +2063,9 @@ s32 execute_mario_action(UNUSED struct Object *o) { // don't update mario when in a cutscene if (gMarioState->playerIndex == 0) { - extern s16 gDialogID; + extern s32 gDialogID; if (gMarioState->freeze > 0) { gMarioState->freeze--; } - if (gMarioState->freeze < 2 && gDialogID != -1) { gMarioState->freeze = 2; } + if (gMarioState->freeze < 2 && gDialogID != DIALOG_NONE) { gMarioState->freeze = 2; } if (gMarioState->freeze < 2 && sCurrPlayMode == PLAY_MODE_PAUSED) { gMarioState->freeze = 2; } } diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 55296f7b8..bd660a2ce 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -238,7 +238,7 @@ s32 geo_switch_peach_eyes(s32 run, struct GraphNode *node, UNUSED s32 a2) { // unused static void stub_is_textbox_active(u16 *a0) { - if (get_dialog_id() == -1) { + if (get_dialog_id() == DIALOG_NONE) { *a0 = 0; } } @@ -576,7 +576,7 @@ s32 act_reading_automatic_dialog(struct MarioState *m) { } } } else if (m->actionState == 10) { // wait until dialog is done - if ((m->playerIndex == 0 && get_dialog_id() >= 0) || + if ((m->playerIndex == 0 && get_dialog_id() != DIALOG_NONE) || (m->playerIndex != 0 && m->dialogId != 0)) { m->actionState--; } diff --git a/src/game/mario_misc.c b/src/game/mario_misc.c index e3071cf7e..ff0c5d61f 100644 --- a/src/game/mario_misc.c +++ b/src/game/mario_misc.c @@ -139,7 +139,7 @@ static void toad_message_talking(void) { gCurrentObject->oToadMessageRecentlyTalked = TRUE; gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING; - u32 dialogId = gCurrentObject->oToadMessageDialogId; + s32 dialogId = gCurrentObject->oToadMessageDialogId; if (dialogId == TOAD_STAR_1_DIALOG) { gCurrentObject->oToadMessageDialogId = TOAD_STAR_1_DIALOG_AFTER; bhv_spawn_star_no_level_exit(gMarioStates[0].marioObj, 0, TRUE); diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index fc223d8dd..4860e72a1 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -850,7 +850,7 @@ s8 current_mario_room_check(s16 room) { /** * Triggers dialog when Mario is facing an object and controls it while in the dialog. */ -s16 trigger_obj_dialog_when_facing(struct MarioState* m, s32 *inDialog, s16 dialogID, f32 dist, s32 actionArg, u8 (*inContinueDialogFunction)(void)) { +s16 trigger_obj_dialog_when_facing(struct MarioState* m, s32 *inDialog, s32 dialogID, f32 dist, s32 actionArg, u8 (*inContinueDialogFunction)(void)) { if (!o) { return 0; } if (!m || !inDialog) { return 0; } s16 dialogueResponse; diff --git a/src/game/obj_behaviors.h b/src/game/obj_behaviors.h index 485ae20af..2595309af 100644 --- a/src/game/obj_behaviors.h +++ b/src/game/obj_behaviors.h @@ -40,7 +40,7 @@ void bhv_bobomb_loop(void); void bhv_bobomb_fuse_smoke_init(void); void bhv_bobomb_buddy_init(void); void bobomb_buddy_act_idle(void); -void bobomb_buddy_cannon_dialog(s16 dialogFirstText, s16 dialogSecondText); +void bobomb_buddy_cannon_dialog(s32 dialogFirstText, s32 dialogSecondText); void bobomb_buddy_act_talk(void); void bobomb_buddy_act_turn_to_talk(void); void bobomb_buddy_actions(void); diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index 819bf6d36..a4380e98e 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -105,7 +105,7 @@ s16 obj_get_pitch_from_vel(void) { * If the player declines the race, then disable time stop and allow Mario to * move again. */ -static s32 obj_update_race_proposition_dialog(struct MarioState* m, s16 dialogID, u8 (*inContinueDialogFunction)(void)) { +static s32 obj_update_race_proposition_dialog(struct MarioState* m, s32 dialogID, u8 (*inContinueDialogFunction)(void)) { s32 dialogResponse = cur_obj_update_dialog_with_cutscene(m, 2, DIALOG_UNK2_FLAG_0 | DIALOG_UNK2_LEAVE_TIME_STOP_ENABLED, CUTSCENE_RACE_DIALOG, dialogID, inContinueDialogFunction); if (dialogResponse == 2) { diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 10ea9cdc9..14269b2d5 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -3184,7 +3184,7 @@ s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, cur_obj_end_dialog(m, dialogFlags, gDialogResponse); } } else if (dialogFlags & DIALOG_UNK1_FLAG_DEFAULT) { - if (get_dialog_id() == -1) { + if (get_dialog_id() == DIALOG_NONE) { cur_obj_end_dialog(m, dialogFlags, 3); } } else { diff --git a/src/game/segment2.h b/src/game/segment2.h index 0a0bced19..e9e4f3345 100644 --- a/src/game/segment2.h +++ b/src/game/segment2.h @@ -57,7 +57,6 @@ extern u8* main_hud_camera_lut[6]; extern const Gfx dl_draw_text_bg_box[]; extern const Gfx dl_draw_triangle[]; extern const u8* seg2_dialog_original[]; -extern void *seg2_dialog_table[]; extern const Gfx dl_billboard_num_0[]; extern const Gfx dl_billboard_num_1[]; extern const Gfx dl_billboard_num_2[]; diff --git a/src/pc/dialog_table.c b/src/pc/dialog_table.c new file mode 100644 index 000000000..7720d5292 --- /dev/null +++ b/src/pc/dialog_table.c @@ -0,0 +1,99 @@ +#include "dialog_table.h" +#include "pc/lua/smlua.h" +#include "dialog_ids.h" +#include "PR/ultratypes.h" +#include "game/segment2.h" +#include "pc/lua/utils/smlua_text_utils.h" +#include "game/memory.h" +#include "pc/platform.h" +#include + +DialogTable *gDialogTable = NULL; + +void dialog_table_init(void) { + gDialogTable = growing_array_init(gDialogTable, 256); + + for (u32 i = 0; i < DIALOG_COUNT; i++) { + const struct DialogEntry* dialogOrig = smlua_text_utils_dialog_get_unmodified(i); + struct DialogEntry* dialog = dialog_table_alloc(NULL); + + if (!dialog) { + sys_fatal("Failed to allocate DialogEntry for dialog ID %d", i); + } + + memcpy(dialog, dialogOrig, sizeof(struct DialogEntry)); + dialog->text = get_dialog_text_ascii(dialog); + } +} + +struct DialogEntry* dialog_table_alloc(s32 *dialogId) { + DialogTable *table = gDialogTable; + + if (table->count >= MAX_ALLOCATED_DIALOGS) { + LOG_LUA_LINE_WARNING("Dialog limit reached! (%d max)", MAX_ALLOCATED_DIALOGS); + if (dialogId) *dialogId = DIALOG_NONE; + return NULL; + } + + struct DialogEntry* dialog = growing_array_alloc(table, sizeof(struct DialogEntry)); + + if (!dialog) { + LOG_LUA_LINE_WARNING("Failed to allocate DialogEntry"); + if (dialogId) *dialogId = DIALOG_NONE; + return NULL; + } + + if (dialogId) *dialogId = table->count - 1; + + return dialog; +} + +struct DialogEntry* dialog_table_get(s32 dialogId) { + if (!IS_VALID_DIALOG(dialogId)) { + return NULL; + } + + return gDialogTable->buffer[dialogId]; +} + +void dialog_table_reset(void) { + DialogTable *table = gDialogTable; + + if (!table) return; + + for (u32 i = 0; i < table->count; i++) { + struct DialogEntry *dialog = table->buffer[i]; + + if (!dialog->replaced) continue; + + if (!IS_CUSTOM_DIALOG(i)) { + smlua_text_utils_dialog_restore(i); + } else { + free((u8*)dialog->str); + free(dialog->text); + free(dialog); + table->buffer[i] = NULL; + } + } + + table->count = DIALOG_COUNT; +} + +void dialog_table_shutdown(void) { + DialogTable *table = gDialogTable; + + if (!table) return; + + dialog_table_reset(); + + for (u32 i = 0; i < DIALOG_COUNT; i++) { + struct DialogEntry *dialog = table->buffer[i]; + + free(dialog->text); + free(dialog); + } + + free(table->buffer); + free(table); + gDialogTable = NULL; +} \ No newline at end of file diff --git a/src/pc/dialog_table.h b/src/pc/dialog_table.h new file mode 100644 index 000000000..c7fb5b47a --- /dev/null +++ b/src/pc/dialog_table.h @@ -0,0 +1,23 @@ +#ifndef DIALOG_TABLE_H +#define DIALOG_TABLE_H + +#include "PR/ultratypes.h" +#include "game/ingame_menu.h" + +#define MAX_ALLOCATED_DIALOGS 0x8000 + +typedef struct GrowingArray DialogTable; + +void dialog_table_init(void); +struct DialogEntry* dialog_table_alloc(s32 *dialogId); +struct DialogEntry* dialog_table_get(s32 dialogId); +void dialog_table_reset(void); +void dialog_table_shutdown(void); + +extern DialogTable *gDialogTable; + +#define IS_CUSTOM_DIALOG(dialogId) ((dialogId) >= DIALOG_COUNT) +#define IS_VALID_DIALOG(dialogId) ((dialogId) >= 0 && (u32)(dialogId) < gDialogTable->count) +#define IS_VALID_VANILLA_DIALOG(dialogId) ((dialogId) >= 0 && (dialogId) < DIALOG_COUNT) + +#endif diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 23de2e9fe..da4895392 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -805,10 +805,11 @@ static struct LuaObjectField sDateTimeFields[LUA_DATE_TIME_FIELD_COUNT] = { { "year", LVT_S32, offsetof(struct DateTime, year), false, LOT_NONE, 1, sizeof(s32) }, }; -#define LUA_DIALOG_ENTRY_FIELD_COUNT 5 +#define LUA_DIALOG_ENTRY_FIELD_COUNT 6 static struct LuaObjectField sDialogEntryFields[LUA_DIALOG_ENTRY_FIELD_COUNT] = { { "leftOffset", LVT_S16, offsetof(struct DialogEntry, leftOffset), true, LOT_NONE, 1, sizeof(s16) }, { "linesPerBox", LVT_S8, offsetof(struct DialogEntry, linesPerBox), true, LOT_NONE, 1, sizeof(s8) }, + { "replaced", LVT_BOOL, offsetof(struct DialogEntry, replaced), true, LOT_NONE, 1, sizeof(bool) }, { "text", LVT_STRING_P, offsetof(struct DialogEntry, text), true, LOT_NONE, 1, sizeof(char*) }, { "unused", LVT_U32, offsetof(struct DialogEntry, unused), true, LOT_NONE, 1, sizeof(u32) }, { "width", LVT_S16, offsetof(struct DialogEntry, width), true, LOT_NONE, 1, sizeof(s16) }, @@ -1507,7 +1508,7 @@ static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = { { "controller", LVT_COBJECT_P, offsetof(struct MarioState, controller), true, LOT_CONTROLLER, 1, sizeof(struct Controller*) }, { "curAnimOffset", LVT_F32, offsetof(struct MarioState, curAnimOffset), false, LOT_NONE, 1, sizeof(f32) }, { "currentRoom", LVT_S16, offsetof(struct MarioState, currentRoom), false, LOT_NONE, 1, sizeof(s16) }, - { "dialogId", LVT_S16, offsetof(struct MarioState, dialogId), true, LOT_NONE, 1, sizeof(s16) }, + { "dialogId", LVT_S32, offsetof(struct MarioState, dialogId), true, LOT_NONE, 1, sizeof(s32) }, { "doubleJumpTimer", LVT_U8, offsetof(struct MarioState, doubleJumpTimer), false, LOT_NONE, 1, sizeof(u8) }, { "faceAngle", LVT_COBJECT, offsetof(struct MarioState, faceAngle), true, LOT_VEC3S, 1, sizeof(Vec3s) }, { "fadeWarpOpacity", LVT_U8, offsetof(struct MarioState, fadeWarpOpacity), false, LOT_NONE, 1, sizeof(u8) }, @@ -2356,7 +2357,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { { "oTiltingPyramidNormalY", LVT_F32, offsetof(struct Object, oTiltingPyramidNormalY), false, LOT_NONE, 1, sizeof(f32) }, { "oTiltingPyramidNormalZ", LVT_F32, offsetof(struct Object, oTiltingPyramidNormalZ), false, LOT_NONE, 1, sizeof(f32) }, { "oTimer", LVT_S32, offsetof(struct Object, oTimer), false, LOT_NONE, 1, sizeof(s32) }, - { "oToadMessageDialogId", LVT_U32, offsetof(struct Object, oToadMessageDialogId), false, LOT_NONE, 1, sizeof(u32) }, + { "oToadMessageDialogId", LVT_S32, offsetof(struct Object, oToadMessageDialogId), false, LOT_NONE, 1, sizeof(s32) }, { "oToadMessageRecentlyTalked", LVT_S32, offsetof(struct Object, oToadMessageRecentlyTalked), false, LOT_NONE, 1, sizeof(s32) }, { "oToadMessageState", LVT_S32, offsetof(struct Object, oToadMessageState), false, LOT_NONE, 1, sizeof(s32) }, // { "oToxBoxMovementPattern", LVT_???, offsetof(struct Object, oToxBoxMovementPattern), false, LOT_???, 1, sizeof(void*) }, <--- UNIMPLEMENTED diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index a318e3b3f..35995263c 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1267,6 +1267,7 @@ char gSmluaConstants[] = "" "L_MOUSE_BUTTON=MOUSE_BUTTON_1\n" "M_MOUSE_BUTTON=MOUSE_BUTTON_2\n" "R_MOUSE_BUTTON=MOUSE_BUTTON_3\n" +"DIALOG_NONE=-1\n" "DIALOG_000=0\n" "DIALOG_001=1\n" "DIALOG_002=2\n" @@ -1737,21 +1738,21 @@ char gSmluaConstants[] = "" "MARIO_SPAWN_PIPE=3\n" "MARIO_SPAWN_TELEPORT=4\n" "MARIO_SPAWN_INSTANT_ACTIVE=0x10\n" -"MARIO_SPAWN_SWIMMING=((MARIO_SPAWN_INSTANT_ACTIVE ) + 1)\n" -"MARIO_SPAWN_AIRBORNE=((MARIO_SPAWN_INSTANT_ACTIVE ) + 2)\n" -"MARIO_SPAWN_HARD_AIR_KNOCKBACK=((MARIO_SPAWN_INSTANT_ACTIVE ) + 3)\n" -"MARIO_SPAWN_SPIN_AIRBORNE_CIRCLE=((MARIO_SPAWN_INSTANT_ACTIVE ) + 4)\n" -"MARIO_SPAWN_DEATH=((MARIO_SPAWN_INSTANT_ACTIVE ) + 5)\n" -"MARIO_SPAWN_SPIN_AIRBORNE=((MARIO_SPAWN_INSTANT_ACTIVE ) + 6)\n" -"MARIO_SPAWN_FLYING=((MARIO_SPAWN_INSTANT_ACTIVE ) + 7)\n" +"MARIO_SPAWN_SWIMMING=17\n" +"MARIO_SPAWN_AIRBORNE=18\n" +"MARIO_SPAWN_HARD_AIR_KNOCKBACK=19\n" +"MARIO_SPAWN_SPIN_AIRBORNE_CIRCLE=20\n" +"MARIO_SPAWN_DEATH=21\n" +"MARIO_SPAWN_SPIN_AIRBORNE=22\n" +"MARIO_SPAWN_FLYING=23\n" "MARIO_SPAWN_PAINTING_STAR_COLLECT=0x20\n" -"MARIO_SPAWN_PAINTING_DEATH=((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 1)\n" -"MARIO_SPAWN_AIRBORNE_STAR_COLLECT=((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 2)\n" -"MARIO_SPAWN_AIRBORNE_DEATH=((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 3)\n" -"MARIO_SPAWN_LAUNCH_STAR_COLLECT=((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 4)\n" -"MARIO_SPAWN_LAUNCH_DEATH=((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 5)\n" -"MARIO_SPAWN_UNUSED_38=((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 6)\n" -"MARIO_SPAWN_FADE_FROM_BLACK=((MARIO_SPAWN_PAINTING_STAR_COLLECT ) + 7)\n" +"MARIO_SPAWN_PAINTING_DEATH=33\n" +"MARIO_SPAWN_AIRBORNE_STAR_COLLECT=34\n" +"MARIO_SPAWN_AIRBORNE_DEATH=35\n" +"MARIO_SPAWN_LAUNCH_STAR_COLLECT=36\n" +"MARIO_SPAWN_LAUNCH_DEATH=37\n" +"MARIO_SPAWN_UNUSED_38=38\n" +"MARIO_SPAWN_FADE_FROM_BLACK=39\n" "MARIO_SPAWN_UNKNOWN_02=0x02\n" "MARIO_SPAWN_UNKNOWN_03=0x03\n" "MARIO_SPAWN_UNKNOWN_27=0x27\n" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 885815bc9..396739a18 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -11908,7 +11908,7 @@ int smlua_func_cutscene_object_with_dialog(lua_State* L) { if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "cutscene_object_with_dialog"); return 0; } struct Object* o = (struct Object*)smlua_to_cobject(L, 2, LOT_OBJECT); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "cutscene_object_with_dialog"); return 0; } - s16 dialogID = smlua_to_integer(L, 3); + s32 dialogID = smlua_to_integer(L, 3); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "cutscene_object_with_dialog"); return 0; } lua_pushinteger(L, cutscene_object_with_dialog(cutscene, o, dialogID)); @@ -13463,7 +13463,7 @@ int smlua_func_play_dialog_sound(lua_State* L) { return 0; } - u8 dialogID = smlua_to_integer(L, 1); + s32 dialogID = smlua_to_integer(L, 1); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "play_dialog_sound"); return 0; } play_dialog_sound(dialogID); @@ -13935,7 +13935,7 @@ int smlua_func_create_dialog_box(lua_State* L) { return 0; } - s16 dialog = smlua_to_integer(L, 1); + s32 dialog = smlua_to_integer(L, 1); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_box"); return 0; } create_dialog_box(dialog); @@ -13952,7 +13952,7 @@ int smlua_func_create_dialog_box_with_var(lua_State* L) { return 0; } - s16 dialog = smlua_to_integer(L, 1); + s32 dialog = smlua_to_integer(L, 1); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_box_with_var"); return 0; } s32 dialogVar = smlua_to_integer(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "create_dialog_box_with_var"); return 0; } @@ -13971,7 +13971,7 @@ int smlua_func_create_dialog_inverted_box(lua_State* L) { return 0; } - s16 dialog = smlua_to_integer(L, 1); + s32 dialog = smlua_to_integer(L, 1); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_inverted_box"); return 0; } create_dialog_inverted_box(dialog); @@ -13988,7 +13988,7 @@ int smlua_func_create_dialog_box_with_response(lua_State* L) { return 0; } - s16 dialog = smlua_to_integer(L, 1); + s32 dialog = smlua_to_integer(L, 1); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_box_with_response"); return 0; } create_dialog_box_with_response(dialog); @@ -35273,6 +35273,23 @@ int smlua_func_smlua_text_utils_dialog_replace(lua_State* L) { return 1; } +int smlua_func_smlua_text_utils_dialog_restore(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_dialog_restore", 1, top); + return 0; + } + + int dialogId = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_dialog_restore"); return 0; } + + smlua_text_utils_dialog_restore(dialogId); + + return 1; +} + int smlua_func_smlua_text_utils_dialog_is_replaced(lua_State* L) { if (L == NULL) { return 0; } @@ -35290,6 +35307,21 @@ int smlua_func_smlua_text_utils_dialog_is_replaced(lua_State* L) { return 1; } +int smlua_func_smlua_text_utils_allocate_dialog(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_allocate_dialog", 0, top); + return 0; + } + + + lua_pushinteger(L, smlua_text_utils_allocate_dialog()); + + return 1; +} + int smlua_func_smlua_text_utils_course_acts_replace(lua_State* L) { if (L == NULL) { return 0; } @@ -38380,7 +38412,9 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "smlua_text_utils_reset_all", smlua_func_smlua_text_utils_reset_all); smlua_bind_function(L, "smlua_text_utils_dialog_get", smlua_func_smlua_text_utils_dialog_get); smlua_bind_function(L, "smlua_text_utils_dialog_replace", smlua_func_smlua_text_utils_dialog_replace); + smlua_bind_function(L, "smlua_text_utils_dialog_restore", smlua_func_smlua_text_utils_dialog_restore); smlua_bind_function(L, "smlua_text_utils_dialog_is_replaced", smlua_func_smlua_text_utils_dialog_is_replaced); + smlua_bind_function(L, "smlua_text_utils_allocate_dialog", smlua_func_smlua_text_utils_allocate_dialog); smlua_bind_function(L, "smlua_text_utils_course_acts_replace", smlua_func_smlua_text_utils_course_acts_replace); smlua_bind_function(L, "smlua_text_utils_secret_star_replace", smlua_func_smlua_text_utils_secret_star_replace); smlua_bind_function(L, "smlua_text_utils_course_name_replace", smlua_func_smlua_text_utils_course_name_replace); diff --git a/src/pc/lua/utils/smlua_misc_utils.h b/src/pc/lua/utils/smlua_misc_utils.h index 0469da92a..b8b5b198b 100644 --- a/src/pc/lua/utils/smlua_misc_utils.h +++ b/src/pc/lua/utils/smlua_misc_utils.h @@ -85,7 +85,7 @@ bool djui_is_playerlist_ping_visible(void); /* |description|Gets the current state of the dialog box|descriptionEnd| */ s8 get_dialog_box_state(void); /* |description|Gets the current dialog box ID|descriptionEnd| */ -s16 get_dialog_id(void); +s32 get_dialog_id(void); /* |description|Gets if the last objective collected was a star (0) or a key (1)|descriptionEnd| */ u8 get_last_star_or_key(void); diff --git a/src/pc/lua/utils/smlua_text_utils.c b/src/pc/lua/utils/smlua_text_utils.c index c0aac16ae..dbce0ed46 100644 --- a/src/pc/lua/utils/smlua_text_utils.c +++ b/src/pc/lua/utils/smlua_text_utils.c @@ -10,14 +10,13 @@ #include "../smlua.h" #include "smlua_level_utils.h" #include "smlua_text_utils.h" +#include "pc/dialog_table.h" #ifdef VERSION_EU extern s32 gInGameLanguage; #include "eu_translation.h" #endif -static bool sReplacedDialog[DIALOG_COUNT] = { 0 }; - #define INVALID_COURSE_NUM(courseNum) (smlua_level_util_get_info_from_course_num(courseNum) == NULL && !COURSE_IS_VALID_COURSE(courseNum)) extern const struct { const char *str; u8 c; u8 menu; } sSm64CharMap[]; @@ -43,7 +42,7 @@ char* get_dialog_text_ascii(struct DialogEntry *dialog) { size_t len = measure_converted_sm64_string(dialog->str); char* asciiStr = malloc(len + 1); - if (!asciiStr) return NULL; + if (!asciiStr) { return NULL; } convert_string_sm64_to_ascii(asciiStr, dialog->str); @@ -86,6 +85,7 @@ static bool sSmluaTextUtilsInited = false; // Save all vanilla act names and course names void smlua_text_utils_init(void) { + dialog_table_init(); memset(gReplacedCourseActNameTable, 0, sizeof(gReplacedCourseActNameTable)); // Vanilla courses @@ -126,15 +126,6 @@ void smlua_text_utils_init(void) { ); } - for (s32 i = 0; i < DIALOG_COUNT; i++) { - struct DialogEntry *dialog = smlua_text_utils_dialog_get(i); - char* dialogText = get_dialog_text_ascii(dialog); - - free(dialog->text); - - dialog->text = dialogText; - } - sSmluaTextUtilsInited = true; } @@ -186,40 +177,7 @@ static void smlua_text_utils_replace_course_or_act_name(struct ReplacedName *nam } void smlua_text_utils_reset_all(void) { - void **dialogTable = NULL; - void **dialogTableOrg = NULL; - -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - dialogTable = segmented_to_virtual(dialog_table_eu_en); - dialogTableOrg = segmented_to_virtual(dialog_table_eu_en_original); - break; - case LANGUAGE_FRENCH: - dialogTable = segmented_to_virtual(dialog_table_eu_fr); - dialogTableOrg = segmented_to_virtual(dialog_table_eu_fr_original); - break; - case LANGUAGE_GERMAN: - dialogTable = segmented_to_virtual(dialog_table_eu_de); - dialogTableOrg = segmented_to_virtual(dialog_table_eu_de_original); - break; - } -#else - dialogTable = segmented_to_virtual(seg2_dialog_table); - dialogTableOrg = segmented_to_virtual(seg2_dialog_original); -#endif - - for (s32 i = 0; i < DIALOG_COUNT; i++) { - if (!sReplacedDialog[i]) { continue; } - const struct DialogEntry *dialogOrig = segmented_to_virtual(dialogTableOrg[i]); - struct DialogEntry *dialog = segmented_to_virtual(dialogTable[i]); - free((u8*)dialog->str); - free(dialog->text); - - memcpy(dialog, dialogOrig, sizeof(struct DialogEntry)); - dialog->text = get_dialog_text_ascii(dialog); - sReplacedDialog[i] = false; - } + dialog_table_reset(); if (sSmluaTextUtilsInited) { for (s16 courseNum = 0; courseNum < COURSE_END; courseNum++) { @@ -234,40 +192,48 @@ void smlua_text_utils_reset_all(void) { smlua_text_utils_reset_course_or_act_name(actName); } } + } else { + dialog_table_shutdown(); } } -struct DialogEntry* smlua_text_utils_dialog_get(enum DialogId dialogId){ - if (dialogId >= DIALOG_COUNT) { return NULL; } +struct DialogEntry* smlua_text_utils_dialog_get(enum DialogId dialogId) { + struct DialogEntry* dialog = dialog_table_get(dialogId); + return dialog; +} - void **dialogTable = NULL; +const struct DialogEntry* smlua_text_utils_dialog_get_unmodified(enum DialogId dialogId) { + if (!IS_VALID_VANILLA_DIALOG(dialogId)) { return NULL; } + + void **dialogTableOrg; #ifdef VERSION_EU switch (gInGameLanguage) { case LANGUAGE_ENGLISH: - dialogTable = segmented_to_virtual(dialog_table_eu_en); + dialogTableOrg = segmented_to_virtual(dialog_table_eu_en_original); break; case LANGUAGE_FRENCH: - dialogTable = segmented_to_virtual(dialog_table_eu_fr); + dialogTableOrg = segmented_to_virtual(dialog_table_eu_fr_original); break; case LANGUAGE_GERMAN: - dialogTable = segmented_to_virtual(dialog_table_eu_de); + dialogTableOrg = segmented_to_virtual(dialog_table_eu_de_original); break; } #else - dialogTable = segmented_to_virtual(seg2_dialog_table); + dialogTableOrg = segmented_to_virtual(seg2_dialog_original); #endif - struct DialogEntry *dialog = segmented_to_virtual(dialogTable[dialogId]); - return dialog; + return segmented_to_virtual(dialogTableOrg[dialogId]); } void smlua_text_utils_dialog_replace(enum DialogId dialogId, UNUSED u32 unused, s8 linesPerBox, s16 leftOffset, s16 width, const char* str) { + if (!IS_VALID_DIALOG(dialogId)) { return; } + struct DialogEntry *dialog = smlua_text_utils_dialog_get(dialogId); if (!dialog) { return; } - if (sReplacedDialog[dialogId]) { + if (dialog->replaced) { free((u8*)dialog->str); } @@ -279,16 +245,41 @@ void smlua_text_utils_dialog_replace(enum DialogId dialogId, UNUSED u32 unused, dialog->width = width; dialog->str = smlua_text_utils_convert(str); dialog->text = strdup(str); + dialog->replaced = true; +} - sReplacedDialog[dialogId] = true; +void smlua_text_utils_dialog_restore(enum DialogId dialogId) { + if (!IS_VALID_VANILLA_DIALOG(dialogId)) { return; } + + struct DialogEntry *dialog = smlua_text_utils_dialog_get(dialogId); + + if (!dialog->replaced) return; + + const struct DialogEntry *dialogOrig = smlua_text_utils_dialog_get_unmodified(dialogId); + + free((u8*)dialog->str); + free(dialog->text); + + memcpy(dialog, dialogOrig, sizeof(struct DialogEntry)); + dialog->text = get_dialog_text_ascii(dialog); } bool smlua_text_utils_dialog_is_replaced(enum DialogId dialogId) { - if (dialogId >= DIALOG_COUNT) { - return false; + if (!IS_VALID_DIALOG(dialogId)) { return false; } + + struct DialogEntry *dialog = dialog_table_get(dialogId); + return dialog->replaced; +} + +s32 smlua_text_utils_allocate_dialog(void) { + s32 dialogId; + struct DialogEntry* dialog = dialog_table_alloc(&dialogId); + + if (dialog) { + dialog->replaced = true; } - return sReplacedDialog[dialogId]; + return dialogId; } 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) { diff --git a/src/pc/lua/utils/smlua_text_utils.h b/src/pc/lua/utils/smlua_text_utils.h index 6d9d53a17..ea2b7bfa9 100644 --- a/src/pc/lua/utils/smlua_text_utils.h +++ b/src/pc/lua/utils/smlua_text_utils.h @@ -3,6 +3,7 @@ #include "types.h" #include "dialog_ids.h" +#include "game/ingame_menu.h" #define MAX_ACTS 6 #define MAX_ACTS_AND_100_COINS 7 @@ -26,16 +27,23 @@ struct CourseActNames { extern struct CourseActNames gReplacedCourseActNameTable[]; // indexed by COURSE_* constants +char* get_dialog_text_ascii(struct DialogEntry *dialog); + void smlua_text_utils_init(void); void smlua_text_utils_shutdown(void); /* |description|Resets every modified dialog back to vanilla|descriptionEnd|*/ void smlua_text_utils_reset_all(void); /* |description|Gets the DialogEntry struct for the given `dialogId`|descriptionEnd| */ struct DialogEntry* smlua_text_utils_dialog_get(enum DialogId dialogId); +const struct DialogEntry* smlua_text_utils_dialog_get_unmodified(enum DialogId dialogId); /* |description|Replaces `dialogId` with a custom one|descriptionEnd| */ void smlua_text_utils_dialog_replace(enum DialogId dialogId, u32 unused, s8 linesPerBox, s16 leftOffset, s16 width, const char* str); +/* |description|Restores a replaced DialogEntry to its original state.|descriptionEnd| */ +void smlua_text_utils_dialog_restore(enum DialogId dialogId); /* |description|Returns whether the dialog with the given ID has been replaced|descriptionEnd| */ bool smlua_text_utils_dialog_is_replaced(enum DialogId dialogId); +/* |description|Allocates a new dialog entry|descriptionEnd|*/ +s32 smlua_text_utils_allocate_dialog(void); /* |description|Replaces the act names of `courseNum`|descriptionEnd| */ 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); /* |description|Replaces the secret star course name of `courseNum` with `courseName`|descriptionEnd| */ diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 8747963f6..793def2db 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -77,7 +77,7 @@ struct PacketPlayerData { u8 areaSyncValid; u8 knockbackTimer; - s16 dialogId; + s32 dialogId; }; #pragma pack() diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 2ad21c964..ddcc6a734 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -52,7 +52,6 @@ #include "pc/djui/djui_lua_profiler.h" #include "pc/debuglog.h" #include "pc/utils/misc.h" - #include "pc/mods/mods.h" #include "debug_context.h" diff --git a/text/define_text.inc.c b/text/define_text.inc.c index 4a932ffb5..0d2177ec0 100644 --- a/text/define_text.inc.c +++ b/text/define_text.inc.c @@ -9,15 +9,7 @@ #undef DEFINE_DIALOG #define DEFINE_DIALOG(id, unused, linesPerBox, leftOffset, width, _) \ static const struct DialogEntry dialog_entry_orig_ ## id = { \ - unused, linesPerBox, leftOffset, width, dialog_text_ ## id, NULL \ - }; - -#include "dialogs.h" - -#undef DEFINE_DIALOG -#define DEFINE_DIALOG(id, unused, linesPerBox, leftOffset, width, _) \ - static struct DialogEntry dialog_entry_ ## id = { \ - unused, linesPerBox, leftOffset, width, dialog_text_ ## id, NULL \ + unused, linesPerBox, leftOffset, width, dialog_text_ ## id, NULL, false \ }; #include "dialogs.h" @@ -31,12 +23,6 @@ const struct DialogEntry *const seg2_dialog_original[] = { }; #undef DEFINE_DIALOG -#define DEFINE_DIALOG(id, _1, _2, _3, _4, _5) &dialog_entry_ ## id, - -const struct DialogEntry *const seg2_dialog_table[] = { -#include "dialogs.h" - NULL -}; // == courses == // (defines en_course_name_table etc.)