Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ## BizHawk CDL to IDC converter - Sega Genesis/Megadrive
- ## By : ehw
- import sys
- ##Variables:
- inputfile = ''
- outputfile = ''
- cdl_ROMseg_addr = 0x2E ##might not be the same every time, and for future versions
- cdl_ROMseg_endbyte = '\x07\x36\x38\x4B' ###.68K, or, the beginning of the 68K RAM segment.
- ## MAIN CODE START
- def main(argv):
- print("BizHawk CDL to IDC converter - Sega Genesis/Megadrive\n")
- print("By : ehw\n")
- print("\t Usage: md_cdl2idc.py input.cdl output.idc\n")
- ##2.) Check and make sure the user specified both input/output files
- if(len(sys.argv) < 2):
- print("\t Usage: md_cdl2idc.py input.cdl output.idc\n")
- sys.exit(2)
- ##3.) Once the check has passed, get and then parse the cdl file
- inputfile = open(sys.argv[1], 'rb')
- outputfile = open(sys.argv[2], 'w')
- init_idc(outputfile)
- parse_cdl(inputfile, outputfile)
- print("Program End")
- inputfile.close();
- outputfile.close();
- sys.exit(2)
- ## MAIN CODE END
- def parse_cdl(inputfile, outputfile):
- ##Flags:
- Exec68k_flag = '\x01'
- Data68k_flag = '\x04'
- ExecZ80First_flag = '\x08'
- ExecZ80Operand_flag = '\x10'
- DataZ80_flag = '\x20'
- DMASource_flag = '\x40' ## Should be useful for identifying the origin of graphics data on the cart ROM.
- Exec68k_Count = 0
- Data68k_Count = 0
- ExecZ80First_Count = 0
- ExecZ80Operand_Count = 0
- DataZ80_Count = 0
- DMASource_Count = 0
- Unknown_Count = 0
- ##1.) Get the ROM segment size from the CDL file
- rom_size = get_romseg_size(inputfile, cdl_ROMseg_endbyte, cdl_ROMseg_addr)
- ##2.) Set the offset to the ROM segment
- print("Conversion Process Start!")
- print("Parsing ROM segment at {:x}".format(cdl_ROMseg_addr))
- inputfile.seek(cdl_ROMseg_addr)
- ##3.) Scan through the cdl file one byte at a time,
- currentAddress = cdl_ROMseg_addr
- while(currentAddress != cdl_ROMseg_addr+rom_size):
- if(inputfile.read(1) == Exec68k_flag):
- outputfile.write("MakeCode(0x{:x});\n".format(currentAddress-cdl_ROMseg_addr))
- Exec68k_Count += 1
- if(inputfile.read(1) == Data68k_flag):
- outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
- Data68k_Count += 1
- if(inputfile.read(1) == ExecZ80First_flag):
- outputfile.write('MakeComm(0x{:x}, "Z80First Code");\n'.format(currentAddress-cdl_ROMseg_addr))
- outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
- ExecZ80First_Count += 1
- if(inputfile.read(1) == ExecZ80Operand_flag):
- outputfile.write('MakeComm(0x{:x}, "Z80Operand Code");\n'.format(currentAddress-cdl_ROMseg_addr))
- outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
- ExecZ80Operand_Count += 1
- if(inputfile.read(1) == DataZ80_flag):
- outputfile.write('MakeComm(0x{:x}, "Z80 Data");\n'.format(currentAddress-cdl_ROMseg_addr))
- outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
- DataZ80_Count += 1
- if(inputfile.read(1) == DMASource_flag):
- outputfile.write('MakeComm(0x{:x}, "DMA (could be graphics)");\n'.format(currentAddress-cdl_ROMseg_addr))
- outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
- DMASource_Count += 1
- if(inputfile.read(1) == '\x00'):
- Unknown_Count += 1
- currentAddress += 1
- inputfile.seek(currentAddress)
- print("ROM segment parsing complete!")
- ##DO 68k RAM STUFF HERE
- cdl_RAMseg_addr = currentAddress + 12 ##since currentAddress is now at the end of the ROM segment, we can just add 12 to get to the next RAM segment since the segment header size is fixed
- ram68k_size = 65536 ##ram is always the same size no matter what (64kb)
- ##Set the offset in the filestream to the beginning of the RAM segment
- inputfile.seek(cdl_RAMseg_addr)
- currentAddress = cdl_RAMseg_addr
- print("Parsing 68K RAM segment at {:x}".format(cdl_RAMseg_addr))
- ##Note: I can probably truncate this to make it more compact but the write out to
- ## the idc file is going to be different for RAM depending on the usage of the game
- ## so more different flags might be set in ram in some games than others. Also,
- ## the write out to the idc file needs to add an additional string for RAM space
- ##
- ##Note 2: The RAM segment in IDA Pro might need to be created with the proper base
- ## address before this script is run.
- while(currentAddress != cdl_RAMseg_addr+ram68k_size):
- if(inputfile.read(1) == Exec68k_flag):
- outputfile.write("MakeCode(0xFF{0:0{1}x});\n".format(currentAddress-cdl_RAMseg_addr,4))
- Exec68k_Count += 1
- if(inputfile.read(1) == Data68k_flag):
- outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
- Data68k_Count += 1
- if(inputfile.read(1) == ExecZ80First_flag):
- outputfile.write('MakeComm(0xFF{0:0{1}x}, "Z80First Code");\n'.format(currentAddress-cdl_RAMseg_addr,4))
- outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
- ExecZ80First_Count += 1
- if(inputfile.read(1) == ExecZ80Operand_flag):
- outputfile.write('MakeComm(0xFF{0:0{1}x}, "Z80Operand Code");\n'.format(currentAddress-cdl_RAMseg_addr,4))
- outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
- ExecZ80Operand_Count += 1
- if(inputfile.read(1) == DataZ80_flag):
- outputfile.write('MakeComm(0xFF{0:0{1}x}, "Z80 Data");\n'.format(currentAddress-cdl_RAMseg_addr,4))
- outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
- DataZ80_Count += 1
- if(inputfile.read(1) == DMASource_flag):
- outputfile.write('MakeComm(0xFF{0:0{1}x}, "DMA (could be graphics)");\n'.format(currentAddress-cdl_RAMseg_addr,4))
- outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
- DMASource_Count += 1
- if(inputfile.read(1) == '\x00'):
- Unknown_Count += 1
- currentAddress += 1
- inputfile.seek(currentAddress)
- print("68K RAM segment parsing complete!")
- ##DO Z80 RAM STUFF HERE
- cdl_Z80RAMseg_addr = currentAddress + 12 ##same thing as before
- ramz80_size = 8192 ##this isnt really the total size of z80 ram, but its usually what games can access
- ##Set the offset in the filestream to the beginning of the Z80 RAM segment
- inputfile.seek(cdl_Z80RAMseg_addr)
- currentAddress = cdl_Z80RAMseg_addr
- print("Parsing Z80 RAM segment at {:x}".format(cdl_Z80RAMseg_addr))
- ##NOTE: Same thing as before, but just doing all the checking just to be sure.
- while(currentAddress != cdl_Z80RAMseg_addr+ram68k_size):
- if(inputfile.read(1) == Exec68k_flag):
- outputfile.write("MakeCode(0x00A0{0:0{1}x});\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
- Exec68k_Count += 1
- if(inputfile.read(1) == Data68k_flag):
- outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
- Data68k_Count += 1
- if(inputfile.read(1) == ExecZ80First_flag):
- outputfile.write('MakeComm(0x00A0{0:0{1}x}, "Z80First Code");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
- outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
- ExecZ80First_Count += 1
- if(inputfile.read(1) == ExecZ80Operand_flag):
- outputfile.write('MakeComm(0x00A0{0:0{1}x}, "Z80Operand Code");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
- outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
- ExecZ80Operand_Count += 1
- if(inputfile.read(1) == DataZ80_flag):
- outputfile.write('MakeComm(0x00A0{0:0{1}x}, "Z80 Data");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
- outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
- DataZ80_Count += 1
- if(inputfile.read(1) == DMASource_flag):
- outputfile.write('MakeComm(0x00A0{0:0{1}x}, "DMA (could be graphics)");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
- outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
- DMASource_Count += 1
- if(inputfile.read(1) == '\x00'):
- Unknown_Count += 1
- currentAddress += 1
- inputfile.seek(currentAddress)
- print("Z80 RAM segment parsing complete!")
- outputfile.write("}") ##close the idc script, we're done
- print("Conversion completed!\n")
- print("Identified Data:\n")
- print("\t Exec68k : {:x} bytes".format(Exec68k_Count))
- print("\t Data68k : {:x} bytes".format(Data68k_Count))
- print("\t ExecZ80First : {:x} bytes".format(ExecZ80First_Count))
- print("\t ExecZ80Operand : {:x} bytes".format(ExecZ80Operand_Count))
- print("\t DataZ80 : {:x} bytes".format(DataZ80_Count))
- print("\t DMASource : {:x} bytes".format(DMASource_Count))
- print("\t Unknown : {:x} bytes".format(Unknown_Count))
- return
- def get_romseg_size(inputfile, cdl_ROMseg_endbyte, cdl_ROMseg_addr):
- cdl_ROMseg_size = 0x00
- currentAddress = cdl_ROMseg_addr
- inputfile.seek(currentAddress)
- print("...Calculating ROM Segment size...Please Wait...\n")
- while(inputfile.read(4) != cdl_ROMseg_endbyte):
- cdl_ROMseg_size += 1 #add 1 to the total size
- currentAddress += 1 #move to the next byte
- inputfile.seek(currentAddress) #set as current address, necessary?
- print('ROM Size calculated! The size is {:x} bytes\n'.format(cdl_ROMseg_size))
- return cdl_ROMseg_size
- def init_idc(outputfile):
- outputfile.write("#include <idc.idc>\n")
- outputfile.write("static main() {\n")
- ##create RAM segments just in case they havent been made by the user? might take this out
- outputfile.write('SegRename(0x000000, "ROM");\n')
- outputfile.write('SegCreate(0xA00000, 0xA0FFFF,0,0,0,2);\n')
- outputfile.write('SegRename(0xA00000, "Z80");\n')
- outputfile.write('SegCreate(0xA10000, 0xA10FFF,0,0,0,2);\n')
- outputfile.write('SegRename(0xA10000, "IO");\n')
- outputfile.write('SegCreate(0xA11000, 0xA11FFF,0,0,0,2);\n')
- outputfile.write('SegRename(0xA11000, "Control");\n')
- outputfile.write('SegCreate(0xC00000, 0xDFFFFF,0,0,0,2);\n')
- outputfile.write('SegRename(0xC00000, "VDP");\n')
- outputfile.write('SegCreate(0xFF0000, 0xFFFFFF,0,0,0,2);\n')
- outputfile.write('SegRename(0xFF0000, "RAM");\n')
- return
- if __name__ == "__main__":
- main(sys.argv[1:])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement