Created
September 24, 2023 16:31
-
-
Save cogwheel/5e9af99aa0a40bfd9fe136478de91f4d to your computer and use it in GitHub Desktop.
Read .map file from mos-nes-mmc3 target and summarize RAM/ROM usage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import sys | |
TOTAL_SYSTEM_RAM = 0x800 # 2kb built into the NES | |
TOTAL_WORK_RAM = 0x2000 # 8kb of PRG RAM thanks to the mapper TODO: banking? | |
TOTAL_PRG_BANKS = 64 | |
PRG_BANK_SIZE = 0x2000 # 8KiB banks | |
TOTAL_CHR_BANKS = 256 | |
CHR_BANK_SIZE = 0x0400 # 1KiB banks | |
ZP_SIZE = 0x100 | |
ZP_RESERVED = 0x20 # Compiler uses 32 bytes (customizable) for registers. | |
SRAM_SIZE = TOTAL_SYSTEM_RAM - ZP_SIZE | |
SWSTACK_SIZE = 0x100 | |
WRAM_SIZE = TOTAL_WORK_RAM - SWSTACK_SIZE | |
PRG_BANKS_RESERVED = 2 # Fixed banks from 0xC000-0xFFFF | |
AVAILABLE_PRG_BANKS = TOTAL_PRG_BANKS - PRG_BANKS_RESERVED | |
with open(sys.argv[1], "r") as file: | |
zp_left = ZP_SIZE - ZP_RESERVED | |
sram_left = SRAM_SIZE | |
wram_left = WRAM_SIZE | |
fixed_prg_left = PRG_BANK_SIZE * PRG_BANKS_RESERVED | |
prg_rom_left = [PRG_BANK_SIZE] * AVAILABLE_PRG_BANKS | |
used_prg_banks = set() | |
chr_banks_left = TOTAL_CHR_BANKS | |
for line in file: | |
try: | |
vma, lma, size, _, section = line.split() | |
vma = int(vma, 16) | |
lma = int(lma, 16) | |
size = int(size, 16) | |
section = re.match(r"^(\.[\w.]+)$", section).groups()[0] | |
except: | |
continue | |
# TODO: use memory regions and the values of vma/lma instead of | |
# hard-coded string names/patterns | |
if section.startswith(".debug"): | |
continue | |
if section in [".comment", ".symtab", ".shstrtab", ".strtab"]: | |
continue | |
if section.startswith(".zp"): | |
zp_left -= size | |
if (vma != lma): | |
# Data-like segment; initializer value is in ROM, but program | |
# accesses it through RAM | |
fixed_prg_left -= size | |
elif section in [".bss", ".noinit"]: | |
wram_left -= size | |
elif section == ".data": | |
wram_left -= size | |
fixed_prg_left -= size | |
elif section in [".text", ".rodata", ".dpcm", ".reset", ".vectors"]: | |
fixed_prg_left -= size | |
elif segment == ".ram": | |
sram_left -= size | |
elif section == ".chr_rom": | |
assert(size % CHR_BANK_SIZE == 0) | |
chr_banks_left -= size // CHR_BANK_SIZE | |
elif match := re.match(r".prg_rom_(\d*)", section): | |
index = int(match.groups()[0]) | |
prg_rom_left[index] -= size | |
used_prg_banks.add(index) | |
else: | |
raise ValueError(f"Unknown section: {section}") | |
remaining_prg_banks = AVAILABLE_PRG_BANKS - len(used_prg_banks) | |
print(f""" | |
Remaining RAM bytes: | |
ZP: {zp_left:5d} | |
SRAM: {sram_left:5d} | |
WRAM: {wram_left:5d} | |
Remaining PRG ROM bytes: | |
FIXED: {fixed_prg_left:5d}""") | |
if used_prg_banks: | |
for i in range(0, max(used_prg_banks) + 1): | |
if i in used_prg_banks: | |
print(f"""\ | |
PRG{i:02d}: {prg_rom_left[i]:5d}""") | |
else: | |
print(f"""\ | |
PRG{i:02d}: {PRG_BANK_SIZE:5d} (Unused)""") | |
print(f""" | |
Available ROM banks: | |
PRG: {remaining_prg_banks:5d} ({round(remaining_prg_banks * PRG_BANK_SIZE / 1024)} KiB) | |
CHR: {chr_banks_left:5d} ({chr_banks_left} KiB)""") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment