Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2016
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.10 KB | None | 0 0
  1. ## BizHawk CDL to IDC converter - Sega Genesis/Megadrive
  2. ## By : ehw
  3.  
  4. import sys
  5.  
  6. ##Variables:
  7.    
  8. inputfile = ''
  9. outputfile = ''
  10.  
  11. cdl_ROMseg_addr = 0x2E ##might not be the same every time, and for future versions
  12. cdl_ROMseg_endbyte = '\x07\x36\x38\x4B' ###.68K, or, the beginning of the 68K RAM segment.
  13.  
  14. ## MAIN CODE START
  15.  
  16. def main(argv):
  17.     print("BizHawk CDL to IDC converter - Sega Genesis/Megadrive\n")
  18.     print("By : ehw\n")
  19.     print("\t Usage: md_cdl2idc.py input.cdl output.idc\n")
  20.  
  21. ##2.) Check and make sure the user specified both input/output files
  22.     if(len(sys.argv) < 2):
  23.         print("\t Usage: md_cdl2idc.py input.cdl output.idc\n")
  24.         sys.exit(2)
  25. ##3.) Once the check has passed, get and then parse the cdl file
  26.     inputfile = open(sys.argv[1], 'rb')
  27.     outputfile = open(sys.argv[2], 'w')
  28.     init_idc(outputfile)
  29.     parse_cdl(inputfile, outputfile)
  30.    
  31.     print("Program End")
  32.     inputfile.close();
  33.     outputfile.close();
  34.     sys.exit(2)
  35.    
  36. ## MAIN CODE END
  37. def parse_cdl(inputfile, outputfile):
  38.     ##Flags:
  39.     Exec68k_flag = '\x01'
  40.     Data68k_flag = '\x04'
  41.     ExecZ80First_flag = '\x08'
  42.     ExecZ80Operand_flag = '\x10'
  43.     DataZ80_flag = '\x20'
  44.     DMASource_flag = '\x40' ## Should be useful for identifying the origin of graphics data on the cart ROM.
  45.  
  46.  
  47.     Exec68k_Count = 0
  48.     Data68k_Count = 0
  49.     ExecZ80First_Count = 0
  50.     ExecZ80Operand_Count = 0
  51.     DataZ80_Count = 0
  52.     DMASource_Count = 0
  53.     Unknown_Count = 0
  54.  
  55.     ##1.) Get the ROM segment size from the CDL file
  56.     rom_size = get_romseg_size(inputfile, cdl_ROMseg_endbyte, cdl_ROMseg_addr)
  57.  
  58.     ##2.) Set the offset to the ROM segment
  59.     print("Conversion Process Start!")
  60.     print("Parsing ROM segment at {:x}".format(cdl_ROMseg_addr))
  61.     inputfile.seek(cdl_ROMseg_addr)
  62.    
  63.     ##3.) Scan through the cdl file one byte at a time,
  64.     currentAddress = cdl_ROMseg_addr
  65.     while(currentAddress != cdl_ROMseg_addr+rom_size):
  66.         if(inputfile.read(1) == Exec68k_flag):
  67.             outputfile.write("MakeCode(0x{:x});\n".format(currentAddress-cdl_ROMseg_addr))
  68.             Exec68k_Count += 1
  69.         if(inputfile.read(1) == Data68k_flag):
  70.             outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
  71.             Data68k_Count += 1
  72.         if(inputfile.read(1) == ExecZ80First_flag):
  73.             outputfile.write('MakeComm(0x{:x}, "Z80First Code");\n'.format(currentAddress-cdl_ROMseg_addr))
  74.             outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
  75.             ExecZ80First_Count += 1
  76.         if(inputfile.read(1) == ExecZ80Operand_flag):
  77.             outputfile.write('MakeComm(0x{:x}, "Z80Operand Code");\n'.format(currentAddress-cdl_ROMseg_addr))
  78.             outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
  79.             ExecZ80Operand_Count += 1
  80.         if(inputfile.read(1) == DataZ80_flag):
  81.             outputfile.write('MakeComm(0x{:x}, "Z80 Data");\n'.format(currentAddress-cdl_ROMseg_addr))
  82.             outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
  83.             DataZ80_Count += 1
  84.         if(inputfile.read(1) == DMASource_flag):
  85.             outputfile.write('MakeComm(0x{:x}, "DMA (could be graphics)");\n'.format(currentAddress-cdl_ROMseg_addr))
  86.             outputfile.write("MakeData(0x{:x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_ROMseg_addr))
  87.             DMASource_Count += 1
  88.         if(inputfile.read(1) == '\x00'):
  89.             Unknown_Count += 1
  90.         currentAddress += 1
  91.         inputfile.seek(currentAddress)
  92.  
  93.     print("ROM segment parsing complete!")
  94.     ##DO 68k RAM STUFF HERE
  95.     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
  96.     ram68k_size = 65536 ##ram is always the same size no matter what (64kb)
  97.  
  98.     ##Set the offset in the filestream to the beginning of the RAM segment
  99.     inputfile.seek(cdl_RAMseg_addr)
  100.     currentAddress = cdl_RAMseg_addr
  101.     print("Parsing 68K RAM segment at {:x}".format(cdl_RAMseg_addr))
  102.     ##Note: I can probably truncate this to make it more compact but the write out to
  103.     ## the idc file is going to be different for RAM depending on the usage of the game
  104.     ## so more different flags might be set in ram in some games than others. Also,
  105.     ## the write out to the idc file needs to add an additional string for RAM space
  106.     ##
  107.     ##Note 2: The RAM segment in IDA Pro might need to be created with the proper base
  108.     ## address before this script is run.
  109.     while(currentAddress != cdl_RAMseg_addr+ram68k_size):
  110.         if(inputfile.read(1) == Exec68k_flag):
  111.             outputfile.write("MakeCode(0xFF{0:0{1}x});\n".format(currentAddress-cdl_RAMseg_addr,4))
  112.             Exec68k_Count += 1
  113.         if(inputfile.read(1) == Data68k_flag):
  114.             outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
  115.             Data68k_Count += 1
  116.         if(inputfile.read(1) == ExecZ80First_flag):
  117.             outputfile.write('MakeComm(0xFF{0:0{1}x}, "Z80First Code");\n'.format(currentAddress-cdl_RAMseg_addr,4))
  118.             outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
  119.             ExecZ80First_Count += 1
  120.         if(inputfile.read(1) == ExecZ80Operand_flag):
  121.             outputfile.write('MakeComm(0xFF{0:0{1}x}, "Z80Operand Code");\n'.format(currentAddress-cdl_RAMseg_addr,4))
  122.             outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
  123.             ExecZ80Operand_Count += 1
  124.         if(inputfile.read(1) == DataZ80_flag):
  125.             outputfile.write('MakeComm(0xFF{0:0{1}x}, "Z80 Data");\n'.format(currentAddress-cdl_RAMseg_addr,4))
  126.             outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
  127.             DataZ80_Count += 1
  128.         if(inputfile.read(1) == DMASource_flag):
  129.             outputfile.write('MakeComm(0xFF{0:0{1}x}, "DMA (could be graphics)");\n'.format(currentAddress-cdl_RAMseg_addr,4))
  130.             outputfile.write("MakeData(0xFF{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_RAMseg_addr,4))
  131.             DMASource_Count += 1
  132.         if(inputfile.read(1) == '\x00'):
  133.             Unknown_Count += 1
  134.         currentAddress += 1
  135.         inputfile.seek(currentAddress)
  136.  
  137.     print("68K RAM segment parsing complete!")
  138.  
  139.     ##DO Z80 RAM STUFF HERE
  140.     cdl_Z80RAMseg_addr = currentAddress + 12 ##same thing as before
  141.     ramz80_size = 8192 ##this isnt really the total size of z80 ram, but its usually what games can access
  142.  
  143.     ##Set the offset in the filestream to the beginning of the Z80 RAM segment
  144.     inputfile.seek(cdl_Z80RAMseg_addr)
  145.     currentAddress = cdl_Z80RAMseg_addr
  146.     print("Parsing Z80 RAM segment at {:x}".format(cdl_Z80RAMseg_addr))
  147.     ##NOTE: Same thing as before, but just doing all the checking just to be sure.
  148.     while(currentAddress != cdl_Z80RAMseg_addr+ram68k_size):
  149.         if(inputfile.read(1) == Exec68k_flag):
  150.             outputfile.write("MakeCode(0x00A0{0:0{1}x});\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
  151.             Exec68k_Count += 1
  152.         if(inputfile.read(1) == Data68k_flag):
  153.             outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
  154.             Data68k_Count += 1
  155.         if(inputfile.read(1) == ExecZ80First_flag):
  156.             outputfile.write('MakeComm(0x00A0{0:0{1}x}, "Z80First Code");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
  157.             outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
  158.             ExecZ80First_Count += 1
  159.         if(inputfile.read(1) == ExecZ80Operand_flag):
  160.             outputfile.write('MakeComm(0x00A0{0:0{1}x}, "Z80Operand Code");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
  161.             outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
  162.             ExecZ80Operand_Count += 1
  163.         if(inputfile.read(1) == DataZ80_flag):
  164.             outputfile.write('MakeComm(0x00A0{0:0{1}x}, "Z80 Data");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
  165.             outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
  166.             DataZ80_Count += 1
  167.         if(inputfile.read(1) == DMASource_flag):
  168.             outputfile.write('MakeComm(0x00A0{0:0{1}x}, "DMA (could be graphics)");\n'.format(currentAddress-cdl_Z80RAMseg_addr,4))
  169.             outputfile.write("MakeData(0x00A0{0:0{1}x}, FF_BYTE, 0x1, 0);\n".format(currentAddress-cdl_Z80RAMseg_addr,4))
  170.             DMASource_Count += 1
  171.         if(inputfile.read(1) == '\x00'):
  172.             Unknown_Count += 1
  173.         currentAddress += 1
  174.         inputfile.seek(currentAddress)
  175.  
  176.     print("Z80 RAM segment parsing complete!")
  177.  
  178.  
  179.     outputfile.write("}") ##close the idc script, we're done
  180.     print("Conversion completed!\n")
  181.     print("Identified Data:\n")
  182.     print("\t Exec68k : {:x} bytes".format(Exec68k_Count))
  183.     print("\t Data68k : {:x} bytes".format(Data68k_Count))
  184.     print("\t ExecZ80First : {:x} bytes".format(ExecZ80First_Count))
  185.     print("\t ExecZ80Operand : {:x} bytes".format(ExecZ80Operand_Count))
  186.     print("\t DataZ80 : {:x} bytes".format(DataZ80_Count))
  187.     print("\t DMASource : {:x} bytes".format(DMASource_Count))
  188.     print("\t Unknown : {:x} bytes".format(Unknown_Count))
  189.  
  190.     return
  191.  
  192. def get_romseg_size(inputfile, cdl_ROMseg_endbyte, cdl_ROMseg_addr):
  193.     cdl_ROMseg_size = 0x00
  194.  
  195.     currentAddress = cdl_ROMseg_addr
  196.     inputfile.seek(currentAddress)
  197.  
  198.     print("...Calculating ROM Segment size...Please Wait...\n")
  199.     while(inputfile.read(4) != cdl_ROMseg_endbyte):
  200.         cdl_ROMseg_size += 1 #add 1 to the total size
  201.         currentAddress += 1 #move to the next byte
  202.         inputfile.seek(currentAddress) #set as current address, necessary?
  203.  
  204.     print('ROM Size calculated! The size is {:x} bytes\n'.format(cdl_ROMseg_size))
  205.     return cdl_ROMseg_size
  206.  
  207. def init_idc(outputfile):
  208.     outputfile.write("#include <idc.idc>\n")
  209.     outputfile.write("static main() {\n")
  210.     ##create RAM segments just in case they havent been made by the user? might take this out
  211.     outputfile.write('SegRename(0x000000, "ROM");\n')
  212.     outputfile.write('SegCreate(0xA00000, 0xA0FFFF,0,0,0,2);\n')
  213.     outputfile.write('SegRename(0xA00000, "Z80");\n')
  214.     outputfile.write('SegCreate(0xA10000, 0xA10FFF,0,0,0,2);\n')
  215.     outputfile.write('SegRename(0xA10000, "IO");\n')
  216.     outputfile.write('SegCreate(0xA11000, 0xA11FFF,0,0,0,2);\n')
  217.     outputfile.write('SegRename(0xA11000, "Control");\n')
  218.     outputfile.write('SegCreate(0xC00000, 0xDFFFFF,0,0,0,2);\n')
  219.     outputfile.write('SegRename(0xC00000, "VDP");\n')
  220.     outputfile.write('SegCreate(0xFF0000, 0xFFFFFF,0,0,0,2);\n')
  221.     outputfile.write('SegRename(0xFF0000, "RAM");\n')
  222.     return
  223.  
  224. if __name__ == "__main__":
  225.     main(sys.argv[1:])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement