Skip to content
Abdyy edited this page Aug 25, 2026 · 59 revisions

MSBT, short for Message Studio Binary Text is a file format used to store messages linked to labels. PylibMS offers several functions used for dealing with these files.

Reading

from lms.message.msbtio import read_msbt_path

msbt = read_msbt_path("path/to/msbt")

Any IOBase, BytesIO, bytearray, memoryview, or bytes stream object can be passed instead when reading. Useful for msbts embedded into archive files.

from lms.message.msbtio import read_msbt

stream = b"" # Data here
msbt = read_msbt(stream) 

stream = memoryview(b"")
msbt = read_msbt(stream) 

stream = BytesIO(b"")
msbt = read_msbt(stream) 

Writing

from lms.message.msbtio import write_msbt_path

write_msbt_path("path/to/msbt", msbt)

If the raw data is needed, write_msbt can be utilized

from lms.message.msbtio import write_msbt

raw_data = write_msbt(msbt)

MSBTEntries are a container for all the data stored per label entry in the MSBT.

Properties

  • name: the name (sometimes called label) of the entry.
  • message: the message text object of the entry.
  • attribute: the attribute for the entry.
  • style_index: the style index of the entry.

Accessing

# By index
entry = msbt.get_entry_by_index(4)
# By name
entry = msbt.get_entry_by_name("Entry04")

Deleting

msbt.delete_entry(entry)

Messages

Text and control tag related data is accessed through a LMS_MessageText object. This class gives extra tag manipulation functionality.

Text

message = entry.message
message.text
# >>> "Hi"

Control Tags

Control tags are bb-code formatted form of tags that alters the properties of a message or inserts text. PylibMS offers additional tag viewing option and manipulation functions.

Tag Formats

Tags parsed from PylibMS may be encoded or decoded. The type of tag is determined by it's parameters.

  • Encoded: [1:3 00-00-00-CD]
  • Encoded: [Mii:Nickname 01-00-00-CD]
  • Decoded: [System:Color r="0" g="0" b="0" a="255"]
  • Decoded: [Reference:SpecialProduct buffer="0" type="Name" sp="Plural"]

The value preceding the colon is always the tag group, and value after is the index/name of the tag in that group. When a config is provided, they are replaced by their names. Tag groups are a container that group related tags together.

Tags modify messages in unique ways and are game-specifc. In some cases, closing tags (i.e [/Group:Tag] is a closing tag) may be used to indicate where the region the tag affects ends.

Tag Properties

Both types of tags are stored as LMS_EncodedTag and LMS_DecodedTag objects. Both share the following properties:

  • group_id: The ID of the group.
  • tag_index: The index of the tag in the group.
  • parameters: The parameters for the tag. May be a list of hex strings or a LMS_FieldMap.
  • is_closing: Determines if the tag is a closing tag

Decoded Specific attributes

  • group_name: The name of the group for the game.
  • tag_name: The name of the tag in the group.
  • description: The description of the tag.

Decoded tags loaded from a TitleConfig.

Internally,LMS_MessageText stores message data as a list splitting the text by its tags. As a result, the object can be iterated directly, allowing you to loop given raw text and tags.

from lms.message.tags.lms_tag import LMS_EncodedTag, LMS_DecodedTag

entry = msbt.get_entry_by_name("Entry00")

for part in entry.message:
    match part:
       case LMS_DecodedTag():
          ... # Decoded info actions
       case LMS_EncodedTag():
         ... # Encoded info actions
       case _:
         ... # Anything to do with raw text

Alternative option is importing the is_tag TypeGuard to catch both tag types.

from lms.message.tags.lms_tag import is_tag

for part in entry.message:
    if is_tag(part):
       ...

The list of control tags can be retrieved from the current message through the message.tags property.

Adding and modifying tags.

Several functions can be utilized to add and modify control tags in messages. In both cases, the resulting tag that was created is returned to the user.

# Appending an encoded tag (Same as '[1:3 00-00-00-CD]')
tag = message.append_encoded_tag(1, 3, 0x00, 0x00 , 0x16, 0xCD)

Note: if you are attempting to add an uneven amount of parameters, the byte 0xCD will automatically be appended to the parameter list.

# Appending an decoded tag (Same as '[Reference:SpecialProduct buffer="0" type="Name" sp="Plural"]')
tag = message.append_decoded_tag("Reference", "SpecialProduct", buffer=0, type="Name", sp="Plural")

Tags may also be added from their string representation. It'll automatically detect if the argument is an encoded or decoded tag.

tag = message.append_tag_string('[1:3 00-00-00-CD]')
tag = message.append_tag_string('[/2:3]')
tag = message.append_tag_string('[Reference:SpecialProduct buffer="0" type="Name" sp="Plural"]']
tag = message.append_tag_string('[/Edward:ToLowerRange]')

You may also access and edit the parameters of the tags. Values are verified when they are modified, so ensure they follow the boundaries of the datatype.

# Decoded Editing
tag = message.append_decoded_tag("Reference", "SpecialProduct", buffer=0, type="Name", sp="Plural")
buffer_field = tag.parameters["buffer"] 
tag.parameters["buffer"] = 43

Attributes

Attributes are LMS_FieldMaps mapped to each label in a MSBT file. These may be byte objects when encoded, and LMS_Fields when decoded, depending on if a TitleConfig is provided.

# Encoded attributes (by default)
msbt = read_msbt(stream)
entry = msbt.get_entry_by_name("Entry00")
entry.attribute
# >>> b"\x01\x01\x00\x00"
# Decoded attributes
main_attr_config = config.get_attribute_config("Main")
msbt = read_msbt(stream, attribute_config=main_attr_config)
entry = msbt.get_entry_by_name("Entry00")
entry.attribute
# >>> {"RegionJP": LMS_Field(value="Enabled"), "RegionEU": LMS_Field(value="Enabled"), "RegionEU": LMS_Field(value="Disabled"), "RegionKR": LMS_Field(value="Disabled"))

Style Indexes

The index of styles in a MSBP object is located in the MSBTEntry object through the style_index property, and the style object can be accessed through a MSBP object.

index = entry.style_index
style = msbp.styles[index]
# >>> LMS.Project.Definitions.Style.LMS_Style object at 0x00

Creating a MSBT

A new MSBT file may be created from scratch using the new classmethod and entries can be added to it.

from lms.message.msbt import MSBT
from lms.message.msbtentry import MSBTEntry

msbt = MSBT.new()
msbt.add_entry(MSBTEntry("Entry00")) # Defaults to empty text
msbt.add_entry(MSBTEntry("Entry01", message="Hello!"))

It is worth noting that apart from text, if an entry adds an atttribute or style_index, every single entry must define one as well. Since MSBT files store data for every single entry in every single block (even if they may be unused).

Pass in a config to add decoded attributes and tags

from lms.titleconfig.config import TitleConfig
from lms.message.msbtentry import MSBTEntry

config = TitleConfig.load_file("Config.yaml")

msbt = MSBT.new(tag_config=config.tag_config, attribute_config=config.attribute_config["Main"])
msbt.add_entry(MSBTEntry(
    "Entry01",
    text='Hello [System:Color r="255" g="0" b="0" a="255"]Bro[System:Color r="0" g="0" b="0" a="255"].',
    attribute={
        "text_speed": 3,
        "fixed_width": False
    },
    style_index=2
))

The default info for a MSBT object is:

  • Little endian
  • UTF-16 Encoding
  • Version 3
  • Section count 2

These parameters can be modified if needed.

from lms.fileio.encoding import FileEncoding

msbt = MSBT.new(is_big_endian=True, encoding=FileEncoding.UTF8, version=4)

If your MSBT uses the NLI1 section, this can be specified as an argument.

msbt = MSBT.new(uses_nli1=True, encoding=FileEncoding.UTF8, version=4)

Wiki Home

Home

File Formats

LMS Objects & Enums

TitleConfig

Clone this wiki locally