In a2_pack.py unpack in address order (rather than compressed then uncompressed)...
authorNick Downing <nick@ndcode.org>
Tue, 21 Jun 2022 01:53:41 +0000 (11:53 +1000)
committerNick Downing <nick@ndcode.org>
Tue, 21 Jun 2022 01:53:41 +0000 (11:53 +1000)
loader/a2_pack.py
loader/lzss_unpack.asm

index a9e0774..49bd512 100755 (executable)
@@ -205,101 +205,92 @@ segments = (
   intersect(segments, [0x100, 0x200])
 )
 
-compressed = []
-uncompressed = []
-for i in range(0, len(segments), 2):
-  addr0 = segments[i]
-  addr1 = segments[i + 1]
-  data = list(intelhex.tobinstr(addr0, addr1 - 1))
-  if len(data) > 0x100:
-    compressed.append((addr0, addr1, lzss_pack(addr0, data)))
-  else:
-    uncompressed.append((addr0, addr1, data))
-
 bin = [0x4c, 0x00, 0x00] # jmp 0 (fixup: loader)
 loader = [
   0xd8,                # cld
   0xa2, 0xff,  # ldx #0xff
   0x9a,                # txs
 ]
-compressed_addr = load_addr + len(bin)
-for addr0, addr1, data in compressed:
-  addr2 = load_addr + len(bin)
-  bin.extend(data)
-  addr3 = load_addr + len(bin)
-  print(
-    f'[0x{addr0:04x}, 0x{addr1:04x}) -> [0x{addr2:04x}, 0x{addr3:04x}) {100. * (addr3 - addr2) / (addr1 - addr0):5.1f}%'
-  )
-  if addr2 == compressed_addr:
-    loader.extend(
-      [
-        0xa9, compressed_addr & 0xff,  # lda #<compressed_addr
-        0x85, 0xf0,                    # sta src
-        0xa9, compressed_addr >> 8,    # lda #>compressed_addr
-        0x85, 0xf1,                    # sta src + 1
-      ]
-    )
-  loader.extend([0x20, 0x00, 0x00]) # jsr 0 (fixup: lzss_unpack)
-for addr0, addr1, data in uncompressed:
-  count = addr1 - addr0
-  zpage = addr0 < 0x100
-  if count >= 8:
+fixup_lzss_unpack = []
+for i in range(0, len(segments), 2):
+  addr0 = segments[i]
+  addr1 = segments[i + 1]
+  data = list(intelhex.tobinstr(addr0, addr1 - 1))
+  if len(data) > 0x100:
     addr2 = load_addr + len(bin)
-    bin.extend(data)
+    bin.extend(lzss_pack(addr0, data))
     addr3 = load_addr + len(bin)
     print(
-      f'[0x{addr0:04x}, 0x{addr1:04x}) -> [0x{addr2:04x}, 0x{addr3:04x})'
+      f'[0x{addr0:04x}, 0x{addr1:04x}) -> [0x{addr2:04x}, 0x{addr3:04x}) {100. * (addr3 - addr2) / (addr1 - addr0):5.1f}%'
     )
 
-    addr1 -= 0x100
-    addr3 -= 0x100
+    addr2 += 5 - 0x100
     loader.extend(
       [
-        0xa2, -count & 0xff,                           # ldx #-count
-        0xbd, addr3 & 0xff, (addr3 >> 8) & 0xff,       # lda addr3,x
-        0x95, addr1 & 0xff,                            # sta *addr1,x
-        0xe8,                                          # inx
-        0xd0, 0xf8                                     # bne .-6
-      ]
-    if zpage else
-      [
-        0xa2, -count & 0xff,                           # ldx #-count
-        0xbd, addr3 & 0xff, (addr3 >> 8) & 0xff,       # lda addr3,x
-        0x9d, addr1 & 0xff, (addr1 >> 8) & 0xff,       # sta addr1,x
-        0xe8,                                          # inx
-        0xd0, 0xf7                                     # bne .-7
+        0xa9, addr2 & 0xff,    # lda #<addr2
+        0xa0, addr2 >> 8,      # ldy #>addr2
+        0x20, 0x00, 0x00,      # jsr 0 (fixup: lzss_unpack)
       ]
     )
+    fixup_lzss_unpack.append(len(loader) - 2)
   else:
-    print(f'[0x{addr0:04x}, 0x{addr1:04x})')
-    for i in range(count):
+    count = addr1 - addr0
+    zpage = addr0 < 0x100
+    if count > 4:
+      addr2 = load_addr + len(bin)
+      bin.extend(data)
+      addr3 = load_addr + len(bin)
+      print(
+        f'[0x{addr0:04x}, 0x{addr1:04x}) -> [0x{addr2:04x}, 0x{addr3:04x})'
+      )
+  
+      addr1 -= 0x100
+      addr3 -= 0x100
       loader.extend(
         [
-          0xa9, data[i],                       # lda #data
-          0x85, addr0,                         # sta *addr0
+          0xa2, -count & 0xff,                         # ldx #-count
+          0xbd, addr3 & 0xff, (addr3 >> 8) & 0xff,     # lda addr3,x
+          0x95, addr1 & 0xff,                          # sta *addr1,x
+          0xe8,                                                # inx
+          0xd0, 0xf8                                   # bne .-6
         ]
       if zpage else
         [
-          0xa9, data[i],                       # lda #data
-          0x8d, addr0 & 0xff, addr0 >> 8       # sta addr0
+          0xa2, -count & 0xff,                         # ldx #-count
+          0xbd, addr3 & 0xff, (addr3 >> 8) & 0xff,     # lda addr3,x
+          0x9d, addr1 & 0xff, (addr1 >> 8) & 0xff,     # sta addr1,x
+          0xe8,                                                # inx
+          0xd0, 0xf7                                   # bne .-7
         ]
       )
-      addr0 += 1
-if len(compressed):
+    else:
+      print(f'[0x{addr0:04x}, 0x{addr1:04x})')
+      for i in range(count):
+        loader.extend(
+          [
+            0xa9, data[i],                     # lda #data
+            0x85, addr0,                       # sta *addr0
+          ]
+        if zpage else
+          [
+            0xa9, data[i],                     # lda #data
+            0x8d, addr0 & 0xff, addr0 >> 8     # sta addr0
+          ]
+        )
+        addr0 += 1
+loader.extend(
+  [0x4c, entry_point & 0xff, entry_point >> 8] # jmp entry_point
+)
+if len(fixup_lzss_unpack):
   lzss_unpack_addr = load_addr + len(bin)
-  for i in range(len(compressed)):
-    assert loader[12 + i * 3] == 0x20 # jsr
-    loader[12 + i * 3 + 1] = lzss_unpack_addr & 0xff
-    loader[12 + i * 3 + 2] = lzss_unpack_addr >> 8
+  for i in fixup_lzss_unpack:
+    loader[i] = lzss_unpack_addr & 0xff
+    loader[i + 1] = lzss_unpack_addr >> 8
   bin.extend(lzss_unpack)
 loader_addr = load_addr + len(bin)
-assert bin[0] == 0x4c # jmp
 bin[1] = loader_addr & 0xff
 bin[2] = loader_addr >> 8
-bin.extend(
-  loader + [0x4c, entry_point & 0xff, entry_point >> 8] # jmp entry_point
-)
+bin.extend(loader)
 load_size = len(bin)
 
 hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
index 19ef09e..262134a 100644 (file)
@@ -13,11 +13,11 @@ len:        .ds     1                       ; length
 
        .area   text
 
-       ; enter with src = address of data block
-       ;   0 (word): destination address
-       ;   2 (word): count of bit buffer refills to do
-       ;   4 (byte): bit buffer (highest 1 = sentinel)
-       ;   5+: LZSS-compressed data
+       ; enter with y:a = address of LZSS data - 0x100
+       ; LZSS data is preceded by data block
+       ;   -5 (word): destination address
+       ;   -3 (word): count of bit buffer refills to do
+       ;   -1 (byte): bit buffer (highest 1 = sentinel)
        ; type of LZSS item depends on a bit from bit buffer:
        ;   0: literal
        ;   1: pointer
@@ -25,15 +25,11 @@ len:        .ds     1                       ; length
        ;   0: short pointer, lddddddd
        ;   1: long pointer, lllllldd:dddddddd (LS byte first)
 
-       ; src += 5 - 0x100
-       clc
-       lda     src
-       adc     #5
+       ; src = y:a
        sta     src
-       bcs     0$
-       dec     src + 1
+       sty     src + 1
 
-0$:    ; copy data block
+       ; copy data block
        ldy     #-5
 1$:    lda     [src],y
        sta     dest + 5 - 0x100,y