mirror of
https://github.com/notwa/mm
synced 2024-11-05 00:29:02 -08:00
allow for compressed files
This commit is contained in:
parent
1fc77b93ad
commit
608589b274
1 changed files with 57 additions and 27 deletions
84
z64dump.py
84
z64dump.py
|
@ -43,6 +43,8 @@ def z_dump_file(f, i=0, name=None, uncompress=True):
|
||||||
pe = R4(f.read(4)) # physical end
|
pe = R4(f.read(4)) # physical end
|
||||||
here = f.tell()
|
here = f.tell()
|
||||||
|
|
||||||
|
dump = uncompress and dump_wrap or dump_as
|
||||||
|
|
||||||
if vs == ve == ps == pe == 0:
|
if vs == ve == ps == pe == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -56,13 +58,13 @@ def z_dump_file(f, i=0, name=None, uncompress=True):
|
||||||
|
|
||||||
if ps == 0xFFFFFFFF or pe == 0xFFFFFFFF:
|
if ps == 0xFFFFFFFF or pe == 0xFFFFFFFF:
|
||||||
#lament('file does not exist')
|
#lament('file does not exist')
|
||||||
dump_as(b'', fn, size)
|
dump_as(b'', fn, 0)
|
||||||
elif pe == 0:
|
elif pe == 0:
|
||||||
#lament('file is uncompressed')
|
#lament('file is uncompressed')
|
||||||
pe = ps + size
|
pe = ps + size
|
||||||
f.seek(ps)
|
f.seek(ps)
|
||||||
data = f.read(pe - ps)
|
data = f.read(pe - ps)
|
||||||
dump_wrap(data, fn, size)
|
dump(data, fn, size)
|
||||||
else:
|
else:
|
||||||
#lament('file is compressed')
|
#lament('file is compressed')
|
||||||
f.seek(ps)
|
f.seek(ps)
|
||||||
|
@ -70,16 +72,16 @@ def z_dump_file(f, i=0, name=None, uncompress=True):
|
||||||
if compressed[:4] == b'Yaz0':
|
if compressed[:4] == b'Yaz0':
|
||||||
if uncompress:
|
if uncompress:
|
||||||
data = Yaz0.decode(compressed)
|
data = Yaz0.decode(compressed)
|
||||||
dump_wrap(data, fn, size)
|
dump(data, fn, size)
|
||||||
else:
|
else:
|
||||||
dump_wrap(compressed, fn+'.Yaz0', len(compressed))
|
dump(compressed, fn+'.Yaz0', len(compressed))
|
||||||
else:
|
else:
|
||||||
if uncompress:
|
if uncompress:
|
||||||
lament('unknown compression; skipping:', fn)
|
lament('unknown compression; skipping:', fn)
|
||||||
lament(compressed[:4])
|
lament(compressed[:4])
|
||||||
else:
|
else:
|
||||||
lament('unknown compression:', fn)
|
lament('unknown compression:', fn)
|
||||||
dump_wrap(compressed, fn, len(compressed))
|
dump(compressed, fn, len(compressed))
|
||||||
|
|
||||||
f.seek(here)
|
f.seek(here)
|
||||||
return True
|
return True
|
||||||
|
@ -97,7 +99,7 @@ def z_find_dma(f):
|
||||||
else:
|
else:
|
||||||
f.seek(len(rest), 1)
|
f.seek(len(rest), 1)
|
||||||
|
|
||||||
def z_dump(f, names=None):
|
def z_dump(f, names=None, uncompress=True):
|
||||||
f.seek(0x1060) # skip header when finding dmatable
|
f.seek(0x1060) # skip header when finding dmatable
|
||||||
addr = z_find_dma(f)
|
addr = z_find_dma(f)
|
||||||
if addr == None:
|
if addr == None:
|
||||||
|
@ -112,17 +114,17 @@ def z_dump(f, names=None):
|
||||||
i = 0
|
i = 0
|
||||||
if names:
|
if names:
|
||||||
for n in names:
|
for n in names:
|
||||||
if z_dump_file(f, i, n):
|
if z_dump_file(f, i, n, uncompress):
|
||||||
i += 1
|
i += 1
|
||||||
else:
|
else:
|
||||||
lament("ran out of filenames")
|
lament("ran out of filenames")
|
||||||
break
|
break
|
||||||
while z_dump_file(f, i):
|
while z_dump_file(f, i, None, uncompress):
|
||||||
i += 1
|
i += 1
|
||||||
if names and i > len(names):
|
if names and i > len(names):
|
||||||
lament("extraneous filenames")
|
lament("extraneous filenames")
|
||||||
|
|
||||||
def dump_rom(fn):
|
def dump_rom(fn, uncompress=True):
|
||||||
with open(fn, 'rb') as f:
|
with open(fn, 'rb') as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
|
|
||||||
|
@ -151,7 +153,7 @@ def dump_rom(fn):
|
||||||
names = [n.strip() for n in names]
|
names = [n.strip() for n in names]
|
||||||
with SubDir(romhash):
|
with SubDir(romhash):
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
z_dump(f, names)
|
z_dump(f, names, uncompress)
|
||||||
|
|
||||||
def z_read_file(path, fn=None):
|
def z_read_file(path, fn=None):
|
||||||
if fn == None:
|
if fn == None:
|
||||||
|
@ -205,7 +207,10 @@ def fix_rom(f):
|
||||||
f.write(W4(crc1))
|
f.write(W4(crc1))
|
||||||
f.write(W4(crc2))
|
f.write(W4(crc2))
|
||||||
|
|
||||||
def create_rom(d):
|
def align(x):
|
||||||
|
return (x + 15) // 16 * 16
|
||||||
|
|
||||||
|
def create_rom(d, compress=False):
|
||||||
root, _, files = next(os.walk(d))
|
root, _, files = next(os.walk(d))
|
||||||
files.sort()
|
files.sort()
|
||||||
|
|
||||||
|
@ -217,7 +222,8 @@ def create_rom(d):
|
||||||
f.write(bytearray(rom_size))
|
f.write(bytearray(rom_size))
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
|
||||||
start = 0
|
start_v = 0
|
||||||
|
start_p = 0
|
||||||
|
|
||||||
for i, fn in enumerate(files):
|
for i, fn in enumerate(files):
|
||||||
path = os.path.join(root, fn)
|
path = os.path.join(root, fn)
|
||||||
|
@ -226,44 +232,68 @@ def create_rom(d):
|
||||||
lament('skipping:', fn)
|
lament('skipping:', fn)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
size_v = len(data)
|
||||||
|
size_p = size_v
|
||||||
|
unempty = size_v > 0
|
||||||
|
compressed = size_v >= 4 and data[:4] == b'Yaz0'
|
||||||
|
|
||||||
if i <= 2:
|
if i <= 2:
|
||||||
# makerom, boot, dmadata need to be exactly where they were
|
# makerom, boot, dmadata need to be exactly where they were
|
||||||
start = vs
|
start_v = vs
|
||||||
|
start_p = start_v
|
||||||
else:
|
else:
|
||||||
# align to next row
|
start_v = align(start_v)
|
||||||
start = (start + 15)//16*16
|
start_p = align(start_p)
|
||||||
|
if compress and unempty:
|
||||||
|
lament('Comp…: {}'.format(fn))
|
||||||
|
data = Yaz0.encode(data)
|
||||||
|
size_p = len(data)
|
||||||
|
lament("Ratio: {:3}%".format(int(size_p / size_v * 100)))
|
||||||
|
compressed = True
|
||||||
|
|
||||||
size = len(data)
|
if unempty:
|
||||||
if size:
|
ps = start_p
|
||||||
ps = start
|
if compressed:
|
||||||
pe = 0
|
pe = align(start_p + size_p)
|
||||||
|
ve = vs + int.from_bytes(data[4:8], 'big')
|
||||||
|
#ve = vs + len(Yaz0.decode(data))
|
||||||
|
else:
|
||||||
|
pe = 0
|
||||||
|
ve = vs + size_v
|
||||||
else:
|
else:
|
||||||
ps = 0xFFFFFFFF
|
ps = 0xFFFFFFFF
|
||||||
pe = 0xFFFFFFFF
|
pe = 0xFFFFFFFF
|
||||||
ve = vs + size
|
ve = vs
|
||||||
|
|
||||||
assert(start <= rom_size)
|
|
||||||
assert(start + size <= rom_size)
|
assert(start_v <= rom_size)
|
||||||
|
assert(start_v + size_v <= rom_size)
|
||||||
assert(vs < rom_size)
|
assert(vs < rom_size)
|
||||||
assert(ve <= rom_size)
|
assert(ve <= rom_size)
|
||||||
|
|
||||||
if size:
|
if unempty:
|
||||||
f.seek(start)
|
f.seek(start_p)
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
|
||||||
dma.append([vs, ve, ps, pe])
|
dma.append([vs, ve, ps, pe])
|
||||||
start += size
|
|
||||||
|
start_v += size_v
|
||||||
|
start_p += size_p
|
||||||
|
|
||||||
z_write_dma(f, dma)
|
z_write_dma(f, dma)
|
||||||
fix_rom(f)
|
fix_rom(f)
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
|
compress = False
|
||||||
for path in args:
|
for path in args:
|
||||||
|
if path == '-c':
|
||||||
|
compress = not compress
|
||||||
|
continue
|
||||||
# directories are technically files, so check this first
|
# directories are technically files, so check this first
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
create_rom(path)
|
create_rom(path, compress)
|
||||||
elif os.path.isfile(path):
|
elif os.path.isfile(path):
|
||||||
dump_rom(path)
|
dump_rom(path, not compress)
|
||||||
else:
|
else:
|
||||||
lament('no-op:', path)
|
lament('no-op:', path)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue