mirror of
				https://github.com/coop-deluxe/sm64coopdx.git
				synced 2025-10-30 08:01:01 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			76 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env python
 | |
| 
 | |
| import argparse
 | |
| import re
 | |
| import sys
 | |
| 
 | |
| def read_file(filepath):
 | |
|     with open(filepath) as f:
 | |
|         lines = f.readlines()
 | |
|         split_lines = [re.split(r'[ ,]+', l.strip().replace('$', '')) for l in lines]
 | |
|         return split_lines
 | |
| 
 | |
| # jumps and branches with named targets
 | |
| jumps = ['jal', 'j']
 | |
| branches = ['beq', 'bgez', 'bgtz', 'blez', 'bltz', 'bne']
 | |
| jump_branches = jumps + branches
 | |
| # jumps and branches with delay slots
 | |
| has_delay_slot = jump_branches + ['jr']
 | |
| 
 | |
| def decode_references(instructions):
 | |
|     refs = []
 | |
|     for ins in instructions:
 | |
|         if ins[3] in jump_branches:
 | |
|             target = int(ins[-1], 0)
 | |
|             if target not in refs:
 | |
|                 refs.append(target)
 | |
|     return refs
 | |
| 
 | |
| def reassemble(args, instructions, refs):
 | |
|     print('.rsp')
 | |
|     print('\n.create DATA_FILE, 0x%04X' % 0x0000)
 | |
|     print('\n.close // DATA_FILE\n')
 | |
|     print('.create CODE_FILE, 0x%08X\n' % args.base)
 | |
|     delay_slot = False
 | |
|     for ins in instructions:
 | |
|         addr = int(ins[0], 0)
 | |
|         if (addr & 0xFFFF) in refs:
 | |
|             print('%s_%08x:' % (args.name, addr))
 | |
|         sys.stdout.write(' ' * args.indent)
 | |
|         if delay_slot:
 | |
|             sys.stdout.write(' ')
 | |
|             delay_slot = False
 | |
|         if ins[3] in jumps:
 | |
|             target = int(ins[-1], 0) | (args.base & 0xFFFF0000)
 | |
|             ins[-1] = '%s_%08x' % (args.name, target)
 | |
|         elif ins[3] in branches:
 | |
|             if ins[3][-1] =='z' and ins[5] == 'zero':
 | |
|                 del ins[5] # remove 'zero' operand from branch
 | |
|             target = (int(ins[-1], 0) & 0x1FFF) + (args.base & 0xFFFF0000)
 | |
|             ins[-1] = '%s_%08x' % (args.name, target)
 | |
|         elif ins[3] == 'vsar': # fixup last operand of vsar
 | |
|             reg_map = {'ACC_H': 0, 'ACC_M': 1, 'ACC_L': 2}
 | |
|             reg = ins[4].split(r'[')[0]
 | |
|             num = reg_map[ins[-1]]
 | |
|             ins[-1] = '%s[%d]' % (reg, num)
 | |
|         if ins[3] in has_delay_slot:
 | |
|             delay_slot = True
 | |
|         if len(ins) > 4: # with args
 | |
|             print('%-5s %s' % (ins[3], ', '.join(ins[4:])))
 | |
|         else:
 | |
|             print('%s' % ins[3])
 | |
|     print('\n.close // CODE_FILE')
 | |
| 
 | |
| def main():
 | |
|     parser = argparse.ArgumentParser()
 | |
|     parser.add_argument('input_file', help="input assembly file generated from `rasm2 -D -e -a rsp -B -o 0x04001000 -f`")
 | |
|     parser.add_argument('-b', type=int, help="base address of file", dest='base', default=0x04001000)
 | |
|     parser.add_argument('-i', type=int, help="amount of indentation", dest='indent', default=4)
 | |
|     parser.add_argument('-n', help="name to prefex labels with", dest='name', default='f3d')
 | |
|     args = parser.parse_args()
 | |
| 
 | |
|     lines = read_file(args.input_file)
 | |
|     refs = decode_references(lines)
 | |
|     reassemble(args, lines, refs)
 | |
| 
 | |
| main()
 | 
