PyLibMS 3.1.8__tar.gz → 3.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pylibms-3.1.8 → pylibms-3.2.0}/PKG-INFO +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/PyLibMS.egg-info/PKG-INFO +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/fileio/io.py +7 -7
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/section/atr1.py +7 -4
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/section/txt2.py +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/tag/io/param_io.py +9 -7
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/ali2.py +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/string.py +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/tag2.py +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/tgg2.py +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/tgp2.py +2 -2
- {pylibms-3.1.8 → pylibms-3.2.0}/pyproject.toml +1 -1
- {pylibms-3.1.8 → pylibms-3.2.0}/LICENSE +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/MANIFEST.in +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/PyLibMS.egg-info/SOURCES.txt +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/PyLibMS.egg-info/dependency_links.txt +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/PyLibMS.egg-info/requires.txt +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/PyLibMS.egg-info/top_level.txt +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/README.md +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/common/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/common/lms_datatype.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/common/lms_exceptions.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/common/lms_fileinfo.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/common/stream/fileinfo.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/common/stream/hashtable.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/common/stream/section.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/fileio/encoding.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/definitions/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/definitions/field/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/definitions/field/io.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/definitions/field/lms_field.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/definitions/lms_messagetext.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/msbt.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/msbtentry.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/msbtio.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/section/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/section/tsy1.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/tag/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/tag/io/tag_io.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/tag/lms_tag.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/message/tag/lms_tagexceptions.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/definitions/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/definitions/attribute.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/definitions/color.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/definitions/style.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/definitions/tag.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/msbp.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/msbpread.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/ati2.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/clr1.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/project/section/syl3.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/config.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/definitions/__init__.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/definitions/attribute.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/definitions/tags.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/definitions/value.py +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Badge Arcade.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Brain Age Concentration Training.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Kirby Planet Robobot.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Super Mario 3D Land.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Super Mario 3D World + Bowsers Fury.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Super Mario Odyssey.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/The Legend of Zelda Echos of Wisdom.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/The Legend of Zelda a Link Between Worlds.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Tomodachi Life.yaml +0 -0
- {pylibms-3.1.8 → pylibms-3.2.0}/setup.cfg +0 -0
|
@@ -93,7 +93,7 @@ class FileReader:
|
|
|
93
93
|
def read_string_len(self, length: int) -> str:
|
|
94
94
|
return self._stream.read(length).decode("UTF-8")
|
|
95
95
|
|
|
96
|
-
def
|
|
96
|
+
def read_encoded_string(self):
|
|
97
97
|
message = b""
|
|
98
98
|
while (
|
|
99
99
|
raw_char := self.read_bytes(self.encoding.width)
|
|
@@ -101,7 +101,7 @@ class FileReader:
|
|
|
101
101
|
message += raw_char
|
|
102
102
|
return message.decode(self.encoding.to_string_format(self.is_big_endian))
|
|
103
103
|
|
|
104
|
-
def
|
|
104
|
+
def read_len_string_encoded(self):
|
|
105
105
|
self.align(self.encoding.width)
|
|
106
106
|
length = self.read_uint16()
|
|
107
107
|
return self.read_bytes(length).decode(
|
|
@@ -138,7 +138,7 @@ class FileWriter:
|
|
|
138
138
|
return self.data.tell()
|
|
139
139
|
|
|
140
140
|
def write_alignment(self, data: bytes, alignment: int) -> None:
|
|
141
|
-
self.write_bytes(data * self.
|
|
141
|
+
self.write_bytes(data * self._align(self.tell(), alignment))
|
|
142
142
|
|
|
143
143
|
def write_uint16_array(self, array: list[int]) -> None:
|
|
144
144
|
for number in array:
|
|
@@ -168,18 +168,18 @@ class FileWriter:
|
|
|
168
168
|
def write_string(self, string: str):
|
|
169
169
|
self.write_bytes(string.encode("UTF-8"))
|
|
170
170
|
|
|
171
|
-
def
|
|
171
|
+
def write_len_encoded_string(self, string: str) -> None:
|
|
172
172
|
self.write_uint16(len(string) * self.encoding.width)
|
|
173
|
-
self.
|
|
173
|
+
self.write_encoded_string(string, False)
|
|
174
174
|
|
|
175
|
-
def
|
|
175
|
+
def write_encoded_string(self, string: str, terminate: bool = True):
|
|
176
176
|
self.write_bytes(
|
|
177
177
|
string.encode(self.encoding.to_string_format(self.is_big_endian))
|
|
178
178
|
)
|
|
179
179
|
if terminate:
|
|
180
180
|
self.write_bytes(b"\x00" * self.encoding.width)
|
|
181
181
|
|
|
182
|
-
def
|
|
182
|
+
def _align(self, number: int, alignment: int) -> int:
|
|
183
183
|
return (-number % alignment + alignment) % alignment
|
|
184
184
|
|
|
185
185
|
def _get_datatype(self, name: str) -> str:
|
|
@@ -3,8 +3,11 @@ from dataclasses import dataclass
|
|
|
3
3
|
from lms.common.lms_datatype import LMS_DataType
|
|
4
4
|
from lms.fileio.io import FileReader, FileWriter
|
|
5
5
|
from lms.message.definitions.field.io import read_field, write_field
|
|
6
|
-
from lms.message.definitions.field.lms_field import (
|
|
7
|
-
|
|
6
|
+
from lms.message.definitions.field.lms_field import (
|
|
7
|
+
LMS_DataType,
|
|
8
|
+
LMS_Field,
|
|
9
|
+
LMS_FieldMap,
|
|
10
|
+
)
|
|
8
11
|
from lms.titleconfig.definitions.attribute import AttributeConfig
|
|
9
12
|
|
|
10
13
|
|
|
@@ -54,7 +57,7 @@ def read_decoded_atr1(reader: FileReader, config: AttributeConfig) -> ATR1Data:
|
|
|
54
57
|
if definition.datatype is LMS_DataType.STRING:
|
|
55
58
|
last = reader.tell() + 4
|
|
56
59
|
reader.seek(section_start + reader.read_uint32())
|
|
57
|
-
value = LMS_Field(reader.
|
|
60
|
+
value = LMS_Field(reader.read_encoded_string(), definition)
|
|
58
61
|
reader.seek(last)
|
|
59
62
|
else:
|
|
60
63
|
value = read_field(reader, definition)
|
|
@@ -109,4 +112,4 @@ def write_decoded_atr1(
|
|
|
109
112
|
write_field(writer, field)
|
|
110
113
|
|
|
111
114
|
for string in string_table:
|
|
112
|
-
writer.
|
|
115
|
+
writer.write_encoded_string(string)
|
|
@@ -58,7 +58,7 @@ def write_txt2(writer: FileWriter, messages: list[LMS_MessageText]) -> None:
|
|
|
58
58
|
if isinstance(part, (LMS_EncodedTag, LMS_DecodedTag)):
|
|
59
59
|
write_tag(writer, part)
|
|
60
60
|
else:
|
|
61
|
-
writer.
|
|
61
|
+
writer.write_encoded_string(part, False)
|
|
62
62
|
|
|
63
63
|
writer.write_bytes(writer.encoding.terminator)
|
|
64
64
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
from typing import cast
|
|
2
2
|
|
|
3
|
-
from common.lms_datatype import is_string_datatype
|
|
3
|
+
from lms.common.lms_datatype import is_string_datatype
|
|
4
4
|
from lms.common.lms_datatype import LMS_DataType
|
|
5
5
|
from lms.fileio.io import FileReader, FileWriter
|
|
6
6
|
from lms.message.definitions.field.io import read_field, write_field
|
|
7
7
|
from lms.message.definitions.field.lms_field import LMS_Field, LMS_FieldMap
|
|
8
|
-
from lms.message.tag.lms_tagexceptions import (
|
|
9
|
-
|
|
8
|
+
from lms.message.tag.lms_tagexceptions import (
|
|
9
|
+
LMS_TagReadingError,
|
|
10
|
+
LMS_TagWritingException,
|
|
11
|
+
)
|
|
10
12
|
from lms.titleconfig.definitions.tags import TagDefinition
|
|
11
13
|
|
|
12
14
|
TAG_PADDING_BYTE = b"\xcd"
|
|
@@ -30,12 +32,12 @@ def read_decoded_parameters(
|
|
|
30
32
|
param_offset = reader.tell()
|
|
31
33
|
try:
|
|
32
34
|
if param.datatype is LMS_DataType.STRING:
|
|
33
|
-
value = LMS_Field(reader.
|
|
35
|
+
value = LMS_Field(reader.read_len_string_encoded(), param)
|
|
34
36
|
else:
|
|
35
37
|
value = read_field(reader, param)
|
|
36
38
|
except Exception as e:
|
|
37
39
|
raise LMS_TagReadingError(
|
|
38
|
-
f"An error
|
|
40
|
+
f"An error occurred reading tag '[{definition.group_name}:{definition.tag_name}]', parameter '{param.name}' at offset {param_offset}"
|
|
39
41
|
) from e
|
|
40
42
|
|
|
41
43
|
parameters[param.name] = value
|
|
@@ -75,12 +77,12 @@ def write_decoded_parameters(
|
|
|
75
77
|
writer.write_bytes(TAG_PADDING_BYTE)
|
|
76
78
|
needs_padding = False
|
|
77
79
|
|
|
78
|
-
writer.
|
|
80
|
+
writer.write_len_encoded_string(field.value)
|
|
79
81
|
else:
|
|
80
82
|
write_field(writer, field)
|
|
81
83
|
except Exception as e:
|
|
82
84
|
raise LMS_TagWritingException(
|
|
83
|
-
f"An error
|
|
85
|
+
f"An error occurred in tag [{group_name}:{tag_name} writing parameter '{field.name}' at offset {writer.tell()}!"
|
|
84
86
|
) from e
|
|
85
87
|
|
|
86
88
|
if needs_padding:
|
|
@@ -12,7 +12,7 @@ def read_ali2(reader: FileReader) -> list[list[str]]:
|
|
|
12
12
|
item_count = reader.read_uint32()
|
|
13
13
|
for offset in reader.read_offset_array(item_count):
|
|
14
14
|
reader.seek(offset)
|
|
15
|
-
items.append(reader.
|
|
15
|
+
items.append(reader.read_encoded_string())
|
|
16
16
|
|
|
17
17
|
attr_lists.append(items)
|
|
18
18
|
|
|
@@ -12,6 +12,6 @@ def read_strings(reader: FileReader, four_byte_count: bool) -> list[str]:
|
|
|
12
12
|
|
|
13
13
|
for offset in reader.read_offset_array(count):
|
|
14
14
|
reader.seek(offset)
|
|
15
|
-
string_list.append(reader.
|
|
15
|
+
string_list.append(reader.read_encoded_string())
|
|
16
16
|
|
|
17
17
|
return string_list
|
|
@@ -11,7 +11,7 @@ def read_tag2(reader: FileReader) -> list[LMS_TagDefinition]:
|
|
|
11
11
|
|
|
12
12
|
param_count = reader.read_uint16()
|
|
13
13
|
parameter_indexes = reader.read_uint16_array(param_count)
|
|
14
|
-
name = reader.
|
|
14
|
+
name = reader.read_encoded_string()
|
|
15
15
|
|
|
16
16
|
info_list.append(LMS_TagDefinition(name, parameter_indexes))
|
|
17
17
|
|
|
@@ -16,7 +16,7 @@ def read_tgg2(reader: FileReader, version: int) -> list[LMS_TagGroup]:
|
|
|
16
16
|
tag_count = reader.read_uint16()
|
|
17
17
|
tag_indexes = reader.read_uint16_array(tag_count)
|
|
18
18
|
|
|
19
|
-
name = reader.
|
|
19
|
+
name = reader.read_encoded_string()
|
|
20
20
|
group_list.append(LMS_TagGroup(name, group_id, tag_indexes))
|
|
21
21
|
|
|
22
22
|
return group_list
|
|
@@ -13,14 +13,14 @@ def read_tgp2(reader: FileReader) -> list[LMS_TagParamDefinition]:
|
|
|
13
13
|
datatype = LMS_DataType(reader.read_uint8())
|
|
14
14
|
|
|
15
15
|
if datatype is not LMS_DataType.LIST:
|
|
16
|
-
name = reader.
|
|
16
|
+
name = reader.read_encoded_string()
|
|
17
17
|
parameter_info.append(LMS_TagParamDefinition(name, datatype))
|
|
18
18
|
continue
|
|
19
19
|
|
|
20
20
|
reader.skip(1)
|
|
21
21
|
list_count = reader.read_uint16()
|
|
22
22
|
list_indexes = reader.read_uint16_array(list_count)
|
|
23
|
-
name = reader.
|
|
23
|
+
name = reader.read_encoded_string()
|
|
24
24
|
parameter_info.append(
|
|
25
25
|
LMS_TagParamDefinition(name, LMS_DataType.LIST, list_indexes)
|
|
26
26
|
)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "PyLibMS"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.2.0"
|
|
8
8
|
requires-python = ">=3.12"
|
|
9
9
|
description = "Python library built for the libMessageStudio (LMS) proprietary file formats from Nintendo. Supports MSBT, MSBP, and MSBF."
|
|
10
10
|
readme = "README.md"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Brain Age Concentration Training.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/Super Mario 3D World + Bowsers Fury.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{pylibms-3.1.8 → pylibms-3.2.0}/lms/titleconfig/presets/The Legend of Zelda Echos of Wisdom.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|