This document provides high-level information about text handling in Majora's Mask and the text manipulation tools provided by EZTR. This is not meant to be an in-depth guide to everything related to EZTR and Majora's Mask text, but a quick overview to get you started with EZTR.
If you want a more in-depth look at Majora's Mask text handling, I recommend this page: https://wiki.cloudmodding.com/mm/Text_Format
EZTR makes no changes to how the messages and text data in Majora's Mask are structured, stored, and processed. Therefore, any information relevant to text in vanilla Majora's Mask should be applicable to EZTR.
In brief, the first 11 bytes of a message are a header, with the content of the message itself following after. The header is laid out in the following way:
0xFFFF
or the EZTR_NO_VALUE
macro.0xFFFF
or the EZTR_NO_VALUE
macro.0xFFFF
or the EZTR_NO_VALUE
macro.All data after the header is considered part of the message content.
The text encoding of the message content is non-standard: while all the printable characters are standard ASCII, the control codes are not. Of particular note, the termination character is \xBF
rather than \x00
(also written as \0
). Most of the control codes are documented on the Control_Code_Macros page.
The header and content regions combined cannot be more than 1280 bytes, as that is the maximum size of the vanilla buffer. Since the header is 11 bytes, that leaves 1269 bytes for the content region.
Depending on what you're doing, you may not need to work with message buffers directly. For example, while EZTR does store messages as preconstructed message buffers, the functions EZTR_Basic_ReplaceText, EZTR_Basic_AddCustomText, and EZTR_Basic_ReplaceCustomText all construct and store the message buffer for you. The only consideration you'll need to make is the maximum size of the content
variable in each case, since that region cannot be larger than 1269 bytes.
Some cases where you'd work with the message buffer directly include:
To begin with, EZTR uses the type EZTR_MsgBuffer to represent the Majora's Mask message buffer. It's a union between a couple different ways to represent the message buffer information. Of particular note is the data
member, which lets you assign to each part of the header as well as the content region by treating the buffer as a packed struct. Read the type's own documentation for more details.
EZTR also provides many functions for operating on message buffers (too many to list here). These functions are broken up into two categories:
MsgBuffer provides general operations such as creating and destroying buffers, copying from one buffer to another, and getting the size of the data on the buffer. It also provides getters and setters for the buffer's header data (as an alternative to the packed struct).
MsgSContent provides string operations designed to work with the unique encoding of Majora's Mask message data. It includes reimplemented versions of standard C functions such as str[n]cpy
, str[n]cmp
, str[n]len
, str[n]cat
, and even [s[n]]printf
. Note that these functions are designed to operate on any \xBF
-terminated char
array, not just the content region of message buffers. As a result, if you want to operate on a message buffer's content, you'll need a pointer to the content region. You can get this using the EZTR_MsgBuffer_GetContentPtr function, or the data.content
member of EZTR_MsgBuffer.
The most common time you'll use a message buffer directly is when using EZTR's message callbacks to create dynamically generated messages.
EZTR makes message callbacks easy to set up, as EZTR provides a macro that simplifies declaring callback functions. See EZTR_MSG_CALLBACK for more information.
When run, the callback will receive an EZTR_MsgBuffer
pointer. The lifetime of this buffer is managed by EZTR internally, and therefore you should NOT try to destroy it.
The buffer will be prepopulated with a copy of the message data EZTR has stored, which will then be passed on to the Majora's Mask message handler to be displayed.
For example, consider this code used by the Forms Use More Items mod. We define the message replacement with the header options we want and a default message. Then, when the message is loaded, day_1_and_2_callback
is called, letting us overwrite the content of the message if appropriate.
If needed, you can create your own instances of EZTR_MsgBuffer using EZTR_MsgBuffer_Create or one of its related functions. This enables more advanced use cases of EZTR, such as constructing messages or replacements using data from an external source.
Keep in mind:
char*
, as long as it's \xBF
-terminated.