Last active
April 27, 2023 20:21
-
-
Save jaames/daaf2531bae31f72cca675df4361c0d4 to your computer and use it in GitHub Desktop.
convert Flipnote Studio .lst and .pls files to and from .txt
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
from sys import argv | |
import hashlib | |
import numpy as np | |
xorkey = [ | |
0xF7, 0x4C, 0x6A, 0x3A, 0xFB, 0x82, 0xA6, 0x37, | |
0x6E, 0x11, 0x38, 0xCF, 0xA0, 0xDD, 0x85, 0xC0, | |
0xC7, 0x9B, 0xC4, 0xD8, 0xDD, 0x28, 0x8A, 0x87, | |
0x53, 0x20, 0xEE, 0xE0, 0x0B, 0xEB, 0x43, 0xA0, | |
0xDB, 0x55, 0x0F, 0x75, 0x36, 0x37, 0xEB, 0x35, | |
0x6A, 0x34, 0x7F, 0xB5, 0x0F, 0x99, 0xF7, 0xEF, | |
0x43, 0x25, 0xCE, 0xA0, 0x29, 0x46, 0xD9, 0xD4, | |
0x4D, 0xBB, 0x04, 0x66, 0x68, 0x08, 0xF1, 0xF8 | |
] | |
def xor(data): | |
# Storage for the decrypted entry data | |
decrypted = bytes(); | |
# XOR the entry data | |
for index, byte in enumerate(data): | |
decrypted += bytes([ byte ^ xorkey[index % len(xorkey)] ]); | |
# Convert the XOR'ed data to a bytes object | |
return decrypted | |
def checksum(data): | |
hash = hashlib.md5() | |
hash.update(data) | |
digest = hash.digest() | |
return bytes([digest[6], digest[8]]) | |
def decode(lstBuffer, outBuffer): | |
data = lstBuffer.read() | |
xordata = xor(data) | |
# Find the first null byte in the decoded file -- this is where the entry content ends | |
entryLength = xordata.index(b"\x00") + 1 | |
# Write the entry data to the out buffer, removing the final newline and the null byte at the end | |
outBuffer.write(xordata.split(b"\x0A\x00")[0]) | |
def encode(txtBuffer, outBuffer, targetLength): | |
# Split the xtx file buffer into lines | |
content = txtBuffer.readlines() | |
# Strip any newlines that are left | |
content = [x.strip("\n") for x in content] | |
# Join all the items in content together with newlines between | |
# (We do all this just to make sure the input is "clean") | |
content = "\n".join(content) | |
# Create a bytearray and add the content to it | |
data = bytearray() | |
data.extend(map(ord, content)) | |
# Add the trailing newline and null byte | |
data += bytes([0x0A, 0x00]) | |
# Checksum everything | |
md5 = checksum(data) | |
# XOR all the data so far | |
data = xor(data) | |
# Add a checksum to the XOR data | |
data += md5 | |
# Load the data into a numpy array | |
data = np.fromstring(data, dtype=np.uint8) | |
# Add null padding | |
data = np.pad(data, (0, targetLength - len(data)), 'constant', constant_values=(0, 0)) | |
# Convert the array to bytes and write them to the out buffer | |
outBuffer.write(data.tobytes()) | |
if len(argv) < 3: | |
print("\nlst.py") | |
print("writen by james daniel (github.com/jaames)") | |
print("\nconvert .txt to .lst/.pls:") | |
print("\tpython3 lst.py -e input.txt output.lst desired_length_in_bytes") | |
print("\n\tlength reference:") | |
print("\t.dirmemo2.lst - 160000") | |
print("\t.mark0.pls | mark1.pls | mark2.pls | mark3.pls - 8000") | |
print("\t.recent10.pls - 4000") | |
print("\nconvert .lst/.pls to .txt:") | |
print("\tpython3 lst.py -d input.lst output.txt") | |
else: | |
if argv[1] == "-e": | |
with open(argv[2], "r") as txt, open(argv[3], "wb") as lst: | |
encode(txt, lst, int(argv[4])) | |
elif args[1] == "-d": | |
with open(argv[2], "rb") as lst, open(argv[3], "wb") as txt: | |
decode(lst, txt) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think you have a typo on line 81, "args" instead of "argv"