Skip to content

Instantly share code, notes, and snippets.

@NWPlayer123
Created January 31, 2023 06:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NWPlayer123/c00569500c3b34608de75ce9e0e1c030 to your computer and use it in GitHub Desktop.
Save NWPlayer123/c00569500c3b34608de75ce9e0e1c030 to your computer and use it in GitHub Desktop.
!Extremely Slow! Python reimplementation of https://gist.github.com/NWPlayer123/72648a8f8d29ab48b4b070bebdb8d7f0
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