mirror of https://github.com/zeldaret/oot.git
				
				
				
			
		
			
				
	
	
		
			112 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
| #!/usr/bin/python3
 | |
| 
 | |
| import os
 | |
| import sys
 | |
| import struct
 | |
| import argparse
 | |
| import re
 | |
| from overlayhelpers.filemap import GetFromVRam
 | |
| 
 | |
| ICHAIN_MACROS = [
 | |
|     'ICHAIN_U8',
 | |
|     'ICHAIN_S8',
 | |
|     'ICHAIN_U16',
 | |
|     'ICHAIN_S16',
 | |
|     'ICHAIN_U32',
 | |
|     'ICHAIN_S32',
 | |
|     'ICHAIN_F32',
 | |
|     'ICHAIN_F32_DIV1000',
 | |
|     'ICHAIN_VEC3F',
 | |
|     'ICHAIN_VEC3F_DIV1000',
 | |
|     'ICHAIN_VEC3S',
 | |
| ]
 | |
| 
 | |
| Z64_ACTOR_PATH = "../include/z64actor.h"
 | |
| 
 | |
| def get_rom_address(offset):
 | |
| 
 | |
|     if offset.startswith("D_"):
 | |
|         offset = offset[2:]
 | |
| 
 | |
|     offset = int(offset, 16)
 | |
| 
 | |
|     if offset >= 0x80000000:
 | |
|         result = GetFromVRam(offset)
 | |
|         offset = result.vrom.start + result.offset
 | |
| 
 | |
|     return hex(offset)
 | |
| 
 | |
| def get_actor_var_names():
 | |
|     in_actor = False
 | |
|     actor_vars = {}
 | |
|     with open(os.path.dirname(os.path.realpath(__file__)) + "/" + Z64_ACTOR_PATH) as actor_h:
 | |
|         for line in actor_h:
 | |
|             if in_actor:
 | |
|                 if "}" in line:
 | |
|                     # Reached the end of the actor struct so break out
 | |
|                     break
 | |
| 
 | |
|                 # Parse out the memory address (from the comment) and the variable name
 | |
|                 regex = r'.*\/\* (.*) \*\/\s+(struct)?\s*.+\s+(.+);.*'
 | |
|                 actor_var_info = re.match(regex, line)
 | |
| 
 | |
|                 if actor_var_info:
 | |
|                     # Strip off the 0x0* part and store it
 | |
|                     new_var_index = re.sub('0x0*', '', actor_var_info[1])
 | |
|                     actor_vars[new_var_index] = actor_var_info[3]
 | |
| 
 | |
|             elif "typedef struct Actor {" in line:
 | |
|                 # Found the Actor struct
 | |
|                 in_actor = True
 | |
|     return actor_vars
 | |
| 
 | |
| def main():
 | |
|     parser = argparse.ArgumentParser(description='Decompiles an InitChain')
 | |
|     parser.add_argument('filename', help='ROM file path')
 | |
|     parser.add_argument('offset', help='ROM offset or symbol of an InitChain')
 | |
|     parser.add_argument('--names', action="store_true", help='Retrieve variable names from the actor struct')
 | |
|     args = parser.parse_args()
 | |
| 
 | |
|     # Get the ROM address, if the offset is already a ROM address it will just be returned.
 | |
|     args.offset = get_rom_address(args.offset)
 | |
| 
 | |
|     romOff = int(args.offset, 16)
 | |
| 
 | |
|     try:
 | |
|         with open(args.filename, 'rb') as f:
 | |
|             romData = f.read()
 | |
|     except IOError:
 | |
|         print('failed to read file ' + args.filename)
 | |
|         sys.exit(1)
 | |
| 
 | |
|     print ('static InitChainEntry sInitChain[] = {')
 | |
| 
 | |
|     if args.names:
 | |
|         actor_variable_names = get_actor_var_names()
 | |
| 
 | |
|     while True:
 | |
|         entry = struct.unpack('>I', romData[romOff:romOff+4])[0]
 | |
|         romOff += 4
 | |
| 
 | |
|         cont = entry >> 31
 | |
|         t = (entry >> 27) & 0xF
 | |
|         offset = ((entry) >> 16) & 0x7FF
 | |
|         value = (entry) & 0xFFFF
 | |
|         if value >= 0x8000 and not ICHAIN_MACROS[t].startswith('ICHAIN_U'):
 | |
|             value -= 0x10000
 | |
| 
 | |
|         var_name = '{0:X}'.format(offset)
 | |
| 
 | |
|         if args.names and var_name in actor_variable_names:
 | |
|             var_name = actor_variable_names[var_name]
 | |
|         else:
 | |
|             var_name = "unk_" + var_name
 | |
| 
 | |
|         print('    {0}({1}, {2}, {3}),'.format(ICHAIN_MACROS[t], var_name, value, ('ICHAIN_CONTINUE' if cont == 1 else 'ICHAIN_STOP')))
 | |
|         if cont == 0:
 | |
|             break
 | |
|     print ('};')
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 |