Created
April 29, 2023 07:03
-
-
Save ktemkin/b4b36ab334eb9bb83f075bcddbba16b7 to your computer and use it in GitHub Desktop.
WIP script to unpack Roli firmware files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import math | |
import mido | |
FIRMWARE_IN = "firmware.syx" | |
FIRMWARE_OUT = "firmware.bin" | |
FIRMWARE_PUSH_COMMAND = 0x04 | |
leftover_data = [] | |
def demangle(data): | |
""" Demangles data that's been encoded as 7-bit numbers. """ | |
input_data = data[:] | |
output_data = bytearray() | |
while input_data: | |
chunk = input_data[0:8] | |
del input_data[0:8] | |
# Typically, we get 7 bytes per 8, since we had 7 of 8 bits... | |
resultant_size = math.floor(len(chunk) * 7 / 8) | |
resultant_bits = resultant_size * 8 | |
# Convert the 7-bit chunks into one fewer eight bit chunks... | |
septets = [f"{i:07b}" for i in chunk] | |
long_equivalent = "".join(septets)[0:resultant_bits] | |
# ... and convert that back to bytes. | |
raw = int(long_equivalent, 2) | |
octets = raw.to_bytes(resultant_size, byteorder='big') | |
output_data.extend(octets) | |
print(len(output_data)) | |
return output_data | |
# Read the firware into memory. | |
roli_syx = mido.read_syx_file(FIRMWARE_IN) | |
# Prepare to write our output file. | |
output = open(FIRMWARE_OUT, "wb") | |
# Go through each message, and see what we have. | |
for message in roli_syx: | |
data = list(message.data) | |
# The first byte is already extracted for us, as it's SysEx standard. | |
# The next four bytes are ID information and separator; throw those away. | |
del data[0:4] | |
# The _last_ byte is a checksum of the packet. | |
# Discard it. | |
del data[-1] | |
# The next byte is the command. | |
command = data.pop(0) | |
# Skip non-firmware commands. | |
if command not in [FIRMWARE_PUSH_COMMAND]: | |
continue | |
data_demangled = demangle(data) | |
address = data_demangled[0:4] | |
address = int.from_bytes(address, byteorder='little') | |
del data_demangled[0:4] | |
output.write(data_demangled) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment