1
0
Fork 0
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:
Connor Olding 2016-04-04 07:37:08 -07:00
parent 1fc77b93ad
commit 608589b274

View file

@ -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)