Created
January 31, 2023 06:36
-
-
Save NWPlayer123/c00569500c3b34608de75ce9e0e1c030 to your computer and use it in GitHub Desktop.
!Extremely Slow! Python reimplementation of https://gist.github.com/NWPlayer123/72648a8f8d29ab48b4b070bebdb8d7f0
This file contains hidden or 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 struct import pack, unpack | |
import sys | |
#.bss | |
left9 = [0] * 0x400 #u16 | |
right9 = [0] * 0x400 #u16 | |
left12 = [0] * 0x10000 #u16 | |
right12 = [0] * 0x10000 #u16 | |
stack = [0] * 0x100 #u32 | |
#.sbss | |
bitlen = [0, 0] #s32 | |
ccnt = [0, 0] #s32 | |
wptr = [0, 0] #s32 | |
bitcode = [0, 0] #u32 | |
def getbitsc(src, size, slot): | |
global bitlen, wptr, bitcode | |
src.seek(wptr[slot]) | |
m = bitlen[slot] | |
g = bitcode[slot] | |
if m + size > 32: | |
j = unpack(">I", src.read(4))[0] | |
wptr[slot] += 4 | |
bitlen[slot] = (m + size - 32) & 0xFFFFFFFF; | |
bitcode[slot] = (j << (m + size - 32)) & 0xFFFFFFFF | |
return (g >> (32 - size)) | (j >> (64 - size - m)) | |
elif m + size == 32: | |
wptr[slot] += 4 | |
bitlen[slot] = 0 | |
bitcode[slot] = unpack(">I", src.read(4))[0] | |
return g >> (32 - size) | |
else: | |
bitlen[slot] = (m + size) & 0xFFFFFFFF | |
bitcode[slot] = (g << size) & 0xFFFFFFFF | |
return g >> (32 - size) | |
def readtree9(src): | |
global ccnt, stack, left9, right9 | |
sp = 0 | |
j = ccnt[0] | |
m = ccnt[0] | |
while True: | |
if getbitsc(src, 1, 0): | |
stack[sp] = (j | 0x80000000) & 0xFFFFFFFF | |
stack[sp + 1] = (j | 0x40000000) & 0xFFFFFFFF | |
j += 1 | |
m += 1 | |
sp += 2 | |
else: | |
z = getbitsc(src, 9, 0) | |
while sp: | |
sp -= 1 | |
f = stack[sp] | |
if not f & 0x80000000: | |
left9[f & 0x3FFFFFFF] = (z & 0xFFFF) | |
j = m | |
break | |
else: | |
right9[f & 0x3FFFFFFF] = (z & 0xFFFF) | |
z = f & 0x3FFFFFFF | |
if sp == 0: | |
return z | |
def readtree12(src): | |
global ccnt, stack, left12, right12 | |
sp = 0 | |
j = ccnt[1] | |
m = ccnt[1] | |
while True: | |
if getbitsc(src, 1, 1): | |
stack[sp] = (j | 0x80000000) & 0xFFFFFFFF | |
stack[sp + 1] = (j | 0x40000000) & 0xFFFFFFFF | |
j += 1 | |
m += 1 | |
sp += 2 | |
else: | |
z = getbitsc(src, 15, 1) | |
while sp: | |
sp -= 1 | |
f = stack[sp] | |
if not f & 0x80000000: | |
left12[f & 0x3FFFFFFF] = (z & 0xFFFF) | |
j = m | |
break | |
else: | |
right12[f & 0x3FFFFFFF] = (z & 0xFFFF) | |
z = f & 0x3FFFFFFF | |
if sp == 0: | |
return z | |
with open(sys.argv[1], "rb") as f: | |
with open(".".join(sys.argv[1].split(".")[:-1]), "wb+") as o: | |
header = unpack(">4s2I", f.read(12)) | |
assert header[0] == "ASH0" | |
out_size = header[1] | |
wptr = [12, header[2]] | |
bitlen = [0, 0] | |
ccnt = [0x200, 0x8000] #remaining allocation for each tree | |
#get initial code for each tree | |
getbitsc(f, 32, 0) | |
getbitsc(f, 32, 1) | |
root9 = readtree9(f) | |
root12 = readtree12(f) | |
q = 0 | |
while q < out_size: | |
j = root9 | |
while j >= 0x200: | |
if getbitsc(f, 1, 0): | |
j = right9[j] | |
else: | |
j = left9[j] | |
if j < 0x100: | |
o.seek(q) | |
o.write(pack(">B", j)) | |
q += 1 | |
else: | |
i = root12 | |
while i >= 0x8000: | |
if getbitsc(f, 1, 1): | |
i = right12[i] | |
else: | |
i = left12[i] | |
j -= 253 | |
i = q - i - 1 | |
while j > 0: | |
o.seek(i) | |
data = o.read(1) | |
o.seek(q) | |
o.write(data) | |
j -= 1 | |
q += 1 | |
i += 1 | |
print(q) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment