Text that appears in textboxes is stored within *_message_data_static files, where * represents one of the 4 (possibly 5 if we ever get to analyze the iQue version) languages that the N64 version of Ocarina of Time was written in/translated into. Since NTSC and PAL support different languages, the *_message_data_static files found within them are different, as seen below.
Excluding textbox codes, the Japanese message_data_static file is encoded in Shift-JIS, while the English, German, and French message_data_static files are encoded in the ASCII subset of Shift-JIS. This makes it easy to perform simple edits in a hex editor, even in compressed ROMs since message_data_static files aren't compressed.
The only difference from standard US-ASCII is "\" is replaced by "¥".
Message Entry Table
The message entry table breaks down the message_data_static files into dialogs. NTSC releases have a slightly different table format than PAL (Debug Rom) releases because of the different supported languages.
|NTSC||iiii xy00 ssoo oooo||Japanese, English entries|
|PAL||iiii xy00 ssoo oooo||English entries|
|PAL||ssoo oooo||German, French entries|
- i = Message Id. This is the two byte number addressed by actors. 0xFFFC contains a character set used for the Title Screen's "PRESS START" and "NO CONTROLLER" logos, as well as the File Select screen. 0xFFFD marks the end offset of the last valid text box. 0xFFFF marks the end of the table for that language
- x = Text box type
- y = Text box y position
- s = Segment Id. 07 for English/German/French text banks, 08 for Japanese
- o = Message offset, relative to the start of the text bank file (*_message_data_static)
In NTSC versions, only the Japanese message entry table contains data for Message Id 0xFFFC.
In PAL versions, only the English message entry table contains data for Message ID 0xFFFC.
The start and end segment address for message Id 0xFFFC is hardcoded within a function that loads the "File Select" character set.
In NTSC versions, the Japanese entries are listed one after another until id 0xFFFF is encountered, then is followed with the English entries.
In PAL version, the English entries are listed first and use the same format as NTSC, but the the German and French tables that follow (in that order) afterwards simply list the bank/offset addresses for each message. This means two things:
- Changing the textbox settings for the English table in PAL will change the settings for the other two languages (if you wanted to support multiple languages)
- The NTSC Japanese/English and PAL's English/German/French tables end up being the same size
Text box types
0 = Black box 1 = Wooden box 2 = Blue box 3 = Ocarina input box 4 = No box, fixed to bottom of screen, no vertical centering 5 = No box, text shadow is disabled
Note: Text colors are altered for Type 1 and 5
Text box position values
0 = Top/bottom screen (maybe influenced by view angle) 1 = Top screen 2 = Middle screen 3 = Bottom screen
- The message offset should NOT be pointing to a 00 (null) byte, as it would freeze the game. It must point to a valid character or text control code.
- Message length is determined by looking at the address of the next message. If the following address is equal to the current address, the game will softlock when the message should be displayed. If the following address is less than the current address, the game will freeze (information by DeathBasket).
- Invalid Message IDs seem to result in the first message (0001: obtaining the Pocket Egg) being called up instead
This information is only fully valid for Ocarina of Time. Majora's Mask has its own format.
Also note that only Japanese text has its own codes and values; other languages share a common set.
|04||81A5||Box Break; begin next message box.|
|05 xx||000B xxxx||Color the following text with color xx.|
|06 xx||86C7 00xx||Shift text that follows it x pixels to the right.|
|07 xx xx||81CB xxxx||Go to (follow up with) Message ID xxxx.|
|08||8189||Enable instantaneous text.|
|09||818A||Disable instantaneous text.|
|0A||86C8||Keep message box opened; no reaction to buttons. Used in shop item descriptions.|
|0B||819F||Trigger an event? Used in minigame text, shop text, sidequest text, fairy fountains, and when being rewarded by uncursed skulltulas, among others. Used to indicate receiving something, perhaps? Appears to always occur before 02 (End Marker).|
|0C xx||81A3 00xx||Box Break with delay; wait xx visual frames before next message box.|
|0D||????||(Unused?) Wait for button press, continue in same box or line.|
|0E xx||819E 00xx||Fade out after waiting xx visual frames?|
|0F||874F||Print the player's name.|
|10||81F0||Initialize Ocarina playing.|
|11||????||(Unused?) Fade out and wait; ignore following text.|
|12 xxxx||81F3 xxxx||Play sound effect xxxx.|
|13 xx||819A 00xx||Display icon xx.|
|14 xx||86C9 00xx||Set text speed to xx. (Delay printing each character by xx frames.)|
|15 xx xx xx||86B3 00xx xxxx||Set message background to xxxxxx. Values unknown.|
|16||8791||Print Marathon time.|
|17||8792||Print Race time.|
|18||879B||Print number of points.|
|19||86A3||Print number of Gold Skulltulas collected.|
|1A||8199||Prevent the following text from being skipped by the B button.|
|1B||81BC||Initialize a two-choice selection.|
|1C||81B8||Initialize a three-choice selection.|
|1D||86A4||Print the length (Japanese only) or weight of the caught fish.|
|1E xx||869F 00xx||Print various highscore values.|
|1F||81A1||Print the in-game world time.|
|9F||839F||[A] Button Icon.|
|A0||83A0||[B] Button Icon.|
|A1||83A1||[C] Button Icon.|
|A2||83A2||[L] Button Icon.|
|A3||83A3||[R] Button Icon.|
|A4||83A4||[Z] Button Icon.|
|A5||83A5||[C Up] Button Icon.|
|A6||83A6||[C Down] Button Icon.|
|A7||83A7||[C Left] Button Icon.|
|A8||83A8||[C Right] Button Icon.|
|A9||83A9|| Triangle: ▼.
Used in Z-targeting description.
|AA||83AA||[Control Stick] Icon.|
|AB||83AB||[D-Pad] Icon. Unused.|
1 î was incorrectly changed to Á in the GameCube releases. The VWF is still set for î, and it messes up the French and possibly German text. Debug is correct.
Only the 4 lowest bits are used to determine color, even though they are specified as 0x40 - 0x47 and 0x0C00 - 0x0C07.
Any value above 7 will execute the same code as value 0, and therefore have the same color.
|Value||JP Value||Default Colors||Type 1 Colors||Type 5 Colors|
|44||0C04||Light Blue||#64B4FF||Light Blue||#5AB4FF|
Note that even though type 1 color 42 / 02 is the same as default, it is separate in code.
Sound Effects Used in Text Boxes
Because the original releases of Ocarina of Time lack filenames for audio files, the names below were taken from the 3DS remake of the game and applied retroactively.
|28DF||NA_SE_EV_COW_CRY||Environment - Cow - Cry||Cow - Moo|
|28E3||NA_SE_EV_FROG_CRY_0||Environment - Frog - Cry - 0||Frog - Croak When Jumping in Water|
|28E4||NA_SE_EV_FROG_CRY_1||Environment - Frog - Cry - 1||Frog - Croak After Increasing in Size|
|3880||NA_SE_EN_NUTS_DAMAGE||Enemy - Scrub - Damage||Mad Scrub - Take Damage|
|3882||NA_SE_EN_NUTS_FAINT||Enemy - Scrub - Faint||Business Scrub - Squeak|
|38EC||NA_SE_EN_PO_LAUGH||Enemy - Poe - Laugh||Poe - Laugh|
|4807||NA_SE_SY_TRE_BOX_APPEAR||System - Treasure - Chest - Appear|| Reveal Treasure Chest|
Play Song Correctly
|6844||NA_SE_VO_NA_HELLO_3||Voice - Navi - Hello - 3||Navi - "H'lo!"|
|6852||NA_SE_VO_TA_CRY_0||Voice - Talon - Cry - 0||Talon - "Huh?"|
|6855||NA_SE_VO_IN_LOST||Voice - Ingo - Lost||Ingo & Carpenter Boss - Frustrated|
|685F||NA_SE_VO_NA_HELLO_2||Voice - Navi - Hello - 2||Navi - "Hey!"|
|6863||NA_SE_VO_RT_LAUGH_0||Voice - Ruto - Laugh - 0||Ruto - Laugh|
|6867||NA_SE_VO_ST_DAMAGE||Voice - Skulltula - Damage||Cursed Skulltula Man - Scared of Mask|
|6869||NA_SE_VO_Z0_HURRY||Voice - Zelda 0 - Hurry||Child Zelda - Gasp Before Retelling Legend|
|686B||NA_SE_VO_Z0_QUESTION||Voice - Zelda 0 - Question||Child Zelda - Question Link's Honesty|
|686C||NA_SE_VO_Z0_SIGH_0||Voice - Zelda 0 - Sigh - 0||Child Zelda - Sigh|
|686D||NA_SE_VO_Z0_SMILE_0||Voice - Zelda 0 - Smile - 0||Child Zelda - Laugh Gently|
|00||Horseback Archery Score|
|03||Horse Race Time|
|06||Dampé Race Time|
JP: 8440: Hylian character set (~48 characters)
Non-JP: 00 is used as padding after an end marker; both 00 and 03 yield garbage when used in a message.