diff --git a/pyrekordbox/anlz/file.py b/pyrekordbox/anlz/file.py index 2df531e..495d57e 100644 --- a/pyrekordbox/anlz/file.py +++ b/pyrekordbox/anlz/file.py @@ -8,6 +8,7 @@ from typing import Union from .tags import TAGS from . import structs +from construct import Int16ub logger = logging.getLogger(__name__) @@ -103,6 +104,19 @@ def _parse(self, data: bytes): # Get the four byte struct type tag_type = tag_data[:4].decode("ascii") + if tag_type == "PSSI": + # deobfuscate tag_data[18:] using xor with verysecretcode+len_entries + verysecretcode = bytearray.fromhex( + "CB E1 EE FA E5 EE AD EE E9 D2 E9 EB E1 E9 F3 E8 E9 F4 E1" + ) + len_entries = Int16ub.parse(tag_data[16:]) + tag_data = bytearray(data[i : i + len(tag_data)]) + for x in range(len(tag_data[18:])): + decryptmask = verysecretcode[x % len(verysecretcode)] + len_entries + if decryptmask > 255: + decryptmask -= 256 + tag_data[x + 18] ^= decryptmask + try: # Parse the struct tag = TAGS[tag_type](tag_data) diff --git a/pyrekordbox/anlz/structs.py b/pyrekordbox/anlz/structs.py index df54441..ba995b8 100644 --- a/pyrekordbox/anlz/structs.py +++ b/pyrekordbox/anlz/structs.py @@ -195,8 +195,6 @@ # -- Song Structure Tag (PSSI) --------------------------------------------------------- -# FixMe: Implement reverse XOR mask to descramble values - SongStructureEntry = Struct( "index" / Int16ub, "beat" / Int16ub, @@ -221,11 +219,11 @@ PSSI = Struct( "len_entry_bytes" / Const(24, Int32ub), "len_entries" / Int16ub, - "mood" / Bytes(2), + "mood" / Int16ub, "u1" / Bytes(6), - "end_beat" / Bytes(2), + "end_beat" / Int16ub, "u2" / Bytes(2), - "bank" / Bytes(1), + "bank" / Int8ub, "u3" / Bytes(1), "entries" / Array(this.len_entries, SongStructureEntry), )