├── .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 |
--------------------------------------------------------------------------------