dest = rle2[9] + (rle2[0xd] << 8)
assert rle2[0x6b] == 0x4c # jmp NNNN
-load_addr = rle2[0x6c] | (rle2[0x6d] << 8)
-load_size = dest + 1 - load_addr
-
-print(f'rle2 {load_size0:04x} orig {load_size:04x}')
+entry_point = rle2[0x6c] | (rle2[0x6d] << 8)
rle2 = rle2[0xa1:]
bin = []
bin.extend(rle2[-1:-3:-1] * (count >> 1) + rle2[-1:] * (count & 1))
del rle2[-2:]
assert len(rle2) == 0
-assert len(bin) == load_size
-
bin = bin[::-1]
-hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
+load_size = len(bin)
+print(f'rle2 {load_size0:04x} orig {load_size:04x}')
+
+load_addr = dest + 1 - load_size
+if entry_point != load_addr:
+ bin = [0x4c, entry_point & 0xff, entry_point >> 8] + bin # jmp NNNN
+ load_addr -= 3
+ load_size += 3
+
+hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
with open(out_bin, 'wb') as fout:
fout.write(bytes(hdr + bin))
load_size0 = hdr[2] | (hdr[3] << 8)
assert load_size0 == len(bin)
+# absorb a jump to the real entry point, ensuring that we
+# can losslessly reconstruct the jump when decoding later
+entry_point = load_addr0
+if bin[0] == 0x4c: # jmp NNNN
+ entry_point = bin[1] | (bin[2] << 8)
+ assert entry_point != load_addr0 + 3
+
+ bin = bin[3:]
+ load_addr0 += 3
+ load_size0 -= 3
+
rle2 = []
while len(bin):
# look for a run
rle2[0xd] = dest >> 8
assert rle2[0x6b] == 0x4c # jmp NNNN
-rle2[0x6c] = load_addr0 & 0xff
-rle2[0x6d] = load_addr0 >> 8
+rle2[0x6c] = entry_point & 0xff
+rle2[0x6d] = entry_point >> 8
hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
-
with open(out_bin, 'wb') as fout:
fout.write(bytes(hdr + rle2))
dest = rle[9] + (rle[0xd] << 8)
assert rle[0x67] == 0x4c # jmp NNNN
-load_addr = rle[0x68] | (rle[0x69] << 8)
-load_size = dest + 1 - load_addr
-
-print(f'rle {load_size0:04x} orig {load_size:04x}')
+entry_point = rle[0x68] | (rle[0x69] << 8)
rle = rle[0x6a:]
bin = []
bin.extend(rle[-1:] * count)
del rle[-1:]
assert len(rle) == 0
-assert len(bin) == load_size
-
bin = bin[::-1]
-hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
+load_size = len(bin)
+print(f'rle {load_size0:04x} orig {load_size:04x}')
+
+load_addr = dest + 1 - load_size
+if entry_point != load_addr:
+ bin = [0x4c, entry_point & 0xff, entry_point >> 8] + bin # jmp NNNN
+ load_addr -= 3
+ load_size += 3
+
+hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
with open(out_bin, 'wb') as fout:
fout.write(bytes(hdr + bin))
load_size0 = hdr[2] | (hdr[3] << 8)
assert load_size0 == len(bin)
+# absorb a jump to the real entry point, ensuring that we
+# can losslessly reconstruct the jump when decoding later
+entry_point = load_addr0
+if bin[0] == 0x4c: # jmp NNNN
+ entry_point = bin[1] | (bin[2] << 8)
+ assert entry_point != load_addr0 + 3
+
+ bin = bin[3:]
+ load_addr0 += 3
+ load_size0 -= 3
+
rle = []
while len(bin):
# look for a run
rle[0xd] = dest >> 8
assert rle[0x67] == 0x4c # jmp NNNN
-rle[0x68] = load_addr0 & 0xff
-rle[0x69] = load_addr0 >> 8
+rle[0x68] = entry_point & 0xff
+rle[0x69] = entry_point >> 8
hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
-
with open(out_bin, 'wb') as fout:
fout.write(bytes(hdr + rle))
bits = tree[0x2e] | ((tree[0x2f] & 0x20) << 3)
assert tree[0x60] == 0x4c # jmp NNNN
-load_addr = tree[0x61] | (tree[0x62] << 8)
+entry_point = tree[0x61] | (tree[0x62] << 8)
assert tree[0x65] == 0xe9 # sbc #NN
break3 = tree[0x66]
print(f'tree {load_size0:04x} orig {load_size:04x}')
load_addr = dest + 1 - load_size
-hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
+if entry_point != load_addr:
+ bin = [0x4c, entry_point & 0xff, entry_point >> 8] + bin # jmp NNNN
+ load_addr -= 3
+ load_size += 3
+hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
with open(out_bin, 'wb') as fout:
fout.write(bytes(hdr + bin))
load_size0 = hdr[2] | (hdr[3] << 8)
assert load_size0 == len(bin)
-bin = list(bin)
+# absorb a jump to the real entry point, ensuring that we
+# can losslessly reconstruct the jump when decoding later
+entry_point = load_addr0
+if bin[0] == 0x4c: # jmp NNNN
+ entry_point = bin[1] | (bin[2] << 8)
+ assert entry_point != load_addr0 + 3
+
+ bin = bin[3:]
+ load_addr0 += 3
+ load_size0 -= 3
freq = heapdict() #{}
for i in range(len(bin) - 1):
tree[0x2f] |= (bits >> 3) & 0x20 # clc or sec
assert tree[0x60] == 0x4c # jmp NNNN
-tree[0x61] = load_addr0 & 0xff
-tree[0x62] = load_addr0 >> 8
+tree[0x61] = entry_point & 0xff
+tree[0x62] = entry_point >> 8
assert tree[0x65] == 0xe9 # sbc #NN
tree[0x66] = break3
tree[0x7e] = left1 >> 8
hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
-
with open(out_bin, 'wb') as fout:
fout.write(bytes(hdr + tree))