tasd 1.0.0__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.
tasd/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ from tasd.file import TASD
2
+ import tasd.packets
3
+ import tasd.constants
4
+ import tasd.utils
tasd/constants.py ADDED
@@ -0,0 +1,56 @@
1
+ class _MetaPacketType():
2
+ def __init_subclass__(self):
3
+ keys = [key for key in self.__dict__.keys() if type(self.__dict__[key]) == int]
4
+ self._key2name = dict()
5
+ for key in keys:
6
+ self._key2name[self.__dict__[key]] = key
7
+
8
+ class PacketType(_MetaPacketType):
9
+ # General Keys
10
+ CONSOLE_TYPE = 0x0001
11
+ CONSOLE_REGION = 0x0002
12
+ GAME_TITLE = 0x0003
13
+ ROM_NAME = 0x0004
14
+ ATTRIBUTION = 0x0005
15
+ CATEGORY = 0x0006
16
+ EMULATOR_NAME = 0x0007
17
+ EMULATOR_VERSION = 0x0008
18
+ EMULATOR_CORE = 0x0009
19
+ TAS_LAST_MODIFIED = 0x000A
20
+ DUMP_CREATED = 0x000B
21
+ DUMP_LAST_MODIFIED = 0x000C
22
+ TOTAL_FRAMES = 0x000D
23
+ RERECORDS = 0x000E
24
+ SOURCE_LINK = 0x000F
25
+ BLANK_FRAMES = 0x0010
26
+ VERIFIED = 0x0011
27
+ MEMORY_INIT = 0x0012
28
+ GAME_IDENTIFIER = 0x0013
29
+ MOVIE_LICENSE = 0x0014
30
+ MOVIE_FILE = 0x0015
31
+ PORT_CONTROLLER = 0x00F0
32
+ PORT_OVERREAD = 0x00F1
33
+ # NES Specific Keys
34
+ NES_LATCH_FILTER = 0x0101
35
+ NES_CLOCK_FILTER = 0x0102
36
+ NES_GAME_GENIE_CODE = 0x0104
37
+ # SNES Specific Keys
38
+ SNES_LATCH_FILTER = 0x0201
39
+ SNES_CLOCK_FILTER = 0x0202
40
+ SNES_GAME_GENIE_CODE = 0x0204
41
+ SNES_LATCH_TRAIN = 0x0205
42
+ # Genesis Specific Keys
43
+ GENESIS_GAME_GENIE_CODE = 0x0804
44
+ # Input Frame/Timing Keys
45
+ INPUT_CHUNK = 0xFE01
46
+ INPUT_MOMENT = 0xFE02
47
+ TRANSITION = 0xFE03
48
+ LAG_FRAME_CHUNK = 0xFE04
49
+ MOVIE_TRANSITION = 0xFE05
50
+ # Extraneous Keys
51
+ COMMENT = 0xFF01
52
+ EXPERIMENTAL = 0xFFFE
53
+ UNSPECIFIED = 0xFFFF
54
+ @classmethod
55
+ def lookup(cls, key):
56
+ return cls._key2name.get(key, f'UNKNOWN_PACKET_{key:04X}')
tasd/file.py ADDED
@@ -0,0 +1,57 @@
1
+ import tasd.packets as packets
2
+ import tasd.constants as constants
3
+ import tasd.utils as utils
4
+ from tasd.packet import lookup_packet, _TASDPacket
5
+ from typing import List
6
+
7
+ class TASD():
8
+ MAGIC = b"TASD"
9
+ def __init__(self, version = 1, g_keylen = 2):
10
+ self.version = version
11
+ self.g_keylen = g_keylen
12
+ self.packets: List[_TASDPacket] = []
13
+ @classmethod
14
+ def from_bytes(cls, buffer: bytes, *, bypass_errors = False):
15
+ magic = utils.readBytes(buffer, 0, 4)
16
+ if magic != cls.MAGIC:
17
+ raise ValueError("Invalid TASD File, Missing Magic")
18
+ version = utils.readUint16(buffer, 4)
19
+ if version != 1 and not bypass_errors:
20
+ raise ValueError("Unsupported TASD File, Version Unsupported", version)
21
+ g_keylen = utils.readUint8(buffer, 6)
22
+ if g_keylen != 2:
23
+ raise ValueError("Unsupported TASD File, Unknown G_KEYLEN", g_keylen)
24
+ self = cls(version, g_keylen)
25
+ index = 7
26
+ while index < len(buffer):
27
+ key = utils.readUintN(buffer, index, self.g_keylen)
28
+ index += self.g_keylen
29
+ packet_cls = lookup_packet(key)
30
+ pexp = utils.readUint8(buffer, index)
31
+ index += 1
32
+ plen = utils.readUintN(buffer, index, pexp)
33
+ index += pexp
34
+ data = utils.readBytes(buffer, index, plen)
35
+ index += plen
36
+ packet = packet_cls.from_bytes(data)
37
+ self.packets.append(packet)
38
+ return self
39
+ def to_bytes(self):
40
+ header = bytearray(7)
41
+ header[0:4] = self.MAGIC
42
+ utils.writeUint16(self.version, header, 4)
43
+ utils.writeUint8(self.g_keylen, header, 6)
44
+ packets = [ header ]
45
+ for packet in self.packets:
46
+ plen = packet.size()
47
+ pexp = utils.minUint(plen)
48
+ size = self.g_keylen + 1 + pexp
49
+ buffer = bytearray(size)
50
+ utils.writeUintN(packet._key, buffer, 0, self.g_keylen)
51
+ utils.writeUint8(pexp, buffer, self.g_keylen)
52
+ utils.writeUintN(plen, buffer, self.g_keylen + 1, pexp)
53
+ payload = packet.to_bytes()
54
+ packets.append(buffer + payload)
55
+ return b"".join(packets)
56
+ def __repr__(self):
57
+ return f"TASD(version={self.version}, g_keylen={self.g_keylen})"
tasd/packet.py ADDED
@@ -0,0 +1,304 @@
1
+ from typing import NamedTuple, List, Any
2
+ from enum import Enum
3
+
4
+ from tasd.constants import PacketType
5
+ from tasd.utils import *
6
+
7
+ class _VariableType(Enum):
8
+ STRING_EOP = 0x00
9
+ STRING_PLEN = 0x01
10
+ STRING_PEXP = 0x02
11
+ BYTES_EOP = 0x10
12
+ BYTES_PLEN = 0x11
13
+ BYTES_PEXP = 0x12
14
+ INT_8 = 0x20
15
+ INT_16 = 0x21
16
+ INT_24 = 0x22
17
+ INT_32 = 0x23
18
+ INT_64 = 0x24
19
+ INT_N = 0x25
20
+ UINT_8 = 0x30
21
+ UINT_16 = 0x31
22
+ UINT_24 = 0x32
23
+ UINT_32 = 0x33
24
+ UINT_64 = 0x34
25
+ UINT_N = 0x35
26
+ BOOL = 0x40
27
+ LIST_UINT_64 = 0x50
28
+
29
+
30
+ class _VariableDefinition(NamedTuple):
31
+ name: str
32
+ type: _VariableType
33
+ default: Any
34
+
35
+ class _EnumDefinition(NamedTuple):
36
+ name: str
37
+ enum: Enum
38
+
39
+ class _TASDPacket():
40
+ @classmethod
41
+ def from_bytes(cls, buffer: bytes):
42
+ self = cls()
43
+ index = 0
44
+ for variable in cls._variables:
45
+ match variable.type:
46
+ case _VariableType.STRING_EOP:
47
+ setattr(self, variable.name, readString(buffer, index, len(buffer) - index))
48
+ index = len(buffer)
49
+ case _VariableType.STRING_PLEN:
50
+ plen = readInt8(buffer, index)
51
+ index += 1
52
+ setattr(self, variable.name, readString(buffer, index, plen))
53
+ index += plen
54
+ case _VariableType.STRING_PEXP:
55
+ pexp = readInt8(buffer, index)
56
+ index += 1
57
+ plen = readIntN(buffer, index, pexp)
58
+ index += pexp
59
+ setattr(self, variable.name, readString(buffer, index, plen))
60
+ index += plen
61
+ case _VariableType.BYTES_EOP:
62
+ setattr(self, variable.name, readBytes(buffer, index, len(buffer)))
63
+ index = len(buffer)
64
+ case _VariableType.BYTES_PLEN:
65
+ plen = readInt8(buffer, index)
66
+ index += 1
67
+ setattr(self, variable.name, readBytes(buffer, index, plen))
68
+ index += plen
69
+ case _VariableType.BYTES_PEXP:
70
+ pexp = readInt8(buffer, index)
71
+ index += 1
72
+ plen = readIntN(buffer, index, pexp)
73
+ index += pexp
74
+ setattr(self, variable.name, readBytes(buffer, index, plen))
75
+ index += plen
76
+ case _VariableType.INT_8:
77
+ setattr(self, variable.name, readInt8(buffer, index))
78
+ index += 1
79
+ case _VariableType.INT_16:
80
+ setattr(self, variable.name, readInt16(buffer, index))
81
+ index += 2
82
+ case _VariableType.INT_24:
83
+ setattr(self, variable.name, readInt24(buffer, index))
84
+ index += 3
85
+ case _VariableType.INT_32:
86
+ setattr(self, variable.name, readInt32(buffer, index))
87
+ index += 4
88
+ case _VariableType.INT_64:
89
+ setattr(self, variable.name, readInt64(buffer, index))
90
+ index += 8
91
+ case _VariableType.INT_N:
92
+ pexp = readInt8(buffer, index)
93
+ index += 1
94
+ setattr(self, variable.name, readIntN(buffer, index, pexp))
95
+ index += pexp
96
+ case _VariableType.UINT_8:
97
+ setattr(self, variable.name, readUint8(buffer, index))
98
+ index += 1
99
+ case _VariableType.UINT_16:
100
+ setattr(self, variable.name, readUint16(buffer, index))
101
+ index += 2
102
+ case _VariableType.UINT_24:
103
+ setattr(self, variable.name, readUint24(buffer, index))
104
+ index += 3
105
+ case _VariableType.UINT_32:
106
+ setattr(self, variable.name, readUint32(buffer, index))
107
+ index += 4
108
+ case _VariableType.UINT_64:
109
+ setattr(self, variable.name, readUint64(buffer, index))
110
+ index += 8
111
+ case _VariableType.UINT_N:
112
+ pexp = readUint8(buffer, index)
113
+ index += 1
114
+ setattr(self, variable.name, readUintN(buffer, index, pexp))
115
+ index += pexp
116
+ case _VariableType.BOOL:
117
+ setattr(self, variable.name, readBoolean(buffer, index))
118
+ index += 1
119
+ case _VariableType.LIST_UINT_64:
120
+ l = list()
121
+ while index < len(buffer):
122
+ l.append(readUint64(buffer, index))
123
+ index += 8
124
+ setattr(self, variable.name, l)
125
+ case _:
126
+ raise ValueError("Unknown Variable Type", variable)
127
+ return self
128
+ def size(self):
129
+ size = 0
130
+ for variable in self._variables:
131
+ value = getattr(self, variable.name)
132
+ match variable.type:
133
+ case _VariableType.STRING_EOP:
134
+ size += sizeString(value)
135
+ case _VariableType.STRING_PLEN:
136
+ size += ( 1 + sizeString(value) )
137
+ case _VariableType.STRING_PEXP:
138
+ vsize = sizeString(value)
139
+ size += ( 1 + minUint(vsize) + vsize )
140
+ case _VariableType.BYTES_EOP:
141
+ size += len(value)
142
+ case _VariableType.BYTES_PLEN:
143
+ size += ( 1 + len(value) )
144
+ case _VariableType.BYTES_PEXP:
145
+ vsize = len(value)
146
+ size += ( 1 + minUint(vsize) + vsize )
147
+ case _VariableType.INT_8:
148
+ size += 1
149
+ case _VariableType.INT_16:
150
+ size += 2
151
+ case _VariableType.INT_24:
152
+ size += 3
153
+ case _VariableType.INT_32:
154
+ size += 4
155
+ case _VariableType.INT_64:
156
+ size += 8
157
+ case _VariableType.INT_N:
158
+ size += minInt(value)
159
+ case _VariableType.UINT_8:
160
+ size += 1
161
+ case _VariableType.UINT_16:
162
+ size += 2
163
+ case _VariableType.UINT_24:
164
+ size += 3
165
+ case _VariableType.UINT_32:
166
+ size += 4
167
+ case _VariableType.UINT_64:
168
+ size += 8
169
+ case _VariableType.UINT_N:
170
+ size += minUint(value)
171
+ case _VariableType.BOOL:
172
+ size += 1
173
+ case _VariableType.LIST_UINT_64:
174
+ size += ( 8 * len(value) )
175
+ case _:
176
+ raise ValueError("Unknown Variable Type", variable)
177
+ return size
178
+ def to_bytes(self):
179
+ buffer = bytearray(self.size())
180
+ index = 0
181
+ for variable in self._variables:
182
+ value = getattr(self, variable.name)
183
+ match variable.type:
184
+ case _VariableType.STRING_EOP:
185
+ writeString(value, buffer, index)
186
+ index += sizeString(value)
187
+ case _VariableType.STRING_PLEN:
188
+ plen = sizeString(value)
189
+ writeUint8(plen, buffer, index)
190
+ index += 1
191
+ writeString(value, buffer, index)
192
+ index += plen
193
+ case _VariableType.STRING_PEXP:
194
+ plen = sizeString(value)
195
+ pexp = minUint(plen)
196
+ writeUint8(pexp, buffer, index)
197
+ index += 1
198
+ writeUintN(plen, buffer, index, pexp)
199
+ index += pexp
200
+ writeString(value, buffer, index)
201
+ index += plen
202
+ case _VariableType.BYTES_EOP:
203
+ writeBytes(value, buffer, index)
204
+ index += len(value)
205
+ case _VariableType.BYTES_PLEN:
206
+ plen = len(value)
207
+ writeUint8(plen, buffer, index)
208
+ index += 1
209
+ writeBytes(value, buffer, index)
210
+ index += plen
211
+ case _VariableType.BYTES_PEXP:
212
+ plen = len(value)
213
+ pexp = minUint(plen)
214
+ writeUint8(pexp, buffer, index)
215
+ index += 1
216
+ writeUintN(plen, buffer, index, pexp)
217
+ index += pexp
218
+ writeBytes(value, buffer, index)
219
+ index += plen
220
+ case _VariableType.INT_8:
221
+ writeInt8(value, buffer, index)
222
+ index += 1
223
+ case _VariableType.INT_16:
224
+ writeInt16(value, buffer, index)
225
+ index += 2
226
+ case _VariableType.INT_24:
227
+ writeInt24(value, buffer, index)
228
+ index += 3
229
+ case _VariableType.INT_32:
230
+ writeInt32(value, buffer, index)
231
+ index += 4
232
+ case _VariableType.INT_64:
233
+ writeInt64(value, buffer, index)
234
+ index += 8
235
+ case _VariableType.INT_N:
236
+ pexp = minInt(value)
237
+ writeUint8(pexp, buffer, index)
238
+ index += 1
239
+ writeIntN(value, buffer, index, pexp)
240
+ index += pexp
241
+ case _VariableType.UINT_8:
242
+ writeUint8(value, buffer, index)
243
+ index += 1
244
+ case _VariableType.UINT_16:
245
+ writeUint16(value, buffer, index)
246
+ index += 2
247
+ case _VariableType.UINT_24:
248
+ writeUint24(value, buffer, index)
249
+ index += 3
250
+ case _VariableType.UINT_32:
251
+ writeUint32(value, buffer, index)
252
+ index += 4
253
+ case _VariableType.UINT_64:
254
+ writeUint64(value, buffer, index)
255
+ index += 8
256
+ case _VariableType.UINT_N:
257
+ pexp = minInt(value)
258
+ writeUint8(pexp, buffer, index)
259
+ index += 1
260
+ writeUintN(value, buffer, index, pexp)
261
+ index += pexp
262
+ case _VariableType.BOOL:
263
+ writeBoolean(value, buffer, index)
264
+ index += 1
265
+ case _VariableType.LIST_UINT_64:
266
+ for val in value:
267
+ writeUint64(val, buffer, index)
268
+ index += 8
269
+ case _:
270
+ raise ValueError("Unknown Variable Type", variable)
271
+ return buffer
272
+ def __repr__(self):
273
+ return f"{self._name}({', '.join(f'{var.name}={getattr(self, var.name)}' for var in self._variables)})"
274
+
275
+ _lookup_table = dict()
276
+
277
+ def _TASDPacketFactory(name: str, key: int, variables: List[_VariableDefinition] = [], enums: List[_EnumDefinition] = []):
278
+ class Packet(_TASDPacket):
279
+ _variables = variables
280
+ _key = key
281
+ _name = name
282
+ def __init__(self, **kwargs):
283
+ for variable in Packet._variables:
284
+ setattr(self, variable.name, kwargs.get(variable.name, variable.default))
285
+
286
+ for enum in enums:
287
+ setattr(Packet, enum.name, enum.enum)
288
+
289
+ _lookup_table[key] = Packet
290
+
291
+ Packet.__name__ = name
292
+ Packet.__qualname__ = name
293
+ return Packet
294
+
295
+ def _build_unknown_packet(key):
296
+ _UnknownPacket = _TASDPacketFactory(f"UnknownPacket_{key:04x}", key, [ _VariableDefinition("data", _VariableType.BYTES_EOP, b"") ])
297
+ return _UnknownPacket
298
+
299
+ def lookup_packet(key: int) -> _TASDPacket:
300
+ packet = _lookup_table.get(key, None)
301
+ if packet == None:
302
+ packet = _build_unknown_packet(key)
303
+ return packet
304
+
@@ -0,0 +1,6 @@
1
+ import tasd.packets.general
2
+ import tasd.packets.nes
3
+ import tasd.packets.snes
4
+ import tasd.packets.genesis
5
+ import tasd.packets.input
6
+ import tasd.packets.extra
tasd/packets/extra.py ADDED
@@ -0,0 +1,38 @@
1
+ from tasd.packet import _TASDPacketFactory as _TASD_PF, _VariableType as _VType, _VariableDefinition as _VDef, _EnumDefinition as _EDef
2
+ from tasd.constants import PacketType
3
+
4
+ '''
5
+ 4.3.6.1. COMMENT Packet
6
+ '''
7
+
8
+ Comment = _TASD_PF(
9
+ "Comment",
10
+ PacketType.COMMENT,
11
+ [
12
+ _VDef("comment", _VType.STRING_EOP, "")
13
+ ]
14
+ )
15
+
16
+ '''
17
+ 4.3.6.2. EXPERIMENTAL Packet
18
+ '''
19
+
20
+ Experimental = _TASD_PF(
21
+ "Experimental",
22
+ PacketType.EXPERIMENTAL,
23
+ [
24
+ _VDef("experimental", _VType.BOOL, False)
25
+ ]
26
+ )
27
+
28
+ '''
29
+ 4.3.6.3. UNSPECIFIED Packet
30
+ '''
31
+
32
+ Unspecified = _TASD_PF(
33
+ "Unspecified",
34
+ PacketType.UNSPECIFIED,
35
+ [
36
+ _VDef("data", _VType.BYTES_EOP, b"")
37
+ ]
38
+ )
@@ -0,0 +1,406 @@
1
+ from tasd.packet import _TASDPacketFactory as _TASD_PF, _VariableType as _VType, _VariableDefinition as _VDef, _EnumDefinition as _EDef
2
+ from tasd.constants import PacketType
3
+
4
+ '''
5
+ 4.3.1.1. CONSOLE_TYPE Packet
6
+ '''
7
+
8
+ class CONSOLE_TYPE():
9
+ NES = 0x01
10
+ SNES = 0x02
11
+ N64 = 0x03
12
+ GC = 0x04
13
+ GB = 0x05
14
+ GBC = 0x06
15
+ GBA = 0x07
16
+ GENESIS = 0x08
17
+ A2600 = 0x09
18
+ CUSTOM = 0xFF
19
+ ConsoleType = _TASD_PF(
20
+ "ConsoleType",
21
+ PacketType.CONSOLE_TYPE,
22
+ [
23
+ _VDef("console", _VType.UINT_8, CONSOLE_TYPE.NES),
24
+ _VDef("name", _VType.STRING_EOP, "")
25
+ ],
26
+ [
27
+ _EDef("CONSOLE_TYPE", CONSOLE_TYPE)
28
+ ]
29
+ )
30
+
31
+ '''
32
+ 4.3.1.2. CONSOLE_REGION Packet
33
+ '''
34
+
35
+ class CONSOLE_REGION():
36
+ NTSC = 0x01
37
+ PAL = 0x02
38
+ OTHER = 0xFF
39
+ ConsoleRegion = _TASD_PF(
40
+ "ConsoleRegion",
41
+ PacketType.CONSOLE_REGION,
42
+ [
43
+ _VDef("region", _VType.UINT_8, CONSOLE_REGION.NTSC)
44
+ ],
45
+ [
46
+ _EDef("CONSOLE_REGION", CONSOLE_REGION)
47
+ ]
48
+ )
49
+
50
+ '''
51
+ 4.3.1.3. GAME_TITLE Packet
52
+ '''
53
+
54
+ GameTitle = _TASD_PF(
55
+ "GameTitle",
56
+ PacketType.GAME_TITLE,
57
+ [
58
+ _VDef("title", _VType.STRING_EOP, "")
59
+ ]
60
+ )
61
+
62
+
63
+ '''
64
+ 4.3.1.4. ROM_NAME Packet
65
+ '''
66
+
67
+ RomName = _TASD_PF(
68
+ "RomName",
69
+ PacketType.ROM_NAME,
70
+ [
71
+ _VDef("name", _VType.STRING_EOP, "")
72
+ ]
73
+ )
74
+
75
+ '''
76
+ 4.3.1.5. ATTRIBUTION Packet
77
+ '''
78
+
79
+ class ATTRIBUTION_TYPE():
80
+ AUTHOR = 0x01
81
+ VERIFIER = 0x02
82
+ TASD_FILE_CREATOR = 0x03
83
+ TASD_FILE_EDITOR = 0x04
84
+ OTHER = 0xFF
85
+ Attribution = _TASD_PF(
86
+ "Attribution",
87
+ PacketType.ATTRIBUTION,
88
+ [
89
+ _VDef("type", _VType.UINT_8, ATTRIBUTION_TYPE.AUTHOR),
90
+ _VDef("name", _VType.STRING_EOP, "")
91
+ ],
92
+ [
93
+ _EDef("ATTRIBUTION_TYPE", ATTRIBUTION_TYPE)
94
+ ]
95
+ )
96
+
97
+
98
+ '''
99
+ 4.3.1.6. CATEGORY Packet
100
+ '''
101
+
102
+ Category = _TASD_PF(
103
+ "Category",
104
+ PacketType.CATEGORY,
105
+ [
106
+ _VDef("category", _VType.STRING_EOP, "")
107
+ ]
108
+ )
109
+
110
+ '''
111
+ 4.3.1.7. EMULATOR_NAME Packet
112
+ '''
113
+
114
+ EmulatorName = _TASD_PF(
115
+ "EmulatorName",
116
+ PacketType.EMULATOR_NAME,
117
+ [
118
+ _VDef("name", _VType.STRING_EOP, "")
119
+ ]
120
+ )
121
+
122
+ '''
123
+ 4.3.1.8. EMULATOR_VERSION Packet
124
+ '''
125
+
126
+ EmulatorVersion = _TASD_PF(
127
+ "EmulatorVersion",
128
+ PacketType.EMULATOR_VERSION,
129
+ [
130
+ _VDef("version", _VType.STRING_EOP, "")
131
+ ]
132
+ )
133
+
134
+ '''
135
+ 4.3.1.9. EMULATOR_CORE Packet
136
+ '''
137
+
138
+ EmulatorCore = _TASD_PF(
139
+ "EmulatorCore",
140
+ PacketType.EMULATOR_CORE,
141
+ [
142
+ _VDef("core", _VType.STRING_EOP, "")
143
+ ]
144
+ )
145
+
146
+ '''
147
+ 4.3.1.10. TAS_LAST_MODIFIED Packet
148
+ '''
149
+
150
+ TASLastModified = _TASD_PF(
151
+ "TASLastModified",
152
+ PacketType.TAS_LAST_MODIFIED,
153
+ [
154
+ _VDef("timestamp", _VType.INT_64, 0)
155
+ ]
156
+ )
157
+
158
+ '''
159
+ 4.3.1.11. DUMP_CREATED Packet
160
+ '''
161
+
162
+ DumpCreated = _TASD_PF(
163
+ "DumpCreated",
164
+ PacketType.DUMP_CREATED,
165
+ [
166
+ _VDef("timestamp", _VType.INT_64, 0)
167
+ ]
168
+ )
169
+
170
+ '''
171
+ 4.3.1.12. DUMP_LAST_MODIFIED Packet
172
+ '''
173
+
174
+ DumpLastModified = _TASD_PF(
175
+ "DumpLastModified",
176
+ PacketType.DUMP_LAST_MODIFIED,
177
+ [
178
+ _VDef("timestamp", _VType.INT_64, 0)
179
+ ]
180
+ )
181
+
182
+ '''
183
+ 4.3.1.13. TOTAL_FRAMES Packet
184
+ '''
185
+
186
+ TotalFrames = _TASD_PF(
187
+ "TotalFrames",
188
+ PacketType.TOTAL_FRAMES,
189
+ [
190
+ _VDef("frames", _VType.UINT_32, 0)
191
+ ]
192
+ )
193
+
194
+ '''
195
+ 4.3.1.14. RERECORDS Packet
196
+ '''
197
+
198
+ Rerecords = _TASD_PF(
199
+ "Rerecords",
200
+ PacketType.RERECORDS,
201
+ [
202
+ _VDef("rerecords", _VType.UINT_32, 0)
203
+ ]
204
+ )
205
+
206
+ '''
207
+ 4.3.1.15. SOURCE_LINK Packet
208
+ '''
209
+
210
+ SourceLink = _TASD_PF(
211
+ "SourceLink",
212
+ PacketType.SOURCE_LINK,
213
+ [
214
+ _VDef("link", _VType.STRING_EOP, "")
215
+ ]
216
+ )
217
+
218
+ '''
219
+ 4.3.1.16. BLANK_FRAMES Packet
220
+ '''
221
+
222
+ BlankFrames = _TASD_PF(
223
+ "BlankFrames",
224
+ PacketType.BLANK_FRAMES,
225
+ [
226
+ _VDef("frames", _VType.INT_16, 0)
227
+ ]
228
+ )
229
+
230
+ '''
231
+ 4.3.1.17. VERIFIED Packet
232
+ '''
233
+
234
+ Verified = _TASD_PF(
235
+ "Verified",
236
+ PacketType.VERIFIED,
237
+ [
238
+ _VDef("verified", _VType.BOOL, False)
239
+ ]
240
+ )
241
+
242
+ '''
243
+ 4.3.1.18. MEMORY_INIT Packet
244
+ '''
245
+
246
+ class MEMORY_INIT_TYPE():
247
+ NONE = 0x01
248
+ ALL_00 = 0x02
249
+ ALL_FF = 0x03
250
+ PATTERN_00000000FFFFFFFF = 0x04
251
+ RANDOM = 0x05
252
+ CUSTOM = 0xFF
253
+ class MEMORY_INIT_DEVICE():
254
+ NES_CPU_RAM = 0x0101
255
+ NES_CART_SRAM = 0x0102
256
+ SNES_CPU_RAM = 0x0201
257
+ SNES_CART_SRAM = 0x0202
258
+ GB_CPU_RAM = 0x0501
259
+ GB_CART_SRAM = 0x0502
260
+ GBC_CPU_RAM = 0x0601
261
+ GBC_CART_SRAM = 0x0602
262
+ GBA_CPU_RAM = 0x0701
263
+ GBA_CART_SRAM = 0x0702
264
+ GENESIS_CPU_RAM = 0x0801
265
+ GENESIS_CART_SRAM = 0x0802
266
+ A2600_CPU_RAM = 0x0901
267
+ A2600_CART_SRAM = 0x0902
268
+ CUSTOM = 0xFFFF
269
+ MemoryInit = _TASD_PF(
270
+ "MemoryInit",
271
+ PacketType.MEMORY_INIT,
272
+ [
273
+ _VDef("type", _VType.UINT_8, MEMORY_INIT_TYPE.NONE),
274
+ _VDef("device", _VType.UINT_16, MEMORY_INIT_DEVICE.NES_CPU_RAM),
275
+ _VDef("required", _VType.BOOL, False),
276
+ _VDef("name", _VType.STRING_PLEN, ""),
277
+ _VDef("data", _VType.BYTES_EOP, b"")
278
+ ],
279
+ [
280
+ _EDef("MEMORY_INIT_TYPE", MEMORY_INIT_TYPE),
281
+ _EDef("MEMORY_INIT_DEVICE", MEMORY_INIT_DEVICE)
282
+ ]
283
+ )
284
+
285
+ '''
286
+ 4.3.1.19. GAME_IDENTIFIER Packet
287
+ '''
288
+
289
+ class GAME_IDENTIFIER_TYPE():
290
+ MD5 = 0x01
291
+ SHA1 = 0x02
292
+ SHA224 = 0x03
293
+ SHA256 = 0x04
294
+ SHA384 = 0x05
295
+ SHA512 = 0x06
296
+ SHA512_224 = 0x07
297
+ SHA512_256 = 0x08
298
+ SHA3_224 = 0x09
299
+ SHA3_256 = 0x0A
300
+ SHA3_384 = 0x0B
301
+ SHA3_512 = 0x0C
302
+ SHAKE_128 = 0x0D
303
+ SHAKE_256 = 0x0E
304
+ OTHER = 0xFF
305
+ class GAME_IDENTIFIER_BASE():
306
+ RAW_BINARY = 0x01
307
+ BASE16 = 0x02
308
+ BASE32 = 0x03
309
+ BASE64 = 0x04
310
+ OTHER = 0xFF
311
+ GameIdentifier = _TASD_PF(
312
+ "GameIdentifier",
313
+ PacketType.GAME_IDENTIFIER,
314
+ [
315
+ _VDef("type", _VType.UINT_8, GAME_IDENTIFIER_TYPE.MD5),
316
+ _VDef("encoding", _VType.UINT_8, GAME_IDENTIFIER_BASE.RAW_BINARY),
317
+ _VDef("name", _VType.STRING_PLEN, ""),
318
+ _VDef("identifier", _VType.BYTES_EOP, b"")
319
+ ],
320
+ [
321
+ _EDef("GAME_IDENTIFIER_TYPE", GAME_IDENTIFIER_TYPE),
322
+ _EDef("GAME_IDENTIFIER_BASE", GAME_IDENTIFIER_BASE)
323
+ ])
324
+
325
+ '''
326
+ 4.3.1.20. MOVIE_LICENSE Packet
327
+ '''
328
+
329
+ MovieLicense = _TASD_PF(
330
+ "MovieLicense",
331
+ PacketType.MOVIE_LICENSE,
332
+ [
333
+ _VDef("link", _VType.STRING_EOP, "")
334
+ ]
335
+ )
336
+
337
+ '''
338
+ 4.3.1.21. MOVIE_FILE Packet
339
+ '''
340
+
341
+ MovieFile = _TASD_PF(
342
+ "MovieFile",
343
+ PacketType.MOVIE_FILE,
344
+ [
345
+ _VDef("name", _VType.STRING_PLEN, ""),
346
+ _VDef("data", _VType.BYTES_EOP, b"")
347
+ ]
348
+ )
349
+
350
+ '''
351
+ 4.3.1.22. PORT_CONTROLLER Packet
352
+ '''
353
+
354
+ class CONTROLLER_TYPE():
355
+ NES_STANDARD_CONTROLLER = 0x0101
356
+ NES_FOUR_SCORE = 0x0102
357
+ NES_ZAPPER = 0x0103
358
+ NES_POWER_PAD = 0x0104
359
+ FAMICOM_FAMILY_BASIC_KEYBOARD = 0x0105
360
+ SNES_STANDARD_CONTROLLER = 0x0201
361
+ SNES_SUPER_MULTITAP = 0x0202
362
+ SNES_MOUSE = 0x0203
363
+ SNES_SUPERSCOPE = 0x0204
364
+ N64_STANDARD_CONTROLLER = 0x0301
365
+ N64_STANDARD_CONTROLLER_WITH_RUMBLE_PAK = 0x0302
366
+ N64_STANDARD_CONTROLLER_WITH_CONTROLLER_PAK = 0x0303
367
+ N64_STANDARD_CONTROLLER_WITH_TRANSFER_PAK = 0x0304
368
+ N64_MOUSE = 0x0305
369
+ N64_VOICE_RECOGNITION_UNIT = 0x0306
370
+ N64_RANDNET_KEYBOARD = 0x0307
371
+ N64_DENSHA_DE_GO = 0x0308
372
+ GC_STANDARD_CONTROLLER = 0x0401
373
+ GC_KEYBOARD = 0x0402
374
+ GB_GAMEPAD = 0x0501
375
+ GBC_GAMEPAD = 0x0601
376
+ GBA_GAMEPAD = 0x0701
377
+ GENESIS_3BUTTON = 0x0801
378
+ GENESIS_6BUTTON = 0x0802
379
+ A2600_JOYSTICK = 0x0901
380
+ A2600_PADDLE = 0x0902
381
+ A2600_KEYBOARD_CONTROLLER = 0x0903
382
+ OTHER_UNSPECIFIED = 0xFFFF
383
+ PortController = _TASD_PF(
384
+ "PortController",
385
+ PacketType.PORT_CONTROLLER,
386
+ [
387
+ _VDef("port", _VType.UINT_8, 1),
388
+ _VDef("type", _VType.UINT_16, CONTROLLER_TYPE.NES_STANDARD_CONTROLLER)
389
+ ],
390
+ [
391
+ _EDef("CONTROLLER_TYPE", CONTROLLER_TYPE)
392
+ ]
393
+ )
394
+
395
+ '''
396
+ 4.3.1.23. PORT_OVERREAD Packet
397
+ '''
398
+
399
+ PortOverread = _TASD_PF(
400
+ "PortOverread",
401
+ PacketType.PORT_OVERREAD,
402
+ [
403
+ _VDef("port", _VType.UINT_8, 1),
404
+ _VDef("high", _VType.BOOL, False)
405
+ ]
406
+ )
@@ -0,0 +1,18 @@
1
+ from tasd.packet import _TASDPacketFactory as _TASD_PF, _VariableType as _VType, _VariableDefinition as _VDef, _EnumDefinition as _EDef
2
+ from tasd.constants import PacketType
3
+
4
+ '''
5
+ 4.3.4.1. GENESIS_GAME_GENIE_CODE Packet
6
+ '''
7
+
8
+ GenesisGameGenieCode = _TASD_PF(
9
+ "GenesisGameGenieCode",
10
+ PacketType.GENESIS_GAME_GENIE_CODE,
11
+ [
12
+ _VDef("code", _VType.STRING_EOP, "")
13
+ ]
14
+ )
15
+
16
+ __all__ = [
17
+ GenesisGameGenieCode
18
+ ]
tasd/packets/input.py ADDED
@@ -0,0 +1,106 @@
1
+ from tasd.packet import _TASDPacketFactory as _TASD_PF, _VariableType as _VType, _VariableDefinition as _VDef, _EnumDefinition as _EDef
2
+ from tasd.constants import PacketType
3
+
4
+ '''
5
+ 4.3.5.1. INPUT_CHUNK Packet
6
+ '''
7
+
8
+ InputChunk = _TASD_PF(
9
+ "InputChunk",
10
+ PacketType.INPUT_CHUNK,
11
+ [
12
+ _VDef("port", _VType.UINT_8, 1),
13
+ _VDef("data", _VType.BYTES_EOP, b"")
14
+ ]
15
+ )
16
+
17
+ '''
18
+ 4.3.5.2. INPUT_MOMENT Packet
19
+ '''
20
+
21
+ class INPUT_MOMENT_INDEX_TYPE():
22
+ FRAME = 0x01
23
+ CYCLE_COUNT = 0x02
24
+ MILLISECONDS = 0x03
25
+ MICROSECONDS_X10 = 0x04
26
+ InputMoment = _TASD_PF(
27
+ "InputMoment",
28
+ PacketType.INPUT_MOMENT,
29
+ [
30
+ _VDef("port", _VType.UINT_8, 1),
31
+ _VDef("hold", _VType.BOOL, False),
32
+ _VDef("index_type", _VType.UINT_8, INPUT_MOMENT_INDEX_TYPE.FRAME),
33
+ _VDef("index", _VType.UINT_64, 0),
34
+ _VDef("inputs", _VType.BYTES_EOP, b"")
35
+ ],
36
+ [
37
+ _EDef("INPUT_MOMENT_INDEX_TYPE", INPUT_MOMENT_INDEX_TYPE)
38
+ ]
39
+ )
40
+
41
+ '''
42
+ 4.3.5.3. TRANSITION Packet
43
+ '''
44
+
45
+ class TRANSITION_INDEX_TYPE():
46
+ FRAME = 0x01
47
+ CYCLE_COUNT = 0x02
48
+ MILLISECONDS = 0x03
49
+ MICROSECONDS = 0x04
50
+ NANOSECONDS = 0x05
51
+ INPUT_CHUNK_INDEX = 0x06
52
+ class TRANSITION_TYPE():
53
+ SOFT_RESET = 0x01
54
+ POWER_RESET = 0x02
55
+ RESTART_TASD_FILE = 0x03
56
+ PACKET_DERIVED = 0xFF
57
+ Transition = _TASD_PF(
58
+ "Transition",
59
+ PacketType.TRANSITION,
60
+ [
61
+ _VDef("port", _VType.UINT_8, 1),
62
+ _VDef("index_type", _VType.UINT_8, TRANSITION_INDEX_TYPE.FRAME),
63
+ _VDef("index", _VType.UINT_64, 0),
64
+ _VDef("type", _VType.UINT_8, TRANSITION_TYPE.SOFT_RESET),
65
+ _VDef("packet", _VType.BYTES_EOP, b"")
66
+ ],
67
+ [
68
+ _EDef("TRANSITION_INDEX_TYPE", TRANSITION_INDEX_TYPE),
69
+ _EDef("TRANSITION_TYPE", TRANSITION_TYPE)
70
+ ]
71
+ )
72
+
73
+ '''
74
+ 4.3.5.4. LAG_FRAME_CHUNK Packet
75
+ '''
76
+
77
+ LagFrameChunk = _TASD_PF(
78
+ "LagFrameChunk",
79
+ PacketType.LAG_FRAME_CHUNK,
80
+ [
81
+ _VDef("frame", _VType.UINT_32, 0),
82
+ _VDef("count", _VType.UINT_32, 0)
83
+ ]
84
+ )
85
+
86
+ '''
87
+ 4.3.5.5. MOVIE_TRANSITION
88
+ '''
89
+
90
+ class MOVIE_TRANSITION_TYPE():
91
+ SOFT_RESET = 0x01
92
+ POWER_RESET = 0x02
93
+ RESTART_TASD_FILE = 0x03
94
+ PACKET_DERIVED = 0xFF
95
+ MovieTransition = _TASD_PF(
96
+ "MovieTransition",
97
+ PacketType.MOVIE_TRANSITION,
98
+ [
99
+ _VDef("frame", _VType.UINT_32, 0),
100
+ _VDef("type", _VType.UINT_8, MOVIE_TRANSITION_TYPE.SOFT_RESET),
101
+ _VDef("packet", _VType.BYTES_EOP, b"")
102
+ ],
103
+ [
104
+ _EDef("MOVIE_TRANSITION_TYPE", MOVIE_TRANSITION_TYPE),
105
+ ]
106
+ )
tasd/packets/nes.py ADDED
@@ -0,0 +1,38 @@
1
+ from tasd.packet import _TASDPacketFactory as _TASD_PF, _VariableType as _VType, _VariableDefinition as _VDef, _EnumDefinition as _EDef
2
+ from tasd.constants import PacketType
3
+
4
+ '''
5
+ 4.3.2.1. NES_LATCH_FILTER Packet
6
+ '''
7
+
8
+ NESLatchFilter = _TASD_PF(
9
+ "NESLatchFilter",
10
+ PacketType.NES_LATCH_FILTER,
11
+ [
12
+ _VDef("time", _VType.UINT_16, 0)
13
+ ]
14
+ )
15
+
16
+ '''
17
+ 4.3.2.2. NES_CLOCK_FILTER Packet
18
+ '''
19
+
20
+ NESClockFilter = _TASD_PF(
21
+ "NESClockFilter",
22
+ PacketType.NES_CLOCK_FILTER,
23
+ [
24
+ _VDef("time", _VType.UINT_8, 0)
25
+ ]
26
+ )
27
+
28
+ '''
29
+ 4.3.2.3. NES_GAME_GENIE_CODE Packet
30
+ '''
31
+
32
+ NESGameGenieCode = _TASD_PF(
33
+ "NESGameGenieCode",
34
+ PacketType.NES_GAME_GENIE_CODE,
35
+ [
36
+ _VDef("code", _VType.STRING_EOP, "")
37
+ ]
38
+ )
tasd/packets/snes.py ADDED
@@ -0,0 +1,50 @@
1
+ from tasd.packet import _TASDPacketFactory as _TASD_PF, _VariableType as _VType, _VariableDefinition as _VDef, _EnumDefinition as _EDef
2
+ from tasd.constants import PacketType
3
+
4
+ '''
5
+ 4.3.3.1. SNES_LATCH_FILTER Packet
6
+ '''
7
+
8
+ SNESLatchFilter = _TASD_PF(
9
+ "SNESLatchFilter",
10
+ PacketType.SNES_LATCH_FILTER,
11
+ [
12
+ _VDef("time", _VType.UINT_16, 0)
13
+ ]
14
+ )
15
+
16
+ '''
17
+ 4.3.3.2. SNES_CLOCK_FILTER Packet
18
+ '''
19
+
20
+ SNESClockFilter = _TASD_PF(
21
+ "SNESClockFilter",
22
+ PacketType.SNES_CLOCK_FILTER,
23
+ [
24
+ _VDef("time", _VType.UINT_8, 0)
25
+ ]
26
+ )
27
+
28
+ '''
29
+ 4.3.3.3. SNES_GAME_GENIE_CODE Packet
30
+ '''
31
+
32
+ SNESGameGenieCode = _TASD_PF(
33
+ "SNESGameGenieCode",
34
+ PacketType.SNES_GAME_GENIE_CODE,
35
+ [
36
+ _VDef("code", _VType.STRING_EOP, "")
37
+ ]
38
+ )
39
+
40
+ '''
41
+ 4.3.3.4. SNES_LATCH_TRAIN Packet
42
+ '''
43
+
44
+ SNESLatchTrain = _TASD_PF(
45
+ "SNESLatchTrain",
46
+ PacketType.SNES_LATCH_TRAIN,
47
+ [
48
+ _VDef("trains", _VType.LIST_UINT_64, None)
49
+ ]
50
+ )
tasd/utils.py ADDED
@@ -0,0 +1,128 @@
1
+ def readString(buffer: bytearray, index: int, length: int) -> str:
2
+ return buffer[index:index+length].decode("utf8")
3
+ def writeString(string: str, buffer: bytearray, index: int) -> None:
4
+ rawstring = string.encode("utf8")
5
+ buffer[index:index+len(rawstring)] = rawstring
6
+ def sizeString(string: str) -> int:
7
+ return len(string.encode("utf8"))
8
+
9
+ def readBytes(buffer: bytearray, index: int, length: int) -> bytes:
10
+ return buffer[index:index+length]
11
+ def writeBytes(value: bytes, buffer: bytearray, index: int) -> None:
12
+ buffer[index:index+len(value)] = value
13
+
14
+ def readUint8(buffer: bytearray, index: int) -> int:
15
+ return int.from_bytes(buffer[index:index+1], byteorder="big", signed=False)
16
+ def readUint16(buffer: bytearray, index: int) -> int:
17
+ return int.from_bytes(buffer[index:index+2], byteorder="big", signed=False)
18
+ def readUint24(buffer: bytearray, index: int) -> int:
19
+ return int.from_bytes(buffer[index:index+3], byteorder="big", signed=False)
20
+ def readUint32(buffer: bytearray, index: int) -> int:
21
+ return int.from_bytes(buffer[index:index+4], byteorder="big", signed=False)
22
+ def readUint64(buffer: bytearray, index: int) -> int:
23
+ return int.from_bytes(buffer[index:index+8], byteorder="big", signed=False)
24
+ def readUintN(buffer: bytearray, index: int, size: int) -> int:
25
+ if size == 1:
26
+ return readUint8(buffer, index)
27
+ if size == 2:
28
+ return readUint16(buffer, index)
29
+ if size == 3:
30
+ return readUint24(buffer, index)
31
+ if size == 4:
32
+ return readUint32(buffer, index)
33
+ raise ValueError("Unsuported UintN size", size)
34
+
35
+ def writeUint8(value: int, buffer: bytearray, index: int) -> None:
36
+ buffer[index:index+1] = (value & (2 ** 8 - 1)).to_bytes(1, byteorder="big", signed=False)
37
+ def writeUint16(value: int, buffer: bytearray, index: int) -> None:
38
+ buffer[index:index+2] = (value & (2 ** 16 - 1)).to_bytes(2, byteorder="big", signed=False)
39
+ def writeUint24(value: int, buffer: bytearray, index: int) -> None:
40
+ buffer[index:index+3] = (value & (2 ** 24 - 1)).to_bytes(3, byteorder="big", signed=False)
41
+ def writeUint32(value: int, buffer: bytearray, index: int) -> None:
42
+ buffer[index:index+4] = (value & (2 ** 32 - 1)).to_bytes(4, byteorder="big", signed=False)
43
+ def writeUint64(value: int, buffer: bytearray, index: int) -> None:
44
+ buffer[index:index+8] = (value & (2 ** 64 - 1)).to_bytes(8, byteorder="big", signed=False)
45
+ def writeUintN(value: int, buffer: bytearray, index: int, size: int) -> None:
46
+ if size == 1:
47
+ return writeUint8(value, buffer, index)
48
+ if size == 2:
49
+ return writeUint16(value, buffer, index)
50
+ if size == 3:
51
+ return writeUint24(value, buffer, index)
52
+ if size == 4:
53
+ return writeUint32(value, buffer, index)
54
+ raise ValueError("Unsuported UintN size", size)
55
+
56
+ def minUint(value: int) -> int:
57
+ if value < 256:
58
+ return 1
59
+ if value < 65536:
60
+ return 2
61
+ if value < 16777216:
62
+ return 3
63
+ if value < 4294967296:
64
+ return 4
65
+ raise ValueError("Unsupported UInt size", value);
66
+
67
+
68
+ def readInt8(buffer: bytearray, index: int) -> int:
69
+ return int.from_bytes(buffer[index:index+1], byteorder="big", signed=True)
70
+ def readInt16(buffer: bytearray, index: int) -> int:
71
+ return int.from_bytes(buffer[index:index+2], byteorder="big", signed=True)
72
+ def readInt24(buffer: bytearray, index: int) -> int:
73
+ return int.from_bytes(buffer[index:index+3], byteorder="big", signed=True)
74
+ def readInt32(buffer: bytearray, index: int) -> int:
75
+ return int.from_bytes(buffer[index:index+4], byteorder="big", signed=True)
76
+ def readInt64(buffer: bytearray, index: int) -> int:
77
+ return int.from_bytes(buffer[index:index+8], byteorder="big", signed=True)
78
+ def readIntN(buffer: bytearray, index: int, n: int) -> int:
79
+ if n == 1:
80
+ return readInt8(buffer, index)
81
+ if n == 2:
82
+ return readInt16(buffer, index)
83
+ if n == 3:
84
+ return readInt24(buffer, index)
85
+ if n == 4:
86
+ return readInt32(buffer, index)
87
+ raise ValueError("Unsuported IntN size", n)
88
+
89
+ def writeInt8(value: int, buffer: bytearray, index: int) -> None:
90
+ buffer[index:index+1] = (value & (2 ** 8 - 1)).to_bytes(1, byteorder="big", signed=True)
91
+ def writeInt16(value: int, buffer: bytearray, index: int) -> None:
92
+ buffer[index:index+2] = (value & (2 ** 16 - 1)).to_bytes(2, byteorder="big", signed=True)
93
+ def writeInt24(value: int, buffer: bytearray, index: int) -> None:
94
+ buffer[index:index+3] = (value & (2 ** 24 - 1)).to_bytes(3, byteorder="big", signed=True)
95
+ def writeInt32(value: int, buffer: bytearray, index: int) -> None:
96
+ buffer[index:index+4] = (value & (2 ** 32 - 1)).to_bytes(4, byteorder="big", signed=True)
97
+ def writeInt64(value: int, buffer: bytearray, index: int) -> None:
98
+ buffer[index:index+8] = (value & (2 ** 64 - 1)).to_bytes(8, byteorder="big", signed=True)
99
+ def writeIntN(value: int, buffer: bytearray, index: int, size: int) -> None:
100
+ if size == 1:
101
+ return writeInt8(value, buffer, index)
102
+ if size == 2:
103
+ return writeInt16(value, buffer, index)
104
+ if size == 3:
105
+ return writeInt24(value, buffer, index)
106
+ if size == 4:
107
+ return writeInt32(value, buffer, index)
108
+ raise ValueError("Unsuported IntN size", size)
109
+
110
+ def minInt(value: int) -> int:
111
+ if -0x80 <= value <= 0x7f:
112
+ return 1
113
+ if -0x8000 <= value <= 0x7fff:
114
+ return 2
115
+ if -0x800000 <= value <= 0x7fffff:
116
+ return 3
117
+ if -0x80000000 <= value <= 0x7fffffff:
118
+ return 4
119
+ raise ValueError("Unsupported Int size", value);
120
+
121
+ def readBoolean(buffer: bytearray, index: int) -> bool:
122
+ if buffer[index] == 1:
123
+ return True
124
+ if buffer[index] == 0:
125
+ return False
126
+ raise ValueError("Invalid Boolean value")
127
+ def writeBoolean(bool: bool, buffer: bytearray, index: int) -> None:
128
+ buffer[index] = (1 if bool else 0)
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: tasd
3
+ Version: 1.0.0
4
+ Summary: TASD file serializer and deserializer
5
+ Author-email: TheMas3212 <mas3212@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/themas3212/tasd-py
8
+ Project-URL: Issues, https://github.com/themas3212/tasd-py/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Dynamic: license-file
15
+
16
+
17
+ # TASD
18
+
19
+ This is a python library for the serialization and deserialization of tasd files using the [tasd file specfication](https://tasd.io/)
20
+
21
+
22
+ ## Installation
23
+
24
+ Install tasd with pip
25
+
26
+ ```bash
27
+ pip install tasd
28
+ ```
29
+
30
+ ## Usage/Examples
31
+
32
+
33
+ Read a file in a print all the packets in it
34
+ ```py
35
+ from tasd import TASD
36
+
37
+ with open("example.tasd", "rb") as f:
38
+ file = TASD.from_bytes(f.read())
39
+
40
+ print(file)
41
+ for packet in file. packets:
42
+ print(packet)
43
+ ```
44
+
45
+ Create a tasd file from scratch and add packets to it
46
+ ```py
47
+ from tasd import TASD, packets
48
+
49
+ file = TASD()
50
+ file.packets.append(packets.extra.Comment(comment="This is a comment"))
51
+ file.packets.append(packets.general.Attribution(type=packets.general.Attribution.ATTRIBUTION_TYPE.TASD_FILE_CREATOR, name="Me"))
52
+
53
+ for packet in file. packets:
54
+ print(packet)
55
+
56
+ print(file.to_bytes())
57
+ ```
58
+ ## Brief API Reference
59
+
60
+ Not an exhaustive list
61
+
62
+ `tasd.TASD`
63
+
64
+ Class holding properties of the tasd file itself: Version and KeyLength
65
+
66
+ `tasd.constants.PACKET_TYPES`
67
+
68
+ Enumlike class containing the different packet type indentifiers
69
+
70
+ `tasd.packets`
71
+
72
+ Submodule containing all the different packet classes
73
+
74
+ For details about the different packet types i suggest reading the specification document to determine what packets you need to consider for your use case
75
+ ## Appendix
76
+
77
+ Any additional information goes here
78
+
@@ -0,0 +1,17 @@
1
+ tasd/__init__.py,sha256=1yGBy9LKlZOfg7qB2BXhSRECm4ag1eOELMnMKUT5Yns,86
2
+ tasd/constants.py,sha256=A60Y_e_PqF6oCX2VlINZqbRm0ooqGF4azpMuohaHbW0,2149
3
+ tasd/file.py,sha256=CiRx1Vi-vqIzofRcGrWXXIKhz80AqBRgXlsepSw_vcw,2315
4
+ tasd/packet.py,sha256=SFdHIHCb4gKL4eOzNBZwsfJi5O-QLPbgYCDCW3E0iPQ,12204
5
+ tasd/utils.py,sha256=m3dFok1VswQ1Ba5t_nYPLG90Y90KegkLFIvNN4LMJyk,5842
6
+ tasd/packets/__init__.py,sha256=aznvDufzsVEIfHAV__FA3W1bnE4wrQWzsMc5wbMQbqs,157
7
+ tasd/packets/extra.py,sha256=upxQ7_V69nAbNhdCMuO1QFR_QR8ZRywj8YEglkwu0p4,676
8
+ tasd/packets/general.py,sha256=Ib2UZbYAa7aP27X_iyAmBTMJwf7MzUdWYWs0GCE327k,8858
9
+ tasd/packets/genesis.py,sha256=CHqKBRmZjma6Q-VD8S635jBbRZwk2vsNCLV8NVjurRo,424
10
+ tasd/packets/input.py,sha256=OkPQvSC3hbNSVHYYMt1Ss5FI3SLz67j1Z1hHhI5IdsE,2620
11
+ tasd/packets/nes.py,sha256=X4JuKT9TkDvd6PL3PDHCujPKh7V_JAb51NkMVQCg2_s,729
12
+ tasd/packets/snes.py,sha256=GpJmbp-wlSEWC5E__9a0r_9lJ6hrJctzPysZlPNkbNQ,932
13
+ tasd-1.0.0.dist-info/licenses/LICENSE,sha256=g3ow4YGepg8H1fLp2CiNhGHkMFiBvfX1P-JH3oKmA3g,1067
14
+ tasd-1.0.0.dist-info/METADATA,sha256=PEaPbWhxNgP0XlMRhqornw7fjp2-v2iwuwPwUpyoTJI,1841
15
+ tasd-1.0.0.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
16
+ tasd-1.0.0.dist-info/top_level.txt,sha256=Ys1rtVCDs2s_wERGa-Z-umkR87S0XWHo9UzpemZxDsg,5
17
+ tasd-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (79.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 TheMas3212
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ tasd