Make a2_pack_fwd.py have the mini-linker from a2_pack_rev.py
authorNick Downing <nick@ndcode.org>
Tue, 21 Jun 2022 09:01:31 +0000 (19:01 +1000)
committerNick Downing <nick@ndcode.org>
Tue, 21 Jun 2022 09:01:31 +0000 (19:01 +1000)
loader/a2_pack_fwd.py

index 86bcedb..d5c49cf 100755 (executable)
@@ -216,20 +216,19 @@ FIXUP_FLAG_TARGET_END_RELATIVE = 2
 FIXUP_FLAG_LO_BYTE = 4
 FIXUP_FLAG_HI_BYTE = 8
 
-# each section has a data area, an end address and a list of fixups
-# the data is constructed from top to bottom, hence is reversed here
-# relocation is done after section lengths and end addresses known
+# each section has a data area, a load address and a list of fixups
+# relocation is done after section lengths and load addresses known
 class Section:
-  def __init__(self, data, end_addr, fixups):
+  def __init__(self, data, load_addr, fixups):
     self.data = data
-    self.end_addr = end_addr
+    self.load_addr = load_addr
     self.fixups = fixups
 section_lzss_unpack = Section([], 0, [])
 section_loader = Section([], 0, [])
 section_payload = Section([], 0, [])
 
-# sections are output to the a2bin file from top to bottom as follows:
-sections = [section_lzss_unpack, section_loader, section_payload]
+# sections are output to the a2bin file from bottom to top as follows:
+sections = [section_payload, section_loader, section_lzss_unpack]
 
 # report is a 5-tuple:
 #   (report type, ihx start, ihx end, a2bin start, a2bin end)
@@ -400,19 +399,24 @@ section_payload.fixups.extend(
   ] 
 )
 
-# relocate
+# sections that were constructed in reverse can now be made normal
+section_lzss_unpack.data = section_lzss_unpack.data[::-1]
+section_loader.data = section_loader.data[::-1]
+section_payload.data = section_payload.data[::-1]
+
+# relocate from top down
 load_addr = end_addr
-for section in sections:
-  section.end_addr = load_addr
+for section in sections[::-1]:
   load_addr -= len(section.data)
+  section.load_addr = load_addr
 load_size = end_addr - load_addr
 
 for report_type, addr0, addr1, addr2, addr3 in report[::-1]:
   if report_type == REPORT_TYPE_DIRECT_POKE:
     print(f'[0x{addr0:04x}, 0x{addr1:04x})')
   else:
-    addr2 += section_payload.end_addr
-    addr3 += section_payload.end_addr
+    addr2 += section_payload.load_addr + len(section_payload.data)
+    addr3 += section_payload.load_addr + len(section_payload.data)
     print(
       f'[0x{addr0:04x}, 0x{addr1:04x}) -> [0x{addr2:04x}, 0x{addr3:04x})' + (
         f'{100. * (addr3 - addr2) / (addr1 - addr0):6.1f}%'
@@ -424,24 +428,21 @@ for report_type, addr0, addr1, addr2, addr3 in report[::-1]:
 bin = []
 for section in sections:
   for fixup_flags, fixup_addr, target_section, target_addr in section.fixups:
-    assert fixup_flags & FIXUP_FLAG_TARGET_END_RELATIVE
-    target_addr += target_section.end_addr
-
-    # fixup_addr is in range -len(section.data) .. -1
-    # -1 means last byte of target_section, but since the target_section data is
-    # reversed, a fixup at -1 would be done at data[0] and so forth
-    assert fixup_flags & FIXUP_FLAG_FIXUP_END_RELATIVE
-    fixup_addr = ~fixup_addr
+    if fixup_flags & FIXUP_FLAG_FIXUP_END_RELATIVE:
+      fixup_addr += len(section.data)
+    if fixup_flags & FIXUP_FLAG_TARGET_END_RELATIVE:
+      target_addr += len(target_section.data)
+
+    target_addr += target_section.load_addr
     if fixup_flags & FIXUP_FLAG_LO_BYTE:
       assert section.data[fixup_addr] == 0
       section.data[fixup_addr] = target_addr & 0xff
-      fixup_addr -= 1
+      fixup_addr += 1
     if fixup_flags & FIXUP_FLAG_HI_BYTE:
       assert section.data[fixup_addr] == 0
       section.data[fixup_addr] = target_addr >> 8
-      #fixup_addr -= 1
+      #fixup_addr += 1
   bin.extend(section.data)
-bin = bin[::-1]
 
 hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
 with open(out_a2bin, 'wb') as fout: