intersect(segments, [0x100, 0x200])
)
-# sections are output to the a2bin file from top to bottom as follows:
-SECTION_UNPACKER = 0
-SECTION_LOADER = 1
-SECTION_PAYLOAD = 2
-N_SECTIONS = 3
-
# fixup is a 4-tuple:
# (fixup type, fixup address, target section, target address)
# both addresses are negative and relative to the end address of the section
self.data = data
self.end_addr = end_addr
self.fixups = fixups
-sections = [Section([], 0, []) for i in range(N_SECTIONS)]
+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]
# report is a 5-tuple:
# (report type, ihx start, ihx end, a2bin start, a2bin end)
report = []
# epilogue
-sections[SECTION_LOADER].data.extend(
+section_loader.data.extend(
[
0x4c, entry_point & 0xff, entry_point >> 8, # jmp entry_point
][::-1]
# use of zpage version is determined byte by byte
for i in data[::-1]:
addr1 -= 1
- sections[SECTION_LOADER].data.extend(
+ section_loader.data.extend(
[
0xa9, i, # lda #data
0x85, addr1, # sta *addr1
][::-1]
)
elif len(data) <= 0x100:
- addr3 = -len(sections[SECTION_PAYLOAD].data)
- sections[SECTION_PAYLOAD].data.extend(
+ addr3 = -len(section_payload.data)
+ section_payload.data.extend(
data[::-1]
)
- addr2 = -len(sections[SECTION_PAYLOAD].data)
+ addr2 = -len(section_payload.data)
report.append(
(REPORT_TYPE_UNCOMPRESSED, addr0, addr1, addr2, addr3)
)
addr1 -= 0x100
addr3 -= 0x100
- sections[SECTION_LOADER].data.extend(
+ section_loader.data.extend(
[
0xa2, -len(data) & 0xff, # ldx #-count
0xbd, 0x00, 0x00, # lda addr3,x
0xd0, 0xf7 # bne .-7
][::-1]
)
- sections[SECTION_LOADER].fixups.extend(
+ section_loader.fixups.extend(
[
(
FIXUP_TYPE_WORD,
- 3 - len(sections[SECTION_LOADER].data),
- SECTION_PAYLOAD,
+ 3 - len(section_loader.data),
+ section_payload,
addr3
),
]
)
else:
- addr3 = -len(sections[SECTION_PAYLOAD].data)
- sections[SECTION_PAYLOAD].data.extend(
+ addr3 = -len(section_payload.data)
+ section_payload.data.extend(
lzss_pack(addr0, data)[::-1]
)
- addr2 = -len(sections[SECTION_PAYLOAD].data)
+ addr2 = -len(section_payload.data)
report.append(
(REPORT_TYPE_COMPRESSED, addr0, addr1, addr2, addr3)
)
- if len(sections[SECTION_UNPACKER].data) == 0:
- sections[SECTION_UNPACKER].data.extend(
+ if len(section_lzss_unpack.data) == 0:
+ section_lzss_unpack.data.extend(
lzss_unpack_fwd[::-1]
)
addr2 += 5 - 0x100
- sections[SECTION_LOADER].data.extend(
+ section_loader.data.extend(
[
0xa9, 0x00, # lda #<addr2
0xa0, 0x00, # ldy #>addr2
0x20, 0x00, 0x00, # jsr lzss_unpack_fwd
][::-1]
)
- sections[SECTION_LOADER].fixups.extend(
+ section_loader.fixups.extend(
[
(
FIXUP_TYPE_LO_BYTE,
- 1 - len(sections[SECTION_LOADER].data),
- SECTION_PAYLOAD,
+ 1 - len(section_loader.data),
+ section_payload,
addr2
),
(
FIXUP_TYPE_HI_BYTE,
- 3 - len(sections[SECTION_LOADER].data),
- SECTION_PAYLOAD,
+ 3 - len(section_loader.data),
+ section_payload,
addr2
),
(
FIXUP_TYPE_WORD,
- 5 - len(sections[SECTION_LOADER].data),
- SECTION_UNPACKER,
- -len(sections[SECTION_UNPACKER].data)
+ 5 - len(section_loader.data),
+ section_lzss_unpack,
+ -len(section_lzss_unpack.data)
),
]
)
# prologue
-sections[SECTION_LOADER].data.extend(
+section_loader.data.extend(
[
0xd8, # cld
0xa2, 0xff, # ldx #0xff
0x9a, # txs
][::-1]
)
-sections[SECTION_PAYLOAD].data.extend(
+section_payload.data.extend(
[
0x4c, 0x00, 0x00, # jmp loader
][::-1]
)
-sections[SECTION_PAYLOAD].fixups.extend(
+section_payload.fixups.extend(
[
(
FIXUP_TYPE_WORD,
- 1 - len(sections[SECTION_PAYLOAD].data),
- SECTION_LOADER,
- -len(sections[SECTION_LOADER].data)
+ 1 - len(section_payload.data),
+ section_loader,
+ -len(section_loader.data)
),
]
)
# relocate
load_addr = end_addr
-for i in range(N_SECTIONS):
- sections[i].end_addr = load_addr
- load_addr -= len(sections[i].data)
+for section in sections:
+ section.end_addr = load_addr
+ load_addr -= len(section.data)
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 += sections[SECTION_PAYLOAD].end_addr
- addr3 += sections[SECTION_PAYLOAD].end_addr
+ addr2 += section_payload.end_addr
+ addr3 += section_payload.end_addr
print(
f'[0x{addr0:04x}, 0x{addr1:04x}) -> [0x{addr2:04x}, 0x{addr3:04x})' + (
f'{100. * (addr3 - addr2) / (addr1 - addr0):6.1f}%'
)
bin = []
-for i in range(N_SECTIONS):
- for fixup_type, fixup_addr, section, addr in sections[i].fixups:
- addr += sections[section].end_addr
+for section in sections:
+ for fixup_type, fixup_addr, target_section, target_addr in section.fixups:
+ target_addr += target_section.end_addr
- # fixup_addr is in range -len(sections[i].data) .. -1
- # -1 means last byte of section, but since the section data is
+ # 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
if fixup_type == FIXUP_TYPE_LO_BYTE:
- assert sections[i].data[~fixup_addr] == 0
- sections[i].data[~fixup_addr] = addr & 0xff
+ assert section.data[~fixup_addr] == 0
+ section.data[~fixup_addr] = target_addr & 0xff
elif fixup_type == FIXUP_TYPE_HI_BYTE:
- assert sections[i].data[~fixup_addr] == 0
- sections[i].data[~fixup_addr] = addr >> 8
+ assert section.data[~fixup_addr] == 0
+ section.data[~fixup_addr] = target_addr >> 8
elif fixup_type == FIXUP_TYPE_WORD:
- assert sections[i].data[~fixup_addr] == 0
- sections[i].data[~fixup_addr] = addr & 0xff
- assert sections[i].data[~fixup_addr - 1] == 0
- sections[i].data[~fixup_addr - 1] = addr >> 8
+ assert section.data[~fixup_addr] == 0
+ section.data[~fixup_addr] = target_addr & 0xff
+ assert section.data[~fixup_addr - 1] == 0
+ section.data[~fixup_addr - 1] = target_addr >> 8
else:
assert False
- bin.extend(sections[i].data)
+ bin.extend(section.data)
bin = bin[::-1]
hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
intersect(segments, [0x200, 0x10000])
)
-# sections are output to the a2bin file from bottom to top as follows:
-SECTION_LOADER = 0
-SECTION_UNPACKER = 1
-SECTION_PAYLOAD = 2
-N_SECTIONS = 3
-
# fixup is a 4-tuple:
# (fixup type, fixup address, target section, target address)
# both addresses are relative to the load address of the section,
self.data = data
self.load_addr = load_addr
self.fixups = fixups
-sections = [Section([], 0, []) for i in range(N_SECTIONS)]
+section_lzss_unpack = Section([], 0, [])
+section_loader = Section([], 0, [])
+section_payload = Section([], 0, [])
+
+# sections are output to the a2bin file from bottom to top as follows:
+sections = [section_loader, section_lzss_unpack, section_payload]
# report is a 5-tuple:
# (report type, ihx start, ihx end, a2bin start, a2bin end)
report = []
# prologue
-sections[SECTION_LOADER].data.extend(
+section_loader.data.extend(
[
0x4c, entry_point & 0xff, entry_point >> 8, # jmp entry_point
][::-1]
# use of zpage version is determined byte by byte
for i in data:
- sections[SECTION_LOADER].data.extend(
+ section_loader.data.extend(
[
0xa9, i, # lda #data
0x85, addr0, # sta *addr0
)
addr0 += 1
elif len(data) <= 0x100:
- addr2 = len(sections[SECTION_PAYLOAD].data)
- sections[SECTION_PAYLOAD].data.extend(
+ addr2 = len(section_payload.data)
+ section_payload.data.extend(
data
)
- addr3 = len(sections[SECTION_PAYLOAD].data)
+ addr3 = len(section_payload.data)
report.append(
(REPORT_TYPE_UNCOMPRESSED, addr0, addr1, addr2, addr3)
)
if len(data) == 0x100:
# for the full count we will copy forward (an exception)
- sections[SECTION_LOADER].data.extend(
+ section_loader.data.extend(
[
0xa2, 0x00, # ldx #0
0xbd, 0x00, 0x00, # lda addr2,x
else:
addr0 -= 1
addr2 -= 1
- sections[SECTION_LOADER].data.extend(
+ section_loader.data.extend(
[
0xa2, len(data), # ldx #count
0xbd, 0x00, 0x00, # lda addr2,x
0xd0, 0xf7 # bne .-7
][::-1]
)
- sections[SECTION_LOADER].fixups.extend(
+ section_loader.fixups.extend(
[
(
FIXUP_TYPE_WORD,
- 3 - len(sections[SECTION_LOADER].data),
- SECTION_PAYLOAD,
+ 3 - len(section_loader.data),
+ section_payload,
addr2
),
]
)
else:
- addr2 = len(sections[SECTION_PAYLOAD].data)
- sections[SECTION_PAYLOAD].data.extend(
+ addr2 = len(section_payload.data)
+ section_payload.data.extend(
lzss_pack(addr1 - 1, data)
)
- addr3 = len(sections[SECTION_PAYLOAD].data)
+ addr3 = len(section_payload.data)
report.append(
(REPORT_TYPE_COMPRESSED, addr0, addr1, addr2, addr3)
)
- if len(sections[SECTION_UNPACKER].data) == 0:
- sections[SECTION_UNPACKER].data.extend(
+ if len(section_lzss_unpack.data) == 0:
+ section_lzss_unpack.data.extend(
lzss_unpack_rev
)
addr3 -= 5 + 1
- sections[SECTION_LOADER].data.extend(
+ section_loader.data.extend(
[
0xa9, 0x00, # lda #<addr3
0xa0, 0x00, # ldy #>addr3
0x20, 0x00, 0x00, # jsr lzss_unpack_rev
][::-1]
)
- sections[SECTION_LOADER].fixups.extend(
+ section_loader.fixups.extend(
[
(
FIXUP_TYPE_LO_BYTE,
- 1 - len(sections[SECTION_LOADER].data),
- SECTION_PAYLOAD,
+ 1 - len(section_loader.data),
+ section_payload,
addr3
),
(
FIXUP_TYPE_HI_BYTE,
- 3 - len(sections[SECTION_LOADER].data),
- SECTION_PAYLOAD,
+ 3 - len(section_loader.data),
+ section_payload,
addr3
),
(
FIXUP_TYPE_WORD,
- 5 - len(sections[SECTION_LOADER].data),
- SECTION_UNPACKER,
+ 5 - len(section_loader.data),
+ section_lzss_unpack,
0
),
]
# prologue
-sections[SECTION_LOADER].data.extend(
+section_loader.data.extend(
[
0xd8, # cld
0xa2, 0xff, # ldx #0xff
0x9a, # txs
][::-1]
)
-sections[SECTION_LOADER].data = sections[SECTION_LOADER].data[::-1]
+section_loader.data = section_loader.data[::-1]
# relocate
end_addr = load_addr
-for i in range(N_SECTIONS):
- sections[i].load_addr = end_addr
- end_addr += len(sections[i].data)
+for section in sections:
+ section.load_addr = end_addr
+ end_addr += len(section.data)
load_size = end_addr - load_addr
for report_type, addr0, addr1, addr2, addr3 in report:
if report_type == REPORT_TYPE_DIRECT_POKE:
print(f'[0x{addr0:04x}, 0x{addr1:04x})')
else:
- addr2 += sections[SECTION_PAYLOAD].load_addr
- addr3 += sections[SECTION_PAYLOAD].load_addr
+ addr2 += section_payload.load_addr
+ addr3 += section_payload.load_addr
print(
f'[0x{addr0:04x}, 0x{addr1:04x}) -> [0x{addr2:04x}, 0x{addr3:04x})' + (
f'{100. * (addr3 - addr2) / (addr1 - addr0):6.1f}%'
)
bin = []
-for i in range(N_SECTIONS):
- for fixup_type, fixup_addr, section, addr in sections[i].fixups:
- addr += sections[section].load_addr
+for section in sections:
+ for fixup_type, fixup_addr, target_section, target_addr in section.fixups:
+ target_addr += target_section.load_addr
if fixup_type == FIXUP_TYPE_LO_BYTE:
- assert sections[i].data[fixup_addr] == 0
- sections[i].data[fixup_addr] = addr & 0xff
+ assert section.data[fixup_addr] == 0
+ section.data[fixup_addr] = target_addr & 0xff
elif fixup_type == FIXUP_TYPE_HI_BYTE:
- assert sections[i].data[fixup_addr] == 0
- sections[i].data[fixup_addr] = addr >> 8
+ assert section.data[fixup_addr] == 0
+ section.data[fixup_addr] = target_addr >> 8
elif fixup_type == FIXUP_TYPE_WORD:
- assert sections[i].data[fixup_addr] == 0
- sections[i].data[fixup_addr] = addr & 0xff
- assert sections[i].data[fixup_addr + 1] == 0
- sections[i].data[fixup_addr + 1] = addr >> 8
+ assert section.data[fixup_addr] == 0
+ section.data[fixup_addr] = target_addr & 0xff
+ assert section.data[fixup_addr + 1] == 0
+ section.data[fixup_addr + 1] = target_addr >> 8
else:
assert False
- bin.extend(sections[i].data)
+ bin.extend(section.data)
hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
with open(out_a2bin, 'wb') as fout: