mirror of
https://github.com/zeldaret/mm.git
synced 2024-11-26 22:30:58 +00:00
Port over OoT's new text pipeline (#1685)
* Port OoT's new msgdis and msgenc * format * Remove item_ids try block * Update assets/text/charmap.txt Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> --------- Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com>
This commit is contained in:
parent
7bb0e9287d
commit
0514d963d9
18
Makefile
18
Makefile
@ -481,6 +481,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
|
||||
@ -533,6 +534,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)
|
||||
@ -545,15 +551,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)
|
||||
|
21
assets/text/charmap.txt
Normal file
21
assets/text/charmap.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Determines how certain text sequences should be encoded. The text sequence is
|
||||
# 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),
|
||||
|
||||
'[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),
|
||||
}
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
// For use in message_data_static files
|
||||
|
||||
// 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 }
|
||||
|
||||
// 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 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)
|
||||
|
||||
#else
|
||||
|
||||
#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)
|
||||
#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
|
||||
|
||||
|
@ -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 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
|
||||
|
||||
#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
|
||||
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)
|
||||
#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)
|
||||
|
||||
/*
|
||||
* 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 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,11 @@ 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 },
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
|
@ -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)
|
@ -1,85 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# message_data_static text encoder
|
||||
#
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
|
||||
CHAR_REGEX = r'(?P<chr>\\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)
|
@ -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)
|
@ -1,72 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# message_data_static text encoder
|
||||
#
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
|
||||
CHAR_REGEX = r'(?P<chr>\\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)
|
3187
tools/text/msgdis.py
Executable file
3187
tools/text/msgdis.py
Executable file
File diff suppressed because it is too large
Load Diff
166
tools/text/msgenc.py
Normal file
166
tools/text/msgenc.py
Normal file
@ -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()
|
Loading…
Reference in New Issue
Block a user