dougeff wrote:
Sometimes with a CDL file from FCEUX (made by playing the game with CDL logger turned 'on')
I've recently tried disassembling an MMC1 game (Maniac Mansion) this way and found the only way I could get the CDL to be of use throughout the whole rom was if I split up the NES and CDL file into 32kb chunks that I ran through disasm6 one pair at a time. Using a CDL file from a complete playthrough this way gave me much better results than not using any CDL at all or just the whole CDL and NES file in one go.
I wrote some python scripts and BAT files to help with the splitting of the NES and CDL files, as well as one script that turns all registers within $0000-$7FFF into constants at the top of any ASM file passed to it.
disasm.bat
Code:
cd "REPLACE THIS WITH THE PATH TO ALL THE FILES"
python split_file.py "Maniac Mansion (Sweden).nes"
python split_file.py "Maniac Mansion (Sweden).cdl"
disasm6.exe "Maniac Mansion (Sweden)_0.nes" -t maniac0.asm -cdl "Maniac Mansion (Sweden)_0.cdl" -r
disasm6.exe "Maniac Mansion (Sweden)_1.nes" -t maniac1.asm -cdl "Maniac Mansion (Sweden)_1.cdl" -r
disasm6.exe "Maniac Mansion (Sweden)_2.nes" -t maniac2.asm -cdl "Maniac Mansion (Sweden)_2.cdl" -r
disasm6.exe "Maniac Mansion (Sweden)_3.nes" -t maniac3.asm -cdl "Maniac Mansion (Sweden)_3.cdl" -r
disasm6.exe "Maniac Mansion (Sweden)_4.nes" -t maniac4.asm -cdl "Maniac Mansion (Sweden)_4.cdl" -r
disasm6.exe "Maniac Mansion (Sweden)_5.nes" -t maniac5.asm -cdl "Maniac Mansion (Sweden)_5.cdl" -r
disasm6.exe "Maniac Mansion (Sweden)_6.nes" -t maniac6.asm -cdl "Maniac Mansion (Sweden)_6.cdl" -r
disasm6.exe "Maniac Mansion (Sweden)_7.nes" -t maniac7.asm -cdl "Maniac Mansion (Sweden)_7.cdl" -r
python maniac.py maniac0.asm
python maniac.py maniac1.asm
python maniac.py maniac2.asm
python maniac.py maniac3.asm
python maniac.py maniac4.asm
python maniac.py maniac5.asm
python maniac.py maniac6.asm
python maniac.py maniac7.asm
make.bat
split_file.py
Code:
import re
import sys
file = sys.argv[1]
file_suffix_pattern = r"(\.[a-zA-Z0-9]*)"
file_suffix = re.findall(file_suffix_pattern, file)
CHUNK_SIZE = 32768
arg_len = len(sys.argv)
if arg_len > 2:
CHUNK_SIZE = sys.argv[2]
file_index = 0
with open(file, "rb") as f:
# is there a header?
header = f.read(16)
if not header.decode('ascii').startswith("NES"):
f.seek(0)
header = None
print("No header found")
chunk = f.read(CHUNK_SIZE)
while chunk:
new_file = re.sub(file_suffix_pattern, "_" + str(file_index) + r"\1", file)
print(new_file)
with open(new_file, "wb") as chunk_file:
if file_index == 0:
if not header == None:
chunk_file.write(header)
chunk_file.write(chunk)
#print(chunk)
file_index += 1
chunk = f.read(CHUNK_SIZE)
maniac.py (replaces all register reads/writes within $0000-$7FFF with constants)
Code:
import re
import sys
file = sys.argv[1]
constant_prefix = "__"
pattern = re.compile("([a-z]{3} \({0,1})\$([0-9|a-z]{2,4})")
replace_pattern = r"\1" + constant_prefix + r"\2"
variables = []
output_lines = []
f = open(file, "r")
for line in f:
matches = re.findall(pattern, line)
for match in matches:
if match[1] not in variables:
variables.append(match[1])
# replace match in line with future constant name
line = re.sub(pattern, replace_pattern, line)
output_lines.append(line)
variables = sorted(variables)
temp1 = []
for match in variables:
if len(match) == 2:
temp1.append(match)
for match in variables:
if len(match) == 4:
temp1.append(match)
constants = []
for match in temp1:
constants.append(constant_prefix + match + " = $" + match)
for c in constants:
print(c)
print("Unique variables found: " + str(len(temp1)))
with open(file, "w") as f:
f.write(";-------------------------------------------------------------------------------\n")
f.write("; Constants\n")
f.write(";-------------------------------------------------------------------------------\n")
for x in constants:
f.write(x + "\n")
f.write("\n")
for item in output_lines:
f.write(item)
make.bat
Code:
cd ""REPLACE THIS WITH THE PATH TO ALL THE FILES"
asm6.exe maniac0.asm temp0.bin
asm6.exe maniac1.asm temp1.bin
asm6.exe maniac2.asm temp2.bin
asm6.exe maniac3.asm temp3.bin
asm6.exe maniac4.asm temp4.bin
asm6.exe maniac5.asm temp5.bin
asm6.exe maniac6.asm temp6.bin
asm6.exe maniac7.asm temp7.bin
copy /b temp0.bin+temp1.bin+temp2.bin+temp3.bin+temp4.bin+temp5.bin+temp6.bin+temp7.bin final.nes
fceux.exe final.nes
So far I've only tried this with the swedish version of maniac mansion and apart from the last asm file needing some manual touch up it seems to output assembly that's been categorized by code/data by the CDL throughout the whole NES file. I could not find any info online as to how to make disasm6 use anything past the first 32kb of a CDL so I thought this technique might be good to share.
If you try this technique with the swedish version (might work with others) of maniac mansion and the CDL file i've attached, it will not recompile completely on it's own due to some data being disassembled as code in bank 14 (i think), but with a more complete CDL or some manual fixup it should reassemble into a carbon copy.
This turned out to be a long reply. Basically what I'm trying to get across is that when disassembling with disasm6, CDL files are invaluable. And if you want to use them to disassemble a game with PRG rom larger than 32kb you have to do it in chunks.