Add files

This commit is contained in:
ISSOtm
2018-10-19 00:45:50 +02:00
parent f7afa5a932
commit ad3623c9d2
30 changed files with 3399 additions and 0 deletions

76
src/tools/pb16.py Normal file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env python
"""
PB16 encoder
Copyright 2018 Damian Yerrick
[License: zlib]
PB16 can be thought of as either of two things:
- Run-length encoding (RLE) of two interleaved streams, with
unary-coded run lengths
- LZSS with a fixed distance of 2 and a fixed copy length of 1
Each packet represents 8 bytes of uncompressed data. The bits
of the first byte in a packet, ordered from MSB to LSB, encode
which of the following eight bytes repeat the byte 2 bytes back.
A 0 means a literal byte follows; a 1 means a repeat.
It's similar to the PB8 codec that I've used for NES CHR data,
adapted to the interleaving of Game Boy and Super NES CHR data.
"""
import itertools
import sys
import argparse
def ichunk(data, count):
"""Turn an iterable into lists of a fixed length."""
data = iter(data)
while True:
b = list(itertools.islice(data, count))
if len(b) == 0: break
yield b
def pb16(data):
"""Compress an iterable of bytes into a generator of PB16 packets."""
prev = [0, 0]
for unco in ichunk(data, 8):
# Pad the chunk to a multiple of 2 then to 8 bytes
if len(unco) < 8:
if len(unco) == 1:
unco.append(prev[1])
elif len(unco) % 2:
unco.append(unco[-2])
unco.extend(unco[-2:]*(8 - len(unco)))
packet = bytearray(1)
for i, value in enumerate(unco):
if value == prev[i % 2]:
packet[0] |= 0x80 >> i
else:
packet.append(value)
prev[i % 2] = value
yield packet
def parse_argv(argv):
p = argparse.ArgumentParser()
p.add_argument("infile")
p.add_argument("outfile")
return p.parse_args(argv[1:])
def main(argv=None):
args = parse_argv(argv or sys.argv)
with open(args.infile, "rb") as infp:
data = infp.read()
with open(args.outfile, "wb") as outfp:
outfp.writelines(pb16(data))
def test():
tests = [
()
]
s = b"ABAHBHCHCECEFEFE"
print(b''.join(pb16(s)).hex())
if __name__=='__main__':
main()
## test()