From bee8427a24c3c649d908dc9fe5f5668a254b2662 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Fri, 6 Sep 2024 23:33:36 -0700 Subject: [PATCH 1/4] Port OoT's new msgdis and msgenc --- Makefile | 18 +- assets/text/charmap.txt | 21 + assets/text/message_data_static.c | 4 +- assets/text/staff_message_data_static.c | 6 +- include/message_data_fmt_nes.h | 526 ++-- include/message_data_fmt_staff.h | 248 +- include/message_data_static.h | 6 +- src/code/z_message.c | 6 +- tools/extract_assets.py | 41 +- tools/msg/nes/msgdisNES.py | 322 --- tools/msg/nes/msgencNES.py | 85 - tools/msg/staff/msgdisStaff.py | 237 -- tools/msg/staff/msgencStaff.py | 72 - tools/text/msgdis.py | 3190 +++++++++++++++++++++++ tools/text/msgenc.py | 166 ++ 15 files changed, 3698 insertions(+), 1250 deletions(-) create mode 100644 assets/text/charmap.txt delete mode 100755 tools/msg/nes/msgdisNES.py delete mode 100755 tools/msg/nes/msgencNES.py delete mode 100755 tools/msg/staff/msgdisStaff.py delete mode 100755 tools/msg/staff/msgencStaff.py create mode 100755 tools/text/msgdis.py create mode 100644 tools/text/msgenc.py diff --git a/Makefile b/Makefile index 5aaf1f69ac3..609b161c0fa 100644 --- a/Makefile +++ b/Makefile @@ -458,6 +458,7 @@ setup-audio: assets: $(PYTHON) tools/extract_assets.py $(EXTRACTED_DIR)/baserom assets -j$(N_THREADS) -Z Wno-hardcoded-pointer -v $(VERSION) + $(PYTHON) tools/text/msgdis.py $(EXTRACTED_DIR)/baserom assets/text -v $(VERSION) $(AUDIO_EXTRACT) -o $(EXTRACTED_DIR) -v $(VERSION) --read-xml ## Assembly generation @@ -510,6 +511,11 @@ $(BUILD_DIR)/src/dmadata/dmadata.o: $(BUILD_DIR)/dmadata/dmadata_table_spec.h $(BUILD_DIR)/%.o: %.s $(CPP) $(CPPFLAGS) $(IINC) $< | $(AS) $(ASFLAGS) $(IINC) $(ENDIAN) -o $@ +$(BUILD_DIR)/assets/text/%.o: assets/text/%.c +# Preprocess text with modern cpp for varargs macros + $(CPP) -undef -D_LANGUAGE_C -D__sgi $(CPPFLAGS) $(IINC) $< -o $(@:.o=.c) + $(CC) -c $(CFLAGS) $(WARNINGS) $(C_DEFINES) $(MIPS_VERSION) $(ENDIAN) $(OPTFLAGS) -o $@ $(@:.o=.c) + $(BUILD_DIR)/assets/%.o: assets/%.c $(CC) -c $(CFLAGS) $(IINC) $(WARNINGS) $(C_DEFINES) $(MIPS_VERSION) $(ENDIAN) $(OPTFLAGS) -o $@ $< $(OBJCOPY_BIN) @@ -522,15 +528,15 @@ $(BUILD_DIR)/%.yar.o: $(BUILD_DIR)/%.o $(BUILD_DIR)/baserom/%.o: $(EXTRACTED_DIR)/baserom/% $(OBJCOPY) -I binary -O elf32-big $< $@ -$(BUILD_DIR)/assets/text/message_data.enc.h: assets/text/message_data.h - $(PYTHON) tools/msg/nes/msgencNES.py -o $@ $< +$(BUILD_DIR)/assets/text/message_data.enc.h: assets/text/message_data.h assets/text/charmap.txt + $(CPP) $(CPPFLAGS) -I$(EXTRACTED_DIR) $< | $(PYTHON) tools/text/msgenc.py --encoding nes --charmap assets/text/charmap.txt - $@ -$(BUILD_DIR)/assets/text/staff_message_data.enc.h: assets/text/staff_message_data.h - $(PYTHON) tools/msg/staff/msgencStaff.py -o $@ $< +$(BUILD_DIR)/assets/text/message_data_staff.enc.h: assets/text/message_data_staff.h assets/text/charmap.txt + $(CPP) $(CPPFLAGS) -I$(EXTRACTED_DIR) $< | $(PYTHON) tools/text/msgenc.py --encoding credits --charmap assets/text/charmap.txt - $@ $(BUILD_DIR)/assets/text/message_data_static.o: $(BUILD_DIR)/assets/text/message_data.enc.h -$(BUILD_DIR)/assets/text/staff_message_data_static.o: $(BUILD_DIR)/assets/text/staff_message_data.enc.h -$(BUILD_DIR)/src/code/z_message.o: $(BUILD_DIR)/assets/text/message_data.enc.h $(BUILD_DIR)/assets/text/staff_message_data.enc.h +$(BUILD_DIR)/assets/text/staff_message_data_static.o: $(BUILD_DIR)/assets/text/message_data_staff.enc.h +$(BUILD_DIR)/src/code/z_message.o: $(BUILD_DIR)/assets/text/message_data.enc.h $(BUILD_DIR)/assets/text/message_data_staff.enc.h $(BUILD_DIR)/src/overlays/%_reloc.o: $(BUILD_DIR)/$(SPEC) $(FADO) $$(tools/buildtools/reloc_prereq $< $(*F)) -n $(*F) -o $(@:.o=.s) -M $(@:.o=.d) diff --git a/assets/text/charmap.txt b/assets/text/charmap.txt new file mode 100644 index 00000000000..30330e8892b --- /dev/null +++ b/assets/text/charmap.txt @@ -0,0 +1,21 @@ +# Determines how certain text sequences should be encoded. The text sequence is +# converted to either the first or second tuple element based on whether the +# target encoding is the "wide" encoding. The first element is for the non-wide +# encoding, used for all languages besides JP, while the second element is for +# the wide encoding, used for JP, the third element is for encoding credits. +{ + '\n' : (0x11, 0x000A, 0x01), + + '[A]' : (0xB0, 0x839F, None), + '[B]' : (0xB1, 0x83A0, None), + '[C]' : (0xB2, 0x83A1, None), + '[L]' : (0xB3, 0x83A2, None), + '[R]' : (0xB4, 0x83A3, None), + '[Z]' : (0xB5, 0x83A4, None), + '[C-Up]' : (0xB6, 0x83A5, None), + '[C-Down]' : (0xB7, 0x83A6, None), + '[C-Left]' : (0xB8, 0x83A7, None), + '[C-Right]' : (0xB9, 0x83A8, None), + '▼' : (0xBA, 0x83A9, None), + '[Control-Pad]' : (0xBB, 0x83AA, None), +} diff --git a/assets/text/message_data_static.c b/assets/text/message_data_static.c index 5d1878fb1dc..88adf78513f 100644 --- a/assets/text/message_data_static.c +++ b/assets/text/message_data_static.c @@ -2,8 +2,8 @@ #include "message_data_fmt_nes.h" -#define DEFINE_MESSAGE(textId, typePos, msg) \ - const char _message_##textId[sizeof(msg)] = { msg CMD_END }; +#define DEFINE_MESSAGE(textId, type, pos, msg) \ + const char _message_##textId[] = msg; #include "assets/text/message_data.enc.h" diff --git a/assets/text/staff_message_data_static.c b/assets/text/staff_message_data_static.c index 409febe28f4..de5dad9fd11 100644 --- a/assets/text/staff_message_data_static.c +++ b/assets/text/staff_message_data_static.c @@ -2,9 +2,9 @@ #include "message_data_fmt_staff.h" -#define DEFINE_MESSAGE(textId, typePos, msg) \ - const char _message_##textId##_staff[sizeof(msg)] = { msg CMD_END }; +#define DEFINE_MESSAGE(textId, type, pos, msg) \ + const char _message_##textId##_staff[] = msg; -#include "assets/text/staff_message_data.enc.h" +#include "assets/text/message_data_staff.enc.h" #undef DEFINE_MESSAGE diff --git a/include/message_data_fmt_nes.h b/include/message_data_fmt_nes.h index f2f58f96eeb..949cf94658b 100644 --- a/include/message_data_fmt_nes.h +++ b/include/message_data_fmt_nes.h @@ -1,339 +1,221 @@ #ifndef MESSAGE_DATA_FMT_NES_H #define MESSAGE_DATA_FMT_NES_H -/* - * Macros to create both a constant and a string literal from a magic value - * The constants are used in code files when parsing text for various purposes - * The strings are used in the message_data_static files themselves, as you can only concat strings with other strings - */ - -#ifndef GLUE -#define GLUE(a, b) a##b -#endif - -#define STRINGIFY(s) #s -#define EXPAND_AND_STRINGIFY(s) STRINGIFY(s) - -#define HEX(N) GLUE(0x, N) -#define STR(N) EXPAND_AND_STRINGIFY(GLUE(\x, N)) - +#include "sfx.h" // For sfx ids /* * Text control characters */ -// Control character magic values, in 2-digit hex without prefix -#define CTRL_COLOR_DEFAULT 00 -#define CTRL_COLOR_RED 01 -#define CTRL_COLOR_GREEN 02 -#define CTRL_COLOR_BLUE 03 -#define CTRL_COLOR_YELLOW 04 -#define CTRL_COLOR_LIGHTBLUE 05 -#define CTRL_COLOR_PINK 06 -#define CTRL_COLOR_SILVER 07 -#define CTRL_COLOR_ORANGE 08 -#define CTRL_TEXT_SPEED 0A // Note this should take an arg 0 to 6, but always just sets next decode char as 0 -#define CTRL_HS_BOAT_ARCHERY 0B -#define CTRL_STRAY_FAIRIES 0C -#define CTRL_TOKENS 0D -#define CTRL_POINTS_TENS 0E -#define CTRL_POINTS_THOUSANDS 0F -#define CTRL_BOX_BREAK 10 -#define CTRL_NEWLINE 11 -#define CTRL_BOX_BREAK2 12 -#define CTRL_CARRIAGE_RETURN 13 -#define CTRL_SHIFT 14 -#define CTRL_CONTINUE 15 -#define CTRL_NAME 16 -#define CTRL_QUICKTEXT_ENABLE 17 -#define CTRL_QUICKTEXT_DISABLE 18 -#define CTRL_EVENT 19 -#define CTRL_PERSISTENT 1A -#define CTRL_BOX_BREAK_DELAYED 1B -#define CTRL_FADE 1C -#define CTRL_FADE_SKIPPABLE 1D -#define CTRL_SFX 1E -#define CTRL_DELAY 1F -#define CTRL_BTN_A B0 -#define CTRL_BTN_B B1 -#define CTRL_BTN_C B2 -#define CTRL_BTN_L B3 -#define CTRL_BTN_R B4 -#define CTRL_BTN_Z B5 -#define CTRL_BTN_CUP B6 -#define CTRL_BTN_CDOWN B7 -#define CTRL_BTN_CLEFT B8 -#define CTRL_BTN_CRIGHT B9 -#define CTRL_Z_TARGET BA -#define CTRL_CONTROL_PAD BB -#define CTRL_END BF -#define CTRL_BACKGROUND C1 -#define CTRL_TWO_CHOICE C2 -#define CTRL_THREE_CHOICE C3 -#define CTRL_TIMER_POSTMAN C4 -#define CTRL_TIMER_MINIGAME_1 C5 -#define CTRL_TIMER_2 C6 -#define CTRL_TIMER_MOON_CRASH C7 -#define CTRL_TIMER_MINIGAME_2 C8 -#define CTRL_TIMER_ENV_HAZARD C9 -#define CTRL_TIME CA -#define CTRL_CHEST_FLAGS CB -#define CTRL_INPUT_BANK CC -#define CTRL_RUPEES_SELECTED CD -#define CTRL_RUPEES_TOTAL CE -#define CTRL_TIME_UNTIL_MOON_CRASH CF -#define CTRL_INPUT_DOGGY_RACETRACK_BET D0 -#define CTRL_INPUT_BOMBER_CODE D1 -#define CTRL_PAUSE_MENU D2 -#define CTRL_TIME_SPEED D3 -#define CTRL_OWL_WARP D4 -#define CTRL_INPUT_LOTTERY_CODE D5 -#define CTRL_SPIDER_HOUSE_MASK_CODE D6 -#define CTRL_STRAY_FAIRIES_LEFT_WOODFALL D7 -#define CTRL_STRAY_FAIRIES_LEFT_SNOWHEAD D8 -#define CTRL_STRAY_FAIRIES_LEFT_GREAT_BAY D9 -#define CTRL_STRAY_FAIRIES_LEFT_STONE_TOWER DA -#define CTRL_POINTS_BOAT_ARCHERY DB // Seems to be the exact same as CTRL_POINTS_THOUSANDS -#define CTRL_LOTTERY_CODE DC -#define CTRL_LOTTERY_CODE_GUESS DD -#define CTRL_HELD_ITEM_PRICE DE -#define CTRL_BOMBER_CODE DF -#define CTRL_EVENT2 E0 // Seems to be the exact same as CTRL_EVENT -#define CTRL_SPIDER_HOUSE_MASK_CODE_1 E1 -#define CTRL_SPIDER_HOUSE_MASK_CODE_2 E2 -#define CTRL_SPIDER_HOUSE_MASK_CODE_3 E3 -#define CTRL_SPIDER_HOUSE_MASK_CODE_4 E4 -#define CTRL_SPIDER_HOUSE_MASK_CODE_5 E5 -#define CTRL_SPIDER_HOUSE_MASK_CODE_6 E6 -#define CTRL_HOURS_UNTIL_MOON_CRASH E7 -#define CTRL_TIME_UNTIL_NEW_DAY E8 -#define CTRL_HS_POINTS_BANK_RUPEES F0 -#define CTRL_HS_POINTS_UNK_1 F1 -#define CTRL_HS_POINTS_FISHING F2 -#define CTRL_HS_TIME_BOAT_ARCHERY F3 // Note this interprets the highscore value as a time (not the actual timer for the minigame) -#define CTRL_HS_TIME_HORSE_BACK_BALLOON F4 // Note this interprets the highscore value as a time (not the actual timer for the minigame) -#define CTRL_HS_TIME_LOTTERY_GUESS F5 -#define CTRL_HS_TOWN_SHOOTING_GALLERY F6 -#define CTRL_HS_UNK_1 F7 -#define CTRL_HS_UNK_3_LOWER F8 -#define CTRL_HS_HORSE_BACK_BALLOON F9 -#define CTRL_HS_DEKU_PLAYGROUND_DAY_1 FA -#define CTRL_HS_DEKU_PLAYGROUND_DAY_2 FB -#define CTRL_HS_DEKU_PLAYGROUND_DAY_3 FC -#define CTRL_DEKU_PLAYGROUND_NAME_DAY_1 FD -#define CTRL_DEKU_PLAYGROUND_NAME_DAY_2 FE -#define CTRL_DEKU_PLAYGROUND_NAME_DAY_3 FF +#define MESSAGE_COLOR_DEFAULT 0x00 +#define MESSAGE_COLOR_RED 0x01 +#define MESSAGE_COLOR_GREEN 0x02 +#define MESSAGE_COLOR_BLUE 0x03 +#define MESSAGE_COLOR_YELLOW 0x04 +#define MESSAGE_COLOR_LIGHTBLUE 0x05 +#define MESSAGE_COLOR_PINK 0x06 +#define MESSAGE_COLOR_SILVER 0x07 +#define MESSAGE_COLOR_ORANGE 0x08 +#define MESSAGE_TEXT_SPEED 0x0A // Note this should take an arg 0 to 6, but always just sets next decode char as 0 +#define MESSAGE_HS_BOAT_ARCHERY 0x0B +#define MESSAGE_STRAY_FAIRIES 0x0C +#define MESSAGE_TOKENS 0x0D +#define MESSAGE_POINTS_TENS 0x0E +#define MESSAGE_POINTS_THOUSANDS 0x0F +#define MESSAGE_BOX_BREAK 0x10 +#define MESSAGE_NEWLINE 0x11 +#define MESSAGE_BOX_BREAK2 0x12 +#define MESSAGE_CARRIAGE_RETURN 0x13 +#define MESSAGE_SHIFT 0x14 +#define MESSAGE_CONTINUE 0x15 +#define MESSAGE_NAME 0x16 +#define MESSAGE_QUICKTEXT_ENABLE 0x17 +#define MESSAGE_QUICKTEXT_DISABLE 0x18 +#define MESSAGE_EVENT 0x19 +#define MESSAGE_PERSISTENT 0x1A +#define MESSAGE_BOX_BREAK_DELAYED 0x1B +#define MESSAGE_FADE 0x1C +#define MESSAGE_FADE_SKIPPABLE 0x1D +#define MESSAGE_SFX 0x1E +#define MESSAGE_DELAY 0x1F +#define MESSAGE_BTN_A 0xB0 +#define MESSAGE_BTN_B 0xB1 +#define MESSAGE_BTN_C 0xB2 +#define MESSAGE_BTN_L 0xB3 +#define MESSAGE_BTN_R 0xB4 +#define MESSAGE_BTN_Z 0xB5 +#define MESSAGE_BTN_CUP 0xB6 +#define MESSAGE_BTN_CDOWN 0xB7 +#define MESSAGE_BTN_CLEFT 0xB8 +#define MESSAGE_BTN_CRIGHT 0xB9 +#define MESSAGE_Z_TARGET 0xBA +#define MESSAGE_CONTROL_PAD 0xBB +#define MESSAGE_END 0xBF +#define MESSAGE_BACKGROUND 0xC1 +#define MESSAGE_TWO_CHOICE 0xC2 +#define MESSAGE_THREE_CHOICE 0xC3 +#define MESSAGE_TIMER_POSTMAN 0xC4 +#define MESSAGE_TIMER_MINIGAME_1 0xC5 +#define MESSAGE_TIMER_2 0xC6 +#define MESSAGE_TIMER_MOON_CRASH 0xC7 +#define MESSAGE_TIMER_MINIGAME_2 0xC8 +#define MESSAGE_TIMER_ENV_HAZARD 0xC9 +#define MESSAGE_TIME 0xCA +#define MESSAGE_CHEST_FLAGS 0xCB +#define MESSAGE_INPUT_BANK 0xCC +#define MESSAGE_RUPEES_SELECTED 0xCD +#define MESSAGE_RUPEES_TOTAL 0xCE +#define MESSAGE_TIME_UNTIL_MOON_CRASH 0xCF +#define MESSAGE_INPUT_DOGGY_RACETRACK_BET 0xD0 +#define MESSAGE_INPUT_BOMBER_CODE 0xD1 +#define MESSAGE_PAUSE_MENU 0xD2 +#define MESSAGE_TIME_SPEED 0xD3 +#define MESSAGE_OWL_WARP 0xD4 +#define MESSAGE_INPUT_LOTTERY_CODE 0xD5 +#define MESSAGE_SPIDER_HOUSE_MASK_CODE 0xD6 +#define MESSAGE_STRAY_FAIRIES_LEFT_WOODFALL 0xD7 +#define MESSAGE_STRAY_FAIRIES_LEFT_SNOWHEAD 0xD8 +#define MESSAGE_STRAY_FAIRIES_LEFT_GREAT_BAY 0xD9 +#define MESSAGE_STRAY_FAIRIES_LEFT_STONE_TOWER 0xDA +#define MESSAGE_POINTS_BOAT_ARCHERY 0xDB // Seems to be the exact same as CTRL_POINTS_THOUSANDS +#define MESSAGE_LOTTERY_CODE 0xDC +#define MESSAGE_LOTTERY_CODE_GUESS 0xDD +#define MESSAGE_HELD_ITEM_PRICE 0xDE +#define MESSAGE_BOMBER_CODE 0xDF +#define MESSAGE_EVENT2 0xE0 // Seems to be the exact same as CTRL_EVENT +#define MESSAGE_SPIDER_HOUSE_MASK_CODE_1 0xE1 +#define MESSAGE_SPIDER_HOUSE_MASK_CODE_2 0xE2 +#define MESSAGE_SPIDER_HOUSE_MASK_CODE_3 0xE3 +#define MESSAGE_SPIDER_HOUSE_MASK_CODE_4 0xE4 +#define MESSAGE_SPIDER_HOUSE_MASK_CODE_5 0xE5 +#define MESSAGE_SPIDER_HOUSE_MASK_CODE_6 0xE6 +#define MESSAGE_HOURS_UNTIL_MOON_CRASH 0xE7 +#define MESSAGE_TIME_UNTIL_NEW_DAY 0xE8 +#define MESSAGE_HS_POINTS_BANK_RUPEES 0xF0 +#define MESSAGE_HS_POINTS_UNK_1 0xF1 +#define MESSAGE_HS_POINTS_FISHING 0xF2 +#define MESSAGE_HS_TIME_BOAT_ARCHERY 0xF3 // Note this interprets the highscore value as a time (not the actual timer for the minigame) +#define MESSAGE_HS_TIME_HORSE_BACK_BALLOON 0xF4 // Note this interprets the highscore value as a time (not the actual timer for the minigame) +#define MESSAGE_HS_TIME_LOTTERY_GUESS 0xF5 +#define MESSAGE_HS_TOWN_SHOOTING_GALLERY 0xF6 +#define MESSAGE_HS_UNK_1 0xF7 +#define MESSAGE_HS_UNK_3_LOWER 0xF8 +#define MESSAGE_HS_HORSE_BACK_BALLOON 0xF9 +#define MESSAGE_HS_DEKU_PLAYGROUND_DAY_1 0xFA +#define MESSAGE_HS_DEKU_PLAYGROUND_DAY_2 0xFB +#define MESSAGE_HS_DEKU_PLAYGROUND_DAY_3 0xFC +#define MESSAGE_DEKU_PLAYGROUND_NAME_DAY_1 0xFD +#define MESSAGE_DEKU_PLAYGROUND_NAME_DAY_2 0xFE +#define MESSAGE_DEKU_PLAYGROUND_NAME_DAY_3 0xFF #ifdef MESSAGE_DATA_STATIC // For use in message_data_static files -#define ARG(x) x +#define ARG1(x) (x), +#define ARG2(x) (((x) >> 8) & 0xFF), (((x) >> 0) & 0xFF), +#define CTRL_BASE(name) ARG1(MESSAGE_##name) -#define CMD_COLOR_DEFAULT STR(CTRL_COLOR_DEFAULT) -#define CMD_COLOR_RED STR(CTRL_COLOR_RED) -#define CMD_COLOR_GREEN STR(CTRL_COLOR_GREEN) -#define CMD_COLOR_BLUE STR(CTRL_COLOR_BLUE) -#define CMD_COLOR_YELLOW STR(CTRL_COLOR_YELLOW) -#define CMD_COLOR_LIGHTBLUE STR(CTRL_COLOR_LIGHTBLUE) -#define CMD_COLOR_PINK STR(CTRL_COLOR_PINK) -#define CMD_COLOR_SILVER STR(CTRL_COLOR_SILVER) -#define CMD_COLOR_ORANGE STR(CTRL_COLOR_ORANGE) -#define CMD_TEXT_SPEED STR(CTRL_TEXT_SPEED) -#define CMD_HS_BOAT_ARCHERY STR(CTRL_HS_BOAT_ARCHERY) -#define CMD_STRAY_FAIRIES STR(CTRL_STRAY_FAIRIES) -#define CMD_TOKENS STR(CTRL_TOKENS) -#define CMD_POINTS_TENS STR(CTRL_POINTS_TENS) -#define CMD_POINTS_THOUSANDS STR(CTRL_POINTS_THOUSANDS) -#define CMD_BOX_BREAK STR(CTRL_BOX_BREAK) -// while a control character, newlines are handled in the charmap conversion -// stage to allow normal newline \n usage in message_data_static files -#define CMD_NEWLINE STR(CTRL_NEWLINE) -#define CMD_BOX_BREAK2 STR(CTRL_BOX_BREAK2) -#define CMD_CARRIAGE_RETURN STR(CTRL_CARRIAGE_RETURN) -#define CMD_SHIFT(x) STR(CTRL_SHIFT) ARG(x) // 1 -#define CMD_CONTINUE STR(CTRL_CONTINUE) -#define CMD_NAME STR(CTRL_NAME) -#define CMD_QUICKTEXT_ENABLE STR(CTRL_QUICKTEXT_ENABLE) -#define CMD_QUICKTEXT_DISABLE STR(CTRL_QUICKTEXT_DISABLE) -#define CMD_EVENT STR(CTRL_EVENT) -#define CMD_PERSISTENT STR(CTRL_PERSISTENT) -#define CMD_BOX_BREAK_DELAYED(x) STR(CTRL_BOX_BREAK_DELAYED) ARG(x) // 2 -#define CMD_FADE(x) STR(CTRL_FADE) ARG(x) // 2 -#define CMD_FADE_SKIPPABLE(x) STR(CTRL_FADE_SKIPPABLE) ARG(x) // 2 -#define CMD_SFX(x) STR(CTRL_SFX) ARG(x) // 2 -#define CMD_DELAY(x) STR(CTRL_DELAY) ARG(x) // 2 -// while control characters, button images are handled in the charmap conversion -#define CMD_BTN_A STR(CTRL_BTN_A) // "[A]" -#define CMD_BTN_B STR(CTRL_BTN_B) // "[B]" -#define CMD_BTN_C STR(CTRL_BTN_C) // "[C]" -#define CMD_BTN_L STR(CTRL_BTN_L) // "[L]" -#define CMD_BTN_R STR(CTRL_BTN_R) // "[R]" -#define CMD_BTN_Z STR(CTRL_BTN_Z) // "[Z]" -#define CMD_BTN_CUP STR(CTRL_BTN_CUP) // "[C-Up]" -#define CMD_BTN_CDOWN STR(CTRL_BTN_CDOWN) // "[C-Down]" -#define CMD_BTN_CLEFT STR(CTRL_BTN_CLEFT) // "[C-Left]" -#define CMD_BTN_CRIGHT STR(CTRL_BTN_CRIGHT) // "[C-Right]" -#define CMD_Z_TARGET STR(CTRL_Z_TARGET) // "▼" -#define CMD_CONTROL_PAD STR(CTRL_CONTROL_PAD) // "[Control-Pad]" -#define CMD_END STR(CTRL_END) -#define CMD_BACKGROUND STR(CTRL_BACKGROUND) -#define CMD_TWO_CHOICE STR(CTRL_TWO_CHOICE) -#define CMD_THREE_CHOICE STR(CTRL_THREE_CHOICE) -#define CMD_TIMER_POSTMAN STR(CTRL_TIMER_POSTMAN) -#define CMD_TIMER_MINIGAME_1 STR(CTRL_TIMER_MINIGAME_1) -#define CMD_TIMER_2 STR(CTRL_TIMER_2) -#define CMD_TIMER_MOON_CRASH STR(CTRL_TIMER_MOON_CRASH) -#define CMD_TIMER_MINIGAME_2 STR(CTRL_TIMER_MINIGAME_2) -#define CMD_TIMER_ENV_HAZARD STR(CTRL_TIMER_ENV_HAZARD) -#define CMD_TIME STR(CTRL_TIME) -#define CMD_CHEST_FLAGS STR(CTRL_CHEST_FLAGS) -#define CMD_INPUT_BANK STR(CTRL_INPUT_BANK) -#define CMD_RUPEES_SELECTED STR(CTRL_RUPEES_SELECTED) -#define CMD_RUPEES_TOTAL STR(CTRL_RUPEES_TOTAL) -#define CMD_TIME_UNTIL_MOON_CRASH STR(CTRL_TIME_UNTIL_MOON_CRASH) -#define CMD_INPUT_DOGGY_RACETRACK_BET STR(CTRL_INPUT_DOGGY_RACETRACK_BET) -#define CMD_INPUT_BOMBER_CODE STR(CTRL_INPUT_BOMBER_CODE) -#define CMD_PAUSE_MENU STR(CTRL_PAUSE_MENU) -#define CMD_TIME_SPEED STR(CTRL_TIME_SPEED) -#define CMD_OWL_WARP STR(CTRL_OWL_WARP) -#define CMD_INPUT_LOTTERY_CODE STR(CTRL_INPUT_LOTTERY_CODE) -#define CMD_SPIDER_HOUSE_MASK_CODE STR(CTRL_SPIDER_HOUSE_MASK_CODE) -#define CMD_STRAY_FAIRIES_LEFT_WOODFALL STR(CTRL_STRAY_FAIRIES_LEFT_WOODFALL) -#define CMD_STRAY_FAIRIES_LEFT_SNOWHEAD STR(CTRL_STRAY_FAIRIES_LEFT_SNOWHEAD) -#define CMD_STRAY_FAIRIES_LEFT_GREAT_BAY STR(CTRL_STRAY_FAIRIES_LEFT_GREAT_BAY) -#define CMD_STRAY_FAIRIES_LEFT_STONE_TOWER STR(CTRL_STRAY_FAIRIES_LEFT_STONE_TOWER) -#define CMD_POINTS_BOAT_ARCHERY STR(CTRL_POINTS_BOAT_ARCHERY) -#define CMD_LOTTERY_CODE STR(CTRL_LOTTERY_CODE) -#define CMD_LOTTERY_CODE_GUESS STR(CTRL_LOTTERY_CODE_GUESS) -#define CMD_HELD_ITEM_PRICE STR(CTRL_HELD_ITEM_PRICE) -#define CMD_BOMBER_CODE STR(CTRL_BOMBER_CODE) -#define CMD_EVENT2 STR(CTRL_EVENT2) -#define CMD_SPIDER_HOUSE_MASK_CODE_1 STR(CTRL_SPIDER_HOUSE_MASK_CODE_1) -#define CMD_SPIDER_HOUSE_MASK_CODE_2 STR(CTRL_SPIDER_HOUSE_MASK_CODE_2) -#define CMD_SPIDER_HOUSE_MASK_CODE_3 STR(CTRL_SPIDER_HOUSE_MASK_CODE_3) -#define CMD_SPIDER_HOUSE_MASK_CODE_4 STR(CTRL_SPIDER_HOUSE_MASK_CODE_4) -#define CMD_SPIDER_HOUSE_MASK_CODE_5 STR(CTRL_SPIDER_HOUSE_MASK_CODE_5) -#define CMD_SPIDER_HOUSE_MASK_CODE_6 STR(CTRL_SPIDER_HOUSE_MASK_CODE_6) -#define CMD_HOURS_UNTIL_MOON_CRASH STR(CTRL_HOURS_UNTIL_MOON_CRASH) -#define CMD_TIME_UNTIL_NEW_DAY STR(CTRL_TIME_UNTIL_NEW_DAY) -#define CMD_HS_POINTS_BANK_RUPEES STR(CTRL_HS_POINTS_BANK_RUPEES) -#define CMD_HS_POINTS_UNK_1 STR(CTRL_HS_POINTS_UNK_1) -#define CMD_HS_POINTS_FISHING STR(CTRL_HS_POINTS_FISHING) -#define CMD_HS_TIME_BOAT_ARCHERY STR(CTRL_HS_TIME_BOAT_ARCHERY) -#define CMD_HS_TIME_HORSE_BACK_BALLOON STR(CTRL_HS_TIME_HORSE_BACK_BALLOON) -#define CMD_HS_TIME_LOTTERY_GUESS STR(CTRL_HS_TIME_LOTTERY_GUESS) -#define CMD_HS_TOWN_SHOOTING_GALLERY STR(CTRL_HS_TOWN_SHOOTING_GALLERY) -#define CMD_HS_UNK_1 STR(CTRL_HS_UNK_1) -#define CMD_HS_UNK_3_LOWER STR(CTRL_HS_UNK_3_LOWER) -#define CMD_HS_HORSE_BACK_BALLOON STR(CTRL_HS_HORSE_BACK_BALLOON) -#define CMD_HS_DEKU_PLAYGROUND_DAY_1 STR(CTRL_HS_DEKU_PLAYGROUND_DAY_1) -#define CMD_HS_DEKU_PLAYGROUND_DAY_2 STR(CTRL_HS_DEKU_PLAYGROUND_DAY_2) -#define CMD_HS_DEKU_PLAYGROUND_DAY_3 STR(CTRL_HS_DEKU_PLAYGROUND_DAY_3) -#define CMD_DEKU_PLAYGROUND_NAME_DAY_1 STR(CTRL_DEKU_PLAYGROUND_NAME_DAY_1) -#define CMD_DEKU_PLAYGROUND_NAME_DAY_2 STR(CTRL_DEKU_PLAYGROUND_NAME_DAY_2) -#define CMD_DEKU_PLAYGROUND_NAME_DAY_3 STR(CTRL_DEKU_PLAYGROUND_NAME_DAY_3) +// For use in message_data_static files -#else +// Encoded text consists of an array of bytes. Since it's in a macro it must be wrapped in a varargs macro so that each +// byte is not treated as a separate macro argument to DEFINE_MESSAGE. IDO doesn't support varargs macros, however we +// preprocess the message_data_static files with modern cpp instead. See the makefile rule for assets/text/ +#define MSG(...) \ + { __VA_ARGS__ END } -#define MESSAGE_COLOR_DEFAULT HEX(CTRL_COLOR_DEFAULT) -#define MESSAGE_COLOR_RED HEX(CTRL_COLOR_RED) -#define MESSAGE_COLOR_GREEN HEX(CTRL_COLOR_GREEN) -#define MESSAGE_COLOR_BLUE HEX(CTRL_COLOR_BLUE) -#define MESSAGE_COLOR_YELLOW HEX(CTRL_COLOR_YELLOW) -#define MESSAGE_COLOR_LIGHTBLUE HEX(CTRL_COLOR_LIGHTBLUE) -#define MESSAGE_COLOR_PINK HEX(CTRL_COLOR_PINK) -#define MESSAGE_COLOR_SILVER HEX(CTRL_COLOR_SILVER) -#define MESSAGE_COLOR_ORANGE HEX(CTRL_COLOR_ORANGE) -#define MESSAGE_TEXT_SPEED HEX(CTRL_TEXT_SPEED) -#define MESSAGE_HS_BOAT_ARCHERY HEX(CTRL_HS_BOAT_ARCHERY) -#define MESSAGE_STRAY_FAIRIES HEX(CTRL_STRAY_FAIRIES) -#define MESSAGE_TOKENS HEX(CTRL_TOKENS) -#define MESSAGE_POINTS_TENS HEX(CTRL_POINTS_TENS) -#define MESSAGE_POINTS_THOUSANDS HEX(CTRL_POINTS_THOUSANDS) -#define MESSAGE_BOX_BREAK HEX(CTRL_BOX_BREAK) -#define MESSAGE_NEWLINE HEX(CTRL_NEWLINE) -#define MESSAGE_BOX_BREAK2 HEX(CTRL_BOX_BREAK2) -#define MESSAGE_CARRIAGE_RETURN HEX(CTRL_CARRIAGE_RETURN) -#define MESSAGE_SHIFT HEX(CTRL_SHIFT) -#define MESSAGE_CONTINUE HEX(CTRL_CONTINUE) -#define MESSAGE_NAME HEX(CTRL_NAME) -#define MESSAGE_QUICKTEXT_ENABLE HEX(CTRL_QUICKTEXT_ENABLE) -#define MESSAGE_QUICKTEXT_DISABLE HEX(CTRL_QUICKTEXT_DISABLE) -#define MESSAGE_EVENT HEX(CTRL_EVENT) -#define MESSAGE_PERSISTENT HEX(CTRL_PERSISTENT) -#define MESSAGE_BOX_BREAK_DELAYED HEX(CTRL_BOX_BREAK_DELAYED) -#define MESSAGE_FADE HEX(CTRL_FADE) -#define MESSAGE_FADE_SKIPPABLE HEX(CTRL_FADE_SKIPPABLE) -#define MESSAGE_SFX HEX(CTRL_SFX) -#define MESSAGE_DELAY HEX(CTRL_DELAY) -#define MESSAGE_BTN_A HEX(CTRL_BTN_A) -#define MESSAGE_BTN_B HEX(CTRL_BTN_B) -#define MESSAGE_BTN_C HEX(CTRL_BTN_C) -#define MESSAGE_BTN_L HEX(CTRL_BTN_L) -#define MESSAGE_BTN_R HEX(CTRL_BTN_R) -#define MESSAGE_BTN_Z HEX(CTRL_BTN_Z) -#define MESSAGE_BTN_CUP HEX(CTRL_BTN_CUP) -#define MESSAGE_BTN_CDOWN HEX(CTRL_BTN_CDOWN) -#define MESSAGE_BTN_CLEFT HEX(CTRL_BTN_CLEFT) -#define MESSAGE_BTN_CRIGHT HEX(CTRL_BTN_CRIGHT) -#define MESSAGE_Z_TARGET HEX(CTRL_Z_TARGET) -#define MESSAGE_CONTROL_PAD HEX(CTRL_CONTROL_PAD) -#define MESSAGE_END HEX(CTRL_END) -#define MESSAGE_BACKGROUND HEX(CTRL_BACKGROUND) -#define MESSAGE_TWO_CHOICE HEX(CTRL_TWO_CHOICE) -#define MESSAGE_THREE_CHOICE HEX(CTRL_THREE_CHOICE) -#define MESSAGE_TIMER_POSTMAN HEX(CTRL_TIMER_POSTMAN) -#define MESSAGE_TIMER_MINIGAME_1 HEX(CTRL_TIMER_MINIGAME_1) -#define MESSAGE_TIMER_2 HEX(CTRL_TIMER_2) -#define MESSAGE_TIMER_MOON_CRASH HEX(CTRL_TIMER_MOON_CRASH) -#define MESSAGE_TIMER_MINIGAME_2 HEX(CTRL_TIMER_MINIGAME_2) -#define MESSAGE_TIMER_ENV_HAZARD HEX(CTRL_TIMER_ENV_HAZARD) -#define MESSAGE_TIME HEX(CTRL_TIME) -#define MESSAGE_CHEST_FLAGS HEX(CTRL_CHEST_FLAGS) -#define MESSAGE_INPUT_BANK HEX(CTRL_INPUT_BANK) -#define MESSAGE_RUPEES_SELECTED HEX(CTRL_RUPEES_SELECTED) -#define MESSAGE_RUPEES_TOTAL HEX(CTRL_RUPEES_TOTAL) -#define MESSAGE_TIME_UNTIL_MOON_CRASH HEX(CTRL_TIME_UNTIL_MOON_CRASH) -#define MESSAGE_INPUT_DOGGY_RACETRACK_BET HEX(CTRL_INPUT_DOGGY_RACETRACK_BET) -#define MESSAGE_INPUT_BOMBER_CODE HEX(CTRL_INPUT_BOMBER_CODE) -#define MESSAGE_PAUSE_MENU HEX(CTRL_PAUSE_MENU) -#define MESSAGE_TIME_SPEED HEX(CTRL_TIME_SPEED) -#define MESSAGE_OWL_WARP HEX(CTRL_OWL_WARP) -#define MESSAGE_INPUT_LOTTERY_CODE HEX(CTRL_INPUT_LOTTERY_CODE) -#define MESSAGE_SPIDER_HOUSE_MASK_CODE HEX(CTRL_SPIDER_HOUSE_MASK_CODE) -#define MESSAGE_STRAY_FAIRIES_LEFT_WOODFALL HEX(CTRL_STRAY_FAIRIES_LEFT_WOODFALL) -#define MESSAGE_STRAY_FAIRIES_LEFT_SNOWHEAD HEX(CTRL_STRAY_FAIRIES_LEFT_SNOWHEAD) -#define MESSAGE_STRAY_FAIRIES_LEFT_GREAT_BAY HEX(CTRL_STRAY_FAIRIES_LEFT_GREAT_BAY) -#define MESSAGE_STRAY_FAIRIES_LEFT_STONE_TOWER HEX(CTRL_STRAY_FAIRIES_LEFT_STONE_TOWER) -#define MESSAGE_POINTS_BOAT_ARCHERY HEX(CTRL_POINTS_BOAT_ARCHERY) -#define MESSAGE_LOTTERY_CODE HEX(CTRL_LOTTERY_CODE) -#define MESSAGE_LOTTERY_CODE_GUESS HEX(CTRL_LOTTERY_CODE_GUESS) -#define MESSAGE_HELD_ITEM_PRICE HEX(CTRL_HELD_ITEM_PRICE) -#define MESSAGE_BOMBER_CODE HEX(CTRL_BOMBER_CODE) -#define MESSAGE_EVENT2 HEX(CTRL_EVENT2) -#define MESSAGE_SPIDER_HOUSE_MASK_CODE_1 HEX(CTRL_SPIDER_HOUSE_MASK_CODE_1) -#define MESSAGE_SPIDER_HOUSE_MASK_CODE_2 HEX(CTRL_SPIDER_HOUSE_MASK_CODE_2) -#define MESSAGE_SPIDER_HOUSE_MASK_CODE_3 HEX(CTRL_SPIDER_HOUSE_MASK_CODE_3) -#define MESSAGE_SPIDER_HOUSE_MASK_CODE_4 HEX(CTRL_SPIDER_HOUSE_MASK_CODE_4) -#define MESSAGE_SPIDER_HOUSE_MASK_CODE_5 HEX(CTRL_SPIDER_HOUSE_MASK_CODE_5) -#define MESSAGE_SPIDER_HOUSE_MASK_CODE_6 HEX(CTRL_SPIDER_HOUSE_MASK_CODE_6) -#define MESSAGE_HOURS_UNTIL_MOON_CRASH HEX(CTRL_HOURS_UNTIL_MOON_CRASH) -#define MESSAGE_TIME_UNTIL_NEW_DAY HEX(CTRL_TIME_UNTIL_NEW_DAY) -#define MESSAGE_HS_POINTS_BANK_RUPEES HEX(CTRL_HS_POINTS_BANK_RUPEES) -#define MESSAGE_HS_POINTS_UNK_1 HEX(CTRL_HS_POINTS_UNK_1) -#define MESSAGE_HS_POINTS_FISHING HEX(CTRL_HS_POINTS_FISHING) -#define MESSAGE_HS_TIME_BOAT_ARCHERY HEX(CTRL_HS_TIME_BOAT_ARCHERY) -#define MESSAGE_HS_TIME_HORSE_BACK_BALLOON HEX(CTRL_HS_TIME_HORSE_BACK_BALLOON) -#define MESSAGE_HS_TIME_LOTTERY_GUESS HEX(CTRL_HS_TIME_LOTTERY_GUESS) -#define MESSAGE_HS_TOWN_SHOOTING_GALLERY HEX(CTRL_HS_TOWN_SHOOTING_GALLERY) -#define MESSAGE_HS_UNK_1 HEX(CTRL_HS_UNK_1) -#define MESSAGE_HS_UNK_3_LOWER HEX(CTRL_HS_UNK_3_LOWER) -#define MESSAGE_HS_HORSE_BACK_BALLOON HEX(CTRL_HS_HORSE_BACK_BALLOON) -#define MESSAGE_HS_DEKU_PLAYGROUND_DAY_1 HEX(CTRL_HS_DEKU_PLAYGROUND_DAY_1) -#define MESSAGE_HS_DEKU_PLAYGROUND_DAY_2 HEX(CTRL_HS_DEKU_PLAYGROUND_DAY_2) -#define MESSAGE_HS_DEKU_PLAYGROUND_DAY_3 HEX(CTRL_HS_DEKU_PLAYGROUND_DAY_3) -#define MESSAGE_DEKU_PLAYGROUND_NAME_DAY_1 HEX(CTRL_DEKU_PLAYGROUND_NAME_DAY_1) -#define MESSAGE_DEKU_PLAYGROUND_NAME_DAY_2 HEX(CTRL_DEKU_PLAYGROUND_NAME_DAY_2) -#define MESSAGE_DEKU_PLAYGROUND_NAME_DAY_3 HEX(CTRL_DEKU_PLAYGROUND_NAME_DAY_3) +// Not a control command, used to define the data that begins every message +#define HEADER(unk11F08, itemId, nextTextId, unk1206C, unk12070, unk12074) \ + ARG2(unk11F08) ARG1(itemId) ARG2(nextTextId) ARG2(unk1206C) ARG2(unk12070) ARG2(unk12074) + +#define COLOR_DEFAULT CTRL_BASE(COLOR_DEFAULT) +#define COLOR_RED CTRL_BASE(COLOR_RED) +#define COLOR_GREEN CTRL_BASE(COLOR_GREEN) +#define COLOR_BLUE CTRL_BASE(COLOR_BLUE) +#define COLOR_YELLOW CTRL_BASE(COLOR_YELLOW) +#define COLOR_LIGHTBLUE CTRL_BASE(COLOR_LIGHTBLUE) +#define COLOR_PINK CTRL_BASE(COLOR_PINK) +#define COLOR_SILVER CTRL_BASE(COLOR_SILVER) +#define COLOR_ORANGE CTRL_BASE(COLOR_ORANGE) +#define TEXT_SPEED CTRL_BASE(TEXT_SPEED) +#define HS_BOAT_ARCHERY CTRL_BASE(HS_BOAT_ARCHERY) +#define STRAY_FAIRIES CTRL_BASE(STRAY_FAIRIES) +#define TOKENS CTRL_BASE(TOKENS) +#define POINTS_TENS CTRL_BASE(POINTS_TENS) +#define POINTS_THOUSANDS CTRL_BASE(POINTS_THOUSANDS) +#define BOX_BREAK CTRL_BASE(BOX_BREAK) +// while a control character, newlines are handled in the charmap conversion +// stage to allow normal newline \n usage in message_data_static files +#define NEWLINE CTRL_BASE(NEWLINE) +#define BOX_BREAK2 CTRL_BASE(BOX_BREAK2) +#define CARRIAGE_RETURN CTRL_BASE(CARRIAGE_RETURN) +#define SHIFT(amount) CTRL_BASE(SHIFT) ARG1(amount) +#define CONTINUE CTRL_BASE(CONTINUE) +#define NAME CTRL_BASE(NAME) +#define QUICKTEXT_ENABLE CTRL_BASE(QUICKTEXT_ENABLE) +#define QUICKTEXT_DISABLE CTRL_BASE(QUICKTEXT_DISABLE) +#define EVENT CTRL_BASE(EVENT) +#define PERSISTENT CTRL_BASE(PERSISTENT) +#define BOX_BREAK_DELAYED(delay) CTRL_BASE(BOX_BREAK_DELAYED) ARG2(delay) +#define FADE(delay) CTRL_BASE(FADE) ARG2(delay) +#define FADE_SKIPPABLE(delay) CTRL_BASE(FADE_SKIPPABLE) ARG2(delay) +#define SFX(sfxId) CTRL_BASE(SFX) ARG2(sfxId) +#define DELAY(delay) CTRL_BASE(DELAY) ARG2(delay) +#define END CTRL_BASE(END) +#define BACKGROUND CTRL_BASE(BACKGROUND) +#define TWO_CHOICE CTRL_BASE(TWO_CHOICE) +#define THREE_CHOICE CTRL_BASE(THREE_CHOICE) +#define TIMER_POSTMAN CTRL_BASE(TIMER_POSTMAN) +#define TIMER_MINIGAME_1 CTRL_BASE(TIMER_MINIGAME_1) +#define TIMER_2 CTRL_BASE(TIMER_2) +#define TIMER_MOON_CRASH CTRL_BASE(TIMER_MOON_CRASH) +#define TIMER_MINIGAME_2 CTRL_BASE(TIMER_MINIGAME_2) +#define TIMER_ENV_HAZARD CTRL_BASE(TIMER_ENV_HAZARD) +#define TIME CTRL_BASE(TIME) +#define CHEST_FLAGS CTRL_BASE(CHEST_FLAGS) +#define INPUT_BANK CTRL_BASE(INPUT_BANK) +#define RUPEES_SELECTED CTRL_BASE(RUPEES_SELECTED) +#define RUPEES_TOTAL CTRL_BASE(RUPEES_TOTAL) +#define TIME_UNTIL_MOON_CRASH CTRL_BASE(TIME_UNTIL_MOON_CRASH) +#define INPUT_DOGGY_RACETRACK_BET CTRL_BASE(INPUT_DOGGY_RACETRACK_BET) +#define INPUT_BOMBER_CODE CTRL_BASE(INPUT_BOMBER_CODE) +#define PAUSE_MENU CTRL_BASE(PAUSE_MENU) +#define TIME_SPEED CTRL_BASE(TIME_SPEED) +#define OWL_WARP CTRL_BASE(OWL_WARP) +#define INPUT_LOTTERY_CODE CTRL_BASE(INPUT_LOTTERY_CODE) +#define SPIDER_HOUSE_MASK_CODE CTRL_BASE(SPIDER_HOUSE_MASK_CODE) +#define STRAY_FAIRIES_LEFT_WOODFALL CTRL_BASE(STRAY_FAIRIES_LEFT_WOODFALL) +#define STRAY_FAIRIES_LEFT_SNOWHEAD CTRL_BASE(STRAY_FAIRIES_LEFT_SNOWHEAD) +#define STRAY_FAIRIES_LEFT_GREAT_BAY CTRL_BASE(STRAY_FAIRIES_LEFT_GREAT_BAY) +#define STRAY_FAIRIES_LEFT_STONE_TOWER CTRL_BASE(STRAY_FAIRIES_LEFT_STONE_TOWER) +#define POINTS_BOAT_ARCHERY CTRL_BASE(POINTS_BOAT_ARCHERY) +#define LOTTERY_CODE CTRL_BASE(LOTTERY_CODE) +#define LOTTERY_CODE_GUESS CTRL_BASE(LOTTERY_CODE_GUESS) +#define HELD_ITEM_PRICE CTRL_BASE(HELD_ITEM_PRICE) +#define BOMBER_CODE CTRL_BASE(BOMBER_CODE) +#define EVENT2 CTRL_BASE(EVENT2) +#define SPIDER_HOUSE_MASK_CODE_1 CTRL_BASE(SPIDER_HOUSE_MASK_CODE_1) +#define SPIDER_HOUSE_MASK_CODE_2 CTRL_BASE(SPIDER_HOUSE_MASK_CODE_2) +#define SPIDER_HOUSE_MASK_CODE_3 CTRL_BASE(SPIDER_HOUSE_MASK_CODE_3) +#define SPIDER_HOUSE_MASK_CODE_4 CTRL_BASE(SPIDER_HOUSE_MASK_CODE_4) +#define SPIDER_HOUSE_MASK_CODE_5 CTRL_BASE(SPIDER_HOUSE_MASK_CODE_5) +#define SPIDER_HOUSE_MASK_CODE_6 CTRL_BASE(SPIDER_HOUSE_MASK_CODE_6) +#define HOURS_UNTIL_MOON_CRASH CTRL_BASE(HOURS_UNTIL_MOON_CRASH) +#define TIME_UNTIL_NEW_DAY CTRL_BASE(TIME_UNTIL_NEW_DAY) +#define HS_POINTS_BANK_RUPEES CTRL_BASE(HS_POINTS_BANK_RUPEES) +#define HS_POINTS_UNK_1 CTRL_BASE(HS_POINTS_UNK_1) +#define HS_POINTS_FISHING CTRL_BASE(HS_POINTS_FISHING) +#define HS_TIME_BOAT_ARCHERY CTRL_BASE(HS_TIME_BOAT_ARCHERY) +#define HS_TIME_HORSE_BACK_BALLOON CTRL_BASE(HS_TIME_HORSE_BACK_BALLOON) +#define HS_TIME_LOTTERY_GUESS CTRL_BASE(HS_TIME_LOTTERY_GUESS) +#define HS_TOWN_SHOOTING_GALLERY CTRL_BASE(HS_TOWN_SHOOTING_GALLERY) +#define HS_UNK_1 CTRL_BASE(HS_UNK_1) +#define HS_UNK_3_LOWER CTRL_BASE(HS_UNK_3_LOWER) +#define HS_HORSE_BACK_BALLOON CTRL_BASE(HS_HORSE_BACK_BALLOON) +#define HS_DEKU_PLAYGROUND_DAY_1 CTRL_BASE(HS_DEKU_PLAYGROUND_DAY_1) +#define HS_DEKU_PLAYGROUND_DAY_2 CTRL_BASE(HS_DEKU_PLAYGROUND_DAY_2) +#define HS_DEKU_PLAYGROUND_DAY_3 CTRL_BASE(HS_DEKU_PLAYGROUND_DAY_3) +#define DEKU_PLAYGROUND_NAME_DAY_1 CTRL_BASE(DEKU_PLAYGROUND_NAME_DAY_1) +#define DEKU_PLAYGROUND_NAME_DAY_2 CTRL_BASE(DEKU_PLAYGROUND_NAME_DAY_2) +#define DEKU_PLAYGROUND_NAME_DAY_3 CTRL_BASE(DEKU_PLAYGROUND_NAME_DAY_3) #endif diff --git a/include/message_data_fmt_staff.h b/include/message_data_fmt_staff.h index 011e2733406..d461e85d7a3 100644 --- a/include/message_data_fmt_staff.h +++ b/include/message_data_fmt_staff.h @@ -1,180 +1,102 @@ #ifndef MESSAGE_DATA_FMT_STAFF_H #define MESSAGE_DATA_FMT_STAFF_H - -/* - * Macros to create both a constant and a string literal from a magic value - * The constants are used in code files when parsing text for various purposes - * The strings are used in the message_data_static files themselves, as you can only concat strings with other strings - */ - -#ifndef GLUE -#define GLUE(a, b) a##b -#endif - -#define STRINGIFY(s) #s -#define EXPAND_AND_STRINGIFY(s) STRINGIFY(s) - -#define HEX(N) GLUE(0x, N) -#define STR(N) EXPAND_AND_STRINGIFY(GLUE(\x, N)) - /* * Text control characters */ -// Control character magic values, in 2-digit hex without prefix - -#define CTRL_NEWLINE 01 -#define CTRL_END 02 -#define CTRL_BOX_BREAK 04 -#define CTRL_COLOR 05 -#define CTRL_SHIFT 06 -#define CTRL_TEXTID 07 -#define CTRL_QUICKTEXT_ENABLE 08 -#define CTRL_QUICKTEXT_DISABLE 09 -#define CTRL_PERSISTENT 0A -#define CTRL_EVENT 0B -#define CTRL_BOX_BREAK_DELAYED 0C -#define CTRL_AWAIT_BUTTON_PRESS 0D -#define CTRL_FADE 0E -#define CTRL_NAME 0F -#define CTRL_OCARINA 10 -#define CTRL_FADE2 11 -#define CTRL_SFX 12 -#define CTRL_ITEM_ICON 13 -#define CTRL_TEXT_SPEED 14 -#define CTRL_BACKGROUND 15 -#define CTRL_MARATHON_TIME 16 -#define CTRL_RACE_TIME 17 -#define CTRL_POINTS 18 -#define CTRL_TOKENS 19 -#define CTRL_UNSKIPPABLE 1A -#define CTRL_TWO_CHOICE 1B -#define CTRL_THREE_CHOICE 1C -#define CTRL_FISH_INFO 1D -#define CTRL_HIGHSCORE 1E -#define CTRL_TIME 1F - -/* - * Colors - */ - -#define COLOR_STR(N) EXPAND_AND_STRINGIFY(GLUE(\x4, N)) - -// Color magic values, in single-digit hex without prefix - -#define CTRL_DEFAULT 0 -#define CTRL_RED 1 -#define CTRL_ADJUSTABLE 2 -#define CTRL_BLUE 3 -#define CTRL_LIGHTBLUE 4 -#define CTRL_PURPLE 5 -#define CTRL_YELLOW 6 -#define CTRL_BLACK 7 +#define MESSAGE_NEWLINE 0x01 +#define MESSAGE_END 0x02 +#define MESSAGE_BOX_BREAK 0x04 +#define MESSAGE_COLOR 0x05 +#define MESSAGE_SHIFT 0x06 +#define MESSAGE_TEXTID 0x07 +#define MESSAGE_QUICKTEXT_ENABLE 0x08 +#define MESSAGE_QUICKTEXT_DISABLE 0x09 +#define MESSAGE_PERSISTENT 0x0A +#define MESSAGE_EVENT 0x0B +#define MESSAGE_BOX_BREAK_DELAYED 0x0C +#define MESSAGE_AWAIT_BUTTON_PRESS 0x0D +#define MESSAGE_FADE 0x0E +#define MESSAGE_NAME 0x0F +#define MESSAGE_OCARINA 0x10 +#define MESSAGE_FADE2 0x11 +#define MESSAGE_SFX 0x12 +#define MESSAGE_ITEM_ICON 0x13 +#define MESSAGE_TEXT_SPEED 0x14 +#define MESSAGE_BACKGROUND 0x15 +#define MESSAGE_MARATHON_TIME 0x16 +#define MESSAGE_RACE_TIME 0x17 +#define MESSAGE_POINTS 0x18 +#define MESSAGE_TOKENS 0x19 +#define MESSAGE_UNSKIPPABLE 0x1A +#define MESSAGE_TWO_CHOICE 0x1B +#define MESSAGE_THREE_CHOICE 0x1C +#define MESSAGE_FISH_INFO 0x1D +#define MESSAGE_HIGHSCORE 0x1E +#define MESSAGE_TIME 0x1F + +typedef enum TextColor { + /* 0 */ TEXT_COLOR_DEFAULT, + /* 1 */ TEXT_COLOR_RED, + /* 2 */ TEXT_COLOR_ADJUSTABLE, + /* 3 */ TEXT_COLOR_BLUE, + /* 4 */ TEXT_COLOR_LIGHTBLUE, + /* 5 */ TEXT_COLOR_PURPLE, + /* 6 */ TEXT_COLOR_YELLOW, + /* 7 */ TEXT_COLOR_BLACK +} TextColor; #ifdef MESSAGE_DATA_STATIC // For use in message_data_static files -#define ARG(x) x +// Encoded text consists of an array of bytes. Since it's in a macro it must be wrapped in a varargs macro so that each +// byte is not treated as a separate macro argument to DEFINE_MESSAGE. IDO doesn't support varargs macros, however we +// preprocess the message_data_static files with modern cpp instead. See the makefile rule for assets/text/ +#define MSG(...) \ + { __VA_ARGS__ END } + +#define ARG1(x) (x), +#define ARG2(x) (((x) >> 8) & 0xFF), (((x) >> 0) & 0xFF), +#define ARGC(x) (0x40 | (TEXT_COLOR_##x)), +#define CTRL_BASE(name) ARG1(MESSAGE_##name) +#define ARGB1(x) ARG1(TEXTBOX_BG_##x) +#define ARGB2(a, b, c, d) \ + (((TEXTBOX_BG_FGCOL_##a) << 4) | ((TEXTBOX_BG_BGCOL_##b) << 0)), (((TEXTBOX_BG_Y_OFFSET_##c) << 4) | ((d) << 0)), // while a control character, newlines are handled in the charmap conversion // stage to allow normal newline \n usage in message_data_static files -#define CMD_NEWLINE STR(CTRL_NEWLINE) -#define CMD_END STR(CTRL_END) -#define CMD_BOX_BREAK STR(CTRL_BOX_BREAK) -#define CMD_COLOR(x) STR(CTRL_COLOR) ARG(x) // 1 -#define CMD_SHIFT(x) STR(CTRL_SHIFT) ARG(x) // 1 -#define CMD_TEXTID(x) STR(CTRL_TEXTID) ARG(x) // 2 -#define CMD_QUICKTEXT_ENABLE STR(CTRL_QUICKTEXT_ENABLE) -#define CMD_QUICKTEXT_DISABLE STR(CTRL_QUICKTEXT_DISABLE) -#define CMD_PERSISTENT STR(CTRL_PERSISTENT) -#define CMD_EVENT STR(CTRL_EVENT) -#define CMD_BOX_BREAK_DELAYED(x) STR(CTRL_BOX_BREAK_DELAYED) ARG(x) // 1 -#define CMD_AWAIT_BUTTON_PRESS STR(CTRL_AWAIT_BUTTON_PRESS) -#define CMD_FADE(x) STR(CTRL_FADE) ARG(x) // 1 -#define CMD_NAME STR(CTRL_NAME) -#define CMD_OCARINA STR(CTRL_OCARINA) -#define CMD_FADE2(x) STR(CTRL_FADE2) ARG(x) // 2 -#define CMD_SFX(x) STR(CTRL_SFX) ARG(x) // 2 -#define CMD_ITEM_ICON(x) STR(CTRL_ITEM_ICON) ARG(x) // 1 -#define CMD_TEXT_SPEED(x) STR(CTRL_TEXT_SPEED) ARG(x) // 1 -#define CMD_BACKGROUND(x,y,z) STR(CTRL_BACKGROUND) ARG(x) ARG(y) ARG(z) -#define CMD_MARATHON_TIME STR(CTRL_MARATHON_TIME) -#define CMD_RACE_TIME STR(CTRL_RACE_TIME) -#define CMD_POINTS STR(CTRL_POINTS) -#define CMD_TOKENS STR(CTRL_TOKENS) -#define CMD_UNSKIPPABLE STR(CTRL_UNSKIPPABLE) -#define CMD_TWO_CHOICE STR(CTRL_TWO_CHOICE) -#define CMD_THREE_CHOICE STR(CTRL_THREE_CHOICE) -#define CMD_FISH_INFO STR(CTRL_FISH_INFO) -#define CMD_HIGHSCORE(x) STR(CTRL_HIGHSCORE) ARG(x) // 1 -#define CMD_TIME STR(CTRL_TIME) - -/* - * Highscore values as strings, for code references the HighScores - * enum should be used. - */ - -#define HS_BANK_RUPEES "\x00" -#define HS_UNK_1 "\x01" -#define HS_FISHING "\x02" -#define HS_BOAT_ARCHERY "\x03" -#define HS_HORSE_BACK_BALLOON "\x04" -#define HS_SHOOTING_GALLERY "\x06" - -/* - * Color values as strings - */ - -#define DEFAULT COLOR_STR(CTRL_DEFAULT) -#define RED COLOR_STR(CTRL_RED) -#define ADJUSTABLE COLOR_STR(CTRL_ADJUSTABLE) -#define BLUE COLOR_STR(CTRL_BLUE) -#define LIGHTBLUE COLOR_STR(CTRL_LIGHTBLUE) -#define PURPLE COLOR_STR(CTRL_PURPLE) -#define YELLOW COLOR_STR(CTRL_YELLOW) -#define BLACK COLOR_STR(CTRL_BLACK) - -#else -// For use in code files -#define MSGCOL_DEFAULT HEX(CTRL_DEFAULT) -#define MSGCOL_RED HEX(CTRL_RED) -#define MSGCOL_ADJUSTABLE HEX(CTRL_ADJUSTABLE) -#define MSGCOL_BLUE HEX(CTRL_BLUE) -#define MSGCOL_LIGHTBLUE HEX(CTRL_LIGHTBLUE) -#define MSGCOL_PURPLE HEX(CTRL_PURPLE) -#define MSGCOL_YELLOW HEX(CTRL_YELLOW) -#define MSGCOL_BLACK HEX(CTRL_BLACK) +#define NEWLINE CTRL_BASE(NEWLINE) +#define END CTRL_BASE(END) +#define BOX_BREAK CTRL_BASE(BOX_BREAK) +#define COLOR(color) CTRL_BASE(COLOR) ARGC(color) +#define SHIFT(amount) CTRL_BASE(SHIFT) ARG1(amount) +#define TEXTID(textId) CTRL_BASE(TEXTID) ARG2(textId) +#define QUICKTEXT_ENABLE CTRL_BASE(QUICKTEXT_ENABLE) +#define QUICKTEXT_DISABLE CTRL_BASE(QUICKTEXT_DISABLE) +#define PERSISTENT CTRL_BASE(PERSISTENT) +#define EVENT CTRL_BASE(EVENT) +#define BOX_BREAK_DELAYED(delay) CTRL_BASE(BOX_BREAK_DELAYED) ARG1(delay) +#define AWAIT_BUTTON_PRESS CTRL_BASE(AWAIT_BUTTON_PRESS) +#define FADE(delay) CTRL_BASE(FADE) ARG1(delay) +#define NAME CTRL_BASE(NAME) +#define OCARINA CTRL_BASE(OCARINA) +#define FADE2(delay) CTRL_BASE(FADE2) ARG2(delay) +#define SFX(sfxId) CTRL_BASE(SFX) ARG2(sfxId) +#define ITEM_ICON(itemId) CTRL_BASE(ITEM_ICON) ARG1(itemId) +#define TEXT_SPEED(amount) CTRL_BASE(TEXT_SPEED) ARG1(amount) +#define BACKGROUND(bgIdx, fgColor, bgColor, yOffset, unk) \ + CTRL_BASE(BACKGROUND) ARGB1(bgIdx) ARGB2(fgColor, bgColor, yOffset, unk) +#define MARATHON_TIME CTRL_BASE(MARATHON_TIME) +#define RACE_TIME CTRL_BASE(RACE_TIME) +#define POINTS CTRL_BASE(POINTS) +#define TOKENS CTRL_BASE(TOKENS) +#define UNSKIPPABLE CTRL_BASE(UNSKIPPABLE) +#define TWO_CHOICE CTRL_BASE(TWO_CHOICE) +#define THREE_CHOICE CTRL_BASE(THREE_CHOICE) +#define FISH_INFO CTRL_BASE(FISH_INFO) +#define HIGHSCORE(highscore) CTRL_BASE(HIGHSCORE) ARG1(x) +#define TIME CTRL_BASE(TIME) -#define MESSAGE_NEWLINE HEX(CTRL_NEWLINE) -#define MESSAGE_END HEX(CTRL_END) -#define MESSAGE_BOX_BREAK HEX(CTRL_BOX_BREAK) -#define MESSAGE_COLOR HEX(CTRL_COLOR) -#define MESSAGE_SHIFT HEX(CTRL_SHIFT) -#define MESSAGE_TEXTID HEX(CTRL_TEXTID) -#define MESSAGE_QUICKTEXT_ENABLE HEX(CTRL_QUICKTEXT_ENABLE) -#define MESSAGE_QUICKTEXT_DISABLE HEX(CTRL_QUICKTEXT_DISABLE) -#define MESSAGE_PERSISTENT HEX(CTRL_PERSISTENT) -#define MESSAGE_EVENT HEX(CTRL_EVENT) -#define MESSAGE_BOX_BREAK_DELAYED HEX(CTRL_BOX_BREAK_DELAYED) -#define MESSAGE_AWAIT_BUTTON_PRESS HEX(CTRL_AWAIT_BUTTON_PRESS) -#define MESSAGE_FADE HEX(CTRL_FADE) -#define MESSAGE_NAME HEX(CTRL_NAME) -#define MESSAGE_OCARINA HEX(CTRL_OCARINA) -#define MESSAGE_FADE2 HEX(CTRL_FADE2) -#define MESSAGE_SFX HEX(CTRL_SFX) -#define MESSAGE_ITEM_ICON HEX(CTRL_ITEM_ICON) -#define MESSAGE_TEXT_SPEED HEX(CTRL_TEXT_SPEED) -#define MESSAGE_BACKGROUND HEX(CTRL_BACKGROUND) -#define MESSAGE_MARATHON_TIME HEX(CTRL_MARATHON_TIME) -#define MESSAGE_RACE_TIME HEX(CTRL_RACE_TIME) -#define MESSAGE_POINTS HEX(CTRL_POINTS) -#define MESSAGE_TOKENS HEX(CTRL_TOKENS) -#define MESSAGE_UNSKIPPABLE HEX(CTRL_UNSKIPPABLE) -#define MESSAGE_TWO_CHOICE HEX(CTRL_TWO_CHOICE) -#define MESSAGE_THREE_CHOICE HEX(CTRL_THREE_CHOICE) -#define MESSAGE_FISH_INFO HEX(CTRL_FISH_INFO) -#define MESSAGE_HIGHSCORE HEX(CTRL_HIGHSCORE) -#define MESSAGE_TIME HEX(CTRL_TIME) #endif #endif diff --git a/include/message_data_static.h b/include/message_data_static.h index bdf4fb63457..bed14429b4c 100644 --- a/include/message_data_static.h +++ b/include/message_data_static.h @@ -9,17 +9,17 @@ typedef struct MessageTableEntry { /* 0x4 */ const char* segment; } MessageTableEntry; // size = 0x8; -#define DEFINE_MESSAGE(textId, typePos, msg) \ +#define DEFINE_MESSAGE(textId, type, yPos, msg) \ extern const char _message_##textId[]; #include "assets/text/message_data.h" #undef DEFINE_MESSAGE -#define DEFINE_MESSAGE(textId, typePos, msg) \ +#define DEFINE_MESSAGE(textId, type, yPos, msg) \ extern const char _message_##textId##_staff[]; -#include "assets/text/staff_message_data.h" +#include "assets/text/message_data_staff.h" #undef DEFINE_MESSAGE diff --git a/src/code/z_message.c b/src/code/z_message.c index 48bf4792089..c966718a8d9 100644 --- a/src/code/z_message.c +++ b/src/code/z_message.c @@ -55,7 +55,7 @@ u16 gBombersNotebookWeekEventFlags[BOMBERS_NOTEBOOK_EVENT_MAX] = { #undef DEFINE_PERSON #undef DEFINE_EVENT -#define DEFINE_MESSAGE(textId, typePos, msg) { textId, typePos, _message_##textId }, +#define DEFINE_MESSAGE(textId, type, yPos, msg) { textId, (((type) & 0xF) << 4) | ((yPos) & 0xF), _message_##textId }, MessageTableEntry sMessageTableNES[] = { #include "assets/text/message_data.h" @@ -64,10 +64,10 @@ MessageTableEntry sMessageTableNES[] = { #undef DEFINE_MESSAGE -#define DEFINE_MESSAGE(textId, typePos, msg) { textId, typePos, _message_##textId##_staff }, +#define DEFINE_MESSAGE(textId, type, yPos, msg) { textId, (((type) & 0xF) << 4) | ((yPos) & 0xF), _message_##textId##_staff }, MessageTableEntry sMessageTableCredits[] = { -#include "assets/text/staff_message_data.h" +#include "assets/text/message_data_staff.h" { 0xFFFF, 0, NULL }, }; diff --git a/tools/extract_assets.py b/tools/extract_assets.py index cb8ace7c2f7..1bb345ab3b1 100755 --- a/tools/extract_assets.py +++ b/tools/extract_assets.py @@ -133,42 +133,19 @@ def main(): with extractedAssetsFile.open(encoding='utf-8') as f: extractedAssetsTracker.update(json.load(f, object_hook=manager.dict)) - extract_text_path = outputDir / "text/message_data.h" - extract_staff_text_path = outputDir / "text/staff_message_data.h" - asset_path = args.single if asset_path is not None: - if "text/" in asset_path: - from msg.nes import msgdisNES - print("Extracting message_data") - msgdisNES.main(extract_text_path) - - from msg.staff import msgdisStaff - print("Extracting staff_message_data") - msgdisStaff.main(extract_staff_text_path) - else: - fullPath = os.path.join("assets", "xml", asset_path + ".xml") - if not os.path.exists(fullPath): - print(f"Error. File {fullPath} does not exist.", file=os.sys.stderr) - exit(1) + fullPath = os.path.join("assets", "xml", asset_path + ".xml") + if not os.path.exists(fullPath): + print(f"Error. File {fullPath} does not exist.", file=os.sys.stderr) + exit(1) - initializeWorker(mainAbort, args.unaccounted, extractedAssetsTracker, manager, baseromSegmentsDir, outputDir) - # Always extract if -s is used. - if fullPath in extractedAssetsTracker: - del extractedAssetsTracker[fullPath] - ExtractFunc(fullPath) + initializeWorker(mainAbort, args.unaccounted, extractedAssetsTracker, manager, baseromSegmentsDir, outputDir) + # Always extract if -s is used. + if fullPath in extractedAssetsTracker: + del extractedAssetsTracker[fullPath] + ExtractFunc(fullPath) else: - # Only extract text if the header does not already exist, or if --force was passed - if args.force or not os.path.isfile(extract_text_path): - from msg.nes import msgdisNES - print("Extracting message_data") - msgdisNES.main(baseromSegmentsDir, extract_text_path) - - if args.force or not os.path.isfile(extract_staff_text_path): - from msg.staff import msgdisStaff - print("Extracting staff_message_data") - msgdisStaff.main(baseromSegmentsDir, extract_staff_text_path) - xmlFiles = [] for currentPath, _, files in os.walk(os.path.join("assets", "xml")): for file in files: diff --git a/tools/msg/nes/msgdisNES.py b/tools/msg/nes/msgdisNES.py deleted file mode 100755 index 668007066fb..00000000000 --- a/tools/msg/nes/msgdisNES.py +++ /dev/null @@ -1,322 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -from pathlib import Path -import sys -import struct - -class MessageHeaderNES: - def __init__(self, unk11F08, itemId, nextTextId, unk1206C, unk12070, unk12074): - self.unk11F08 = unk11F08 - self.itemId = itemId - self.nextTextId = nextTextId - self.unk1206C = unk1206C - self.unk12070 = unk12070 - self.unk12074 = unk12074 - - def __str__(self): - return ( - f'unk11F08: 0x{self.unk11F08:04X},\n' - f'itemId: 0x{self.itemId:02X},\n' - f'nextTextId: 0x{self.nextTextId:04X},\n' - f'unk1206C: 0x{self.unk1206C:04X},\n' - f'unk12070: 0x{self.unk12070:04X},\n' - f'unk12074: 0x{self.unk12074:04X}' - ) - - def macro(self): - unk11F08 = struct.pack(">H", self.unk11F08) - itemId = struct.pack(">B", self.itemId) - nextTextId = struct.pack(">H", self.nextTextId) - unk1206C = struct.pack(">H", self.unk1206C) - unk12070 = struct.pack(">H", self.unk12070) - unk12074 = struct.pack(">H", self.unk12074) - return ( - f'"\\x{unk11F08[0]:02X}\\x{unk11F08[1]:02X}" ' - f'"\\x{itemId[0]:02X}" ' - f'"\\x{nextTextId[0]:02X}\\x{nextTextId[1]:02X}" ' - f'"\\x{unk1206C[0]:02X}\\x{unk1206C[1]:02X}" ' - f'"\\x{unk12070[0]:02X}\\x{unk12070[1]:02X}" ' - f'"\\x{unk12074[0]:02X}\\x{unk12074[1]:02X}"' - ) - - -class MessageNES: - BUTTONMAP = { - 0xB0: '[A]', - 0xB1: '[B]', - 0xB2: '[C]', - 0xB3: '[L]', - 0xB4: '[R]', - 0xB5: '[Z]', - 0xB6: '[C-Up]', - 0xB7: '[C-Down]', - 0xB8: '[C-Left]', - 0xB9: '[C-Right]', - 0xBA: '▼', - 0xBB: '[Control-Pad]' - } - - def __init__(self, id, typePos, addr, hdr, text): - self.id = id - self.typePos = typePos - self.addr = addr - self.hdr = hdr - self.text = text - self.decodedText = "" - self.decodePos = 0 - - def __str__(self): - return ( - f'Message 0x{self.id:04X}:\n' - f'Segment: 0x{self.addr:08X}\n' - f'TypePos: 0x{self.typePos:02X}\n' - f'{str(self.hdr)}\n' - f'Text: {self.text}\n' - f'Decoded:\n{self.decodedText}' - ) - - def macro(self): - self.decode() - return ( - f"DEFINE_MESSAGE(0x{self.id:04X}, 0x{self.typePos:02X}, {self.hdr.macro()}\n" - f"{self.decodedText}\n)\n" - ) - - def decode_cmd_arg_none(self, cmd): - return f'{cmd}' - - def decode_cmd_arg_1byte(self, cmd): - arg = self.text[self.decodePos] - self.decodePos += 1 - return f'{cmd}("\\x{arg:02X}")' - - def decode_cmd_arg_2byte(self, cmd): - arg1 = self.text[self.decodePos] - arg2 = self.text[self.decodePos + 1] - self.decodePos += 2 - return f'{cmd}("\\x{arg1:02X}\\x{arg2:02X}")' - - def decode(self): - CMDMAP = { - 0x00: ("CMD_COLOR_DEFAULT", self.decode_cmd_arg_none), - 0x01: ("CMD_COLOR_RED", self.decode_cmd_arg_none), - 0x02: ("CMD_COLOR_GREEN", self.decode_cmd_arg_none), - 0x03: ("CMD_COLOR_BLUE", self.decode_cmd_arg_none), - 0x04: ("CMD_COLOR_YELLOW", self.decode_cmd_arg_none), - 0x05: ("CMD_COLOR_LIGHTBLUE", self.decode_cmd_arg_none), - 0X06: ("CMD_COLOR_PINK", self.decode_cmd_arg_none), - 0x07: ("CMD_COLOR_SILVER", self.decode_cmd_arg_none), - 0x08: ("CMD_COLOR_ORANGE", self.decode_cmd_arg_none), - 0x0A: ("CMD_TEXT_SPEED", self.decode_cmd_arg_none), - 0x0B: ("CMD_HS_BOAT_ARCHERY", self.decode_cmd_arg_none), - 0x0C: ("CMD_STRAY_FAIRIES", self.decode_cmd_arg_none), - 0x0D: ("CMD_TOKENS", self.decode_cmd_arg_none), - 0x0E: ("CMD_POINTS_TENS", self.decode_cmd_arg_none), - 0x0F: ("CMD_POINTS_THOUSANDS", self.decode_cmd_arg_none), - 0x10: ("CMD_BOX_BREAK", self.decode_cmd_arg_none), - 0x12: ("CMD_BOX_BREAK2", self.decode_cmd_arg_none), - 0x13: ("CMD_CARRIAGE_RETURN", self.decode_cmd_arg_none), - 0x14: ("CMD_SHIFT", self.decode_cmd_arg_1byte), - 0x15: ("CMD_CONTINUE", self.decode_cmd_arg_none), - 0x16: ("CMD_NAME", self.decode_cmd_arg_none), - 0x17: ("CMD_QUICKTEXT_ENABLE", self.decode_cmd_arg_none), - 0x18: ("CMD_QUICKTEXT_DISABLE", self.decode_cmd_arg_none), - 0x19: ("CMD_EVENT", self.decode_cmd_arg_none), - 0x1A: ("CMD_PERSISTENT", self.decode_cmd_arg_none), - 0x1B: ("CMD_BOX_BREAK_DELAYED", self.decode_cmd_arg_2byte), - 0x1C: ("CMD_FADE", self.decode_cmd_arg_2byte), - 0x1D: ("CMD_FADE_SKIPPABLE", self.decode_cmd_arg_2byte), - 0x1E: ("CMD_SFX", self.decode_cmd_arg_2byte), - 0x1F: ("CMD_DELAY", self.decode_cmd_arg_2byte), - 0xC1: ("CMD_BACKGROUND", self.decode_cmd_arg_none), - 0xC2: ("CMD_TWO_CHOICE", self.decode_cmd_arg_none), - 0xC3: ("CMD_THREE_CHOICE", self.decode_cmd_arg_none), - 0xC4: ("CMD_TIMER_POSTMAN", self.decode_cmd_arg_none), - 0xC5: ("CMD_TIMER_MINIGAME_1", self.decode_cmd_arg_none), - 0xC6: ("CMD_TIMER_2", self.decode_cmd_arg_none), - 0xC7: ("CMD_TIMER_MOON_CRASH", self.decode_cmd_arg_none), - 0xC8: ("CMD_TIMER_MINIGAME_2", self.decode_cmd_arg_none), - 0xC9: ("CMD_TIMER_TIMER_ENV_HAZARD", self.decode_cmd_arg_none), - 0xCA: ("CMD_TIME", self.decode_cmd_arg_none), - 0xCB: ("CMD_CHEST_FLAGS", self.decode_cmd_arg_none), - 0xCC: ("CMD_INPUT_BANK", self.decode_cmd_arg_none), - 0xCD: ("CMD_RUPEES_SELECTED", self.decode_cmd_arg_none), - 0xCE: ("CMD_RUPEES_TOTAL", self.decode_cmd_arg_none), - 0xCF: ("CMD_TIME_UNTIL_MOON_CRASH", self.decode_cmd_arg_none), - 0xD0: ("CMD_INPUT_DOGGY_RACETRACK_BET", self.decode_cmd_arg_none), - 0xD1: ("CMD_INPUT_BOMBER_CODE", self.decode_cmd_arg_none), - 0xD2: ("CMD_PAUSE_MENU", self.decode_cmd_arg_none), - 0xD3: ("CMD_TIME_SPEED", self.decode_cmd_arg_none), - 0xD4: ("CMD_OWL_WARP", self.decode_cmd_arg_none), - 0xD5: ("CMD_INPUT_LOTTERY_CODE", self.decode_cmd_arg_none), - 0xD6: ("CMD_SPIDER_HOUSE_MASK_CODE", self.decode_cmd_arg_none), - 0xD7: ("CMD_STRAY_FAIRIES_LEFT_WOODFALL", self.decode_cmd_arg_none), - 0xD8: ("CMD_STRAY_FAIRIES_LEFT_SNOWHEAD", self.decode_cmd_arg_none), - 0xD9: ("CMD_STRAY_FAIRIES_LEFT_GREAT_BAY", self.decode_cmd_arg_none), - 0xDA: ("CMD_STRAY_FAIRIES_LEFT_STONE_TOWER", self.decode_cmd_arg_none), - 0xDB: ("CMD_POINTS_BOAT_ARCHERY", self.decode_cmd_arg_none), - 0xDC: ("CMD_LOTTERY_CODE", self.decode_cmd_arg_none), - 0xDD: ("CMD_LOTTERY_CODE_GUESS", self.decode_cmd_arg_none), - 0xDE: ("CMD_HELD_ITEM_PRICE", self.decode_cmd_arg_none), - 0xDF: ("CMD_BOMBER_CODE", self.decode_cmd_arg_none), - 0xE0: ("CMD_EVENT2", self.decode_cmd_arg_none), - 0xE1: ("CMD_SPIDER_HOUSE_MASK_CODE_1", self.decode_cmd_arg_none), - 0xE2: ("CMD_SPIDER_HOUSE_MASK_CODE_2", self.decode_cmd_arg_none), - 0xE3: ("CMD_SPIDER_HOUSE_MASK_CODE_3", self.decode_cmd_arg_none), - 0xE4: ("CMD_SPIDER_HOUSE_MASK_CODE_4", self.decode_cmd_arg_none), - 0xE5: ("CMD_SPIDER_HOUSE_MASK_CODE_5", self.decode_cmd_arg_none), - 0xE6: ("CMD_SPIDER_HOUSE_MASK_CODE_6", self.decode_cmd_arg_none), - 0xE7: ("CMD_HOURS_UNTIL_MOON_CRASH", self.decode_cmd_arg_none), - 0xE8: ("CMD_TIME_UNTIL_NEW_DAY", self.decode_cmd_arg_none), - 0xF0: ("CMD_HS_POINTS_BANK_RUPEES", self.decode_cmd_arg_none), - 0xF1: ("CMD_HS_POINTS_UNK_1", self.decode_cmd_arg_none), - 0xF2: ("CMD_HS_POINTS_FISHING", self.decode_cmd_arg_none), - 0xF3: ("CMD_HS_TIME_BOAT_ARCHERY", self.decode_cmd_arg_none), - 0xF4: ("CMD_HS_TIME_HORSE_BACK_BALLOON", self.decode_cmd_arg_none), - 0xF5: ("CMD_HS_TIME_LOTTERY_GUESS", self.decode_cmd_arg_none), - 0xF6: ("CMD_HS_TOWN_SHOOTING_GALLERY", self.decode_cmd_arg_none), - 0xF7: ("CMD_HS_UNK_1", self.decode_cmd_arg_none), - 0xF8: ("CMD_HS_UNK_3_LOWER", self.decode_cmd_arg_none), - 0xF9: ("CMD_HS_HORSE_BACK_BALLOON", self.decode_cmd_arg_none), - 0xFA: ("CMD_HS_DEKU_PLAYGROUND_DAY_1", self.decode_cmd_arg_none), - 0xFB: ("CMD_HS_DEKU_PLAYGROUND_DAY_2", self.decode_cmd_arg_none), - 0xFC: ("CMD_HS_DEKU_PLAYGROUND_DAY_3", self.decode_cmd_arg_none), - 0xFD: ("CMD_DEKU_PLAYGROUND_NAME_DAY_1", self.decode_cmd_arg_none), - 0xFE: ("CMD_DEKU_PLAYGROUND_NAME_DAY_2", self.decode_cmd_arg_none), - 0xFF: ("CMD_DEKU_PLAYGROUND_NAME_DAY_3", self.decode_cmd_arg_none) - } - if self.decodedText != "": - return - - prevText = False - prevNewline = True - prevCmd = False - self.decodePos = 0 - textLen = len(self.text) - while self.decodePos < textLen: - char = self.text[self.decodePos] - self.decodePos += 1 - - if char >= 0x20 and char <= 0xBB: # Characters - if prevCmd: - self.decodedText += ' "' - elif prevNewline: - self.decodedText += '"' - - if char == 0x22: # Handle escaping " - self.decodedText += '\\"' - elif char >= 0xB0: # Button characters - self.decodedText += f'{MessageNES.BUTTONMAP[char]}' - else: - self.decodedText += chr(char) - - prevText = True - prevNewline = False - prevCmd = False - elif char == 0x11: # New line - if prevCmd: - self.decodedText += ' "' - elif prevNewline: - self.decodedText += '"' - - self.decodedText += f'\\n"\n' - - prevText = False - prevNewline = True - prevCmd = False - elif char == 0x10 or char == 0x12 or char == 0x1B: # Box Breaks add automatic newlines - if prevText: - self.decodedText += '"' - - cmd, decoder = CMDMAP[char] - self.decodedText += f'\n{decoder(cmd)}\n' - - prevText = False - prevNewline = True - prevCmd = False - elif char == 0xBF: # End command, do nothing - if prevText: - self.decodedText += '"' - else: # Control Codes (see message_data_fmt_nes.h) - if prevText: - self.decodedText += '" ' - elif prevCmd: - self.decodedText += ' ' - - cmd, decoder = CMDMAP[char] - self.decodedText += decoder(cmd) - - prevText = False - prevNewline = False - prevCmd = True - -def parseTable(baseromSegmentsDir: Path, start): - table = {} - with open(baseromSegmentsDir / "code","rb") as f: - f.seek(start) - buf = f.read(8) - textId, typePos, segment = struct.unpack(">HBxI", buf) - while textId != 0xFFFF: - table[segment] = (textId, typePos, segment) - buf = f.read(8) - textId, typePos, segment = struct.unpack(">HBxI", buf) - - return table - -NES_MESSAGE_TABLE_ADDR = 0x1210D8 # Location of NES message table in extracted/n64-us/baserom/code -NES_SEGMENT_ADDR = 0x08000000 - -def main(baseromSegmentsDir: Path, outfile): - msgTable = parseTable(baseromSegmentsDir, NES_MESSAGE_TABLE_ADDR) - - buf = (baseromSegmentsDir / "message_data_static").read_bytes() - - bufLen = len(buf) - i = 0 - messages = [] - while i + 12 < bufLen: # Next message must be able to fill a header + 1 at minimum - addr = NES_SEGMENT_ADDR + i - - unk11F08, itemId, nextTextId, unk1206C, unk12070, unk12074 = struct.unpack(">HBHHHH", buf[i:i+11]) - i += 11 - hdr = MessageHeaderNES(unk11F08, itemId, nextTextId, unk1206C, unk12070, unk12074) - - start = i - while i < bufLen and buf[i] != 0xBF: - i += 1 - i += 1 - - if i >= bufLen: - break - - id, typePos, segment = msgTable[addr] - msg = MessageNES(id, typePos, segment, hdr, buf[start:i]) - - messages.append(msg) - - i = (i + 3) & ~0x3 # Next message starts on a 0x4 byte boundary - - if outfile is None: - for msg in messages: - sys.stdout.write(msg.macro()) - sys.stdout.write("\n") - else: - with open(outfile, "w") as f: - for msg in messages: - f.write(msg.macro()) - f.write("\n") - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description="Extract message_data_static text") - parser.add_argument( - "--baserom-segments", - dest="baserom_segments_dir", - type=Path, - required=True, - help="Directory of uncompressed ROM segments", - ) - parser.add_argument('-o', '--outfile', help='output file to write to. None for stdout') - args = parser.parse_args() - - main(args.baserom_segments_dir, args.outfile) diff --git a/tools/msg/nes/msgencNES.py b/tools/msg/nes/msgencNES.py deleted file mode 100755 index ae5e18d75e5..00000000000 --- a/tools/msg/nes/msgencNES.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python3 -# -# message_data_static text encoder -# - -import argparse -import re -import sys - -CHAR_REGEX = r'(?P\\n|\[.*?\])' - -# From https://stackoverflow.com/questions/241327/remove-c-and-c-comments-using-python -def remove_comments(text): - def replacer(match): - s = match.group(0) - if s.startswith('/'): - return " " # note: a space and not an empty string - else: - return s - - pattern = re.compile( - r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE - ) - return re.sub(pattern, replacer, text) - -def parse_char(m): - CHARMAP = { - '\\n' : 0x11, - - '[A]' : 0xB0, - '[B]' : 0xB1, - '[C]' : 0xB2, - '[L]' : 0xB3, - '[R]' : 0xB4, - '[Z]' : 0xB5, - '[C-Up]' : 0xB6, - '[C-Down]' : 0xB7, - '[C-Left]' : 0xB8, - '[C-Right]' : 0xB9, - '▼' : 0xBA, - '[Control-Pad]' : 0xBB, - } - return f'{chr(CHARMAP[m.group(0)])}' - -def cvt_str(m): - if m.group('chr'): - return parse_char(m) - else: - print(f"Error Unknown match {m}", file=sys.stderr) - return m.group(0) # Just return the string back - -def encode(text): - string_regex = re.compile(f'{CHAR_REGEX}') - - # Collapse escaped newlines - text = text.replace("\\\n", "") - - # Encode - text = re.sub(string_regex, cvt_str, text) - - return text - -def main(infile, outfile): - text = "" - with open(infile, "r") as f: - text = f.read() - - text = remove_comments(text) - text = encode(text) - - if outfile is None: - sys.stdout.reconfigure(encoding='raw_unicode_escape') - sys.stdout.write(text) - else: - with open(outfile, "w", encoding="raw_unicode_escape") as f: - f.write(text) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Encode message_data_static text headers") - parser.add_argument("infile", help="path to file to be encoded") - parser.add_argument("-o", "--outfile", help="encoded file. None for stdout") - args = parser.parse_args() - - main(args.infile, args.outfile) diff --git a/tools/msg/staff/msgdisStaff.py b/tools/msg/staff/msgdisStaff.py deleted file mode 100755 index 670d6610511..00000000000 --- a/tools/msg/staff/msgdisStaff.py +++ /dev/null @@ -1,237 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -from pathlib import Path -import sys -import struct - -class MessageCredits: - def __init__(self, id, typePos, addr, text): - self.id = id - self.typePos = typePos - self.addr = addr - self.text = text - self.decodedText = "" - self.decodePos = 0 - - def __str__(self): - return (f' Message 0x{self.id:04X}:\n' - f' Segment: 0x{self.addr:08X}\n' - f' TypePos: 0x{self.typePos:02X}\n' - f' Text: {self.text}\n' - f' Decoded:\n{self.decodedText}') - - def macro(self): - self.decode() - return ( - f"DEFINE_MESSAGE(0x{self.id:04X}, 0x{self.typePos:02X},\n" - f"{self.decodedText}\n)\n" - ) - - def decode_cmd_arg_none(self, cmd): - return f'{cmd}' - - def decode_cmd_arg_1byte(self, cmd): - arg = self.text[self.decodePos] - self.decodePos += 1 - return f'{cmd}("\\x{arg:02X}")' - - def decode_cmd_arg_2byte(self, cmd): - arg1 = self.text[self.decodePos] - arg2 = self.text[self.decodePos + 1] - self.decodePos += 2 - return f'{cmd}("\\x{arg1:02X}\\x{arg2:02X}")' - - def decode_cmd_color(self, cmd): - COLORS = { - 0: "DEFAULT", - 1: "RED", - 2: "ADJUSTABLE", - 3: "BLUE", - 4: "LIGHTBLUE", - 5: "PURPLE", - 6: "YELLOW", - 7: "BLACK" - } - color = self.text[self.decodePos] - self.decodePos += 1 - return f'{cmd}({COLORS[color]}) ' - - def decode_cmd_background(self, cmd): - arg1 = self.text[self.decodePos] - arg2 = self.text[self.decodePos + 1] - arg3 = self.text[self.decodePos + 2] - self.decodePos += 3 - return f'{cmd}("\\x{arg1:02X}","\\x{arg2:02X}","\\x{arg3:02X}")' - - def decode_cmd_highscore(self, cmd): - HIGHSCORES = { - 0: "HS_BANK_RUPEES", - 1: "HS_UNK_1", - 2: "HS_FISHING", - 3: "HS_BOAT_ARCHERY", - 4: "HS_HORSE_BACK_BALLOON", - 6: "HS_SHOOTING_GALLERY" - } - highscore = self.text[self.decodePos] - self.decodePos += 1 - return f'{cmd}({HIGHSCORES[highscore]})' - - def decode(self): - CMDMAP = { - 0x00: ("CMD_COLOR_DEFAULT", self.decode_cmd_arg_none), - 0x04: ("CMD_BOX_BREAK", self.decode_cmd_arg_none), - 0x05: ("CMD_COLOR", self.decode_cmd_color), - 0X06: ("CMD_SHIFT", self.decode_cmd_arg_1byte), - 0x07: ("CMD_TEXTID", self.decode_cmd_arg_2byte), - 0x08: ("CMD_QUICKTEXT_ENABLE", self.decode_cmd_arg_none), - 0x09: ("CMD_QUICKTEXT_DISABLE", self.decode_cmd_arg_none), - 0x0A: ("CMD_PERSISTENT", self.decode_cmd_arg_none), - 0x0B: ("CMD_EVENT", self.decode_cmd_arg_none), - 0x0C: ("CMD_BOX_BREAK_DELAY", self.decode_cmd_arg_2byte), - 0x0D: ("CMD_WAIT_INPUT", self.decode_cmd_arg_none), - 0x0E: ("CMD_FADE", self.decode_cmd_arg_1byte), - 0x0F: ("CMD_NAME", self.decode_cmd_arg_none), - 0x10: ("CMD_OCARINA", self.decode_cmd_arg_none), - 0x11: ("CMD_FADE2", self.decode_cmd_arg_2byte), - 0x12: ("CMD_SFX", self.decode_cmd_arg_2byte), - 0x13: ("CMD_ITEM_ICON", self.decode_cmd_arg_1byte), - 0x14: ("CMD_TEXT_SPEED", self.decode_cmd_arg_1byte), - 0x15: ("CMD_BACKGROUND", self.decode_cmd_background), - 0x16: ("CMD_MARATHONTIME", self.decode_cmd_arg_none), - 0x17: ("CMD_RACETIME", self.decode_cmd_arg_none), - 0x18: ("CMD_POINTS", self.decode_cmd_arg_none), - 0x1A: ("CMD_UNSKIPPABLE", self.decode_cmd_arg_none), - 0x1B: ("CMD_TWO_CHOICE", self.decode_cmd_arg_none), - 0x1C: ("CMD_THREE_CHOICE", self.decode_cmd_arg_none), - 0x1D: ("CMD_FISH_INFO", self.decode_cmd_arg_none), - 0x1E: ("CMD_HIGHSCORE", self.decode_cmd_highscore), - 0x1F: ("CMD_TIME", self.decode_cmd_arg_none), - } - if self.decodedText != "": - return - - prevText = False - prevNewline = True - prevCmd = False - self.decodePos = 0 - textLen = len(self.text) - while self.decodePos < textLen: - char = self.text[self.decodePos] - self.decodePos += 1 - - if char >= 0x20 and char <= 0xAF: # Regular Characters - if prevCmd: - self.decodedText += ' "' - elif prevNewline: - self.decodedText += '"' - - if char == 0x22: # Handle escaping " - self.decodedText += '\\"' - else: - self.decodedText += chr(char) - - prevText = True - prevNewline = False - prevCmd = False - elif char == 0x1: # New line - if prevCmd: - self.decodedText += ' "' - elif prevNewline: - self.decodedText += '"' - - self.decodedText += f'\\n"\n' - - prevText = False - prevNewline = True - prevCmd = False - elif char == 0x04 or char == 0x0C: # Box Breaks add automatic newlines - if prevText: - self.decodedText += '"' - - cmd, decoder = CMDMAP[char] - self.decodedText += f'\n{decoder(cmd)}\n' - - prevText = False - prevNewline = True - prevCmd = False - elif char == 0x02: # End command, do nothing - if prevText: - self.decodedText += '"' - else: # Control Codes (see message_data_fmt_staff.h) - if prevText: - self.decodedText += '" ' - elif prevCmd: - self.decodedText += ' ' - - cmd, decoder = CMDMAP[char] - self.decodedText += decoder(cmd) - - prevText = False - prevNewline = False - prevCmd = True - -def parseTable(baseromSegmentsDir: Path, start): - table = {} - with open(baseromSegmentsDir / "code","rb") as f: - f.seek(start) - buf = f.read(8) - textId, typePos, segment = struct.unpack(">HBxI", buf) - while textId != 0xFFFF: - table[segment] = (textId, typePos, segment) - buf = f.read(8) - textId, typePos, segment = struct.unpack(">HBxI", buf) - - return table - -STAFF_MESSAGE_TABLE_ADDR = 0x12A048 # Location of Staff message table in extracted/n64-us/baserom/code -STAFF_SEGMENT_ADDR = 0x07000000 - -def main(baseromSegmentsDir: Path, outfile): - msgTable = parseTable(baseromSegmentsDir, STAFF_MESSAGE_TABLE_ADDR) - - buf = (baseromSegmentsDir / "staff_message_data_static").read_bytes() - - bufLen = len(buf) - i = 0 - messages = [] - while i < bufLen: - addr = STAFF_SEGMENT_ADDR + i - - start = i - while i < bufLen and buf[i] != 0x2: - i += 1 - i += 1 - - if i >= bufLen: - break - - id, typePos, segment = msgTable[addr] - msg = MessageCredits(id, typePos, segment, buf[start:i]) - messages.append(msg) - - i = (i + 3) & ~0x3 # Next message starts on a 0x4 byte boundary - - if outfile is None: - for msg in messages: - sys.stdout.write(msg.macro()) - sys.stdout.write("\n") - else: - with open(outfile, "w") as f: - for msg in messages: - f.write(msg.macro()) - f.write("\n") - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description="Extract staff_message_data_static text") - parser.add_argument( - "--baserom-segments", - dest="baserom_segments_dir", - type=Path, - required=True, - help="Directory of uncompressed ROM segments", - ) - parser.add_argument('-o', '--outfile', help='output file to write to. None for stdout') - args = parser.parse_args() - - main(args.baserom_segments_dir, args.outfile) diff --git a/tools/msg/staff/msgencStaff.py b/tools/msg/staff/msgencStaff.py deleted file mode 100755 index bf719a64895..00000000000 --- a/tools/msg/staff/msgencStaff.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -# -# message_data_static text encoder -# - -import argparse -import re -import sys - -CHAR_REGEX = r'(?P\\n|\[.*?\])' - -# From https://stackoverflow.com/questions/241327/remove-c-and-c-comments-using-python -def remove_comments(text): - def replacer(match): - s = match.group(0) - if s.startswith('/'): - return " " # note: a space and not an empty string - else: - return s - - pattern = re.compile( - r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE - ) - return re.sub(pattern, replacer, text) - -def parse_char(m): - CHARMAP = { - '\\n' : 0x1, - } - return f'{chr(CHARMAP[m.group(0)])}' - -def cvt_str(m): - if m.group('chr'): - return parse_char(m) - else: - print(f"Error Unknown match {m}", file=sys.stderr) - return m.group(0) # Just return the string back - -def encode(text): - string_regex = re.compile(f'{CHAR_REGEX}') - - # Collapse escaped newlines - text = text.replace("\\\n", "") - - # Encode - text = re.sub(string_regex, cvt_str, text) - - return text - -def main(infile, outfile): - text = "" - with open(infile, "r") as f: - text = f.read() - - text = remove_comments(text) - text = encode(text) - - if outfile is None: - sys.stdout.reconfigure(encoding='raw_unicode_escape') - sys.stdout.write(text) - else: - with open(outfile, "w", encoding="raw_unicode_escape") as f: - f.write(text) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Encode staff_message_data_static text headers") - parser.add_argument("infile", help="path to file to be encoded") - parser.add_argument("-o", "--outfile", help="encoded file. None for stdout") - args = parser.parse_args() - - main(args.infile, args.outfile) diff --git a/tools/text/msgdis.py b/tools/text/msgdis.py new file mode 100755 index 00000000000..d4d173e1db9 --- /dev/null +++ b/tools/text/msgdis.py @@ -0,0 +1,3190 @@ +#!/usr/bin/env python3 +# +# message_data_static disassembler/decompiler +# + +import argparse, re, struct +from pathlib import Path +from typing import Callable, Dict, List, Optional, Tuple, TypeVar + +T = TypeVar("T") + +item_ids = { + 0x00: "ITEM_OCARINA_OF_TIME", + 0x01: "ITEM_BOW", + 0x02: "ITEM_ARROW_FIRE", + 0x03: "ITEM_ARROW_ICE", + 0x04: "ITEM_ARROW_LIGHT", + 0x05: "ITEM_OCARINA_FAIRY", + 0x06: "ITEM_BOMB", + 0x07: "ITEM_BOMBCHU", + 0x08: "ITEM_DEKU_STICK", + 0x09: "ITEM_DEKU_NUT", + 0x0A: "ITEM_MAGIC_BEANS", + 0x0B: "ITEM_SLINGSHOT", + 0x0C: "ITEM_POWDER_KEG", + 0x0D: "ITEM_PICTOGRAPH_BOX", + 0x0E: "ITEM_LENS_OF_TRUTH", + 0x0F: "ITEM_HOOKSHOT", + 0x10: "ITEM_SWORD_GREAT_FAIRY", + 0x11: "ITEM_LONGSHOT", + 0x12: "ITEM_BOTTLE", + 0x13: "ITEM_POTION_RED", + 0x14: "ITEM_POTION_GREEN", + 0x15: "ITEM_POTION_BLUE", + 0x16: "ITEM_FAIRY", + 0x17: "ITEM_DEKU_PRINCESS", + 0x18: "ITEM_MILK_BOTTLE", + 0x19: "ITEM_MILK_HALF", + 0x1A: "ITEM_FISH", + 0x1B: "ITEM_BUG", + 0x1C: "ITEM_BLUE_FIRE", + 0x1D: "ITEM_POE", + 0x1E: "ITEM_BIG_POE", + 0x1F: "ITEM_SPRING_WATER", + 0x20: "ITEM_HOT_SPRING_WATER", + 0x21: "ITEM_ZORA_EGG", + 0x22: "ITEM_GOLD_DUST", + 0x23: "ITEM_MUSHROOM", + 0x24: "ITEM_SEAHORSE", + 0x25: "ITEM_CHATEAU", + 0x26: "ITEM_HYLIAN_LOACH", + 0x27: "ITEM_OBABA_DRINK", + 0x28: "ITEM_MOONS_TEAR", + 0x29: "ITEM_DEED_LAND", + 0x2A: "ITEM_DEED_SWAMP", + 0x2B: "ITEM_DEED_MOUNTAIN", + 0x2C: "ITEM_DEED_OCEAN", + 0x2D: "ITEM_ROOM_KEY", + 0x2E: "ITEM_LETTER_MAMA", + 0x2F: "ITEM_LETTER_TO_KAFEI", + 0x30: "ITEM_PENDANT_OF_MEMORIES", + 0x31: "ITEM_TINGLE_MAP", + 0x32: "ITEM_MASK_DEKU", + 0x33: "ITEM_MASK_GORON", + 0x34: "ITEM_MASK_ZORA", + 0x35: "ITEM_MASK_FIERCE_DEITY", + 0x36: "ITEM_MASK_TRUTH", + 0x37: "ITEM_MASK_KAFEIS_MASK", + 0x38: "ITEM_MASK_ALL_NIGHT", + 0x39: "ITEM_MASK_BUNNY", + 0x3A: "ITEM_MASK_KEATON", + 0x3B: "ITEM_MASK_GARO", + 0x3C: "ITEM_MASK_ROMANI", + 0x3D: "ITEM_MASK_CIRCUS_LEADER", + 0x3E: "ITEM_MASK_POSTMAN", + 0x3F: "ITEM_MASK_COUPLE", + 0x40: "ITEM_MASK_GREAT_FAIRY", + 0x41: "ITEM_MASK_GIBDO", + 0x42: "ITEM_MASK_DON_GERO", + 0x43: "ITEM_MASK_KAMARO", + 0x44: "ITEM_MASK_CAPTAIN", + 0x45: "ITEM_MASK_STONE", + 0x46: "ITEM_MASK_BREMEN", + 0x47: "ITEM_MASK_BLAST", + 0x48: "ITEM_MASK_SCENTS", + 0x49: "ITEM_MASK_GIANT", + 0x4A: "ITEM_BOW_FIRE", + 0x4B: "ITEM_BOW_ICE", + 0x4C: "ITEM_BOW_LIGHT", + 0x4D: "ITEM_SWORD_KOKIRI", + 0x4E: "ITEM_SWORD_RAZOR", + 0x4F: "ITEM_SWORD_GILDED", + 0x50: "ITEM_SWORD_DEITY", + 0x51: "ITEM_SHIELD_HERO", + 0x52: "ITEM_SHIELD_MIRROR", + 0x53: "ITEM_QUIVER_30", + 0x54: "ITEM_QUIVER_40", + 0x55: "ITEM_QUIVER_50", + 0x56: "ITEM_BOMB_BAG_20", + 0x57: "ITEM_BOMB_BAG_30", + 0x58: "ITEM_BOMB_BAG_40", + 0x59: "ITEM_WALLET_DEFAULT", + 0x5A: "ITEM_WALLET_ADULT", + 0x5B: "ITEM_WALLET_GIANT", + 0x5C: "ITEM_FISHING_ROD", + 0x5D: "ITEM_REMAINS_ODOLWA", + 0x5E: "ITEM_REMAINS_GOHT", + 0x5F: "ITEM_REMAINS_GYORG", + 0x60: "ITEM_REMAINS_TWINMOLD", + 0x61: "ITEM_SONG_SONATA", + 0x62: "ITEM_SONG_LULLABY", + 0x63: "ITEM_SONG_NOVA", + 0x64: "ITEM_SONG_ELEGY", + 0x65: "ITEM_SONG_OATH", + 0x66: "ITEM_SONG_SARIA", + 0x67: "ITEM_SONG_TIME", + 0x68: "ITEM_SONG_HEALING", + 0x69: "ITEM_SONG_EPONA", + 0x6A: "ITEM_SONG_SOARING", + 0x6B: "ITEM_SONG_STORMS", + 0x6C: "ITEM_SONG_SUN", + 0x6D: "ITEM_BOMBERS_NOTEBOOK", + 0x6E: "ITEM_SKULL_TOKEN", + 0x6F: "ITEM_HEART_CONTAINER", + 0x70: "ITEM_HEART_PIECE", + 0x71: "ITEM_71", + 0x72: "ITEM_72", + 0x73: "ITEM_SONG_LULLABY_INTRO", + 0x74: "ITEM_KEY_BOSS", + 0x75: "ITEM_COMPASS", + 0x76: "ITEM_DUNGEON_MAP", + 0x77: "ITEM_STRAY_FAIRIES", + 0x78: "ITEM_KEY_SMALL", + 0x79: "ITEM_MAGIC_JAR_SMALL", + 0x7A: "ITEM_MAGIC_JAR_BIG", + 0x7B: "ITEM_HEART_PIECE_2", + 0x7C: "ITEM_INVALID_1", + 0x7D: "ITEM_INVALID_2", + 0x7E: "ITEM_INVALID_3", + 0x7F: "ITEM_INVALID_4", + 0x80: "ITEM_INVALID_5", + 0x81: "ITEM_INVALID_6", + 0x82: "ITEM_INVALID_7", + 0x83: "ITEM_RECOVERY_HEART", + 0x84: "ITEM_RUPEE_GREEN", + 0x85: "ITEM_RUPEE_BLUE", + 0x86: "ITEM_RUPEE_10", + 0x87: "ITEM_RUPEE_RED", + 0x88: "ITEM_RUPEE_PURPLE", + 0x89: "ITEM_RUPEE_SILVER", + 0x8A: "ITEM_RUPEE_HUGE", + 0x8B: "ITEM_DEKU_STICKS_5", + 0x8C: "ITEM_DEKU_STICKS_10", + 0x8D: "ITEM_DEKU_NUTS_5", + 0x8E: "ITEM_DEKU_NUTS_10", + 0x8F: "ITEM_BOMBS_5", + 0x90: "ITEM_BOMBS_10", + 0x91: "ITEM_BOMBS_20", + 0x92: "ITEM_BOMBS_30", + 0x93: "ITEM_ARROWS_10", + 0x94: "ITEM_ARROWS_30", + 0x95: "ITEM_ARROWS_40", + 0x96: "ITEM_ARROWS_50", + 0x97: "ITEM_BOMBCHUS_20", + 0x98: "ITEM_BOMBCHUS_10", + 0x99: "ITEM_BOMBCHUS_1", + 0x9A: "ITEM_BOMBCHUS_5", + 0x9B: "ITEM_DEKU_STICK_UPGRADE_20", + 0x9C: "ITEM_DEKU_STICK_UPGRADE_30", + 0x9D: "ITEM_DEKU_NUT_UPGRADE_30", + 0x9E: "ITEM_DEKU_NUT_UPGRADE_40", + 0x9F: "ITEM_CHATEAU_2", + 0xA0: "ITEM_MILK", + 0xA1: "ITEM_GOLD_DUST_2", + 0xA2: "ITEM_HYLIAN_LOACH_2", + 0xA3: "ITEM_SEAHORSE_CAUGHT", + 0xA4: "ITEM_MAP_POINT_GREAT_BAY", + 0xA5: "ITEM_MAP_POINT_ZORA_HALL", + 0xA6: "ITEM_MAP_POINT_ROMANI_RANCH", + 0xA7: "ITEM_MAP_POINT_DEKU_PALACE", + 0xA8: "ITEM_MAP_POINT_WOODFALL", + 0xA9: "ITEM_MAP_POINT_CLOCK_TOWN", + 0xAA: "ITEM_MAP_POINT_SNOWHEAD", + 0xAB: "ITEM_MAP_POINT_IKANA_GRAVEYARD", + 0xAC: "ITEM_MAP_POINT_IKANA_CANYON", + 0xAD: "ITEM_MAP_POINT_GORON_VILLAGE", + 0xAE: "ITEM_MAP_POINT_STONE_TOWER", + 0xAF: "ITEM_MAP_POINT_GREAT_BAY_COAST", + 0xB0: "ITEM_MAP_POINT_SOUTHERN_SWAMP", + 0xB1: "ITEM_MAP_POINT_MOUNTAIN_VILLAGE", + 0xB2: "ITEM_MAP_POINT_MILK_ROAD", + 0xB3: "ITEM_MAP_POINT_ZORA_CAPE", + 0xB4: "ITEM_B4", + 0xB5: "ITEM_B5", + 0xB6: "ITEM_B6", + 0xB7: "ITEM_B7", + 0xB8: "ITEM_B8", + 0xB9: "ITEM_B9", + 0xBA: "ITEM_BA", + 0xBB: "ITEM_BB", + 0xBC: "ITEM_BC", + 0xBD: "ITEM_BD", + 0xBE: "ITEM_BE", + 0xBF: "ITEM_BF", + 0xC0: "ITEM_C0", + 0xC1: "ITEM_C1", + 0xC2: "ITEM_C2", + 0xC3: "ITEM_C3", + 0xC4: "ITEM_C4", + 0xC5: "ITEM_C5", + 0xC6: "ITEM_C6", + 0xC7: "ITEM_C7", + 0xC8: "ITEM_C8", + 0xC9: "ITEM_C9", + 0xCA: "ITEM_CA", + 0xCB: "ITEM_CB", + 0xCC: "ITEM_CC", + 0xDC: "ITEM_DC", + 0xDD: "ITEM_DD", + 0xDE: "ITEM_DE", + 0xDF: "ITEM_DF", + 0xE0: "ITEM_E0", + 0xE1: "ITEM_E1", + 0xE2: "ITEM_E2", + 0xE3: "ITEM_E3", + 0xE4: "ITEM_E4", + 0xE5: "ITEM_E5", + 0xE6: "ITEM_E6", + 0xE7: "ITEM_E7", + 0xE8: "ITEM_E8", + 0xE9: "ITEM_E9", + 0xEA: "ITEM_EA", + 0xEB: "ITEM_EB", + 0xEC: "ITEM_EC", + 0xED: "ITEM_ED", + 0xEE: "ITEM_EE", + 0xEF: "ITEM_EF", + 0xF0: "ITEM_F0", + 0xF1: "ITEM_F1", + 0xF2: "ITEM_F2", + 0xFC: "ITEM_FC", + 0xFD: "ITEM_FD", + 0xFE: "ITEM_FE", + 0xFF: "ITEM_NONE", +} + +sfx_ids = { + 0x0000: "NA_SE_PL_WALK_GROUND", + 0x0001: "NA_SE_PL_WALK_SAND", + 0x0002: "NA_SE_PL_WALK_CONCRETE", + 0x0003: "NA_SE_PL_WALK_DIRT", + 0x0004: "NA_SE_PL_WALK_WATER0", + 0x0005: "NA_SE_PL_WALK_WATER1", + 0x0006: "NA_SE_PL_WALK_WATER2", + 0x0007: "NA_SE_PL_WALK_MAGMA", + 0x0008: "NA_SE_PL_WALK_GRASS", + 0x0009: "NA_SE_PL_WALK_IRON", + 0x000A: "NA_SE_PL_WALK_LADDER", + 0x000B: "NA_SE_PL_WALK_GLASS", + 0x000C: "NA_SE_PL_WALK_METAL1", + 0x000D: "NA_CODE_DIRT_DEEP", + 0x000E: "NA_SE_PL_WALK_SNOW", + 0x000F: "NA_SE_PL_WALK_ICE", + 0x0010: "NA_SE_PL_JUMP_GROUND", + 0x0011: "NA_SE_PL_JUMP_SAND", + 0x0012: "NA_SE_PL_JUMP_CONCRETE", + 0x0013: "NA_SE_PL_JUMP_DIRT", + 0x0014: "NA_SE_PL_JUMP_WATER0", + 0x0015: "NA_SE_PL_JUMP_WATER1", + 0x0016: "NA_SE_PL_JUMP_WATER2", + 0x0017: "NA_SE_PL_JUMP_MAGMA", + 0x0018: "NA_SE_PL_JUMP_GRASS", + 0x0019: "NA_SE_PL_JUMP_IRON", + 0x001A: "NA_SE_PL_JUMP_LADDER", + 0x001B: "NA_SE_PL_JUMP_GLASS", + 0x001C: "NA_SE_PL_DUMMY_28", + 0x001D: "NA_SE_PL_JUMP_HEAVYBOOTS", + 0x001E: "NA_SE_PL_JUMP_SNOW", + 0x001F: "NA_SE_PL_JUMP_ICE", + 0x0020: "NA_SE_PL_LAND_GROUND", + 0x0021: "NA_SE_PL_LAND_SAND", + 0x0022: "NA_SE_PL_LAND_CONCRETE", + 0x0023: "NA_SE_PL_LAND_DIRT", + 0x0024: "NA_SE_PL_LAND_WATER0", + 0x0025: "NA_SE_PL_LAND_WATER1", + 0x0026: "NA_SE_PL_LAND_WATER2", + 0x0027: "NA_SE_PL_LAND_MAGMA", + 0x0028: "NA_SE_PL_LAND_GRASS", + 0x0029: "NA_SE_PL_LAND_IRON", + 0x002A: "NA_SE_PL_LAND_LADDER", + 0x002B: "NA_SE_PL_LAND_GLASS", + 0x002C: "NA_SE_PL_DUMMY_44", + 0x002D: "NA_SE_PL_LAND_HEAVYBOOTS", + 0x002E: "NA_SE_PL_LAND_SNOW", + 0x002F: "NA_SE_PL_LAND_ICE", + 0x0030: "NA_SE_PL_SLIPDOWN", + 0x0031: "NA_SE_PL_CLIMB_CLIFF", + 0x0032: "NA_SE_PL_SIT_ON_HORSE", + 0x0033: "NA_SE_PL_GET_OFF_HORSE", + 0x0034: "NA_SE_PL_TAKE_OUT_SHIELD", + 0x0035: "NA_SE_PL_CHANGE_ARMS", + 0x0036: "NA_SE_PL_CATCH_BOOMERANG", + 0x0037: "NA_SE_PL_DIVE_INTO_WATER", + 0x0038: "NA_SE_PL_JUMP_OUT_WATER", + 0x0039: "NA_SE_PL_SWIM", + 0x003A: "NA_SE_PL_THROW", + 0x003B: "NA_SE_PL_BODY_BOUND", + 0x003C: "NA_SE_PL_ROLL", + 0x003D: "NA_SE_PL_SKIP", + 0x003E: "NA_SE_PL_BODY_HIT", + 0x003F: "NA_SE_PL_DAMAGE", + 0x0040: "NA_SE_PL_SLIP", + 0x0041: "NA_SE_PL_SLIP_SAND", + 0x0042: "NA_SE_PL_SLIP_CONCRETE", + 0x0043: "NA_SE_PL_SLIP_DIRT", + 0x0044: "NA_SE_PL_SLIP_WATER0", + 0x0045: "NA_SE_PL_SLIP_WATER1", + 0x0046: "NA_SE_PL_SLIP_WATER2", + 0x0047: "NA_SE_PL_SLIP_MAGMA", + 0x0048: "NA_SE_PL_SLIP_GRASS", + 0x0049: "NA_SE_PL_SLIP_IRON", + 0x004A: "NA_SE_PL_SLIP_LADDER", + 0x004B: "NA_SE_PL_SLIP_GLASS", + 0x004C: "NA_SE_PL_DUMMY76", + 0x004D: "NA_SE_PL_SLIP_HEAVYBOOTS", + 0x004E: "NA_SE_PL_SLIP_SNOW", + 0x004F: "NA_SE_PL_SLIP_ICE", + 0x0050: "NA_SE_PL_BOUND", + 0x0051: "NA_SE_PL_BOUND_SAND", + 0x0052: "NA_SE_PL_BOUND_CONCRETE", + 0x0053: "NA_SE_PL_BOUND_DIRT", + 0x0054: "NA_SE_PL_BOUND_WATER0", + 0x0055: "NA_SE_PL_BOUND_WATER1", + 0x0056: "NA_SE_PL_BOUND_WATER2", + 0x0057: "NA_SE_PL_BOUND_MAGMA", + 0x0058: "NA_SE_PL_BOUND_GRASS", + 0x0059: "NA_SE_PL_BOUND_IRON", + 0x005A: "NA_SE_PL_BOUND_LADDER", + 0x005B: "NA_SE_PL_BOUND_WOOD", + 0x005C: "NA_SE_PL_DUMMY_92", + 0x005D: "NA_SE_PL_BOUND_HEAVYBOOTS", + 0x005E: "NA_SE_PL_BOUND_SNOW", + 0x005F: "NA_SE_PL_BOUND_ICE", + 0x0060: "NA_SE_PL_BOW_DRAW", + 0x0061: "NA_SE_PL_MEATL_BOOTS_JUMP", + 0x0062: "NA_SE_PL_DUMMY_98", + 0x0063: "NA_SE_PL_FACE_UP", + 0x0064: "NA_SE_PL_DIVE_BUBBLE", + 0x0065: "NA_SE_PL_MOVE_BUBBLE", + 0x0066: "NA_SE_PL_METALEFFECT_KID", + 0x0067: "NA_SE_PL_METALEFFECT_ADULT", + 0x0068: "NA_SE_PL_SPARK", + 0x0069: "NA_SE_PL_PULL_UP_PLANT", + 0x006A: "NA_SE_PL_PULL_UP_ROCK", + 0x006B: "NA_SE_PL_IN_BUBBLE", + 0x006C: "NA_SE_PL_PULL_UP_BIGROCK", + 0x006D: "NA_SE_PL_SWORD_CHARGE", + 0x006E: "NA_SE_PL_FREEZE", + 0x006F: "NA_SE_PL_PULL_UP_POT", + 0x0070: "NA_SE_PL_KNOCK", + 0x0071: "NA_SE_PL_CALM_HIT", + 0x0072: "NA_SE_PL_CALM_PAT", + 0x0073: "NA_SE_PL_SUBMERGE", + 0x0074: "NA_SE_PL_FREEZE_S", + 0x0075: "NA_SE_PL_ICE_BROKEN", + 0x0076: "NA_SE_PL_SLIP_ICE_LELEL", + 0x0077: "NA_SE_PL_PUT_OUT_ITEM", + 0x0078: "NA_SE_PL_PULL_UP_WOODBOX", + 0x0079: "NA_SE_PL_MAGIC_FIRE", + 0x007A: "NA_SE_PL_MAGIC_WIND_NORMAL", + 0x007B: "NA_SE_PL_MAGIC_WIND_WARP", + 0x007C: "NA_SE_PL_MAGIC_SOUL_NORMAL", + 0x007D: "NA_SE_PL_ARROW_CHARGE_FIRE", + 0x007E: "NA_SE_PL_ARROW_CHARGE_ICE", + 0x007F: "NA_SE_PL_ARROW_CHARGE_LIGHT", + 0x0080: "NA_SE_DUMMY_128", + 0x0081: "NA_SE_DUMMY_129", + 0x0082: "NA_SE_DUMMY_130", + 0x0083: "NA_SE_PL_PULL_UP_RUTO", + 0x0084: "NA_SE_DUMMY_132", + 0x0085: "NA_SE_DUMMY_133", + 0x0086: "NA_SE_DUMMY_134", + 0x0087: "NA_SE_DUMMY_135", + 0x0088: "NA_SE_DUMMY_136", + 0x0089: "NA_SE_DUMMY_137", + 0x008A: "NA_SE_DUMMY_138", + 0x008B: "NA_SE_DUMMY_139", + 0x008C: "NA_SE_DUMMY_140", + 0x008D: "NA_SE_DUMMY_141", + 0x008E: "NA_SE_DUMMY_142", + 0x008F: "NA_SE_DUMMY_143", + 0x0090: "NA_SE_DUMMY_144", + 0x0091: "NA_SE_DUMMY_145", + 0x0092: "NA_SE_DUMMY_146", + 0x0093: "NA_SE_DUMMY_147", + 0x0094: "NA_SE_DUMMY_148", + 0x0095: "NA_SE_DUMMY_149", + 0x0096: "NA_SE_DUMMY_150", + 0x0097: "NA_SE_DUMMY_151", + 0x0098: "NA_SE_DUMMY_152", + 0x0099: "NA_SE_DUMMY_153", + 0x009A: "NA_SE_DUMMY_154", + 0x009B: "NA_SE_DUMMY_155", + 0x009C: "NA_SE_DUMMY_156", + 0x009D: "NA_SE_DUMMY_157", + 0x009E: "NA_SE_DUMMY_158", + 0x009F: "NA_SE_DUMMY_159", + 0x00A0: "NA_SE_DUMMY_160", + 0x00A1: "NA_SE_DUMMY_161", + 0x00A2: "NA_SE_DUMMY_162", + 0x00A3: "NA_SE_DUMMY_163", + 0x00A4: "NA_SE_DUMMY_164", + 0x00A5: "NA_SE_DUMMY_165", + 0x00A6: "NA_SE_DUMMY_166", + 0x00A7: "NA_SE_DUMMY_167", + 0x00A8: "NA_SE_DUMMY_168", + 0x00A9: "NA_SE_DUMMY_169", + 0x00AA: "NA_SE_DUMMY_170", + 0x00AB: "NA_SE_DUMMY_171", + 0x00AC: "NA_SE_DUMMY_172", + 0x00AD: "NA_SE_DUMMY_173", + 0x00AE: "NA_SE_DUMMY_174", + 0x00AF: "NA_SE_DUMMY_175", + 0x00B0: "NA_SE_PL_CRAWL", + 0x00B1: "NA_SE_PL_CRAWL_SAND", + 0x00B2: "NA_SE_PL_CRAWL_CONCRETE", + 0x00B3: "NA_SE_PL_CRAWL_DIRT", + 0x00B4: "NA_SE_PL_CRAWL_WATER0", + 0x00B5: "NA_SE_DUMMY_181", + 0x00B6: "NA_SE_DUMMY_182", + 0x00B7: "NA_SE_DUMMY_183", + 0x00B8: "NA_SE_DUMMY_184", + 0x00B9: "NA_SE_DUMMY_185", + 0x00BA: "NA_SE_DUMMY_186", + 0x00BB: "NA_SE_PL_CRAWL_WOOD", + 0x00BC: "NA_SE_DUMMY_188", + 0x00BD: "NA_SE_DUMMY_189", + 0x00BE: "NA_SE_DUMMY_190", + 0x00BF: "NA_SE_PL_CRAWL_ICE", + 0x00C0: "NA_SE_PL_MAGIC_SOUL_FLASH", + 0x00C1: "NA_SE_PL_ROLL_DUST", + 0x00C2: "NA_SE_DUMMY_194", + 0x00C3: "NA_SE_PL_MAGIC_SOUL_BALL", + 0x00C4: "NA_SE_PL_SPIRAL_HEAL_BEAM", + 0x00C5: "NA_SE_PL_BOUND_NOWEAPON", + 0x00C6: "NA_SE_PL_PLANT_GROW_UP", + 0x00C7: "NA_SE_PL_PLANT_TALLER", + 0x00C8: "NA_SE_PL_MAGIC_WIND_VANISH", + 0x00C9: "NA_SE_PL_HOBBERBOOTS_LV", + 0x00CA: "NA_SE_PL_PLANT_MOVE", + 0x00CB: "NA_SE_EV_WALL_MOVE_SP", + 0x00CC: "NA_SE_PL_PLANT_GROW_BIG", + 0x00CD: "NA_SE_PL_TELESCOPE_MOVEMENT", + 0x00CE: "NA_SE_PL_GIANT_WALK", + 0x00CF: "NA_SE_PL_CHIBI_FAIRY_HEAL", + 0x00D0: "NA_SE_PL_SLIP_LEVEL", + 0x00D1: "NA_SE_PL_SLIP_SAND_LEVEL", + 0x00D2: "NA_SE_PL_SLIP_CONCRETE_LEVEL", + 0x00D3: "NA_SE_PL_SLIP_DIRT_LEVEL", + 0x00D4: "NA_SE_PL_SLIP_WATER0_LEVEL", + 0x00D5: "NA_SE_PL_SLIP_WATER1_LEVEL", + 0x00D6: "NA_SE_PL_SLIP_WATER2_LEVEL", + 0x00D7: "NA_SE_PL_SLIP_MAGMA_LEVEL", + 0x00D8: "NA_SE_PL_SLIP_GRASS_LEVEL", + 0x00D9: "NA_SE_PL_SLIP_IRON_LEVEL", + 0x00DA: "NA_SE_PL_SLIP_LADDER_LEVEL", + 0x00DB: "NA_SE_PL_SLIP_GLASS_LEVEL", + 0x00DC: "NA_SE_PL_DUMMY_220", + 0x00DD: "NA_SE_PL_SLIP_HEAVYBOOTS_LEVEL", + 0x00DE: "NA_SE_PL_DUMMY_222", + 0x00DF: "NA_SE_PL_SLIP_ICE_LEVEL", + 0x00E0: "NA_SE_PL_DEKUNUTS_FIRE", + 0x00E1: "NA_SE_PL_GORON_BALLJUMP", + 0x00E2: "NA_SE_PL_DEKUNUTS_IN_GRD", + 0x00E3: "NA_SE_PL_DEKUNUTS_OUT_GRD", + 0x00E4: "NA_SE_PL_TRANSFORM", + 0x00E5: "NA_SE_PL_TRANSFORM_DEMO", + 0x00E6: "NA_SE_PL_GORON_TO_BALL", + 0x00E7: "NA_SE_PL_BALL_TO_GORON", + 0x00E8: "NA_SE_PL_GORON_PUNCH", + 0x00E9: "NA_SE_PL_SINK_ON_SAND", + 0x00EA: "NA_SE_PL_SINK_ON_SNOW", + 0x00EB: "NA_SE_PL_GORON_BALL_CHARGE", + 0x00EC: "NA_SE_PL_ZORA_SWIM_DASH", + 0x00ED: "NA_SE_PL_ZORA_SWIM_LV", + 0x00EE: "NA_SE_PL_ZORA_SWIM_ROLL", + 0x00EF: "NA_SE_PL_GORON_SQUAT", + 0x00F0: "NA_SE_PL_DUMMY_240", + 0x00F1: "NA_SE_PL_DUMMY_241", + 0x00F2: "NA_SE_PL_DUMMY_242", + 0x00F3: "NA_SE_PL_DUMMY_243", + 0x00F4: "NA_SE_PL_DUMMY_244", + 0x00F5: "NA_SE_PL_DUMMY_245", + 0x00F6: "NA_SE_PL_DUMMY_246", + 0x00F7: "NA_SE_PL_DUMMY_247", + 0x00F8: "NA_SE_PL_DUMMY_248", + 0x00F9: "NA_SE_PL_DUMMY_249", + 0x00FA: "NA_SE_PL_DUMMY_250", + 0x00FB: "NA_SE_PL_DUMMY_251", + 0x00FC: "NA_SE_PL_DUMMY_252", + 0x00FD: "NA_SE_PL_DUMMY_253", + 0x00FE: "NA_SE_PL_DUMMY_254", + 0x00FF: "NA_SE_PL_DUMMY_255", + 0x0100: "NA_SE_PL_DUMMY_256", + 0x0101: "NA_SE_PL_DUMMY_257", + 0x0102: "NA_SE_PL_DUMMY_258", + 0x0103: "NA_SE_PL_DUMMY_259", + 0x0104: "NA_SE_PL_DUMMY_260", + 0x0105: "NA_SE_PL_DUMMY_261", + 0x0106: "NA_SE_PL_DUMMY_262", + 0x0107: "NA_SE_PL_DUMMY_263", + 0x0108: "NA_SE_PL_DUMMY_264", + 0x0109: "NA_SE_PL_DUMMY_265", + 0x010A: "NA_SE_PL_DUMMY_266", + 0x010B: "NA_SE_PL_DUMMY_267", + 0x010C: "NA_SE_PL_DUMMY_268", + 0x010D: "NA_SE_PL_DUMMY_269", + 0x010E: "NA_SE_PL_DUMMY_270", + 0x010F: "NA_SE_PL_DUMMY_271", + 0x0110: "NA_SE_PL_DUMMY_272", + 0x0111: "NA_SE_PL_DUMMY_273", + 0x0112: "NA_SE_PL_DUMMY_274", + 0x0113: "NA_SE_PL_DUMMY_275", + 0x0114: "NA_SE_PL_DUMMY_276", + 0x0115: "NA_SE_PL_DUMMY_277", + 0x0116: "NA_SE_PL_DUMMY_278", + 0x0117: "NA_SE_PL_DUMMY_279", + 0x0118: "NA_SE_PL_DUMMY_280", + 0x0119: "NA_SE_PL_DUMMY_281", + 0x011A: "NA_SE_PL_DUMMY_282", + 0x011B: "NA_SE_PL_DUMMY_283", + 0x011C: "NA_SE_PL_DUMMY_284", + 0x011D: "NA_SE_PL_DUMMY_285", + 0x011E: "NA_SE_PL_DUMMY_286", + 0x011F: "NA_SE_PL_DUMMY_287", + 0x0120: "NA_SE_PL_DUMMY_288", + 0x0121: "NA_SE_PL_DUMMY_289", + 0x0122: "NA_SE_PL_DUMMY_290", + 0x0123: "NA_SE_PL_DUMMY_291", + 0x0124: "NA_SE_PL_DUMMY_292", + 0x0125: "NA_SE_PL_DUMMY_293", + 0x0126: "NA_SE_PL_DUMMY_294", + 0x0127: "NA_SE_PL_DUMMY_295", + 0x0128: "NA_SE_PL_DUMMY_296", + 0x0129: "NA_SE_PL_DUMMY_297", + 0x012A: "NA_SE_PL_DUMMY_298", + 0x012B: "NA_SE_PL_DUMMY_299", + 0x012C: "NA_SE_PL_DUMMY_300", + 0x012D: "NA_SE_PL_DUMMY_301", + 0x012E: "NA_SE_PL_DUMMY_302", + 0x012F: "NA_SE_PL_DUMMY_303", + 0x0130: "NA_SE_PL_DUMMY_304", + 0x0131: "NA_SE_PL_DUMMY_305", + 0x0132: "NA_SE_PL_DUMMY_306", + 0x0133: "NA_SE_PL_DUMMY_307", + 0x0134: "NA_SE_PL_DUMMY_308", + 0x0135: "NA_SE_PL_DUMMY_309", + 0x0136: "NA_SE_PL_DUMMY_310", + 0x0137: "NA_SE_PL_DUMMY_311", + 0x0138: "NA_SE_PL_DUMMY_312", + 0x0139: "NA_SE_PL_DUMMY_313", + 0x013A: "NA_SE_PL_DUMMY_314", + 0x013B: "NA_SE_PL_DUMMY_315", + 0x013C: "NA_SE_PL_DUMMY_316", + 0x013D: "NA_SE_PL_DUMMY_317", + 0x013E: "NA_SE_PL_DUMMY_318", + 0x013F: "NA_SE_PL_DUMMY_319", + 0x0140: "NA_SE_PL_DUMMY_320", + 0x0141: "NA_SE_PL_DUMMY_321", + 0x0142: "NA_SE_PL_DUMMY_322", + 0x0143: "NA_SE_PL_DUMMY_323", + 0x0144: "NA_SE_PL_DUMMY_324", + 0x0145: "NA_SE_PL_DUMMY_325", + 0x0146: "NA_SE_PL_DUMMY_326", + 0x0147: "NA_SE_PL_DUMMY_327", + 0x0148: "NA_SE_PL_DUMMY_328", + 0x0149: "NA_SE_PL_DUMMY_329", + 0x014A: "NA_SE_PL_DUMMY_330", + 0x014B: "NA_SE_PL_DUMMY_331", + 0x014C: "NA_SE_PL_DUMMY_332", + 0x014D: "NA_SE_PL_DUMMY_333", + 0x014E: "NA_SE_PL_DUMMY_334", + 0x014F: "NA_SE_PL_DUMMY_335", + 0x0150: "NA_SE_PL_DUMMY_336", + 0x0151: "NA_SE_PL_DUMMY_337", + 0x0152: "NA_SE_PL_DUMMY_338", + 0x0153: "NA_SE_PL_DUMMY_339", + 0x0154: "NA_SE_PL_DUMMY_340", + 0x0155: "NA_SE_PL_DUMMY_341", + 0x0156: "NA_SE_PL_DUMMY_342", + 0x0157: "NA_SE_PL_DUMMY_343", + 0x0158: "NA_SE_PL_DUMMY_344", + 0x0159: "NA_SE_PL_DUMMY_345", + 0x015A: "NA_SE_PL_DUMMY_346", + 0x015B: "NA_SE_PL_DUMMY_347", + 0x015C: "NA_SE_PL_DUMMY_348", + 0x015D: "NA_SE_PL_DUMMY_349", + 0x015E: "NA_SE_PL_DUMMY_350", + 0x015F: "NA_SE_PL_DUMMY_351", + 0x0160: "NA_SE_EV_MARATHONMAN_RISE", + 0x0161: "NA_SE_PL_DUMMY_353", + 0x0162: "NA_SE_PL_DUMMY_354", + 0x0163: "NA_SE_PL_DUMMY_355", + 0x0164: "NA_SE_PL_DUMMY_356", + 0x0165: "NA_SE_PL_DUMMY_357", + 0x0166: "NA_SE_PL_DUMMY_358", + 0x0167: "NA_SE_PL_DUMMY_359", + 0x0168: "NA_SE_PL_DUMMY_360", + 0x0169: "NA_SE_PL_DUMMY_361", + 0x016A: "NA_SE_PL_DUMMY_362", + 0x016B: "NA_SE_PL_DUMMY_363", + 0x016C: "NA_SE_PL_DUMMY_364", + 0x016D: "NA_SE_PL_DUMMY_365", + 0x016E: "NA_SE_PL_DUMMY_366", + 0x016F: "NA_SE_PL_DUMMY_367", + 0x0170: "NA_SE_EV_MARATHONMAN_LAND", + 0x0171: "NA_SE_PL_DUMMY_369", + 0x0172: "NA_SE_PL_DUMMY_370", + 0x0173: "NA_SE_PL_DUMMY_371", + 0x0174: "NA_SE_PL_DUMMY_372", + 0x0175: "NA_SE_PL_DUMMY_373", + 0x0176: "NA_SE_PL_DUMMY_374", + 0x0177: "NA_SE_PL_DUMMY_375", + 0x0178: "NA_SE_PL_DUMMY_376", + 0x0179: "NA_SE_PL_DUMMY_377", + 0x017A: "NA_SE_PL_DUMMY378", + 0x017B: "NA_SE_PL_DUMMY_379", + 0x017C: "NA_SE_PL_DUMMY_380", + 0x017D: "NA_SE_PL_DUMMY_381", + 0x017E: "NA_SE_PL_DUMMY_382", + 0x017F: "NA_SE_PL_DUMMY_383", + 0x0180: "NA_SE_PL_GORON_CHG_ROLL", + 0x0181: "NA_SE_PL_DUMMY_385", + 0x0182: "NA_SE_PL_DUMMY_386", + 0x0183: "NA_SE_PL_DUMMY_387", + 0x0184: "NA_SE_PL_DUMMY_388", + 0x0185: "NA_SE_PL_DUMMY_389", + 0x0186: "NA_SE_PL_DUMMY_390", + 0x0187: "NA_SE_PL_DUMMY_391", + 0x0188: "NA_SE_PL_DUMMY_392", + 0x0189: "NA_SE_PL_DUMMY_393", + 0x018A: "NA_SE_PL_DUMMY_394", + 0x018B: "NA_SE_PL_DUMMY_395", + 0x018C: "NA_SE_PL_DUMMY_396", + 0x018D: "NA_SE_PL_DUMMY_397", + 0x018E: "NA_SE_PL_DUMMY_398", + 0x018F: "NA_SE_PL_GORON_CHG_ROLL_ICE", + 0x0190: "NA_SE_PL_GORON_ROLL", + 0x0191: "NA_SE_PL_DUMMY_401", + 0x0192: "NA_SE_PL_DUMMY_402", + 0x0193: "NA_SE_PL_DUMMY_403", + 0x0194: "NA_SE_PL_DUMMY_404", + 0x0195: "NA_SE_PL_DUMMY_405", + 0x0196: "NA_SE_PL_DUMMY_406", + 0x0197: "NA_SE_PL_DUMMY_407", + 0x0198: "NA_SE_PL_DUMMY_408", + 0x0199: "NA_SE_PL_DUMMY_409", + 0x019A: "NA_SE_PL_DUMMY_410", + 0x019B: "NA_SE_PL_DUMMY_411", + 0x019C: "NA_SE_PL_DUMMY_412", + 0x019D: "NA_SE_PL_DUMMY_413", + 0x019E: "NA_SE_PL_DUMMY_414", + 0x019F: "NA_SE_PL_GORON_ROLL_ICE", + 0x01A0: "NA_SE_PL_DEKUNUTS_BUD", + 0x01A1: "NA_SE_PL_DEKUNUTS_BUBLE_BREATH", + 0x01A2: "NA_SE_PL_GORON_BALL_CHARGE_FAILED", + 0x01A3: "NA_SE_PL_GORON_BALL_CHARGE_DASH", + 0x01A4: "NA_SE_PL_FACE_CHANGE", + 0x01A5: "NA_SE_PL_FACE_UP_S", + 0x01A6: "NA_SE_PL_DEKUNUTS_STRUGGLE", + 0x01A7: "NA_SE_PL_WARP_PLATE", + 0x01A8: "NA_SE_PL_WARP_PLATE_OUT", + 0x01A9: "NA_SE_PL_DEKUNUTS_ATTACK", + 0x01AA: "NA_SE_PL_TRANSFORM_VOICE", + 0x01AB: "NA_SE_PL_FACE_RETURN", + 0x01AC: "NA_SE_PL_DEKUNUTS_DROP_BOMB", + 0x01AD: "NA_SE_PL_GORON_SLIP", + 0x01AE: "NA_SE_PL_ROLL_SNOW_DUST", + 0x01AF: "NA_SE_PL_ZORA_SPARK_BARRIER", + 0x01B0: "NA_SE_PL_DEKUNUTS_JUMP", + 0x01B1: "NA_SE_PL_DEKUNUTS_JUMP2", + 0x01B2: "NA_SE_PL_DEKUNUTS_JUMP3", + 0x01B3: "NA_SE_PL_DEKUNUTS_JUMP4", + 0x01B4: "NA_SE_PL_DEKUNUTS_JUMP5", + 0x01B5: "NA_SE_PL_DEKUNUTS_JUMP6", + 0x01B6: "NA_SE_PL_DEKUNUTS_JUMP7", + 0x01B7: "NA_SE_PL_DEKUNUTS_JUMP8", + 0x01B8: "NA_SE_PL_GORON_STOMACH_EXPLOSION", + 0x01B9: "NA_SE_PL_GORON_DRINK_BOMB", + 0x01BA: "NA_SE_PL_GET_UP", + 0x01BB: "NA_SE_PL_WARP_WING_OPEN", + 0x01BC: "NA_SE_PL_WARP_WING_CLOSE", + 0x01BD: "NA_SE_PL_WARP_WING_ROLL", + 0x01BE: "NA_SE_PL_WARP_WING_VANISH", + 0x01BF: "NA_SE_PL_DEKUNUTS_MISS_FIRE", + 0x01C0: "NA_SE_PL_FLYING_AIR", + 0x01C1: "NA_SE_PL_FIREWORKS", + 0x01C2: "NA_SE_PL_FIREWORKS_DUMMY", + 0x01C3: "NA_SE_PL_PULL_UP_SNOWBALL", + 0x01C4: "NA_SE_PL_WARP_WING_ROLL_2", + 0x01C5: "NA_SE_PL_TRANSFORM_GIANT", + 0x01C6: "NA_SE_PL_TRANSFORM_NORAML", + 0x01C7: "NA_SE_PL_LI_OKARINATORI", + 0x01C8: "NA_SE_PL_LI_FUTTOBI", + 0x01C9: "NA_SE_PL_LI_OP_OKIAGARI", + 0x01CA: "NA_SE_PL_LI_OP_TATIAGARI", + 0x01CB: "NA_SE_PL_JUMP_METAL", + 0x01CC: "NA_SE_PL_LAND_METAL", + 0x01CD: "NA_SE_PL_BOUND_METAL", + 0x01CE: "NA_SE_PL_WALK_WALL", + 0x01CF: "NA_SE_PL_WALK_WALL_DEKU", + 0x1000: "NA_SE_IT_SWORD_IMPACT", + 0x1001: "NA_SE_IT_SWORD_SWING", + 0x1002: "NA_SE_IT_SWORD_PUTAWAY", + 0x1003: "NA_SE_IT_SWORD_PICKOUT", + 0x1004: "NA_SE_IT_ARROW_SHOT", + 0x1005: "NA_SE_IT_BOOMERANG_THROW", + 0x1006: "NA_SE_IT_SHIELD_BOUND", + 0x1007: "NA_SE_IT_BOW_DRAW", + 0x1008: "NA_SE_IT_SHIELD_REFLECT_SW", + 0x1009: "NA_SE_IT_ARROW_STICK_HRAD", + 0x100A: "NA_SE_IT_HAMMER_HIT", + 0x100B: "NA_SE_IT_HOOKSHOT_CHAIN", + 0x100C: "NA_SE_IT_SHIELD_REFLECT_MG", + 0x100D: "NA_SE_IT_BOMB_IGNIT", + 0x100E: "NA_SE_IT_BOMB_EXPLOSION", + 0x100F: "NA_SE_IT_BOMB_UNEXPLOSION", + 0x1010: "NA_SE_IT_BOOMERANG_FLY", + 0x1011: "NA_SE_IT_SWORD_STRIKE", + 0x1012: "NA_SE_IT_HAMMER_SWING", + 0x1013: "NA_SE_IT_HOOKSHOT_REFLECT", + 0x1014: "NA_SE_IT_HOOKSHOT_STICK_CRE", + 0x1015: "NA_SE_IT_ARROW_STICK_OBJ", + 0x1016: "NA_SE_IT_SWORD_SLASH", + 0x1017: "NA_SE_IT_SWORD_SLASH_HARD", + 0x1018: "NA_SE_IT_SWORD_SWING_HARD", + 0x1019: "NA_SE_IT_BOMB_BOUND", + 0x101A: "NA_SE_IT_WALL_HIT_HARD", + 0x101B: "NA_SE_IT_WALL_HIT_SOFT", + 0x101C: "NA_SE_IT_STONE_HIT", + 0x101D: "NA_SE_IT_WOODSTICK_BROKEN", + 0x101E: "NA_SE_IT_LASH", + 0x101F: "NA_SE_IT_SHIELD_SWING", + 0x1020: "NA_SE_IT_SLING_SHOT", + 0x1021: "NA_SE_IT_SLING_DRAW", + 0x1022: "NA_SE_IT_SWORD_CHARGE", + 0x1023: "NA_SE_IT_ROLLING_CUT", + 0x1024: "NA_SE_IT_SWORD_STRIKE_HARD", + 0x1025: "NA_SE_IT_SLING_REFLECT", + 0x1026: "NA_SE_IT_SHIELD_REMOVE", + 0x1027: "NA_SE_IT_HOOKSHOT_READY", + 0x1028: "NA_SE_IT_HOOKSHOT_RECEIVE", + 0x1029: "NA_SE_IT_HOOKSHOT_STICK_OBJ", + 0x102A: "NA_SE_IT_SWORD_REFLECT_MG", + 0x102B: "NA_SE_IT_DEKU", + 0x102C: "NA_SE_IT_WALL_HIT_BUYO", + 0x102D: "NA_SE_IT_SWORD_PUTAWAY_STN", + 0x102E: "NA_SE_IT_ROLLING_CUT_LV1", + 0x102F: "NA_SE_IT_ROLLING_CUT_LV2", + 0x1030: "NA_SE_IT_BOW_FLICK", + 0x1031: "NA_SE_IT_BOMBCHU_MOVE", + 0x1032: "NA_SE_IT_SHIELD_CHARGE_LV1", + 0x1033: "NA_SE_IT_SHIELD_CHARGE_LV2", + 0x1034: "NA_SE_IT_SHIELD_CHARGE_LV3", + 0x1035: "NA_SE_IT_SLING_FLICK", + 0x1036: "NA_SE_IT_SWORD_STICK_STN", + 0x1037: "NA_SE_IT_REFLECTION_WOOD", + 0x1038: "NA_SE_IT_SHIELD_REFLECT_MG2", + 0x1039: "NA_SE_IT_MAGIC_ARROW_SHOT", + 0x103A: "NA_SE_IT_EXPLOSION_FRAME", + 0x103B: "NA_SE_IT_EXPLOSION_ICE", + 0x103C: "NA_SE_IT_EXPLOSION_LIGHT", + 0x103D: "NA_SE_IT_FISHING_REEL_SLOW", + 0x103E: "NA_SE_IT_FISHING_REEL_HIGH", + 0x103F: "NA_SE_IT_PULL_FISHING_ROD", + 0x1040: "NA_SE_IT_DM_FLYING_GOD_PASS", + 0x1041: "NA_SE_IT_DM_FLYING_GOD_DASH", + 0x1042: "NA_SE_IT_DM_RING_EXPLOSION", + 0x1043: "NA_SE_IT_DM_RING_GATHER", + 0x1044: "NA_SE_IT_INGO_HORSE_NEIGH", + 0x1045: "NA_SE_IT_EARTHQUAKE", + 0x1046: "NA_SE_IT_ERUPTION_PILLAR", + 0x1047: "NA_SE_IT_KAKASHI_JUMP", + 0x1048: "NA_SE_IT_FLAME", + 0x1049: "NA_SE_IT_SHIELD_BEAM", + 0x104A: "NA_SE_IT_FISHING_HIT", + 0x104B: "NA_SE_IT_GOODS_APPEAR", + 0x104C: "NA_SE_IT_MAJIN_SWORD_BROKEN", + 0x104D: "NA_SE_IT_HAND_CLAP", + 0x104E: "NA_SE_IT_MASTER_SWORD_SWING", + 0x104F: "NA_SE_IT_GORON_BALLFANG", + 0x1050: "NA_SE_IT_DEKUNUTS_FLOWER_OPEN", + 0x1051: "NA_SE_IT_DEKUNUTS_FLOWER_ROLL", + 0x1052: "NA_SE_IT_DEKUNUTS_FLOWER_CLOSE", + 0x1053: "NA_SE_IT_DEKUNUTS_BUBLE_BROKEN", + 0x1054: "NA_SE_IT_DEKUNUTS_BUBLE_VANISH", + 0x1055: "NA_SE_IT_DEKUNUTS_DROP_BOMB", + 0x1056: "NA_SE_IT_SET_TRANSFORM_MASK", + 0x1057: "NA_SE_IT_GORON_PUNCH_SWING", + 0x1058: "NA_SE_IT_TRANSFORM_MASK_BROKEN", + 0x1059: "NA_SE_IT_ZORA_KICK_SWING", + 0x105A: "NA_SE_IT_DEKUNUTS_BUBLE_SHOT_LEVEL", + 0x105B: "NA_SE_IT_BIG_BOMB_IGNIT", + 0x105C: "NA_SE_IT_BIG_BOMB_EXPLOSION", + 0x105D: "NA_SE_IT_REFLECTION_SNOW", + 0x105E: "NA_SE_IT_GORON_ROLLING_REFLECTION", + 0x105F: "NA_SE_IT_MASK_BOUND_0", + 0x1060: "NA_SE_IT_MASK_BOUND_1", + 0x1061: "NA_SE_IT_MASK_BOUND_SAND", + 0x1062: "NA_SE_IT_REFLECTION_WATER", + 0x1063: "NA_SE_IT_KYOJIN_BEARING", + 0x1064: "NA_SE_FISHING_REEL_SLOW2", + 0x1065: "NA_SE_IT_LURE_LAND1", + 0x1066: "NA_SE_IT_ROD_THROW", + 0x1067: "NA_SE_IT_REFLECT_BOSS", + 0x1068: "NA_SE_IT_SHIELD_SWING_ZORA", + 0x1069: "NA_SE_IT_SHIELD_REMOVE_ZORA", + 0x106A: "NA_SE_IT_BOMB_EXPLOSION2", + 0x106B: "NA_SE_IT_FISHING_REEL_REVERSE", + 0x106C: "NA_SE_IT_FISHING_WORM_BOUND", + 0x106D: "NA_SE_IT_DUMMY_109", + 0x106E: "NA_SE_IT_DUMMY_110", + 0x106F: "NA_SE_IT_DUMMY_111", + 0x2000: "NA_SE_EV_DOOR_OPEN", + 0x2001: "NA_SE_EV_DOOR_CLOSE", + 0x2002: "NA_SE_EV_EXPLOSION", + 0x2003: "NA_SE_EV_HORSE_WALK", + 0x2004: "NA_SE_EV_HORSE_RUN", + 0x2005: "NA_SE_EV_HORSE_NEIGH", + 0x2006: "NA_SE_EV_RIVER_STREAM", + 0x2007: "NA_SE_EV_WATER_WALL_BIG", + 0x2008: "NA_SE_EV_OUT_OF_WATER", + 0x2009: "NA_SE_EV_DIVE_WATER", + 0x200A: "NA_SE_EV_ROCK_SLIDE", + 0x200B: "NA_SE_EV_MAGMA_LEVEL", + 0x200C: "NA_SE_EV_BRIDGE_OPEN", + 0x200D: "NA_SE_EV_BRIDGE_CLOSE", + 0x200E: "NA_SE_EV_BRIDGE_OPEN_STOP", + 0x200F: "NA_SE_EV_BRIDGE_CLOSE_STOP", + 0x2010: "NA_SE_EV_WALL_BROKEN", + 0x2011: "NA_SE_EV_CHICKEN_CRY_N", + 0x2012: "NA_SE_EV_CHICKEN_CRY_A", + 0x2013: "NA_SE_EV_CHICKEN_CRY_M", + 0x2014: "NA_SE_EV_SLIDE_DOOR_OPEN", + 0x2015: "NA_SE_EV_FOOT_SWITCH", + 0x2016: "NA_SE_EV_HORSE_GROAN", + 0x2017: "NA_SE_EV_BOMB_DROP_WATER", + 0x2018: "NA_SE_EV_HORSE_JUMP", + 0x2019: "NA_SE_EV_HORSE_LAND", + 0x201A: "NA_SE_EV_HORSE_SLIP", + 0x201B: "NA_SE_EV_WHITE_FAIRY_DASH", + 0x201C: "NA_SE_EV_SLIDE_DOOR_CLOSE", + 0x201D: "NA_SE_EV_BIGWALL_BOUND", + 0x201E: "NA_SE_EV_STONE_STATUE_OPEN", + 0x201F: "NA_SE_EV_TBOX_UNLOCK", + 0x2020: "NA_SE_EV_TBOX_OPEN", + 0x2021: "NA_SE_SY_TIMER", + 0x2022: "NA_SE_EV_FLAME_IGNITION", + 0x2023: "NA_SE_EV_SPEAR_HIT", + 0x2024: "NA_SE_EV_ELEVATOR_MOVE", + 0x2025: "NA_SE_EV_WARP_HOLE", + 0x2026: "NA_SE_EV_LINK_WARP", + 0x2027: "NA_SE_EV_PILLAR_SINK", + 0x2028: "NA_SE_EV_WATER_WALL", + 0x2029: "NA_SE_EV_RIVER_STREAM_S", + 0x202A: "NA_SE_EV_RIVER_STREAM_F", + 0x202B: "NA_SE_EV_KID_HORSE_LAND2", + 0x202C: "NA_SE_EV_KID_HORSE_SANDDUST", + 0x202D: "NA_SE_EV_DUMMY_45", + 0x202E: "NA_SE_EV_LIGHTNING", + 0x202F: "NA_SE_EV_BOMB_BOUND", + 0x2030: "NA_SE_EV_WATERDROP", + 0x2031: "NA_SE_EV_TORCH", + 0x2032: "NA_SE_EV_MAGMA_LEVEL_M", + 0x2033: "NA_SE_EV_FIRE_PILLAR", + 0x2034: "NA_SE_EV_FIRE_PLATE", + 0x2035: "NA_SE_EV_BLOCK_BOUND", + 0x2036: "NA_SE_EV_METALDOOR_SLIDE", + 0x2037: "NA_SE_EV_METALDOOR_STOP", + 0x2038: "NA_SE_EV_BLOCK_SHAKE", + 0x2039: "NA_SE_EV_BOX_BREAK", + 0x203A: "NA_SE_EV_HAMMER_SWITCH", + 0x203B: "NA_SE_EV_MAGMA_LEVEL_L", + 0x203C: "NA_SE_EV_SPEAR_FENCE", + 0x203D: "NA_SE_EV_WATERDROP_GRD", + 0x203E: "NA_SE_EV_EXPLSION_LONG", + 0x203F: "NA_SE_EV_WATER_WALL_BIG_SILENT", + 0x2040: "NA_SE_EV_DESERT_WARPHOLE", + 0x2041: "NA_SE_EV_FOUNTAIN", + 0x2042: "NA_SE_EV_KID_HORSE_WALK", + 0x2043: "NA_SE_EV_KID_HORSE_RUN", + 0x2044: "NA_SE_EV_KID_HORSE_NEIGH", + 0x2045: "NA_SE_EV_KID_HORSE_GROAN", + 0x2046: "NA_SE_EV_S_STONE_FLASH", + 0x2047: "NA_SE_EV_LIGHT_GATHER", + 0x2048: "NA_SE_EV_TREE_CUT", + 0x2049: "NA_SE_EV_VOLCANO", + 0x204A: "NA_SE_EV_POSTMAN_WALK", + 0x204B: "NA_SE_EV_POSTMACHINE_HIT_OPEN", + 0x204C: "NA_SE_EV_POSTMACHINE_OPEN", + 0x204D: "NA_SE_EV_CHINETRAP_DOWN", + 0x204E: "NA_SE_EV_PLANT_BROKEN", + 0x204F: "NA_SE_EV_STONE_SWITCH_ON", + 0x2050: "NA_SE_EV_FLUTTER_FLAG", + 0x2051: "NA_SE_EV_TRAP_BOUND", + 0x2052: "NA_SE_EV_ROCK_BROKEN", + 0x2053: "NA_SE_EV_FANTOM_WARP_S2", + 0x2054: "NA_SE_EV_FANTOM_WARP_L2", + 0x2055: "NA_SE_EV_COFFIN_CAP_OPEN", + 0x2056: "NA_SE_EV_TRE_BOX_BOUND", + 0x2057: "NA_SE_EV_WIND_TRAP", + 0x2058: "NA_SE_EV_TRAP_OBJ_SLIDE", + 0x2059: "NA_SE_EV_METALDOOR_OPEN", + 0x205A: "NA_SE_EV_METALDOOR_CLOSE", + 0x205B: "NA_SE_EV_BURN_OUT", + 0x205C: "NA_SE_EV_BLOCKSINK", + 0x205D: "NA_SE_EV_CROWD", + 0x205E: "NA_SE_EV_WATER_LEVEL_DOWN", + 0x205F: "NA_SE_EV_NAVY_VANISH", + 0x2060: "NA_SE_EV_STONE_SWITCH_OFF", + 0x2061: "NA_SE_EV_WEB_VIBRATION", + 0x2062: "NA_SE_EV_ICE_STAND_APPEAR", + 0x2063: "NA_SE_EV_ROLL_STAND", + 0x2064: "NA_SE_EV_SEESAW_WATER_BOUND", + 0x2065: "NA_SE_EV_SECOM_CONVEYOR", + 0x2066: "NA_SE_EV_WOODDOOR_OPEN", + 0x2067: "NA_SE_EV_METALGATE_OPEN", + 0x2068: "NA_SE_IT_SCOOP_UP_WATER", + 0x2069: "NA_SE_EV_FISH_LEAP", + 0x206A: "NA_SE_EV_KAKASHI_SWING", + 0x206B: "NA_SE_EV_KAKASHI_ROLL", + 0x206C: "NA_SE_EV_BOTTLE_CAP_OPEN", + 0x206D: "NA_SE_EV_G_STONE_CRUSH", + 0x206E: "NA_SE_EV_KAKASH_LONGI_ROLL", + 0x206F: "NA_SE_EV_SUN_MARK_FLASH", + 0x2070: "NA_SE_EV_FALL_DOWN_DIRT", + 0x2071: "NA_SE_EV_SEESAW_BOUND", + 0x2072: "NA_SE_EV_FAIRY_ATTACK", + 0x2073: "NA_SE_EV_WOOD_HIT", + 0x2074: "NA_SE_EV_SCOOPUP_WATER", + 0x2075: "NA_SE_EV_DROP_FALL", + 0x2076: "NA_SE_EV_WOOD_GEAR", + 0x2077: "NA_SE_EV_TREE_SWING", + 0x2078: "NA_SE_EV_AUTO_DOOR_CLOSE", + 0x2079: "NA_SE_EV_NAVY_FLY_REBIRTH", + 0x207A: "NA_SE_EV_CHAINLIFT_STOP", + 0x207B: "NA_SE_EV_TRE_BOX_APPEAR", + 0x207C: "NA_SE_EV_CHAIN_KEY_UNLOCK", + 0x207D: "NA_SE_EV_SPINE_TRAP_MOVE", + 0x207E: "NA_SE_EV_HEALING", + 0x207F: "NA_SE_EV_GREAT_FAIRY_APPEAR", + 0x2080: "NA_SE_EV_GREAT_FAIRY_VANISH", + 0x2081: "NA_SE_EV_RED_EYE", + 0x2082: "NA_SE_EV_ROLL_STAND_2", + 0x2083: "NA_SE_EV_WALL_SLIDE", + 0x2084: "NA_SE_EV_TRE_BOX_FLASH", + 0x2085: "NA_SE_EV_WINDMILL_LEVEL", + 0x2086: "NA_SE_EV_GOTO_HEAVEN", + 0x2087: "NA_SE_EV_POT_BROKEN", + 0x2088: "NA_SE_PL_PUT_DOWN_POT", + 0x2089: "NA_SE_EV_DIVE_INTO_WATER", + 0x208A: "NA_SE_EV_JUMP_OUT_WATER", + 0x208B: "NA_SE_EV_ICE_PIECE", + 0x208C: "NA_SE_EV_TRIFORCE", + 0x208D: "NA_SE_EV_AURORA", + 0x208E: "NA_SE_EV_CHIBI_FAIRY_SAVED", + 0x208F: "NA_SE_EV_BUYOSTAND_RISING", + 0x2090: "NA_SE_EV_BUYOSTAND_FALL", + 0x2091: "NA_SE_EV_MILK_POT_BROKEN", + 0x2092: "NA_SE_EV_CHAIR_ROLL", + 0x2093: "NA_SE_EV_STONEDOOR_STOP", + 0x2094: "NA_SE_EV_S_STONE_REVIVAL", + 0x2095: "NA_SE_EV_WATER_TANK", + 0x2096: "NA_SE_EV_HUMAN_BOUND", + 0x2097: "NA_SE_EV_TOILET_WATER", + 0x2098: "NA_SE_EV_EARTHQUAKE", + 0x2099: "NA_SE_EV_SWEEP", + 0x209A: "NA_SE_EV_GOD_LIGHTBALL_2", + 0x209B: "NA_SE_EV_RUN_AROUND", + 0x209C: "NA_SE_EV_CONSENTRATION", + 0x209D: "NA_SE_EV_TIMETRIP_LIGHT", + 0x209E: "NA_SE_EV_DOOR_BELL", + 0x209F: "NA_SE_EV_BOUND_ON_MAGMA", + 0x20A0: "NA_SE_EV_HONEYCOMB_FALL", + 0x20A1: "NA_SE_EV_JUMP_CONC", + 0x20A2: "NA_SE_EV_ICE_MELT", + 0x20A3: "NA_SE_EV_FIRE_PILLAR_S", + 0x20A4: "NA_SE_EV_BLOCK_RISING", + 0x20A5: "NA_SE_EV_CHINCLE_SPELL_EFFECT", + 0x20A6: "NA_SE_EV_LINK_WARP_IN", + 0x20A7: "NA_SE_EV_LINK_WARP_OUT", + 0x20A8: "NA_SE_EV_FIATY_HEAL", + 0x20A9: "NA_SE_EV_CHAIN_KEY_UNLOCK_B", + 0x20AA: "NA_SE_EV_WOODBOX_BREAK", + 0x20AB: "NA_SE_EV_PUT_DOWN_WOODBOX", + 0x20AC: "NA_SE_EV_LAND_DIRT", + 0x20AD: "NA_SE_EV_FLOOR_ROLLING", + 0x20AE: "NA_SE_EV_DOG_CRY_EVENING", + 0x20AF: "NA_SE_EV_JABJAB_HICCUP", + 0x20B0: "NA_SE_EV_STICK_SWING", + 0x20B1: "NA_SE_EV_FROG_JUMP", + 0x20B2: "NA_SE_EV_ICE_FREEZE", + 0x20B3: "NA_SE_EV_BURNING", + 0x20B4: "NA_SE_EV_WOODPLATE_BOUND", + 0x20B5: "NA_SE_EV_MOON_CRY", + 0x20B6: "NA_SE_EV_JABJAB_GROAN", + 0x20B7: "NA_SE_EV_WAVE_S", + 0x20B8: "NA_SE_EV_BIGBALL_ROLL", + 0x20B9: "NA_SE_EV_ELEVATOR_MOVE3", + 0x20BA: "NA_SE_EV_DIAMOND_SWITCH", + 0x20BB: "NA_SE_EV_FLAME_OF_FIRE", + 0x20BC: "NA_SE_EV_FISH_GROW_UP", + 0x20BD: "NA_SE_EV_FLYING_AIR", + 0x20BE: "NA_SE_EV_PASS_AIR", + 0x20BF: "NA_SE_EV_COME_UP_DEKU_JR", + 0x20C0: "NA_SE_EV_SAND_STORM", + 0x20C1: "NA_SE_EV_BOILED_WATER_S", + 0x20C2: "NA_SE_EV_GRAVE_EXPLOSION", + 0x20C3: "NA_SE_EV_LURE_MOVE_W", + 0x20C4: "NA_SE_EV_POT_MOVE_START", + 0x20C5: "NA_SE_EV_DIVE_INTO_WATER_L", + 0x20C6: "NA_SE_EV_OUT_OF_WATER_L", + 0x20C7: "NA_SE_EV_BOILED_WATER_L", + 0x20C8: "NA_SE_EV_DIG_UP", + 0x20C9: "NA_SE_EV_WOOD_BOUND", + 0x20CA: "NA_SE_EV_WATER_BUBBLE", + 0x20CB: "NA_SE_EV_ICE_BROKEN", + 0x20CC: "NA_SE_EV_FROG_GROW_UP", + 0x20CD: "NA_SE_EV_WATER_CONVECTION", + 0x20CE: "NA_SE_EV_GROUND_GATE_OPEN", + 0x20CF: "NA_SE_EV_FACE_BREAKDOWN", + 0x20D0: "NA_SE_EV_TOILET_HAND_APPEAR", + 0x20D1: "NA_SE_EV_TOILET_HAND_VANISH", + 0x20D2: "NA_SE_EV_ROUND_TRAP_MOVE", + 0x20D3: "NA_SE_EV_HIT_SOUND", + 0x20D4: "NA_SE_EV_ICE_SWING", + 0x20D5: "NA_SE_EV_DOWN_TO_GROUND", + 0x20D6: "NA_SE_EV_BIG_TORTOISE_SWIM", + 0x20D7: "NA_SE_EV_TORTOISE_WAKE_UP", + 0x20D8: "NA_SE_EV_SMALL_DOG_BARK", + 0x20D9: "NA_SE_EV_RUPY_FALL", + 0x20DA: "NA_SE_EV_RAIN", + 0x20DB: "NA_SE_EV_IRON_DOOR_OPEN", + 0x20DC: "NA_SE_EV_IRON_DOOR_CLOSE", + 0x20DD: "NA_SE_EV_WHIRLPOOL", + 0x20DE: "NA_SE_EV_BIG_TORTOISE_ROLL", + 0x20DF: "NA_SE_EV_COW_CRY", + 0x20E0: "NA_SE_EV_METAL_BOX_BOUND", + 0x20E1: "NA_SE_EV_ELECTRIC_EXPLOSION", + 0x20E2: "NA_SE_EV_HEAVY_THROW", + 0x20E3: "NA_SE_EV_FROG_CRY_0", + 0x20E4: "NA_SE_EV_FROG_CRY_1", + 0x20E5: "NA_SE_EV_COW_CRY_LV", + 0x20E6: "NA_SE_EV_RONRON_DOOR_CLOSE", + 0x20E7: "NA_SE_EV_BUTTERFRY_TO_FAIRY", + 0x20E8: "NA_SE_EV_FIVE_COUNT_LUPY", + 0x20E9: "NA_SE_EV_STONE_GROW_UP", + 0x20EA: "NA_SE_EV_STONE_LAUNCH", + 0x20EB: "NA_SE_EV_STONE_ROLLING", + 0x20EC: "NA_SE_EV_TOGE_STICK_ROLLING", + 0x20ED: "NA_SE_EV_TOWER_ENERGY", + 0x20EE: "NA_SE_EV_MOON_LIGHT_PILLAR", + 0x20EF: "NA_SE_EV_MONKEY_WALK", + 0x20F0: "NA_SE_EV_KNIGHT_WALK", + 0x20F1: "NA_SE_EV_PILLAR_MOVE_STOP", + 0x20F2: "NA_SE_EV_WAVE", + 0x20F3: "NA_SE_EV_BIGBELL", + 0x20F4: "NA_SE_EV_NUTS_BROKEN", + 0x20F5: "NA_SE_EV_SNOWBALL_BROKEN", + 0x20F6: "NA_SE_EV_SMALLBALL_ROLL", + 0x20F7: "NA_SE_EV_FLOWERPETAL_MOVE", + 0x20F8: "NA_SE_EV_FLOWERPETAL_STOP", + 0x20F9: "NA_SE_EV_FLOWER_ROLLING", + 0x20FA: "NA_SE_EV_GLASSBROKEN_IMPACT", + 0x20FB: "NA_SE_EV_GLASSBROKEN_BOUND", + 0x20FC: "NA_SE_EV_BIGBALL_ROLL_SR", + 0x20FD: "NA_SE_EV_SMALL_SNOWBALL_BROKEN", + 0x20FE: "NA_SE_EV_STATUE_VANISH", + 0x20FF: "NA_SE_EV_BIGBALL_BOUND", + 0x2100: "NA_SE_EV_MONKEY_VO_WALK", + 0x2101: "NA_SE_EV_MONKEY_VO_JOY", + 0x2102: "NA_SE_EV_WALK_WATER", + 0x2103: "NA_SE_EV_PLATE_LIFT_LEVEL", + 0x2104: "NA_SE_EV_BIGBALL_ROLL_2", + 0x2105: "NA_SE_EV_BIGBALL_ROLL_SR_2", + 0x2106: "NA_SE_EV_BIGBALL_ROLL_3", + 0x2107: "NA_SE_EV_BIGBALL_ROLL_SR_3", + 0x2108: "NA_SE_EV_BEAVER_SWIM_MOTOR", + 0x2109: "NA_SE_EV_BEAVER_SWIM_HAND", + 0x210A: "NA_SE_EV_SMALL_DOG_CRY", + 0x210B: "NA_SE_EV_SMALL_DOG_GROAN", + 0x210C: "NA_SE_EV_SMALL_DOG_ATK_BARK", + 0x210D: "NA_SE_EV_ICE_PILLAR_RISING", + 0x210E: "NA_SE_EV_ICE_PILLAR_FALL", + 0x210F: "NA_SE_EV_GORON_CHEER", + 0x2110: "NA_SE_EV_SMALL_DOG_ANG_BARK", + 0x2111: "NA_SE_EV_COMICAL_JUMP", + 0x2112: "NA_SE_EV_LIGHTNING_HARD", + 0x2113: "NA_SE_EV_SMALL_DOG_WHINE", + 0x2114: "NA_SE_EV_PANIC_IN_HOUSE", + 0x2115: "NA_SE_EV_CLOCK_TOWER_BELL", + 0x2116: "NA_SE_EV_CLOCK_TOWER_SECOND_HAND", + 0x2117: "NA_SE_EV_SIGNAL_BIGBELL", + 0x2118: "NA_SE_EV_DUMMY_280", + 0x2119: "NA_SE_EV_BEAVER_VOICE_0", + 0x211A: "NA_SE_EV_BEAVER_VOICE_1", + 0x211B: "NA_SE_EV_WATERWHEEL_LEVEL", + 0x211C: "NA_SE_EV_WOOD_GATE_OPEN_N", + 0x211D: "NA_SE_EV_INVISIBLE_MONKEY", + 0x211E: "NA_SE_EV_CRUISER", + 0x211F: "NA_SE_EV_SECRET_CHEER", + 0x2120: "NA_SE_EV_BOTTLE_WATERING", + 0x2121: "NA_SE_EV_MONKEY_VO_SADNESS", + 0x2122: "NA_SE_EV_SNOWSTORM_HARD", + 0x2123: "NA_SE_EV_UNSKILLFUL_OCARINA", + 0x2124: "NA_SE_EV_BLACK_FAIRY_DASH", + 0x2125: "NA_SE_EV_FAIRY_SURPRISE", + 0x2126: "NA_SE_EV_MONDO_SURPRISE", + 0x2127: "NA_SE_EV_SPOT_LIGHT_OPEN", + 0x2128: "NA_SE_EV_HOUSE_BROKEN", + 0x2129: "NA_SE_EV_MOON_FALL", + 0x212A: "NA_SE_EV_OCARINA_BOUND_0", + 0x212B: "NA_SE_EV_OCARINA_BOUND_1", + 0x212C: "NA_SE_EV_BOMBERS_WALK", + 0x212D: "NA_SE_EV_BOMBERS_LAND", + 0x212E: "NA_SE_EV_BOMBERS_SHOT_BREATH", + 0x212F: "NA_SE_EV_BOMBERS_SHOT_EXPLOSUIN", + 0x2130: "NA_SE_EV_BOMBERS_JUMP", + 0x2131: "NA_SE_EV_SOLDIER_WALK", + 0x2132: "NA_SE_EV_ROCK_CUBE_RISING", + 0x2133: "NA_SE_EV_ROCK_CUBE_FALL", + 0x2134: "NA_SE_EV_BELL_SPIT", + 0x2135: "NA_SE_EV_BELL_SIGH", + 0x2136: "NA_SE_EV_BELL_BRAKE", + 0x2137: "NA_SE_EV_DOG_SWIM", + 0x2138: "NA_SE_EV_CHIBI_FAIRY_HEAL_ORG", + 0x2139: "NA_SE_EV_BOMBERS_CLIMB", + 0x213A: "NA_SE_EV_WOODPLATE_BROKEN", + 0x213B: "NA_SE_EV_WATER_LEVEL_DOWN_FIX", + 0x213C: "NA_SE_EV_HONEYCOMB_BROKEN", + 0x213D: "NA_SE_EV_CLOCK_TOWER_UP", + 0x213E: "NA_SE_EV_CLOCK_TOWER_STOP", + 0x213F: "NA_SE_EV_CLOCK_TOWER_FALL", + 0x2140: "NA_SE_EV_CLOCK_TOWER_BOUND_0", + 0x2141: "NA_SE_EV_CLOCK_TOWER_BOUND_1", + 0x2142: "NA_SE_EV_CLOCK_TOWER_BOUND_2", + 0x2143: "NA_SE_EV_STONEDOOR_OPEN_S", + 0x2144: "NA_SE_EV_ICE_MELT_LEVEL", + 0x2145: "NA_SE_EV_CLOCK_TOWER_STAIR_MOVE", + 0x2146: "NA_SE_EV_DUMMY_326", + 0x2147: "NA_SE_EV_OBJECT_STICK", + 0x2148: "NA_SE_EV_CHICK_TO_CHICKEN", + 0x2149: "NA_SE_EV_MUJURA_BALLOON_BROKEN", + 0x214A: "NA_SE_EV_BALLOON_SWELL", + 0x214B: "NA_SE_EV_SEAHORSE_OUT_BOTTLE", + 0x214C: "NA_SE_EV_KYOJIN_VOICE_SUCCESS", + 0x214D: "NA_SE_EV_KYOJIN_VOICE_FAIL", + 0x214E: "NA_SE_EV_KYOJIN_WALK", + 0x214F: "NA_SE_EV_MOON_FALL_LAST", + 0x2150: "NA_SE_EV_EARTHQUAKE_LAST", + 0x2151: "NA_SE_EV_SEAHORSE_SWIM", + 0x2152: "NA_SE_EV_OPEN_AMBRELLA", + 0x2153: "NA_SE_EV_BUTLER_FRY", + 0x2154: "NA_SE_EV_PIRATE_SHIP", + 0x2155: "NA_SE_EV_DRAIN", + 0x2156: "NA_SE_EV_DORA_L", + 0x2157: "NA_SE_EV_LOG_BOUND", + 0x2158: "NA_SE_EV_CART_WHEEL", + 0x2159: "NA_SE_EV_EARTHQUAKE_LAST2", + 0x215A: "NA_SE_EV_DORA_S", + 0x215B: "NA_SE_EV_ROCK_FALL", + 0x215C: "NA_SE_EV_FREEZE_S", + 0x215D: "NA_SE_EV_WOOD_BOUND_S", + 0x215E: "NA_SE_EV_CLOSE_AMBRELLA", + 0x215F: "NA_SE_EV_OBJECT_SLIDE", + 0x2160: "NA_SE_EV_ROLL_AND_FALL", + 0x2161: "NA_SE_EV_GORON_BOUND_0", + 0x2162: "NA_SE_EV_GORON_BOUND_1", + 0x2163: "NA_SE_EV_MONKEY_VO_DAMAGE", + 0x2164: "NA_SE_EV_FORT_RISING", + 0x2165: "NA_SE_EV_MONKEY_VO_REWARD", + 0x2166: "NA_SE_EV_WATER_PURIFICATION", + 0x2167: "NA_SE_EV_OWL_WARP_SWITCH_ON", + 0x2168: "NA_SE_EV_BIG_WATER_WHEEL_RR", + 0x2169: "NA_SE_EV_BIG_WATER_WHEEL_LR", + 0x216A: "NA_SE_EV_SMALL_WATER_WHEEL", + 0x216B: "NA_SE_EV_COCK_SWITCH_ROLL", + 0x216C: "NA_SE_EV_COCK_SWITCH_STOP", + 0x216D: "NA_SE_EV_PIPE_STREAM_START", + 0x216E: "NA_SE_EV_WATER_PILLAR", + 0x216F: "NA_SE_EV_SEESAW_INCLINE", + 0x2170: "NA_SE_EV_ZORA_WALK", + 0x2171: "NA_SE_EV_PIRATE_WALK", + 0x2172: "NA_SE_EV_PILLAR_UP_FAST", + 0x2173: "NA_SE_EV_DUMMY_WATER_WHEEL_RR", + 0x2174: "NA_SE_EV_DUMMY_WATER_WHEEL_LR", + 0x2175: "NA_SE_EV_MUJURA_FOLLOWERS_FLY", + 0x2176: "NA_SE_EV_MAKE_TURRET", + 0x2177: "NA_SE_EV_CHANDELIER_ROLL", + 0x2178: "NA_SE_EV_CHANDELIER_BROKEN", + 0x2179: "NA_SE_EV_SINK_WOOD_FLOOR", + 0x217A: "NA_SE_EV_REBOUND_WOOD_FLOOR", + 0x217B: "NA_SE_EV_UFO_APPEAR", + 0x217C: "NA_SE_EV_UFO_DASH", + 0x217D: "NA_SE_EV_TORNADE", + 0x217E: "NA_SE_EV_MILK_POT_DAMAGE", + 0x217F: "NA_SE_EV_DUMMY_383", + 0x2180: "NA_SE_EV_KYOJIN_SIGN", + 0x2181: "NA_SE_EV_KYOJIN_GRATITUDE0", + 0x2182: "NA_SE_EV_KYOJIN_GRATITUDE1", + 0x2183: "NA_SE_EV_KYOJIN_GRATITUDE2", + 0x2184: "NA_SE_EV_IKANA_DOOR_OPEN", + 0x2185: "NA_SE_EV_IKANA_DOOR_CLOSE", + 0x2186: "NA_SE_EV_MOONSTONE_FALL", + 0x2187: "NA_SE_EV_COMING_FIRE", + 0x2188: "NA_SE_EV_FAIRY_GROUP_FRY", + 0x2189: "NA_SE_EV_FAIRY_GROUP_HEAL", + 0x218A: "NA_SE_EV_WOOD_DOOR_OPEN_SPEEDY", + 0x218B: "NA_SE_EV_PAMERA_WALK", + 0x218C: "NA_SE_EV_G_STONE_CHANGE_COLOR", + 0x218D: "NA_SE_EV_CURTAIN_DOWN", + 0x218E: "NA_SE_EV_GORON_HAND_HIT", + 0x218F: "NA_SE_EV_SMALL_WOODPLATE_BOUND_0", + 0x2190: "NA_SE_EV_GET_UP_ON_BED", + 0x2191: "NA_SE_EV_LIE_DOWN_ON_BED", + 0x2192: "NA_SE_EV_BANK_MAN_HAND_HIT", + 0x2193: "NA_SE_EV_HANKO", + 0x2194: "NA_SE_EV_CHICK_SONG", + 0x2195: "NA_SE_EV_LAND_SAND", + 0x2196: "NA_SE_EV_JUMP_SAND", + 0x2197: "NA_SE_EV_SECRET_LADDER_APPEAR", + 0x2198: "NA_SE_EV_CLAPPING_2P", + 0x2199: "NA_SE_EV_DIVE_INTO_WEED", + 0x219A: "NA_SE_EV_FAIRY_SHIVER", + 0x219B: "NA_SE_EV_MASK_RISING", + 0x219C: "NA_SE_EV_MOON_EYE_FLASH", + 0x219D: "NA_SE_EV_SLIP_MOON", + 0x219E: "NA_SE_EV_FALL_POWER", + 0x219F: "NA_SE_EV_BELL_DASH_NORMAL", + 0x21A0: "NA_SE_EV_IKANA_BLOCK_MOVE_X", + 0x21A1: "NA_SE_EV_IKANA_BLOCK_MOVE_Z", + 0x21A2: "NA_SE_EV_IKANA_BLOCK_MOVE_Y", + 0x21A3: "NA_SE_EV_IKANA_BLOCK_STOP_C", + 0x21A4: "NA_SE_EV_IKANA_BLOCK_STOP_F", + 0x21A5: "NA_SE_EV_BELL_ANGER", + 0x21A6: "NA_SE_EV_IKANA_BLOCK_SWITCH", + 0x21A7: "NA_SE_EV_BAT_FLY", + 0x21A8: "NA_SE_EV_UFO_LIGHT_BEAM", + 0x21A9: "NA_SE_EV_DOOR_UNLOCK", + 0x21AA: "NA_SE_EV_WOOD_WATER_WHEEL", + 0x21AB: "NA_SE_EV_CONVEYOR_SHUTTER_OPEN", + 0x21AC: "NA_SE_EV_CONVEYOR_SHUTTER_CLOSE", + 0x21AD: "NA_SE_EV_ROOM_CARTAIN", + 0x21AE: "NA_SE_EV_ZORA_KIDS_BORN", + 0x21AF: "NA_SE_EV_ZORA_KIDS_SWIM_0", + 0x21B0: "NA_SE_EV_ZORA_KIDS_SWIM_1", + 0x21B1: "NA_SE_EV_MOON_EXPLOSION", + 0x21B2: "NA_SE_EV_RAINBOW", + 0x21B3: "NA_SE_EV_OMENYA_WALK", + 0x21B4: "NA_SE_EV_KYOJIN_GROAN", + 0x21B5: "NA_SE_EV_UFO_FLY", + 0x21B6: "NA_SE_EV_GRASS_WALL_BROKEN", + 0x21B7: "NA_SE_EV_WARP_HOLE_ENERGY", + 0x21B8: "NA_SE_EV_BOSS_WARP_HOLE", + 0x21B9: "NA_SE_EV_FIREWORKS_LAUNCH", + 0x21BA: "NA_SE_EV_IKANA_SOUL_LV", + 0x21BB: "NA_SE_EV_IKANA_PURIFICATION", + 0x21BC: "NA_SE_EV_ZORA_KIDS_SWIM_2", + 0x21BD: "NA_SE_EV_DARUMA_VANISH", + 0x21BE: "NA_SE_EV_IKANA_SOUL_TRANSFORM", + 0x21BF: "NA_SE_EV_ROMANI_BOW_FLICK", + 0x21C0: "NA_SE_EV_WHITE_FAIRY_SHOT_DASH", + 0x21C1: "NA_SE_EV_BLACK_FAIRY_SHOT_DASH", + 0x21C2: "NA_SE_EV_SWORD_FORGE", + 0x21C3: "NA_SE_EV_STONEDOOR_CLOSE_S", + 0x21C4: "NA_SE_EV_BOTTLE_CAP_CLOSE", + 0x21C5: "NA_SE_EV_PAMET_ROCK_CRASH", + 0x21C6: "NA_SE_EV_GUILLOTINE_UP", + 0x21C7: "NA_SE_EV_ROCK_BROKEN2", + 0x21C8: "NA_SE_EV_OBJECT_STICK2", + 0x21C9: "NA_SE_EV_WOODBOX_BOUND2", + 0x21CA: "NA_SE_EV_DEMO_KID_ATOZUSARI", + 0x21CB: "NA_SE_EV_UNDER_WATER", + 0x21CC: "NA_SE_EV_FREEZE2", + 0x21CD: "NA_SE_EV_DEMO_KID_SAGURU", + 0x21CE: "NA_SE_EV_WATER_WALL3", + 0x21CF: "NA_SE_EV_BOMBERS_TAORE", + 0x3000: "NA_SE_EN_DODO_J_WALK", + 0x3001: "NA_SE_EN_DODO_J_CRY", + 0x3002: "NA_SE_EN_DODO_J_FIRE", + 0x3003: "NA_SE_EN_DODO_J_DAMAGE", + 0x3004: "NA_SE_EN_DODO_J_DEAD", + 0x3005: "NA_SE_EN_BAKUO_ROLL", + 0x3006: "NA_SE_EN_MIZUBABA2_VOICE", + 0x3007: "NA_SE_EN_MIZUBABA2_DAMAGE", + 0x3008: "NA_SE_EN_MIBOSS_FALL_OLD_OLD", + 0x3009: "NA_SE_EN_MIBOSS_DAMAGE_OLD", + 0x300A: "NA_SE_EN_MIBOSS_DASH_OLD", + 0x300B: "NA_SE_EN_MIBOSS_DEAD_OLD", + 0x300C: "NA_SE_EN_MIBOSS_GND1_OLD", + 0x300D: "NA_SE_EN_GOMA_DOWN", + 0x300E: "NA_SE_EN_MIBOSS_GND2_OLD", + 0x300F: "NA_SE_EN_MIBOSS_UNARI_OLD", + 0x3010: "NA_SE_EN_MIBOSS_RHYTHM_OLD", + 0x3011: "NA_SE_EN_MIBOSS_SWORD_OLD", + 0x3012: "NA_SE_EN_ANSATSUSYA_ENTRY", + 0x3013: "NA_SE_EN_MIBOSS_JUMP1", + 0x3014: "NA_SE_EN_MIBOSS_JUMP2", + 0x3015: "NA_SE_EN_MIBOSS_VOICE1_OLD", + 0x3016: "NA_SE_EN_MIBOSS_VOICE2_OLD", + 0x3017: "NA_SE_EN_MIBOSS_VOICE3_OLD", + 0x3018: "NA_SE_EN_INBOSS_SAND_OLD", + 0x3019: "NA_SE_EN_INBOSS_ROAR_OLD", + 0x301A: "NA_SE_EN_INBOSS_DAMAGE_OLD", + 0x301B: "NA_SE_EN_COMMON_WEAKENED", + 0x301C: "NA_SE_EN_MIBOSS_FAINT_OLD", + 0x301D: "NA_SE_EN_MIBOSS_ROLLING_OLD", + 0x301E: "NA_SE_EN_MIZUBABA1_DAMAGE", + 0x301F: "NA_SE_EN_MIZUBABA_DEAD", + 0x3020: "NA_SE_EN_DODO_M_CRY", + 0x3021: "NA_SE_EN_DODO_M_DEAD", + 0x3022: "NA_SE_EN_DODO_M_MOVE", + 0x3023: "NA_SE_EN_DODO_M_DOWN", + 0x3024: "NA_SE_EN_DODO_M_UP", + 0x3025: "NA_SE_EN_MIZUBABA_TRANSFORM", + 0x3026: "NA_SE_EN_DODO_M_EAT", + 0x3027: "NA_SE_EN_MIZUBABA2_WALK", + 0x3028: "NA_SE_EN_BOMCHU_WALK", + 0x3029: "NA_SE_EN_RIZA_CRY", + 0x302A: "NA_SE_EN_RIZA_ATTACK", + 0x302B: "NA_SE_EN_RIZA_DAMAGE", + 0x302C: "NA_SE_EN_RIZA_WARAU", + 0x302D: "NA_SE_EN_RIZA_DEAD", + 0x302E: "NA_SE_EN_RIZA_WALK", + 0x302F: "NA_SE_EN_RIZA_JUMP", + 0x3030: "NA_SE_EN_STALKID_WALK", + 0x3031: "NA_SE_EN_STALKID_ATTACK", + 0x3032: "NA_SE_EN_STALKID_DAMAGE", + 0x3033: "NA_SE_EN_STALKID_DEAD", + 0x3034: "NA_SE_EN_FLOORMASTER_SLIDING", + 0x3035: "NA_SE_EN_TEKU_WALK_WATER", + 0x3036: "NA_SE_EN_LIGHT_ARROW_HIT", + 0x3037: "NA_SE_EN_MIZUBABA2_ATTACK", + 0x3038: "NA_SE_EN_STAL_WARAU", + 0x3039: "NA_SE_EN_STAL_SAKEBI", + 0x303A: "NA_SE_EN_STAL_DAMAGE", + 0x303B: "NA_SE_EN_STAL_DEAD", + 0x303C: "NA_SE_EN_WOLFOS_APPEAR", + 0x303D: "NA_SE_EN_STAL_WALK", + 0x303E: "NA_SE_EN_WOLFOS_CRY", + 0x303F: "NA_SE_EN_WOLFOS_ATTACK", + 0x3040: "NA_SE_EN_FFLY_ATTACK", + 0x3041: "NA_SE_EN_FFLY_FLY", + 0x3042: "NA_SE_EN_FFLY_DEAD", + 0x3043: "NA_SE_EN_WOLFOS_DAMAGE", + 0x3044: "NA_SE_EN_AMOS_WALK", + 0x3045: "NA_SE_EN_AMOS_WAVE", + 0x3046: "NA_SE_EN_EYEGOLE_DEAD", + 0x3047: "NA_SE_EN_EYEGOLE_DAMAGE", + 0x3048: "NA_SE_EN_AMOS_VOICE", + 0x3049: "NA_SE_EN_KUSAMUSHI_VIBE", + 0x304A: "NA_SE_EN_BEE_FLY", + 0x304B: "NA_SE_EN_WOLFOS_DEAD", + 0x304C: "NA_SE_EN_COMMON_E_BALL", + 0x304D: "NA_SE_EN_COMMON_THUNDER_THR", + 0x304E: "NA_SE_EN_COMMON_E_BALL_HIT", + 0x304F: "NA_SE_EN_COMMON_ELEC_ARK", + 0x3050: "NA_SE_EN_SUISEN_EAT", + 0x3051: "NA_SE_EN_SUISEN_DEAD", + 0x3052: "NA_SE_EN_COMMON_E_BALL_THR", + 0x3053: "NA_SE_EN_UTSUBO_APPEAR", + 0x3054: "NA_SE_EN_BOMCHU_VOICE", + 0x3055: "NA_SE_EN_BOMCHU_AIM", + 0x3056: "NA_SE_EN_BOMCHU_RUN", + 0x3057: "NA_SE_EN_UTSUBO_BACK", + 0x3058: "NA_SE_EN_DODO_J_BREATH", + 0x3059: "NA_SE_EN_DODO_J_TAIL", + 0x305A: "NA_SE_EN_WOLFOS_WALK", + 0x305B: "NA_SE_EN_DODO_J_EAT", + 0x305C: "NA_SE_EN_DEKU_MOUTH", + 0x305D: "NA_SE_EN_DEKU_ATTACK", + 0x305E: "NA_SE_EN_DEKU_DAMAGE", + 0x305F: "NA_SE_EN_DEKU_DEAD", + 0x3060: "NA_SE_EN_MIZUBABA1_MOUTH", + 0x3061: "NA_SE_EN_MIZUBABA1_ATTACK", + 0x3062: "NA_SE_EN_DEKU_JR_DEAD", + 0x3063: "NA_SE_EN_DEKU_SCRAPE", + 0x3064: "NA_SE_EN_TAIL_FLY", + 0x3065: "NA_SE_EN_TAIL_CRY", + 0x3066: "NA_SE_EN_TAIL_DEAD", + 0x3067: "NA_SE_EN_GOLON_STAND_IMT", + 0x3068: "NA_SE_EN_STALTU_DOWN", + 0x3069: "NA_SE_EN_STALTU_UP", + 0x306A: "NA_SE_EN_STALTU_LAUGH", + 0x306B: "NA_SE_EN_STALTU_DAMAGE", + 0x306C: "NA_SE_EN_TEKU_JUMP", + 0x306D: "NA_SE_EN_TEKU_DAMAGE", + 0x306E: "NA_SE_EN_TEKU_DEAD", + 0x306F: "NA_SE_EN_TEKU_WALK", + 0x3070: "NA_SE_EN_PO_KANTERA", + 0x3071: "NA_SE_EN_PO_FLY", + 0x3072: "NA_SE_EN_PO_AWAY", + 0x3073: "NA_SE_EN_STALKIDS_APPEAR", + 0x3074: "NA_SE_EN_PO_DISAPPEAR", + 0x3075: "NA_SE_EN_PO_DAMAGE", + 0x3076: "NA_SE_EN_PO_DEAD", + 0x3077: "NA_SE_EN_WIZ_DISAPPEAR", + 0x3078: "NA_SE_EN_EXTINCT", + 0x3079: "NA_SE_EN_GOLON_LAND_BIG", + 0x307A: "NA_SE_EN_GERUDOFT_DOWN", + 0x307B: "NA_SE_EN_EYEGOLE_ATTACK", + 0x307C: "NA_SE_EN_NUTS_UP", + 0x307D: "NA_SE_EN_NUTS_DOWN", + 0x307E: "NA_SE_EN_NUTS_THROW", + 0x307F: "NA_SE_EN_NUTS_WALK", + 0x3080: "NA_SE_EN_NUTS_DAMAGE", + 0x3081: "NA_SE_EN_NUTS_DEAD", + 0x3082: "NA_SE_EN_NUT_FAINT", + 0x3083: "NA_SE_EN_PO_BIG_GET", + 0x3084: "NA_SE_EN_STALTU_ROLL", + 0x3085: "NA_SE_EN_STALTU_DEAD", + 0x3086: "NA_SE_EN_PO_SISTER_DEAD", + 0x3087: "NA_SE_EN_BARI_SPLIT", + 0x3088: "NA_SE_EN_LAST1_GROW_HEAD", + 0x3089: "NA_SE_EN_NUTS_VOICE", + 0x308A: "NA_SE_EN_TEKU_LAND_WATER", + 0x308B: "NA_SE_EN_LAST_DAMAGE", + 0x308C: "NA_SE_EN_STALWALL_ROLL", + 0x308D: "NA_SE_EN_STALWALL_DASH", + 0x308E: "NA_SE_EN_TEKU_JUMP_WATER", + 0x308F: "NA_SE_EN_TEKU_LAND_WATER2", + 0x3090: "NA_SE_EN_FALL_AIM", + 0x3091: "NA_SE_EN_FALL_UP", + 0x3092: "NA_SE_EN_FALL_CATCH", + 0x3093: "NA_SE_EN_FALL_LAND", + 0x3094: "NA_SE_EN_FALL_WALK", + 0x3095: "NA_SE_EN_FALL_DAMAGE", + 0x3096: "NA_SE_EN_DAIOCTA_REVERSE", + 0x3097: "NA_SE_EN_KAICHO_FLUTTER", + 0x3098: "NA_SE_EN_BIRI_FLY", + 0x3099: "NA_SE_EN_BIRI_JUMP", + 0x309A: "NA_SE_EN_BIRI_SPARK", + 0x309B: "NA_SE_EN_BIRI_DEAD", + 0x309C: "NA_SE_EN_COMMON_WATER_DEEP", + 0x309D: "NA_SE_EN_BARI_ROLL", + 0x309E: "NA_SE_EN_COMMON_FREEZE", + 0x309F: "NA_SE_EN_BARI_DEAD", + 0x30A0: "NA_SE_EN_BATTA_FLY", + 0x30A1: "NA_SE_EN_BATTA_ATTACK", + 0x30A2: "NA_SE_EN_BATTA_DAMAGE", + 0x30A3: "NA_SE_EN_BATTA_DEAD", + 0x30A4: "NA_SE_EN_WIZ_UNARI", + 0x30A5: "NA_SE_EN_WIZ_RUN", + 0x30A6: "NA_SE_EN_WIZ_VOICE", + 0x30A7: "NA_SE_EN_WIZ_LAUGH", + 0x30A8: "NA_SE_EN_WIZ_ATTACK", + 0x30A9: "NA_SE_EN_WIZ_DAMAGE", + 0x30AA: "NA_SE_EN_WIZ_DEAD", + 0x30AB: "NA_SE_EN_WIZ_EXP", + 0x30AC: "NA_SE_EN_DAIOCTA_DEAD", + 0x30AD: "NA_SE_EN_DAIOCTA_DEAD2", + 0x30AE: "NA_SE_EN_FANTOM_DAMAGE", + 0x30AF: "NA_SE_EN_DAIOCTA_DAMAGE", + 0x30B0: "NA_SE_EN_WIZ_LAUGH2", + 0x30B1: "NA_SE_EN_GOLON_SIT_IMT", + 0x30B2: "NA_SE_EN_FANTOM_VOICE", + 0x30B3: "NA_SE_EN_KAICHO_DAMAGE", + 0x30B4: "NA_SE_EN_GOLON_COLD", + 0x30B5: "NA_SE_EN_GOLON_JUMP", + 0x30B6: "NA_SE_EN_KAICHO_CRY", + 0x30B7: "NA_SE_EN_KAICHO_ATTACK", + 0x30B8: "NA_SE_EN_GOLON_WALK", + 0x30B9: "NA_SE_EN_SLIME_JUMP", + 0x30BA: "NA_SE_EN_SLIME_DAMAGE", + 0x30BB: "NA_SE_EN_SLIME_BREAK", + 0x30BC: "NA_SE_EN_KUROSUKE_MOVE", + 0x30BD: "NA_SE_EN_KUROSUKE_ATTACK", + 0x30BE: "NA_SE_EN_SLIME_DEAD", + 0x30BF: "NA_SE_EN_SLIME_DEFENCE", + 0x30C0: "NA_SE_EN_OCTAROCK_ROCK", + 0x30C1: "NA_SE_EN_COMMON_WATER_SLW", + 0x30C2: "NA_SE_EN_OCTAROCK_JUMP", + 0x30C3: "NA_SE_EN_DAIOCTA_LAND", + 0x30C4: "NA_SE_EN_DAIOCTA_SINK", + 0x30C5: "NA_SE_EN_COMMON_WATER_MID", + 0x30C6: "NA_SE_EN_OCTAROCK_DEAD1", + 0x30C7: "NA_SE_EN_OCTAROCK_DEAD2", + 0x30C8: "NA_SE_EN_BUBLE_WING", + 0x30C9: "NA_SE_EN_BUBLE_MOUTH", + 0x30CA: "NA_SE_EN_BUBLE_LAUGH", + 0x30CB: "NA_SE_EN_BUBLE_BITE", + 0x30CC: "NA_SE_EN_BUBLE_UP", + 0x30CD: "NA_SE_EN_BUBLE_DOWN", + 0x30CE: "NA_SE_EN_BUBLE_DEAD", + 0x30CF: "NA_SE_EN_BUBLEFALL_FIRE", + 0x30D0: "NA_SE_EN_UTSUBO_DEAD", + 0x30D1: "NA_SE_EN_UTSUBO_DAMAGE", + 0x30D2: "NA_SE_EN_FROG_REAL", + 0x30D3: "NA_SE_EN_FROG_DAMAGE", + 0x30D4: "NA_SE_EN_B_SLIME_EAT", + 0x30D5: "NA_SE_EN_B_SLIME_LAUGH", + 0x30D6: "NA_SE_EN_FROG_DEAD", + 0x30D7: "NA_SE_EN_UTSUBO_BITE", + 0x30D8: "NA_SE_EN_B_SLIME_REVERSE", + 0x30D9: "NA_SE_EN_SLIME_JUMP1", + 0x30DA: "NA_SE_EN_SLIME_JUMP2", + 0x30DB: "NA_SE_EN_B_SLIME_BREAK", + 0x30DC: "NA_SE_EN_BARI_DAMAGE", + 0x30DD: "NA_SE_EN_HIPLOOP_LAND", + 0x30DE: "NA_SE_EN_MOFER_CORE_MOVE_WT", + 0x30DF: "NA_SE_EN_MOFER_CORE_SMJUMP", + 0x30E0: "NA_SE_EN_MONBLIN_GNDWAVE", + 0x30E1: "NA_SE_EN_MONBLIN_HAM_DOWN", + 0x30E2: "NA_SE_EN_MONBLIN_HAM_UP", + 0x30E3: "NA_SE_EN_BUBLE_DAMAGE", + 0x30E4: "NA_SE_EN_REDEAD_CRY", + 0x30E5: "NA_SE_EN_REDEAD_AIM", + 0x30E6: "NA_SE_EN_REDEAD_DAMAGE", + 0x30E7: "NA_SE_EN_REDEAD_DEAD", + 0x30E8: "NA_SE_EN_REDEAD_ATTACK", + 0x30E9: "NA_SE_EN_GOLON_KID_SOB", + 0x30EA: "NA_SE_EN_GOLON_KID_CRY", + 0x30EB: "NA_SE_EN_KAICHO_DEAD", + 0x30EC: "NA_SE_EN_PO_LAUGH", + 0x30ED: "NA_SE_EN_PO_CRY", + 0x30EE: "NA_SE_EN_PO_ROLL", + 0x30EF: "NA_SE_EN_PO_LAUGH2", + 0x30F0: "NA_SE_EN_GOLON_ROLLING", + 0x30F1: "NA_SE_EN_GOLON_READY", + 0x30F2: "NA_SE_EN_GOLON_DASH", + 0x30F3: "NA_SE_EN_PAMET_VOICE", + 0x30F4: "NA_SE_EN_PAMET_ROLL", + 0x30F5: "NA_SE_EN_PAMET_WALK", + 0x30F6: "NA_SE_EN_PAMET_ROAR", + 0x30F7: "NA_SE_EN_PAMET_WAKEUP", + 0x30F8: "NA_SE_EN_PAMET_REVERSE", + 0x30F9: "NA_SE_EN_PAMET_DAMAGE", + 0x30FA: "NA_SE_EN_PAMET_DEAD", + 0x30FB: "NA_SE_EN_BAKUO_VOICE", + 0x30FC: "NA_SE_EN_GOLON_WAKE_UP", + 0x30FD: "NA_SE_EN_GOLON_SIT_DOWN", + 0x30FE: "NA_SE_EN_DAIGOLON_SLEEP3", + 0x30FF: "NA_SE_EN_CHICKEN_FLUTTER", + 0x3100: "NA_SE_EN_KOUME_ILL", + 0x3101: "NA_SE_EN_KOUME_REGAIN", + 0x3102: "NA_SE_EN_KOUME_DRINK", + 0x3103: "NA_SE_EN_KOUME_LAUGH", + 0x3104: "NA_SE_EN_KOUME_FLY", + 0x3105: "NA_SE_EN_KOUME_AWAY", + 0x3106: "NA_SE_EN_KOUME_MAGIC", + 0x3107: "NA_SE_EN_DAIGOLON_SLEEP2", + 0x3108: "NA_SE_EN_STALKIDS_JUMP", + 0x3109: "NA_SE_EN_STALKIDS_FADEOUT", + 0x310A: "NA_SE_EN_STALKIDS_LAUGH", + 0x310B: "NA_SE_EN_STALKIDS_SHAKEHEAD", + 0x310C: "NA_SE_EN_STALKIDS_ONGND", + 0x310D: "NA_SE_EN_STALKIDS_SURPRISED", + 0x310E: "NA_SE_EN_STALKIDS_WALK", + 0x310F: "NA_SE_EN_STALKIDS_REVERSE", + 0x3110: "NA_SE_EN_STALKIDS_FLOAT", + 0x3111: "NA_SE_EN_EYEGOLE_EYE", + 0x3112: "NA_SE_EN_STALKIDS_CAUGHT", + 0x3113: "NA_SE_EN_STALKIDS_MASK_ON", + 0x3114: "NA_SE_EN_TWINROBA_CUTBODY", + 0x3115: "NA_SE_EN_STALKIDS_MASK_OFF", + 0x3116: "NA_SE_EN_STALKIDS_RIDE", + 0x3117: "NA_SE_EN_DEKNUTS_DANCE", + 0x3118: "NA_SE_EN_DEKNUTS_DANCE1", + 0x3119: "NA_SE_EN_DEKNUTS_DANCE2", + 0x311A: "NA_SE_EN_DEKNUTS_DANCE_BIG", + 0x311B: "NA_SE_EN_EYEGOLE_BEAM", + 0x311C: "NA_SE_EN_GOLON_EYE_BIG", + 0x311D: "NA_SE_EN_GOLON_GOOD_BIG", + 0x311E: "NA_SE_EN_STALKIDS_LAUGH_MID", + 0x311F: "NA_SE_EN_STALKIDS_FLOAT_COPY", + 0x3120: "NA_SE_EN_STALKIDS_TURN", + 0x3121: "NA_SE_EN_STALKIDS_DAMAGE", + 0x3122: "NA_SE_EN_STALKIDS_SCREAM", + 0x3123: "NA_SE_EN_STALKIDS_OTEDAMA2", + 0x3124: "NA_SE_EN_STALKIDS_STRETCH", + 0x3125: "NA_SE_EN_STALKIDS_LAUGH_MD2", + 0x3126: "NA_SE_EN_OWL_FLUTTER", + 0x3127: "NA_SE_EN_VALVAISA_LAND", + 0x3128: "NA_SE_EN_IRONNACK_WALK", + 0x3129: "NA_SE_EN_IRONNACK_SWING_AXE", + 0x312A: "NA_SE_EN_STALKIDS_OTEDAMA1", + 0x312B: "NA_SE_EN_PAMET_CUTTER_ON", + 0x312C: "NA_SE_EN_IRONNACK_ARMOR_OFF_DEMO", + 0x312D: "NA_SE_EN_PAMET_CUTTER_OFF", + 0x312E: "NA_SE_EN_B_SLIME_JUMP1", + 0x312F: "NA_SE_EN_B_SLIME_JUMP2", + 0x3130: "NA_SE_EN_FLOORMASTER_ATTACK", + 0x3131: "NA_SE_EN_FLOORMASTER_SM_WALK", + 0x3132: "NA_SE_EN_FLOORMASTER_SM_DEAD", + 0x3133: "NA_SE_EN_FLOORMASTER_RESTORE", + 0x3134: "NA_SE_EN_FLOORMASTER_EXPAND", + 0x3135: "NA_SE_EN_KUSAMUSHI_HIDE", + 0x3136: "NA_SE_EN_FLOORMASTER_SM_STICK", + 0x3137: "NA_SE_EN_FLOORMASTER_SM_LAND", + 0x3138: "NA_SE_EN_B_SLIME_COMBINE", + 0x3139: "NA_SE_EN_B_SLIME_PUNCH_MOVE", + 0x313A: "NA_SE_EN_IRONNACK_ARMOR_HIT", + 0x313B: "NA_SE_EN_CUTBODY", + 0x313C: "NA_SE_EN_LAST1_TRANSFORM", + 0x313D: "NA_SE_EN_LAST1_DEMO_BREAK", + 0x313E: "NA_SE_EN_LAST1_DEMO_WALL", + 0x313F: "NA_SE_EN_B_PAMET_BREAK", + 0x3140: "NA_SE_EN_KONB_DEMO_MOVE_OLD", + 0x3141: "NA_SE_EN_KONB_JUMP_OLD", + 0x3142: "NA_SE_EN_KONB_SINK_OLD", + 0x3143: "NA_SE_EN_UTSUBO_EAT", + 0x3144: "NA_SE_EN_YMAJIN_HOLD_SNOW", + 0x3145: "NA_SE_EN_KONB_DAMAGE_OLD", + 0x3146: "NA_SE_EN_KONB_DEAD_OLD", + 0x3147: "NA_SE_EN_KONB_BOUND_OLD", + 0x3148: "NA_SE_EN_AWA_BOUND", + 0x3149: "NA_SE_EN_AWA_BREAK", + 0x314A: "NA_SE_EN_ICEB_FOOTSTEP_OLD", + 0x314B: "NA_SE_EN_COMMON_THUNDER", + 0x314C: "NA_SE_EN_ICEB_CRY_OLD", + 0x314D: "NA_SE_EN_ICEB_STEAM_LONG_OLD", + 0x314E: "NA_SE_EN_ICEB_STEAMS_DEMO_OLD", + 0x314F: "NA_SE_EN_ICEB_STEAM_DEMO_UP_OLD", + 0x3150: "NA_SE_EN_ICEB_DEAD_OLD", + 0x3151: "NA_SE_EN_ICEB_DAMAGE_OLD", + 0x3152: "NA_SE_EN_KONB_INIT_OLD", + 0x3153: "NA_SE_EN_KONB_DEAD2_OLD", + 0x3154: "NA_SE_EN_PIHAT_UP", + 0x3155: "NA_SE_EN_PIHAT_FLY", + 0x3156: "NA_SE_EN_PIHAT_DAMAGE", + 0x3157: "NA_SE_EN_PIHAT_LAND", + 0x3158: "NA_SE_EN_KONB_BOUND2_OLD", + 0x3159: "NA_SE_EN_KONB_DEAD_JUMP_OLD", + 0x315A: "NA_SE_EN_KONB_DEAD_JUMP2_OLD", + 0x315B: "NA_SE_EN_FROG_JUMP", + 0x315C: "NA_SE_EN_FROG_GREET", + 0x315D: "NA_SE_EN_FROG_HOLD_SLIME", + 0x315E: "NA_SE_EN_FROG_THROW_SLIME", + 0x315F: "NA_SE_EN_FROG_JUMP_MID", + 0x3160: "NA_SE_EN_KONB_BITE_OLD", + 0x3161: "NA_SE_EN_FROG_PUNCH1", + 0x3162: "NA_SE_EN_FROG_PUNCH2", + 0x3163: "NA_SE_EN_UTSUBO_APPEAR_TRG", + 0x3164: "NA_SE_EN_FROG_DOWN", + 0x3165: "NA_SE_EN_FROG_JUMP_ABOVE", + 0x3166: "NA_SE_EN_FROG_KICK", + 0x3167: "NA_SE_EN_YMAJIN_MINI_HOLD", + 0x3168: "NA_SE_EN_YMAJIN_MINI_THROW", + 0x3169: "NA_SE_EN_YMAJIN_MOVE", + 0x316A: "NA_SE_EN_YMAJIN_MINI_MOVE", + 0x316B: "NA_SE_EN_YMAJIN_SURFACE", + 0x316C: "NA_SE_EN_YMAJIN_HIDE", + 0x316D: "NA_SE_EN_YMAJIN_SPLIT", + 0x316E: "NA_SE_EN_YMAJIN_UNITE", + 0x316F: "NA_SE_EN_YMAJIN_DEAD_BREAK", + 0x3170: "NA_SE_EN_BIMOS_ROLL_HEAD", + 0x3171: "NA_SE_EN_BIMOS_LAZER", + 0x3172: "NA_SE_EN_BIMOS_LAZER_GND", + 0x3173: "NA_SE_EN_BIMOS_AIM", + 0x3174: "NA_SE_EN_BUBLEWALK_WALK", + 0x3175: "NA_SE_EN_BUBLEWALK_AIM", + 0x3176: "NA_SE_EN_BUBLEWALK_REVERSE", + 0x3177: "NA_SE_EN_BUBLEWALK_DAMAGE", + 0x3178: "NA_SE_EN_BUBLEWALK_DEAD", + 0x3179: "NA_SE_EN_HIPLOOP_RUN", + 0x317A: "NA_SE_EN_HIPLOOP_PAUSE", + 0x317B: "NA_SE_EN_HIPLOOP_MASC_OFF", + 0x317C: "NA_SE_EN_HIPLOOP_FOOT", + 0x317D: "NA_SE_EN_HIPLOOP_DAMAGE", + 0x317E: "NA_SE_EN_HIPLOOP_DEAD", + 0x317F: "NA_SE_EN_HIPLOOP_FOOTSTEP", + 0x3180: "NA_SE_EN_DEKUHIME_WALK", + 0x3181: "NA_SE_EN_DEKUHIME_TURN", + 0x3182: "NA_SE_EN_DEKUHIME_GREET", + 0x3183: "NA_SE_EN_DEKUHIME_GREET2", + 0x3184: "NA_SE_EN_PIHAT_SM_FLY", + 0x3185: "NA_SE_EN_PIHAT_SM_DEAD", + 0x3186: "NA_SE_EN_STALKID_APPEAR", + 0x3187: "NA_SE_EN_AKINDONUTS_HIDE", + 0x3188: "NA_SE_EN_RIVA_DAMAGE", + 0x3189: "NA_SE_EN_RIVA_DEAD", + 0x318A: "NA_SE_EN_RIVA_MOVE", + 0x318B: "NA_SE_EN_DEKUHIME_VOICE_SAD", + 0x318C: "NA_SE_EN_DEKUHIME_VOICE_JOY", + 0x318D: "NA_SE_EN_NUTS_JUMP", + 0x318E: "NA_SE_EN_NUTS_CLOTHES", + 0x318F: "NA_SE_EN_SITSUJI_VOICE", + 0x3190: "NA_SE_EN_LIKE_WALK", + 0x3191: "NA_SE_EN_LIKE_UNARI", + 0x3192: "NA_SE_EN_SUISEN_DRINK", + 0x3193: "NA_SE_EN_EYEGOLE_DEMO_EYE", + 0x3194: "NA_SE_EN_SUISEN_THROW", + 0x3195: "NA_SE_EN_LIKE_DAMAGE", + 0x3196: "NA_SE_EN_LIKE_DEAD", + 0x3197: "NA_SE_EN_MGANON_SWORD", + 0x3198: "NA_SE_EN_PIRATE_ATTACK", + 0x3199: "NA_SE_EN_PIRATE_DAMAGE", + 0x319A: "NA_SE_EN_PIRATE_DEAD", + 0x319B: "NA_SE_EN_MB_MOTH_FLY", + 0x319C: "NA_SE_EN_MB_MOTH_DEAD", + 0x319D: "NA_SE_EN_MB_INSECT_WALK", + 0x319E: "NA_SE_EN_B_PAMET_ROLL", + 0x319F: "NA_SE_EN_FROG_VOICE1", + 0x31A0: "NA_SE_EN_GERUDOFT_WALK", + 0x31A1: "NA_SE_EN_FROG_VOICE2", + 0x31A2: "NA_SE_EN_B_PAMET_VOICE", + 0x31A3: "NA_SE_EN_B_PAMET_REVERSE", + 0x31A4: "NA_SE_EN_FREEZAD_BREATH", + 0x31A5: "NA_SE_EN_FREEZAD_DAMAGE", + 0x31A6: "NA_SE_EN_FREEZAD_DEAD", + 0x31A7: "NA_SE_EN_DEKUHIMA_VOICE_HURY", + 0x31A8: "NA_SE_EN_KINGNUTS_VOICE", + 0x31A9: "NA_SE_EN_FROG_RUNAWAY", + 0x31AA: "NA_SE_EN_LAST3_DEAD_DEAD1_OLD", + 0x31AB: "NA_SE_EN_LAST3_DEAD_DEAD2_OLD", + 0x31AC: "NA_SE_EN_FROG_RUNAWAY2", + 0x31AD: "NA_SE_EN_DAIGOLON_SLEEP1", + 0x31AE: "NA_SE_EN_IRONNACK_HIT_GND", + 0x31AF: "NA_SE_EN_LAST3_DEAD_WIND1_OLD", + 0x31B0: "NA_SE_EN_TWINROBA_LAUGH", + 0x31B1: "NA_SE_EN_TWINROBA_LAUGH2", + 0x31B2: "NA_SE_EN_IRONNACK_PULLOUT", + 0x31B3: "NA_SE_EN_TWINROBA_SHOOT_VOICE", + 0x31B4: "NA_SE_EN_LAST3_DEAD_WIND2_OLD", + 0x31B5: "NA_SE_EN_LAST3_DEAD_WIND3_OLD", + 0x31B6: "NA_SE_EN_LAST3_DEAD_LIGHTS_OLD", + 0x31B7: "NA_SE_EN_PIRATE_BREATH", + 0x31B8: "NA_SE_EN_LAST3_DEAD_ROD", + 0x31B9: "NA_SE_EN_LAST2_SHOUT", + 0x31BA: "NA_SE_EN_LAST2_PUMP_UP_OLD", + 0x31BB: "NA_SE_EN_LAST2_GROW_HEAD_OLD", + 0x31BC: "NA_SE_EN_LAST2_HEARTBEAT_OLD", + 0x31BD: "NA_SE_EN_ANSATSUSYA_MOVING", + 0x31BE: "NA_SE_EN_ANSATSUSYA_DASH_2", + 0x31BF: "NA_SE_EN_LAST3_DEAD_FLOAT", + 0x31C0: "NA_SE_EN_ANSATSUSYA_CRYING", + 0x31C1: "NA_SE_EN_ANSATSUSYA_SKIP", + 0x31C2: "NA_SE_EN_STALTURA_APPEAR", + 0x31C3: "NA_SE_EN_ANSATSUSYA_JUMP", + 0x31C4: "NA_SE_EN_ANSATSUSYA_FALL", + 0x31C5: "NA_SE_EN_ANSATSUSYA_DAMAGE", + 0x31C6: "NA_SE_EN_ANSATSUSYA_DEAD", + 0x31C7: "NA_SE_EN_ANSATSUSYA_SWORD", + 0x31C8: "NA_SE_EN_BAKUO_DEAD", + 0x31C9: "NA_SE_EN_BAKUO_APPEAR", + 0x31CA: "NA_SE_EN_LAST3_ROD_WIND_OLD", + 0x31CB: "NA_SE_EN_LAST3_ROD_FLOOR_OLD", + 0x31CC: "NA_SE_EN_LAST3_ROD_DANCE_OLD", + 0x31CD: "NA_SE_EN_LAST3_ROD_HOP_OLD", + 0x31CE: "NA_SE_EN_LAST3_ROD_HOP2_OLD", + 0x31CF: "NA_SE_EN_GANON_RESTORE", + 0x31D0: "NA_SE_EN_GOLON_CIRCLE", + 0x31D1: "NA_SE_EN_GOLON_CIRCLE_OFF", + 0x31D2: "NA_SE_EN_LAST1_BLOW_OLD", + 0x31D3: "NA_SE_EN_LAST1_BEAM_OLD", + 0x31D4: "NA_SE_EN_LAST1_ATTACK_OLD", + 0x31D5: "NA_SE_EN_LAST1_DAMAGE1_OLD", + 0x31D6: "NA_SE_EN_LAST1_DAMAGE2_OLD", + 0x31D7: "NA_SE_EN_LAST1_FALL_OLD", + 0x31D8: "NA_SE_EN_MGANON_STAND", + 0x31D9: "NA_SE_EN_LAST2_FIRE_OLD", + 0x31DA: "NA_SE_EN_STALGOLD_ROLL", + 0x31DB: "NA_SE_EN_LAST2_WALK_OLD", + 0x31DC: "NA_SE_EN_LAST2_WAIT_OLD", + 0x31DD: "NA_SE_EN_LAST2_JUMP_OLD", + 0x31DE: "NA_SE_EN_LAST2_BIRD_OLD", + 0x31DF: "NA_SE_EN_LAST2_BIRD2_OLD", + 0x31E0: "NA_SE_EN_STALTU_WAVE", + 0x31E1: "NA_SE_EN_STALTU_DOWN_SET", + 0x31E2: "NA_SE_EN_DEKU_WAKEUP", + 0x31E3: "NA_SE_EN_LAST2_WALK2_OLD", + 0x31E4: "NA_SE_EN_LAST1_FLOAT_OLD", + 0x31E5: "NA_SE_EN_LAST1_ATTACK_2ND_OLD", + 0x31E6: "NA_SE_EN_LAST1_ROLLING_OLD", + 0x31E7: "NA_SE_EN_LAST3_GET_LINK_OLD", + 0x31E8: "NA_SE_EN_PO_BIG_CRY", + 0x31E9: "NA_SE_EN_STALTURA_BOUND", + 0x31EA: "NA_SE_EN_STALGOLD_UP_CRY", + 0x31EB: "NA_SE_EN_GOLON_CRY", + 0x31EC: "NA_SE_EN_LAST3_ROD_SOFT", + 0x31ED: "NA_SE_EN_LAST3_ROD_MID_OLD", + 0x31EE: "NA_SE_EN_RIVA_BIG_APPEAR", + 0x31EF: "NA_SE_EN_LAST3_ROD_HARD", + 0x31F0: "NA_SE_EN_MUSI_WALK", + 0x31F1: "NA_SE_EN_LAST3_COIL_ATTACK_OLD", + 0x31F2: "NA_SE_EN_STALWALL_LAUGH", + 0x31F3: "NA_SE_EN_PIRANHA_EXIST", + 0x31F4: "NA_SE_EN_PIRANHA_ATTACK", + 0x31F5: "NA_SE_EN_PIRANHA_DEAD", + 0x31F6: "NA_SE_EN_KINGNUTS_DAMAGE", + 0x31F7: "NA_SE_EN_COMMON_DEADLIGHT", + 0x31F8: "NA_SE_EN_GOLONKID_WALK", + 0x31F9: "NA_SE_EN_YMAJIN_MINI_DAMAGE", + 0x31FA: "NA_SE_EN_YMAJIN_DAMAGE", + 0x31FB: "NA_SE_EN_KOTAKE_SURPRISED", + 0x31FC: "NA_SE_EN_HANDW_GET", + 0x31FD: "NA_SE_EN_HANDW_RELEASE", + 0x31FE: "NA_SE_EN_SLIME_SURFACE", + 0x31FF: "NA_SE_EN_KOTAKE_SLEEP", + 0x3200: "NA_SE_EN_KOTAKE_SURPRISED2", + 0x3201: "NA_SE_EN_NEMURI_SLEEP", + 0x3202: "NA_SE_EN_LAST1_DEAD_OLD", + 0x3203: "NA_SE_EN_GOLON_SIRLOIN_ROLL", + 0x3204: "NA_SE_EN_GOLON_VOICE_EATFULL", + 0x3205: "NA_SE_EN_GOLON_SIRLOIN_EAT", + 0x3206: "NA_SE_EN_EYEGOLE_WALK", + 0x3207: "NA_SE_EN_EYEGOLE_STAND", + 0x3208: "NA_SE_EN_EYEGOLE_SIT", + 0x3209: "NA_SE_EN_INVADER_DEAD", + 0x320A: "NA_SE_EN_FOLLOWERS_BEAM_PRE", + 0x320B: "NA_SE_EN_FOLLOWERS_BEAM", + 0x320C: "NA_SE_EN_FOLLOWERS_DAMAGE", + 0x320D: "NA_SE_EN_FOLLOWERS_DEAD", + 0x320E: "NA_SE_EN_INBOSS_DEAD_PRE2_OLD", + 0x320F: "NA_SE_EN_IKURA_JUMP1", + 0x3210: "NA_SE_EN_IKURA_JUMP2", + 0x3211: "NA_SE_EN_IKURA_DAMAGE", + 0x3212: "NA_SE_EN_IKURA_DEAD", + 0x3213: "NA_SE_EN_ME_DAMAGE", + 0x3214: "NA_SE_EN_ME_DEAD", + 0x3215: "NA_SE_EN_ME_EXIST", + 0x3216: "NA_SE_EN_ME_ATTACK", + 0x3217: "NA_SE_EN_GOLONKID_SOB_TALK", + 0x3218: "NA_SE_EN_GOLONKID_YAWN", + 0x3219: "NA_SE_EN_GOLONKID_SNORE", + 0x321A: "NA_SE_EN_GOLON_SNORE1", + 0x321B: "NA_SE_EN_GOLON_SNORE2", + 0x321C: "NA_SE_EN_BUBLEFALL_APPEAR", + 0x321D: "NA_SE_EN_INBOSS_DEAD_OLD", + 0x321E: "NA_SE_EN_LAST1_BEAM2_OLD", + 0x321F: "NA_SE_EN_COMMON_EXTINCT_LEV", + 0x3220: "NA_SE_EN_BOSU_HEAD_MID", + 0x3221: "NA_SE_EN_BOSU_HEAD_SHORT", + 0x3222: "NA_SE_EN_DEBU_HEAD_MID", + 0x3223: "NA_SE_EN_DEBU_HEAD_SHORT", + 0x3224: "NA_SE_EN_YASE_HEAD_MID", + 0x3225: "NA_SE_EN_YASE_HEAD_SHORT", + 0x3226: "NA_SE_EN_BOSU_WALK", + 0x3227: "NA_SE_EN_DEBU_WALK", + 0x3228: "NA_SE_EN_YASE_WALK", + 0x3229: "NA_SE_EN_BOSU_SIT", + 0x322A: "NA_SE_EN_BOSU_STAND", + 0x322B: "NA_SE_EN_BOSU_HAND", + 0x322C: "NA_SE_EN_LAST3_KOMA_OLD", + 0x322D: "NA_SE_EN_KONB_PREATTACK_OLD", + 0x322E: "NA_SE_EN_BOSU_SHOCK", + 0x322F: "NA_SE_EN_BOSU_SHIT", + 0x3230: "NA_SE_EN_BOSU_ATTACK", + 0x3231: "NA_SE_EN_BOSU_CYNICAL", + 0x3232: "NA_SE_EN_BOSU_LAUGH", + 0x3233: "NA_SE_EN_BOSU_LAUGH_DEMO", + 0x3234: "NA_SE_EN_DEBU_ATTACK", + 0x3235: "NA_SE_EN_DEBU_LAUGH", + 0x3236: "NA_SE_EN_DEBU_PAUSE", + 0x3237: "NA_SE_EN_YASE_ATTACK", + 0x3238: "NA_SE_EN_YASE_LAUGH", + 0x3239: "NA_SE_EN_YASE_PAUSE", + 0x323A: "NA_SE_EN_BOSU_DAMAGE", + 0x323B: "NA_SE_EN_DEBU_DAMAGE", + 0x323C: "NA_SE_EN_YASE_DAMAGE", + 0x323D: "NA_SE_EN_BOSU_DEAD", + 0x323E: "NA_SE_EN_DEBU_DEAD", + 0x323F: "NA_SE_EN_YASE_DEAD", + 0x3240: "NA_SE_EN_DEBU_PAUSE_K", + 0x3241: "NA_SE_EN_DEBU_LAUGH_SHORT_K", + 0x3242: "NA_SE_EN_DEBU_LAUGH_K", + 0x3243: "NA_SE_EN_YASE_PAUSE_K", + 0x3244: "NA_SE_EN_YASE_LAUGH_K", + 0x3245: "NA_SE_EN_BOSU_LAUGH_DEMO_K", + 0x3246: "NA_SE_EN_DEBU_LAUGH_SHORT", + 0x3247: "NA_SE_EN_BOSU_LAUGH_K", + 0x3248: "NA_SE_EN_DEBU_ATTACK_W", + 0x3249: "NA_SE_EN_YASE_ATTACK_W", + 0x324A: "NA_SE_EN_BOSU_ATTACK_W", + 0x324B: "NA_SE_EN_STAL_FREEZE_LIGHTS", + 0x324C: "NA_SE_EN_BOSU_ATTACK_K", + 0x324D: "NA_SE_EN_BOSU_SWORD", + 0x324E: "NA_SE_EN_KONB_JUMP_LEV_OLD", + 0x324F: "NA_SE_EN_MIBOSS_FREEZE_OLD", + 0x3250: "NA_SE_EN_YMAJIN_THROW", + 0x3251: "NA_SE_EN_BOSU_HEAD_BITE", + 0x3252: "NA_SE_EN_BOSU_HEAD_FLOAT", + 0x3253: "NA_SE_EN_LAST3_VOICE_KICK_OLD", + 0x3254: "NA_SE_EN_LAST3_VOICE_KOMA_OLD", + 0x3255: "NA_SE_EN_LAST3_VOICE_ROD_OLD", + 0x3256: "NA_SE_EN_LAST3_VOICE_THROW_OLD", + 0x3257: "NA_SE_EN_LAST3_VOICE_LAUGH_OLD", + 0x3258: "NA_SE_EN_LAST3_VOICE_DAMAGE_OLD", + 0x3259: "NA_SE_EN_LAST3_VOICE_DAMAGE2_OLD", + 0x325A: "NA_SE_EN_LAST3_VOICE_DEAD_OLD", + 0x325B: "NA_SE_EN_BOSU_DEAD_VOICE", + 0x325C: "NA_SE_EN_DEBU_DEAD_VOICE", + 0x325D: "NA_SE_EN_YASE_DEAD_VOICE", + 0x325E: "NA_SE_EN_LAST2_BALLET_OLD", + 0x325F: "NA_SE_EN_LAST2_MOONWALK_OLD", + 0x3260: "NA_SE_EN_SHARP_FLOAT", + 0x3261: "NA_SE_EN_SHARP_REACTION", + 0x3262: "NA_SE_EN_REDEAD_WEAKENED1", + 0x3263: "NA_SE_EN_REDEAD_WEAKENED_L1", + 0x3264: "NA_SE_EN_REDEAD_WEAKENED2", + 0x3265: "NA_SE_EN_REDEAD_WEAKENED_L2", + 0x3266: "NA_SE_EN_PIRATE_ONGND", + 0x3267: "NA_SE_EN_FOLLOWERS_STAY", + 0x3268: "NA_SE_EN_LAST2_VOICE_BALLET", + 0x3269: "NA_SE_EN_LAST2_VOICE_UAUOO1_OLD", + 0x326A: "NA_SE_EN_LAST2_VOICE_UAUOO2_OLD", + 0x326B: "NA_SE_EN_LAST2_VOICE_SURPRISED_OLD", + 0x326C: "NA_SE_EN_LAST2_DAMAGE_OLD", + 0x326D: "NA_SE_EN_LAST2_DAMAGE2_OLD", + 0x326E: "NA_SE_EN_LAST2_DEAD_OLD", + 0x326F: "NA_SE_EN_LAST2_UAUOO_OLD", + 0x3270: "NA_SE_EN_LAST2_GYM_B_OLD", + 0x3271: "NA_SE_EN_PIRATE_COOL_LAUGH", + 0x3272: "NA_SE_EN_PIRATE_CYNICAL", + 0x3273: "NA_SE_EN_PIRATE_DAMM_BREATH", + 0x3274: "NA_SE_EN_PIRATE_SHOUT", + 0x3275: "NA_SE_EN_STAL01_LAUGH", + 0x3276: "NA_SE_EN_STAL02_LAUGH_SHORT", + 0x3277: "NA_SE_EN_STAL03_LAUGH_BIG", + 0x3278: "NA_SE_EN_STAL04_ANGER", + 0x3279: "NA_SE_EN_STAL05_CYNICAL", + 0x327A: "NA_SE_EN_STAL06_SURPRISED", + 0x327B: "NA_SE_EN_STAL07_ANTONISHED", + 0x327C: "NA_SE_EN_STAL08_CRY_BIG", + 0x327D: "NA_SE_EN_STAL09_SCREAM", + 0x327E: "NA_SE_EN_STAL10_LAUGH_SHY", + 0x327F: "NA_SE_EN_STAL11_LAUGH_SHY2", + 0x3280: "NA_SE_EN_STAL12_LAUGH_KIDLY", + 0x3281: "NA_SE_EN_STAL20_CALL_MOON", + 0x3282: "NA_SE_EN_STAL20_CALL_MOON2", + 0x3283: "NA_SE_EN_STAL21_PSYCHO_VOICE", + 0x3284: "NA_SE_EN_STALKIDS_DOWN_K", + 0x3285: "NA_SE_EN_AKINDO_FLY", + 0x3286: "NA_SE_EN_NPC_APPEAR", + 0x3287: "NA_SE_EN_NPC_FADEAWAY", + 0x3288: "NA_SE_EN_DEBU_PAUSEx2", + 0x3289: "NA_SE_EN_YASE_PAUSEx2", + 0x328A: "NA_SE_EN_DEBU_HEAD_UP", + 0x328B: "NA_SE_EN_YASE_HEAD_UP", + 0x328C: "NA_SE_EN_STAL22_LAUGH_KID_L", + 0x328D: "NA_SE_EN_EVIL_POWER", + 0x328E: "NA_SE_NE_STAL23_COLD", + 0x328F: "NA_SE_EN_STALKIDS_GASAGOSO", + 0x3290: "NA_SE_EN_BOSU_TALK", + 0x3291: "NA_SE_EN_FAMOS_REVERSE1", + 0x3292: "NA_SE_EN_FAMOS_REVERSE2", + 0x3293: "NA_SE_EN_FAMOS_FLOAT", + 0x3294: "NA_SE_EN_FAMOS_FLOAT_REVERSE", + 0x3295: "NA_SE_EN_KOTAKE_ROLL", + 0x3296: "NA_SE_EN_KOTAKE_FLY", + 0x3297: "NA_SE_EN_THIEFBIRD_VOICE", + 0x3298: "NA_SE_EN_THIEFBIRD_DAMAGE", + 0x3299: "NA_SE_EN_THIEFBIRD_DEAD", + 0x329A: "NA_SE_EN_STALKIDS_BODY", + 0x329B: "NA_SE_EN_STALKIDS_BODY_LEV", + 0x329C: "NA_SE_EN_BOSU_STAND_RAPID", + 0x329D: "NA_SE_EN_STAL24_SCREAM2", + 0x329E: "NA_SE_EN_STALKIDS_EARTHQUAKE", + 0x329F: "NA_SE_EN_MASK_FLOAT", + 0x32A0: "NA_SE_EN_STALKIDS_PULLED", + 0x32A1: "NA_SE_EN_KITA_SALUTE", + 0x32A2: "NA_SE_EN_KTIA_WALK", + 0x32A3: "NA_SE_EN_KTIA_PAUSE_K", + 0x32A4: "NA_SE_EN_KITA_LAUGH_K", + 0x32A5: "NA_SE_EN_KITA_DAMAGE", + 0x32A6: "NA_SE_EN_KITA_DEAD", + 0x32A7: "NA_SE_EN_STALBABY_LAUGH", + 0x32A8: "NA_SE_EN_STALBABY_SURPRISED", + 0x32A9: "NA_SE_EN_KITA_BREAK", + 0x32AA: "NA_SE_EN_KITA_ATTACK_W", + 0x32AB: "NA_SE_EN_KONB_WAIT_OLD", + 0x32AC: "NA_SE_EN_DEATH_SCYTHE", + 0x32AD: "NA_SE_EN_DEATH_ROLL", + 0x32AE: "NA_SE_EN_DEATH_SCYTHE_LEV", + 0x32AF: "NA_SE_EN_DEATH_SCYTHE_ONGND", + 0x32B0: "NA_SE_EN_DEATH_VOICE", + 0x32B1: "NA_SE_EN_DEATH_DAMAGE", + 0x32B2: "NA_SE_EN_DEATH_DEAD", + 0x32B3: "NA_SE_EN_DEATH_ATTACK", + 0x32B4: "NA_SE_EN_DEATH_APPEAR", + 0x32B5: "NA_SE_EN_DEATH_HEARTBREAK", + 0x32B6: "NA_SE_EN_KONB_MINI_DEAD", + 0x32B7: "NA_SE_EN_HALF_REDEAD_LOOP", + 0x32B8: "NA_SE_EN_HALF_REDEAD_SURPRISE", + 0x32B9: "NA_SE_EN_HALF_REDEAD_SCREAME", + 0x32BA: "NA_SE_EN_HALF_REDEAD_TRANS", + 0x32BB: "NA_SE_EN_GOLON_VOICE_GENERAL", + 0x32BC: "NA_SE_EN_IWAIGORON_EVERYBODY", + 0x32BD: "NA_SE_EN_IWAIGORON_SOLO", + 0x32BE: "NA_SE_EN_ROMANI_WALK", + 0x32BF: "NA_SE_EN_MOON_SCREAM1", + 0x32C0: "NA_SE_EN_MOON_SCREAM2", + 0x32C1: "NA_SE_EN_MOON_SCREAM3", + 0x32C2: "NA_SE_EN_MOON_SCREAM4", + 0x32C3: "NA_SE_EN_STALKIDS_HEADACHE", + 0x32C4: "NA_SE_EN_BIGNUTS_WALK", + 0x32C5: "NA_SE_EN_KITA_PAUSE", + 0x32C6: "NA_SE_EN_ANSATSUSYA_LAUGH", + 0x32C7: "NA_SE_EN__copy514", + 0x32C8: "NA_SE_EN__copy515", + 0x32C9: "NA_SE_EN__copy516", + 0x32CA: "NA_SE_EN__copy517", + 0x32CB: "NA_SE_EN__copy518", + 0x32CC: "NA_SE_EN__copy519", + 0x32CD: "NA_SE_EN_DALMANI_A", + 0x32CE: "NA_SE_EN_DALMANI_B", + 0x32CF: "NA_SE_EN_DALMANI_C", + 0x32D0: "NA_SE_EN_DALMANI_D", + 0x32D1: "NA_SE_EN__2d1", + 0x32D2: "NA_SE_EN__2d2", + 0x32D3: "NA_SE_EN_EVIL_POWER_PREDEMO", + 0x32D4: "NA_SE_EN_KOUME_DAMAGE", + 0x32D5: "NA_SE_EN_KOUME_DAMAGE2", + 0x32D6: "NA_SE_EN_KONB_MINI_APPEAR", + 0x32D7: "NA_SE_EN_IRONNACK_DAMAGE", + 0x32D8: "NA_SE_EN_IRONNACK_DEAD", + 0x32D9: "NA_SE_EN_ANSATSUSYA_ONGND", + 0x32DA: "NA_SE_EN_ANSATSUSYA_ROCK", + 0x32DB: "NA_SE_EN_REDEAD_REVERSE", + 0x32DC: "NA_SE_EN_STALKIDS_NOSE", + 0x32DD: "NA_SE_EN_KITA_SNORE", + 0x32DE: "NA_SE_EN_IRONNACK_DASH", + 0x32DF: "NA_SE_EN_TUBOOCK_FLY", + 0x4000: "NA_SE_SY_WIN_OPEN", + 0x4001: "NA_SE_SY_WIN_CLOSE", + 0x4002: "NA_SE_SY_CORRECT_CHIME", + 0x4003: "NA_SE_SY_GET_RUPY", + 0x4004: "NA_SE_SY_MESSAGE_WOMAN", + 0x4005: "NA_SE_SY_MESSAGE_MAN", + 0x4006: "NA_SE_SY_ERROR", + 0x4007: "NA_SE_SY_TRE_BOX_APPEAR", + 0x4008: "NA_SE_SY_DECIDE", + 0x4009: "NA_SE_SY_CURSOR", + 0x400A: "NA_SE_SY_CANCEL", + 0x400B: "NA_SE_SY_HP_RECOVER", + 0x400C: "NA_SE_SY_ATTENTION_ON", + 0x400D: "NA_SE_SY_DUMMY_13", + 0x400E: "NA_SE_SY_DUMMY_14", + 0x400F: "NA_SE_SY_LOCK_OFF", + 0x4010: "NA_SE_SY_LOCK_ON_HUMAN", + 0x4011: "NA_SE_SY_DUMMY_17", + 0x4012: "NA_SE_SY_DUMMY_18", + 0x4013: "NA_SE_SY_CAMERA_ZOOM_UP", + 0x4014: "NA_SE_SY_CAMERA_ZOOM_DOWN", + 0x4015: "NA_SE_SY_DUMMY_21", + 0x4016: "NA_SE_SY_DUMMY_22", + 0x4017: "NA_SE_SY_ATTENTION_ON_OLD", + 0x4018: "NA_SE_SY_MESSAGE_PASS", + 0x4019: "NA_SE_SY_WARNING_COUNT_N", + 0x401A: "NA_SE_SY_WARNING_COUNT_E", + 0x401B: "NA_SE_SY_HITPOINT_ALARM", + 0x401C: "NA_SE_SY_DUMMY_28", + 0x401D: "NA_SE_SY_DEMO_CUT", + 0x401E: "NA_SE_SY_NAVY_CALL", + 0x401F: "NA_SE_SY_GAUGE_UP", + 0x4020: "NA_SE_SY_DUMMY_32", + 0x4021: "NA_SE_SY_DUMMY_33", + 0x4022: "NA_SE_SY_DUMMY_34", + 0x4023: "NA_SE_SY_PIECE_OF_HEART", + 0x4024: "NA_SE_SY_GET_ITEM", + 0x4025: "NA_SE_SY_WIN_SCROLL_LEFT", + 0x4026: "NA_SE_SY_WIN_SCROLL_RIGHT", + 0x4027: "NA_SE_SY_OCARINA_ERROR", + 0x4028: "NA_SE_SY_CAMERA_ZOOM_UP_2", + 0x4029: "NA_SE_SY_CAMERA_ZOOM_DOWN_2", + 0x402A: "NA_SE_SY_GLASSMODE_ON", + 0x402B: "NA_SE_SY_GLASSMODE_OFF", + 0x402C: "NA_SE_SY_FOUND", + 0x402D: "NA_SE_SY_HIT_SOUND", + 0x402E: "NA_SE_SY_MESSAGE_END", + 0x402F: "NA_SE_SY_RUPY_COUNT", + 0x4030: "NA_SE_SY_LOCK_ON", + 0x4031: "NA_SE_SY_GET_BOXITEM", + 0x4032: "NA_SE_SY_WHITE_OUT_INTO_MOON", + 0x4033: "NA_SE_SY_WHITE_OUT_S", + 0x4034: "NA_SE_SY_WHITE_OUT_T", + 0x4035: "NA_SE_SY_START_SHOT", + 0x4036: "NA_SE_SY_METRONOME", + 0x4037: "NA_SE_SY_ATTENTION_URGENCY", + 0x4038: "NA_SE_SY_METRONOME_LV", + 0x4039: "NA_SE_SY_FSEL_CURSOR", + 0x403A: "NA_SE_SY_FSEL_DECIDE_S", + 0x403B: "NA_SE_SY_FSEL_DECIDE_L", + 0x403C: "NA_SE_SY_FSEL_CLOSE", + 0x403D: "NA_SE_SY_FSEL_ERROR", + 0x403E: "NA_SE_SY_SET_FIRE_ARROW", + 0x403F: "NA_SE_SY_SET_ICE_ARROW", + 0x4040: "NA_SE_SY_SET_LIGHT_ARROW", + 0x4041: "NA_SE_SY_SYNTH_MAGIC_ARROW", + 0x4042: "NA_SE_SY_METRONOME_2", + 0x4043: "NA_SE_SY_KINSTA_MARK_APPEAR", + 0x4044: "NA_SE_SY_FIVE_COUNT_LUPY", + 0x4045: "NA_SE_SY_CARROT_RECOVER", + 0x4046: "NA_SE_EV_FAIVE_LUPY_COUNT", + 0x4047: "NA_SE_SY_METRONOME_TEMPO", + 0x4048: "NA_SE_SY_COMICAL_SOUND0_0", + 0x4049: "NA_SE_SY_COMICAL_SOUND0_1", + 0x404A: "NA_SE_SY_COMICAL_SOUND0_LAST", + 0x404B: "NA_SE_SY_SOUT_DEMO", + 0x404C: "NA_SE_SY_TIMESIGNAL_BELL", + 0x404D: "NA_SE_SY_DEKUNUTS_JUMP_FAILED", + 0x404E: "NA_SE_SY_ATTENTION_SOUND", + 0x404F: "NA_SE_SY_TRANSFORM_MASK_FLASH", + 0x4050: "NA_SE_SY_CAMERA_SHUTTER", + 0x4051: "NA_SE_SY_STALKIDS_PSYCHO", + 0x4052: "NA_SE_SY_CHICK_JOIN_CHIME", + 0x4053: "NA_SE_SY_HIT_SOUND_L", + 0x4054: "NA_SE_SY_FAIRY_MASK_SUCCESS", + 0x4055: "NA_SE_SY_SCHEDULE_WRITE", + 0x4056: "NA_SE_SY_STOPWATCH_TIMER_3", + 0x4057: "NA_SE_SY_STOPWATCH_TIMER_INF", + 0x4058: "NA_SE_SY_EARTHQUAKE_OUTDOOR", + 0x4059: "NA_SE_SY_SPIRAL_DASH", + 0x405A: "NA_SE_SY_QUIZ_CORRECT", + 0x405B: "NA_SE_SY_QUIZ_INCORRECT", + 0x405C: "NA_SE_SY_DIZZY_EFFECT", + 0x405D: "NA_SE_SY_TIME_CONTROL_SLOW", + 0x405E: "NA_SE_SY_TIME_CONTROL_NORMAL", + 0x405F: "NA_SE_SY_SECOM_WARNING", + 0x5000: "NA_SE_OC_OCARINA", + 0x5001: "NA_SE_OC_ABYSS", + 0x5002: "NA_SE_OC_DOOR_OPEN", + 0x5003: "NA_SE_OC_SECRET_WARP_IN", + 0x5004: "NA_SE_OC_SECRET_WARP_OUT", + 0x5005: "NA_SE_OC_SECRET_HOLE_OUT", + 0x5006: "NA_SE_OC_REVENGE", + 0x5007: "NA_SE_OC_TUNAMI", + 0x5008: "NA_SE_OC_TELOP_IMPACT", + 0x5009: "NA_SE_OC_WOOD_GATE_OPEN", + 0x500A: "NA_SE_OC_FIREWORKS", + 0x500B: "NA_SE_OC_WHITE_OUT_INTO_KYOJIN", + 0x500C: "NA_SE_OC_12", + 0x500D: "NA_SE_OC_13", + 0x500E: "NA_SE_OC_14", + 0x500F: "NA_SE_OC_15", + 0x6000: "NA_SE_VO_LI_SWORD_N", + 0x6001: "NA_SE_VO_LI_SWORD_L", + 0x6002: "NA_SE_VO_LI_LASH", + 0x6003: "NA_SE_VO_LI_HANG", + 0x6004: "NA_SE_VO_LI_CLIMB_END", + 0x6005: "NA_SE_VO_LI_DAMAGE_S", + 0x6006: "NA_SE_VO_LI_FREEZE", + 0x6007: "NA_SE_VO_LI_FALL_S", + 0x6008: "NA_SE_VO_LI_FALL_L", + 0x6009: "NA_SE_VO_LI_BREATH_REST", + 0x600A: "NA_SE_VO_LI_BREATH_DRINK", + 0x600B: "NA_SE_VO_LI_DOWN", + 0x600C: "NA_SE_VO_LI_TAKEN_AWAY", + 0x600D: "NA_SE_VO_LI_HELD", + 0x600E: "NA_SE_VO_LI_SNEEZE", + 0x600F: "NA_SE_VO_LI_SWEAT", + 0x6010: "NA_SE_VO_LI_DRINK", + 0x6011: "NA_SE_VO_LI_RELAX", + 0x6012: "NA_SE_VO_LI_SWORD_PUTAWAY", + 0x6013: "NA_SE_VO_LI_GROAN", + 0x6014: "NA_SE_VO_LI_AUTO_JUMP", + 0x6015: "NA_SE_VO_LI_MAGIC_NALE", + 0x6016: "NA_SE_VO_LI_SURPRISE", + 0x6017: "NA_SE_VO_LI_MAGIC_FROL", + 0x6018: "NA_SE_VO_LI_PUSH", + 0x6019: "NA_SE_VO_LI_HOOKSHOT_HANG", + 0x601A: "NA_SE_VO_LI_LAND_DAMAGE_S", + 0x601B: "NA_SE_VO_LI_MAGIC_START", + 0x601C: "NA_SE_VO_LI_MAGIC_ATTACK", + 0x601D: "NA_SE_VO_BL_DOWN", + 0x601E: "NA_SE_VO_LI_DEMO_DAMAGE", + 0x601F: "NA_SE_VO_LI_SWORD_N_copy30", + 0x6020: "NA_SE_VO_DUMMY_32", + 0x6021: "NA_SE_VO_DUMMY_33", + 0x6022: "NA_SE_VO_DUMMY_34", + 0x6023: "NA_SE_VO_DUMMY_35", + 0x6024: "NA_SE_VO_DUMMY_36", + 0x6025: "NA_SE_VO_DUMMY_37", + 0x6026: "NA_SE_VO_DUMMY_38", + 0x6027: "NA_SE_VO_DUMMY_39", + 0x6028: "NA_SE_VO_NAVY_ENEMY", + 0x6029: "NA_SE_VO_NAVY_HELLO", + 0x602A: "NA_SE_VO_NAVY_HEAR", + 0x602B: "NA_SE_VO_DUMMY_43", + 0x602C: "NA_SE_VO_DUMMY_44", + 0x602D: "NA_SE_VO_DUMMY_45", + 0x602E: "NA_SE_VO_DUMMY_46", + 0x602F: "NA_SE_VO_DUMMY_47", + 0x6030: "NA_SE_VO_DUMMY_48", + 0x6031: "NA_SE_VO_DUMMY_49", + 0x6032: "NA_SE_VO_DUMMY_50", + 0x6033: "NA_SE_VO_DUMMY_51", + 0x6034: "NA_SE_VO_DUMMY_52", + 0x6035: "NA_SE_VO_DUMMY_53", + 0x6036: "NA_SE_VO_DUMMY_54", + 0x6037: "NA_SE_VO_DUMMY_55", + 0x6038: "NA_SE_VO_DUMMY_56", + 0x6039: "NA_SE_VO_DUMMY_57", + 0x603A: "NA_SE_VO_DUMMY_58", + 0x603B: "NA_SE_VO_DUMMY_59", + 0x603C: "NA_SE_VO_DUMMY_60", + 0x603D: "NA_SE_VO_DUMMY_61", + 0x603E: "NA_SE_VO_DUMMY_62", + 0x603F: "NA_SE_VO_DUMMY_63", + 0x6040: "NA_SE_VO_LK_WAKE_UP", + 0x6041: "NA_SE_VO_LK_CATCH_DEMO", + 0x6042: "NA_SE_VO_LK_DRAGGED_DAMAGE", + 0x6043: "NA_SE_VO_NAVY_CALL", + 0x6044: "NA_SE_VO_NA_HELLO_3", + 0x6045: "NA_SE_VO_CHAT_MESSAGE_CALL", + 0x6046: "NA_SE_VO_BELL_MESSAGE", + 0x6047: "NA_SE_VO_MONDO_MESSAGE", + 0x6048: "NA_SE_VO_LK_USING_UP_ENERGY", + 0x6049: "NA_SE_VO_DUMMY_73", + 0x604A: "NA_SE_VO_GO_SLEEP", + 0x604B: "NA_SE_VO_NP_SLEEP_OUT", + 0x604C: "NA_SE_VO_DUMMY_76", + 0x604D: "NA_SE_VO_DUMMY_77", + 0x604E: "NA_SE_VO_NP_DRINK", + 0x604F: "NA_SE_VO_DUMMY_79", + 0x6050: "NA_SE_VO_NARRATION_0", + 0x6051: "NA_SE_VO_TA_SURPRISE", + 0x6052: "NA_SE_VO_TA_CRY_0", + 0x6053: "NA_SE_VO_TA_CRY_1", + 0x6054: "NA_SE_VO_IN_CRY_0", + 0x6055: "NA_SE_VO_IN_LOST", + 0x6056: "NA_SE_VO_IN_LASH_0", + 0x6057: "NA_SE_VO_IN_LASH_1", + 0x6058: "NA_SE_VO_FR_LAUGH_0", + 0x6059: "NA_SE_VO_FR_SMILE_0", + 0x605A: "NA_SE_VO_NB_AGONY", + 0x605B: "NA_SE_VO_NB_CRY_0", + 0x605C: "NA_SE_VO_NB_NOTICE", + 0x605D: "NA_SE_VO_NA_HELLO_0", + 0x605E: "NA_SE_VO_NA_HELLO_1", + 0x605F: "NA_SE_VO_NA_HELLO_2", + 0x6060: "NA_SE_VO_RT_CRASH", + 0x6061: "NA_SE_VO_RT_DISCOVER", + 0x6062: "NA_SE_VO_RT_FALL", + 0x6063: "NA_SE_VO_RT_LAUGH_0", + 0x6064: "NA_SE_VO_RT_LIFT", + 0x6065: "NA_SE_VO_RT_THROW", + 0x6066: "NA_SE_VO_RT_UNBALLANCE", + 0x6067: "NA_SE_VO_ST_DAMAGE", + 0x6068: "NA_SE_VO_ST_ATTACK", + 0x6069: "NA_SE_VO_Z0_HURRY", + 0x606A: "NA_SE_VO_Z0_MEET", + 0x606B: "NA_SE_VO_Z0_QUESTION", + 0x606C: "NA_SE_VO_Z0_SIGH_0", + 0x606D: "NA_SE_VO_Z0_SMILE_0", + 0x606E: "NA_SE_VO_Z0_SURPRISE", + 0x606F: "NA_SE_VO_Z0_THROW", + 0x6070: "NA_SE_VO_SK_CRY_0", + 0x6071: "NA_SE_VO_SK_CRY_1", + 0x6072: "NA_SE_VO_SK_CRASH", + 0x6073: "NA_SE_VO_NA_LISTEN", + 0x6074: "NA_SE_VO_SK_SHOUT", + 0x6075: "NA_SE_VO_Z1_CRY_0", + 0x6076: "NA_SE_VO_Z1_CRY_1", + 0x6077: "NA_SE_VO_Z1_OPENDOOR", + 0x6078: "NA_SE_VO_FR_SMILE_1", + 0x6079: "NA_SE_VO_FR_SMILE_2", + 0x607A: "NA_SE_VO_KZ_MOVE", + 0x607B: "NA_SE_VO_NB_LAUGH", + 0x607C: "NA_SE_VO_IN_JOY0", + 0x607D: "NA_SE_VO_IN_JOY1", + 0x607E: "NA_SE_VO_IN_JOY2", + 0x607F: "NA_SE_VO_DUMMY_127", + 0x6080: "NA_SE_VO_DUMMY_128", + 0x6081: "NA_SE_VO_DUMMY_129", + 0x6082: "NA_SE_VO_DUMMY_130", + 0x6083: "NA_SE_VO_DUMMY_131", + 0x6084: "NA_SE_VO_DUMMY_132", + 0x6085: "NA_SE_VO_DUMMY_133", + 0x6086: "NA_SE_VO_DUMMY_134", + 0x6087: "NA_SE_VO_DUMMY_135", + 0x6088: "NA_SE_VO_DUMMY_136", + 0x6089: "NA_SE_VO_DUMMY_137", + 0x608A: "NA_SE_VO_DUMMY_138", + 0x608B: "NA_SE_VO_DUMMY_139", + 0x608C: "NA_SE_VO_DUMMY_140", + 0x608D: "NA_SE_VO_DUMMY_141", + 0x608E: "NA_SE_VO_DUMMY_142", + 0x608F: "NA_SE_VO_DUMMY_143", + 0x6090: "NA_SE_VO_DUMMY_144", + 0x6091: "NA_SE_VO_DUMMY_145", + 0x6092: "NA_SE_VO_DUMMY_146", + 0x6093: "NA_SE_VO_DUMMY_147", + 0x6094: "NA_SE_VO_DUMMY_148", + 0x6095: "NA_SE_VO_DUMMY_149", + 0x6096: "NA_SE_VO_DUMMY_150", + 0x6097: "NA_SE_VO_DUMMY_151", + 0x6098: "NA_SE_VO_DUMMY_152", + 0x6099: "NA_SE_VO_DUMMY_153", + 0x609A: "NA_SE_VO_DUMMY_154", + 0x609B: "NA_SE_VO_DUMMY_155", + 0x609C: "NA_SE_VO_DUMMY_156", + 0x609D: "NA_SE_VO_DUMMY_157", + 0x609E: "NA_SE_VO_DUMMY_158", + 0x609F: "NA_SE_VO_DUMMY_159", + 0x60A0: "NA_SE_VO_DUMMY_160", + 0x60A1: "NA_SE_VO_DUMMY_161", + 0x60A2: "NA_SE_VO_DUMMY_162", + 0x60A3: "NA_SE_VO_DUMMY_163", + 0x60A4: "NA_SE_VO_DUMMY_164", + 0x60A5: "NA_SE_VO_DUMMY_165", + 0x60A6: "NA_SE_VO_DUMMY_166", + 0x60A7: "NA_SE_VO_DUMMY_167", + 0x60A8: "NA_SE_VO_DUMMY_168", + 0x60A9: "NA_SE_VO_DUMMY_169", + 0x60AA: "NA_SE_VO_DUMMY_170", + 0x60AB: "NA_SE_VO_DUMMY_171", + 0x60AC: "NA_SE_VO_DUMMY_172", + 0x60AD: "NA_SE_VO_DUMMY_173", + 0x60AE: "NA_SE_VO_DUMMY_174", + 0x60AF: "NA_SE_VO_DUMMY_175", + 0x60B0: "NA_SE_VO_DUMMY_176", + 0x60B1: "NA_SE_VO_DUMMY_177", + 0x60B2: "NA_SE_VO_DUMMY_178", + 0x60B3: "NA_SE_VO_DUMMY_179", + 0x60B4: "NA_SE_VO_DUMMY_180", + 0x60B5: "NA_SE_VO_DUMMY_181", + 0x60B6: "NA_SE_VO_DUMMY_182", + 0x60B7: "NA_SE_VO_DUMMY_183", + 0x60B8: "NA_SE_VO_DUMMY_184", + 0x60B9: "NA_SE_VO_DUMMY_185", + 0x60BA: "NA_SE_VO_DUMMY_186", + 0x60BB: "NA_SE_VO_DUMMY_187", + 0x60BC: "NA_SE_VO_DUMMY_188", + 0x60BD: "NA_SE_VO_DUMMY_189", + 0x60BE: "NA_SE_VO_DUMMY_190", + 0x60BF: "NA_SE_VO_DUMMY_191", + 0x60C0: "NA_SE_VO_DUMMY_192", + 0x60C1: "NA_SE_VO_DUMMY_193", + 0x60C2: "NA_SE_VO_DUMMY_194", + 0x60C3: "NA_SE_VO_DUMMY_195", + 0x60C4: "NA_SE_VO_DUMMY_196", + 0x60C5: "NA_SE_VO_DUMMY_197", + 0x60C6: "NA_SE_VO_DUMMY_198", + 0x60C7: "NA_SE_VO_DUMMY_199", + 0x60C8: "NA_SE_VO_DUMMY_200", + 0x60C9: "NA_SE_VO_DUMMY_201", + 0x60CA: "NA_SE_VO_DUMMY_202", + 0x60CB: "NA_SE_VO_DUMMY_203", + 0x60CC: "NA_SE_VO_DUMMY_204", + 0x60CD: "NA_SE_VO_DUMMY_205", + 0x60CE: "NA_SE_VO_DUMMY_206", + 0x60CF: "NA_SE_VO_DUMMY_207", + 0x60D0: "NA_SE_VO_DUMMY_208", + 0x60D1: "NA_SE_VO_DUMMY_209", + 0x60D2: "NA_SE_VO_DUMMY_210", + 0x60D3: "NA_SE_VO_DUMMY_211", + 0x60D4: "NA_SE_VO_DUMMY_212", + 0x60D5: "NA_SE_VO_DUMMY_213", + 0x60D6: "NA_SE_VO_DUMMY_214", + 0x60D7: "NA_SE_VO_DUMMY_215", + 0x60D8: "NA_SE_VO_DUMMY_216", + 0x60D9: "NA_SE_VO_DUMMY_217", + 0x60DA: "NA_SE_VO_DUMMY_218", + 0x60DB: "NA_SE_VO_DUMMY_219", + 0x60DC: "NA_SE_VO_DUMMY_220", + 0x60DD: "NA_SE_VO_DUMMY_221", + 0x60DE: "NA_SE_VO_DUMMY_222", + 0x60DF: "NA_SE_VO_DUMMY_223", + 0x60E0: "NA_SE_VO_LI_POO_WAIT", + 0x60E1: "NA_SE_VO_DUMMY_225", + 0x60E2: "NA_SE_VO_DUMMY_226", + 0x60E3: "NA_SE_VO_DUMMY_227", + 0x60E4: "NA_SE_VO_DUMMY_228", + 0x60E5: "NA_SE_VO_DUMMY_229", + 0x60E6: "NA_SE_VO_DUMMY_230", + 0x60E7: "NA_SE_VO_DUMMY_231", + 0x60E8: "NA_SE_VO_DUMMY_232", + 0x60E9: "NA_SE_VO_DUMMY_233", + 0x60EA: "NA_SE_VO_DUMMY_234", + 0x60EB: "NA_SE_VO_DUMMY_235", + 0x60EC: "NA_SE_VO_DUMMY_236", + 0x60ED: "NA_SE_VO_DUMMY_237", + 0x60EE: "NA_SE_VO_DUMMY_238", + 0x60EF: "NA_SE_VO_DUMMY_239", + 0x60F0: "NA_SE_VO_DUMMY_240", + 0x60F1: "NA_SE_VO_DUMMY_241", + 0x60F2: "NA_SE_VO_DUMMY_242", + 0x60F3: "NA_SE_VO_DUMMY_243", + 0x60F4: "NA_SE_VO_DUMMY_244", + 0x60F5: "NA_SE_VO_DUMMY_245", + 0x60F6: "NA_SE_VO_DUMMY_246", + 0x60F7: "NA_SE_VO_DUMMY_247", + 0x60F8: "NA_SE_VO_DUMMY_248", + 0x60F9: "NA_SE_VO_DUMMY_249", + 0x60FA: "NA_SE_VO_DUMMY_250", + 0x60FB: "NA_SE_VO_DUMMY_251", + 0x60FC: "NA_SE_VO_DUMMY_252", + 0x60FD: "NA_SE_VO_DUMMY_253", + 0x60FE: "NA_SE_VO_DUMMY_254", + 0x60FF: "NA_SE_VO_DUMMY_255", + 0x6100: "NA_SE_VO_JMVO02", + 0x6101: "NA_SE_VO_JMVO04", + 0x6102: "NA_SE_VO_CDVO00", + 0x6103: "NA_SE_VO_CDVO01", + 0x6104: "NA_SE_VO_CDVO02", + 0x6105: "NA_SE_VO_CDVO03", + 0x6106: "NA_SE_VO_BBVO00", + 0x6107: "NA_SE_VO_BBVO01", + 0x6108: "NA_SE_VO_BBVO02", + 0x6109: "NA_SE_VO_BBVO03", + 0x610A: "NA_SE_VO_BBVO04", + 0x610B: "NA_SE_VO_BBVO05", + 0x610C: "NA_SE_VO_OBVO01", + 0x610D: "NA_SE_VO_ARVO00", + 0x610E: "NA_SE_VO_ARVO01", + 0x610F: "NA_SE_VO_MMVO00", + 0x6110: "NA_SE_VO_MMVO01", + 0x6111: "NA_SE_VO_MMVO02", + 0x6112: "NA_SE_VO_MMVO03", + 0x6113: "NA_SE_VO_MMVO04", + 0x6114: "NA_SE_VO_MMVO05", + 0x6115: "NA_SE_VO_ABVO00", + 0x6116: "NA_SE_VO_ABVO01", + 0x6117: "NA_SE_VO_NPVO00", + 0x6118: "NA_SE_VO_FPVO00", + 0x6119: "NA_SE_VO_FPVO01", + 0x611A: "NA_SE_VO_FPVO02", + 0x611B: "NA_SE_VO_FPVO03", + 0x611C: "NA_SE_VO_ROVO01", + 0x611D: "NA_SE_VO_ROVO02", + 0x611E: "NA_SE_VO_RYVO01", + 0x611F: "NA_SE_VO_RYVO02", + 0x6120: "NA_SE_VO_RYVO03", + 0x6121: "NA_SE_VO_RYVO04", + 0x6122: "NA_SE_VO_ANVO00", + 0x6123: "NA_SE_VO_ANVO01", + 0x6124: "NA_SE_VO_ANVO02", + 0x6125: "NA_SE_VO_ANVO03", + 0x6126: "NA_SE_VO_CRVO00", + 0x6127: "NA_SE_VO_CRVO01", + 0x6128: "NA_SE_VO_CRVO02", + 0x6129: "NA_SE_VO_CRVO03", + 0x612A: "NA_SE_VO_HNVO00", + 0x612B: "NA_SE_VO_HNVO01", + 0x612C: "NA_SE_VO_HNVO02", + 0x612D: "NA_SE_VO_RMVO00", + 0x612E: "NA_SE_VO_RMVO01", + 0x612F: "NA_SE_VO_RMVO02", + 0x6130: "NA_SE_VO_PMVO01", + 0x6131: "NA_SE_VO_PMVO02", + 0x6132: "NA_SE_VO_PMVO03", + 0x6133: "NA_SE_VO_DHVO00", + 0x6134: "NA_SE_VO_DHVO01", + 0x6135: "NA_SE_VO_DHVO02", + 0x6136: "NA_SE_VO_DHVO03", + 0x6137: "NA_SE_VO_DHVO04", + 0x6138: "NA_SE_VO_TFVO00", + 0x6139: "NA_SE_VO_ANVO04", + 0x613A: "NA_SE_VO_ANVO05", + 0x613B: "NA_SE_VO_PMVO00", + 0x613C: "NA_SE_VO_CHVO03", + 0x613D: "NA_SE_VO_CHVO04", + 0x613E: "NA_SE_VO_CHVO05", + 0x613F: "NA_SE_VO_CHVO06", + 0x6140: "NA_SE_VO_CHVO07", + 0x6141: "NA_SE_VO_CHVO08", + 0x6142: "NA_SE_VO_CHVO09", + 0x6143: "NA_SE_VO_DPVO00", + 0x6144: "NA_SE_VO_DPVO01", + 0x6145: "NA_SE_VO_DPVO02", + 0x6146: "NA_SE_VO_SKVO00", + 0x6147: "NA_SE_VO_SKVO01", + 0x6148: "NA_SE_VO_KHVO00", + 0x6149: "NA_SE_VO_KHVO01", + 0x614A: "NA_SE_VO_KHVO02", + 0x614B: "NA_SE_VO_SHVO00", + 0x614C: "NA_SE_VO_SHVO01", + 0x614D: "NA_SE_VO_KAVO02", + 0x614E: "NA_SE_VO_KAVO03", + 0x614F: "NA_SE_VO_MTVO00", + 0x6150: "NA_SE_VO_TTVO00", + 0x6151: "NA_SE_VO_ITVO00", + 0x6152: "NA_SE_VO_ITVO01", + 0x6153: "NA_SE_VO_ITVO02", + 0x6154: "NA_SE_VO_KMVO00", + 0x6155: "NA_SE_VO_KMVO01", + 0x6156: "NA_SE_VO_JOVO00", + 0x6157: "NA_SE_VO_JYVO00", + 0x6158: "NA_SE_VO_DTVO00", + 0x6159: "NA_SE_VO_GUVO00", + 0x615A: "NA_SE_VO_KTVO00", + 0x615B: "NA_SE_VO_KTVO01", + 0x615C: "NA_SE_VO_KTVO03", + 0x615D: "NA_SE_VO_ZBVO00", + 0x615E: "NA_SE_VO_ZBVO01", + 0x615F: "NA_SE_VO_DAVO01", + 0x6160: "NA_SE_VO_SHVO04", + 0x6161: "NA_SE_VO_GBVO02", + 0x6162: "NA_SE_VO_GBVO03", + 0x6163: "NA_SE_VO_PFVO00", + 0x6164: "NA_SE_VO_PFVO01", + 0x6165: "NA_SE_VO_GAVO00", + 0x6166: "NA_SE_VO_GAVO01", + 0x6167: "NA_SE_VO_DJVO00", + 0x6168: "NA_SE_VO_DJVO01", + 0x6169: "NA_SE_VO_MSVO00", + 0x616A: "NA_SE_VO_MSVO01", + 0x616B: "NA_SE_VO_JPVO00", + 0x616C: "NA_SE_VO_HYVO00", + 0x616D: "NA_SE_VO_HYVO01", + 0x616E: "NA_SE_VO_BAVO00", + 0x616F: "NA_SE_VO_POVO00", + 0x6170: "NA_SE_VO_DAVO00", + 0x6171: "NA_SE_VO_DAVO02", + 0x6172: "NA_SE_VO_MKVO00", + 0x6173: "NA_SE_VO_MKVO01", + 0x6174: "NA_SE_VO_MKVO02", + 0x6175: "NA_SE_VO_MKVO03", + 0x6176: "NA_SE_VO_MKVO04", + 0x6177: "NA_SE_VO_TIVO00", + 0x6178: "NA_SE_VO_TIVO01", + 0x6179: "NA_SE_VO_TIVO02", + 0x617A: "NA_SE_VO_TIVO03", + 0x617B: "NA_SE_VO_TIVO04", + 0x617C: "NA_SE_VO_TIVO05", + 0x617D: "NA_SE_VO_OMVO00", + 0x617E: "NA_SE_VO_OMVO01", + 0x617F: "NA_SE_VO_OMVO02", + 0x6180: "NA_SE_VO_OMVO03", + 0x6181: "NA_SE_VO_OMVO04", + 0x6182: "NA_SE_VO_OMVO05", + 0x6183: "NA_SE_VO_OMVO06", + 0x6184: "NA_SE_VO_DEMO_FALL2", + 0x6185: "NA_SE_VO_DEMO_384", + 0x6186: "NA_SE_VO_DEMO_385", + 0x6187: "NA_SE_VO_DEMO_386", + 0x6188: "NA_SE_VO_DEMO_387", + 0x6189: "NA_SE_VO_DEMO_388", + 0x618A: "NA_SE_VO_DEMO_389", + 0x618B: "NA_SE_VO_DEMO_390", + 0x618C: "NA_SE_VO_DEMO_391", + 0x618D: "NA_SE_VO_DEMO_392", + 0x618E: "NA_SE_VO_DEMO_393", + 0x618F: "NA_SE_VO_DEMO_394", +} + +def read4(data : bytes, p : int) -> int: + return struct.unpack(">I", data[p:p+4])[0] + +def unique_or_none(lst : List[T]) -> Optional[T]: + if not lst: + return None + elem = lst[0] + for e in lst[1:]: + if e != elem: + return None + return elem + +class MessageDecoder: + def __init__(self, control_end : int, control_codes : Dict[int, Tuple[str, str, Optional[Tuple[Callable[[int], str]]]]], + control_header : Tuple[str, str, Optional[Tuple[Callable[[int], str]]]], extraction_charmap : Dict[int, str]) -> None: + self.control_end : int = control_end + self.control_codes : Dict[int, Tuple[str, str, Optional[Tuple[Callable[[int], str]]]]] = control_codes + self.control_header : Tuple[str, str, Optional[Tuple[Callable[[int], str]]]] = control_header + self.extraction_charmap : Dict[int, str] = extraction_charmap + self.msg : Optional[bytes] = None + + def pop_char(self) -> int: + # Implement in subclass + raise NotImplementedError() + + def pop_char_end(self) -> int: + # Implement in subclass + raise NotImplementedError() + + def decode_char(self, c : int) -> str: + # Implement in subclass + raise NotImplementedError() + + def pop_byte(self) -> int: + c, self.msg = self.msg[0], self.msg[1:] + return c + + def pop_byte_end(self) -> int: + c, self.msg = self.msg[-1], self.msg[:-1] + return c + + def pop_2byte(self) -> int: + u = self.pop_byte() + l = self.pop_byte() + return (u << 8) | l + + def pop_2byte_end(self) -> int: + l = self.pop_byte_end() + u = self.pop_byte_end() + return (u << 8) | l + + def format_sfx_id(self, c : int) -> str: + try: + if c & 0x800: + return sfx_ids[c & ~0x800] + else: + return f"{sfx_ids[c]} - SFX_FLAG" + except KeyError: + return f"0x{c:04X}" + + def format_byte_hex(self, c: int) -> str: + return f"0x{c:02X}" + + def format_2byte_hex(self, c: int) -> str: + return f"0x{c:04X}" + + def format_item_id(self, c : int) -> str: + try: + return item_ids[c] + except KeyError: + return f"0x{c:04X}" + + def format_decimal(self, c : int) -> str: + return str(c) + + def format_text_id(self, c : int) -> str: + return f"0x{c:04X}" + + def format_bg_arg(self, c : int) -> str: + return { + 0 : "X_LEFT", + 1 : "X_RIGHT", + }[c] + + def format_bg_bits1(self, c : int) -> str: + c1 = (c >> 4) & 0xF + c2 = (c >> 0) & 0xF + + fgcol = { + 0 : "WHITE", + 1 : "DARK_RED", + 2 : "ORANGE", + 3 : "WHITE_3", + 4 : "WHITE_4", + 5 : "WHITE_5", + 6 : "WHITE_6", + 7 : "WHITE_7", + }[c1] + bgcol = { + 0 : "BLACK", + 1 : "GOLD", + 2 : "BLACK_2", + 3 : "BLACK_3", + }[c2] + + return f"{fgcol}, {bgcol}" + + def format_bg_bits2(self, c : int) -> str: + c1 = (c >> 4) & 0xF + c2 = (c >> 0) & 0xF + + y_offset = { + 0 : "1", + 1 : "2", + }[c1] + + return f"{y_offset}, {c2}" + + def emit_tokens(self, tokens : List[Tuple[str, str]]) -> str: + if len(tokens) == 0: + return "\"\"" + + out = "" + + q_state = False + s_state = False + nindentlines = 0 + + def maybe_enter_q(): + nonlocal out, q_state + if not q_state: + # If we're not in quotes, open quotes + out += "\"" + q_state = True + + def maybe_exit_q(space=False): + nonlocal out, q_state + if q_state: + # If we're in quotes, close quotes + out += "\"" + if space: + # If the caller asked for a trailing space following closing quotes, also add it + out += " " + q_state = False + + for tok_type,tok_dat in tokens: + if tok_type == "HEADER": + out += tok_dat + "\n" + continue + + if tok_type in ("BOX_BREAK", "BOX_BREAK2", "BOX_BREAK_DELAYED"): + # Box break has special handling since it is preceded by a newline and followed by two newlines + + # Close quotes since we're about to newline + maybe_exit_q() + nindentlines = 0 + s_state = False + + # Emit box break control character surrounded by real newlines + out += "\n" + tok_dat + "\n\n" + continue + + if s_state: + # Add a leading space before this token + out += " " + s_state = False + + if tok_type == "NEWLINE": + # Coming up on a newline + maybe_enter_q() + # Add the escaped newline character and a real newline + out += "\\n\"\n" + # Always closes quotes since we're at EOL + q_state = False + # Indent the line if requested + if nindentlines != 0: + out += " " + nindentlines -= 1 + elif tok_type == "TEXT": + # Coming up on text + maybe_enter_q() + # Emit text + out += tok_dat + else: + # Control characters + maybe_exit_q(space=True) + + # Emit the control character + out += tok_dat + + if tok_type == "TWO_CHOICE": + # Start a new line and indent next two lines + nindentlines = 2-1 + out += "\n " + elif tok_type == "THREE_CHOICE": + # Start a new line and indent next three lines + nindentlines = 3-1 + out += "\n " + else: + # No particular special handling + # Signal to next token to add a trailing space + s_state = True + + # If the message ended with quotes open, close them + maybe_exit_q() + + if out[-1] == "\n": + out = out[:-1] + + return out + + def decode_ctrl(self, name : str, argfmt : str, formatters : Tuple[Callable[[int], str]]) -> str: + if argfmt == "": + # No args to handle, just return the control char name + return name + + # Read and format args + args : List[int] = [] + for a in argfmt: + if a == "x": + assert self.pop_byte() == 0 + else: + args.append({ + "b" : self.pop_byte, + "h" : self.pop_2byte, + }[a]()) + return f"{name}({', '.join(formatters[i](a) for i,a in enumerate(args))})" + + def decode(self, msg : bytes) -> str: + if len(msg) == 0: + # Empty message without even an END? + return "None" + + # Strip trailing 0 bytes (assumed padding) + while msg[-1] == 0: + msg = msg[:-1] + + self.msg = msg + + # Must end in an END control code + assert self.pop_char_end() == self.control_end, msg + + tokens : List[Tuple[str, str]] = [] + token_run = "" + def flush_text(): + nonlocal tokens, token_run + if token_run != "": + tokens.append(("TEXT", token_run)) + token_run = "" + + if self.control_header: + tokens.append(("HEADER", self.decode_ctrl(*self.control_header))) + + # Consume the message, transforming it into tokens + while len(self.msg) != 0: + c = self.pop_char() + # print(f"{c:02X}", self.control_codes.get(c,None)) + + if c in self.control_codes: + # Hit a control character, flush current run of text + flush_text() + # Add a token for the control character + tokens.append((self.control_codes[c][0], self.decode_ctrl(*self.control_codes[c]))) + else: + # Not a control character, accumulate a run of text + if c in self.extraction_charmap: + token_run += self.extraction_charmap[c] + else: + token_run += self.decode_char(c) + + # Flush any remaining text + flush_text() + + self.msg = None + + # Convert tokens to final decoded text + return self.emit_tokens(tokens) + + def format_highscore(self, c : int) -> str: + return { + 0: "HS_BANK_RUPEES", + 1: "HS_UNK_1", + 2: "HS_FISHING", + 3: "HS_BOAT_ARCHERY", + 4: "HS_HORSE_BACK_BALLOON", + 6: "HS_SHOOTING_GALLERY" + }[c] + +class MessageDecoderNES(MessageDecoder): + def __init__(self) -> None: + control_end = 0xBF + control_codes = { + 0x00: ("COLOR_DEFAULT", "", None), + 0x01: ("COLOR_RED", "", None), + 0x02: ("COLOR_GREEN", "", None), + 0x03: ("COLOR_BLUE", "", None), + 0x04: ("COLOR_YELLOW", "", None), + 0x05: ("COLOR_LIGHTBLUE", "", None), + 0X06: ("COLOR_PINK", "", None), + 0x07: ("COLOR_SILVER", "", None), + 0x08: ("COLOR_ORANGE", "", None), + 0x0A: ("TEXT_SPEED", "", None), + 0x0B: ("HS_BOAT_ARCHERY", "", None), + 0x0C: ("STRAY_FAIRIES", "", None), + 0x0D: ("TOKENS", "", None), + 0x0E: ("POINTS_TENS", "", None), + 0x0F: ("POINTS_THOUSANDS", "", None), + 0x10: ("BOX_BREAK", "", None), + 0x11: ("NEWLINE", "", None), + 0x12: ("BOX_BREAK2", "", None), + 0x13: ("CARRIAGE_RETURN", "", None), + 0x14: ("SHIFT", "b", (self.format_decimal,)), + 0x15: ("CONTINUE", "", None), + 0x16: ("NAME", "", None), + 0x17: ("QUICKTEXT_ENABLE", "", None), + 0x18: ("QUICKTEXT_DISABLE", "", None), + 0x19: ("EVENT", "", None), + 0x1A: ("PERSISTENT", "", None), + 0x1B: ("BOX_BREAK_DELAYED", "h", (self.format_decimal,)), + 0x1C: ("FADE", "h", (self.format_decimal,)), + 0x1D: ("FADE_SKIPPABLE", "h", (self.format_decimal,)), + 0x1E: ("SFX", "h", (self.format_sfx_id,)), + 0x1F: ("DELAY", "h", (self.format_decimal,)), + 0xBF: ("END", "", None), + 0xC1: ("BACKGROUND", "", None), + 0xC2: ("TWO_CHOICE", "", None), + 0xC3: ("THREE_CHOICE", "", None), + 0xC4: ("TIMER_POSTMAN", "", None), + 0xC5: ("TIMER_MINIGAME_1", "", None), + 0xC6: ("TIMER_2", "", None), + 0xC7: ("TIMER_MOON_CRASH", "", None), + 0xC8: ("TIMER_MINIGAME_2", "", None), + 0xC9: ("TIMER_TIMER_ENV_HAZARD", "", None), + 0xCA: ("TIME", "", None), + 0xCB: ("CHEST_FLAGS", "", None), + 0xCC: ("INPUT_BANK", "", None), + 0xCD: ("RUPEES_SELECTED", "", None), + 0xCE: ("RUPEES_TOTAL", "", None), + 0xCF: ("TIME_UNTIL_MOON_CRASH", "", None), + 0xD0: ("INPUT_DOGGY_RACETRACK_BET", "", None), + 0xD1: ("INPUT_BOMBER_CODE", "", None), + 0xD2: ("PAUSE_MENU", "", None), + 0xD3: ("TIME_SPEED", "", None), + 0xD4: ("OWL_WARP", "", None), + 0xD5: ("INPUT_LOTTERY_CODE", "", None), + 0xD6: ("SPIDER_HOUSE_MASK_CODE", "", None), + 0xD7: ("STRAY_FAIRIES_LEFT_WOODFALL", "", None), + 0xD8: ("STRAY_FAIRIES_LEFT_SNOWHEAD", "", None), + 0xD9: ("STRAY_FAIRIES_LEFT_GREAT_BAY", "", None), + 0xDA: ("STRAY_FAIRIES_LEFT_STONE_TOWER", "", None), + 0xDB: ("POINTS_BOAT_ARCHERY", "", None), + 0xDC: ("LOTTERY_CODE", "", None), + 0xDD: ("LOTTERY_CODE_GUESS", "", None), + 0xDE: ("HELD_ITEM_PRICE", "", None), + 0xDF: ("BOMBER_CODE", "", None), + 0xE0: ("EVENT2", "", None), + 0xE1: ("SPIDER_HOUSE_MASK_CODE_1", "", None), + 0xE2: ("SPIDER_HOUSE_MASK_CODE_2", "", None), + 0xE3: ("SPIDER_HOUSE_MASK_CODE_3", "", None), + 0xE4: ("SPIDER_HOUSE_MASK_CODE_4", "", None), + 0xE5: ("SPIDER_HOUSE_MASK_CODE_5", "", None), + 0xE6: ("SPIDER_HOUSE_MASK_CODE_6", "", None), + 0xE7: ("HOURS_UNTIL_MOON_CRASH", "", None), + 0xE8: ("TIME_UNTIL_NEW_DAY", "", None), + 0xF0: ("HS_POINTS_BANK_RUPEES", "", None), + 0xF1: ("HS_POINTS_UNK_1", "", None), + 0xF2: ("HS_POINTS_FISHING", "", None), + 0xF3: ("HS_TIME_BOAT_ARCHERY", "", None), + 0xF4: ("HS_TIME_HORSE_BACK_BALLOON", "", None), + 0xF5: ("HS_TIME_LOTTERY_GUESS", "", None), + 0xF6: ("HS_TOWN_SHOOTING_GALLERY", "", None), + 0xF7: ("HS_UNK_1", "", None), + 0xF8: ("HS_UNK_3_LOWER", "", None), + 0xF9: ("HS_HORSE_BACK_BALLOON", "", None), + 0xFA: ("HS_DEKU_PLAYGROUND_DAY_1", "", None), + 0xFB: ("HS_DEKU_PLAYGROUND_DAY_2", "", None), + 0xFC: ("HS_DEKU_PLAYGROUND_DAY_3", "", None), + 0xFD: ("DEKU_PLAYGROUND_NAME_DAY_1", "", None), + 0xFE: ("DEKU_PLAYGROUND_NAME_DAY_2", "", None), + 0xFF: ("DEKU_PLAYGROUND_NAME_DAY_3", "", None) + } + control_header = ( + "HEADER", "hbhhhh", + ( + self.format_2byte_hex, self.format_byte_hex, self.format_text_id, + self.format_2byte_hex, self.format_2byte_hex, self.format_2byte_hex, + ) + ) + extraction_charmap = { + 0xB0: '[A]', + 0xB1: '[B]', + 0xB2: '[C]', + 0xB3: '[L]', + 0xB4: '[R]', + 0xB5: '[Z]', + 0xB6: '[C-Up]', + 0xB7: '[C-Down]', + 0xB8: '[C-Left]', + 0xB9: '[C-Right]', + 0xBA: '▼', + 0xBB: '[Control-Pad]' + } + super().__init__(control_end, control_codes, control_header, extraction_charmap) + self.pop_char = self.pop_byte + self.pop_char_end = self.pop_byte_end + + def decode_char(self, c : int) -> str: + decoded = bytes([c]).decode("ASCII") + # Escape quotes within the text itself + if decoded == "\"": + decoded = "\\\"" + return decoded + +class MessageDecoderCredits(MessageDecoder): + def __init__(self) -> None: + control_end = 0x2 + control_codes = { + 0x00: ("COLOR_DEFAULT", "", None), + 0x01: ("NEWLINE", "", None), + 0x02: ("END", "", None), + 0x04: ("BOX_BREAK", "", None), + 0x05: ("COLOR", "b", (self.format_color,)), + 0X06: ("SHIFT", "b", (self.format_decimal,)), + 0x07: ("TEXTID", "h", (self.format_text_id,)), + 0x08: ("QUICKTEXT_ENABLE", "", None), + 0x09: ("QUICKTEXT_DISABLE", "", None), + 0x0A: ("PERSISTENT", "", None), + 0x0B: ("EVENT", "", None), + 0x0C: ("BOX_BREAK_DELAY", "h", (self.format_decimal,)), + 0x0D: ("WAIT_INPUT", "", None), + 0x0E: ("FADE", "b", (self.format_decimal,)), + 0x0F: ("NAME", "", None), + 0x10: ("OCARINA", "", None), + 0x11: ("FADE2", "h", (self.format_decimal,)), + 0x12: ("SFX", "h", (self.format_sfx_id,)), + 0x13: ("ITEM_ICON", "b", (self.format_item_id,)), + 0x14: ("TEXT_SPEED", "b", (self.format_decimal,)), + 0x15: ("BACKGROUND", "bbb", (self.format_bg_arg, self.format_bg_bits1, self.format_bg_bits2,)), + 0x16: ("MARATHONTIME", "", None), + 0x17: ("RACETIME", "", None), + 0x18: ("POINTS", "", None), + 0x1A: ("UNSKIPPABLE", "", None), + 0x1B: ("TWO_CHOICE", "", None), + 0x1C: ("THREE_CHOICE", "", None), + 0x1D: ("FISH_INFO", "", None), + 0x1E: ("HIGHSCORE", "b", (self.format_highscore,)), + 0x1F: ("TIME", "", None) + } + extraction_charmap = {} + super().__init__(control_end, control_codes, None, extraction_charmap) + self.pop_char = self.pop_byte + self.pop_char_end = self.pop_byte_end + + def decode_char(self, c : int) -> str: + decoded = bytes([c]).decode("ASCII") + # Escape quotes within the text itself + if decoded == "\"": + decoded = "\\\"" + return decoded + + def format_color(self, c): + c1 = c & 0xF + c2 = c & ~0xF + assert c2 == 0x0C00 + return { + 0 : "DEFAULT", + 1 : "RED", + 2 : "ADJUSTABLE", + 3 : "BLUE", + 4 : "LIGHTBLUE", + 5 : "PURPLE", + 6 : "YELLOW", + 7 : "BLACK", + }[c1] + +class MessageTableDesc: + def __init__(self, table_name : str, seg_name : str, decoder : MessageDecoder, parent : Optional[int]) -> None: + self.table_name : str = table_name + self.seg_name : str = seg_name + self.decoder : MessageDecoder = decoder + self.parent : Optional[int] = parent + +class MessageTableEntry: + SIZE = 8 + + def __init__(self, text_id : int, box_type : int, box_pos : int, addr : int) -> None: + self.text_id, self.box_type, self.box_pos, self.addr = text_id, box_type, box_pos, addr + + @staticmethod + def from_bin(data : bytes) -> "MessageTableEntry": + text_id,info,addr = struct.unpack(">HBxI", data) + box_type = (info >> 4) & 0xF + box_pos = (info >> 0) & 0xF + return MessageTableEntry(text_id, box_type, box_pos, addr) + +class MessageData: + def __init__(self, box_type : int, box_pos : int, decoded_text : str): + self.box_type : int = box_type + self.box_pos : int = box_pos + self.decoded_text : str = decoded_text + +class MessageEntry: + def __init__(self, message_tables : List[Optional[MessageTableDesc]], text_id : int) -> None: + self.text_id : int = text_id + self.data : List[Optional[MessageData]] = [None for _ in message_tables] + self.select = tuple(tbl is not None for tbl in message_tables) + + def define_message(self, defn : str, box_type : int, box_pos : int, data : List[Optional[MessageData]]) -> str: + out = f"{defn}(0x{self.text_id:04X}, 0x{box_type:02X}, 0x{box_pos:02X},\n" + out += "\n,\n".join(f"MSG(\n{d.decoded_text}\n)" if d is not None else "MSG(/* MISSING */)" for d in data) + out += "\n)\n" + return out + + + def decode(self) -> str: + selection = tuple(not (select and data is None) for select,data in zip(self.select,self.data)) + assert any(selection) + + out = self.define_message("DEFINE_MESSAGE", self.data[0].box_type, self.data[0].box_pos, self.data) + + return out + +# TODO: Use version_config instead +def collect_messages(message_tables : List[Optional[MessageTableDesc]], baserom_segments_dir : Path, + config : Dict[str,int], code_vram : int, code_bin : bytes): + + messages : Dict[int,MessageEntry] = {} + + all_text_ids : List[Optional[List[int]]] = [None for _ in range(len(message_tables))] + + for lang_num,desc in enumerate(message_tables): + if desc is None: + continue + + baserom_seg = (baserom_segments_dir / desc.seg_name).read_bytes() + code_offset = config[desc.table_name] - code_vram + + if desc.parent is None: + # Complete table + + table_entries : List[MessageTableEntry] = [] + text_ids : List[int] = [] + + while True: + end = code_offset + MessageTableEntry.SIZE + entry = MessageTableEntry.from_bin(code_bin[code_offset:end]) + code_offset = end + + table_entries.append(entry) + text_ids.append(entry.text_id) + + if entry.text_id == 0xFFFF: + break + + all_text_ids[lang_num] = text_ids + + for i in range(len(table_entries) - 1): + curr = table_entries[i + 0] + next = table_entries[i + 1] + + curr_offset = curr.addr & ~0x0F000000 + next_offset = (next.addr & ~0x0F000000) if next.text_id != 0xFFFF else len(baserom_seg) + size = next_offset - curr_offset + + if curr.text_id not in messages: + messages[curr.text_id] = MessageEntry(message_tables, curr.text_id) + messages[curr.text_id].data[lang_num] = MessageData( + curr.box_type, curr.box_pos, desc.decoder.decode(baserom_seg[curr_offset : curr_offset+size])) + else: + # Addresses only + + for text_id in all_text_ids[desc.parent][:-1]: # Exclude text id 0xFFFF + if text_id in (0xFFFC,): + continue + + curr = read4(code_bin, code_offset + 0) + next = read4(code_bin, code_offset + 4) + code_offset += 4 + + curr_offset = curr & ~0x0F000000 + next_offset = next & ~0x0F000000 if text_id != 0xFFFD else len(baserom_seg) + size = next_offset - curr_offset + + # The text id is guaranteed to already exist + parent_data = messages[text_id].data[desc.parent] + messages[text_id].data[lang_num] = MessageData( + parent_data.box_type, parent_data.box_pos, desc.decoder.decode(baserom_seg[curr_offset:curr_offset+size])) + + return messages + +def main(): + parser = argparse.ArgumentParser(description="Extract text from the baserom into .h files") + parser.add_argument( + "baserom_segments_dir", + type=Path, + help="Directory of uncompressed ROM segments", + ) + parser.add_argument( + "output_dir", + type=Path, + help="Output directory to place files in", + ) + parser.add_argument( + "-v", + "--version", + help="version to process", + default="n64-us", + ) + args = parser.parse_args() + + baserom_segments_dir : Path = args.baserom_segments_dir + output_dir : Path = args.output_dir + + # TODO: use version config instead to get code vram + code_vram = 0x800A5AC0 + + code_bin = (baserom_segments_dir / "code").read_bytes() + + nes_decoder = MessageDecoderNES() + credits_decoder = MessageDecoderCredits() + + message_tables : MessageTableDesc = [None for _ in range(1)] # EN + message_table_staff : MessageTableDesc = None + + message_tables[0] = MessageTableDesc("sMessageTableNES", "message_data_static", nes_decoder, None) + message_table_staff = MessageTableDesc("sMessageTableCredits", "staff_message_data_static", credits_decoder, None) + + # TODO: use version config instead + config = { + "sMessageTableNES": 0x801C6B98, + "sMessageTableCredits": 0x801CFB08, + } + + messages = collect_messages(message_tables, baserom_segments_dir, config, code_vram, code_bin) + staff_messages = collect_messages([message_table_staff], baserom_segments_dir, config, code_vram, code_bin) + + message_data = [] + + for text_id in sorted(messages.keys()): + # TODO: Add back when we start extracting assets to extracted + # if text_id in (0xFFFC,0xFFFD): + # # Skip committed text ids + # continue + message_data.append(messages[text_id].decode()) + + message_data = "\n".join(message_data) + message_data_staff = "\n".join(staff_messages[text_id].decode() for text_id in sorted(staff_messages.keys())) + + (output_dir / "message_data.h").write_text(message_data) + (output_dir / "message_data_staff.h").write_text(message_data_staff) + +if __name__ == "__main__": + main() diff --git a/tools/text/msgenc.py b/tools/text/msgenc.py new file mode 100644 index 00000000000..5049ee63857 --- /dev/null +++ b/tools/text/msgenc.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +# +# message_data_static text encoder +# + +import argparse, ast, re, sys +from typing import Dict, Optional + +def read_charmap(path : str, wchar : bool, index : int) -> Dict[str,str]: + with open(path) as infile: + charmap = infile.read() + charmap = ast.literal_eval(charmap) + + out_charmap = {} + for k,v in charmap.items(): + v = v[index] + if v is None: + v = 0 + assert isinstance(k, str) + assert v in (range(0xFFFF + 1) if wchar else range(0xFF + 1)) + + k = repr(k)[1:-1] + + if wchar: + u = (v >> 8) & 0xFF + l = (v >> 0) & 0xFF + out_charmap[k] = f"0x{u:02X}, 0x{l:02X}," + else: + out_charmap[k] = f"0x{v:02X}," + + return out_charmap + +# From https://stackoverflow.com/questions/241327/remove-c-and-c-comments-using-python +def remove_comments(text : str) -> str: + def replacer(match : re.Match) -> str: + string : str = match.group(0) + if string.startswith("/"): + return " " # note: a space and not an empty string + else: + return string + + pattern = re.compile( + r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE + ) + return re.sub(pattern, replacer, text) + +def convert_text(text : str, encoding : str, charmap : Dict[str, str]) -> str: + def cvt_str(match : re.Match) -> str: + string : str = match.group(0) + + # strip quotes + string = string[1:-1] + + def cvt_escape(s : str): + # Convert escape sequences such as "\\\"" to "\"" + return s.encode("ascii").decode("unicode-escape") + + run_start = 0 + + def emit(text : Optional[str], advance : int): + nonlocal out, string, i, run_start + # flush text + to_flush = string[run_start:i] + if len(string[run_start:i]) != 0: + out += ",".join(f"0x{b:02X}" for b in to_flush.encode(encoding)) + out += "," + if text is None: + return + # emit + advance source pos + out += text + i += advance + # start new run + run_start = i + + out = "" + + i = 0 + while i != len(string): + # check charmap + for k in charmap.keys(): + if string.startswith(k, i): + # is in charmap, emit the mapped sequence + emit(charmap[k], len(k)) + break + else: + if string[i] == "\\" and string[i + 1] != "\\": + # is already escaped, emit the escape sequence verbatim + if string[i + 1] == "x": + # \x** + emit("0" + string[i + 1 : i + 4] + ",", 4) + else: + # \* + e = cvt_escape(string[i : i + 2]).encode(encoding) + assert len(e) == 1 + emit(f"0x{e[0]:02X},", 2) + else: + # increment pos, accumulating text that requires encoding + i += 1 + + # emit remaining accumulated text + emit(None, 0) + + return out + + # Naive string matcher, assumes single line strings and no comments, handles escaped quotations + string_regex = re.compile(r'"((?:[^\\"\n]|\\.)*)"') + + # Collapse escaped newlines + text = text.replace("\\\n", "") + # Encode according to charmap + text = re.sub(string_regex, cvt_str, text) + + return text + +def main(): + parser = argparse.ArgumentParser( + description="Encode message_data_static text headers" + ) + parser.add_argument( + "input", + help="path to file to be encoded, or - for stdin", + ) + parser.add_argument( + "output", + help="path to write encoded file, or - for stdout", + ) + parser.add_argument( + "--encoding", + help="encoding (nes, jpn, or credits)", + required=True, + type=str, + choices=("nes", "jpn", "credits"), + ) + parser.add_argument( + "--charmap", + help="path to charmap file specifying custom encoding elements", + required=True, + ) + args = parser.parse_args() + + wchar,encoding,index = { + "nes" : (False, "raw-unicode-escape", 0), + "jpn" : (True, "SHIFT-JIS", 1), + "credits" : (False, "raw-unicode-escape", 2) + }[args.encoding] + + charmap = read_charmap(args.charmap, wchar, index) + + text = "" + if args.input == "-": + text = sys.stdin.read() + else: + with open(args.input, "r") as infile: + text = infile.read() + + text = remove_comments(text) + text = convert_text(text, encoding, charmap) + + if args.output == "-": + sys.stdout.buffer.write(text.encode("utf-8")) + else: + with open(args.output, "w") as outfile: + outfile.write(text) + +if __name__ == "__main__": + main() From 6d59596ba7c0acefc764c9b79f60c843feee5dc0 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sat, 7 Sep 2024 14:47:15 -0700 Subject: [PATCH 2/4] format --- src/code/z_message.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/code/z_message.c b/src/code/z_message.c index c966718a8d9..537c2c0c0e6 100644 --- a/src/code/z_message.c +++ b/src/code/z_message.c @@ -55,7 +55,7 @@ u16 gBombersNotebookWeekEventFlags[BOMBERS_NOTEBOOK_EVENT_MAX] = { #undef DEFINE_PERSON #undef DEFINE_EVENT -#define DEFINE_MESSAGE(textId, type, yPos, msg) { textId, (((type) & 0xF) << 4) | ((yPos) & 0xF), _message_##textId }, +#define DEFINE_MESSAGE(textId, type, yPos, msg) { textId, (((type)&0xF) << 4) | ((yPos)&0xF), _message_##textId }, MessageTableEntry sMessageTableNES[] = { #include "assets/text/message_data.h" @@ -64,7 +64,8 @@ MessageTableEntry sMessageTableNES[] = { #undef DEFINE_MESSAGE -#define DEFINE_MESSAGE(textId, type, yPos, msg) { textId, (((type) & 0xF) << 4) | ((yPos) & 0xF), _message_##textId##_staff }, +#define DEFINE_MESSAGE(textId, type, yPos, msg) \ + { textId, (((type)&0xF) << 4) | ((yPos)&0xF), _message_##textId##_staff }, MessageTableEntry sMessageTableCredits[] = { #include "assets/text/message_data_staff.h" From 5ec8d73601f552480b729a98c845e11768bc1739 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sat, 7 Sep 2024 14:55:38 -0700 Subject: [PATCH 3/4] Remove item_ids try block --- tools/text/msgdis.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/text/msgdis.py b/tools/text/msgdis.py index d4d173e1db9..264fdfb125b 100755 --- a/tools/text/msgdis.py +++ b/tools/text/msgdis.py @@ -2602,10 +2602,7 @@ def format_2byte_hex(self, c: int) -> str: return f"0x{c:04X}" def format_item_id(self, c : int) -> str: - try: - return item_ids[c] - except KeyError: - return f"0x{c:04X}" + return item_ids[c] def format_decimal(self, c : int) -> str: return str(c) From f30c339bba1224c86c12b81fc922d292e09ece7a Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Thu, 10 Oct 2024 21:40:24 -0700 Subject: [PATCH 4/4] Update assets/text/charmap.txt Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> --- assets/text/charmap.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/text/charmap.txt b/assets/text/charmap.txt index 30330e8892b..a54d9a645d9 100644 --- a/assets/text/charmap.txt +++ b/assets/text/charmap.txt @@ -1,8 +1,8 @@ # Determines how certain text sequences should be encoded. The text sequence is -# converted to either the first or second tuple element based on whether the -# target encoding is the "wide" encoding. The first element is for the non-wide -# encoding, used for all languages besides JP, while the second element is for -# the wide encoding, used for JP, the third element is for encoding credits. +# converted to one of the tuple elements based on the chosen encoding: +# Element 1: Non-wide encoding, for text other than Japanese text and the credits. +# Element 2: For Japanese text. +# Element 3: For credits text. { '\n' : (0x11, 0x000A, 0x01),