├── .gitignore ├── decomp ├── c │ ├── __init__.py │ ├── cpp.py │ ├── types.py │ ├── gen.py │ └── decl.py ├── cpu │ ├── __init__.py │ ├── mips │ │ ├── abi │ │ │ ├── __init__.py │ │ │ └── n32.py │ │ ├── __init__.py │ │ ├── data.py │ │ ├── insns.py │ │ └── gen.py │ ├── ida.py │ └── regs.py ├── __init__.py ├── utils.py ├── data.py └── ida.py ├── .gitattributes ├── goodies └── epanos.it ├── THANKS.md ├── idabits ├── asm_forms.pl ├── make_function_non_library_function.py ├── n32_regs.py └── fptrs.py ├── overrides.h ├── LICENSE.md ├── README.md ├── ep.h ├── epanos.py └── notes ├── decomp.txt └── ep_new.asm /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /decomp/c/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /decomp/cpu/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.py text 4 | -------------------------------------------------------------------------------- /goodies/epanos.it: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drvink/epanos/HEAD/goodies/epanos.it -------------------------------------------------------------------------------- /decomp/cpu/mips/abi/__init__.py: -------------------------------------------------------------------------------- 1 | # XXX ABI is hardcoded to N32 for now 2 | from decomp.cpu.mips.abi.n32 import * 3 | -------------------------------------------------------------------------------- /decomp/cpu/mips/__init__.py: -------------------------------------------------------------------------------- 1 | # make the package modules directly available along with the one abi function 2 | # that should be exposed 3 | from decomp.cpu.mips import data, gen, insns 4 | from decomp.cpu.mips.abi import get_abi_fn_arg_map 5 | -------------------------------------------------------------------------------- /decomp/cpu/ida.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | from idaapi import ph_get_regnames as ida_reg_list 3 | from idc import GetLongPrm, INF_PROCNAME 4 | 5 | cpu_repls = {'mipsb' : 'mips'} 6 | 7 | def ida_current_cpu_name(): 8 | '''unit -> str''' 9 | return cpu_repls[GetLongPrm(INF_PROCNAME)] 10 | 11 | def ida_current_cpu(): 12 | '''unit -> module''' 13 | cpu_name = ida_current_cpu_name() 14 | return importlib.import_module('.%s' % cpu_name, __package__) 15 | -------------------------------------------------------------------------------- /THANKS.md: -------------------------------------------------------------------------------- 1 | SPECIAL THANKS TO 2 | ================= 3 | * Neill Corlett, for providing the source to his MIPS decompiler that prompted 4 | me to write my own 5 | * Imran Hameed, for concurrent programming advice and C++11 help 6 | * dusthillguy, for allowing me to distribute epanos.it (the real reason for this 7 | project's name) with EPANOS. Please use OpenMPT to listen to it. 8 | * Everyone at Hex-Rays 9 | * The Otaru crew 10 | * Scotch 'n soda 11 | * All Capcom staff 12 | * **AND YOU...** 13 | -------------------------------------------------------------------------------- /idabits/asm_forms.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my %insn_forms; 7 | 8 | while (<>) { 9 | next if /^(?:#|$)/; 10 | chomp; 11 | s/^\t+//; 12 | my $c; 13 | my ($insn, $ops) = split /\t+/; 14 | if (!defined $ops) { 15 | $c = 0; 16 | } else { 17 | $c = split /,/, $ops; 18 | } 19 | $insn_forms{$insn}{$c} = 1; 20 | } 21 | 22 | while (my ($insn, $forms) = each %insn_forms) { 23 | print "$insn\t", join(', ', sort(keys %$forms)), "\n"; 24 | } 25 | -------------------------------------------------------------------------------- /idabits/make_function_non_library_function.py: -------------------------------------------------------------------------------- 1 | import idc 2 | 3 | def make_fn_non_library_fn(fn): 4 | ea = idc.LocByName(fn) 5 | idc.SetFunctionFlags(ea, idc.GetFunctionFlags(ea) & ~(idc.FUNC_LIB)) 6 | 7 | def main(): 8 | fnlistfile = idc.AskFile(0, '*.*', 'Choose file') 9 | if fnlistfile is None: return 10 | 11 | with open(fnlistfile, 'rU') as f: 12 | while True: 13 | fn = f.readline() 14 | if fn == '': 15 | break 16 | else: 17 | make_fn_non_library_fn(fn.strip()) 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /idabits/n32_regs.py: -------------------------------------------------------------------------------- 1 | from idaapi import * 2 | 3 | # rename IDA's O32 MIPS registers to N32 4 | 5 | registers = {'$t0':'$a4','$t1':'$a5','$t2':'$a6','$t3':'$a7'} # '$fp':'$s8' 6 | 7 | def main(): 8 | ea = get_screen_ea() 9 | seg = getseg(ea) 10 | 11 | func = get_func(seg.startEA) 12 | while func is not None and func.startEA < seg.endEA: 13 | funcea = func.startEA 14 | fname = GetFunctionName(funcea) 15 | 16 | for i in registers.iteritems(): 17 | add_regvar(func, funcea, func.endEA, i[0], i[1], '') 18 | 19 | func = get_next_func(funcea) 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /overrides.h: -------------------------------------------------------------------------------- 1 | #ifndef DEFS_H 2 | #define DEFS_H 3 | /* for irix GL/gl.h */ 4 | #define _LANGUAGE_C 5 | /* irix has a strange gettimeofday signature */ 6 | typedef struct timezone* __timezone_ptr_t; 7 | /* IDA stuff */ 8 | #define __cdecl 9 | #define __int8 uint8_t 10 | #define __int16 uint16_t 11 | #define __int32 uint32_t 12 | #define __int64 uint64_t 13 | /* override pycparser's fake headers */ 14 | typedef long* time_t; 15 | typedef unsigned uintptr_t; 16 | typedef unsigned char uint8_t; 17 | typedef signed int int32_t; 18 | typedef unsigned int uint32_t; 19 | typedef unsigned long long uint64_t; 20 | typedef signed long long int64_t; 21 | typedef unsigned int size_t; 22 | #endif 23 | -------------------------------------------------------------------------------- /idabits/fptrs.py: -------------------------------------------------------------------------------- 1 | import idaapi, idautils, idc 2 | 3 | # a script to move call target alts between databases (they are not exported 4 | # in an idc dump) 5 | 6 | def get_fptrs(): 7 | d = {} 8 | nn = idaapi.netnode('$ mips') 9 | 10 | for fn in idautils.Functions(): 11 | for ea in idautils.FuncItems(fn): 12 | if not idc.isCode(idaapi.getFlags(ea)): 13 | continue 14 | target = nn.altval(ea) - 1 15 | if target != -1: 16 | d[ea] = idc.Name(target) 17 | 18 | return d 19 | 20 | def set_fptrs(d): 21 | nn = idaapi.netnode('$ mips') 22 | 23 | for ea, target in d.iteritems(): 24 | nn.altset(ea, idc.LocByName(target) + 1) 25 | idaapi.noUsed(ea) 26 | 27 | return 28 | -------------------------------------------------------------------------------- /decomp/cpu/regs.py: -------------------------------------------------------------------------------- 1 | from decomp import utils 2 | from decomp.cpu import ida 3 | 4 | class reg_base(object): 5 | '''base class for a cpu register''' 6 | __slots__ = ['reg'] 7 | 8 | def __init__(self, reg): 9 | if type(self) is reg_base: 10 | raise utils.BugError('reg_base cannot be directly instantiated') 11 | self.reg = reg 12 | 13 | def __eq__(self, other): 14 | return type(self) is type(other) and self.reg == other.reg 15 | def __ne__(self, other): 16 | return not self.__eq__(other) 17 | 18 | def __str__(self): 19 | return '%s' % ida.ida_current_cpu().abi.reg_list[self.reg] 20 | def __repr__(self): 21 | return '%s(reg=%u)' % (self.__class__.__name__, self.reg) 22 | 23 | class fpr(reg_base): 24 | def __str__(self): 25 | return '%s' % ida.ida_current_cpu().abi.reg_list[ 26 | self.reg + ida.ida_current_cpu().abi.fpr_off] 27 | 28 | class gpr(reg_base): pass 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | EPANOS licensing 2 | ================ 3 | 4 | ### epanos.it 5 | 6 | Copyright (C) 2009 dusthillguy. All rights reserved. Distributed with 7 | permission. 8 | 9 | ### The rest 10 | 11 | Copyright (C) 2014 Mark Laws 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of 14 | this software and associated documentation files (the "Software"), to deal in 15 | the Software without restriction, including without limitation the rights to 16 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 17 | the Software, and to permit persons to whom the Software is furnished to do so, 18 | subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 25 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 26 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /decomp/__init__.py: -------------------------------------------------------------------------------- 1 | import inspect, os, sys 2 | 3 | def our_modules(): 4 | '''unit -> [str]''' 5 | def is_ours(mn): 6 | def get_file(m): 7 | try: 8 | f = inspect.getfile(m) 9 | if os.name == 'nt': 10 | # python is a piece of shit 11 | f = f.replace(r'/', r'\\') 12 | return f 13 | except TypeError: 14 | return '' 15 | 16 | if mn == '__main__' or not mn.startswith('%s.' % __package__): 17 | return False 18 | 19 | m = sys.modules[mn] 20 | f = get_file(m) 21 | if f == '': 22 | return False 23 | else: 24 | me = os.path.dirname(os.path.abspath(__file__)) 25 | mp = os.path.dirname(os.path.abspath(f)) 26 | cp = os.path.commonprefix([me, mp]) 27 | return True if cp == me else False 28 | 29 | return filter(is_ours, sys.modules.iterkeys()) 30 | 31 | def unload(): 32 | '''unit -> unit''' 33 | def del_module(arg): 34 | '''str -> unit''' 35 | try: del sys.modules[arg] 36 | except KeyError: pass 37 | 38 | for x in our_modules(): 39 | del_module(x) 40 | del_module(__package__) 41 | 42 | try: 43 | from decomp.utils import cpp_decomp_tag 44 | from decomp.c.cpp import set_cpp 45 | from decomp.c.gen import run 46 | except: 47 | unload() 48 | raise 49 | -------------------------------------------------------------------------------- /decomp/utils.py: -------------------------------------------------------------------------------- 1 | decomp_tag = 'EPANOS_' 2 | args_tag = 'ARGS' 3 | cpp_decomp_tag = '<%scpp>' % decomp_tag 4 | 5 | class BugError(Exception): pass 6 | 7 | def dictswitch(key, tbl, arg, error, error_arg): 8 | '''hashable -> dict -> a -> fn -> b -> c 9 | Look up a function in tbl given a key, returning the result of evaluating 10 | the function with arg as the argument. Calls error with error_arg if 11 | lookup fails.''' 12 | try: fn = tbl[key] 13 | except KeyError: return error(error_arg) 14 | else: return fn(arg) 15 | 16 | class type_instance(object): 17 | '''a generic comparable type that can optionally carry a value''' 18 | __slots__ = ['value'] 19 | 20 | def __init__(self, value=None): 21 | self.value = value 22 | 23 | def __eq__(self, other): 24 | return type(self) == type(other) and self.value == other.value 25 | def __not__(self, other): 26 | return not self.__eq__(other) 27 | 28 | def __repr__(self): 29 | return '%s()' % self.__class__.__name__ 30 | 31 | def zip_prefixes(shorts, longs): 32 | '''[str] -> [str] -> [(str, str)]''' 33 | # XXX this is a very inefficient algorithm if the input lists are long 34 | try: 35 | return [(max([s for s in shorts if l.startswith(s)]), 36 | l) 37 | for l in longs] 38 | except ValueError: 39 | raise BugError('lists vary in length or unable to match all items') 40 | 41 | def init(xs): 42 | itr = iter(xs) 43 | prev = itr.next() 44 | for x in itr: 45 | yield prev 46 | prev = x 47 | 48 | def items_or_default(expr, default): 49 | try: 50 | return expr() 51 | except StopIteration: 52 | return default 53 | -------------------------------------------------------------------------------- /decomp/c/cpp.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | PATH_LIST = ['cpp'] 4 | 5 | def set_cpp(cpp_path='cpp', cpp_args=''): 6 | '''Set path and arguments to cpp. 7 | cpp_path: 8 | The path to 'cpp' on your system. If no path is provided, it 9 | attempts to just execute 'cpp', so it must be in your PATH. 10 | 11 | cpp_args: 12 | Set this to the command line arguments to cpp. Be careful with 13 | quotes - it's best to pass a raw string (r'') here. For example: 14 | r'-I../utils/fake_libc_include' 15 | If several arguments are required, pass a list of strings. 16 | ''' 17 | # XXX this simplifies setting cpp params for the user, but we should really 18 | # pass it around instead of setting state 19 | global PATH_LIST 20 | PATH_LIST = [cpp_path] 21 | if isinstance(cpp_args, list): 22 | PATH_LIST += cpp_args 23 | elif cpp_args != '': 24 | PATH_LIST += [cpp_args] 25 | 26 | def make_cpp_input(tag, text): 27 | '''str -> str -> str''' 28 | return '''#line 1 "%s"\n%s\n''' % (tag, text) 29 | 30 | # modified from pycparser __init__.py, as its version doesn't take input from 31 | # a pipe 32 | def preprocess(text): 33 | '''Preprocess a file using cpp. 34 | 35 | When successful, returns the preprocessed file's contents. 36 | Errors from cpp will be printed out. 37 | ''' 38 | try: 39 | CREATE_NO_WINDOW = 0x08000000 # don't create a window on Windows 40 | # Note the use of universal_newlines to treat all newlines 41 | # as \n for Python's purpose 42 | pipe = subprocess.Popen( 43 | PATH_LIST, stdout=subprocess.PIPE, stdin=subprocess.PIPE, 44 | universal_newlines=True, creationflags=CREATE_NO_WINDOW) 45 | processed_text = pipe.communicate(text)[0] 46 | except OSError as e: 47 | raise RuntimeError("Unable to invoke 'cpp'. " + 48 | 'Make sure its path was passed correctly\n' + 49 | ('Original error: %s' % e)) 50 | 51 | return processed_text 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EPANOS 2 | ====== 3 | 4 | the **E**lectro**P*aint **A**utomatic **N**o-source **O**bject rea**S**sembler 5 | 6 | a backronym; see THANKS.md 7 | 8 | ### Who? 9 | 10 | http://github.com/drvink 11 | 12 | ### What? 13 | 14 | This is a very dumb MIPS to C static translator. Consider it a proof of 15 | concept, as it has successfully worked on at least 16 | [one non-trivial program][electroportis]. 17 | 18 | [electroportis]: https://github.com/drvink/electroportis 19 | 20 | ### When? 21 | 22 | From December 2013 to March 2014. 23 | 24 | ### Where? 25 | 26 | Tokyo. 27 | 28 | ### How? 29 | 30 | You will need a version of [IDA][] that is not yet public. Whatever 31 | version comes after 6.5 should contain all the fixes that are needed 32 | to produce the code used in ElectroPortis. 33 | 34 | [IDA]: http://www.hex-rays.com 35 | 36 | The decompiler depends on these libraries: 37 | 38 | * [pycparser](http://github.com/eliben/pycparser) 39 | * [flufl.enum](http://pythonhosted.org/flufl.enum/) 40 | * [pyc-fmtstr-parser](http://github.com/drvink/pyc-fmtstr-parser) 41 | 42 | The decompiler is not a push-button solution: some small annotations to the IDA 43 | database were needed to produce fully-working code. If you wish to use it on 44 | your own target, you will probably want to modify it to do data/bss segment 45 | extraction in a saner way. The easiest thing would probably be to just lift 46 | them out and treat them opaquely, i.e. as a char[], and then handle endianness 47 | issues accordingly. 48 | 49 | ### Why? 50 | 51 | People have wanted ElectroPaint (the real thing, not a clone) on something other 52 | than IRIX for longer than your author (of the decompiler) has been alive. 53 | *Someone* had to do it. 54 | 55 | ### Python? 56 | 57 | __ __ 58 | /..\ /| |'-. 59 | \O_/. || | | OH WOW 60 | _.' \ _ \|_|_.-' DYNAMIC TYPING 61 | .='.__/ \ | _) (_ 62 | |\_. \| |"""""""""| LET ME OUT 63 | /` .'| | | OF THIS 64 | \ \"""; | | 65 | )\ \ | |.-------.| 66 | '`_` ' " " 67 | 68 | This was an experiment. The two options that did not require writing bindings 69 | for IDA were C++ and Python. I don't think I'll use Python again for personal 70 | projects in the future, and I should have written IDA bindings to a statically 71 | typed language (other than C++). 72 | -------------------------------------------------------------------------------- /ep.h: -------------------------------------------------------------------------------- 1 | #ifndef EP_H 2 | #define EP_H 3 | #include 4 | 5 | /* structs from ep.c manual rewrite; just for reference */ 6 | 7 | struct animCmd; 8 | 9 | struct animSeq { 10 | int seqnum; 11 | char seq_enabled_XXX; 12 | char field_5; 13 | char field_6; 14 | char field_7; 15 | float framepos; 16 | float relFrame; 17 | float seq_duration_XXX; 18 | float seq_variance_XXX; 19 | struct animCmd *cmdptr; 20 | struct animCmd *cmdptr2; 21 | struct animCmd *cmdptr3; 22 | struct animSeq *next; 23 | }; 24 | 25 | struct animCmd { 26 | int acttype; 27 | int arg; 28 | float absFrame; 29 | float argf; 30 | struct animSeq *editSeq; 31 | struct animCmd *next; 32 | }; 33 | 34 | struct actAnim { 35 | char byte_off0; 36 | char byte_off1; 37 | char field_2; 38 | char field_3; 39 | float field_4; 40 | float field_8; 41 | float anim_duration_XXX; 42 | float field_10; 43 | float field_14; 44 | float field_18; 45 | float field_1C; 46 | float field_20; 47 | float field_24; 48 | }; 49 | 50 | enum epcmd_t { 51 | CMD_FRAME = 0x0, 52 | CMD_ABSFRAME = 0x1, 53 | CMD_ACTLIM1 = 0x2, 54 | CMD_ACTLIM2 = 0x3, 55 | CMD_ACTSET = 0x4, 56 | CMD_ACTRESET = 0x5, 57 | CMD_ACTRESETALL = 0x6, 58 | CMD_ACTSTOP = 0x7, 59 | CMD_ACTSTOPALL = 0x8, 60 | CMD_SEQNAME = 0x9, 61 | CMD_SEQDO = 0xA, 62 | CMD_SEQSTOP = 0xB, 63 | CMD_SEQLOOP = 0xC, 64 | CMD_SEQREPEAT = 0xD, 65 | CMD_SEQKILL = 0xE, 66 | CMD_SEQKILLALL = 0xF, 67 | CMD_DURATION = 0x65, 68 | CMD_VARIANCE = 0x66, 69 | CMD_RANDDELAY = 0x67 70 | }; 71 | 72 | typedef union EPANOS_REG { 73 | uint8_t u8; 74 | int32_t i32; 75 | uint32_t u32; 76 | int64_t i64; 77 | uint64_t u64; 78 | float s; 79 | double d; 80 | } EPANOS_REG; 81 | 82 | typedef struct EPANOS_ARGS { 83 | EPANOS_REG v0; 84 | EPANOS_REG v1; 85 | EPANOS_REG a0; 86 | EPANOS_REG a1; 87 | EPANOS_REG a2; 88 | EPANOS_REG a3; 89 | EPANOS_REG a4; 90 | EPANOS_REG a5; 91 | EPANOS_REG a6; 92 | EPANOS_REG a7; 93 | EPANOS_REG f0; 94 | EPANOS_REG f2; 95 | EPANOS_REG f12; 96 | EPANOS_REG f13; 97 | EPANOS_REG f14; 98 | EPANOS_REG f15; 99 | EPANOS_REG f16; 100 | EPANOS_REG f17; 101 | EPANOS_REG f18; 102 | EPANOS_REG f19; 103 | } EPANOS_ARGS; 104 | #endif 105 | -------------------------------------------------------------------------------- /epanos.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | import idc 3 | 4 | def ep_unload(): 5 | global decomp 6 | try: 7 | decomp.unload() 8 | del decomp 9 | except NameError: 10 | pass 11 | m = sys.modules['__main__'] 12 | try: 13 | del m.ep_unload, m.run, m.intro, m.p, m.c 14 | except AttributeError: 15 | pass 16 | 17 | try: 18 | import decomp 19 | except: 20 | ep_unload() 21 | raise 22 | 23 | def run(decompile=True): 24 | # change cpp path/args as needed 25 | pycparser_dir = r'%s\local\pycparser\utils' % os.environ['HOMEPATH'] 26 | decomp_dir = os.path.dirname(os.path.abspath(__file__)) 27 | cpppath = r'%s\cpp.exe' % pycparser_dir 28 | cppargs = [ 29 | r'-I%s' % path for path in 30 | (r'%s\fake_libc_include' % pycparser_dir, 31 | decomp_dir)] 32 | decomp.set_cpp(cpppath, cppargs) 33 | 34 | ## Desired functions (missing functions will cause a warning if encountered 35 | ## while emitting code) 36 | 37 | # XXX missing _assert because of bizarre IDA behavior (bug?); fortunately we 38 | # don't need it 39 | externs = frozenset( 40 | ['expm1', 'drand48', 'fmodf', 'srand48', 'glMatrixMode', 41 | 'glScalef', 'glPopMatrix', 'scanf', 'glColor3f', 'sscanf', 42 | 'strcmp', 'strcspn', 'malloc', 'strlen', 'free', 'strncmp', 43 | 'glVertex2f', 'printf', 'glTranslatef', 'glPushMatrix', 'glRotatef', 44 | 'gettimeofday', 'exit', 'glMultMatrixf', 'glBegin', 45 | 'glEnd', 'glViewport', 'glLoadIdentity', 'gluPerspective', 'glClear', 46 | 'floor', 'glFinish', 'time', 'glClearColor', 'glShadeModel']) 47 | text_fns = frozenset( 48 | ['value__GfN21', 'hls_to_rgb__GfN21PfN24', 'exprand__Gf', 49 | 'addToSeq__GP7animSeqP11animCommand', 'readAnimation__Gv', 50 | 'stopAnimation__Gv', 'killSeq__GP7animSeq', 51 | 'processCommand__GP11animCommand', 'tasteQueue__Gv', 52 | 'setacttargets__Gv', 'twixt__GiPff', 'foldtwixt__GiPffT3', 53 | 'drawshape__GiT1', 'drawit__Gv', 'animateacts__Gv', 54 | 'createBlankActAnim__Gv', 'createActTable__Gv', 'reshape__GiT1', 55 | 'display__Gv', 'main']) 56 | cpp_filter = ''' 57 | #include "overrides.h" 58 | #line 2 "%s" 59 | ''' % decomp.cpp_decomp_tag 60 | cpp_all = ''' 61 | #include "overrides.h" 62 | #include "ep.h" 63 | #include "GL/gl.h" 64 | #line 2 "%s" 65 | ''' % decomp.cpp_decomp_tag 66 | 67 | return decomp.run(externs, text_fns, cpp_filter, cpp_all, decompile) 68 | 69 | intro = ''' 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | ''' 79 | 80 | if __name__ == '__main__': 81 | p = idc.AskYN(1, 'Run the decompiler?') 82 | if p == -1: 83 | print 'Aborting.' 84 | elif p == 1: 85 | print intro 86 | print run(decompile=True) 87 | else: 88 | run(decompile=False) # just load it (for interactive use/testing) 89 | -------------------------------------------------------------------------------- /decomp/c/types.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | from flufl.enum import Enum 3 | from pycparser import c_ast 4 | from decomp import utils 5 | 6 | # convenience functions for ast building 7 | 8 | def array(ty, dim=None, quals=[]): 9 | return c_ast.ArrayDecl(ty, dim, quals) 10 | 11 | def ptr(ty, quals=[]): 12 | return c_ast.PtrDecl(quals, ty) 13 | 14 | def simple_typename(names, quals=[]): 15 | return c_ast.TypeDecl(None, quals, c_ast.IdentifierType(names)) 16 | 17 | def simple_cast(ty, expr, quals=[]): 18 | return c_ast.Cast(c_ast.Typename(quals, ty), expr) 19 | 20 | def cast_to_dest_reg(insn, arg): 21 | return simple_cast(slot_to_typename[insn.slots[0]], arg) 22 | 23 | def constant(typename, arg): 24 | return c_ast.Constant(typename, arg) 25 | 26 | def initlist(arg): 27 | if type(arg) is not list: 28 | raise utils.BugError('non-list passed') 29 | return c_ast.InitList(arg) 30 | 31 | def do_nop(**kw): 32 | return c_ast.EmptyStatement() 33 | 34 | def do_op(**kw): 35 | #{rd} = {rs} {subst} {rt} 36 | # XXX this is a mess 37 | lvalue = c_ast.BinaryOp(kw['subst'], kw['rs'], kw['rt']) 38 | try: 39 | cast_with = slot_to_typename[kw['result']] 40 | except KeyError: 41 | return do_assign( 42 | rt=kw['rd'], 43 | op=lvalue) 44 | else: 45 | return do_assign( 46 | rt=kw['rd'], 47 | op=simple_cast(cast_with, lvalue)) 48 | 49 | def do_jump(**kw): 50 | #goto {loc} 51 | # fmt_op returns an ID but Goto takes a bare string 52 | return c_ast.Goto(kw['loc'].name) 53 | 54 | def do_branch(**kw): 55 | # ast fragment--must fill in at least .iftrue attr 56 | return c_ast.If(c_ast.BinaryOp(kw['subst'], kw['rs'], kw['rt']), 57 | None, 58 | None) 59 | 60 | def do_assign(**kw): 61 | #{rt} = {op} 62 | return c_ast.Assignment('=', kw['rt'], kw['op']) 63 | 64 | def args_for_call(args): 65 | '''[c_ast] -> c_ast''' 66 | if args[0] is None: 67 | return None 68 | else: 69 | return c_ast.ExprList(args) 70 | 71 | def make_call(callee, ret_reg=None, args=None, for_extern=None): 72 | ret = c_ast.FuncCall(c_ast.ID(callee), args) 73 | if ret_reg is None: 74 | return ret 75 | else: 76 | if for_extern is not None: 77 | # cast the return value of an extern function to our register's type 78 | return do_assign(rt=ret_reg, op=simple_cast(for_extern.type, ret)) 79 | else: 80 | return do_assign(rt=ret_reg, op=ret) 81 | 82 | def internal_call(callee): 83 | # for calling functions inside our target 84 | return make_call( 85 | callee, args=args_for_call([ 86 | c_ast.ID('%s' % utils.args_tag)])) 87 | 88 | ep_ctypes = Enum('ep_ctypes', [ 89 | 'schar', 'uchar', 'short', 'ushort', 'int', 'uint', 'longint', 'ulongint', 90 | 'longlongint', 'ulonglongint', 'float', 'double', 'char', 'pointer']) 91 | slot_types = Enum('slot_types', ['s', 'd', 'i8', 'u8', 'i16', 'u16', 92 | 'i32', 'u32', 'i64', 'u64', '_']) 93 | 94 | slot_to_typename = { 95 | slot_types.s : simple_typename(['float']), 96 | slot_types.d : simple_typename(['double']), 97 | slot_types.i8 : simple_typename(['int8_t']), 98 | slot_types.u8 : simple_typename(['uint8_t']), 99 | slot_types.i16 : simple_typename(['int16_t']), 100 | slot_types.u16 : simple_typename(['uint16_t']), 101 | slot_types.i32 : simple_typename(['int32_t']), 102 | slot_types.u32 : simple_typename(['uint32_t']), 103 | slot_types.i64 : simple_typename(['int64_t']), 104 | slot_types.u64 : simple_typename(['uint64_t']) 105 | } 106 | 107 | class cnum(object): 108 | '''base class for C-style printable floating-point numbers''' 109 | __slots__ = ['value'] 110 | 111 | def __init__(self, value): 112 | tyty = type(value) 113 | if tyty is not float: 114 | raise utils.BugError('must be float, not %s' % tyty.__name__) 115 | self.value = value 116 | 117 | def __eq__(self, other): 118 | return type(self) is type(other) and self.value == other.value 119 | def __ne__(self, other): 120 | return not self.__eq__(other) 121 | 122 | class cfloat(cnum): 123 | '''wrapper to print round-trippable floats with C-style postfix f''' 124 | fmt = '%#.9g' 125 | 126 | def __str__(self): 127 | return (self.fmt + 'f') % self.value 128 | def __repr__(self): 129 | return '%s(%s)' % (self.__class__.__name__, self.fmt) % self.value 130 | 131 | class cdouble(cnum): 132 | '''wrapper to print round-trippable doubles''' 133 | def __str__(self): 134 | return '%#.17g' % self.value 135 | def __repr__(self): 136 | return '%s(%s)' % (self.__class__.__name__, self.value) 137 | 138 | fn_sig = namedtuple('fn_sig', ['return_type', 'arg_regs']) 139 | -------------------------------------------------------------------------------- /notes/decomp.txt: -------------------------------------------------------------------------------- 1 | TODO 2 | ==== 3 | formatter rewrite 4 | casting to non-ptrs for assignments, to ptrs for fn calls when needed 5 | needed for op, load, store, call, la, usefn, li, lui 6 | # ...i think? definitely la and addiu 7 | constant embedding 8 | local variables for registers 9 | elision of unused variables? 10 | unnecessary register save elision 11 | unnecessary la/addiu elision 12 | comment printing? 13 | re compilation 14 | 15 | FUTURE TODO 16 | =========== 17 | * should probably build cache of type to register mappings, especially because 18 | we have to recursively resolve typedefs 19 | * handle strange offset cases better 20 | * e.g. (&arr[idx] + off), despite its rarity 21 | * eliminate "name" pseudo-type 22 | * make better use of IDA's own info 23 | * opinfo_t, tinfo_t etc. already have the information we need, why wrap them 24 | with our own op_ty? 25 | 26 | useful IDA functions 27 | ==================== 28 | segs 29 | idaapi.getseg 30 | 31 | xrefs 32 | Dfirst 33 | Dnext 34 | 35 | disasm 36 | GetDisasm 37 | GetCurrentLine 38 | 39 | data 40 | GetManyBytes 41 | FindData 42 | 43 | etc 44 | GetCommentEx 45 | GetFunctionCmt 46 | is_ret_insn 47 | is_call_insn 48 | idaapi.get_switch_info_ex 49 | calc_switch_cases 50 | # how to determine insn is part of switch: 51 | nn = idaapi.netnode($' ignore micro') 52 | nn.charval(ea, 0) == idaapi.IM_SWITCH (3) 53 | 54 | fns 55 | # how to get crap from "jal $t9 ; crap": 56 | nn = idaapi.netnode('$ mips') 57 | nn.altval(ea) - 1 58 | GetFrame 59 | GetMemberQty 60 | GetFirstMember 61 | GetStrucNextOff 62 | GetStrucId 63 | GetMemberId 64 | GetMemberName 65 | GetMemberSize 66 | GetMemberFlag 67 | 68 | flags 69 | # use isWhatever, don't & flags by hand 70 | 71 | types 72 | idaapi.print_type2(ea, idaapi.PRTYPE_CPP | idaapi.PRTYPE_SEMI) 73 | get_item_head/tinfo/is_array 74 | 75 | operands 76 | .text:10006350 addiu $a1, (aElectropaint - 0x10010000) # "ElectroPaint" 77 | GetOperandValue(ea, 1) 78 | cmd = DecodeInstruction(ea) 79 | cmd[1].reg is 0 for no reg, a value for a register 80 | cmd[1].type is o_imm for immediate, o_displ for register-indexed 81 | 82 | arrays 83 | idc.ItemSize/idaapi.get_item_size will give size in bytes. to get length of 84 | array: 85 | 86 | (idc.ItemEnd(ea) - idc.ItemHead(ea)) # maybe NextNotTail instead of ItemEnd? 87 | / idc.SizeOf(idc.ParseType('float guy;', 0)[1]) 88 | 89 | decls for testing 90 | ================= 91 | JUNK_DECLS = ''' 92 | typedef int (*stupid)(i); 93 | 94 | int time[][2] = { {1, 2}, {3, 4} }; 95 | char *strs[16]; 96 | char morestrs[32][32]; 97 | 98 | dumbdef(i) const int i; {} 99 | int decla(i); 100 | int *defb(f, j, k) float f; int k; int j; {} 101 | int defc(float f) {} 102 | int fnd(i); 103 | int fnd(i) {} 104 | rudedef(int (*bdc)(i)) {} 105 | int empty_param_def() {} 106 | ''' 107 | FPTRS = ''' 108 | void (*p)(void); 109 | void (*fptrs[4])(void); 110 | ''' 111 | # bad decls (but pycparser will accept them): 112 | int arr_fn[4](int i); 113 | int arr_fn(int i)[4]; 114 | 115 | tree libraries 116 | ============== 117 | bintrees 118 | rbtree 119 | blackjack 120 | viridis 121 | pybst 122 | pyavl 123 | banyan 124 | 125 | various translation concerns 126 | ============================ 127 | 128 | #include 129 | #include 130 | #include 131 | #include 132 | 133 | /* how to do trunc_w_d */ 134 | 135 | typedef union reg { 136 | int32_t i32; 137 | float s; 138 | double d; 139 | } reg; 140 | 141 | int32_t 142 | trunc_w_d(double x) 143 | { 144 | double r = trunc(x); 145 | if (r > INT32_MAX || r < INT32_MIN) 146 | return INT32_MAX; 147 | else 148 | return r; 149 | } 150 | 151 | int 152 | main(void) 153 | { 154 | reg r; 155 | int x = 10; 156 | 157 | r.s = x; 158 | r.d = floor(r.s); 159 | r.i32 = trunc_w_d(r.d); 160 | memcpy(&x, &r, 4); 161 | printf("%d\n", x); 162 | 163 | return 0; 164 | } 165 | 166 | /* ===== */ 167 | 168 | #if 0 169 | #include 170 | #include 171 | #include 172 | 173 | /* this is how we will deal with swc1/lwc1 etc. */ 174 | 175 | int 176 | main(void) 177 | { 178 | union { uint64_t i; float s; double d; } x; 179 | uint64_t r, *p = (uint64_t *)&r; 180 | float f; 181 | 182 | x.d = -0.1; 183 | x.s = x.d; /* cvt.s.d */ 184 | r = x.i; /* mfc1 */ 185 | memcpy(&f, &x, 4); /* swc1 */ 186 | // XXX but this breaks strict aliasing! 187 | printf("%#x %f %f\n", r, *(float *)&r, f); 188 | 189 | return 0; 190 | } 191 | #endif 192 | 193 | /* ===== */ 194 | 195 | #if 0 196 | #include 197 | #include 198 | 199 | /* 200 | * sadly, casting a function pointer to a data pointer is considered undefined 201 | * behavior (though it will work on most systems)--we must avoid using it 202 | */ 203 | 204 | int 205 | main(void) 206 | { 207 | uintptr_t putty = (uintptr_t)puts; 208 | 209 | ((int (*)(const char *))putty)("hi"); 210 | return 0; 211 | } 212 | #endif 213 | -------------------------------------------------------------------------------- /decomp/c/gen.py: -------------------------------------------------------------------------------- 1 | from itertools import imap, chain 2 | from pycparser import c_generator, c_ast 3 | from decomp import data, ida 4 | from decomp.c import decl as cdecl, types as ep_ct 5 | from decomp.cpu import ida as cpu_ida 6 | 7 | XXX_INTRO_HACK = cpu_ida.ida_current_cpu().insns.support_header + ''' 8 | #include 9 | typedef union EPANOS_REG { 10 | uint8_t u8; 11 | int32_t i32; 12 | uint32_t u32; 13 | int64_t i64; 14 | uint64_t u64; 15 | float s; 16 | double d; 17 | } EPANOS_REG; 18 | 19 | typedef struct EPANOS_ARGS { 20 | EPANOS_REG v0; 21 | EPANOS_REG v1; 22 | EPANOS_REG a0; 23 | EPANOS_REG a1; 24 | EPANOS_REG a2; 25 | EPANOS_REG a3; 26 | EPANOS_REG a4; 27 | EPANOS_REG a5; 28 | EPANOS_REG a6; 29 | EPANOS_REG a7; 30 | EPANOS_REG f0; 31 | EPANOS_REG f2; 32 | EPANOS_REG f12; 33 | EPANOS_REG f13; 34 | EPANOS_REG f14; 35 | EPANOS_REG f15; 36 | EPANOS_REG f16; 37 | EPANOS_REG f17; 38 | EPANOS_REG f18; 39 | EPANOS_REG f19; 40 | } EPANOS_ARGS; 41 | ''' 42 | 43 | gen_from_node = c_generator.CGenerator().visit 44 | flatten = chain.from_iterable 45 | 46 | def c_for_insn(ea, our_fns, extern_reg_map, stkvars): 47 | while True: 48 | (ea, c) = cpu_ida.ida_current_cpu().gen.fmt_insn( 49 | ea, our_fns, extern_reg_map, stkvars, from_delay=False) 50 | yield c 51 | if ea == ida.BADADDR: 52 | break 53 | 54 | def generate(ea, decl, our_fns, extern_reg_map, stkvar_map, stkvar_decls): 55 | '''ea_t -> c_ast() -> frozenset(str) -> {str : reg_sig} -> 56 | {str : {int : tinfo_t}} {str : [c_ast]} -> c_ast''' 57 | try: 58 | stkvars = stkvar_map[decl.name] 59 | var_decls = stkvar_decls[decl.name] 60 | except KeyError: 61 | stkvars = {} 62 | var_decls = [] 63 | 64 | start_ea = ida.get_func(ea).startEA 65 | body = [XXX_STACKVAR_HACK()] + [var_decls] + [x for x in 66 | c_for_insn(start_ea, our_fns, extern_reg_map, stkvars)] 67 | funcdef = c_ast.FuncDef(decl, None, c_ast.Compound(flatten(body))) 68 | 69 | return funcdef 70 | 71 | def XXX_STACKVAR_HACK(): 72 | # XXX FIXME this will be going away once we've added elision of unnecessary 73 | # stack variables (probably will just stick declarations into the AST) 74 | regs = list( 75 | c_ast.Decl( 76 | x, [], [], [], 77 | c_ast.TypeDecl( 78 | x, [], 79 | c_ast.IdentifierType( 80 | ['EPANOS_REG'])), 81 | None, None) 82 | for x in 83 | list('t%s' % str(n) for n in range(4, 8)) 84 | + list('s%s' % str(n) for n in range(0, 8)) 85 | + ['at', 't8', 't9', 'gp', 'sp', 'ra', 'fp', 'f1'] 86 | + list('f%s' % str(n) for n in range(3, 12)) 87 | + list('f%s' % str(n) for n in range(20, 32))) 88 | regs += [ 89 | c_ast.Decl( 90 | 'EPANOS_fp_cond', [], [], [], 91 | c_ast.TypeDecl( 92 | 'EPANOS_fp_cond', [], 93 | c_ast.IdentifierType( 94 | ['int'])), 95 | None, None)] 96 | return regs 97 | 98 | def run(externs, our_fns, cpp_filter, cpp_all, decompile=True): 99 | '''frozenset(str) -> frozenset(str) -> str -> str -> opt:bool -> [c_ast]''' 100 | global OUR_FNS, EXTERN_REG_MAP, STKVAR_MAP # for repl convenience 101 | OUR_FNS = our_fns 102 | 103 | fn_segs = data.get_segs(['extern', '.text']) 104 | rodata_segs = data.get_segs(['.rodata', '.srdata']) 105 | data_segs = data.get_segs(['.data', '.bss']) 106 | lit_segs = data.get_segs(['.lit4', '.lit8']) 107 | 108 | num_lits = data.get_num_literals(lit_segs) 109 | str_lits = data.get_str_literals(rodata_segs) 110 | data_txt = data.get_data(data_segs, cpp_filter) 111 | 112 | # XXX FIXME this will be going away once we've added emitting numeric and 113 | # string constants directly at their site of use 114 | if decompile is True: 115 | for (k, v) in num_lits.iteritems(): 116 | ty = type(v) 117 | if ty is ep_ct.cfloat: 118 | print 'float %s = %s;' % (k, v) 119 | elif ty is ep_ct.cdouble: 120 | print 'double %s = %s;' % (k, v) 121 | else: 122 | raise Exception('o no') 123 | for (k, v) in str_lits.iteritems(): 124 | print 'const char *%s = %s;' % (k, data.c_stringify(v)) 125 | 126 | protos = map(cdecl.make_internal_fn_decl, our_fns) 127 | 128 | (lib_fns, tds) = data.get_fns_and_types(fn_segs, externs, cpp_all) 129 | all_tds = {x.name : x for x in tds} 130 | typedefs = cdecl.resolve_typedefs(all_tds) 131 | EXTERN_REG_MAP = data.get_fn_arg_map(lib_fns, typedefs) 132 | STKVAR_MAP = data.get_stkvars(our_fns) 133 | stkvar_decls = data.make_stkvar_txt(our_fns, STKVAR_MAP, cpp_filter) 134 | 135 | if decompile is True: 136 | print XXX_INTRO_HACK 137 | return gen_from_node(c_ast.FileAST( 138 | data_txt + 139 | protos + 140 | list(generate(ida.loc_by_name(decl.name), decl, our_fns, 141 | EXTERN_REG_MAP, STKVAR_MAP, stkvar_decls) 142 | for decl in protos))) 143 | else: 144 | return 145 | 146 | def repl_make_insn(ea, from_delay): 147 | # for testing: print the C that will be generated from a line of assembly. 148 | # note that if you ask for the ea of an insn in a delay slot, you get only 149 | # that instruction; if you ask for a delayed instruction, you get both 150 | try: 151 | stkvars = STKVAR_MAP[ida.get_func_name(ea)] 152 | except KeyError: 153 | stkvars = {} 154 | 155 | return list(gen_from_node(x) for x in 156 | cpu_ida.ida_current_cpu().gen.fmt_insn( 157 | ea, OUR_FNS, EXTERN_REG_MAP, stkvars, from_delay).c) 158 | -------------------------------------------------------------------------------- /decomp/cpu/mips/data.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | from decomp import ida, utils 3 | from decomp.cpu import regs 4 | from decomp.cpu.mips import abi, insns 5 | 6 | class SwitchTroubleError(Exception): pass 7 | class UnsupportedInstructionError(Exception): pass 8 | class FunctionPointerError(Exception): pass 9 | class VarargsError(Exception): pass 10 | 11 | def immval(arg): 12 | '''int -> int''' 13 | return ctypes.c_int16(arg & 0xffff).value 14 | 15 | def interpret_li_arg(arg): 16 | # XXX IDA's li simplification is not so good for printing in C, e.g.: 17 | # 18 | # addiu $t0, $zero, -1 19 | # 20 | # becomes li $t0, 0xFFFFFFFF -- this will cause trouble with promotions. 21 | # need to report this 22 | return ctypes.c_int32(arg).value 23 | 24 | def get_op_addrmode(ea, op, cmd): 25 | '''ea_t -> int -> insn_t -> op_ret''' 26 | # the ida module calls back into this module to deal with some MIPS-specific 27 | # operand handling here 28 | mnem = ida.get_mnem(ea) 29 | op = ida.mips_op_hack(cmd, op) 30 | 31 | if cmd[op].type == ida.o_imm: 32 | val = cmd[op].value 33 | elif cmd[op].type == ida.o_displ: 34 | val = cmd[op].addr 35 | else: 36 | raise utils.BugError('neither imm nor displ passed to get_op_addrmode') 37 | 38 | if mnem in insns.has_special_opnd: 39 | target = val 40 | return ida.resolve_opnd(target, val) 41 | # addiu is often used for address calculation, which IDA will resolve to a 42 | # name, so handle addiu's immval only if we fail to resolve it later 43 | elif mnem != 'addiu' and mnem in insns.has_imm: 44 | return ida.op_ret(ida.op_ty.value, immval(val), 0) 45 | else: 46 | target = ida.calc_target(ea, ea, op, immval(val)) 47 | if target == ida.BADADDR and cmd[op].type == ida.o_displ: 48 | reg = cmd[op].reg 49 | if reg >= 0 and reg <= 31: 50 | reg = regs.gpr(reg) 51 | elif reg >= 32 and reg <= 63: 52 | reg = regs.fpr(reg) 53 | else: 54 | raise utils.BugError('bogus register %u' % reg) 55 | return ida.op_ret(ida.op_ty.displ, 56 | ida.displ(reg=reg, 57 | displ=immval(val)), 58 | 0) 59 | else: 60 | opnd = ida.resolve_opnd(target, val) 61 | if mnem == 'addiu' and opnd.ty == ida.op_ty.value: 62 | # addiu is being used for regular addition; handle its third 63 | # operand as an immediate value 64 | return ida.op_ret(ida.op_ty.value, immval(opnd.val), 0) 65 | else: 66 | return opnd 67 | 68 | def get_arg_for_va_function(callee, start_ea): 69 | '''str -> ea_t -> str''' 70 | # XXX hacky; not a very general function 71 | # XXX imperative 72 | # get a relevant item needed for processing a variadic function 73 | sw = { 74 | 'printf' : regs.gpr(abi.arg_regs[0]), 75 | 'scanf' : regs.gpr(abi.arg_regs[0]), 76 | 'sscanf' : regs.gpr(abi.arg_regs[1]) 77 | } 78 | try: 79 | wanted_reg = sw[callee] 80 | except KeyError: 81 | raise utils.BugError('unrecognized callee %s' % callee) 82 | 83 | distance = 0 84 | fn = ida.get_func(start_ea) 85 | # first, look at the delay slot 86 | ea = ida.next_head(start_ea, fn.endEA) 87 | 88 | while True: 89 | if distance > 10: 90 | raise VarargsError( 91 | 'gave up looking for needed varargs argument for %s between ' + 92 | '%s..%s' % (ida.atoa(ea), ida.atoa(start_ea))) 93 | 94 | if ea == start_ea: 95 | ea = ida.prev_head(ea) 96 | continue # skip the call insn 97 | elif list(ida.code_refs_from(ea, 0)) != []: 98 | raise VarargsError( 99 | 'encountered branch/jump while looking for varargs argument ' + 100 | 'between %s..%s' % (ida.atoa(ea), ida.atoa(start_ea))) 101 | 102 | rd = ida.get_op(ea, 0) 103 | if rd.val == wanted_reg: 104 | opvals = ida.get_opvals(ea) # XXX should try to track stkvar values 105 | s = ida.get_string(opvals[-1].target) 106 | if s is not None: 107 | return s 108 | 109 | ea = ida.prev_head(ea) 110 | distance += 1 111 | 112 | def get_swval(start_ea): 113 | '''ea_t -> (str, op_ty, int)''' 114 | # XXX imperative 115 | ida.get_switch_info(start_ea) # confirm this insn has switch info 116 | 117 | distance = 0 118 | ea = ida.prev_head(start_ea) 119 | 120 | while True: 121 | if distance > 10: 122 | raise SwitchTroubleError( 123 | 'gave up looking for switch value between %s..%s' 124 | % (ida.atoa(ea), ida.atoa(start_ea))) 125 | 126 | if ida.is_switch_insn(ea): 127 | mnem = ida.get_mnem(ea) 128 | # dunno if there are other common switch idioms 129 | if mnem == 'sltiu': 130 | return (mnem, ida.get_op(ea, 1), 1) 131 | elif list(ida.code_refs_from(ea, 0)) != []: 132 | raise SwitchTroubleError( 133 | 'encountered branch/jump while looking for switch value ' + 134 | 'between %s..%s' % (ida.atoa(ea), ida.atoa(start_ea))) 135 | 136 | ea = ida.prev_head(ea) 137 | distance += 1 138 | 139 | def get_callee(ea, mnem, args): 140 | '''ea_t -> str -> formatter_args -> str''' 141 | # XXX we don't handle function pointers yet, but it should be easy now that 142 | # we handle all internal functions as having the same signature...i think 143 | if mnem == 'jalr': 144 | nn = ida.netnode('$ mips') 145 | fun = nn.altval(ea) - 1 146 | if fun == -1: 147 | raise FunctionPointerError( 148 | 'unknown target for function pointer at %s' 149 | % ida.atoa(ea)) 150 | return ida.name(fun) 151 | elif mnem == 'jal': 152 | return args['rs'].name 153 | else: 154 | raise utils.BugError('unhandled call insn: %s' % mnem) 155 | -------------------------------------------------------------------------------- /decomp/data.py: -------------------------------------------------------------------------------- 1 | from itertools import imap, izip 2 | from decomp import ida, utils 3 | from decomp.c import cpp, decl as cdecl, types as ep_ct 4 | 5 | class UnknownDataTypeError(Exception): pass 6 | 7 | def get_literals(segs, fn, pred): 8 | '''[str] -> fn -> fn -> {str : }''' 9 | return {name : fn(ea) 10 | for (name, ea) in ida.ea_list_from_segs(segs) 11 | if pred(ea)} 12 | 13 | def get_one_item(ea, ti, sz): 14 | '''ea_t -> tinfo_t -> int -> c.types obj | int | long?''' 15 | if ti.is_float(): 16 | return ep_ct.cfloat(ida.get_float(ea)) 17 | elif ti.is_double(): 18 | return ep_ct.cdouble(ida.get_double(ea)) 19 | else: 20 | try: 21 | # NOTE this gets the SOURCE'S size for a given type, which may not 22 | # match the target's 23 | size_to_fn = { 24 | 1 : ida.byte, 2 : ida.word, 4 : ida.dword, 8 : ida.qword} 25 | fn = size_to_fn[sz] 26 | except KeyError: 27 | raise UnknownDataTypeError('unknown data type at %s' % ida.atoa(ea)) 28 | return fn(ea) 29 | 30 | def get_item(ea, ti): 31 | '''ea_t -> tinfo_t -> c.types obj | int | str''' 32 | if ti.is_array(): 33 | ai = ida.array_details(ti) 34 | if ai.elem_type.is_char(): 35 | return ida.get_string(ea) 36 | else: 37 | sz = ai.elem_type.get_size() 38 | ret = get_one_item(ea, ai.elem_type, sz) 39 | return ret 40 | else: 41 | sz = ida.size_of(ti) 42 | return get_one_item(ea, ti, sz) 43 | 44 | def get_num_literals(segs): 45 | '''[str] -> {str : c.types obj}''' 46 | def get_num(ea): 47 | ti = ida.get_or_guess_tinfo(ea) 48 | return get_item(ea, ti) 49 | 50 | return get_literals(segs, get_num, lambda x: True) 51 | 52 | def get_str_literals(segs): 53 | '''[str] -> {str : str}''' 54 | # XXX making a bad assumption that we only need a string if it's referred to 55 | # in .text, but this avoids some junk in .rodata (e.g. jump tables) 56 | return get_literals(segs, ida.get_string, 57 | lambda x: cdecl.is_c_str(ida.guess_type(x)) and 58 | '.text' in list(ida.seg_name(y) for y in 59 | (ida.data_refs_to(x)))) 60 | 61 | def get_type_for_c_ast_constant(ti): 62 | '''tinfo_t -> str''' 63 | if ti.is_floating(): 64 | return 'float' 65 | elif ti.is_char(): 66 | return 'string' 67 | else: 68 | return 'int' 69 | 70 | def get_data(segs, cpp_in): 71 | '''[str] -> str -> [c_ast]''' 72 | def gen(((ti, ea, declstr), node)): 73 | '''(tinfo_t, ea_t) -> c_ast''' 74 | # NOTE mutates node 75 | has_data = ida.seg_name(ea) != '.bss' 76 | ptr = ida.can_be_off32(ea) 77 | if ptr not in [ida.BADADDR, 0]: 78 | ptr_ti = ida.get_or_guess_tinfo(ptr) 79 | ti_node = cdecl.get_decls(declstr).decls[utils.cpp_decomp_tag][0] 80 | return gen(((ptr_ti, ptr, ''), ti_node)) 81 | # XXX our data segment has no strings, but that's probably specific to 82 | # the one binary we're dealing with 83 | elif ti.is_array(): 84 | ai = ida.array_type_data_t() 85 | ti.get_array_details(ai) 86 | item_size = ai.elem_type.get_size() 87 | typename = get_type_for_c_ast_constant(ai.elem_type) 88 | length = (ida.item_end(ea) - ida.item_head(ea)) / item_size 89 | if has_data is True: 90 | if ai.elem_type.is_char(): 91 | node.init = ep_ct.constant(typename, c_stringify( 92 | ida.get_string(ea))) 93 | else: 94 | items = list(get_item(ea + j * item_size, ti) 95 | for j in xrange(0, length)) 96 | node.init = ep_ct.initlist( 97 | [ep_ct.constant(typename, str(x)) for x in items]) 98 | else: 99 | if has_data is True: 100 | typename = get_type_for_c_ast_constant(ti) 101 | node.init = ep_ct.constant(typename, 102 | str(get_item(ea, ti))) 103 | return node 104 | 105 | def get_tinfo_and_declstr(ea): 106 | ti = ida.get_or_guess_tinfo(ea) 107 | return (ti, ea, ida.print_tinfo(ida.name(ea), ti)) 108 | 109 | def has_got_seg_in_data_refs(refs): 110 | # filter out data not referenced by GOT 111 | return '.got' in [ida.seg_name(x) for x in refs] 112 | 113 | def get_refs_and_ea((_, ea)): 114 | return (ida.data_refs_to(ea), ea) 115 | 116 | refs_eas = imap(get_refs_and_ea, 117 | ida.ea_list_from_segs(segs)) 118 | data = list(get_tinfo_and_declstr(ea) 119 | for (refs, ea) in refs_eas 120 | if has_got_seg_in_data_refs(refs)) 121 | declstrs = '\n'.join([x[2] for x in data]) 122 | decls = izip(data, 123 | cdecl.get_decls(declstrs, cpp_in).decls[utils.cpp_decomp_tag]) 124 | return map(gen, decls) 125 | 126 | def get_fns_and_types(segs, wanted_fns, cpp_in): 127 | '''[str] -> [str] -> str -> ([c_ast], [c_ast])''' 128 | # NOTE mutates, because... 129 | # 130 | # IDA will always give us demangled names in type signatures, so we have to 131 | # replace the name in the returned decl with the mangled name 132 | def get_wanted(l, (name, decl)): 133 | return l + [decl] if name in wanted_fns else l 134 | 135 | def get_name_type((name, ea)): 136 | return (name, ida.print_type2(ea)) 137 | 138 | fns = reduce(get_wanted, 139 | imap(get_name_type, ida.ea_list_from_segs(segs)), 140 | []) 141 | 142 | (decls, typedefs) = cdecl.get_decls('\n'.join(fns), cpp_in) 143 | name_to_decl = {x.name : x for x in decls[utils.cpp_decomp_tag]} 144 | for (decl, mangled) in utils.zip_prefixes(name_to_decl.keys(), 145 | wanted_fns): 146 | name_to_decl[decl].name = mangled 147 | 148 | return decls[utils.cpp_decomp_tag], typedefs 149 | 150 | def get_segs(segs): 151 | '''[str] -> [(str, ea_t)]''' 152 | def get_name_base(seg): 153 | return (seg, ida.seg_by_name(seg)) 154 | 155 | return list((name, ida.seg_by_base(idx)) for (name, idx) in 156 | imap(get_name_base, segs) if idx != ida.BADADDR) 157 | 158 | def get_fn_arg_map(decls, typedefs): 159 | '''[c_ast] -> {(strs) : (strs)} -> {str : reg_sig}''' 160 | return {x.name : cdecl.get_fn_sig(x, typedefs) for x in decls} 161 | 162 | def get_stkvars(fns): 163 | '''frozenset(str) -> {str : {int : tinfo_t}}''' 164 | def make_input(d, fn): 165 | # NOTE mutates d 166 | var_map = ida.get_stkvar_map(ida.loc_by_name(fn)) 167 | if var_map == {}: 168 | pass 169 | else: 170 | d[fn] = var_map 171 | return d 172 | 173 | return reduce(make_input, fns, {}) 174 | 175 | def make_stkvar_txt(fns, stkvar_map, cpp_filter): 176 | '''frozenset(str) -> {str : {int : tinfo_t}} -> str -> {str : c_ast}''' 177 | def make_decls(acc, (fn, items)): 178 | txt = '\n'.join(ida.print_tinfo(name, ti) 179 | for (name, ti) in items.itervalues()) 180 | return acc + cpp.make_cpp_input(fn, txt) 181 | 182 | cpp_in = reduce(make_decls, stkvar_map.iteritems(), cpp_filter) 183 | # force preprocessing by passing as cpp_in instead of decls 184 | vardecls = cdecl.get_decls('', cpp_in, fns).decls 185 | return {fn : vardecls[fn] for fn in vardecls.iterkeys()} 186 | 187 | def c_stringify(s): 188 | r = s.replace('"', r'\"') 189 | return '"%s"' % repr(r).rstrip("'").lstrip("'").replace(r'\\', '\\') 190 | -------------------------------------------------------------------------------- /decomp/c/decl.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | from cStringIO import StringIO 3 | import re, struct 4 | from pycparser import c_parser, c_ast 5 | from decomp import utils 6 | from decomp.c import cpp 7 | from decomp.cpu import ida 8 | 9 | class ComplicatedDeclError(Exception): pass 10 | class EmptyArgListError(Exception): pass 11 | class UnwantedNodeError(Exception): pass 12 | 13 | # instantiate a parser here so we can reuse it 14 | parser = c_parser.CParser() 15 | 16 | decls_and_types = namedtuple('decls_and_types', ['decls', 'typedefs']) 17 | resolved_types = namedtuple('resolved_types', ['no_tag', 'tag']) 18 | 19 | ### 20 | ### Functions for parsing C declarations and argument to register mapping 21 | ### 22 | 23 | def node_fail(exc, msg, node): 24 | '''exc -> str -> c_ast -> unit''' 25 | out = StringIO() 26 | node.show(nodenames=True, attrnames=True, buf=out) 27 | raise exc(msg % out.getvalue) 28 | 29 | def get_decl_type_and_names(node): 30 | '''c_ast -> (c_ast, (str*))''' 31 | def fail(node): 32 | node_fail(ComplicatedDeclError, 33 | 'not a typedef or data declaration:\n%s', 34 | node) 35 | 36 | sw = { 37 | c_ast.Decl : lambda x: get_decl_type_and_names(x.decl), 38 | c_ast.TypeDecl : lambda x: get_decl_type_and_names(x.type), 39 | c_ast.Typename : lambda x: get_decl_type_and_names(x.names), 40 | c_ast.Struct : lambda x: (c_ast.Struct, (x.name,)), 41 | c_ast.Union : lambda x: (c_ast.Union, (x.name,)), 42 | c_ast.Enum : lambda x: (c_ast.Decl, (x.name,)), 43 | c_ast.ArrayDecl : lambda x: get_decl_type_and_names(x.type), 44 | c_ast.PtrDecl : lambda x: get_decl_type_and_names(x.type), 45 | c_ast.IdentifierType : lambda x: (c_ast.Decl, tuple(x.names)) 46 | } 47 | 48 | return utils.dictswitch(type(node), sw, node, fail, node) 49 | 50 | def process_ast(ast, wanted): 51 | '''c_ast -> [str] -> ({str : [c_ast]}, [c_ast])''' 52 | # NOTE mutates typedefs, decls 53 | def get_decls_and_typedefs((decls, typedefs), (_, node)): 54 | nodety = type(node) 55 | if nodety not in (c_ast.Decl, c_ast.Typedef): 56 | node_fail(UnwantedNodeError, 'unwanted node:\n%s', node) 57 | 58 | if nodety is c_ast.Typedef: 59 | typedefs.append(node) 60 | elif node.coord.file in all_wanted and node: 61 | # retrieve user-provided decls, but skip any from user's #includes 62 | try: 63 | decls[node.coord.file].append(node) 64 | except KeyError: 65 | decls[node.coord.file] = [node] 66 | 67 | return decls_and_types(decls, typedefs) 68 | 69 | all_wanted = wanted.union([utils.cpp_decomp_tag]) 70 | return reduce(get_decls_and_typedefs, ast.children(), ({}, [])) 71 | 72 | def make_internal_fn_decl(name): 73 | '''str -> c_ast''' 74 | # don't you wish python had a macro system? 75 | return c_ast.Decl( 76 | name, [], [], [], 77 | c_ast.FuncDecl( 78 | c_ast.ParamList( 79 | [c_ast.Decl( 80 | utils.args_tag, [], [], [], 81 | c_ast.PtrDecl( 82 | [], 83 | c_ast.TypeDecl( 84 | utils.args_tag, [], 85 | c_ast.IdentifierType(['%s%s' 86 | % (utils.decomp_tag, 87 | utils.args_tag)]))), 88 | None, None)]), 89 | c_ast.TypeDecl( 90 | name, [], 91 | c_ast.IdentifierType(['void']))), 92 | None, None) 93 | 94 | def get_decls(decls, cpp_in='', wanted=frozenset()): 95 | '''str -> opt:str -> opt:frozenset([str]) -> 96 | ({str : [c_ast]}, [c_ast])''' 97 | if cpp_in != '': 98 | decls = cpp.preprocess('%s\n%s' % (cpp_in, decls)) 99 | return process_ast(parser.parse(decls, filename=utils.cpp_decomp_tag), 100 | wanted) 101 | 102 | def resolve_typedefs(nodes): 103 | '''[c_ast()] -> {(str*) : (str*)}''' 104 | # NOTE mutates: modifies d 105 | def resolve_type_name(typename, d): 106 | try: 107 | return resolve_type_name(d[typename], d) 108 | except KeyError: 109 | return typename 110 | 111 | def resolve(d, (name, node)): 112 | try: 113 | (tag, typenames) = get_decl_type_and_names(node.type) 114 | if tag is c_ast.Decl: 115 | which = d.no_tag 116 | elif tag in [c_ast.Struct, c_ast.Union, c_ast.Enum]: 117 | which = d.tag 118 | which[name] = resolve_type_name(typenames, which) 119 | except ComplicatedDeclError: 120 | pass 121 | return d 122 | 123 | return reduce(resolve, nodes.iteritems(), 124 | resolved_types({}, {})) 125 | 126 | def find_node(node, wanted): 127 | '''c_ast -> ty -> c_ast''' 128 | if type(node) is wanted: 129 | return node 130 | else: 131 | return find_node(node.type, wanted) 132 | 133 | def get_fn_sig(node, typedefs): 134 | '''c_ast -> {str : {str : (str*)}} -> fn_sig''' 135 | def resolve_types(node, typedefs): 136 | def resolve_one_type(node, typedefs): 137 | # NOTE mutates: modifies n.names (changes ast) 138 | try: 139 | n = find_node(node, c_ast.IdentifierType) 140 | n.names = list(typedefs.no_tag[' '.join(n.names)]) 141 | except (AttributeError, KeyError): 142 | # AttributeError: will happen on e.g. structs; ignore 143 | # KeyError: type not in the typedef dict 144 | pass 145 | 146 | if node.args is not None: 147 | for (_, x) in node.args.children(): 148 | resolve_one_type(x, typedefs) 149 | resolve_one_type(node.type, typedefs) 150 | 151 | def get_sig(node, typedefs): 152 | resolve_types(node, typedefs) 153 | if node.args is not None: 154 | return ida.ida_current_cpu().get_abi_fn_arg_map(node) 155 | else: 156 | raise EmptyArgListError( 157 | "use (void) if %s takes no arguments" % node.name) 158 | 159 | return get_sig(find_node(node, c_ast.FuncDecl), typedefs) 160 | 161 | def is_c_str(string): 162 | '''str -> bool''' 163 | # XXX this is for the benefit of get_str_literals to avoid using pycparser 164 | # for a very simple type--IDA will always(?) return char[size] for 165 | # GuessType() on a C string. this will probably break on other string 166 | # types, or if we change get_str_literals to use get_or_guess_type and a 167 | # user provides their own type that doesn't match this. 168 | return re.search(r'^char\[(?:\d+)?\]$', string) is not None 169 | 170 | def castify(node): 171 | '''c_ast -> c_ast''' 172 | # NOTE mutates declname (changes ast) 173 | # 174 | # in order to make extern calls without warnings, we must cast our register 175 | # arguments (which are just ints) to the argument types. this function 176 | # takes ast nodes like these: 177 | # 178 | # ArrayDecl : dim_quals=[] 179 | # PtrDecl : quals=[] 180 | # TypeDecl : declname=argv, quals=[] 181 | # IdentifierType : names=['char'] 182 | # 183 | # TypeDecl : declname=main, quals=[] 184 | # IdentifierType : names=['int'] 185 | # 186 | # and produces these: 187 | # 188 | # Typename : quals=[] 189 | # ArrayDecl : dim_quals=[] 190 | # PtrDecl : quals=[] 191 | # TypeDecl : declname=None, quals=[] 192 | # IdentifierType : names=['char'] 193 | # 194 | # Typename : quals=[] 195 | # TypeDecl : declname=None, quals=[] 196 | # IdentifierType : names=['int'] 197 | # 198 | # which are suitable for use with c_ast.Cast. (we have to make declname 199 | # None or CGenerator().visit will include the name--bogus in a cast) 200 | find_node(node, c_ast.TypeDecl).declname = None 201 | return c_ast.Typename(node.quals, node) 202 | -------------------------------------------------------------------------------- /decomp/cpu/mips/insns.py: -------------------------------------------------------------------------------- 1 | import re 2 | from collections import namedtuple 3 | from flufl.enum import Enum 4 | from decomp import utils 5 | from decomp.c import types as ep_ct 6 | 7 | ## Instruction format table 8 | # XXX the fp rounding mode is currently NOT tracked! if the rounding mode is 9 | # changed in the program, the emitted code will NOT be accurate to the original! 10 | # 11 | # commas delimit fields, non-leading spaces delimit arguments, _ is n/a or none 12 | # 13 | # insn: mnemonic 14 | # union slot: union field to use for each operand 15 | # opfs: controls handling of operand (see mips.gen) 16 | # insn types: controls handling of insn (see mips.gen) 17 | # subst: an argument for the function that handles this insn 18 | # result: cast rvalue to this or use this slot for lvalue 19 | # 20 | #insn opslots opfs type subtypes subst result 21 | insn_fmts=''' 22 | add.d, d d d, fpr fpr fpr, op, _, +, _ 23 | add.s, s s s, fpr fpr fpr, op, _, +, _ 24 | addiu, u64 u32 _, gpr gpr imm, op, _, +, i32 25 | addu, u64 u32 u32, gpr gpr gpr, op, _, +, i32 26 | andi, u64 u64 _, gpr gpr imm, op, zimm, &, _ 27 | b, _, loc, jump, _, _, _ 28 | bc1f, _, loc, fbranch, _, !%sfp_cond, _ 29 | bc1t, _, loc, fbranch, _, %sfp_cond, _ 30 | beq, u64 u64 _, gpr gpr loc, branch, _, ==, _ 31 | beqz, u64 _, gpr loc, branch, zero, ==, _ 32 | bgez, i64 _, gpr loc, branch, zero, >=, _ 33 | blez, i64 _, gpr loc, branch, zero, <=, _ 34 | bne, u64 u64 _, gpr gpr loc, branch, _, !=, _ 35 | bnez, u64 _, gpr loc, branch, zero, !=, _ 36 | bnezl, u64 _, gpr loc, branch, zero likely, !=, _ 37 | c.eq.s, s s, fpr fpr, fcmp, _, ==, _ 38 | c.le.d, d d, fpr fpr, fcmp, _, <=, _ 39 | c.le.s, s s, fpr fpr, fcmp, _, <=, _ 40 | c.lt.d, d d, fpr fpr, fcmp, _, <, _ 41 | c.lt.s, s s, fpr fpr, fcmp, _, <, _ 42 | cvt.d.s, d s, fpr fpr, load, _, _, _ 43 | cvt.s.d, s d, fpr fpr, load, _, _, _ 44 | cvt.s.w, s i32, fpr fpr, load, _, _, _ 45 | div.d, d d d, fpr fpr fpr, op, _, /, _ 46 | div.s, s s s, fpr fpr fpr, op, _, /, _ 47 | dmfc1, u64 u64, gpr fpr, load, _, _, _ 48 | dmtc1, u64 u64, gpr fpr, store, _, _, _ 49 | jal, _, loc, call, _, _, _ 50 | jalr, _, gpr, call, _, _, _ 51 | jr, _, gpr, jr, _, _, _ 52 | la, u64 _, gpr spec, la, _, _, _ 53 | lbu, u64 _, gpr addr, load, _, int8_t, _ 54 | ld, u64 _, gpr addr, load, _, uint64_t, _ 55 | ldc1, _, addr addr, usefn, _, memcpy, _ 56 | li, u64 _, gpr spec, li, _, _, _ 57 | lui, u64 _, gpr spec, lui, _, _, i32 58 | lw, u64 _, gpr addr, load, _, int32_t, _ 59 | lwc1, _, addr addr, usefn, _, memcpy, _ 60 | mov.d, d d, fpr fpr, load, _, _, _ 61 | mov.s, s s, fpr fpr, load, _, _, _ 62 | move, u64 u64, gpr gpr, load, _, _, _ 63 | mtc1, u32 u32, gpr fpr, store, _, _, _ 64 | mul.d, d d d, fpr fpr fpr, op, _, *, _ 65 | mul.s, s s s, fpr fpr fpr, op, _, *, _ 66 | nop, _, _, nop, _, _, _ 67 | sb, u8 _, gpr addr, store, _, uint8_t, _ 68 | sd, u64 _, gpr addr, store, _, uint64_t, _ 69 | sdc1, _, addr addr, usefn, _, memcpy, _ 70 | sll, u64 u32 _, gpr gpr spec, op, _, <<, i32 71 | slt, u64 i64 i64, gpr gpr gpr, slt, _, signed, _ 72 | slti, u64 i64 _, gpr gpr imm, slt, _, signed, _ 73 | sltiu, u64 u64 _, gpr gpr imm, slt, _, unsigned, _ 74 | sra, u64 i32 _, gpr gpr spec, op, _, >>, i32 75 | sub.s, s s s, fpr fpr fpr, op, _, -, _ 76 | subu, u64 u32 u32, gpr gpr gpr, op, _, -, i32 77 | sw, u32 _, gpr addr, store, _, uint32_t, _ 78 | swc1, _, addr addr, usefn, _, memcpy, _ 79 | trunc.w.d, d, fpr fpr, usefn, _, trunc_w_d, i32 80 | xor, u64 u64 u64, gpr gpr gpr, op, _, ^, _ 81 | ''' % (utils.decomp_tag, utils.decomp_tag) 82 | 83 | # stuff to support emulation of some MIPS instructions 84 | support_header = ''' 85 | #include /* for trunc */ 86 | #include /* for INT32_MIN/MAX */ 87 | #include /* for memcpy */ 88 | 89 | int32_t 90 | trunc_w_d(double x) 91 | { 92 | double r = trunc(x); 93 | if (r > INT32_MAX || r < INT32_MIN) 94 | return INT32_MAX; 95 | else 96 | return r; 97 | } 98 | ''' 99 | 100 | mips_insn = namedtuple('mips_insn', ['insn', 'slots', 'opfs', 'ty', 'subty', 101 | 'subst', 'result']) 102 | types = Enum('insn_ty', 103 | ['op', 'load', 'store', 'jump', 'fbranch', 'branch', 'slt', 104 | 'call', 'jr', 'delay', 'fcmp', 'nop', 'la', 'li', 'lui', 105 | 'usefn']) 106 | subtypes = Enum('subtypes', ['zero', 'likely', 'zimm', '_']) 107 | opnd_types = Enum('opnd_types', ['fpr', 'gpr', 'imm', 'loc', 'spec', 'addr']) 108 | 109 | def create_insn_table(): 110 | '''unit -> {str : mips_insn}''' 111 | def make_insn(fmt): 112 | '''[str] -> (str, mips_insn)''' 113 | def split(arg, ty): 114 | fields = re.split(r'\s+', arg) 115 | return list(ty[x] for x in fields) 116 | 117 | (insn, slots, opfs, ty, subty, subst, result) = list( 118 | x.strip() for x in fmt.split(',')) 119 | slots = split(slots, ep_ct.slot_types) if slots != '_' else [] 120 | opfs = split(opfs, opnd_types) if opfs != '_' else [] 121 | subty = split(subty, subtypes) if subty != '_' else [] 122 | result = ep_ct.slot_types[result] 123 | 124 | return (insn, mips_insn( 125 | insn, slots, opfs, types[ty], subty, subst, result)) 126 | 127 | lines = [y for y in insn_fmts.splitlines() 128 | if re.search(r'^#|^$', y) is None] 129 | 130 | return dict(make_insn(x) for x in lines) 131 | 132 | def create_insn_type_table(insns, ty): 133 | '''{str : mips_insn} -> [insn_ty] -> frozenset(str)''' 134 | return frozenset(x.insn for x in insns.itervalues() if x.ty in ty) 135 | 136 | def create_insn_uses_opnd_type_table(insns, ty): 137 | return frozenset(x.insn for x in insns.itervalues() 138 | if filter(None, [ty == y for y in x.opfs])) 139 | 140 | insns = create_insn_table() 141 | 142 | # XXX MIPS III-specific stuff in here, e.g. ancient MIPS has load delays, but 143 | # newer MIPS does not 144 | delayed = create_insn_type_table( 145 | insns, [types.jump, types.fbranch, types.branch, types.call, types.jr]) 146 | has_special_opnd = create_insn_uses_opnd_type_table(insns, opnd_types.spec) 147 | has_imm = create_insn_uses_opnd_type_table(insns, opnd_types.imm) 148 | -------------------------------------------------------------------------------- /decomp/cpu/mips/abi/n32.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | from itertools import chain, izip 3 | from pycparser import c_ast 4 | from pyc_fmtstr_parser.printf_parse import printf_parse, Arg_type as p_Arg_type 5 | from pyc_fmtstr_parser.scanf_parse import scanf_parse, Arg_type as s_Arg_type 6 | from decomp import ida, utils 7 | from decomp.c import decl as cdecl, types as ep_ct 8 | from decomp.cpu import ida as cpu_ida, regs 9 | 10 | flatten = chain.from_iterable 11 | 12 | # MIPS N32 13 | # $v0,$v1, $a0..$a7 for return/args 14 | # $f0,$f2 and $f12..f19 for fp return/args 15 | 16 | class RegSpillError(Exception): pass 17 | class StructByValueError(Exception): pass 18 | 19 | # WARNING: this must be in the same order as c.types.ep_ctypes! 20 | # (pointer is intentionally missing) 21 | c_type_to_slot = zip( 22 | iter(ep_ct.ep_ctypes), 23 | [ep_ct.slot_to_typename[x] for x in 24 | [ep_ct.slot_types[y] for y in 25 | ['i8', # signed char 26 | 'u8', # unsigned char 27 | 'i16', # short 28 | 'u16', # unsigned short 29 | 'i32', # int 30 | 'u32', # unsigned int 31 | 'i32', # long 32 | 'u32', # unsigned long 33 | 'i64', # long long 34 | 'u64', # unsigned long long 35 | 's', # float 36 | 'd', # double 37 | 'i8' # char 38 | ]]]) 39 | 40 | def make_stdio_sw(fmt_type, types, pointerize): 41 | '''enum -> [str] -> bool -> dict''' 42 | # the printf/scanf parsers can parse nearly all format string types, but we 43 | # do not handle all of them here 44 | fmt_to_type = izip([fmt_type[x] for x in types], 45 | c_type_to_slot) 46 | 47 | return {ty : (ep_ct.ptr(val) 48 | if pointerize is True 49 | else val) 50 | for (ty, (_, val)) in fmt_to_type} 51 | 52 | printf_types = [ 53 | 'TYPE_SCHAR', 'TYPE_UCHAR', 'TYPE_SHORT', 'TYPE_USHORT', 54 | 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONGINT', 'TYPE_ULONGINT', 55 | 'TYPE_LONGLONGINT', 'TYPE_ULONGLONGINT', 'TYPE_DOUBLE', 56 | 'TYPE_DOUBLE', 'TYPE_CHAR' 57 | ] 58 | 59 | scanf_types = [ 60 | 'TYPE_SCHAR', 'TYPE_UCHAR', 'TYPE_SHORT', 'TYPE_USHORT', 61 | 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONGINT', 'TYPE_ULONGINT', 62 | 'TYPE_LONGLONGINT', 'TYPE_ULONGLONGINT', 'TYPE_FLOAT', 63 | 'TYPE_DOUBLE', 'TYPE_CHAR' 64 | ] 65 | 66 | printf_sw = make_stdio_sw(p_Arg_type, printf_types, pointerize=False) 67 | printf_sw[p_Arg_type.TYPE_POINTER] = ep_ct.ptr( 68 | ep_ct.simple_typename(['void'])) 69 | printf_sw[p_Arg_type.TYPE_STRING] = ep_ct.ptr( 70 | ep_ct.simple_typename(['char'])) 71 | 72 | scanf_sw = make_stdio_sw(s_Arg_type, scanf_types, pointerize=True) 73 | scanf_sw[s_Arg_type.TYPE_POINTER] = ep_ct.ptr(ep_ct.ptr( 74 | ep_ct.simple_typename(['void']))) 75 | scanf_sw[s_Arg_type.TYPE_STRING] = ep_ct.ptr( 76 | ep_ct.simple_typename(['char'])) 77 | scanf_sw[s_Arg_type.TYPE_CHARSEQ] = scanf_sw[s_Arg_type.TYPE_STRING] 78 | 79 | def n32ify_regs(regs): 80 | '''[str] -> [str]''' 81 | n32_map = {'$t0' : '$a4', '$t1' : '$a5', '$t2' : '$a6', '$t3' : '$a7'} 82 | r = enumerate(regs) 83 | 84 | return list(n32_map[reg] if reg in n32_map else regs[i] for (i, reg) in r) 85 | 86 | # fix up IDA's register list for N32 87 | reg_list = n32ify_regs(cpu_ida.ida_reg_list()) 88 | # offset of beginning of FPR regs in IDA's list 89 | fpr_off = reg_list.index('$f0') 90 | # callee-saved registers 91 | saveregs = frozenset(flatten([ 92 | xrange(16, 24), # $s0..$s7 93 | xrange(28, 31), # $gp, $sp, $fp 94 | xrange(fpr_off + 20, fpr_off + 32, 2) # $f20..$f31, evens 95 | ])) 96 | 97 | # gpr and fpr argument and return registers 98 | arg_regs = list(xrange(4, 12)) # $a0..$a7 99 | fp_arg_regs = list(xrange(fpr_off + 12, fpr_off + 20)) # $f12..$f19 100 | ret_regs = list([2, 3]) # $v0..$v1 101 | fp_ret_regs = list([fpr_off, fpr_off + 2]) # $f0,$f2 102 | 103 | # registers that we pass via the ARGS struct 104 | regs_by_reference = frozenset(arg_regs + fp_arg_regs + ret_regs + fp_ret_regs) 105 | 106 | def type_to_reg_and_slot(node, chooser, i): 107 | '''c_ast -> fn -> int -> (reg_type, slot_type) | None''' 108 | def yield_void(): 109 | # return an empty list for (void) arglists 110 | raise StopIteration 111 | 112 | def maybe_fail(node): 113 | if type(node) is c_ast.Struct: 114 | raise StructByValueError('structs by value not yet supported') 115 | return type_to_reg_and_slot(node.type, chooser, i) 116 | 117 | def get(names): 118 | '''[str] -> (gpr|fpr, slot_ty)''' 119 | if 'void' in names: 120 | return yield_void() 121 | 122 | ti = ida.parse_decl(' '.join(names)) 123 | (ty, base, slot) = chooser(ti) 124 | return (ty(base + i), slot) 125 | 126 | sw = { 127 | c_ast.Decl : lambda x: type_to_reg_and_slot(x.type, chooser, i), 128 | c_ast.TypeDecl : lambda x: type_to_reg_and_slot(x.type, chooser, i), 129 | c_ast.Typename : lambda x: type_to_reg_and_slot(x.type, chooser, i), 130 | c_ast.IdentifierType : lambda x: get(x.names) 131 | } 132 | 133 | if i > 7: 134 | raise RegSpillError('spilling registers to stack not yet supported') 135 | 136 | # in order to use chooser we need a tinfo_t--make one suitable for an 137 | # an int (which is also suitable for a pointer on N32) 138 | dummy_ti = ida.parse_decl('int') 139 | 140 | (_, base, _) = chooser(dummy_ti) 141 | node_ty = type(node) 142 | 143 | if node_ty in [c_ast.ArrayDecl, c_ast.PtrDecl]: 144 | return (regs.gpr(base + i), ep_ct.slot_types.u64) 145 | elif node_ty is c_ast.Enum: 146 | return (regs.gpr(base + i), ep_ct.slot_types.i64) 147 | else: 148 | return utils.dictswitch(node_ty, sw, node, maybe_fail, node) 149 | 150 | def get_info_for_types(nodes, caster, chooser, pos=0, handle_va=False): 151 | '''[c_ast] -> fn -> fn -> int -> bool -> 152 | (reg_type, slot_type) | c_ast.EllipsisParam | None''' 153 | # nodes: a list of Decls from a FuncDecl 154 | # caster: use this function to produce casts to arg types (see 'castify' in 155 | # c.decl) 156 | # chooser: a function that will determine the register number for a return 157 | # value or argument 158 | # pos: number of a positional argument (0-indexed) 159 | # handle_va: pass False if making the initial list of function signatures 160 | # from; pass True if we want variable arguments to be processed 161 | return [c_ast.EllipsisParam 162 | if (handle_va is False and 163 | type(node) is c_ast.EllipsisParam) 164 | else 165 | type_to_reg_and_slot(node, chooser, i) + (caster(node),) 166 | for (i, node) in enumerate(nodes, pos)] 167 | 168 | def va_chooser(gpr_base, _, ti): 169 | '''int -> int -> tinfo_t -> (type, int, slot_ty)''' 170 | if ti.is_float(): 171 | slot = ep_ct.slot_types.s 172 | elif ti.is_double(): 173 | slot = ep_ct.slot_types.d 174 | else: 175 | slot = ep_ct.slot_types.u64 176 | return (regs.gpr, gpr_base, slot) 177 | 178 | def pos_chooser(gpr_base, fpr_base, ti): 179 | '''int -> int -> tinfo_t -> (type, int, slot_ty)''' 180 | if ti.is_float(): 181 | return (regs.fpr, fpr_base, ep_ct.slot_types.s) 182 | elif ti.is_double(): 183 | return (regs.fpr, fpr_base, ep_ct.slot_types.d) 184 | else: 185 | return (regs.gpr, gpr_base, ep_ct.slot_types.u64) 186 | 187 | pos_wrap = partial(pos_chooser, 4, 12) 188 | # varargs of *any* type are passed in $a0..$a7 on N32 (the second argument to 189 | # the partially-applied va_chooser is unused) 190 | va_wrap = partial(va_chooser, 4, 12) 191 | 192 | def get_abi_fn_arg_map(node): 193 | '''c_ast -> fn_sig''' 194 | # non-fp args are returned in $2..$3, fp-args in $f0,$f2 195 | # XXX multi-reg returns are not supported, but this is rare 196 | ret_chooser = partial(pos_chooser, 2, 0) 197 | caster = lambda x: cdecl.castify(x.type) 198 | rtype = utils.items_or_default( 199 | lambda: get_info_for_types([node], caster, ret_chooser)[0], 200 | None) # if void return type, return None 201 | 202 | args = [x for (_, x) in node.args.children()] 203 | arg_types = utils.items_or_default( 204 | lambda: list(get_info_for_types(args, caster, pos_wrap)), 205 | []) # if function takes no args, return empty list 206 | 207 | return ep_ct.fn_sig(rtype, arg_types) 208 | 209 | def get_args_for_va_function(callee, pos_arg): 210 | '''str -> str -> [(reg_type, slot_type) | None]''' 211 | def get_convs(acc, va_arg): 212 | return acc + [sw[va_arg.type]] 213 | 214 | pos_sw = {'printf' : (1, printf_sw, printf_parse, va_wrap), 215 | 'scanf' : (1, scanf_sw, scanf_parse, pos_wrap), 216 | 'sscanf' : (2, scanf_sw, scanf_parse, pos_wrap)} 217 | try: 218 | (pos, sw, fn, chooser) = pos_sw[callee] 219 | except KeyError: 220 | raise utils.BugError('unrecognized callee %s' % callee) 221 | 222 | (_, args) = fn(pos_arg) 223 | convs = reduce(get_convs, args.arg, []) 224 | 225 | return list(get_info_for_types( 226 | convs, lambda x: x, chooser, pos=pos, handle_va=True)) 227 | -------------------------------------------------------------------------------- /decomp/ida.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | import itertools, re, sys 3 | from flufl.enum import Enum 4 | 5 | try: 6 | import idaapi, idautils, idc 7 | except ImportError: 8 | pass 9 | else: 10 | from idaapi import (get_func, 11 | o_imm, 12 | o_displ, 13 | BADADDR, 14 | get_func_name, 15 | is_ret_insn, 16 | netnode, 17 | is_ret_insn, 18 | next_head, 19 | tinfo_t, 20 | parse_decl2, 21 | cvar, 22 | array_type_data_t, 23 | can_be_off32) 24 | from idautils import (DataRefsTo as data_refs_to, 25 | DecodeInstruction as decode_instruction, 26 | Heads as heads, 27 | CodeRefsFrom as code_refs_from) 28 | from idc import (Name as name, 29 | SegByBase as seg_by_base, 30 | GetType as get_type, 31 | SegName as seg_name, 32 | Byte as byte, 33 | Word as word, 34 | Dword as dword, 35 | Qword as qword, 36 | GetFloat as get_float, 37 | GetDouble as get_double, 38 | GetString as get_string, 39 | GuessType as guess_type, 40 | ItemEnd as item_end, 41 | ItemHead as item_head, 42 | LocByName as loc_by_name, 43 | PrevHead as prev_head, 44 | atoa, 45 | SegByName as seg_by_name) 46 | 47 | from decomp import utils 48 | from decomp.c import decl as cdecl 49 | from decomp.cpu import ida as cpu_ida, regs 50 | 51 | class OperandUnresolvableError(Exception): pass 52 | class NoSwitchError(Exception): pass 53 | class NoInsnError(Exception): pass 54 | class ParseDeclError(Exception): pass 55 | class NotArrayError(Exception): pass 56 | 57 | ### 58 | ### Functions for dealing with data from IDA 59 | ### 60 | 61 | flatten = itertools.chain.from_iterable 62 | 63 | sw_cases = namedtuple('sw_cases', ['default', 'cases']) 64 | 65 | discardable = namedtuple('discardable', ['addr']) 66 | displ = namedtuple('displ', ['reg', 'displ']) 67 | op_ret = namedtuple('op_ret', ['ty', 'val', 'target']) 68 | # XXX name types are awful! see fmt_op in decomp.cpu.mips.gen for more info. 69 | # actually, op_ty is a bug too; we should just be using IDA's tinfo_t as it 70 | # carries much more information. 71 | op_ty = Enum('op_ty', ['displ', 'value', 'name', 'reg', 'ptr', 'array', 'func']) 72 | 73 | def size_of(ti): 74 | '''tinfo_t -> int''' 75 | if ti.is_ptr(): 76 | ptr_ti = parse_decl('void *') 77 | size = ptr_ti.get_size() 78 | return size 79 | else: 80 | return ti.get_size() 81 | 82 | def print_tinfo(name, ti): 83 | '''str -> tinfo_t -> str''' 84 | return idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE | idaapi.PRTYPE_SEMI, 85 | ti, name, '') 86 | 87 | def print_type2(ea): 88 | '''ea_t -> str''' 89 | return idaapi.print_type2(ea, idaapi.PRTYPE_1LINE | idaapi.PRTYPE_SEMI) 90 | 91 | def parse_decl(arg): 92 | '''str -> tinfo_t''' 93 | ti = idaapi.tinfo_t() 94 | success = idaapi.parse_decl2(idaapi.cvar.idati, arg + ';', '', ti, 0) 95 | if success is False: 96 | raise ParseDeclError("%s: couldn't parse type" % arg) 97 | return ti 98 | 99 | def ea_list_from_segs(segs): 100 | '''[str] -> [(str, ea_t)]''' 101 | name_addr = [(idc.Name(addr), addr) for addr in 102 | flatten((idautils.Heads(addr, idc.SegEnd(addr))) 103 | for (_, addr) in segs)] 104 | 105 | return list(x for x in name_addr if x[0] != '') 106 | 107 | def get_or_guess_tinfo(ea): 108 | '''ea_t -> tinfo_t''' 109 | # XXX mutates (blah_tinfo2, unavoidable) 110 | ti = idaapi.tinfo_t() 111 | idaapi.get_tinfo2(ea, ti) or idaapi.guess_tinfo2(ea, ti) 112 | 113 | return ti 114 | 115 | def name_of_head(ea): 116 | '''ea -> str''' 117 | return idc.Name(idc.ItemHead(ea)) 118 | 119 | def mips_op_hack(cmd, op): 120 | '''insn_t -> int''' 121 | # see note for get_operands 122 | if cpu_ida.ida_current_cpu_name() == 'mips': 123 | mnem = get_mnem(cmd.ea) 124 | if (len(cpu_ida.ida_current_cpu().insns.insns[mnem].opfs) != 125 | len(ida_operands(cmd))): 126 | if op > 0: 127 | return op - 1 128 | else: 129 | return op 130 | else: 131 | return op 132 | else: 133 | return op 134 | 135 | def ida_operands(cmd): 136 | '''insn_t -> [op_t]''' 137 | return list(x for x in cmd.Operands if x.type != idaapi.o_void) 138 | 139 | def get_operands(cmd): 140 | '''insn_t -> [op_t]''' 141 | opnds = ida_operands(cmd) 142 | 143 | if cpu_ida.ida_current_cpu_name() == 'mips': 144 | # IDA returns "simplified" instructions with only two operands when the 145 | # first and second operands are the same register, but this forces you 146 | # to handle multiple formats for a single instruction, so here we 147 | # transform them into their canonical form 148 | mnem = get_mnem(cmd.ea) 149 | 150 | if len(cpu_ida.ida_current_cpu().insns.insns[mnem].opfs) != len(opnds): 151 | return [opnds[0], opnds[0], opnds[1]] 152 | else: 153 | return opnds 154 | else: 155 | return opnds 156 | 157 | def get_stkvar_map(ea): 158 | '''ea_t -> {int : (str, tinfo_t)}''' 159 | # NOTE mutates d 160 | frame = idaapi.get_frame(ea) 161 | 162 | def make_map(d, (off, name, _)): 163 | mem = idaapi.get_member(frame, off) 164 | ti = idaapi.tinfo_t() 165 | idaapi.get_or_guess_member_tinfo2(mem, ti) 166 | d[off] = (name, ti) 167 | return d 168 | 169 | return reduce(make_map, idautils.StructMembers(frame.id), {}) 170 | 171 | def get_mnem(ea): 172 | '''ea -> str''' 173 | mnem = re.search(r'^([a-zA-Z0-9.]+)', idc.GetDisasm(ea)) 174 | if mnem is None: 175 | raise NoInsnError("can't get insn at %s" % ida.atoa(ea)) 176 | else: 177 | return mnem.groups()[0] 178 | 179 | def array_details(ti): 180 | if ti.is_array() is False: 181 | raise NotArrayError('ti is not an array') 182 | ai = idaapi.array_type_data_t() 183 | ti.get_array_details(ai) 184 | return ai 185 | 186 | def array_elem_size(ti): 187 | '''tinfo_t -> int''' 188 | ai = array_details(ti) 189 | size = ai.elem_type.get_size() 190 | return size 191 | 192 | def item_off(ea): 193 | '''ea_t -> (int, int)''' 194 | head = idc.ItemHead(ea) 195 | end = idc.ItemEnd(head) 196 | ti = get_or_guess_tinfo(head) 197 | try: 198 | size = array_elem_size(ti) 199 | except NotArrayError: 200 | size = ti.get_size() 201 | diff = ea - head 202 | idx = diff / size 203 | rem = diff % size 204 | 205 | return (idx, rem) 206 | 207 | def op_ret_for_ti(ti, name, target, val): 208 | '''tinfo_t -> str -> int -> int -> op_ret''' 209 | if ti.is_array(): 210 | return op_ret(op_ty.array, name, target) 211 | elif ti.is_ptr(): 212 | return op_ret(op_ty.ptr, name, target) 213 | elif ti.is_func(): 214 | return op_ret(op_ty.func, name, target) 215 | elif name != '': # XXX name types are a misfeature, see mips/gen.py 216 | return op_ret(op_ty.name, name, target) 217 | else: 218 | if cpu_ida.ida_current_cpu_name() == 'mips': 219 | return op_ret(op_ty.value, 220 | cpu_ida.ida_current_cpu().data.interpret_li_arg(val), 221 | 0) 222 | else: 223 | return op_ret(op_ty.value, val, 0) 224 | 225 | def resolve_opnd(target, val): 226 | '''ea_t -> str | int -> op_ret''' # XXX probably wrong 227 | head = idc.ItemHead(target) 228 | name = idc.Name(head) 229 | ti = get_or_guess_tinfo(head) 230 | return op_ret_for_ti(ti, name, target, val) 231 | 232 | def get_op(ea, op, stkvars=None): 233 | '''ea_t -> int -> opt:{int : tinfo_t} -> op_ret''' 234 | cmd = idautils.DecodeInstruction(ea) 235 | cmd.Operands = get_operands(cmd) # for mips_op_hack 236 | op = mips_op_hack(cmd, op) 237 | opd = cmd[op] 238 | 239 | if opd.type == idaapi.o_reg: # gpr, XXX sorta MIPS-specific 240 | return op_ret(op_ty.reg, regs.gpr(opd.reg), 0) 241 | elif opd.type == idaapi.o_idpspec1: # fpr, XXX sorta MIPS-specific 242 | return op_ret(op_ty.reg, regs.fpr(opd.reg), 0) 243 | elif opd.type in [idaapi.o_near, idaapi.o_mem]: 244 | return op_ret(op_ty.name, idc.Name(opd.addr), 0) 245 | elif idc.isStkvar1(idc.GetFlags(ea)): 246 | # IDA seems to set this flag even for operands beyond the second, 247 | # i.e. both of these are true for isStkvar1: 248 | # .text:10003A84 sd $a1, 0x2E0+var_58($sp) 249 | # .text:10003A68 addiu $a1, $sp, 0x2E0+var_2D8 250 | try: 251 | func = idaapi.get_func(ea) 252 | off = idaapi.calc_stkvar_struc_offset(func, ea, op) 253 | (name, ti) = stkvars[off] 254 | 255 | return op_ret_for_ti(ti, name, off, off) 256 | except KeyError: 257 | raise OperandUnresolvableError( 258 | 'unable to get operand %u at %s' % (op, idc.atoa(ea))) 259 | elif opd.type in [idaapi.o_imm, idaapi.o_displ]: 260 | return cpu_ida.ida_current_cpu().data.get_op_addrmode(ea, op, cmd) 261 | else: 262 | raise OperandUnresolvableError( 263 | 'unable to get operand %u at %s' % (op, idc.atoa(ea))) 264 | 265 | def calc_target(from_, ea, n, opval): 266 | '''ea_t -> ea_t -> int -> int -> ea_t''' 267 | return idaapi.calc_target( 268 | from_, ea, mips_op_hack(idautils.DecodeInstruction(ea), n), opval) 269 | 270 | def get_switch_info(ea): 271 | '''ea_t -> switch_info_ex_t''' 272 | sw = idaapi.get_switch_info_ex(ea) 273 | if sw is None: 274 | raise NoSwitchError('ea at %s has no switch info' % atoa(ea)) 275 | else: 276 | return sw 277 | 278 | def switch_cases(ea): 279 | '''ea_t -> {int : ea_t}''' 280 | # NOTE mutates d 281 | sw = get_switch_info(ea) 282 | ct = idaapi.calc_switch_cases(ea, sw) 283 | 284 | def make_cases(d, (case, target)): 285 | # this is lame, but the only way IDA marks the default case other than 286 | # by adding a comment like "jumptable ADDR default case" 287 | if idc.Name(target).startswith('def_'): 288 | d['default'] = target 289 | else: 290 | d['cases'][case] = target 291 | return d 292 | 293 | cases = reduce(make_cases, 294 | ((ct.cases[idx][cidx], ct.targets[idx]) 295 | for idx in xrange(len(ct.cases)) 296 | for cidx in xrange(len(ct.cases[idx]))), 297 | {'cases' : {}}) 298 | return sw_cases(cases['default'], cases['cases']) 299 | 300 | def is_switch_insn(ea): 301 | '''ea_t -> bool''' 302 | IM_SWITCH = 3 # IDA doesn't export this to python; hope it doesn't change! 303 | nn = idaapi.netnode('$ ignore micro') 304 | return nn.charval(ea, 0) == IM_SWITCH 305 | 306 | def get_opvals(ea, stkvars=None): 307 | '''ea_t -> stkvar_dict -> [op_ret]''' 308 | cmd = decode_instruction(ea) 309 | return list(get_op(ea, n, stkvars) for (n, _) in 310 | enumerate(get_operands(cmd))) 311 | -------------------------------------------------------------------------------- /decomp/cpu/mips/gen.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | from itertools import chain, izip 3 | import re 4 | from pycparser import c_ast 5 | from decomp import ida, utils 6 | from decomp.c import types as ep_ct 7 | from decomp.cpu import regs 8 | from decomp.cpu.mips import abi, data, insns 9 | 10 | next_ea_and_c = namedtuple('next_ea_and_c', ['next_ea', 'c']) 11 | 12 | def reg_strip(arg): 13 | # generally here the "arg" is a register object whose __str__ will be called 14 | return re.sub(r'^\$', '', str(arg)) 15 | 16 | def fmt_reg(mnem, arg, slot=None): 17 | '''str -> int -> reg -> opt:slot_types -> str''' 18 | if arg == regs.gpr(0): 19 | return c_ast.Constant('int', '0') 20 | else: 21 | insn = insns.insns[mnem] 22 | stripped = reg_strip(arg) 23 | # XXX FIXME: we store the register gpr/fpr register number, but 24 | # regs_by_reference is offsets into IDA's register list 25 | regnum = arg.reg + (abi.fpr_off if type(arg) is regs.fpr else 0) 26 | if regnum in abi.regs_by_reference: 27 | # refer to argument via ARGS-> 28 | r = c_ast.StructRef(c_ast.ID(utils.args_tag), '->', 29 | c_ast.ID(stripped)) 30 | else: 31 | r = c_ast.ID(stripped) 32 | 33 | if slot is not None and slot != ep_ct.slot_types._: 34 | # use a union slot 35 | return c_ast.StructRef(r, '.', c_ast.ID(slot.name)) 36 | else: 37 | return r 38 | 39 | def fmt_op(arg, mnem, op=None): 40 | '''op_ty -> str -> opt:int -> c_ast()''' 41 | insn = insns.insns[mnem] 42 | 43 | def addrof_or_deref(arg): 44 | # since addiu cannot touch memory, it must be calculating an address 45 | if mnem == 'addiu' or (insn.ty == insns.types.usefn and 46 | insn.subst == 'memcpy'): 47 | return c_ast.UnaryOp('&', arg) 48 | else: 49 | return arg 50 | 51 | if arg.ty == ida.op_ty.reg: 52 | try: 53 | slot = insn.slots[op] 54 | except IndexError: 55 | slot = None 56 | reg = fmt_reg(mnem, arg.val, slot) 57 | if insn.ty == insns.types.usefn and insn.subst == 'memcpy': 58 | return c_ast.UnaryOp('&', reg) 59 | else: 60 | return reg 61 | 62 | if mnem == 'la': 63 | # XXX the "name" type is neither suitable for a decompiler nor a 64 | # braindead static translator such as this one. i.e., in order to 65 | # translate to C, we have no choice but to deal with C's type system, 66 | # because things like "la ptr" should be translated as "reg = ptr", but 67 | # "la not_ptr" should be translated as "reg = ¬_ptr" 68 | if arg.ty in [ida.op_ty.array, ida.op_ty.ptr]: 69 | return c_ast.ID(arg.val) 70 | elif arg.ty == ida.op_ty.name: 71 | return c_ast.UnaryOp('&', c_ast.ID(arg.val)) 72 | else: # an address 73 | return c_ast.Constant('int', str(arg.val)) 74 | elif arg.ty == ida.op_ty.array: 75 | (idx, rem) = ida.item_off(arg.target) 76 | arr = c_ast.ArrayRef(c_ast.ID(arg.val), c_ast.Constant('int', 77 | str(idx))) 78 | 79 | return addrof_or_deref(arr) 80 | # retained in case we ever come across some strange pointer math. this 81 | # will generate a nonsense lvalue anyway, so we'd need to handle it some 82 | # other way 83 | #left = addrof_or_deref(arr) 84 | #return c_ast.BinaryOp('+', left, c_ast.Constant('int', str(rem))) 85 | elif arg.ty == ida.op_ty.ptr: 86 | # dereferencing of pointers is handled by the "displ" case, so just 87 | # return an address here too 88 | (_, rem) = ida.item_off(arg.target) 89 | 90 | return c_ast.ID(arg.val) 91 | # same as above 92 | #return c_ast.BinaryOp('+', 93 | # c_ast.ID(arg.val), 94 | # c_ast.Constant('int', str(rem))) 95 | elif arg.ty == ida.op_ty.name: 96 | nameval = c_ast.ID(arg.val) 97 | return addrof_or_deref(nameval) 98 | elif arg.ty == ida.op_ty.displ: 99 | r = fmt_reg(mnem, arg.val.reg, ep_ct.slot_types.u32) 100 | off = c_ast.BinaryOp( 101 | '+', r, c_ast.Constant('int', str(arg.val.displ))) 102 | tyns = ['char' if insns.types.usefn and insn.subst == 'memcpy' 103 | else insn.subst] 104 | cast = ep_ct.simple_cast(ep_ct.ptr(ep_ct.simple_typename(tyns)), off) 105 | 106 | if insn.ty == insns.types.usefn and insn.subst == 'memcpy': 107 | return cast 108 | else: 109 | return c_ast.UnaryOp('*', cast) 110 | else: 111 | return c_ast.Constant('int', str(arg.val)) 112 | 113 | def do_fbranch(**kw): 114 | return c_ast.If(c_ast.ID(kw['subst']), ep_ct.do_jump(**kw), None) 115 | 116 | def do_fcmp(**kw): 117 | #if ({rs} {subst} {rt}) fp_cond = 1; else fp_cond = 0 118 | fragment = ep_ct.do_branch(**kw) 119 | fragment.iftrue = ep_ct.do_assign( 120 | rt=c_ast.ID('%sfp_cond' % utils.decomp_tag), 121 | op=c_ast.Constant('int', '1')) 122 | fragment.iffalse = ep_ct.do_assign( 123 | rt=c_ast.ID('%sfp_cond' % utils.decomp_tag), 124 | op=c_ast.Constant('int', '0')) 125 | return fragment 126 | 127 | def do_slt(**kw): 128 | #if (({subst}){rs} < ({subst}){rt}) {rd} = 1; else {rd} = 0; 129 | def cast(which): 130 | return ep_ct.simple_cast(ep_ct.simple_typename([kw['subst']]), 131 | which) 132 | 133 | def assign(to): 134 | return ep_ct.do_assign(rt=kw['rd'], 135 | op=c_ast.Constant('int', to)) 136 | 137 | br = ep_ct.do_branch(subst='<', rs=cast(kw['rs']), rt=cast(kw['rt'])) 138 | br.iftrue = assign('1') 139 | br.iffalse = assign('0') 140 | 141 | return br 142 | 143 | def do_store(**kw): 144 | #{op} = {rt} 145 | return ep_ct.do_assign(rt=kw['op'], op=kw['rt']) 146 | 147 | def do_lui(**kw): 148 | #{rt} = {op} << 16 149 | return ep_ct.do_assign(rt=kw['rt'], op=ep_ct.simple_cast( 150 | ep_ct.slot_to_typename[kw['result']], 151 | c_ast.BinaryOp( 152 | '<<', kw['op'], c_ast.Constant('int', '16')))) 153 | 154 | def create_insn_to_c_table(tbl): 155 | '''{str : mips_insn} -> {str : fun}''' 156 | insn_tmpls = { 157 | insns.types.op : ep_ct.do_op, 158 | insns.types.jump : ep_ct.do_jump, 159 | insns.types.fbranch : do_fbranch, 160 | # as branch likely complicates things, "branch" is a partial template 161 | insns.types.branch : ep_ct.do_branch, #'if ({rs} {subst} {rt})', 162 | insns.types.fcmp : do_fcmp, 163 | insns.types.load : ep_ct.do_assign, 164 | insns.types.store : do_store, 165 | insns.types.nop : ep_ct.do_nop, 166 | insns.types.slt : do_slt, 167 | insns.types.la : ep_ct.do_assign, 168 | insns.types.li : ep_ct.do_assign, 169 | insns.types.lui : do_lui 170 | } 171 | 172 | return {x.insn : insn_tmpls[x.ty] for x in tbl.itervalues() 173 | if x.ty not in [insns.types.usefn, insns.types.call, 174 | insns.types.jr]} 175 | 176 | insns_c = create_insn_to_c_table(insns.insns) 177 | 178 | def extern_call(callee, sig, mnem, ea): 179 | '''str -> fn_sig -> str -> ea_t -> c_ast''' 180 | # generate an ast node for a call to an external function 181 | def fmt_reg_for_call(reg, slot, node): 182 | '''reg -> slot_ty -> c_ast -> c_ast''' 183 | reg_ast = fmt_reg(mnem, reg, slot) 184 | return ep_ct.simple_cast(node, reg_ast) 185 | 186 | if sig.arg_regs == []: 187 | fn_args = None 188 | else: 189 | if sig.arg_regs[-1] is c_ast.EllipsisParam: 190 | va_arg = data.get_arg_for_va_function(callee, ea) 191 | params = (list(utils.init(sig.arg_regs)) 192 | + abi.get_args_for_va_function(callee, va_arg)) 193 | else: 194 | params = sig.arg_regs 195 | 196 | fn_args = ep_ct.args_for_call( 197 | list(fmt_reg_for_call(reg, slot, node) 198 | for (reg, slot, node) in params)) 199 | 200 | if sig.return_type is None: 201 | return ep_ct.make_call(callee, args=fn_args) 202 | else: 203 | (reg, slot, rtype) = sig.return_type 204 | ret_reg = fmt_reg(mnem, reg, slot) 205 | return ep_ct.make_call(callee, ret_reg=ret_reg, args=fn_args, 206 | for_extern=rtype) 207 | 208 | def do_switch_or_return(ea): 209 | if ida.is_ret_insn(ea): 210 | return c_ast.Return(None) 211 | else: # switch 212 | try: 213 | sw = ida.switch_cases(ea) 214 | except ida.NoSwitchError: 215 | raise utils.BugError('unhandled jr at ea %s' % ida.atoa(ea)) 216 | 217 | default = sw.default 218 | defexpr = [c_ast.Default([c_ast.Goto(ida.name(default))])] 219 | cases = list(c_ast.Case(c_ast.Constant('int', str(addr)), 220 | [c_ast.Goto(ida.name(loc))]) 221 | for (addr, loc) in sw.cases.iteritems()) 222 | (mnem, opnd, opn) = data.get_swval(ea) 223 | swval = fmt_op(opnd, mnem, opn) 224 | return c_ast.Switch(swval, 225 | c_ast.Compound( 226 | cases + defexpr)) 227 | 228 | def get_formatter(mnem): 229 | '''str -> fn''' 230 | try: 231 | return insns_c[mnem] 232 | except KeyError: 233 | raise utils.BugError("%s: couldn't find formatter" % mnem) 234 | 235 | def make_args_for_formatter(insn, vals): 236 | '''mips_insn -> -> []''' 237 | # takes list of values from fmt_op for the formatter's consumption 238 | def simple_2op(insn, opvals): 239 | # cast the rvalue to the lvalue's type to avoid a warning for la 240 | # XXX do lw too? 241 | # 242 | # XXX we should also handle sw here, but op_ty doesn't carry enough 243 | # information to be able to do this. see decomp.ida for why op_ty 244 | # sucks. we need to be able to cast to the type of the lvalue, but 245 | # op_ty's knowledge of types isn't expressive enough 246 | op = (ep_ct.cast_to_dest_reg(insn, opvals[1]) 247 | if insn.insn == 'la' 248 | else opvals[1]) 249 | return dict(izip(['result', 'rt', 'op'], 250 | [insn.result, opvals[0], op])) 251 | 252 | def subst_rs_rt(insn, opvals): 253 | rt = (c_ast.Constant('int', '0') 254 | if insns.subtypes.zero in insn.subty # for beqz, bgez, etc. 255 | else opvals[1]) 256 | return dict(izip(['subst', 'rs', 'rt'], 257 | [insn.subst, opvals[0], rt])) 258 | 259 | subst_3op = lambda insn, opvals: dict( 260 | izip(['subst', 'result', 'rd', 'rs', 'rt'], 261 | [insn.subst, insn.result] + opvals)) 262 | sw = { 263 | insns.types.op : subst_3op, 264 | insns.types.jump : lambda insn, opvals: dict( 265 | izip(['loc'], opvals)), 266 | insns.types.fbranch : lambda insn, opvals: dict( 267 | izip(['subst', 'loc'], 268 | [insn.subst] + opvals)), 269 | insns.types.branch : subst_rs_rt, 270 | insns.types.fcmp : subst_rs_rt, 271 | insns.types.load : simple_2op, 272 | insns.types.store : simple_2op, 273 | insns.types.slt : subst_3op, 274 | insns.types.la : simple_2op, 275 | insns.types.li : simple_2op, 276 | insns.types.lui : simple_2op, 277 | insns.types.call : lambda insn, opvals: dict( 278 | izip(['rs'], opvals)) 279 | } 280 | try: 281 | return sw[insn.ty](insn, vals) 282 | except KeyError: 283 | return {} 284 | 285 | def fmt_insn(ea, our_fns, extern_reg_map, stkvars, from_delay): 286 | '''ea_t -> frozenset(str) -> {str : reg_sig} -> {int : c_ast()} -> 287 | (ea_t, str)''' 288 | # XXX this function is too long and its interaction with the formatter steps 289 | # is not very clear 290 | # NOTE mutation in a few places 291 | # 292 | # we cannot rely simply on IDA's disassembly when generating C. e.g.: 293 | # 294 | # .text:100052F4 lwc1 $f12, (square - 0x10008E50)($s1) 295 | # 296 | # THIS means f12 = square[0] (square is declared as an array). but... 297 | # 298 | # .text:100041A4 lw $a1, (seqList - 0x1000BF78)($a1) 299 | # 300 | # THIS means a1 = seqList--NOT *seqList or seqList[0]. GetOperand and 301 | # similar functions are thus useless for our purposes. unfortunately, we 302 | # have no choice but to handle C's type system in order to emit C from 303 | # disassembly. we don't COMPLETELY handle it (patches welcome!!!1), but we 304 | # do achieve enough that with minor database annotations we have a POC in 305 | # our chosen target. 306 | def labelize(ea, stmt): 307 | if from_delay is False: 308 | label = ida.name(ea) 309 | if label != '': 310 | return c_ast.Label(label, stmt) 311 | else: 312 | return stmt 313 | else: 314 | return stmt 315 | 316 | fn = ida.get_func(ea) 317 | fn_name = ida.get_func_name(ea) 318 | fn_end = fn.endEA 319 | mnem = ida.get_mnem(ea) 320 | insn = insns.insns[mnem] 321 | is_delayed = mnem in insns.delayed 322 | delay_ea = ida.next_head(ea, fn_end) 323 | next_ea = (delay_ea 324 | if is_delayed is False 325 | else ida.next_head(delay_ea, fn_end)) 326 | 327 | if ida.is_switch_insn(ea) is True: 328 | # don't emit stmts that IDA marks as being part of a switch idiom 329 | # 330 | # pass delay_ea as the next ea to check, because we may have a case in 331 | # which a non-switch insn follows a delayed switch insn 332 | return next_ea_and_c(delay_ea, [labelize(ea, c_ast.EmptyStatement())]) 333 | 334 | opvals = ida.get_opvals(ea, stkvars) 335 | 336 | # addiu has many forms, some of which require transformation into 337 | # two-operand statements, others which need to be kept as three-operand 338 | # statements, so we have to handle it here, not fmt_op 339 | # 340 | # we can elide a previous modification to that register within a basic 341 | # block if it has no uses between a modification and the addiu, though we 342 | # don't yet do this 343 | if mnem == 'addiu' and opvals[-1].ty != ida.op_ty.value: 344 | # handles cases where addiu is effectively an assignment (e.g. when 345 | # used for address calculation) 346 | 347 | # first op is always a register 348 | reg = fmt_op(opvals[0], mnem, 0) 349 | # any non-number as the final operand should be handled according to 350 | # fmt_op's usual rules 351 | arg = fmt_op(opvals[-1], mnem) 352 | assign = labelize( 353 | ea, 354 | ep_ct.do_assign(rt=reg, op=ep_ct.cast_to_dest_reg(insn, arg))) 355 | return next_ea_and_c(next_ea, [assign]) 356 | 357 | if mnem == 'trunc.w.d': 358 | # emulate trunc.w.d with our function 359 | vals = [fmt_reg(mnem, opvals[0].val, insn.result), 360 | fmt_reg(mnem, opvals[1].val, insn.slots[0])] 361 | return next_ea_and_c( 362 | next_ea, 363 | [labelize( 364 | ea, 365 | ep_ct.make_call(insn.subst, ret_reg=vals[0], 366 | args=ep_ct.args_for_call([vals[1]])))]) 367 | elif mnem in ['jalr', 'jr']: 368 | # jalr and jr need special handling 369 | vals = [] 370 | else: 371 | vals = list(fmt_op(x, mnem, op) for (op, x) in enumerate(opvals)) 372 | 373 | if insn.ty == insns.types.usefn: 374 | if insn.subst == 'memcpy': 375 | # this should be redesigned to not use memcpy just to make the 376 | # generated code a little nicer, but the complexity hasn't been 377 | # worth it. the issue is: the fact that [ls][dw]c1 move data 378 | # between the fpu and memory is no guarantee that the data held in 379 | # an fpu register is actually a float or a double, which complicates 380 | # the logic a little bit. fortunately, we can just use memcpy 381 | # instead, and modern compilers will inline it so that it's 382 | # equivalent to a load/store for small sizes. 383 | if mnem in ['ldc1', 'sdc1']: 384 | size = 8 385 | elif mnem in ['lwc1', 'swc1']: 386 | size = 4 387 | else: 388 | raise utils.BugError('unhandled usefn insn %s' % mnem) 389 | 390 | # need to swap the order of arguments for a store, since loads and 391 | # stores are written in the same direction, but they aren't in C! 392 | args = list(reversed(vals) if mnem.startswith('s') else vals) 393 | return next_ea_and_c( 394 | next_ea, 395 | [labelize( 396 | ea, 397 | ep_ct.make_call( 398 | insn.subst, args=ep_ct.args_for_call( 399 | [args[0], 400 | args[1], 401 | c_ast.Constant('int', str(size))])))]) 402 | else: 403 | raise utils.BugError('unhandled usefn instruction %s' % mnem) 404 | else: 405 | args = make_args_for_formatter(insn, vals) 406 | 407 | if is_delayed is True: 408 | # format our delayed instruction before processing this instruction--but 409 | # see below for an important note about the case of branch likely 410 | (_, delay_slot) = fmt_insn(delay_ea, our_fns, extern_reg_map, stkvars, 411 | from_delay=True) 412 | # branch target 413 | loc = opvals[-1].val 414 | 415 | if mnem == 'jr': 416 | delayed = do_switch_or_return(ea) 417 | elif insn.ty == insns.types.call: 418 | callee = data.get_callee(ea, mnem, args) 419 | 420 | if callee in our_fns: 421 | delayed = ep_ct.internal_call(callee) 422 | else: # external function call 423 | try: 424 | sig = extern_reg_map[callee] 425 | except KeyError: 426 | # XXX we should really modify pycparser to allow insertion 427 | # of comments, as it would make the emitted codemuch easier 428 | # to follow. just alert the user that we couldn't make some 429 | # calls for now 430 | print ('/* %s: no regmap info, emitting empty stmt at %s */' 431 | % (callee, ida.atoa(ea))) 432 | delayed = ep_ct.do_nop() 433 | else: 434 | delayed = extern_call(callee, sig, mnem, ea) 435 | else: # some other sort of delayed insn 436 | delayed = get_formatter(mnem)(**args) 437 | 438 | goto = c_ast.Goto(loc) 439 | if insns.subtypes.likely in insn.subty: 440 | # for branch likely, the delay slot is NOT executed if the branch is 441 | # not taken 442 | delayed.iftrue = c_ast.Compound(delay_slot + 443 | [goto, 444 | labelize(delay_ea, delay_slot[0])]) 445 | ret = labelize(ea, delayed) 446 | else: 447 | if insn.ty in [insns.types.branch, insns.types.fbranch]: 448 | delayed.iftrue = c_ast.Compound(delay_slot + [goto]) 449 | delayed.iffalse = labelize(delay_ea, delay_slot[0]) 450 | ret = labelize(ea, delayed) 451 | else: 452 | ret = labelize(ea, 453 | c_ast.Compound([labelize(delay_ea, delay_slot[0]), 454 | delayed])) 455 | return next_ea_and_c(next_ea, [ret]) 456 | 457 | return next_ea_and_c(next_ea, [labelize(ea, get_formatter(mnem)(**args))]) 458 | -------------------------------------------------------------------------------- /notes/ep_new.asm: -------------------------------------------------------------------------------- 1 | # bgez 2 2 | # jal 1 3 | # c.le.d 2 4 | # move 2 5 | # bc1f 1 6 | # lbu 2 7 | # sw 2 8 | # add.d 2 9 | # bc1t 1 10 | # jalr 1 11 | # sub.s 2, 3 12 | # bnez 2 13 | # lwc1 2 14 | # slti 3 15 | # sra 3 16 | # dmtc1 2 17 | # beq 3 18 | # cvt.s.d 2 19 | # c.lt.d 2 20 | # c.eq.s 2 21 | # ldc1 2 22 | # c.le.s 2 23 | # dmfc1 2 24 | # mov.s 2 25 | # sdc1 2 26 | # addiu 2, 3 27 | # trunc.w.d 2 28 | # mul.d 2, 3 29 | # b 1 30 | # sll 2, 3 31 | # li 2 32 | # lw 2 33 | # jr 1 34 | # sd 2 35 | # nop 0 36 | # beqz 2 37 | # div.d 2, 3 38 | # bne 3 39 | # sltiu 3 40 | # subu 2, 3 41 | # cvt.d.s 2 42 | # mul.s 2, 3 43 | # bnezl 2 44 | # mtc1 2 45 | # la 2 46 | # c.lt.s 2 47 | # blez 2 48 | # addu 2, 3 49 | # slt 2, 3 50 | # sb 2 51 | # div.s 2 52 | # add.s 2, 3 53 | # xor 2, 3 54 | # lui 2 55 | # ld 2 56 | # cvt.s.w 2 57 | # mov.d 2 58 | # swc1 2 59 | # andi 2 60 | 61 | li $v0, 0xD980 62 | addu $at, $t9, $v0 63 | lwc1 $f7, (flt_10009290 - 0x10010F9C)($at) 64 | c.lt.s $f7, $f14 65 | ldc1 $f3, (dbl_100092D0 - 0x10010F9C)($at) 66 | bc1f loc_10003640 67 | lwc1 $f0, (flt_10009294 - 0x10010F9C)($at) 68 | add.s $f14, $f0 69 | mtc1 $zero, $f1 70 | nop 71 | c.lt.s $f14, $f1 72 | lwc1 $f0, (flt_1000929C - 0x10010F9C)($at) 73 | lwc1 $f5, (flt_100092A4 - 0x10010F9C)($at) 74 | bc1f loc_10003660 75 | lwc1 $f6, (flt_100092A0 - 0x10010F9C)($at) 76 | add.s $f14, $f7 77 | c.lt.s $f14, $f0 78 | nop 79 | bc1t loc_100036C0 80 | mov.s $f0, $f13 81 | c.lt.s $f14, $f6 82 | nop 83 | bc1t locret_100036E8 84 | nop 85 | c.lt.s $f14, $f5 86 | nop 87 | bc1f locret_100036B8 88 | mov.s $f0, $f12 89 | sub.s $f2, $f5, $f14 90 | cvt.d.s $f2, $f2 91 | div.d $f2, $f3 92 | sub.s $f1, $f13, $f12 93 | cvt.d.s $f1, $f1 94 | cvt.d.s $f0, $f12 95 | mul.d $f1, $f2 96 | add.d $f0, $f1 97 | jr $ra 98 | cvt.s.d $f0, $f0 99 | jr $ra 100 | nop 101 | ldc1 $f3, (dbl_100092D0 - 0x10010F9C)($at) 102 | cvt.d.s $f2, $f14 103 | div.d $f2, $f3 104 | sub.s $f1, $f13, $f12 105 | cvt.d.s $f1, $f1 106 | cvt.d.s $f0, $f12 107 | mul.d $f1, $f2 108 | add.d $f0, $f1 109 | jr $ra 110 | cvt.s.d $f0, $f0 111 | jr $ra 112 | nop 113 | lui $at, 1 114 | addiu $sp, -0x50 115 | li $at, 0xD8AC 116 | sd $gp, 0x50+var_20($sp) 117 | addu $gp, $t9, $at 118 | ldc1 $f1, dbl_100092D8 119 | cvt.d.s $f0, $f13 120 | sdc1 $f20, 0x50+var_18($sp) 121 | sd $s2, 0x50+var_28($sp) 122 | c.le.d $f0, $f1 123 | mov.s $f4, $f13 124 | sd $s1, 0x50+var_30($sp) 125 | mov.s $f5, $f12 126 | move $s1, $a5 127 | sd $s0, 0x50+var_38($sp) 128 | move $s0, $a4 129 | move $s2, $a3 130 | bc1f loc_10003748 131 | lwc1 $f6, flt_100092A8 132 | add.s $f20, $f14, $f6 133 | b loc_10003754 134 | mul.s $f20, $f13, $f20 135 | mul.s $f21, $f13, $f14 136 | add.s $f20, $f13, $f14 137 | sub.s $f20, $f21 138 | mtc1 $zero, $f23 139 | nop 140 | c.eq.s $f14, $f23 141 | nop 142 | bc1f loc_10003794 143 | sd $ra, 0x50+var_10($sp) 144 | swc1 $f4, 0($s1) 145 | swc1 $f4, 0($s0) 146 | swc1 $f4, 0($s2) 147 | ld $s0, 0x50+var_38($sp) 148 | ld $s1, 0x50+var_30($sp) 149 | ld $s2, 0x50+var_28($sp) 150 | ldc1 $f20, 0x50+var_18($sp) 151 | ld $gp, 0x50+var_20($sp) 152 | jr $ra 153 | addiu $sp, 0x50 154 | ldc1 $f15, dbl_100092E0 155 | cvt.d.s $f14, $f5 156 | mul.d $f14, $f15 157 | lwc1 $f12, flt_100092AC 158 | cvt.s.d $f14, $f14 159 | ldc1 $f15, dbl_100092E8 160 | sdc1 $f14, 0x50+var_50($sp) 161 | cvt.d.s $f14, $f14 162 | la $t9, value__GfN21 163 | mul.s $f12, $f4, $f12 164 | sdc1 $f14, 0x50+var_48($sp) 165 | add.d $f14, $f15 166 | sub.s $f12, $f20 167 | mov.s $f13, $f20 168 | sdc1 $f12, 0x50+var_40($sp) 169 | jal value__GfN21 170 | cvt.s.d $f14, $f14 171 | la $t9, value__GfN21 172 | swc1 $f0, 0($s2) 173 | ldc1 $f12, 0x50+var_40($sp) 174 | mov.s $f13, $f20 175 | jal value__GfN21 176 | ldc1 $f14, 0x50+var_50($sp) 177 | ldc1 $f15, dbl_100092F0 178 | ldc1 $f14, 0x50+var_48($sp) 179 | la $t9, value__GfN21 180 | add.d $f14, $f15 181 | ldc1 $f12, 0x50+var_40($sp) 182 | swc1 $f0, 0($s0) 183 | mov.s $f13, $f20 184 | jal value__GfN21 185 | cvt.s.d $f14, $f14 186 | ld $ra, 0x50+var_10($sp) 187 | b loc_10003778 188 | swc1 $f0, 0($s1) 189 | dmtc1 $zero, $f0 190 | addiu $sp, -0x20 191 | sdc1 $f30, 0x20+var_20($sp) 192 | cvt.d.s $f30, $f12 193 | c.lt.d $f0, $f30 194 | lui $at, 1 195 | sd $ra, 0x20+var_10($sp) 196 | li $at, 0xD77C 197 | sd $gp, 0x20+var_18($sp) 198 | bc1f loc_10003890 199 | addu $gp, $t9, $at 200 | la $t9, drand48 201 | jalr $t9 202 | nop 203 | la $t9, expm1 204 | jalr $t9 205 | mul.d $f12, $f0, $f30 206 | la $t9, expm1 207 | mov.d $f30, $f0 208 | jalr $t9 209 | ldc1 $f12, dbl_10009300 210 | div.d $f0, $f30, $f0 211 | ld $ra, 0x20+var_10($sp) 212 | ld $gp, 0x20+var_18($sp) 213 | ldc1 $f30, 0x20+var_20($sp) 214 | addiu $sp, 0x20 215 | jr $ra 216 | cvt.s.d $f0, $f0 217 | la $t9, __assert 218 | li $a2, 0x108 219 | la $a1, aEp_c 220 | jalr $t9 221 | la $a0, aM0_0 222 | b loc_10003850 223 | la $t9, drand48 224 | lui $v0, 1 225 | addiu $sp, -0x10 226 | li $v0, 0xD6F0 227 | sd $gp, 0x10+var_8($sp) 228 | addu $gp, $t9, $v0 229 | ldc1 $f1, dbl_10009300 230 | cvt.d.s $f0, $f12 231 | la $at, 0x10010000 232 | sd $ra, 0x10+var_10($sp) 233 | la $t9, glMultMatrixf 234 | addiu $at, (aflag - 0x10010000) 235 | add.d $f0, $f1 236 | swc1 $f13, (flt_10008EAC - 0x10008E48)($at) 237 | swc1 $f14, (flt_10008EC0 - 0x10008E48)($at) 238 | cvt.s.d $f0, $f0 239 | addiu $a0, $at, (flt_10008EA8 - 0x10008E48) 240 | jalr $t9 241 | swc1 $f0, (flt_10008EA8 - 0x10008E48)($at) 242 | ld $ra, 0x10+var_10($sp) 243 | ld $gp, 0x10+var_8($sp) 244 | jr $ra 245 | addiu $sp, 0x10 246 | sw $a0, 0x10($a1) 247 | lw $a4, 0x18($a0) 248 | beqz $a4, loc_10003994 249 | lwc1 $f4, 8($a1) 250 | lwc1 $f0, 8($a4) 251 | c.lt.s $f4, $f0 252 | nop 253 | bc1t loc_10003988 254 | lw $a3, 0x14($a4) 255 | beqz $a3, loc_100039A0 256 | nop 257 | lwc1 $f1, 8($a3) 258 | c.lt.s $f4, $f1 259 | nop 260 | bc1t loc_1000395C 261 | nop 262 | move $a4, $a3 263 | lw $a3, 0x14($a3) 264 | bnez $a3, loc_10003930 265 | nop 266 | b loc_10003968 267 | lw $at, 0x14($a1) 268 | sw $a3, 0x14($a1) 269 | sw $a1, 0x14($a4) 270 | lw $at, 0x14($a1) 271 | bnez $at, locret_10003980 272 | nop 273 | lw $v0, 0x20($a0) 274 | sw $a1, 0x14($v0) 275 | jr $ra 276 | sw $a1, 0x20($a0) 277 | jr $ra 278 | nop 279 | sw $a4, 0x14($a1) 280 | jr $ra 281 | sw $a1, 0x18($a0) 282 | sw $a1, 0x20($a0) 283 | jr $ra 284 | sw $a1, 0x18($a0) 285 | sw $a1, 0x14($a4) 286 | jr $ra 287 | sw $a1, 0x20($a0) 288 | addiu $sp, -0x2E0 289 | sd $s3, 0x2E0+var_C0($sp) 290 | li $s3, 0xD5F0 291 | sd $gp, 0x2E0+var_D0($sp) 292 | addu $gp, $t9, $s3 293 | la $s3, oflag 294 | sd $s0, 0x2E0+var_C8($sp) 295 | lbu $a0, (oflag - 0x1000A3B8)($s3) 296 | la $s0, defaultScript 297 | sd $ra, 0x2E0+var_18($sp) 298 | beqz $a0, loc_100039F4 299 | lw $s0, (defaultScript - 0x10008F2C)($s0) 300 | la $t9, printf 301 | la $a0, 0x10010000 302 | jalr $t9 303 | addiu $a0, (aReadingAnimati - 0x10010000) 304 | lbu $a0, (oflag - 0x1000A3B8)($s3) 305 | sdc1 $f20, 0x2E0+var_50($sp) 306 | sd $s5, 0x2E0+var_8($sp) 307 | sd $s1, 0x2E0+var_10($sp) 308 | beqz $a0, loc_10003A14 309 | sd $s6, 0x2E0+var_20($sp) 310 | la $t9, printf 311 | jalr $t9 312 | la $a0, asc_10009338 313 | la $s5, sscanf 314 | la $s1, strcmp 315 | la $s6, strcspn 316 | sd $s7, 0x2E0+var_30($sp) 317 | sd $s4, 0x2E0+var_38($sp) 318 | sd $fp, 0x2E0+var_40($sp) 319 | sd $s2, 0x2E0+var_48($sp) 320 | mtc1 $zero, $f20 321 | lw $a1, 0x2E0+var_2E0($sp) 322 | b loc_10003B54 323 | sd $a1, 0x2E0+var_A8($sp) 324 | la $a0, asc_10009388 325 | addiu $a1, $sp, 0x2E0+var_2D8 326 | jalr $t9 327 | li $a2, 1 328 | beqz $v0, loc_100047C0 329 | lbu $a0, 0($s3) 330 | beqz $a0, loc_10003A78 331 | la $t9, free 332 | la $t9, printf 333 | la $a0, 0x10010000 334 | addiu $a1, $sp, 0x2E0+var_2D8 335 | jalr $t9 336 | addiu $a0, (aBadCommandS - 0x10010000) 337 | la $t9, free 338 | jalr $t9 339 | move $a0, $s2 340 | li $a1, 1 341 | sd $a1, 0x2E0+var_58($sp) 342 | ld $a2, 0x2E0+var_58($sp) 343 | sd $a2, 0x2E0+var_60($sp) 344 | ld $a3, 0x2E0+var_60($sp) 345 | sd $a3, 0x2E0+var_68($sp) 346 | ld $a4, 0x2E0+var_68($sp) 347 | sd $a4, 0x2E0+var_70($sp) 348 | ld $a5, 0x2E0+var_70($sp) 349 | sd $a5, 0x2E0+var_78($sp) 350 | ld $a6, 0x2E0+var_78($sp) 351 | sd $a6, 0x2E0+var_80($sp) 352 | ld $a7, 0x2E0+var_80($sp) 353 | sd $a7, 0x2E0+var_88($sp) 354 | ld $fp, 0x2E0+var_88($sp) 355 | move $s7, $fp 356 | move $s4, $s7 357 | move $fp, $s4 358 | move $s7, $fp 359 | move $s4, $s7 360 | move $s7, $s4 361 | move $fp, $s7 362 | move $s7, $fp 363 | move $s4, $s7 364 | beqz $s4, loc_10003DA4 365 | move $t9, $s5 366 | move $a0, $s0 367 | addiu $a2, $sp, 0x2E0+var_1D8 368 | jalr $t9 369 | la $a1, asc_10009390 370 | lbu $t4, 0($s3) 371 | beqz $t4, loc_10003B18 372 | la $t5, bflag 373 | la $t9, printf 374 | addiu $a1, $sp, 0x2E0+var_1D8 375 | jalr $t9 376 | la $a0, aS_0 377 | la $t5, bflag 378 | lbu $t5, (bflag - 0x10008E49)($t5) 379 | la $s2, strlen 380 | beqz $t5, loc_10003DD8 381 | sb $zero, 0x2E0+var_1D8($sp) 382 | move $t9, $s6 383 | move $a0, $s0 384 | jalr $t9 385 | la $a1, asc_10009338 386 | move $t9, $s2 387 | addu $s0, $v0, $s0 388 | addiu $s0, 1 389 | jalr $t9 390 | move $a0, $s0 391 | beqz $v0, loc_100041A4 392 | la $a1, seqList 393 | sd $zero, 0x2E0+var_58($sp) 394 | sd $zero, 0x2E0+var_60($sp) 395 | sd $zero, 0x2E0+var_68($sp) 396 | sd $zero, 0x2E0+var_70($sp) 397 | sd $zero, 0x2E0+var_78($sp) 398 | sd $zero, 0x2E0+var_80($sp) 399 | sd $zero, 0x2E0+var_88($sp) 400 | sd $zero, 0x2E0+var_90($sp) 401 | sd $zero, 0x2E0+var_98($sp) 402 | move $s2, $zero 403 | sd $zero, 0x2E0+var_A0($sp) 404 | move $fp, $zero 405 | move $s7, $zero 406 | sd $zero, 0x2E0+var_B0($sp) 407 | move $s4, $zero 408 | move $t9, $s5 409 | sd $zero, 0x2E0+var_B8($sp) 410 | move $a0, $s0 411 | addiu $a2, $sp, 0x2E0+var_2D8 412 | sd $zero, 0x2E0+var_D8($sp) 413 | jalr $t9 414 | la $a1, aS 415 | move $t9, $s6 416 | move $a0, $s0 417 | la $a1, asc_10009340 418 | jalr $t9 419 | sd $s2, 0x2E0+var_28($sp) 420 | la $t9, malloc 421 | li $a0, 0x18 422 | jalr $t9 423 | addu $s0, $v0, $s0 424 | la $t8, absFrame 425 | move $t9, $s1 426 | lwc1 $f0, (absFrame - 0x1000A3C8)($t8) 427 | move $s2, $v0 428 | addiu $a1, $sp, 0x2E0+var_2D8 429 | la $a0, aFrame 430 | jalr $t9 431 | swc1 $f0, 8($v0) 432 | beqz $v0, loc_10003D30 433 | move $t9, $s5 434 | la $a0, 0x10010000 435 | move $t9, $s1 436 | addiu $a1, $sp, 0x2E0+var_2D8 437 | jalr $t9 438 | addiu $a0, (aRelframe - 0x10010000) 439 | beqz $v0, loc_10003E58 440 | move $t9, $s5 441 | la $a0, 0x10010000 442 | move $t9, $s1 443 | addiu $a1, $sp, 0x2E0+var_2D8 444 | ld $s4, 0x2E0+var_D8($sp) 445 | jalr $t9 446 | addiu $a0, (aAbsframe - 0x10010000) 447 | beqz $v0, loc_10003ED0 448 | la $a0, 0x10010000 449 | move $t9, $s1 450 | addiu $a1, $sp, 0x2E0+var_2D8 451 | ld $s7, 0x2E0+var_B8($sp) 452 | jalr $t9 453 | addiu $a0, (aRanddelay - 0x10010000) 454 | beqz $v0, loc_10003F48 455 | la $a0, 0x10010000 456 | move $t9, $s1 457 | addiu $a1, $sp, 0x2E0+var_2D8 458 | ld $fp, 0x2E0+var_B0($sp) 459 | jalr $t9 460 | addiu $a0, (aDuration - 0x10010000) 461 | beqz $v0, loc_10004014 462 | la $a0, 0x10010000 463 | move $t9, $s1 464 | addiu $a1, $sp, 0x2E0+var_2D8 465 | jalr $t9 466 | addiu $a0, (aVariance - 0x10010000) 467 | beqz $v0, loc_10004074 468 | la $a0, 0x10010000 469 | move $t9, $s1 470 | addiu $a1, $sp, 0x2E0+var_2D8 471 | ld $s4, 0x2E0+var_A0($sp) 472 | jalr $t9 473 | addiu $a0, (aActlim1 - 0x10010000) 474 | beqz $v0, loc_100040D0 475 | la $a0, 0x10010000 476 | move $t9, $s1 477 | addiu $a1, $sp, 0x2E0+var_2D8 478 | ld $s7, 0x2E0+var_98($sp) 479 | jalr $t9 480 | addiu $a0, (aActlim2 - 0x10010000) 481 | beqz $v0, loc_10004138 482 | move $t9, $s1 483 | addiu $a1, $sp, 0x2E0+var_2D8 484 | ld $fp, 0x2E0+var_90($sp) 485 | jalr $t9 486 | la $a0, aActset 487 | beqz $v0, loc_100042C0 488 | la $a0, 0x10010000 489 | move $t9, $s1 490 | addiu $a1, $sp, 0x2E0+var_2D8 491 | jalr $t9 492 | addiu $a0, (aActreset - 0x10010000) 493 | beqz $v0, loc_100043B4 494 | la $a0, 0x10010000 495 | move $t9, $s1 496 | addiu $a1, $sp, 0x2E0+var_2D8 497 | jalr $t9 498 | addiu $a0, (aActresetall - 0x10010000) 499 | bnez $v0, loc_10003DFC 500 | la $a0, 0x10010000 501 | li $a2, 6 502 | sw $a2, 0($s2) 503 | lbu $a1, 0($s3) 504 | beqz $a1, loc_10003AC0 505 | move $s7, $fp 506 | la $t9, printf 507 | la $a0, aS 508 | jalr $t9 509 | addiu $a1, $sp, 0x2E0+var_2D8 510 | b loc_10003AC0 511 | move $s7, $fp 512 | addiu $a2, $s2, 0xC 513 | la $a1, aF 514 | move $a0, $s0 515 | jalr $t9 516 | sw $zero, 0($s2) 517 | move $t9, $s6 518 | move $a0, $s0 519 | jalr $t9 520 | la $a1, asc_10009340 521 | lbu $a3, 0($s3) 522 | beqz $a3, loc_10003D7C 523 | addu $s0, $v0, $s0 524 | lwc1 $f1, 0xC($s2) 525 | la $t9, printf 526 | cvt.d.s $f1, $f1 527 | addiu $a1, $sp, 0x2E0+var_2D8 528 | dmfc1 $a2, $f1 529 | jalr $t9 530 | la $a0, aSF 531 | lwc1 $f4, 0xC($s2) 532 | la $a5, relFrame 533 | la $a6, baseFrame 534 | lwc1 $f3, (relFrame - 0x1000A3C0)($a5) 535 | lwc1 $f2, (baseFrame - 0x1000A3C4)($a6) 536 | add.s $f3, $f4 537 | la $a4, absFrame 538 | swc1 $f3, (relFrame - 0x1000A3C0)($a5) 539 | add.s $f2, $f3 540 | swc1 $f2, (absFrame - 0x1000A3C8)($a4) 541 | la $a0, editSeq 542 | lw $a0, (editSeq - 0x1000BF7C)($a0) 543 | beqz $a0, loc_1000445C 544 | la $s4, addToSeq__GP7animSeqP11animCommand 545 | move $t9, $s4 546 | jal addToSeq__GP7animSeqP11animCommand 547 | move $a1, $s2 548 | la $a1, editSeq 549 | la $a2, relFrame 550 | lw $a1, (editSeq - 0x1000BF7C)($a1) 551 | lwc1 $f5, (relFrame - 0x1000A3C0)($a2) 552 | b loc_10003AE4 553 | swc1 $f5, 0xC($a1) 554 | la $t9, scanf 555 | li $s0, 0xFFFFFFFF 556 | la $a0, asc_10009390 557 | jalr $t9 558 | ld $a1, 0x2E0+var_A8($sp) 559 | beq $v0, $s0, loc_100041A4 560 | la $a1, seqList 561 | b loc_10003B54 562 | ld $s0, 0x2E0+var_A8($sp) 563 | move $t9, $s1 564 | addiu $a1, $sp, 0x2E0+var_2D8 565 | jalr $t9 566 | addiu $a0, (aActstop - 0x10010000) 567 | beqz $v0, loc_10004408 568 | la $a0, 0x10010000 569 | move $t9, $s1 570 | addiu $a1, $sp, 0x2E0+var_2D8 571 | jalr $t9 572 | addiu $a0, (aActstopall - 0x10010000) 573 | bnez $v0, loc_10003FA4 574 | la $a0, 0x10010000 575 | li $a2, 8 576 | sw $a2, 0($s2) 577 | lbu $a1, 0($s3) 578 | beqz $a1, loc_10003AB4 579 | ld $a7, 0x2E0+var_80($sp) 580 | la $t9, printf 581 | la $a0, aS 582 | jalr $t9 583 | addiu $a1, $sp, 0x2E0+var_2D8 584 | b loc_10003AB4 585 | ld $a7, 0x2E0+var_80($sp) 586 | addiu $a2, $s2, 0xC 587 | la $a1, aF 588 | move $a0, $s0 589 | jalr $t9 590 | sw $zero, 0($s2) 591 | move $t9, $s6 592 | move $a0, $s0 593 | jalr $t9 594 | la $a1, asc_10009340 595 | lbu $a3, 0($s3) 596 | beqz $a3, loc_10003EA4 597 | addu $s0, $v0, $s0 598 | lwc1 $f6, 0xC($s2) 599 | la $t9, printf 600 | cvt.d.s $f6, $f6 601 | addiu $a1, $sp, 0x2E0+var_2D8 602 | dmfc1 $a2, $f6 603 | jalr $t9 604 | la $a0, aSF 605 | lwc1 $f9, 0xC($s2) 606 | la $a5, relFrame 607 | la $a6, baseFrame 608 | lwc1 $f8, (relFrame - 0x1000A3C0)($a5) 609 | lwc1 $f7, (baseFrame - 0x1000A3C4)($a6) 610 | add.s $f8, $f9 611 | la $a4, absFrame 612 | swc1 $f8, (relFrame - 0x1000A3C0)($a5) 613 | add.s $f7, $f8 614 | b loc_10003AE0 615 | swc1 $f7, (absFrame - 0x1000A3C8)($a4) 616 | addiu $a2, $s2, 0xC 617 | move $t9, $s5 618 | la $a1, aF 619 | move $a0, $s0 620 | li $s4, 1 621 | jalr $t9 622 | sw $s4, 0($s2) 623 | move $t9, $s6 624 | move $a0, $s0 625 | jalr $t9 626 | la $a1, asc_10009340 627 | lbu $a7, 0($s3) 628 | beqz $a7, loc_10003F24 629 | addu $s0, $v0, $s0 630 | lwc1 $f10, 0xC($s2) 631 | la $t9, printf 632 | cvt.d.s $f10, $f10 633 | addiu $a1, $sp, 0x2E0+var_2D8 634 | dmfc1 $a2, $f10 635 | jalr $t9 636 | la $a0, aSF 637 | la $t6, relFrame 638 | la $t5, baseFrame 639 | swc1 $f20, (relFrame - 0x1000A3C0)($t6) 640 | lwc1 $f12, 0xC($s2) 641 | la $t4, absFrame 642 | swc1 $f12, (baseFrame - 0x1000A3C4)($t5) 643 | lwc1 $f11, 0xC($s2) 644 | b loc_10003ADC 645 | swc1 $f11, (absFrame - 0x1000A3C8)($t4) 646 | addiu $a2, $s2, 0xC 647 | move $t9, $s5 648 | la $a1, aF 649 | move $a0, $s0 650 | li $s4, 0x67 651 | jalr $t9 652 | sw $s4, 0($s2) 653 | move $t9, $s6 654 | move $a0, $s0 655 | jalr $t9 656 | la $a1, asc_10009340 657 | lbu $t7, 0($s3) 658 | beqz $t7, loc_10003AD8 659 | addu $s0, $v0, $s0 660 | lwc1 $f13, 0xC($s2) 661 | la $t9, printf 662 | cvt.d.s $f13, $f13 663 | addiu $a1, $sp, 0x2E0+var_2D8 664 | dmfc1 $a2, $f13 665 | jalr $t9 666 | la $a0, aSF 667 | b loc_10003ADC 668 | move $s7, $fp 669 | move $t9, $s1 670 | addiu $a1, $sp, 0x2E0+var_2D8 671 | jalr $t9 672 | addiu $a0, (aSeqname - 0x10010000) 673 | beqz $v0, loc_100044F8 674 | move $t9, $s1 675 | la $a0, aSeqdo 676 | jalr $t9 677 | addiu $a1, $sp, 0x2E0+var_2D8 678 | beqz $v0, loc_10004630 679 | la $a0, 0x10010000 680 | move $t9, $s1 681 | addiu $a1, $sp, 0x2E0+var_2D8 682 | jalr $t9 683 | addiu $a0, (aSeqloop - 0x10010000) 684 | bnez $v0, loc_10004328 685 | la $a0, 0x10010000 686 | li $a2, 0xC 687 | sw $a2, 0($s2) 688 | lbu $a1, 0($s3) 689 | beqz $a1, loc_10003AA4 690 | ld $a5, 0x2E0+var_70($sp) 691 | la $t9, printf 692 | la $a0, aS 693 | jalr $t9 694 | addiu $a1, $sp, 0x2E0+var_2D8 695 | b loc_10003AA4 696 | ld $a5, 0x2E0+var_70($sp) 697 | move $a0, $s0 698 | move $t9, $s5 699 | ld $s7, 0x2E0+var_28($sp) 700 | la $a1, aF 701 | li $s4, 0x65 702 | sw $s4, 0($s2) 703 | jalr $t9 704 | addiu $a2, $s2, 0xC 705 | move $t9, $s6 706 | move $a0, $s0 707 | jalr $t9 708 | la $a1, asc_10009340 709 | lbu $a3, 0($s3) 710 | beqz $a3, loc_10003AD4 711 | addu $s0, $v0, $s0 712 | lwc1 $f14, 0xC($s2) 713 | la $t9, printf 714 | cvt.d.s $f14, $f14 715 | la $a0, aSF 716 | dmfc1 $a2, $f14 717 | jalr $t9 718 | addiu $a1, $sp, 0x2E0+var_2D8 719 | b loc_10003AD8 720 | move $fp, $s7 721 | move $a0, $s0 722 | move $t9, $s5 723 | la $a1, aF 724 | li $s7, 0x66 725 | sw $s7, 0($s2) 726 | jalr $t9 727 | addiu $a2, $s2, 0xC 728 | move $t9, $s6 729 | move $a0, $s0 730 | jalr $t9 731 | la $a1, asc_10009340 732 | lbu $a4, 0($s3) 733 | beqz $a4, loc_10003AD0 734 | addu $s0, $v0, $s0 735 | lwc1 $f15, 0xC($s2) 736 | la $t9, printf 737 | cvt.d.s $f15, $f15 738 | la $a0, aSF 739 | dmfc1 $a2, $f15 740 | jalr $t9 741 | addiu $a1, $sp, 0x2E0+var_2D8 742 | b loc_10003AD4 743 | move $s7, $s4 744 | move $a0, $s0 745 | la $a1, aDF 746 | move $t9, $s5 747 | addiu $a2, $s2, 4 748 | li $s4, 2 749 | sw $s4, 0($s2) 750 | jalr $t9 751 | addiu $a3, $s2, 0xC 752 | move $t9, $s6 753 | move $a0, $s0 754 | jalr $t9 755 | la $a1, asc_10009340 756 | lbu $a5, 0($s3) 757 | beqz $a5, loc_10003ACC 758 | addu $s0, $v0, $s0 759 | lwc1 $f16, 0xC($s2) 760 | la $t9, printf 761 | la $a0, 0x10010000 762 | cvt.d.s $f16, $f16 763 | addiu $a1, $sp, 0x2E0+var_2D8 764 | lw $a2, 4($s2) 765 | dmfc1 $a3, $f16 766 | jalr $t9 767 | addiu $a0, (aSDF - 0x10010000) 768 | b loc_10003AD0 769 | move $s4, $s7 770 | move $a0, $s0 771 | la $a1, aDF 772 | move $t9, $s5 773 | addiu $a2, $s2, 4 774 | li $s4, 3 775 | sw $s4, 0($s2) 776 | jalr $t9 777 | addiu $a3, $s2, 0xC 778 | move $t9, $s6 779 | move $a0, $s0 780 | jalr $t9 781 | la $a1, asc_10009340 782 | lbu $a1, 0($s3) 783 | beqz $a1, loc_10003AC8 784 | addu $s0, $v0, $s0 785 | lwc1 $f17, 0xC($s2) 786 | la $t9, printf 787 | la $a0, 0x10010000 788 | cvt.d.s $f17, $f17 789 | addiu $a1, $sp, 0x2E0+var_2D8 790 | lw $a2, 4($s2) 791 | dmfc1 $a3, $f17 792 | jalr $t9 793 | addiu $a0, (aSDF - 0x10010000) 794 | b loc_10003ACC 795 | move $s7, $fp 796 | la $a1, seqList 797 | lw $a1, (seqList - 0x1000BF78)($a1) 798 | beqz $a1, loc_100041C4 799 | move $s4, $a1 800 | lw $a2, 0($s4) 801 | beqz $a2, loc_10004624 802 | nop 803 | lw $s4, 0x24($s4) 804 | bnez $s4, loc_100041B0 805 | lbu $a3, 0($s3) 806 | beqz $a3, loc_100041E4 807 | la $a1, seqList 808 | la $t9, printf 809 | la $a0, 0x10010000 810 | jalr $t9 811 | addiu $a0, (aDoneReadingAni - 0x10010000) 812 | la $a1, seqList 813 | lw $a1, (seqList - 0x1000BF78)($a1) 814 | la $s1, printf 815 | beqz $a1, loc_10004288 816 | move $s4, $a1 817 | b loc_1000424C 818 | lbu $a1, 0($s3) 819 | lw $s0, 0x14($s0) 820 | beqz $s0, loc_10004240 821 | nop 822 | beqz $a0, loc_100041FC 823 | nop 824 | lwc1 $f18, 0xC($s0) 825 | la $a0, 0x10010000 826 | move $t9, $s1 827 | cvt.d.s $f18, $f18 828 | lw $a1, 0($s0) 829 | lw $a2, 4($s0) 830 | dmfc1 $a3, $f18 831 | jalr $t9 832 | addiu $a0, (aCmdDDF - 0x10010000) 833 | lw $s0, 0x14($s0) 834 | bnez $s0, loc_10004280 835 | nop 836 | lw $s4, 0x24($s4) 837 | beqz $s4, loc_10004288 838 | lbu $a1, 0($s3) 839 | beqz $a1, loc_10004274 840 | nop 841 | lwc1 $f19, 8($s4) 842 | la $a0, 0x10010000 843 | move $t9, $s1 844 | cvt.d.s $f19, $f19 845 | lw $a1, 0($s4) 846 | dmfc1 $a2, $f19 847 | jalr $t9 848 | addiu $a0, (aSeqDAt_2f - 0x10010000) 849 | lw $s0, 0x18($s4) 850 | beqz $s0, loc_10004240 851 | la $s1, printf 852 | b loc_10004208 853 | lbu $a0, 0($s3) 854 | ld $s5, 0x2E0+var_8($sp) 855 | ld $s1, 0x2E0+var_10($sp) 856 | ld $s6, 0x2E0+var_20($sp) 857 | ld $s7, 0x2E0+var_30($sp) 858 | ld $s4, 0x2E0+var_38($sp) 859 | ld $fp, 0x2E0+var_40($sp) 860 | ld $s2, 0x2E0+var_48($sp) 861 | ldc1 $f20, 0x2E0+var_50($sp) 862 | ld $ra, 0x2E0+var_18($sp) 863 | ld $gp, 0x2E0+var_D0($sp) 864 | ld $s0, 0x2E0+var_C8($sp) 865 | ld $s3, 0x2E0+var_C0($sp) 866 | jr $ra 867 | addiu $sp, 0x2E0 868 | move $a0, $s0 869 | la $a1, aDF 870 | move $t9, $s5 871 | addiu $a2, $s2, 4 872 | li $s7, 4 873 | sw $s7, 0($s2) 874 | jalr $t9 875 | addiu $a3, $s2, 0xC 876 | move $t9, $s6 877 | move $a0, $s0 878 | jalr $t9 879 | la $a1, asc_10009340 880 | lbu $a1, 0($s3) 881 | beqz $a1, loc_10003AC4 882 | addu $s0, $v0, $s0 883 | lwc1 $f21, 0xC($s2) 884 | la $t9, printf 885 | la $a0, 0x10010000 886 | cvt.d.s $f21, $f21 887 | addiu $a1, $sp, 0x2E0+var_2D8 888 | lw $a2, 4($s2) 889 | dmfc1 $a3, $f21 890 | jalr $t9 891 | addiu $a0, (aSDF - 0x10010000) 892 | b loc_10003AC8 893 | move $fp, $s4 894 | move $t9, $s1 895 | addiu $a1, $sp, 0x2E0+var_2D8 896 | jalr $t9 897 | addiu $a0, (aSeqstop - 0x10010000) 898 | beqz $v0, loc_1000469C 899 | la $a0, 0x10010000 900 | move $t9, $s1 901 | addiu $a1, $sp, 0x2E0+var_2D8 902 | jalr $t9 903 | addiu $a0, (aSeqrepeat - 0x10010000) 904 | beqz $v0, loc_100046F0 905 | la $a0, 0x10010000 906 | move $t9, $s1 907 | addiu $a1, $sp, 0x2E0+var_2D8 908 | jalr $t9 909 | addiu $a0, (aSeqkill - 0x10010000) 910 | beqz $v0, loc_1000476C 911 | la $a0, 0x10010000 912 | move $t9, $s1 913 | addiu $a1, $sp, 0x2E0+var_2D8 914 | jalr $t9 915 | addiu $a0, (aSeqkillall - 0x10010000) 916 | bnez $v0, loc_10003A40 917 | la $t9, strncmp 918 | li $a2, 0xF 919 | sw $a2, 0($s2) 920 | lbu $a1, 0($s3) 921 | beqz $a1, loc_10003A8C 922 | ld $a2, 0x2E0+var_58($sp) 923 | la $t9, printf 924 | la $a0, aS 925 | jalr $t9 926 | addiu $a1, $sp, 0x2E0+var_2D8 927 | b loc_10003A8C 928 | ld $a2, 0x2E0+var_58($sp) 929 | move $a0, $s0 930 | move $t9, $s5 931 | la $a1, aD 932 | li $a3, 5 933 | sw $a3, 0($s2) 934 | jalr $t9 935 | addiu $a2, $s2, 4 936 | move $t9, $s6 937 | move $a0, $s0 938 | jalr $t9 939 | la $a1, asc_10009340 940 | lbu $a4, 0($s3) 941 | beqz $a4, loc_10003AC0 942 | addu $s0, $v0, $s0 943 | la $t9, printf 944 | la $a0, aSD 945 | addiu $a1, $sp, 0x2E0+var_2D8 946 | jalr $t9 947 | lw $a2, 4($s2) 948 | b loc_10003AC4 949 | move $s4, $s7 950 | move $a0, $s0 951 | move $t9, $s5 952 | la $a1, aD 953 | li $a5, 7 954 | sw $a5, 0($s2) 955 | jalr $t9 956 | addiu $a2, $s2, 4 957 | move $t9, $s6 958 | move $a0, $s0 959 | jalr $t9 960 | la $a1, asc_10009340 961 | lbu $a6, 0($s3) 962 | beqz $a6, loc_10003AB8 963 | addu $s0, $v0, $s0 964 | la $t9, printf 965 | la $a0, aSD 966 | addiu $a1, $sp, 0x2E0+var_2D8 967 | jalr $t9 968 | lw $a2, 4($s2) 969 | b loc_10003ABC 970 | ld $fp, 0x2E0+var_88($sp) 971 | la $t9, malloc 972 | jalr $t9 973 | li $a0, 0x28 974 | la $a4, editSeq 975 | sw $v0, (editSeq - 0x1000BF7C)($a4) 976 | li $t8, 1 977 | sb $t8, 4($v0) 978 | lw $t7, (editSeq - 0x1000BF7C)($a4) 979 | sw $zero, 0($t7) 980 | lw $t6, (editSeq - 0x1000BF7C)($a4) 981 | lwc1 $f25, flt_100092B0 982 | swc1 $f20, 8($t6) 983 | lw $t5, (editSeq - 0x1000BF7C)($a4) 984 | lwc1 $f23, flt_100092A8 985 | swc1 $f25, 0x10($t5) 986 | lw $t4, (editSeq - 0x1000BF7C)($a4) 987 | swc1 $f23, 0x14($t4) 988 | lw $a7, (editSeq - 0x1000BF7C)($a4) 989 | swc1 $f25, 0x10($a7) 990 | lw $a6, (editSeq - 0x1000BF7C)($a4) 991 | swc1 $f23, 0x14($a6) 992 | lw $a5, (editSeq - 0x1000BF7C)($a4) 993 | sw $zero, 0x20($a5) 994 | lw $a3, (editSeq - 0x1000BF7C)($a4) 995 | sw $zero, 0x1C($a3) 996 | lw $a2, (editSeq - 0x1000BF7C)($a4) 997 | sw $zero, 0x18($a2) 998 | lw $a1, (editSeq - 0x1000BF7C)($a4) 999 | la $a0, seqList 1000 | sw $zero, 0x24($a1) 1001 | lw $a0, (seqList - 0x1000BF78)($a0) 1002 | la $t9, seqList 1003 | beqz $a0, loc_100044E8 1004 | lw $a4, (editSeq - 0x1000BF7C)($a4) 1005 | sw $a0, 0x24($a4) 1006 | la $a0, editSeq 1007 | lw $a0, (editSeq - 0x1000BF7C)($a0) 1008 | b loc_10003DB0 1009 | sw $a0, (seqList - 0x1000BF78)($t9) 1010 | move $a0, $s0 1011 | move $t9, $s5 1012 | li $a1, 9 1013 | sw $a1, 0($s2) 1014 | la $a1, aD 1015 | jalr $t9 1016 | addiu $a2, $s2, 4 1017 | move $t9, $s6 1018 | move $a0, $s0 1019 | jalr $t9 1020 | la $a1, asc_10009340 1021 | lbu $a2, 0($s3) 1022 | beqz $a2, loc_10004544 1023 | addu $s0, $v0, $s0 1024 | la $t9, printf 1025 | la $a0, aSD 1026 | addiu $a1, $sp, 0x2E0+var_2D8 1027 | jalr $t9 1028 | lw $a2, 4($s2) 1029 | la $a4, relFrame 1030 | la $a5, absFrame 1031 | la $a3, seqList 1032 | la $a6, baseFrame 1033 | lw $a3, (seqList - 0x1000BF78)($a3) 1034 | swc1 $f20, (baseFrame - 0x1000A3C4)($a6) 1035 | swc1 $f20, (absFrame - 0x1000A3C8)($a5) 1036 | swc1 $f20, (relFrame - 0x1000A3C0)($a4) 1037 | beqz $a3, loc_1000468C 1038 | move $s4, $a3 1039 | lw $v0, 4($s2) 1040 | lw $a7, 0($s4) 1041 | beq $a7, $v0, loc_10004684 1042 | nop 1043 | lw $s4, 0x24($s4) 1044 | bnez $s4, loc_10004570 1045 | la $t9, malloc 1046 | jalr $t9 1047 | li $a0, 0x28 1048 | la $a4, editSeq 1049 | sw $v0, (editSeq - 0x1000BF7C)($a4) 1050 | lw $t7, 4($s2) 1051 | sw $t7, 0($v0) 1052 | lw $t6, (editSeq - 0x1000BF7C)($a4) 1053 | li $t5, 1 1054 | sb $t5, 4($t6) 1055 | lw $t4, (editSeq - 0x1000BF7C)($a4) 1056 | lwc1 $f29, flt_100092B0 1057 | swc1 $f20, 8($t4) 1058 | lw $a7, (editSeq - 0x1000BF7C)($a4) 1059 | lwc1 $f27, flt_100092A8 1060 | swc1 $f29, 0x10($a7) 1061 | lw $a6, (editSeq - 0x1000BF7C)($a4) 1062 | swc1 $f27, 0x14($a6) 1063 | lw $a5, (editSeq - 0x1000BF7C)($a4) 1064 | sw $zero, 0x18($a5) 1065 | lw $a3, (editSeq - 0x1000BF7C)($a4) 1066 | sw $zero, 0x1C($a3) 1067 | lw $a2, (editSeq - 0x1000BF7C)($a4) 1068 | sw $zero, 0x20($a2) 1069 | lw $a1, (editSeq - 0x1000BF7C)($a4) 1070 | la $a0, seqList 1071 | sw $zero, 0x24($a1) 1072 | lw $a0, (seqList - 0x1000BF78)($a0) 1073 | la $t8, editSeq 1074 | la $t9, seqList 1075 | beqz $a0, loc_10004608 1076 | lw $a4, (editSeq - 0x1000BF7C)($a4) 1077 | sw $a0, 0x24($a4) 1078 | lw $t8, (editSeq - 0x1000BF7C)($t8) 1079 | sw $t8, (seqList - 0x1000BF78)($t9) 1080 | la $t9, free 1081 | jalr $t9 1082 | move $a0, $s2 1083 | b loc_10003AE8 1084 | move $t9, $s5 1085 | lw $t9, 0x18($s4) 1086 | b loc_100041C4 1087 | sw $t9, 0x1C($s4) 1088 | move $a0, $s0 1089 | move $t9, $s5 1090 | la $a1, aD 1091 | li $ra, 0xA 1092 | sw $ra, 0($s2) 1093 | jalr $t9 1094 | addiu $a2, $s2, 4 1095 | move $t9, $s6 1096 | move $a0, $s0 1097 | jalr $t9 1098 | la $a1, asc_10009340 1099 | lbu $at, 0($s3) 1100 | beqz $at, loc_10003AA8 1101 | addu $s0, $v0, $s0 1102 | la $t9, printf 1103 | la $a0, aSD 1104 | addiu $a1, $sp, 0x2E0+var_2D8 1105 | jalr $t9 1106 | lw $a2, 4($s2) 1107 | b loc_10003AAC 1108 | ld $a6, 0x2E0+var_78($sp) 1109 | la $v0, editSeq 1110 | sw $s4, (editSeq - 0x1000BF7C)($v0) 1111 | bnez $s4, loc_10004614 1112 | la $t9, free 1113 | b loc_10004588 1114 | la $t9, malloc 1115 | move $a0, $s0 1116 | move $t9, $s5 1117 | la $a1, aD 1118 | li $v1, 0xB 1119 | sw $v1, 0($s2) 1120 | jalr $t9 1121 | addiu $a2, $s2, 4 1122 | move $t9, $s6 1123 | move $a0, $s0 1124 | jalr $t9 1125 | la $a1, asc_10009340 1126 | lbu $a0, 0($s3) 1127 | beqz $a0, loc_10003A98 1128 | addu $s0, $v0, $s0 1129 | la $t9, printf 1130 | la $a0, aSD 1131 | addiu $a1, $sp, 0x2E0+var_2D8 1132 | jalr $t9 1133 | lw $a2, 4($s2) 1134 | b loc_10003A9C 1135 | ld $a4, 0x2E0+var_68($sp) 1136 | move $a0, $s0 1137 | move $t9, $s5 1138 | li $a1, 0xD 1139 | sw $a1, 0($s2) 1140 | la $a1, aD 1141 | jalr $t9 1142 | addiu $a2, $s2, 4 1143 | move $t9, $s6 1144 | move $a0, $s0 1145 | jalr $t9 1146 | la $a1, asc_10009340 1147 | lbu $a2, 0($s3) 1148 | beqz $a2, loc_10004758 1149 | addu $s0, $v0, $s0 1150 | la $t9, printf 1151 | la $a0, aSD 1152 | addiu $a1, $sp, 0x2E0+var_2D8 1153 | jalr $t9 1154 | lw $a2, 4($s2) 1155 | lbu $a3, 0($s3) 1156 | beqz $a3, loc_10004758 1157 | la $t9, printf 1158 | la $a0, 0x10010000 1159 | addiu $a1, $sp, 0x2E0+var_2D8 1160 | jalr $t9 1161 | addiu $a0, (aWarningSNotImp - 0x10010000) 1162 | la $t9, free 1163 | jalr $t9 1164 | move $a0, $s2 1165 | b loc_10003AE8 1166 | move $t9, $s5 1167 | move $a0, $s0 1168 | move $t9, $s5 1169 | li $a1, 0xE 1170 | sw $a1, 0($s2) 1171 | la $a1, aD 1172 | jalr $t9 1173 | addiu $a2, $s2, 4 1174 | move $t9, $s6 1175 | move $a0, $s0 1176 | jalr $t9 1177 | la $a1, asc_10009340 1178 | lbu $a2, 0($s3) 1179 | beqz $a2, loc_10003A90 1180 | addu $s0, $v0, $s0 1181 | la $t9, printf 1182 | la $a0, aSD 1183 | addiu $a1, $sp, 0x2E0+var_2D8 1184 | jalr $t9 1185 | lw $a2, 4($s2) 1186 | b loc_10003A94 1187 | ld $a3, 0x2E0+var_60($sp) 1188 | beqz $a0, loc_100047DC 1189 | la $t9, free 1190 | la $t9, printf 1191 | la $a0, aS 1192 | jalr $t9 1193 | addiu $a1, $sp, 0x2E0+var_2D8 1194 | la $t9, free 1195 | jalr $t9 1196 | move $a0, $s2 1197 | b loc_10003AE8 1198 | move $t9, $s5 1199 | li $v0, 0xC7B0 1200 | addu $at, $t9, $v0 1201 | move $a3, $zero 1202 | lw $a2, (acttable_ptr - 0x10010F9C)($at) 1203 | lw $a5, 0($a2) 1204 | addiu $a2, 4 1205 | addiu $a3, 1 1206 | beqz $a5, loc_10004818 1207 | slti $a4, $a3, 0x400 1208 | sb $zero, 0($a5) 1209 | bnezl $a4, loc_10004804 1210 | lw $a5, 0($a2) 1211 | jr $ra 1212 | nop 1213 | addiu $sp, -0x30 1214 | sd $s1, 0x30+var_20($sp) 1215 | sd $ra, 0x30+var_18($sp) 1216 | sd $s0, 0x30+var_30($sp) 1217 | lui $at, 1 1218 | move $s0, $a0 1219 | sd $s2, 0x30+var_10($sp) 1220 | li $at, 0xC774 1221 | sd $gp, 0x30+var_28($sp) 1222 | beqz $a0, loc_10004904 1223 | addu $gp, $t9, $at 1224 | la $s1, seqList 1225 | sb $zero, 4($a0) 1226 | lw $a3, (seqList - 0x1000BF78)($s1) 1227 | bne $a0, $a3, loc_100048A4 1228 | la $s2, free 1229 | lw $a0, 0x24($a3) 1230 | sw $a0, (seqList - 0x1000BF78)($s1) 1231 | lw $a0, 0x18($a0) 1232 | beqz $a0, loc_10004894 1233 | move $t9, $s2 1234 | move $t9, $s2 1235 | jalr $t9 1236 | lw $s1, 0x14($a0) 1237 | bnez $s1, loc_1000487C 1238 | move $a0, $s1 1239 | move $t9, $s2 1240 | la $s1, seqList 1241 | jalr $t9 1242 | move $a0, $s0 1243 | lw $a3, (seqList - 0x1000BF78)($s1) 1244 | lw $a2, 0x24($a3) 1245 | beqz $a2, loc_10004904 1246 | la $s2, free 1247 | beq $a2, $s0, loc_100048D0 1248 | nop 1249 | move $a3, $a2 1250 | lw $a2, 0x24($a2) 1251 | bnez $a2, loc_100048B0 1252 | nop 1253 | b loc_10004908 1254 | ld $s2, 0x30+var_10($sp) 1255 | lw $a2, 0x24($s0) 1256 | sw $a2, 0x24($a3) 1257 | lw $a1, 0x18($s0) 1258 | beqz $a1, loc_100048F8 1259 | move $a0, $a1 1260 | move $t9, $s2 1261 | jalr $t9 1262 | lw $s1, 0x14($a0) 1263 | bnez $s1, loc_100048E4 1264 | move $a0, $s1 1265 | move $t9, $s2 1266 | jalr $t9 1267 | move $a0, $s0 1268 | ld $s2, 0x30+var_10($sp) 1269 | ld $ra, 0x30+var_18($sp) 1270 | ld $s0, 0x30+var_30($sp) 1271 | ld $s1, 0x30+var_20($sp) 1272 | ld $gp, 0x30+var_28($sp) 1273 | jr $ra 1274 | addiu $sp, 0x30 1275 | lui $v0, 1 1276 | addiu $sp, -0x20 1277 | li $v0, 0xC67C 1278 | sd $gp, 0x20+var_18($sp) 1279 | addu $gp, $t9, $v0 1280 | la $at, oflag 1281 | lbu $at, (oflag - 0x1000A3B8)($at) 1282 | sd $s0, 0x20+var_20($sp) 1283 | move $s0, $a0 1284 | beqz $at, loc_10004990 1285 | sd $ra, 0x20+var_10($sp) 1286 | lwc1 $f2, 8($a0) 1287 | lw $a2, 0x10($a0) 1288 | la $a3, currentFrame 1289 | lwc1 $f1, 8($a2) 1290 | lwc1 $f0, (currentFrame - 0x1000A3BC)($a3) 1291 | lw $a4, 0($a0) 1292 | cvt.d.s $f2, $f2 1293 | la $t9, printf 1294 | cvt.d.s $f1, $f1 1295 | la $a0, 0x10010000 1296 | dmfc1 $a5, $f2 1297 | cvt.d.s $f0, $f0 1298 | dmfc1 $a3, $f1 1299 | lw $a2, 0($a2) 1300 | dmfc1 $a1, $f0 1301 | jalr $t9 1302 | addiu $a0, (aProcCurrentfra - 0x10010000) 1303 | lw $a1, 0($s0) 1304 | la $a0, 0x10010000 1305 | sltiu $a5, $a1, 0x68 1306 | sll $a2, $a1, 2 1307 | addiu $a0, (jpt_100049B4 - 0x10010000) 1308 | la $a4, currentFrame 1309 | beqz $a5, loc_100049C8 1310 | addu $a0, $a2 1311 | lw $a2, 0($a0) 1312 | jr $a2 1313 | la $t9, exprand__Gf 1314 | jal killSeq__GP7animSeq 1315 | nop 1316 | lw $a1, 0($s0) 1317 | la $t9, printf 1318 | la $a0, 0x10010000 1319 | lw $a2, 0x10($s0) 1320 | jalr $t9 1321 | addiu $a0, (aWarningBadComm - 0x10010000) 1322 | lw $a2, 0x10($s0) 1323 | lw $a1, 0x1C($a2) 1324 | lw $a1, 0x14($a1) 1325 | sw $a1, 0x1C($a2) 1326 | ld $ra, 0x20+var_10($sp) 1327 | ld $s0, 0x20+var_20($sp) 1328 | ld $gp, 0x20+var_18($sp) 1329 | jr $ra 1330 | addiu $sp, 0x20 1331 | lw $a3, 0x10($s0) 1332 | lw $a2, 0x1C($a3) 1333 | lw $a2, 0x14($a2) 1334 | b loc_100049EC 1335 | sw $a2, 0x1C($a3) 1336 | jal exprand__Gf 1337 | lwc1 $f12, flt_100092A8 1338 | lwc1 $f8, flt_100092A8 1339 | lwc1 $f4, 0xC($s0) 1340 | lw $a4, 0x10($s0) 1341 | ldc1 $f9, dbl_10009308 1342 | cvt.d.s $f7, $f0 1343 | lwc1 $f5, 0x14($a4) 1344 | mul.d $f7, $f9 1345 | cvt.d.s $f6, $f4 1346 | sub.s $f8, $f5 1347 | mul.d $f6, $f7 1348 | lwc1 $f3, 8($a4) 1349 | cvt.d.s $f5, $f5 1350 | mul.s $f4, $f8 1351 | mul.d $f5, $f6 1352 | cvt.d.s $f4, $f4 1353 | cvt.d.s $f3, $f3 1354 | add.d $f4, $f5 1355 | add.d $f3, $f4 1356 | cvt.s.d $f3, $f3 1357 | swc1 $f3, 8($a4) 1358 | lw $a4, 0x10($s0) 1359 | lw $a3, 0x1C($a4) 1360 | lw $a3, 0x14($a3) 1361 | b loc_100049EC 1362 | sw $a3, 0x1C($a4) 1363 | lwc1 $f4, 0xC($s0) 1364 | dmtc1 $zero, $f6 1365 | cvt.d.s $f4, $f4 1366 | c.lt.d $f4, $f6 1367 | nop 1368 | bc1f loc_10004E0C 1369 | ldc1 $f5, dbl_10009300 1370 | b loc_10004E20 1371 | mov.d $f4, $f6 1372 | lwc1 $f4, 0xC($s0) 1373 | ldc1 $f5, dbl_10009300 1374 | cvt.d.s $f4, $f4 1375 | c.lt.d $f4, $f5 1376 | nop 1377 | bc1f loc_10004DEC 1378 | nop 1379 | b loc_10004DEC 1380 | mov.d $f4, $f5 1381 | la $a5, seqList 1382 | lw $a5, (seqList - 0x1000BF78)($a5) 1383 | beqz $a5, loc_100049C8 1384 | move $a0, $a5 1385 | lw $a1, 0x10($s0) 1386 | bne $a1, $a0, loc_100049BC 1387 | la $t9, killSeq__GP7animSeq 1388 | lw $a6, 0x1C($a1) 1389 | lw $a6, 0x14($a6) 1390 | sw $a6, 0x1C($a1) 1391 | lw $a0, 0x24($a0) 1392 | bnez $a0, loc_10004AD8 1393 | nop 1394 | b loc_100049C8 1395 | lw $a1, 0($s0) 1396 | la $a7, seqList 1397 | lw $a7, (seqList - 0x1000BF78)($a7) 1398 | beqz $a7, loc_10004D24 1399 | move $a0, $a7 1400 | b loc_10004D18 1401 | lw $a1, 4($s0) 1402 | lw $t5, 0x10($s0) 1403 | lw $t4, 0x1C($t5) 1404 | lw $t4, 0x14($t4) 1405 | b loc_100049EC 1406 | sw $t4, 0x1C($t5) 1407 | lw $t7, 0x10($s0) 1408 | lw $t6, 0x18($t7) 1409 | sw $t6, 0x1C($t7) 1410 | lw $t5, 0x10($s0) 1411 | lwc1 $f6, 0xC($t5) 1412 | lwc1 $f5, 8($t5) 1413 | add.s $f5, $f6 1414 | b loc_100049EC 1415 | swc1 $f5, 8($t5) 1416 | la $t8, seqList 1417 | lw $t8, (seqList - 0x1000BF78)($t8) 1418 | beqz $t8, loc_10004D60 1419 | move $a0, $t8 1420 | b loc_10004D54 1421 | lw $a1, 4($s0) 1422 | la $t9, seqList 1423 | lw $t9, (seqList - 0x1000BF78)($t9) 1424 | beqz $t9, loc_10004DA0 1425 | move $a0, $t9 1426 | b loc_10004D94 1427 | lw $a1, 4($s0) 1428 | lw $at, 0x10($s0) 1429 | lw $ra, 0x1C($at) 1430 | lw $ra, 0x14($ra) 1431 | b loc_100049EC 1432 | sw $ra, 0x1C($at) 1433 | la $t9, stopAnimation__Gv 1434 | jal stopAnimation__Gv 1435 | nop 1436 | lw $v0, 0x10($s0) 1437 | lw $at, 0x1C($v0) 1438 | lw $at, 0x14($at) 1439 | b loc_100049EC 1440 | sw $at, 0x1C($v0) 1441 | lw $a1, 4($s0) 1442 | la $a0, acttable 1443 | sll $a1, 2 1444 | addu $a0, $a1 1445 | lw $a0, 0($a0) 1446 | beqz $a0, loc_10004BD8 1447 | nop 1448 | sb $zero, 0($a0) 1449 | lw $a3, 0x10($s0) 1450 | lw $a2, 0x1C($a3) 1451 | lw $a2, 0x14($a2) 1452 | b loc_100049EC 1453 | sw $a2, 0x1C($a3) 1454 | lw $a4, 0x10($s0) 1455 | lw $a3, 0x1C($a4) 1456 | lw $a3, 0x14($a3) 1457 | b loc_100049EC 1458 | sw $a3, 0x1C($a4) 1459 | lw $a1, 4($s0) 1460 | la $a0, acttable 1461 | sll $a1, 2 1462 | addu $a0, $a1 1463 | lw $a0, 0($a0) 1464 | beqz $a0, loc_10004C24 1465 | nop 1466 | lwc1 $f7, 0x24($a0) 1467 | swc1 $f7, 0x18($a0) 1468 | lw $a3, 0x10($s0) 1469 | lw $a2, 0x1C($a3) 1470 | lw $a2, 0x14($a2) 1471 | b loc_100049EC 1472 | sw $a2, 0x1C($a3) 1473 | lw $a1, 4($s0) 1474 | la $a0, acttable 1475 | sll $a1, 2 1476 | addu $a0, $a1 1477 | lw $a0, 0($a0) 1478 | beqz $a0, loc_10004C5C 1479 | nop 1480 | lwc1 $f8, 0xC($s0) 1481 | swc1 $f8, 0x18($a0) 1482 | lw $a3, 0x10($s0) 1483 | lw $a2, 0x1C($a3) 1484 | lw $a2, 0x14($a2) 1485 | b loc_100049EC 1486 | sw $a2, 0x1C($a3) 1487 | lw $a1, 4($s0) 1488 | la $a0, acttable 1489 | sll $a1, 2 1490 | addu $a0, $a1 1491 | lw $a0, 0($a0) 1492 | beqz $a0, loc_10004E6C 1493 | nop 1494 | lwc1 $f5, 0xC($s0) 1495 | lwc1 $f4, 0x10($a0) 1496 | c.lt.s $f4, $f5 1497 | nop 1498 | bc1f loc_10004E80 1499 | lwc1 $f6, 0xC($a0) 1500 | c.lt.s $f5, $f6 1501 | nop 1502 | bc1f loc_10004E40 1503 | nop 1504 | b loc_10004E40 1505 | mov.s $f5, $f6 1506 | lw $a1, 4($s0) 1507 | la $a0, acttable 1508 | sll $a1, 2 1509 | addu $a0, $a1 1510 | lw $a0, 0($a0) 1511 | beqz $a0, loc_10004DD8 1512 | nop 1513 | lwc1 $f5, 0xC($s0) 1514 | lwc1 $f4, 0x10($a0) 1515 | c.lt.s $f4, $f5 1516 | nop 1517 | bc1f loc_10004DD4 1518 | nop 1519 | b loc_10004DD4 1520 | mov.s $f5, $f4 1521 | lw $a3, 0x10($s0) 1522 | lw $a2, 0x1C($a3) 1523 | lw $a2, 0x14($a2) 1524 | b loc_100049EC 1525 | sw $a2, 0x1C($a3) 1526 | lw $a0, 0x24($a0) 1527 | beqz $a0, loc_10004D24 1528 | nop 1529 | lw $a3, 0($a0) 1530 | bne $a3, $a1, loc_10004D0C 1531 | nop 1532 | lw $a1, 0x10($s0) 1533 | bne $a1, $a0, loc_100049F0 1534 | ld $ra, 0x20+var_10($sp) 1535 | beqz $a0, loc_10004EB4 1536 | la $t9, killSeq__GP7animSeq 1537 | jal killSeq__GP7animSeq 1538 | nop 1539 | b loc_100049F0 1540 | ld $ra, 0x20+var_10($sp) 1541 | lw $a0, 0x24($a0) 1542 | beqz $a0, loc_10004D6C 1543 | nop 1544 | lw $a4, 0($a0) 1545 | bne $a4, $a1, loc_10004D48 1546 | nop 1547 | beqz $a0, loc_10004D6C 1548 | nop 1549 | sw $zero, 0x1C($a0) 1550 | lw $a1, 0x10($s0) 1551 | beq $a1, $a0, loc_100049F0 1552 | ld $ra, 0x20+var_10($sp) 1553 | lw $a5, 0x1C($a1) 1554 | lw $a5, 0x14($a5) 1555 | b loc_100049EC 1556 | sw $a5, 0x1C($a1) 1557 | lw $a0, 0x24($a0) 1558 | beqz $a0, loc_10004DB8 1559 | nop 1560 | lw $a6, 0($a0) 1561 | bne $a6, $a1, loc_10004D88 1562 | nop 1563 | beqz $a0, loc_10004DB8 1564 | nop 1565 | lw $a7, 0x18($a0) 1566 | sw $a7, 0x1C($a0) 1567 | lwc1 $f9, 0($a4) 1568 | swc1 $f9, 8($a0) 1569 | lw $a1, 0x10($s0) 1570 | beq $a1, $a0, loc_100049F0 1571 | ld $ra, 0x20+var_10($sp) 1572 | lw $t4, 0x1C($a1) 1573 | lw $t4, 0x14($t4) 1574 | b loc_100049EC 1575 | sw $t4, 0x1C($a1) 1576 | swc1 $f5, 0x10($a0) 1577 | lw $t6, 0x10($s0) 1578 | lw $t5, 0x1C($t6) 1579 | lw $t5, 0x14($t5) 1580 | b loc_100049EC 1581 | sw $t5, 0x1C($t6) 1582 | lw $t7, 0x10($s0) 1583 | cvt.s.d $f10, $f4 1584 | swc1 $f10, 0x10($t7) 1585 | lw $t7, 0x10($s0) 1586 | lw $t6, 0x1C($t7) 1587 | lw $t6, 0x14($t6) 1588 | b loc_100049EC 1589 | sw $t6, 0x1C($t7) 1590 | c.lt.d $f5, $f4 1591 | nop 1592 | bc1f loc_10004E20 1593 | nop 1594 | mov.d $f4, $f5 1595 | lw $t9, 0x10($s0) 1596 | cvt.s.d $f11, $f4 1597 | swc1 $f11, 0x14($t9) 1598 | lw $t9, 0x10($s0) 1599 | lw $t8, 0x1C($t9) 1600 | lw $t8, 0x14($t8) 1601 | b loc_100049EC 1602 | sw $t8, 0x1C($t9) 1603 | b loc_10004E4C 1604 | swc1 $f5, 0xC($a0) 1605 | swc1 $f5, 0x10($a0) 1606 | lw $v0, 0x10($s0) 1607 | lwc1 $f13, 0x10($v0) 1608 | swc1 $f13, 0x1C($a0) 1609 | lw $at, 0x10($s0) 1610 | lwc1 $f12, 0x14($at) 1611 | li $ra, 1 1612 | sb $ra, 0($a0) 1613 | swc1 $f12, 0x20($a0) 1614 | lw $a0, 0x10($s0) 1615 | lw $v1, 0x1C($a0) 1616 | lw $v1, 0x14($v1) 1617 | b loc_100049EC 1618 | sw $v1, 0x1C($a0) 1619 | c.lt.s $f4, $f6 1620 | nop 1621 | bc1f loc_10004E94 1622 | mov.s $f5, $f4 1623 | mov.s $f5, $f6 1624 | swc1 $f5, 0xC($a0) 1625 | lwc1 $f6, 0xC($s0) 1626 | c.lt.s $f4, $f6 1627 | nop 1628 | bc1f loc_10004E48 1629 | mov.s $f5, $f6 1630 | b loc_10004E48 1631 | mov.s $f5, $f4 1632 | lw $a0, 0x1C($a1) 1633 | lw $a0, 0x14($a0) 1634 | b loc_100049EC 1635 | sw $a0, 0x1C($a1) 1636 | addiu $sp, -0x30 1637 | sd $ra, 0x30+var_8($sp) 1638 | sd $s0, 0x30+var_18($sp) 1639 | sdc1 $f20, 0x30+var_30($sp) 1640 | sd $s2, 0x30+var_10($sp) 1641 | lui $v0, 1 1642 | sd $s1, 0x30+var_20($sp) 1643 | li $v0, 0xC0D8 1644 | sd $gp, 0x30+var_28($sp) 1645 | addu $gp, $t9, $v0 1646 | lwc1 $f1, flt_100092A8 1647 | la $s1, currentFrame 1648 | la $at, seqList 1649 | lwc1 $f0, (currentFrame - 0x1000A3BC)($s1) 1650 | lw $at, (seqList - 0x1000BF78)($at) 1651 | la $s2, processCommand__GP11animCommand 1652 | ldc1 $f20, dbl_100092D8 1653 | add.s $f0, $f1 1654 | move $s0, $at 1655 | beqz $at, loc_10004FCC 1656 | swc1 $f0, (currentFrame - 0x1000A3BC)($s1) 1657 | b loc_10004F2C 1658 | lwc1 $f4, (currentFrame - 0x1000A3BC)($s1) 1659 | lw $s0, 0x24($s0) 1660 | beqz $s0, loc_10004FCC 1661 | lwc1 $f4, 0($s1) 1662 | lwc1 $f5, 8($s0) 1663 | cvt.d.s $f4, $f4 1664 | cvt.d.s $f2, $f5 1665 | add.d $f4, $f20 1666 | c.lt.d $f2, $f4 1667 | lw $a0, 0x1C($s0) 1668 | bc1f loc_10004F20 1669 | lbu $a2, 4($s0) 1670 | beqz $a2, loc_10004F20 1671 | nop 1672 | beqz $a0, loc_10004F20 1673 | nop 1674 | lwc1 $f6, 8($a0) 1675 | add.s $f6, $f5 1676 | cvt.d.s $f6, $f6 1677 | c.lt.d $f6, $f4 1678 | nop 1679 | bc1f loc_10004F20 1680 | nop 1681 | move $t9, $s2 1682 | jal processCommand__GP11animCommand 1683 | nop 1684 | lbu $v1, 4($s0) 1685 | lwc1 $f9, 8($s0) 1686 | lwc1 $f8, 0($s1) 1687 | beqz $v1, loc_10004FC4 1688 | lw $a0, 0x1C($s0) 1689 | beqz $a0, loc_10004FC4 1690 | nop 1691 | lwc1 $f7, 8($a0) 1692 | cvt.d.s $f8, $f8 1693 | add.s $f7, $f9 1694 | add.d $f8, $f20 1695 | cvt.d.s $f7, $f7 1696 | c.lt.d $f7, $f8 1697 | nop 1698 | bc1t loc_10004F7C 1699 | move $t9, $s2 1700 | b loc_10004F24 1701 | lw $s0, 0x24($s0) 1702 | ld $gp, 0x30+var_28($sp) 1703 | ld $s0, 0x30+var_18($sp) 1704 | ld $ra, 0x30+var_8($sp) 1705 | ld $s1, 0x30+var_20($sp) 1706 | ld $s2, 0x30+var_10($sp) 1707 | ldc1 $f20, 0x30+var_30($sp) 1708 | jr $ra 1709 | addiu $sp, 0x30 1710 | addiu $sp, -0x30 1711 | sd $s2, 0x30+var_28($sp) 1712 | sd $ra, 0x30+var_18($sp) 1713 | sdc1 $f20, 0x30+var_30($sp) 1714 | sd $s1, 0x30+var_20($sp) 1715 | lui $at, 1 1716 | sd $s0, 0x30+var_10($sp) 1717 | li $at, 0xBFB0 1718 | sd $gp, 0x30+var_8($sp) 1719 | addu $gp, $t9, $at 1720 | la $s0, acttable 1721 | move $s1, $zero 1722 | b loc_10005034 1723 | lwc1 $f20, flt_100092A8 1724 | addiu $s1, 1 1725 | slti $v0, $s1, 0x400 1726 | beqz $v0, loc_10005108 1727 | addiu $s0, 4 1728 | lw $s2, 0($s0) 1729 | beqz $s2, loc_10005024 1730 | nop 1731 | lbu $v1, 0($s2) 1732 | beqz $v1, loc_10005024 1733 | lbu $a1, 1($s2) 1734 | bnez $a1, loc_10005024 1735 | la $t9, drand48 1736 | li $a0, 1 1737 | jalr $t9 1738 | sb $a0, 1($s2) 1739 | lwc1 $f3, 0xC($s2) 1740 | cvt.s.d $f0, $f0 1741 | lwc1 $f1, 0x10($s2) 1742 | sub.s $f2, $f20, $f0 1743 | mul.s $f0, $f3, $f0 1744 | la $t9, exprand__Gf 1745 | mul.s $f1, $f2 1746 | add.s $f0, $f1 1747 | mov.s $f12, $f20 1748 | jal exprand__Gf 1749 | swc1 $f0, 8($s2) 1750 | lwc1 $f6, flt_100092AC 1751 | lwc1 $f2, 0x20($s2) 1752 | lwc1 $f1, 0x1C($s2) 1753 | mul.s $f3, $f0, $f6 1754 | sub.s $f4, $f20, $f2 1755 | mul.s $f3, $f1, $f3 1756 | mul.s $f1, $f4 1757 | mul.s $f2, $f3 1758 | add.s $f1, $f2 1759 | c.lt.s $f1, $f20 1760 | nop 1761 | bc1f loc_10005128 1762 | mov.s $f5, $f20 1763 | lwc1 $f7, 0x14($s2) 1764 | lwc1 $f4, 8($s2) 1765 | sub.s $f4, $f7 1766 | div.s $f4, $f5 1767 | mtc1 $zero, $f7 1768 | nop 1769 | c.lt.s $f7, $f4 1770 | addiu $s0, 4 1771 | addiu $a2, $s1, 1 1772 | slti $a1, $s1, 0x3FF 1773 | move $s1, $a2 1774 | bc1f loc_100050FC 1775 | swc1 $f4, 0x14($s2) 1776 | b loc_10005100 1777 | mov.s $f4, $f20 1778 | lwc1 $f4, flt_100092B4 1779 | bnez $a1, loc_10005034 1780 | swc1 $f4, 4($s2) 1781 | ld $gp, 0x30+var_8($sp) 1782 | ld $s0, 0x30+var_10($sp) 1783 | ld $ra, 0x30+var_18($sp) 1784 | ld $s1, 0x30+var_20($sp) 1785 | ld $s2, 0x30+var_28($sp) 1786 | ldc1 $f20, 0x30+var_30($sp) 1787 | jr $ra 1788 | addiu $sp, 0x30 1789 | la $t9, exprand__Gf 1790 | jal exprand__Gf 1791 | mov.s $f12, $f20 1792 | lwc1 $f6, flt_100092AC 1793 | lwc1 $f7, 0x20($s2) 1794 | lwc1 $f5, 0x1C($s2) 1795 | mul.s $f8, $f0, $f6 1796 | sub.s $f9, $f20, $f7 1797 | mul.s $f8, $f5, $f8 1798 | mul.s $f5, $f9 1799 | mul.s $f7, $f8 1800 | b loc_100050C0 1801 | add.s $f5, $f7 1802 | addiu $a4, $a0, -1 1803 | sll $a6, $a0, 2 1804 | lui $v0, 1 1805 | addu $a5, $a1, $a6 1806 | li $v0, 0xBE40 1807 | blez $a0, loc_100051A0 1808 | addu $at, $t9, $v0 1809 | lwc1 $f2, (flt_100092A8 - 0x10010F9C)($at) 1810 | sll $v1, $a4, 2 1811 | lwc1 $f0, 0($a5) 1812 | addu $v1, $a1, $v1 1813 | lwc1 $f1, 0($v1) 1814 | sub.s $f2, $f14 1815 | mul.s $f0, $f14 1816 | mul.s $f1, $f2 1817 | jr $ra 1818 | add.s $f0, $f1 1819 | b loc_10005178 1820 | addiu $a4, 0x80 1821 | addiu $a4, $a0, -1 1822 | lui $v0, 1 1823 | sll $a5, $a0, 2 1824 | li $v0, 0xBDF4 1825 | blez $a0, loc_10005238 1826 | addu $at, $t9, $v0 1827 | addu $a2, $a5, $a1 1828 | lwc1 $f5, 0($a2) 1829 | sll $v1, $a4, 2 1830 | lwc1 $f8, (flt_100092B8 - 0x10010F9C)($at) 1831 | addu $v1, $a1 1832 | lwc1 $f6, 0($v1) 1833 | mul.s $f8, $f15, $f8 1834 | sub.s $f4, $f5, $f6 1835 | lwc1 $f7, (flt_100092A8 - 0x10010F9C)($at) 1836 | c.lt.s $f8, $f4 1837 | lwc1 $f9, (flt_100092BC - 0x10010F9C)($at) 1838 | bc1t loc_10005224 1839 | sub.s $f7, $f14 1840 | mul.s $f10, $f15, $f9 1841 | c.lt.s $f4, $f10 1842 | nop 1843 | bc1f loc_10005218 1844 | mul.s $f8, $f7, $f6 1845 | add.s $f0, $f5, $f15 1846 | mul.s $f0, $f14, $f0 1847 | jr $ra 1848 | add.s $f0, $f8, $f0 1849 | mul.s $f0, $f5, $f14 1850 | jr $ra 1851 | add.s $f0, $f8, $f0 1852 | add.s $f0, $f6, $f15 1853 | mul.s $f1, $f5, $f14 1854 | mul.s $f0, $f7, $f0 1855 | jr $ra 1856 | add.s $f0, $f1 1857 | b loc_100051C0 1858 | addiu $a4, 0x80 1859 | addiu $sp, -0x20 1860 | sd $s0, 0x20+var_18($sp) 1861 | sd $s1, 0x20+var_10($sp) 1862 | lui $at, 1 1863 | sd $ra, 0x20+var_8($sp) 1864 | li $at, 0xBD5C 1865 | sd $gp, 0x20+var_20($sp) 1866 | beqz $a1, loc_100052DC 1867 | addu $gp, $t9, $at 1868 | la $t9, glBegin 1869 | jalr $t9 1870 | li $a0, 9 1871 | la $s0, glVertex2f 1872 | la $s1, square 1873 | move $t9, $s0 1874 | lwc1 $f12, (square - 0x10008E50)($s1) 1875 | jalr $t9 1876 | lwc1 $f13, (square+4 - 0x10008E50)($s1) 1877 | move $t9, $s0 1878 | lwc1 $f12, (square+8 - 0x10008E50)($s1) 1879 | jalr $t9 1880 | lwc1 $f13, (square+0xC - 0x10008E50)($s1) 1881 | move $t9, $s0 1882 | lwc1 $f12, (square+0x10 - 0x10008E50)($s1) 1883 | jalr $t9 1884 | lwc1 $f13, (square+0x14 - 0x10008E50)($s1) 1885 | move $t9, $s0 1886 | lwc1 $f12, (square+0x18 - 0x10008E50)($s1) 1887 | jalr $t9 1888 | lwc1 $f13, (square+0x1C - 0x10008E50)($s1) 1889 | la $t9, glEnd 1890 | jalr $t9 1891 | nop 1892 | ld $ra, 0x20+var_8($sp) 1893 | ld $s0, 0x20+var_18($sp) 1894 | ld $s1, 0x20+var_10($sp) 1895 | ld $gp, 0x20+var_20($sp) 1896 | jr $ra 1897 | addiu $sp, 0x20 1898 | la $t9, glBegin 1899 | jalr $t9 1900 | li $a0, 1 1901 | la $s0, glVertex2f 1902 | la $s1, square 1903 | move $t9, $s0 1904 | lwc1 $f12, (square - 0x10008E50)($s1) 1905 | jalr $t9 1906 | lwc1 $f13, (square+4 - 0x10008E50)($s1) 1907 | move $t9, $s0 1908 | lwc1 $f12, (square+8 - 0x10008E50)($s1) 1909 | jalr $t9 1910 | lwc1 $f13, (square+0xC - 0x10008E50)($s1) 1911 | move $t9, $s0 1912 | lwc1 $f12, (square+8 - 0x10008E50)($s1) 1913 | jalr $t9 1914 | lwc1 $f13, (square+0xC - 0x10008E50)($s1) 1915 | move $t9, $s0 1916 | lwc1 $f12, (square+0x10 - 0x10008E50)($s1) 1917 | jalr $t9 1918 | lwc1 $f13, (square+0x14 - 0x10008E50)($s1) 1919 | move $t9, $s0 1920 | lwc1 $f12, (square+0x10 - 0x10008E50)($s1) 1921 | jalr $t9 1922 | lwc1 $f13, (square+0x14 - 0x10008E50)($s1) 1923 | move $t9, $s0 1924 | lwc1 $f12, (square+0x18 - 0x10008E50)($s1) 1925 | jalr $t9 1926 | lwc1 $f13, (square+0x1C - 0x10008E50)($s1) 1927 | move $t9, $s0 1928 | lwc1 $f12, (square+0x18 - 0x10008E50)($s1) 1929 | jalr $t9 1930 | lwc1 $f13, (square+0x1C - 0x10008E50)($s1) 1931 | move $t9, $s0 1932 | lwc1 $f12, (square - 0x10008E50)($s1) 1933 | jalr $t9 1934 | lwc1 $f13, (square+4 - 0x10008E50)($s1) 1935 | la $t9, glEnd 1936 | jalr $t9 1937 | nop 1938 | b loc_100052C8 1939 | ld $ra, 0x20+var_8($sp) 1940 | addiu $sp, -0x110 1941 | sdc1 $f22, 0x110+var_F8($sp) 1942 | lui $at, 1 1943 | sd $s0, 0x110+var_C0($sp) 1944 | li $at, 0xBC18 1945 | sd $gp, 0x110+var_B0($sp) 1946 | addu $gp, $t9, $at 1947 | lwc1 $f22, flt_100092A8 1948 | la $s0, glColor3f 1949 | mov.s $f12, $f22 1950 | move $t9, $s0 1951 | sd $s1, 0x110+var_10($sp) 1952 | mov.s $f13, $f22 1953 | sd $ra, 0x110+var_B8($sp) 1954 | jalr $t9 1955 | mov.s $f14, $f22 1956 | la $s1, glPushMatrix 1957 | move $t9, $s1 1958 | sdc1 $f20, 0x110+var_70($sp) 1959 | jalr $t9 1960 | sd $fp, 0x110+var_30($sp) 1961 | mtc1 $zero, $f20 1962 | la $fp, glRotatef 1963 | sdc1 $f24, 0x110+var_58($sp) 1964 | mov.s $f13, $f22 1965 | la $v0, wheel 1966 | move $t9, $fp 1967 | sd $s3, 0x110+var_40($sp) 1968 | mov.s $f14, $f20 1969 | lwc1 $f12, (wheel - 0x1000A3CC)($v0) 1970 | jalr $t9 1971 | mov.s $f15, $f20 1972 | lwc1 $f24, flt_100092BC 1973 | sdc1 $f26, 0x110+var_68($sp) 1974 | sdc1 $f30, 0x110+var_60($sp) 1975 | sdc1 $f28, 0x110+var_50($sp) 1976 | sd $s6, 0x110+var_38($sp) 1977 | sd $s7, 0x110+var_18($sp) 1978 | sd $s5, 0x110+var_20($sp) 1979 | la $a3, nlimit 1980 | la $a1, n 1981 | lw $v1, (nlimit - 0x1000BF70)($a3) 1982 | sd $s4, 0x110+var_28($sp) 1983 | lw $a4, (n - 0x1000BF6C)($a1) 1984 | slt $v1, $zero, $v1 1985 | sd $s2, 0x110+var_48($sp) 1986 | sd $v1, 0x110+var_A8($sp) 1987 | beqz $v1, loc_100054E4 1988 | move $s3, $a4 1989 | la $s2, twixt__GiPff 1990 | la $s4, glTranslatef 1991 | la $s5, dzoom 1992 | b loc_100054B8 1993 | la $s1, t 1994 | slti $a0, $s0, 0x80 1995 | bnez $a0, loc_10005470 1996 | move $t9, $s2 1997 | addiu $s0, -0x80 1998 | move $t9, $s2 1999 | move $a0, $s0 2000 | move $a1, $s5 2001 | jal twixt__GiPff 2002 | lwc1 $f14, 0($s1) 2003 | mov.s $f12, $f20 2004 | move $t9, $s4 2005 | mov.s $f13, $f20 2006 | jalr $t9 2007 | mul.s $f14, $f0, $f24 2008 | la $a3, nlimit 2009 | la $a1, n 2010 | lw $a0, (nlimit - 0x1000BF70)($a3) 2011 | lw $a4, (n - 0x1000BF6C)($a1) 2012 | addiu $s3, -1 2013 | subu $a0, $a4, $a0 2014 | slt $a2, $a0, $s3 2015 | beqz $a2, loc_100054E0 2016 | slt $a2, $a0, $a4 2017 | sra $a2, $s3, 31 2018 | xor $a0, $s3, $a2 2019 | subu $a0, $a2 2020 | andi $a0, 0x7F 2021 | xor $a0, $a2 2022 | subu $a0, $a2 2023 | bgez $a0, loc_1000545C 2024 | move $s0, $a0 2025 | b loc_1000545C 2026 | addiu $s0, $a0, 0x80 2027 | sd $a2, 0x110+var_A8($sp) 2028 | la $s5, foldtwixt__GiPffT3 2029 | la $s1, t 2030 | la $s4, glTranslatef 2031 | ld $at, 0x110+var_A8($sp) 2032 | la $s2, twixt__GiPff 2033 | la $s7, colRGBA 2034 | la $s6, outlinecolRGBA 2035 | beqz $at, loc_10005858 2036 | move $s3, $a4 2037 | addiu $a4, $s7, (colRGBA+8 - 0x10008E98) 2038 | sd $a4, 0x110+var_98($sp) 2039 | addiu $a2, $s7, (colRGBA+4 - 0x10008E98) 2040 | sd $a2, 0x110+var_80($sp) 2041 | addiu $v1, $s6, (outlinecolRGBA+8 - 0x10008E88) 2042 | sd $v1, 0x110+var_88($sp) 2043 | addiu $v0, $s6, (outlinecolRGBA+4 - 0x10008E88) 2044 | b loc_10005C10 2045 | sd $v0, 0x110+var_90($sp) 2046 | slti $a5, $s0, 0x80 2047 | bnez $a5, loc_10005540 2048 | move $t9, $s2 2049 | addiu $s0, -0x80 2050 | move $t9, $s2 2051 | la $a1, x 2052 | move $a0, $s0 2053 | jal twixt__GiPff 2054 | lwc1 $f14, 0($s1) 2055 | move $t9, $s2 2056 | la $a1, y 2057 | mov.s $f30, $f0 2058 | move $a0, $s0 2059 | jal twixt__GiPff 2060 | lwc1 $f14, 0($s1) 2061 | sdc1 $f0, 0x110+var_D0($sp) 2062 | move $t9, $s2 2063 | la $a1, dzoom 2064 | move $a0, $s0 2065 | jal twixt__GiPff 2066 | lwc1 $f14, 0($s1) 2067 | move $t9, $s2 2068 | la $a1, arm 2069 | mov.s $f24, $f0 2070 | move $a0, $s0 2071 | jal twixt__GiPff 2072 | lwc1 $f14, 0($s1) 2073 | sdc1 $f0, 0x110+var_C8($sp) 2074 | la $a1, wrist 2075 | move $t9, $s2 2076 | lwc1 $f14, 0($s1) 2077 | move $a0, $s0 2078 | jal twixt__GiPff 2079 | sdc1 $f24, 0x110+var_100($sp) 2080 | move $t9, $s2 2081 | la $a1, size 2082 | mov.s $f28, $f0 2083 | move $a0, $s0 2084 | jal twixt__GiPff 2085 | lwc1 $f14, 0($s1) 2086 | lwc1 $f24, flt_10009290 2087 | move $t9, $s5 2088 | mov.s $f26, $f0 2089 | la $a1, spin 2090 | move $a0, $s0 2091 | lwc1 $f14, 0($s1) 2092 | jal foldtwixt__GiPffT3 2093 | mov.s $f15, $f24 2094 | sdc1 $f0, 0x110+var_E0($sp) 2095 | la $a1, flip 2096 | move $t9, $s5 2097 | lwc1 $f14, 0($s1) 2098 | move $a0, $s0 2099 | mov.s $f15, $f24 2100 | jal foldtwixt__GiPffT3 2101 | sdc1 $f26, 0x110+var_108($sp) 2102 | sdc1 $f0, 0x110+var_D8($sp) 2103 | move $t9, $s2 2104 | la $a1, dtwist 2105 | move $a0, $s0 2106 | jal twixt__GiPff 2107 | lwc1 $f14, 0($s1) 2108 | move $t9, $s5 2109 | mov.s $f24, $f0 2110 | la $a1, hue 2111 | move $a0, $s0 2112 | lwc1 $f14, 0($s1) 2113 | jal foldtwixt__GiPffT3 2114 | mov.s $f15, $f22 2115 | la $a1, alpha 2116 | move $t9, $s2 2117 | lwc1 $f14, 0($s1) 2118 | mov.s $f26, $f0 2119 | move $a0, $s0 2120 | jal twixt__GiPff 2121 | sdc1 $f24, 0x110+var_110($sp) 2122 | sdc1 $f0, 0x110+var_E8($sp) 2123 | move $t9, $s5 2124 | la $a1, light 2125 | move $a0, $s0 2126 | lwc1 $f14, 0($s1) 2127 | jal foldtwixt__GiPffT3 2128 | mov.s $f15, $f22 2129 | move $t9, $s2 2130 | la $a1, alphaout 2131 | mov.s $f24, $f0 2132 | move $a0, $s0 2133 | jal twixt__GiPff 2134 | lwc1 $f14, 0($s1) 2135 | la $t9, hls_to_rgb__GfN21PfN24 2136 | sdc1 $f0, 0x110+var_F0($sp) 2137 | mov.s $f12, $f26 2138 | mov.s $f13, $f24 2139 | ld $a4, 0x110+var_80($sp) 2140 | mov.s $f14, $f22 2141 | move $a3, $s7 2142 | jal hls_to_rgb__GfN21PfN24 2143 | ld $a5, 0x110+var_98($sp) 2144 | lwc1 $f7, flt_100092B8 2145 | add.s $f5, $f26, $f7 2146 | ldc1 $f6, dbl_10009300 2147 | cvt.d.s $f2, $f5 2148 | ldc1 $f1, 0x110+var_F0($sp) 2149 | c.lt.d $f6, $f2 2150 | ldc1 $f0, 0x110+var_E8($sp) 2151 | swc1 $f1, 0xC($s6) 2152 | swc1 $f0, 0xC($s7) 2153 | bc1f loc_100056E8 2154 | mov.s $f12, $f5 2155 | lwc1 $f12, flt_100092B4 2156 | add.s $f12, $f5, $f12 2157 | la $t9, hls_to_rgb__GfN21PfN24 2158 | sub.s $f13, $f22, $f24 2159 | ld $a4, 0x110+var_90($sp) 2160 | mov.s $f14, $f22 2161 | move $a3, $s6 2162 | jal hls_to_rgb__GfN21PfN24 2163 | ld $a5, 0x110+var_88($sp) 2164 | la $t9, glPushMatrix 2165 | jalr $t9 2166 | nop 2167 | move $t9, $s4 2168 | mov.s $f12, $f30 2169 | ldc1 $f13, 0x110+var_D0($sp) 2170 | jalr $t9 2171 | mov.s $f14, $f20 2172 | mov.s $f13, $f20 2173 | move $t9, $fp 2174 | mov.s $f14, $f20 2175 | ldc1 $f12, 0x110+var_E0($sp) 2176 | jalr $t9 2177 | mov.s $f15, $f22 2178 | move $t9, $s4 2179 | mov.s $f12, $f20 2180 | ldc1 $f13, 0x110+var_C8($sp) 2181 | jalr $t9 2182 | mov.s $f14, $f20 2183 | mov.s $f13, $f20 2184 | move $t9, $fp 2185 | mov.s $f14, $f22 2186 | ldc1 $f12, 0x110+var_D8($sp) 2187 | jalr $t9 2188 | mov.s $f15, $f20 2189 | mov.s $f12, $f28 2190 | move $t9, $s4 2191 | mov.s $f13, $f20 2192 | jalr $t9 2193 | mov.s $f14, $f20 2194 | la $a6, fill 2195 | addu $a6, $s0, $a6 2196 | sd $a6, 0x110+var_78($sp) 2197 | lbu $a6, 0($a6) 2198 | beqz $a6, loc_100057BC 2199 | la $a7, outline 2200 | la $t9, glColor3f 2201 | lwc1 $f12, 0($s7) 2202 | lwc1 $f13, 4($s7) 2203 | jalr $t9 2204 | lwc1 $f14, 8($s7) 2205 | la $t9, drawshape__GiT1 2206 | move $a0, $s0 2207 | jal drawshape__GiT1 2208 | li $a1, 1 2209 | la $a7, outline 2210 | addu $a7, $s0, $a7 2211 | sd $a7, 0x110+var_A0($sp) 2212 | lbu $a7, 0($a7) 2213 | beqz $a7, loc_100057F8 2214 | la $t9, glPopMatrix 2215 | la $t9, glColor3f 2216 | lwc1 $f12, 0($s6) 2217 | lwc1 $f13, 4($s6) 2218 | jalr $t9 2219 | lwc1 $f14, 8($s6) 2220 | la $t9, drawshape__GiT1 2221 | move $a0, $s0 2222 | jal drawshape__GiT1 2223 | move $a1, $zero 2224 | la $t9, glPopMatrix 2225 | jalr $t9 2226 | nop 2227 | la $a1, n 2228 | la $a3, nlimit 2229 | la $t4, sflag 2230 | lbu $t4, (sflag - 0x1000A3B9)($t4) 2231 | beqz $t4, loc_100058AC 2232 | la $t9, glScalef 2233 | lw $t6, (nlimit - 0x1000BF70)($a3) 2234 | addiu $s3, -1 2235 | lw $t5, (n - 0x1000BF6C)($a1) 2236 | sra $a2, $s3, 31 2237 | xor $a0, $s3, $a2 2238 | subu $t5, $t6 2239 | subu $a0, $a2 2240 | slt $t5, $s3 2241 | andi $a0, 0x7F 2242 | xor $a0, $a2 2243 | beqz $t5, loc_10005858 2244 | subu $a0, $a2 2245 | bgez $a0, loc_1000552C 2246 | move $s0, $a0 2247 | b loc_1000552C 2248 | addiu $s0, $a0, 0x80 2249 | ld $s2, 0x110+var_48($sp) 2250 | ld $s3, 0x110+var_40($sp) 2251 | ld $s6, 0x110+var_38($sp) 2252 | ld $fp, 0x110+var_30($sp) 2253 | ld $s4, 0x110+var_28($sp) 2254 | ld $s0, 0x110+var_C0($sp) 2255 | ld $s5, 0x110+var_20($sp) 2256 | ld $s7, 0x110+var_18($sp) 2257 | ld $s1, 0x110+var_10($sp) 2258 | ldc1 $f20, 0x110+var_70($sp) 2259 | ldc1 $f26, 0x110+var_68($sp) 2260 | ldc1 $f30, 0x110+var_60($sp) 2261 | la $t9, glPopMatrix 2262 | ldc1 $f22, 0x110+var_F8($sp) 2263 | ldc1 $f24, 0x110+var_58($sp) 2264 | jalr $t9 2265 | ldc1 $f28, 0x110+var_50($sp) 2266 | ld $ra, 0x110+var_B8($sp) 2267 | ld $gp, 0x110+var_B0($sp) 2268 | jr $ra 2269 | addiu $sp, 0x110 2270 | mov.s $f12, $f22 2271 | lwc1 $f13, flt_100092B4 2272 | jalr $t9 2273 | mov.s $f14, $f22 2274 | la $t9, glPushMatrix 2275 | jalr $t9 2276 | nop 2277 | move $t9, $s4 2278 | mov.s $f12, $f30 2279 | ldc1 $f13, 0x110+var_D0($sp) 2280 | jalr $t9 2281 | mov.s $f14, $f20 2282 | mov.s $f13, $f20 2283 | move $t9, $fp 2284 | mov.s $f14, $f20 2285 | ldc1 $f12, 0x110+var_E0($sp) 2286 | jalr $t9 2287 | mov.s $f15, $f22 2288 | move $t9, $s4 2289 | mov.s $f12, $f20 2290 | ldc1 $f13, 0x110+var_C8($sp) 2291 | jalr $t9 2292 | mov.s $f14, $f20 2293 | mov.s $f13, $f20 2294 | move $t9, $fp 2295 | mov.s $f14, $f22 2296 | ldc1 $f12, 0x110+var_D8($sp) 2297 | jalr $t9 2298 | mov.s $f15, $f20 2299 | mov.s $f12, $f28 2300 | move $t9, $s4 2301 | mov.s $f13, $f20 2302 | jalr $t9 2303 | mov.s $f14, $f20 2304 | ldc1 $f13, 0x110+var_108($sp) 2305 | la $t9, glScalef 2306 | mov.s $f14, $f22 2307 | jalr $t9 2308 | mov.s $f12, $f13 2309 | ld $a1, 0x110+var_78($sp) 2310 | lbu $a1, 0($a1) 2311 | beqz $a1, loc_10005980 2312 | ld $a2, 0x110+var_A0($sp) 2313 | la $t9, glColor3f 2314 | lwc1 $f12, 0($s7) 2315 | lwc1 $f13, 4($s7) 2316 | jalr $t9 2317 | lwc1 $f14, 8($s7) 2318 | la $t9, drawshape__GiT1 2319 | move $a0, $s0 2320 | jal drawshape__GiT1 2321 | li $a1, 1 2322 | ld $a2, 0x110+var_A0($sp) 2323 | lbu $a2, 0($a2) 2324 | beqz $a2, loc_100059B4 2325 | la $t9, glPopMatrix 2326 | la $t9, glColor3f 2327 | lwc1 $f12, 0($s6) 2328 | lwc1 $f13, 4($s6) 2329 | jalr $t9 2330 | lwc1 $f14, 8($s6) 2331 | la $t9, drawshape__GiT1 2332 | move $a0, $s0 2333 | jal drawshape__GiT1 2334 | move $a1, $zero 2335 | la $t9, glPopMatrix 2336 | jalr $t9 2337 | nop 2338 | mov.s $f13, $f20 2339 | move $t9, $fp 2340 | mov.s $f14, $f20 2341 | lwc1 $f12, flt_100092A0 2342 | jalr $t9 2343 | mov.s $f15, $f22 2344 | la $t9, glPushMatrix 2345 | jalr $t9 2346 | nop 2347 | move $t9, $s4 2348 | mov.s $f12, $f30 2349 | ldc1 $f13, 0x110+var_D0($sp) 2350 | jalr $t9 2351 | mov.s $f14, $f20 2352 | mov.s $f13, $f20 2353 | move $t9, $fp 2354 | mov.s $f14, $f20 2355 | ldc1 $f12, 0x110+var_E0($sp) 2356 | jalr $t9 2357 | mov.s $f15, $f22 2358 | move $t9, $s4 2359 | mov.s $f12, $f20 2360 | ldc1 $f13, 0x110+var_C8($sp) 2361 | jalr $t9 2362 | mov.s $f14, $f20 2363 | mov.s $f13, $f20 2364 | move $t9, $fp 2365 | mov.s $f14, $f22 2366 | ldc1 $f12, 0x110+var_D8($sp) 2367 | jalr $t9 2368 | mov.s $f15, $f20 2369 | mov.s $f12, $f28 2370 | move $t9, $s4 2371 | mov.s $f13, $f20 2372 | jalr $t9 2373 | mov.s $f14, $f20 2374 | ldc1 $f13, 0x110+var_108($sp) 2375 | la $t9, glScalef 2376 | mov.s $f14, $f22 2377 | jalr $t9 2378 | mov.s $f12, $f13 2379 | ld $a3, 0x110+var_78($sp) 2380 | lbu $a3, 0($a3) 2381 | beqz $a3, loc_10005A90 2382 | la $t9, glColor3f 2383 | lwc1 $f12, 0($s7) 2384 | lwc1 $f13, 4($s7) 2385 | jalr $t9 2386 | lwc1 $f14, 8($s7) 2387 | la $t9, drawshape__GiT1 2388 | move $a0, $s0 2389 | jal drawshape__GiT1 2390 | li $a1, 1 2391 | ld $a4, 0x110+var_A0($sp) 2392 | lbu $a4, 0($a4) 2393 | beqz $a4, loc_10005AC0 2394 | la $t9, glColor3f 2395 | lwc1 $f12, 0($s6) 2396 | lwc1 $f13, 4($s6) 2397 | jalr $t9 2398 | lwc1 $f14, 8($s6) 2399 | la $t9, drawshape__GiT1 2400 | move $a0, $s0 2401 | jal drawshape__GiT1 2402 | move $a1, $zero 2403 | la $t9, glPopMatrix 2404 | jalr $t9 2405 | nop 2406 | la $t9, glScalef 2407 | mov.s $f12, $f22 2408 | lwc1 $f13, flt_100092B4 2409 | jalr $t9 2410 | mov.s $f14, $f22 2411 | la $t9, glPushMatrix 2412 | jalr $t9 2413 | nop 2414 | move $t9, $s4 2415 | mov.s $f12, $f30 2416 | ldc1 $f13, 0x110+var_D0($sp) 2417 | jalr $t9 2418 | mov.s $f14, $f20 2419 | mov.s $f13, $f20 2420 | move $t9, $fp 2421 | mov.s $f14, $f20 2422 | ldc1 $f12, 0x110+var_E0($sp) 2423 | jalr $t9 2424 | mov.s $f15, $f22 2425 | move $t9, $s4 2426 | mov.s $f12, $f20 2427 | ldc1 $f13, 0x110+var_C8($sp) 2428 | jalr $t9 2429 | mov.s $f14, $f20 2430 | mov.s $f13, $f20 2431 | move $t9, $fp 2432 | mov.s $f14, $f22 2433 | ldc1 $f12, 0x110+var_D8($sp) 2434 | jalr $t9 2435 | mov.s $f15, $f20 2436 | mov.s $f12, $f28 2437 | move $t9, $s4 2438 | mov.s $f13, $f20 2439 | jalr $t9 2440 | mov.s $f14, $f20 2441 | ldc1 $f13, 0x110+var_108($sp) 2442 | la $t9, glScalef 2443 | mov.s $f14, $f22 2444 | jalr $t9 2445 | mov.s $f12, $f13 2446 | ld $a5, 0x110+var_78($sp) 2447 | lbu $a5, 0($a5) 2448 | beqz $a5, loc_10005B9C 2449 | la $t9, glColor3f 2450 | lwc1 $f12, 0($s7) 2451 | lwc1 $f13, 4($s7) 2452 | jalr $t9 2453 | lwc1 $f14, 8($s7) 2454 | la $t9, drawshape__GiT1 2455 | move $a0, $s0 2456 | jal drawshape__GiT1 2457 | li $a1, 1 2458 | ld $a6, 0x110+var_A0($sp) 2459 | lbu $a6, 0($a6) 2460 | beqz $a6, loc_10005BCC 2461 | la $t9, glColor3f 2462 | lwc1 $f12, 0($s6) 2463 | lwc1 $f13, 4($s6) 2464 | jalr $t9 2465 | lwc1 $f14, 8($s6) 2466 | la $t9, drawshape__GiT1 2467 | move $a0, $s0 2468 | jal drawshape__GiT1 2469 | move $a1, $zero 2470 | la $t9, glPopMatrix 2471 | jalr $t9 2472 | nop 2473 | mov.s $f13, $f20 2474 | move $t9, $fp 2475 | mov.s $f14, $f20 2476 | ldc1 $f12, 0x110+var_110($sp) 2477 | jalr $t9 2478 | mov.s $f15, $f22 2479 | move $t9, $s4 2480 | mov.s $f12, $f20 2481 | mov.s $f13, $f20 2482 | jalr $t9 2483 | ldc1 $f14, 0x110+var_100($sp) 2484 | la $a1, n 2485 | b loc_10005818 2486 | la $a3, nlimit 2487 | sra $a2, $s3, 31 2488 | xor $a0, $s3, $a2 2489 | subu $a0, $a2 2490 | andi $a0, 0x7F 2491 | xor $a0, $a2 2492 | subu $a0, $a2 2493 | b loc_10005848 2494 | nop 2495 | li $v0, 0xB36C 2496 | dmtc1 $zero, $f9 2497 | addu $at, $t9, $v0 2498 | move $a3, $zero 2499 | b loc_10005C54 2500 | lw $a4, (acttable_ptr - 0x10010F9C)($at) 2501 | swc1 $f5, 0x18($a2) 2502 | beqz $a5, locret_10005CB8 2503 | addiu $a3, 1 2504 | lw $a2, 0($a4) 2505 | addiu $a4, 4 2506 | beqz $a2, loc_10005C50 2507 | slti $a5, $a3, 0x400 2508 | lwc1 $f8, 0x18($a2) 2509 | lwc1 $f7, 4($a2) 2510 | lbu $v1, 0($a2) 2511 | lwc1 $f4, 8($a2) 2512 | lbu $a6, 1($a2) 2513 | beqz $v1, loc_10005C50 2514 | lwc1 $f6, 0x14($a2) 2515 | beqz $a6, loc_10005C50 2516 | nop 2517 | add.s $f5, $f6, $f8 2518 | sub.s $f0, $f4, $f5 2519 | mul.s $f0, $f7, $f0 2520 | cvt.d.s $f0, $f0 2521 | c.lt.d $f0, $f9 2522 | nop 2523 | bc1f loc_10005C4C 2524 | nop 2525 | mov.s $f5, $f4 2526 | b loc_10005C4C 2527 | sb $zero, 1($a2) 2528 | jr $ra 2529 | nop 2530 | lui $at, 1 2531 | addiu $sp, -0x10 2532 | li $at, 0xB2DC 2533 | sd $gp, 0x10+var_8($sp) 2534 | addu $gp, $t9, $at 2535 | la $t9, malloc 2536 | sd $ra, 0x10+var_10($sp) 2537 | jalr $t9 2538 | li $a0, 0x28 2539 | lwc1 $f2, flt_100092A8 2540 | lwc1 $f1, flt_100092C0 2541 | ld $gp, 0x10+var_8($sp) 2542 | mtc1 $zero, $f0 2543 | swc1 $f2, 4($v0) 2544 | swc1 $f0, 8($v0) 2545 | swc1 $f0, 0xC($v0) 2546 | swc1 $f0, 0x10($v0) 2547 | swc1 $f0, 0x14($v0) 2548 | swc1 $f0, 0x18($v0) 2549 | ld $ra, 0x10+var_10($sp) 2550 | swc1 $f0, 0x1C($v0) 2551 | swc1 $f1, 0x20($v0) 2552 | addiu $sp, 0x10 2553 | jr $ra 2554 | swc1 $f0, 0x24($v0) 2555 | addiu $sp, -0x20 2556 | lui $at, 1 2557 | sd $s1, 0x20+var_20($sp) 2558 | li $at, 0xB278 2559 | sd $gp, 0x20+var_10($sp) 2560 | addu $gp, $t9, $at 2561 | la $s1, createBlankActAnim__Gv 2562 | move $t9, $s1 2563 | sd $ra, 0x20+var_18($sp) 2564 | jal createBlankActAnim__Gv 2565 | sd $s0, 0x20+var_8($sp) 2566 | la $s0, acttable 2567 | move $t9, $s1 2568 | jal createBlankActAnim__Gv 2569 | sw $v0, (acttable+0x48 - 0x100093B8)($s0) 2570 | move $t9, $s1 2571 | jal createBlankActAnim__Gv 2572 | sw $v0, (acttable+0x124 - 0x100093B8)($s0) 2573 | move $t9, $s1 2574 | jal createBlankActAnim__Gv 2575 | sw $v0, (acttable+0x7C - 0x100093B8)($s0) 2576 | move $t9, $s1 2577 | jal createBlankActAnim__Gv 2578 | sw $v0, (acttable+0x98 - 0x100093B8)($s0) 2579 | move $t9, $s1 2580 | jal createBlankActAnim__Gv 2581 | sw $v0, (acttable+0x140 - 0x100093B8)($s0) 2582 | move $t9, $s1 2583 | jal createBlankActAnim__Gv 2584 | sw $v0, (acttable+0x1B0 - 0x100093B8)($s0) 2585 | lwc1 $f0, flt_100092C4 2586 | move $t9, $s1 2587 | swc1 $f0, 0x18($v0) 2588 | jal createBlankActAnim__Gv 2589 | sw $v0, (acttable+0xD0 - 0x100093B8)($s0) 2590 | move $t9, $s1 2591 | jal createBlankActAnim__Gv 2592 | sw $v0, (acttable+0x194 - 0x100093B8)($s0) 2593 | move $t9, $s1 2594 | jal createBlankActAnim__Gv 2595 | sw $v0, (acttable+0x1FC - 0x100093B8)($s0) 2596 | move $t9, $s1 2597 | jal createBlankActAnim__Gv 2598 | sw $v0, (acttable+0x1EC - 0x100093B8)($s0) 2599 | move $t9, $s1 2600 | jal createBlankActAnim__Gv 2601 | sw $v0, (acttable+0x15C - 0x100093B8)($s0) 2602 | move $t9, $s1 2603 | jal createBlankActAnim__Gv 2604 | sw $v0, (acttable+0x178 - 0x100093B8)($s0) 2605 | lwc1 $f1, flt_100092A8 2606 | move $t9, $s1 2607 | swc1 $f1, 0x18($v0) 2608 | jal createBlankActAnim__Gv 2609 | sw $v0, (acttable+0xB4 - 0x100093B8)($s0) 2610 | ld $s1, 0x20+var_20($sp) 2611 | ld $ra, 0x20+var_18($sp) 2612 | ld $gp, 0x20+var_10($sp) 2613 | sw $v0, (acttable+0x208 - 0x100093B8)($s0) 2614 | ld $s0, 0x20+var_8($sp) 2615 | jr $ra 2616 | addiu $sp, 0x20 2617 | lui $at, 1 2618 | addiu $sp, -0x20 2619 | li $at, 0xB180 2620 | sd $gp, 0x20+var_10($sp) 2621 | addu $gp, $t9, $at 2622 | la $t9, glViewport 2623 | move $a3, $a1 2624 | sd $s3, 0x20+var_20($sp) 2625 | move $s3, $a0 2626 | move $a0, $zero 2627 | sd $a1, 0x20+var_8($sp) 2628 | move $a1, $zero 2629 | sd $ra, 0x20+var_18($sp) 2630 | jalr $t9 2631 | move $a2, $s3 2632 | la $t9, glMatrixMode 2633 | jalr $t9 2634 | li $a0, 0x1701 2635 | la $t9, glLoadIdentity 2636 | jalr $t9 2637 | nop 2638 | ld $v0, 0x20+var_8($sp) 2639 | mtc1 $s3, $f13 2640 | mtc1 $v0, $f14 2641 | cvt.s.w $f13, $f13 2642 | cvt.s.w $f14, $f14 2643 | div.s $f13, $f14 2644 | la $t9, gluPerspective 2645 | ldc1 $f15, dbl_10009320 2646 | ldc1 $f12, dbl_10009310 2647 | ldc1 $f14, dbl_10009318 2648 | jalr $t9 2649 | cvt.d.s $f13, $f13 2650 | mtc1 $zero, $f12 2651 | la $t9, glTranslatef 2652 | ld $s3, 0x20+var_20($sp) 2653 | lwc1 $f14, flt_100092C8 2654 | jalr $t9 2655 | mov.s $f13, $f12 2656 | la $t9, glMatrixMode 2657 | jalr $t9 2658 | li $a0, 0x1700 2659 | ld $ra, 0x20+var_18($sp) 2660 | ld $gp, 0x20+var_10($sp) 2661 | jr $ra 2662 | addiu $sp, 0x20 2663 | lui $at, 1 2664 | addiu $sp, -0x50 2665 | li $at, 0xB0C8 2666 | sd $gp, 0x50+var_30($sp) 2667 | addu $gp, $t9, $at 2668 | la $t9, glClear 2669 | sd $ra, 0x50+var_38($sp) 2670 | li $a0, 0x4000 2671 | jalr $t9 2672 | sdc1 $f20, 0x50+var_28($sp) 2673 | lwc1 $f20, flt_100092A8 2674 | la $t9, glColor3f 2675 | mov.s $f14, $f20 2676 | mov.s $f13, $f20 2677 | sd $s0, 0x50+var_8($sp) 2678 | jalr $t9 2679 | mov.s $f12, $f20 2680 | la $s0, acttable 2681 | la $v1, t 2682 | lw $v0, (acttable+0xB4 - 0x100093B8)($s0) 2683 | lwc1 $f1, (t - 0x1000BF74)($v1) 2684 | lwc1 $f2, 0x18($v0) 2685 | sd $s1, 0x50+var_20($sp) 2686 | la $s1, n 2687 | ldc1 $f0, dbl_10009300 2688 | add.s $f1, $f2 2689 | lw $a0, (n - 0x1000BF6C)($s1) 2690 | cvt.d.s $f1, $f1 2691 | addiu $a0, 1 2692 | sd $s2, 0x50+var_18($sp) 2693 | sra $a3, $a0, 31 2694 | c.le.d $f0, $f1 2695 | la $a2, aflag 2696 | xor $a0, $a3 2697 | sd $s3, 0x50+var_10($sp) 2698 | li $s3, 1 2699 | subu $a0, $a3 2700 | lbu $a1, (aflag - 0x10008E48)($a2) 2701 | mtc1 $zero, $f0 2702 | bc1f loc_10005F8C 2703 | andi $a0, 0x7F 2704 | swc1 $f0, (t - 0x1000BF74)($v1) 2705 | xor $a0, $a3 2706 | subu $a0, $a3 2707 | b loc_10005F90 2708 | sw $a0, (n - 0x1000BF6C)($s1) 2709 | move $s3, $zero 2710 | beqz $a1, loc_10005FB8 2711 | la $t9, tasteQueue__Gv 2712 | jal tasteQueue__Gv 2713 | nop 2714 | la $t9, setacttargets__Gv 2715 | jal setacttargets__Gv 2716 | nop 2717 | la $t9, animateacts__Gv 2718 | jal animateacts__Gv 2719 | nop 2720 | la $t9, floor 2721 | la $a2, dtwist 2722 | la $a4, dwheel 2723 | la $a6, wrist 2724 | la $t4, arm 2725 | la $s2, n 2726 | la $t6, dzoom 2727 | lw $s2, (n - 0x1000BF6C)($s2) 2728 | mtc1 $zero, $f18 2729 | la $t8, y 2730 | la $ra, x 2731 | sll $s1, $s2, 2 2732 | lw $t7, (acttable+0x7C - 0x100093B8)($s0) 2733 | addu $t8, $s1, $t8 2734 | addu $ra, $s1, $ra 2735 | swc1 $f18, 0($t8) 2736 | swc1 $f18, 0($ra) 2737 | lwc1 $f17, 0x18($t7) 2738 | lw $t5, (acttable+0x178 - 0x100093B8)($s0) 2739 | addu $t6, $s1, $t6 2740 | swc1 $f17, 0($t6) 2741 | lwc1 $f16, 0x18($t5) 2742 | lw $a7, (acttable+0x194 - 0x100093B8)($s0) 2743 | addu $t4, $s1, $t4 2744 | swc1 $f16, 0($t4) 2745 | lwc1 $f15, 0x18($a7) 2746 | lw $a5, (acttable+0x124 - 0x100093B8)($s0) 2747 | addu $a6, $s1, $a6 2748 | swc1 $f15, 0($a6) 2749 | lwc1 $f14, 0x18($a5) 2750 | lw $a3, (acttable+0x98 - 0x100093B8)($s0) 2751 | swc1 $f14, (dwheel - 0x1000A3D0)($a4) 2752 | lwc1 $f13, 0x18($a3) 2753 | lw $a1, (acttable+0xD0 - 0x100093B8)($s0) 2754 | addu $a2, $s1, $a2 2755 | swc1 $f13, 0($a2) 2756 | lwc1 $f12, 0x18($a1) 2757 | sdc1 $f14, 0x50+var_50($sp) 2758 | jalr $t9 2759 | cvt.d.s $f12, $f12 2760 | la $a6, nlimit 2761 | trunc.w.d $f23, $f0 2762 | swc1 $f23, (nlimit - 0x1000BF70)($a6) 2763 | lw $a5, (acttable+0x48 - 0x100093B8)($s0) 2764 | lwc1 $f21, 0x18($a5) 2765 | dmtc1 $zero, $f19 2766 | cvt.d.s $f21, $f21 2767 | la $a4, outline 2768 | c.lt.d $f19, $f21 2769 | li $a3, 1 2770 | addu $a4, $s2, $a4 2771 | lw $a2, (acttable+0x1EC - 0x100093B8)($s0) 2772 | bc1t loc_10006094 2773 | nop 2774 | move $a3, $zero 2775 | sb $a3, 0($a4) 2776 | lwc1 $f5, 0x18($a2) 2777 | lwc1 $f6, flt_100092B4 2778 | la $a1, hue 2779 | c.le.s $f20, $f5 2780 | la $a3, light 2781 | addu $a1, $s1, $a1 2782 | lw $a2, (acttable+0x208 - 0x100093B8)($s0) 2783 | addu $a7, $s1, $a3 2784 | bc1f loc_100060C8 2785 | swc1 $f5, 0($a1) 2786 | add.s $f5, $f6 2787 | swc1 $f5, 0($a1) 2788 | c.le.s $f5, $f20 2789 | nop 2790 | bc1f loc_100060E0 2791 | nop 2792 | add.s $f25, $f5, $f20 2793 | swc1 $f25, 0($a1) 2794 | lwc1 $f27, 0x18($a2) 2795 | lwc1 $f20, flt_10009290 2796 | beqz $s3, loc_10006194 2797 | swc1 $f27, 0($a7) 2798 | lw $t5, 0x140($s0) 2799 | la $t6, dflip 2800 | lw $t7, 0x15C($s0) 2801 | la $s3, gflip 2802 | lwc1 $f13, 0x18($t7) 2803 | lwc1 $f12, (gflip - 0x1000BF58)($s3) 2804 | la $s3, fmodf 2805 | swc1 $f13, (dflip - 0x1000BF5C)($t6) 2806 | lwc1 $f29, 0x18($t5) 2807 | la $t4, dspin 2808 | move $t9, $s3 2809 | sdc1 $f29, 0x50+var_48($sp) 2810 | add.s $f12, $f13 2811 | mov.s $f13, $f20 2812 | jalr $t9 2813 | swc1 $f29, (dspin - 0x1000BF64)($t4) 2814 | la $s1, gspin 2815 | ldc1 $f13, 0x50+var_48($sp) 2816 | lwc1 $f12, (gspin - 0x1000BF60)($s1) 2817 | move $t9, $s3 2818 | la $t8, gflip 2819 | sdc1 $f0, 0x50+var_40($sp) 2820 | swc1 $f0, (gflip - 0x1000BF58)($t8) 2821 | add.s $f12, $f13 2822 | jalr $t9 2823 | mov.s $f13, $f20 2824 | sra $ra, $s2, 31 2825 | xor $t9, $s2, $ra 2826 | subu $t9, $ra 2827 | andi $t9, 0x7F 2828 | ldc1 $f15, 0x50+var_40($sp) 2829 | xor $t9, $ra 2830 | la $at, flip 2831 | subu $t9, $ra 2832 | la $ra, spin 2833 | sll $t9, 2 2834 | swc1 $f0, (gspin - 0x1000BF60)($s1) 2835 | addu $at, $t9, $at 2836 | addu $t9, $ra 2837 | swc1 $f15, 0($at) 2838 | swc1 $f0, 0($t9) 2839 | la $t9, fmodf 2840 | la $ra, wheel 2841 | ldc1 $f13, 0x50+var_50($sp) 2842 | lwc1 $f12, (wheel - 0x1000A3CC)($ra) 2843 | ld $s1, 0x50+var_20($sp) 2844 | ld $s2, 0x50+var_18($sp) 2845 | ld $s3, 0x50+var_10($sp) 2846 | sub.s $f12, $f13 2847 | jalr $t9 2848 | mov.s $f13, $f20 2849 | la $t9, drawit__Gv 2850 | la $at, wheel 2851 | ldc1 $f20, 0x50+var_28($sp) 2852 | jal drawit__Gv 2853 | swc1 $f0, (wheel - 0x1000A3CC)($at) 2854 | lw $v1, 0xB4($s0) 2855 | la $v0, t 2856 | lwc1 $f15, 0x18($v1) 2857 | lwc1 $f14, (t - 0x1000BF74)($v0) 2858 | la $t9, glFinish 2859 | add.s $f14, $f15 2860 | jalr $t9 2861 | swc1 $f14, (t - 0x1000BF74)($v0) 2862 | la $t9, swapBuffers__Q2_10GLXWrapper6windowGv 2863 | la $a0, theWindow 2864 | ld $s0, 0x50+var_8($sp) 2865 | jal swapBuffers__Q2_10GLXWrapper6windowGv 2866 | lw $a0, (theWindow - 0x1000BF80)($a0) 2867 | la $t9, sginap 2868 | jalr $t9 2869 | move $a0, $zero 2870 | ld $ra, 0x50+var_38($sp) 2871 | ld $gp, 0x50+var_30($sp) 2872 | jr $ra 2873 | addiu $sp, 0x50 2874 | li $v1, 0xFF1B 2875 | li $v0, 0xAD7C 2876 | beq $a0, $v1, loc_1000623C 2877 | addu $at, $t9, $v0 2878 | jr $ra 2879 | nop 2880 | lw $a0, (theWindow_ptr - 0x10010F9C)($at) 2881 | lw $a0, 0($a0) 2882 | li $v1, 1 2883 | jr $ra 2884 | sb $v1, 0x28($a0) 2885 | addiu $sp, -0x20 2886 | lui $at, 1 2887 | sd $ra, 0x20+var_8($sp) 2888 | li $at, 0xAD4C 2889 | sd $gp, 0x20+var_18($sp) 2890 | addu $gp, $t9, $at 2891 | move $a0, $zero 2892 | la $v0, acttable 2893 | addiu $a0, 1 2894 | slti $v1, $a0, 0x400 2895 | addiu $v0, 4 2896 | bnez $v1, loc_10006270 2897 | sw $zero, -4($v0) 2898 | la $t9, createActTable__Gv 2899 | jal createActTable__Gv 2900 | sd $s0, 0x20+var_10($sp) 2901 | la $a0, outline 2902 | la $a4, aflag 2903 | move $v0, $zero 2904 | li $s0, 1 2905 | la $a1, fill 2906 | addiu $v0, 1 2907 | slti $a2, $v0, 0x80 2908 | addiu $a1, 1 2909 | sb $s0, 0($a0) 2910 | addiu $a0, 1 2911 | bnez $a2, loc_100062A4 2912 | sb $s0, -1($a1) 2913 | lbu $a3, 0($a4) 2914 | beqz $a3, loc_100062DC 2915 | la $t9, srand48 2916 | la $t9, readAnimation__Gv 2917 | jal readAnimation__Gv 2918 | nop 2919 | la $t9, srand48 2920 | jalr $t9 2921 | move $a0, $zero 2922 | la $t9, time 2923 | jalr $t9 2924 | move $a0, $zero 2925 | la $t9, srand48 2926 | jalr $t9 2927 | move $a0, $v0 2928 | sw $zero, 0x20+var_20($sp) 2929 | la $a6, nlimit 2930 | la $t9, __nw__GUi 2931 | la $a4, wheel 2932 | mtc1 $zero, $f0 2933 | li $a5, 0x34 2934 | sw $a5, (nlimit - 0x1000BF70)($a6) 2935 | li $a0, 0x4C 2936 | jalr $t9 2937 | swc1 $f0, (wheel - 0x1000A3CC)($a4) 2938 | beqz $v0, loc_10006364 2939 | sw $v0, 0x20+var_1C($sp) 2940 | sw $s0, 0x20+var_20($sp) 2941 | move $a0, $v0 2942 | la $t9, __ct__Q2_10GLXWrapper6windowGPciN32 2943 | move $a2, $zero 2944 | move $a3, $zero 2945 | la $a1, 0x10010000 2946 | li $a4, 0x280 2947 | li $a5, 0x1E0 2948 | jal __ct__Q2_10GLXWrapper6windowGPciN32 2949 | addiu $a1, (aElectropaint - 0x10010000) 2950 | lw $v0, 0x20+var_1C($sp) 2951 | sw $zero, 0x20+var_20($sp) 2952 | b loc_10006368 2953 | nop 2954 | move $v0, $zero 2955 | mtc1 $zero, $f12 2956 | la $t9, glClearColor 2957 | la $s0, theWindow 2958 | lwc1 $f15, flt_100092A8 2959 | mov.s $f14, $f12 2960 | sw $v0, (theWindow - 0x1000BF80)($s0) 2961 | jalr $t9 2962 | mov.s $f13, $f12 2963 | la $t9, glShadeModel 2964 | jalr $t9 2965 | li $a0, 0x1D00 2966 | la $t9, glClear 2967 | jalr $t9 2968 | li $a0, 0x4000 2969 | la $t9, setRedraw__Q2_10GLXWrapper6windowGPGv_v 2970 | la $a1, display__Gv 2971 | jal setRedraw__Q2_10GLXWrapper6windowGPGv_v 2972 | lw $a0, (theWindow - 0x1000BF80)($s0) 2973 | la $t9, setReshape__Q2_10GLXWrapper6windowGPGiT1_v 2974 | la $a1, reshape__GiT1 2975 | jal setReshape__Q2_10GLXWrapper6windowGPGiT1_v 2976 | lw $a0, (theWindow - 0x1000BF80)($s0) 2977 | la $t9, setIdle__Q2_10GLXWrapper6windowGPGv_v 2978 | la $a1, display__Gv 2979 | jal setIdle__Q2_10GLXWrapper6windowGPGv_v 2980 | lw $a0, (theWindow - 0x1000BF80)($s0) 2981 | la $t9, setKeyboard__Q2_10GLXWrapper6windowGPGi_v 2982 | la $a1, keyboard__Gi 2983 | jal setKeyboard__Q2_10GLXWrapper6windowGPGi_v 2984 | lw $a0, (theWindow - 0x1000BF80)($s0) 2985 | la $t9, mainLoop__Q2_10GLXWrapper6windowGv 2986 | jal mainLoop__Q2_10GLXWrapper6windowGv 2987 | lw $a0, (theWindow - 0x1000BF80)($s0) 2988 | lw $v0, (theWindow - 0x1000BF80)($s0) 2989 | beqz $v0, loc_10006414 2990 | ld $ra, 0x20+var_8($sp) 2991 | lw $a0, 0x48($v0) 2992 | lw $t9, 0x14($a0) 2993 | lw $a0, 0xC($a0) 2994 | li $a1, 3 2995 | jalr $t9 2996 | addu $a0, $v0 2997 | ld $ra, 0x20+var_8($sp) 2998 | move $v0, $zero 2999 | ld $s0, 0x20+var_10($sp) 3000 | ld $gp, 0x20+var_18($sp) 3001 | jr $ra 3002 | addiu $sp, 0x20 3003 | lw $at, 0($a1) 3004 | li $v0, 0x13 3005 | bne $at, $v0, locret_10006448 3006 | lw $v1, 0x14($a1) 3007 | bne $v1, $a2, locret_10006448 3008 | li $v0, 1 3009 | jr $ra 3010 | nop 3011 | jr $ra 3012 | move $v0, $zero 3013 | jr $ra 3014 | li $v0, 1 3015 | jr $ra 3016 | nop 3017 | --------------------------------------------------------------------------------