PyLibMS 5.0.2__py3-none-any.whl → 5.0.4__py3-none-any.whl

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.
Files changed (63) hide show
  1. lms/common/field/io.py +80 -80
  2. lms/common/field/lms_datatype.py +152 -152
  3. lms/common/field/lms_field.py +183 -183
  4. lms/common/lms_constants.py +12 -12
  5. lms/common/lms_exceptions.py +13 -13
  6. lms/common/lms_fileinfo.py +11 -11
  7. lms/common/stream/fileinfo.py +80 -80
  8. lms/common/stream/hashtable.py +88 -88
  9. lms/common/stream/section.py +57 -57
  10. lms/fileio/encoding.py +42 -42
  11. lms/fileio/io.py +198 -198
  12. lms/flowchart/definitions/lms_nodeexceptions.py +7 -7
  13. lms/flowchart/definitions/node.py +632 -632
  14. lms/flowchart/definitions/node_type.py +130 -130
  15. lms/flowchart/flw3.py +421 -421
  16. lms/flowchart/msbf.py +208 -208
  17. lms/flowchart/msbfio.py +139 -139
  18. lms/message/lms_messagetext.py +184 -184
  19. lms/message/msbt.py +271 -271
  20. lms/message/msbtentry.py +103 -103
  21. lms/message/msbtio.py +246 -246
  22. lms/message/section/atr1.py +115 -115
  23. lms/message/section/nli1.py +22 -22
  24. lms/message/section/tsy1.py +13 -13
  25. lms/message/section/txt2.py +67 -67
  26. lms/message/tag/io/param_io.py +91 -91
  27. lms/message/tag/io/tag_io.py +115 -115
  28. lms/message/tag/lms_tag.py +236 -236
  29. lms/message/tag/lms_tagexceptions.py +10 -10
  30. lms/project/definitions/attribute.py +32 -32
  31. lms/project/definitions/color.py +10 -10
  32. lms/project/definitions/style.py +10 -10
  33. lms/project/definitions/tag.py +137 -137
  34. lms/project/msbp.py +71 -71
  35. lms/project/msbpread.py +111 -111
  36. lms/project/section/ali2.py +22 -22
  37. lms/project/section/ati2.py +17 -17
  38. lms/project/section/clr1.py +15 -15
  39. lms/project/section/string.py +16 -16
  40. lms/project/section/syl3.py +17 -17
  41. lms/project/section/tag2.py +20 -20
  42. lms/project/section/tgg2.py +24 -24
  43. lms/project/section/tgp2.py +30 -30
  44. lms/titleconfig/config.py +301 -301
  45. lms/titleconfig/definitions/attribute.py +28 -28
  46. lms/titleconfig/definitions/field.py +32 -32
  47. lms/titleconfig/definitions/nodes.py +151 -151
  48. lms/titleconfig/definitions/tags.py +90 -90
  49. {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/METADATA +118 -117
  50. pylibms-5.0.4.dist-info/RECORD +67 -0
  51. {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/licenses/LICENSE +6 -6
  52. lms/titleconfig/presets/Badge Arcade.yaml +0 -430
  53. lms/titleconfig/presets/Brain Age Concentration Training.yaml +0 -132
  54. lms/titleconfig/presets/Kirby Planet Robobot.yaml +0 -209
  55. lms/titleconfig/presets/Super Mario 3D Land.yaml +0 -367
  56. lms/titleconfig/presets/Super Mario 3D World + Bowsers Fury.yaml +0 -200
  57. lms/titleconfig/presets/Super Mario Odyssey.yaml +0 -1961
  58. lms/titleconfig/presets/The Legend of Zelda Echos of Wisdom.yaml +0 -110
  59. lms/titleconfig/presets/The Legend of Zelda a Link Between Worlds.yaml +0 -383
  60. lms/titleconfig/presets/Tomodachi Life Living The Dream.yaml +0 -3369
  61. pylibms-5.0.2.dist-info/RECORD +0 -76
  62. {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/WHEEL +0 -0
  63. {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/top_level.txt +0 -0
lms/common/field/io.py CHANGED
@@ -1,80 +1,80 @@
1
- from typing import Callable
2
-
3
- from lms.common.field.lms_datatype import (
4
- LMS_DataType,
5
- is_bool_datatype,
6
- is_enum_datatype,
7
- is_number_datatype,
8
- )
9
- from lms.common.field.lms_field import LMS_Field
10
- from lms.fileio.io import FileReader, FileWriter
11
- from lms.titleconfig.definitions.field import FieldDefinition
12
-
13
-
14
- def read_field(
15
- reader: FileReader,
16
- definition: FieldDefinition,
17
- read_variable_width_value: Callable | None = None,
18
- ) -> LMS_Field:
19
- # String is excluded as their reading varies between MSBT/MSBF
20
- match definition.datatype:
21
- case LMS_DataType.UINT8:
22
- value = reader.read_uint8()
23
- case LMS_DataType.UINT16:
24
- value = reader.read_uint16()
25
- case LMS_DataType.UINT32:
26
- value = reader.read_uint32()
27
- case LMS_DataType.INT8:
28
- value = reader.read_int8()
29
- case LMS_DataType.INT16:
30
- value = reader.read_int16()
31
- case LMS_DataType.INT32:
32
- value = reader.read_int32()
33
- case LMS_DataType.FLOAT32:
34
- value = reader.read_float32()
35
- case LMS_DataType.ENUM:
36
- if read_variable_width_value is not None:
37
- index = read_variable_width_value()
38
- else:
39
- index = reader.read_uint8()
40
- value = definition.enum_members[index]
41
- case LMS_DataType.BOOL:
42
- if read_variable_width_value is not None:
43
- value = bool(read_variable_width_value())
44
- else:
45
- value = bool(reader.read_uint8())
46
-
47
- return LMS_Field(value, definition)
48
-
49
-
50
- def write_field(
51
- writer: FileWriter,
52
- field: LMS_Field,
53
- write_variable_width_value: Callable | None = None,
54
- ) -> None:
55
- if is_number_datatype(field.value, field.datatype):
56
- write_functions: dict[LMS_DataType, Callable] = {
57
- LMS_DataType.UINT8: writer.write_uint8,
58
- LMS_DataType.INT8: writer.write_int8,
59
- LMS_DataType.UINT16: writer.write_uint16,
60
- LMS_DataType.INT16: writer.write_int16,
61
- LMS_DataType.UINT32: writer.write_uint32,
62
- LMS_DataType.INT32: writer.write_int32,
63
- LMS_DataType.FLOAT32: writer.write_float32,
64
- }
65
- write_functions[field.datatype](field.value)
66
- return
67
-
68
- if is_enum_datatype(field.value, field.datatype):
69
- value = list(field.enum_members.values()).index(field.value)
70
- if write_variable_width_value is not None:
71
- write_variable_width_value(value)
72
- else:
73
- writer.write_uint8(value)
74
- elif is_bool_datatype(field.value, field.datatype):
75
- if write_variable_width_value is not None:
76
- write_variable_width_value(bool(field.value))
77
- else:
78
- writer.write_uint8(bool(field.value))
79
- else:
80
- raise ValueError(f"Unsupported datatype: {field.datatype}")
1
+ from typing import Callable
2
+
3
+ from lms.common.field.lms_datatype import (
4
+ LMS_DataType,
5
+ is_bool_datatype,
6
+ is_enum_datatype,
7
+ is_number_datatype,
8
+ )
9
+ from lms.common.field.lms_field import LMS_Field
10
+ from lms.fileio.io import FileReader, FileWriter
11
+ from lms.titleconfig.definitions.field import FieldDefinition
12
+
13
+
14
+ def read_field(
15
+ reader: FileReader,
16
+ definition: FieldDefinition,
17
+ read_variable_width_value: Callable | None = None,
18
+ ) -> LMS_Field:
19
+ # String is excluded as their reading varies between MSBT/MSBF
20
+ match definition.datatype:
21
+ case LMS_DataType.UINT8:
22
+ value = reader.read_uint8()
23
+ case LMS_DataType.UINT16:
24
+ value = reader.read_uint16()
25
+ case LMS_DataType.UINT32:
26
+ value = reader.read_uint32()
27
+ case LMS_DataType.INT8:
28
+ value = reader.read_int8()
29
+ case LMS_DataType.INT16:
30
+ value = reader.read_int16()
31
+ case LMS_DataType.INT32:
32
+ value = reader.read_int32()
33
+ case LMS_DataType.FLOAT32:
34
+ value = reader.read_float32()
35
+ case LMS_DataType.ENUM:
36
+ if read_variable_width_value is not None:
37
+ index = read_variable_width_value()
38
+ else:
39
+ index = reader.read_uint8()
40
+ value = definition.enum_members[index]
41
+ case LMS_DataType.BOOL:
42
+ if read_variable_width_value is not None:
43
+ value = bool(read_variable_width_value())
44
+ else:
45
+ value = bool(reader.read_uint8())
46
+
47
+ return LMS_Field(value, definition)
48
+
49
+
50
+ def write_field(
51
+ writer: FileWriter,
52
+ field: LMS_Field,
53
+ write_variable_width_value: Callable | None = None,
54
+ ) -> None:
55
+ if is_number_datatype(field.value, field.datatype):
56
+ write_functions: dict[LMS_DataType, Callable] = {
57
+ LMS_DataType.UINT8: writer.write_uint8,
58
+ LMS_DataType.INT8: writer.write_int8,
59
+ LMS_DataType.UINT16: writer.write_uint16,
60
+ LMS_DataType.INT16: writer.write_int16,
61
+ LMS_DataType.UINT32: writer.write_uint32,
62
+ LMS_DataType.INT32: writer.write_int32,
63
+ LMS_DataType.FLOAT32: writer.write_float32,
64
+ }
65
+ write_functions[field.datatype](field.value)
66
+ return
67
+
68
+ if is_enum_datatype(field.value, field.datatype):
69
+ value = list(field.enum_members.values()).index(field.value)
70
+ if write_variable_width_value is not None:
71
+ write_variable_width_value(value)
72
+ else:
73
+ writer.write_uint8(value)
74
+ elif is_bool_datatype(field.value, field.datatype):
75
+ if write_variable_width_value is not None:
76
+ write_variable_width_value(bool(field.value))
77
+ else:
78
+ writer.write_uint8(bool(field.value))
79
+ else:
80
+ raise ValueError(f"Unsupported datatype: {field.datatype}")
@@ -1,152 +1,152 @@
1
- from __future__ import annotations
2
-
3
- from enum import IntEnum, auto
4
- from typing import Type, TypeGuard
5
-
6
- FLOAT32_MIN = -3.4028235e38
7
- FLOAT32_MAX = 3.4028235e38
8
-
9
- ALIAS_MAP = {
10
- "u8": "UINT8",
11
- "u16": "UINT16",
12
- "u32": "UINT32",
13
- "i8": "INT8",
14
- "i16": "INT16",
15
- "i32": "INT32",
16
- "f32": "FLOAT32",
17
- "str": "STRING",
18
- # LIST fallback for ENUM datatype
19
- "list": "ENUM",
20
- "bool": "BOOL",
21
- }
22
-
23
-
24
- def is_number_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[int | float]:
25
- if isinstance(value, float) and datatype is LMS_DataType.FLOAT32:
26
- return True
27
-
28
- return datatype in (
29
- LMS_DataType.UINT8,
30
- LMS_DataType.UINT16,
31
- LMS_DataType.UINT32,
32
- LMS_DataType.INT8,
33
- LMS_DataType.INT16,
34
- LMS_DataType.INT32,
35
- ) and isinstance(value, int)
36
-
37
-
38
- def is_enum_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
39
- return datatype is LMS_DataType.ENUM and isinstance(value, str)
40
-
41
-
42
- def is_bool_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bool]:
43
- return datatype is LMS_DataType.BOOL and isinstance(value, bool)
44
-
45
-
46
- def is_bytes_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bytes]:
47
- return datatype is LMS_DataType.BYTES and isinstance(value, bytes)
48
-
49
-
50
- def is_string_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
51
- return datatype is LMS_DataType.STRING and isinstance(value, str)
52
-
53
-
54
- class LMS_DataType(IntEnum):
55
- """Enum that represents a datatype for a value entry in a MSBT/MSBP file."""
56
-
57
- UINT8 = 0
58
- UINT16 = 1
59
- UINT32 = 2
60
-
61
- INT8 = 3
62
- INT16 = 4
63
- INT32 = 5
64
-
65
- FLOAT32 = 6
66
-
67
- STRING = 8
68
- ENUM = 9
69
-
70
- # Interface type for UINT8
71
- BOOL = auto()
72
-
73
- @property
74
- def signed(self) -> bool:
75
- """Property for if the type is signed or not."""
76
- if self not in [
77
- self.STRING,
78
- self.ENUM,
79
- self.BOOL,
80
- ]:
81
- return self in [self.INT8, self.INT16, self.INT32]
82
-
83
- raise TypeError(f"Signed is not a valid property for '{self.name.lower()}'!")
84
-
85
- @property
86
- def builtin_type(self) -> Type[int | float | str | bool | bytes]:
87
- """The enum as the builtin python type."""
88
- return {
89
- self.UINT8: int,
90
- self.UINT16: int,
91
- self.UINT32: int,
92
- self.INT8: int,
93
- self.INT16: int,
94
- self.INT32: int,
95
- self.FLOAT32: float,
96
- self.STRING: str,
97
- self.ENUM: str,
98
- self.BOOL: bool,
99
- }[self]
100
-
101
- @property
102
- def stream_size(self) -> int:
103
- """Size of the datatype, only for fixed integers."""
104
- sizes = {
105
- self.UINT8: 1,
106
- self.UINT16: 2,
107
- self.UINT32: 4,
108
- self.INT8: 1,
109
- self.INT16: 2,
110
- self.INT32: 4,
111
- self.FLOAT32: 4,
112
- }
113
-
114
- try:
115
- return sizes[self]
116
- except KeyError:
117
- raise TypeError(f"Stream size is not defined for '{self.name.lower()}'.")
118
-
119
- @classmethod
120
- def from_string(cls, string: str):
121
- """Creates an enum value from its string representation"""
122
- member = string.upper()
123
- if member in cls.__members__:
124
- return cls[member]
125
-
126
- alias_member = ALIAS_MAP.get(string.lower())
127
- if alias_member is not None:
128
- return cls[alias_member]
129
- else:
130
- raise ValueError(f"Unknown value of '{string}' was provided!")
131
-
132
-
133
- def verify_number_from_datatype(
134
- value: int | float,
135
- datatype: LMS_DataType,
136
- ):
137
- if datatype is LMS_DataType.FLOAT32:
138
- max_value = FLOAT32_MAX
139
- min_value = FLOAT32_MIN
140
- else:
141
- bits = datatype.stream_size * 8
142
- if datatype.signed:
143
- min_value = -(2 ** (bits - 1))
144
- max_value = (2 ** (bits - 1)) - 1
145
- else:
146
- min_value, max_value = 0, (2 ** bits) - 1
147
-
148
- if not min_value <= value <= max_value:
149
- raise ValueError(
150
- f"""The value '{value}' of type '{datatype.name}' provided
151
- is out of range of ({min_value}, {max_value})"""
152
- )
1
+ from __future__ import annotations
2
+
3
+ from enum import IntEnum, auto
4
+ from typing import Type, TypeGuard
5
+
6
+ FLOAT32_MIN = -3.4028235e38
7
+ FLOAT32_MAX = 3.4028235e38
8
+
9
+ ALIAS_MAP = {
10
+ "u8": "UINT8",
11
+ "u16": "UINT16",
12
+ "u32": "UINT32",
13
+ "i8": "INT8",
14
+ "i16": "INT16",
15
+ "i32": "INT32",
16
+ "f32": "FLOAT32",
17
+ "str": "STRING",
18
+ # LIST fallback for ENUM datatype
19
+ "list": "ENUM",
20
+ "bool": "BOOL",
21
+ }
22
+
23
+
24
+ def is_number_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[int | float]:
25
+ if isinstance(value, float) and datatype is LMS_DataType.FLOAT32:
26
+ return True
27
+
28
+ return datatype in (
29
+ LMS_DataType.UINT8,
30
+ LMS_DataType.UINT16,
31
+ LMS_DataType.UINT32,
32
+ LMS_DataType.INT8,
33
+ LMS_DataType.INT16,
34
+ LMS_DataType.INT32,
35
+ ) and isinstance(value, int)
36
+
37
+
38
+ def is_enum_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
39
+ return datatype is LMS_DataType.ENUM and isinstance(value, str)
40
+
41
+
42
+ def is_bool_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bool]:
43
+ return datatype is LMS_DataType.BOOL and isinstance(value, bool)
44
+
45
+
46
+ def is_bytes_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bytes]:
47
+ return datatype is LMS_DataType.BYTES and isinstance(value, bytes)
48
+
49
+
50
+ def is_string_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
51
+ return datatype is LMS_DataType.STRING and isinstance(value, str)
52
+
53
+
54
+ class LMS_DataType(IntEnum):
55
+ """Enum that represents a datatype for a value entry in a MSBT/MSBP file."""
56
+
57
+ UINT8 = 0
58
+ UINT16 = 1
59
+ UINT32 = 2
60
+
61
+ INT8 = 3
62
+ INT16 = 4
63
+ INT32 = 5
64
+
65
+ FLOAT32 = 6
66
+
67
+ STRING = 8
68
+ ENUM = 9
69
+
70
+ # Interface type for UINT8
71
+ BOOL = auto()
72
+
73
+ @property
74
+ def signed(self) -> bool:
75
+ """Property for if the type is signed or not."""
76
+ if self not in [
77
+ self.STRING,
78
+ self.ENUM,
79
+ self.BOOL,
80
+ ]:
81
+ return self in [self.INT8, self.INT16, self.INT32]
82
+
83
+ raise TypeError(f"Signed is not a valid property for '{self.name.lower()}'!")
84
+
85
+ @property
86
+ def builtin_type(self) -> Type[int | float | str | bool | bytes]:
87
+ """The enum as the builtin python type."""
88
+ return {
89
+ self.UINT8: int,
90
+ self.UINT16: int,
91
+ self.UINT32: int,
92
+ self.INT8: int,
93
+ self.INT16: int,
94
+ self.INT32: int,
95
+ self.FLOAT32: float,
96
+ self.STRING: str,
97
+ self.ENUM: str,
98
+ self.BOOL: bool,
99
+ }[self]
100
+
101
+ @property
102
+ def stream_size(self) -> int:
103
+ """Size of the datatype, only for fixed integers."""
104
+ sizes = {
105
+ self.UINT8: 1,
106
+ self.UINT16: 2,
107
+ self.UINT32: 4,
108
+ self.INT8: 1,
109
+ self.INT16: 2,
110
+ self.INT32: 4,
111
+ self.FLOAT32: 4,
112
+ }
113
+
114
+ try:
115
+ return sizes[self]
116
+ except KeyError:
117
+ raise TypeError(f"Stream size is not defined for '{self.name.lower()}'.")
118
+
119
+ @classmethod
120
+ def from_string(cls, string: str):
121
+ """Creates an enum value from its string representation"""
122
+ member = string.upper()
123
+ if member in cls.__members__:
124
+ return cls[member]
125
+
126
+ alias_member = ALIAS_MAP.get(string.lower())
127
+ if alias_member is not None:
128
+ return cls[alias_member]
129
+ else:
130
+ raise ValueError(f"Unknown value of '{string}' was provided!")
131
+
132
+
133
+ def verify_number_from_datatype(
134
+ value: int | float,
135
+ datatype: LMS_DataType,
136
+ ):
137
+ if datatype is LMS_DataType.FLOAT32:
138
+ max_value = FLOAT32_MAX
139
+ min_value = FLOAT32_MIN
140
+ else:
141
+ bits = datatype.stream_size * 8
142
+ if datatype.signed:
143
+ min_value = -(2 ** (bits - 1))
144
+ max_value = (2 ** (bits - 1)) - 1
145
+ else:
146
+ min_value, max_value = 0, (2 ** bits) - 1
147
+
148
+ if not min_value <= value <= max_value:
149
+ raise ValueError(
150
+ f"""The value '{value}' of type '{datatype.name}' provided
151
+ is out of range of ({min_value}, {max_value})"""
152
+ )