[Scummvm-cvs-logs] SF.net SVN: scummvm: [28579] tools/branches/gsoc2007-decompiler

brixxie at users.sourceforge.net brixxie at users.sourceforge.net
Mon Aug 13 05:38:23 CEST 2007


Revision: 28579
          http://scummvm.svn.sourceforge.net/scummvm/?rev=28579&view=rev
Author:   brixxie
Date:     2007-08-12 20:38:23 -0700 (Sun, 12 Aug 2007)

Log Message:
-----------
diassembler for versions 0 to 5

svn propset ...

removing *.pyc files which were carelessly added

Added Paths:
-----------
    tools/branches/gsoc2007-decompiler/finalD/
    tools/branches/gsoc2007-decompiler/finalD/bytecode.py
    tools/branches/gsoc2007-decompiler/finalD/decompiler.py
    tools/branches/gsoc2007-decompiler/finalD/disasm.py
    tools/branches/gsoc2007-decompiler/finalD/docs/
    tools/branches/gsoc2007-decompiler/finalD/docs/v0_support.txt
    tools/branches/gsoc2007-decompiler/finalD/docs/v2_support.txt
    tools/branches/gsoc2007-decompiler/finalD/docs/v5_support.txt
    tools/branches/gsoc2007-decompiler/finalD/iformat.py
    tools/branches/gsoc2007-decompiler/finalD/scumm.py
    tools/branches/gsoc2007-decompiler/finalD/test_bytecode.py

Property Changed:
----------------
    tools/branches/gsoc2007-decompiler/


Property changes on: tools/branches/gsoc2007-decompiler
___________________________________________________________________
Name: svk:merge
   - 489ca303-0d3d-4dc1-a57d-017c7912a06a:/local/gsoc2007-decompiler:65
   + 489ca303-0d3d-4dc1-a57d-017c7912a06a:/local/gsoc2007-decompiler:71

Added: tools/branches/gsoc2007-decompiler/finalD/bytecode.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/bytecode.py	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/bytecode.py	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,180 @@
+"""Classes and functions for reading and handling of bytecode."""
+
+import array
+
+
+class Error(Exception):
+    """Base class for exceptions in this module."""
+    pass
+
+class OutOfBoundsError(Error):
+    """Error raised when bytecode is reached."""
+    pass
+
+class IncompleteFetchError(Error):
+    """Error raised when a fetch is incomplete."""
+    pass
+
+class OpCodeNotFoundError(Error):
+    """Error raised when an opcode is not implemented."""
+
+
+class ByteCode:
+    """Class for reading bytecode."""
+
+    def __init__(self, init, def_opcode_fetch=0):
+        """
+        Initialize ByteCode object from init.
+
+        Arguments:
+        init -- a list or a string
+        def_opcode_fetch -- fetch function
+
+        >>> def_opcode_fetch = bytecode.ByteCode.fetch_u8
+        >>> def_opcode_fetch(bytecode.ByteCode([1]))
+        1
+        """
+        self._data = array.array("B", init)
+        """Store bytecode in array of unsigned bytes."""
+        self._pos = 0
+        """Store initial bytecode position."""
+        self.optable = {}
+        """Map from opcode to opcode handler."""
+        self._def_opcode_fetch = \
+            def_opcode_fetch or ByteCode.fetch_u8
+        """Hold default opcode fetch function."""
+
+        self.populate()
+
+    def register_opcode(self, opcode, handler):
+        """Register handler for opcode."""
+        self.optable[opcode] = handler
+
+    def register_opcodes(self, opcodes, handler):
+        """Register handler for opcodes."""
+        for opcode in opcodes:
+            self.register_opcode(opcode, handler)
+
+    def populate(self):
+        """Populate self.optable"""
+        pass
+
+    def decode_next(self, alt_opcode_fetch=0):
+        """
+        Decode next instruction.
+
+        Arguments:
+        alt_opcode_fetch -- opcode fetch function (default 0)
+
+        alt_opcode_fetch, if not zero is used instead of
+        self._def_opcode_fetch. (see self.__init__())
+        """
+        opcode_fetch = alt_opcode_fetch or self._def_opcode_fetch
+        opc = opcode_fetch(self)
+        if self.optable.has_key(opc):
+            return self.optable[opc](opc)
+        raise OpCodeNotFoundError, "opcode %d is not handled" % opc
+
+    def __len__(self):
+        """Return length of _array."""
+        return len(self._data)
+
+    def _fetch_guard(self, n, emsg=''):
+        """
+        Check if fetching of n bytes is possible.
+
+        Raise IncompleteFetchError exception with emsg if not.
+        """
+        if self._pos + n > len(self._data):
+            raise IncompleteFetchError, \
+                ("incomplete fetch of %d bytes" % n) + \
+                (emsg and " (" + emsg + ")")
+
+    def seek(self, offset, whence=0):
+        """
+        Set self._pos according to offset and whence.
+
+        Arguments:
+        offset -- offset to seek by
+        whence -- specifies the type of offset (default 0)
+
+        whence can be either 0 (self._pos relative seek)
+        or 1 (absolute seek).  A negative offset seeks
+        backward from self._pos or the end of self._data
+        respectively.
+        """
+        length = len(self._data)
+        # self._pos relative seek
+        if whence == 0:
+            self._pos += offset
+            # unless 0 <= self._pos <= length holds,
+            # raise exception and clamp self._pos
+            if self._pos < 0:
+                self._pos = 0
+                raise OutOfBoundsError, \
+                    "negative index via relative seek by %d" % offset
+            if self._pos > length:
+                self._pos = length
+                raise OutOfBoundsError, \
+                    "beyond fence via relative seek by %d" % offset
+        # absolute seek
+        elif whence == 1:
+            if not -length <= offset <= length:
+                raise OutOfBoundsError, "absolute seek to %d" % offset
+            if offset < 0: offset = length + offset
+            self._pos = offset
+
+    ## Basic Data Fetchers
+    #
+    # TODO: maybe generalize LE/BE reading
+
+    def fetch_u8(self, peek=False):
+        """Return next byte as unsigned character."""
+        self._fetch_guard(1, 'fetch_u8')
+        ret = self._data[self._pos]
+        if not peek: self.seek(1)
+        return ret
+
+    def fetch_be_u16(self, peek=False):
+        """Return next unsigned 16-bit word in BE."""
+        self._fetch_guard(2, 'fetch_be_u16')
+        ret = (self._data[self._pos] << 8) | self._data[self._pos+1]
+        if not peek: self.seek(2)
+        return ret
+
+    def fetch_le_u16(self, peek=False):
+        """Return next unsigned 16-bit word in LE."""
+        self._fetch_guard(2, 'fetch_le_u16')
+        ret = self._data[self._pos] | (self._data[self._pos+1] << 8)
+        if not peek: self.seek(2)
+        return ret
+
+    def fetch_be_u32(self, peek=False):
+        """Return next unsigned 32-bit word in BE."""
+        self._fetch_guard(4, 'fetch_be_u32')
+        ret = (self._data[self._pos] << 24) | \
+            (self._data[self._pos+1] << 16) | \
+            (self._data[self._pos+2] <<  8) | \
+            self._data[self._pos+3]
+        if not peek: self.seek(4)
+        return ret
+
+    def fetch_le_u32(self, peek=False):
+        """Return next unsigned 32-bit word in LE."""
+        self._fetch_guard(4, 'fetch_le_u32')
+        ret = self._data[self._pos] | \
+            (self._data[self._pos+1] << 8) | \
+            (self._data[self._pos+2] << 16) | \
+            (self._data[self._pos+3] << 24)
+        if not peek: self.seek(4)
+        return ret
+
+    ## Getters
+
+    def get_pos(self):
+        """Return self._pos"""
+        return self._pos
+
+    def get_data(self):
+        """Return self._data"""
+        return self._data


Property changes on: tools/branches/gsoc2007-decompiler/finalD/bytecode.py
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: tools/branches/gsoc2007-decompiler/finalD/decompiler.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/decompiler.py	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/decompiler.py	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,29 @@
+"""Decompiler class and program entry point."""
+
+import disasm
+import scumm
+import bytecode
+
+import array
+from optparse import OptionParser
+
+class Decompiler:
+    """The Core"""
+    pass
+
+if __name__ == '__main__':
+    parser = OptionParser()
+    parser.add_option("-f", "--file", dest="filename")
+    (options, args) = parser.parse_args()
+    f = open(options.filename, 'r')
+    sc = scumm.SCUMM345(array.array('B', f.read()),
+                        3,
+                        indy_flag = True,
+                        halt_on_error = False)
+    sc.parse_header()
+    try:
+        while 1:
+            print sc.decode_next()
+    except bytecode.IncompleteFetchError:
+        pass
+    print "END"


Property changes on: tools/branches/gsoc2007-decompiler/finalD/decompiler.py
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: tools/branches/gsoc2007-decompiler/finalD/disasm.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/disasm.py	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/disasm.py	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,39 @@
+"""Disassembler base module."""
+
+import bytecode
+
+
+## Exceptions ##
+
+class Error(Exception):
+    """Base class for exceptions in this module."""
+    pass
+
+
+## Disassembler base class ##
+
+class Disasm:
+    """Disassembler base class"""
+
+    def __init__(self, bc):
+        """
+        Initialize Disasm instance.
+
+        Arguments:
+        bc -- instance of bytecode.ByteCode class
+        """
+        self.decoded = []
+        """Hold decoded instructions."""
+        self._bc = bc
+        """Hold bytecode.ByteCode instance."""
+
+    def decode(self):
+        """Decode all instructions."""
+        try:
+            # Append results of self.decode_next() to self.decoded until
+            # an exception is raised.
+            while 1:
+                self.decoded.append(self._bc.decode_next())
+        except bytecode.IncompleteFetchError:
+            # If an bytecode.IncompleteFetchError was raised, we are done.
+            return self.decoded


Property changes on: tools/branches/gsoc2007-decompiler/finalD/disasm.py
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: tools/branches/gsoc2007-decompiler/finalD/docs/v0_support.txt
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/docs/v0_support.txt	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/docs/v0_support.txt	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,320 @@
+/* 00 */
+OPCODE(o5_stopObjectCode), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o5_startMusic), CHECK
+OPCODE(o_doSentence), CHECK
+/* 04 */
+OPCODE(o_isGreaterEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o5_getDist), CHECK
+OPCODE(o5_getActorRoom), CHECK
+/* 08 */
+OPCODE(o_isNotEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* 0C */
+OPCODE(o_loadSound), CHECK
+OPCODE(o_printEgo_c64), CHECK
+OPCODE(o_putActorAtObject), CHECK
+OPCODE(o2_clearState02), CHECK
+/* 10 */
+OPCODE(o5_breakHere), CHECK
+OPCODE(o_animateActor), CHECK
+OPCODE(o2_panCameraTo), CHECK
+OPCODE(o_lockCostume), CHECK
+/* 14 */
+OPCODE(o_print_c64), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o5_getRandomNr), CHECK
+OPCODE(o_clearState08), CHECK
+/* 18 */
+OPCODE(o_jumpRelative), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o5_move), CHECK
+OPCODE(o_getActorBitVar), CHECK
+/* 1C */
+OPCODE(o5_startSound), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState04), CHECK
+/* 20 */
+OPCODE(o5_stopMusic), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o5_saveLoadGame), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* 24 */
+OPCODE(o_unknown2), CHECK
+OPCODE(o5_loadRoom), CHECK
+OPCODE(o_getClosestObjActor), CHECK
+OPCODE(o2_getActorY), CHECK
+/* 28 */
+OPCODE(o_equalZero), CHECK
+OPCODE(o_setOwnerOf), CHECK
+OPCODE(o2_delay), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* 2C */
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o_print_c64), CHECK
+OPCODE(o2_ifState08), CHECK
+/* 30 */
+OPCODE(o_loadCostume), CHECK
+OPCODE(o_getBitVar), CHECK
+OPCODE(o2_setCameraAt), CHECK
+OPCODE(o_lockScript), CHECK
+/* 34 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_clearState04), CHECK
+/* 38 */
+OPCODE(o_isLessEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_subtract), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* 3C */
+OPCODE(o5_stopSound), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState02), CHECK
+/* 40 */
+OPCODE(o_cutscene), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_startScript), CHECK
+OPCODE(o_doSentence), CHECK
+/* 44 */
+OPCODE(o_isLess), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o5_increment), CHECK
+OPCODE(o2_getActorX), CHECK
+/* 48 */
+OPCODE(o_isEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_loadRoom), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* 4C */
+OPCODE(o_loadScript), CHECK
+OPCODE(o_lockRoom), CHECK
+OPCODE(o_putActorAtObject), CHECK
+OPCODE(o2_clearState02), CHECK
+/* 50 */
+OPCODE(o_nop), CHECK
+OPCODE(o_animateActor), CHECK
+OPCODE(o5_actorFollowCamera), CHECK
+OPCODE(o_lockSound), CHECK
+/* 54 */
+OPCODE(o_setObjectName), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o_getActorMoving), CHECK
+OPCODE(o_clearState08), CHECK
+/* 58 */
+OPCODE(o_beginOverride), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_add), CHECK
+OPCODE(o_getActorBitVar), CHECK
+/* 5C */
+OPCODE(o5_startSound), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState04), CHECK
+/* 60 */
+OPCODE(o_cursorCommand), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_stopScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* 64 */
+OPCODE(o_ifActiveObject), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_getClosestObjActor), CHECK
+OPCODE(o5_getActorFacing), CHECK
+/* 68 */
+OPCODE(o5_isScriptRunning), CHECK
+OPCODE(o_setOwnerOf), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* 6C */
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o2_dummy), CHECK
+OPCODE(o2_ifState08), CHECK
+/* 70 */
+OPCODE(o_lights), CHECK
+OPCODE(o_getBitVar), CHECK
+OPCODE(o_nop), CHECK
+OPCODE(o5_getObjectOwner), CHECK
+/* 74 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o_printEgo_c64), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_clearState04), CHECK
+/* 78 */
+OPCODE(o_isGreater), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* 7C */
+OPCODE(o5_isSoundRunning), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState02), CHECK
+/* 80 */
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_doSentence), CHECK
+/* 84 */
+OPCODE(o_isGreaterEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_nop), CHECK
+OPCODE(o5_getActorRoom), CHECK
+/* 88 */
+OPCODE(o_isNotEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* 8C */
+OPCODE(o_loadSound), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_putActorAtObject), CHECK
+OPCODE(o2_setState02), CHECK
+/* 90 */
+OPCODE(o_pickupObject), CHECK
+OPCODE(o_animateActor), CHECK
+OPCODE(o2_panCameraTo), CHECK
+OPCODE(o_unlockCostume), CHECK
+/* 94 */
+OPCODE(o5_print), CHECK
+OPCODE(o2_actorFromPos), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_setState08), CHECK
+/* 98 */
+OPCODE(o2_restart), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o5_move), CHECK
+OPCODE(o_getActorBitVar), CHECK
+/* 9C */
+OPCODE(o5_startSound), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState04), CHECK
+/* A0 */
+OPCODE(o5_stopObjectCode), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o5_saveLoadGame), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* A4 */
+OPCODE(o_unknown2), CHECK
+OPCODE(o5_loadRoom), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_getActorY), CHECK
+/* A8 */
+OPCODE(o_notEqualZero), CHECK
+OPCODE(o_setOwnerOf), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* AC */
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o_print_c64), CHECK
+OPCODE(o2_ifNotState08), CHECK
+/* B0 */
+OPCODE(o_loadCostume), CHECK
+OPCODE(o_getBitVar), CHECK
+OPCODE(o2_setCameraAt), CHECK
+OPCODE(o_unlockScript), CHECK
+/* B4 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_setState04), CHECK
+/* B8 */
+OPCODE(o_isLessEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_subtract), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* BC */
+OPCODE(o5_stopSound), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState02), CHECK
+/* C0 */
+OPCODE(o_endCutscene), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_startScript), CHECK
+OPCODE(o_doSentence), CHECK
+/* C4 */
+OPCODE(o_isLess), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o5_decrement), CHECK
+OPCODE(o2_getActorX), CHECK
+/* C8 */
+OPCODE(o_isEqual), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_loadRoom), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* CC */
+OPCODE(o_loadScript), CHECK
+OPCODE(o_unlockRoom), CHECK
+OPCODE(o_putActorAtObject), CHECK
+OPCODE(o2_setState02), CHECK
+/* D0 */
+OPCODE(o_nop), CHECK
+OPCODE(o_animateActor), CHECK
+OPCODE(o5_actorFollowCamera), CHECK
+OPCODE(o_unlockSound), CHECK
+/* D4 */
+OPCODE(o_setObjectName), CHECK
+OPCODE(o2_actorFromPos), CHECK
+OPCODE(o_getActorMoving), CHECK
+OPCODE(o_setState08), CHECK
+/* D8 */
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_add), CHECK
+OPCODE(o_getActorBitVar), CHECK
+/* DC */
+OPCODE(o5_startSound), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState04), CHECK
+/* E0 */
+OPCODE(o_cursorCommand), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_stopScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* E4 */
+OPCODE(o_ifActiveObject), CHECK
+OPCODE(o_loadRoomWithEgo), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o5_getActorFacing), CHECK
+/* E8 */
+OPCODE(o5_isScriptRunning), CHECK
+OPCODE(o_setOwnerOf), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_setActorBitVar), CHECK
+/* EC */
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o2_dummy), CHECK
+OPCODE(o2_ifNotState08), CHECK
+/* F0 */
+OPCODE(o_lights), CHECK
+OPCODE(o_getBitVar), CHECK
+OPCODE(o_nop), CHECK
+OPCODE(o5_getObjectOwner), CHECK
+/* F4 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_setState04), CHECK
+/* F8 */
+OPCODE(o_isGreater), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+OPCODE(o_stopCurrentScript), CHECK
+/* FC */
+OPCODE(o5_isSoundRunning), CHECK
+OPCODE(o_setBitVar), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState02) CHECK


Property changes on: tools/branches/gsoc2007-decompiler/finalD/docs/v0_support.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: tools/branches/gsoc2007-decompiler/finalD/docs/v2_support.txt
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/docs/v2_support.txt	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/docs/v2_support.txt	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,320 @@
+/* 00 */
+OPCODE(o5_stopObjectCode), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o5_startMusic), CHECK
+OPCODE(o5_getActorRoom), CHECK
+/* 04 */
+OPCODE(o2_isGreaterEqual), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o2_getActorElevation), CHECK
+OPCODE(o2_setState08), CHECK
+/* 08 */
+OPCODE(o5_isNotEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o2_assignVarWordIndirect), CHECK
+OPCODE(o2_setObjPreposition), CHECK
+/* 0C */
+OPCODE(o2_resourceRoutines), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o2_putActorAtObject), CHECK
+OPCODE(o2_ifNotState08), CHECK
+/* 10 */
+OPCODE(o5_getObjectOwner), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o2_panCameraTo), CHECK
+OPCODE(o2_actorOps), CHECK
+/* 14 */
+OPCODE(o5_print), CHECK
+OPCODE(o2_actorFromPos), CHECK
+OPCODE(o5_getRandomNr), CHECK
+OPCODE(o2_clearState02), CHECK
+/* 18 */
+OPCODE(o5_jumpRelative), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o5_move), CHECK
+OPCODE(o2_setBitVar), CHECK
+/* 1C */
+OPCODE(o5_startSound), CHECK
+OPCODE(o2_ifClassOfIs), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState02), CHECK
+/* 20 */
+OPCODE(o5_stopMusic), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o5_saveLoadGame), CHECK
+OPCODE(o2_getActorY), CHECK
+/* 24 */
+OPCODE(o2_loadRoomWithEgo), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o5_setVarRange), CHECK
+OPCODE(o2_setState04), CHECK
+/* 28 */
+OPCODE(o5_equalZero), CHECK
+OPCODE(o2_setOwnerOf), CHECK
+OPCODE(o2_addIndirect), CHECK
+OPCODE(o5_delayVariable), CHECK
+/* 2C */
+OPCODE(o2_assignVarByte), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o2_delay), CHECK
+OPCODE(o2_ifNotState04), CHECK
+/* 30 */
+OPCODE(o2_setBoxFlags), CHECK
+OPCODE(o2_getBitVar), CHECK
+OPCODE(o2_setCameraAt), CHECK
+OPCODE(o2_roomOps), CHECK
+/* 34 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o2_findObject), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_setState01), CHECK
+/* 38 */
+OPCODE(o2_isLessEqual), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o2_subtract), CHECK
+OPCODE(o2_waitForActor), CHECK
+/* 3C */
+OPCODE(o5_stopSound), CHECK
+OPCODE(o2_setActorElevation), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState01), CHECK
+/* 40 */
+OPCODE(o2_cutscene), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_startScript), CHECK
+OPCODE(o2_getActorX), CHECK
+/* 44 */
+OPCODE(o2_isLess), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o5_increment), CHECK
+OPCODE(o2_clearState08), CHECK
+/* 48 */
+OPCODE(o5_isEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o2_chainScript), CHECK
+OPCODE(o2_setObjPreposition), CHECK
+/* 4C */
+OPCODE(o2_waitForSentence), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o2_putActorAtObject), CHECK
+OPCODE(o2_ifState08), CHECK
+/* 50 */
+OPCODE(o2_pickupObject), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o5_actorFollowCamera), CHECK
+OPCODE(o2_actorOps), CHECK
+/* 54 */
+OPCODE(o5_setObjectName), CHECK
+OPCODE(o2_actorFromPos), CHECK
+OPCODE(o5_getActorMoving), CHECK
+OPCODE(o2_setState02), CHECK
+/* 58 */
+OPCODE(o2_beginOverride), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o2_add), CHECK
+OPCODE(o2_setBitVar), CHECK
+/* 5C */
+OPCODE(o2_dummy), CHECK
+OPCODE(o2_ifClassOfIs), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState02), CHECK
+/* 60 */
+OPCODE(o2_cursorCommand), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_stopScript), CHECK
+OPCODE(o5_getActorFacing), CHECK
+/* 64 */
+OPCODE(o2_loadRoomWithEgo), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o5_getClosestObjActor), CHECK
+OPCODE(o2_clearState04), CHECK
+/* 68 */
+OPCODE(o5_isScriptRunning), CHECK
+OPCODE(o2_setOwnerOf), CHECK
+OPCODE(o2_subIndirect), CHECK
+OPCODE(o2_dummy), CHECK
+/* 6C */
+OPCODE(o2_getObjPreposition), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o2_dummy), CHECK
+OPCODE(o2_ifState04), CHECK
+/* 70 */
+OPCODE(o2_lights), CHECK
+OPCODE(o5_getActorCostume), CHECK
+OPCODE(o5_loadRoom), CHECK
+OPCODE(o2_roomOps), CHECK
+/* 74 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o2_findObject), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_clearState01), CHECK
+/* 78 */
+OPCODE(o2_isGreater), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o2_verbOps), CHECK
+OPCODE(o2_getActorWalkBox), CHECK
+/* 7C */
+OPCODE(o5_isSoundRunning), CHECK
+OPCODE(o2_setActorElevation), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState01), CHECK
+/* 80 */
+OPCODE(o5_breakHere), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o5_startMusic), CHECK
+OPCODE(o5_getActorRoom), CHECK
+/* 84 */
+OPCODE(o2_isGreaterEqual), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o2_getActorElevation), CHECK
+OPCODE(o2_setState08), CHECK
+/* 88 */
+OPCODE(o5_isNotEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o2_assignVarWordIndirect), CHECK
+OPCODE(o2_setObjPreposition), CHECK
+/* 8C */
+OPCODE(o2_resourceRoutines), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o2_putActorAtObject), CHECK
+OPCODE(o2_ifNotState08), CHECK
+/* 90 */
+OPCODE(o5_getObjectOwner), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o2_panCameraTo), CHECK
+OPCODE(o2_actorOps), CHECK
+/* 94 */
+OPCODE(o5_print), CHECK
+OPCODE(o2_actorFromPos), CHECK
+OPCODE(o5_getRandomNr), CHECK
+OPCODE(o2_clearState02), CHECK
+/* 98 */
+OPCODE(o2_restart), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o5_move), CHECK
+OPCODE(o2_setBitVar), CHECK
+/* 9C */
+OPCODE(o5_startSound), CHECK
+OPCODE(o2_ifClassOfIs), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState02), CHECK
+/* A0 */
+OPCODE(o5_stopObjectCode), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o5_saveLoadGame), CHECK
+OPCODE(o2_getActorY), CHECK
+/* A4 */
+OPCODE(o2_loadRoomWithEgo), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o5_setVarRange), CHECK
+OPCODE(o2_setState04), CHECK
+/* A8 */
+OPCODE(o5_notEqualZero), CHECK
+OPCODE(o2_setOwnerOf), CHECK
+OPCODE(o2_addIndirect), CHECK
+OPCODE(o2_switchCostumeSet),
+/* AC */
+OPCODE(o2_drawSentence), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o2_waitForMessage), CHECK
+OPCODE(o2_ifNotState04), CHECK
+/* B0 */
+OPCODE(o2_setBoxFlags), CHECK
+OPCODE(o2_getBitVar), CHECK
+OPCODE(o2_setCameraAt), CHECK
+OPCODE(o2_roomOps), CHECK
+/* B4 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o2_findObject), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_setState01), CHECK
+/* B8 */
+OPCODE(o2_isLessEqual), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o2_subtract), CHECK
+OPCODE(o2_waitForActor), CHECK
+/* BC */
+OPCODE(o5_stopSound), CHECK
+OPCODE(o2_setActorElevation), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState01), CHECK
+/* C0 */
+OPCODE(o2_endCutscene), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_startScript), CHECK
+OPCODE(o2_getActorX), CHECK
+/* C4 */
+OPCODE(o2_isLess), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o5_decrement), CHECK
+OPCODE(o2_clearState08), CHECK
+/* C8 */
+OPCODE(o5_isEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o2_chainScript), CHECK
+OPCODE(o2_setObjPreposition), CHECK
+/* CC */
+OPCODE(o5_pseudoRoom), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o2_putActorAtObject), CHECK
+OPCODE(o2_ifState08), CHECK
+/* D0 */
+OPCODE(o2_pickupObject), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o5_actorFollowCamera), CHECK
+OPCODE(o2_actorOps), CHECK
+/* D4 */
+OPCODE(o5_setObjectName), CHECK
+OPCODE(o2_actorFromPos), CHECK
+OPCODE(o5_getActorMoving), CHECK
+OPCODE(o2_setState02), CHECK
+/* D8 */
+OPCODE(o5_printEgo), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o2_add), CHECK
+OPCODE(o2_setBitVar), CHECK
+/* DC */
+OPCODE(o2_dummy), CHECK
+OPCODE(o2_ifClassOfIs), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifNotState02), CHECK
+/* E0 */
+OPCODE(o2_cursorCommand), CHECK
+OPCODE(o2_putActor), CHECK
+OPCODE(o2_stopScript), CHECK
+OPCODE(o5_getActorFacing), CHECK
+/* E4 */
+OPCODE(o2_loadRoomWithEgo), CHECK
+OPCODE(o2_drawObject), CHECK
+OPCODE(o5_getClosestObjActor), CHECK
+OPCODE(o2_clearState04), CHECK
+/* E8 */
+OPCODE(o5_isScriptRunning), CHECK
+OPCODE(o2_setOwnerOf), CHECK
+OPCODE(o2_subIndirect), CHECK
+OPCODE(o2_dummy), CHECK
+/* EC */
+OPCODE(o2_getObjPreposition), CHECK
+OPCODE(o2_putActorInRoom), CHECK
+OPCODE(o2_dummy), CHECK
+OPCODE(o2_ifState04), CHECK
+/* F0 */
+OPCODE(o2_lights), CHECK
+OPCODE(o5_getActorCostume), CHECK
+OPCODE(o5_loadRoom), CHECK
+OPCODE(o2_roomOps), CHECK
+/* F4 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o2_findObject), CHECK
+OPCODE(o2_walkActorToObject), CHECK
+OPCODE(o2_clearState01), CHECK
+/* F8 */
+OPCODE(o2_isGreater), CHECK
+OPCODE(o2_doSentence), CHECK
+OPCODE(o2_verbOps), CHECK
+OPCODE(o2_getActorWalkBox), CHECK
+/* FC */
+OPCODE(o5_isSoundRunning), CHECK
+OPCODE(o2_setActorElevation), CHECK
+OPCODE(o2_walkActorTo), CHECK
+OPCODE(o2_ifState01) CHECK


Property changes on: tools/branches/gsoc2007-decompiler/finalD/docs/v2_support.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: tools/branches/gsoc2007-decompiler/finalD/docs/v5_support.txt
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/docs/v5_support.txt	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/docs/v5_support.txt	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,320 @@
+/* 00 */
+OPCODE(o5_stopObjectCode), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_startMusic), CHECK
+OPCODE(o5_getActorRoom), CHECK
+/* 04 */
+OPCODE(o5_isGreaterEqual), CHECK
+OPCODE(o5_drawObject), CHECK
+OPCODE(o5_getActorElevation), CHECK
+OPCODE(o5_setState), CHECK
+/* 08 */
+OPCODE(o5_isNotEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_getVerbEntrypoint), CHECK
+/* 0C */
+OPCODE(o5_resourceRoutines), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o5_putActorAtObject), CHECK
+OPCODE(o5_getObjectState), CHECK
+/* 10 */
+OPCODE(o5_getObjectOwner), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o5_panCameraTo), CHECK
+OPCODE(o5_actorOps), CHECK
+/* 14 */
+OPCODE(o5_print), CHECK
+OPCODE(o5_actorFromPos), CHECK
+OPCODE(o5_getRandomNr), CHECK
+OPCODE(o5_and), CHECK
+/* 18 */
+OPCODE(o5_jumpRelative), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_move), CHE
+OPCODE(o5_multiply), CHECK
+/* 1C */
+OPCODE(o5_startSound), CHECK
+OPCODE(o5_ifClassOfIs), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_isActorInBox), CHECK
+/* 20 */
+OPCODE(o5_stopMusic), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_getAnimCounter), CHECK
+OPCODE(o5_getActorY), CHECK
+/* 24 */
+OPCODE(o5_loadRoomWithEgo), CHECK
+OPCODE(o5_pickupObject), CHECK
+OPCODE(o5_setVarRange), CHECK
+OPCODE(o5_stringOps), CHECK
+/* 28 */
+OPCODE(o5_equalZero), CHECK
+OPCODE(o5_setOwnerOf), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_delayVariable), CHECK
+/* 2C */
+OPCODE(o5_cursorCommand), CHECK
+OPCODE(o5_putActorInRoom), CHECK
+OPCODE(o5_delay), CHECK
+OPCODE(o5_ifNotState), CHECK
+/* 30 */
+OPCODE(o5_matrixOps), CHECK
+OPCODE(o5_getInventoryCount), CHECK
+OPCODE(o5_setCameraAt), CHECK
+OPCODE(o5_roomOps), CHECK
+/* 34 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o5_findObject), CHECK
+OPCODE(o5_walkActorToObject), CHECK
+OPCODE(o5_startObject), CHECK
+/* 38 */
+OPCODE(o5_lessOrEqual), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_subtract), CHECK
+OPCODE(o5_getActorScale), CHECK
+/* 3C */
+OPCODE(o5_stopSound), CHECK
+OPCODE(o5_findInventory), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_drawBox), CHECK
+/* 40 */
+OPCODE(o5_cutscene), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_chainScript), CHECK
+OPCODE(o5_getActorX), CHECK
+/* 44 */
+OPCODE(o5_isLess), CHECK
+OPCODE(o5_drawObject), CHECK
+OPCODE(o5_increment), CHECK
+OPCODE(o5_setState), CHECK
+/* 48 */
+OPCODE(o5_isEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_getVerbEntrypoint), CHECK
+/* 4C */
+OPCODE(o5_soundKludge), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o5_putActorAtObject), CHECK
+OPCODE(o5_ifState), CHECK
+/* 50 */
+OPCODE(o5_pickupObjectOld), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o5_actorFollowCamera), CHECK
+OPCODE(o5_actorOps), CHECK
+/* 54 */
+OPCODE(o5_setObjectName), CHECK
+OPCODE(o5_actorFromPos), CHECK
+OPCODE(o5_getActorMoving), CHECK
+OPCODE(o5_or), CHECK
+/* 58 */
+OPCODE(o5_beginOverride), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_add), CHECK
+OPCODE(o5_divide), CHECK
+/* 5C */
+OPCODE(o5_oldRoomEffect), CHECK
+OPCODE(o5_setClass), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_isActorInBox), CHECK
+/* 60 */
+OPCODE(o5_freezeScripts), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_stopScript), CHECK
+OPCODE(o5_getActorFacing), CHECK
+/* 64 */
+OPCODE(o5_loadRoomWithEgo), CHECK
+OPCODE(o5_pickupObject), CHECK
+OPCODE(o5_getClosestObjActor), CHECK
+OPCODE(o5_getStringWidth), CHECK
+/* 68 */
+OPCODE(o5_isScriptRunning), CHECK
+OPCODE(o5_setOwnerOf), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_debug), CHECK
+/* 6C */
+OPCODE(o5_getActorWidth), CHECK
+OPCODE(o5_putActorInRoom), CHECK
+OPCODE(o5_stopObjectScript), CHECK
+OPCODE(o5_ifNotState), CHECK
+/* 70 */
+OPCODE(o5_lights), CHECK
+OPCODE(o5_getActorCostume), CHECK
+OPCODE(o5_loadRoom), CHECK
+OPCODE(o5_roomOps), CHECK
+/* 74 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o5_findObject), CHECK
+OPCODE(o5_walkActorToObject), CHECK
+OPCODE(o5_startObject), CHECK
+/* 78 */
+OPCODE(o5_isGreater), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_verbOps), CHECK
+OPCODE(o5_getActorWalkBox), CHECK
+/* 7C */
+OPCODE(o5_isSoundRunning), CHECK
+OPCODE(o5_findInventory), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_drawBox), CHECK
+/* 80 */
+OPCODE(o5_breakHere), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_startMusic), CHECK
+OPCODE(o5_getActorRoom), CHECK
+/* 84 */
+OPCODE(o5_isGreaterEqual), CHECK
+OPCODE(o5_drawObject), CHECK
+OPCODE(o5_getActorElevation), CHECK
+OPCODE(o5_setState), CHECK
+/* 88 */
+OPCODE(o5_isNotEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_getVerbEntrypoint), CHECK
+/* 8C */
+OPCODE(o5_resourceRoutines), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o5_putActorAtObject), CHECK
+OPCODE(o5_getObjectState), CHECK
+/* 90 */
+OPCODE(o5_getObjectOwner), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o5_panCameraTo), CHECK
+OPCODE(o5_actorOps), CHECK
+/* 94 */
+OPCODE(o5_print), CHECK
+OPCODE(o5_actorFromPos), CHECK
+OPCODE(o5_getRandomNr), CHECK
+OPCODE(o5_and), CHECK
+/* 98 */
+OPCODE(o5_systemOps), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_move), CHECK
+OPCODE(o5_multiply), CHECK
+/* 9C */
+OPCODE(o5_startSound), CHECK
+OPCODE(o5_ifClassOfIs), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_isActorInBox), CHECK
+/* A0 */
+OPCODE(o5_stopObjectCode), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_getAnimCounter), CHECK
+OPCODE(o5_getActorY), CHECK
+/* A4 */
+OPCODE(o5_loadRoomWithEgo), CHECK
+OPCODE(o5_pickupObject), CHECK
+OPCODE(o5_setVarRange), CHECK
+OPCODE(o5_saveLoadVars), CHECK
+/* A8 */
+OPCODE(o5_notEqualZero), CHECK
+OPCODE(o5_setOwnerOf), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_saveRestoreVerbs), CHECK
+/* AC */
+OPCODE(o5_expression), CHECK
+OPCODE(o5_putActorInRoom), CHECK
+OPCODE(o5_wait), CHECK
+OPCODE(o5_ifNotState), CHECK
+/* B0 */
+OPCODE(o5_matrixOps), CHECK
+OPCODE(o5_getInventoryCount), CHECK
+OPCODE(o5_setCameraAt), CHECK
+OPCODE(o5_roomOps), CHECK
+/* B4 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o5_findObject), CHECK
+OPCODE(o5_walkActorToObject), CHECK
+OPCODE(o5_startObject), CHECK
+/* B8 */
+OPCODE(o5_lessOrEqual), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_subtract), CHECK
+OPCODE(o5_getActorScale), CHECK
+/* BC */
+OPCODE(o5_stopSound), CHECK
+OPCODE(o5_findInventory), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_drawBox), CHECK
+/* C0 */
+OPCODE(o5_endCutscene), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_chainScript), CHECK
+OPCODE(o5_getActorX), CHECK
+/* C4 */
+OPCODE(o5_isLess), CHECK
+OPCODE(o5_drawObject), CHECK
+OPCODE(o5_decrement), CHECK
+OPCODE(o5_setState), CHECK
+/* C8 */
+OPCODE(o5_isEqual), CHECK
+OPCODE(o5_faceActor), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_getVerbEntrypoint), CHECK
+/* CC */
+OPCODE(o5_pseudoRoom), CHECK
+OPCODE(o5_walkActorToActor), CHECK
+OPCODE(o5_putActorAtObject), CHECK
+OPCODE(o5_ifState), CHECK
+/* D0 */
+OPCODE(o5_pickupObjectOld), CHECK
+OPCODE(o5_animateActor), CHECK
+OPCODE(o5_actorFollowCamera), CHECK
+OPCODE(o5_actorOps), CHECK
+/* D4 */
+OPCODE(o5_setObjectName), CHECK
+OPCODE(o5_actorFromPos), CHECK
+OPCODE(o5_getActorMoving), CHECK
+OPCODE(o5_or), CHECK
+/* D8 */
+OPCODE(o5_printEgo), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_add), CHECK
+OPCODE(o5_divide), CHECK
+/* DC */
+OPCODE(o5_oldRoomEffect), CHECK
+OPCODE(o5_setClass), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_isActorInBox), CHECK
+/* E0 */
+OPCODE(o5_freezeScripts), CHECK
+OPCODE(o5_putActor), CHECK
+OPCODE(o5_stopScript), CHECK
+OPCODE(o5_getActorFacing), CHECK
+/* E4 */
+OPCODE(o5_loadRoomWithEgo), CHECK
+OPCODE(o5_pickupObject), CHECK
+OPCODE(o5_getClosestObjActor), CHECK
+OPCODE(o5_getStringWidth), CHECK
+/* E8 */
+OPCODE(o5_isScriptRunning), CHECK
+OPCODE(o5_setOwnerOf), CHECK
+OPCODE(o5_startScript), CHECK
+OPCODE(o5_debug), CHECK
+/* EC */
+OPCODE(o5_getActorWidth), CHECK
+OPCODE(o5_putActorInRoom), CHECK
+OPCODE(o5_stopObjectScript), CHECK
+OPCODE(o5_ifNotState), CHECK
+/* F0 */
+OPCODE(o5_lights), CHECK
+OPCODE(o5_getActorCostume), CHECK
+OPCODE(o5_loadRoom), CHECK
+OPCODE(o5_roomOps), CHECK
+/* F4 */
+OPCODE(o5_getDist), CHECK
+OPCODE(o5_findObject), CHECK
+OPCODE(o5_walkActorToObject), CHECK
+OPCODE(o5_startObject), CHECK
+/* F8 */
+OPCODE(o5_isGreater), CHECK
+OPCODE(o5_doSentence), CHECK
+OPCODE(o5_verbOps), CHECK
+OPCODE(o5_getActorWalkBox), CHECK
+/* FC */
+OPCODE(o5_isSoundRunning), CHECK
+OPCODE(o5_findInventory), CHECK
+OPCODE(o5_walkActorTo), CHECK
+OPCODE(o5_drawBox) CHECK


Property changes on: tools/branches/gsoc2007-decompiler/finalD/docs/v5_support.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: tools/branches/gsoc2007-decompiler/finalD/iformat.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/iformat.py	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/iformat.py	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,53 @@
+"""Intermediary format of bytecode instructions."""
+
+class Instr:
+    """
+    Instruction in intermediate format.
+
+    After disassembly, all instructions within a bytecode file will
+    have been translated into instances of this class.
+    """
+
+    def __init__(self, op, args):
+        self.op = op
+        self.args = args
+
+    def __str__(self):
+        buf = self.op + '('
+        first = 1
+        for arg in self.args:
+            if not first:
+                buf += ", "
+            first = 0
+            buf += "%s" % arg
+        buf += ')'
+        return buf
+
+class AssgnInstr(Instr):
+    """Assignment Instruction in intermediate format."""
+
+    def __init__(self, op, dst, val):
+        Instr.__init__(self, op, (dst, val))
+
+    def __str__(self):
+        dst, val = self.args
+        return "%s %s %s" % (str(dst), str(self.op), str(val))
+
+class Jump(Instr):
+    """Unconditional jump instruction in intermediate format."""
+
+    def __init__(self, to):
+        Instr.__init__(self, "goto", (to,))
+
+    def __str__(self):
+        return "goto %.4X" % self.args[0]
+
+class CondJump(Jump):
+    """Conditional jump instruction in intermediate format."""
+
+    def __init__(self, to, condition):
+        Jump.__init__(self, to)
+        self.condition = condition
+
+    def __str__(self):
+        return "unless(%s) goto %.4X" % (self.condition, self.args[0])


Property changes on: tools/branches/gsoc2007-decompiler/finalD/iformat.py
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: tools/branches/gsoc2007-decompiler/finalD/scumm.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/scumm.py	                        (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/scumm.py	2007-08-13 03:38:23 UTC (rev 28579)
@@ -0,0 +1,1788 @@
+"""Scumm Disasm and ByteCode"""
+
+import bytecode
+import disasm
+from iformat import *
+
+
+## Exceptions ##
+
+class Error(Exception):
+    """Base class for exceptions in this module."""
+    pass
+
+class VarIndexOutOfRangeError(Error):
+    """Error raised when a variable index is out of range."""
+    pass
+
+class ArgListVarNumError(Error):
+    """Error raised when an argument list holds too many variables."""
+    pass
+
+class UnknownSubOpError(Error):
+    """Error raised when a sub opcode is unknown."""
+    pass
+
+class InvalidExpressionCodeError(Error):
+    """Error raised when an expression code is unknown."""
+    pass
+
+class ScriptTooSmallError(Error):
+    """Error raised when script is too small."""
+    pass
+
+class UnknownScriptTypeError(Error):
+    """Error raised when script type is unknown."""
+    pass
+
+
+## Disassembler for SCUMM scripts ##
+
+class DisSCUMM(disasm.Disasm):
+    """Disassembler for SCUMM."""
+    pass
+
+
+## Globals ##
+
+_var_names0 = ("VAR_EGO",
+               "VAR_RESULT",
+               "VAR_CAMERA_POS_X",
+               "VAR_HAVE_MSG",
+               # 4
+               "VAR_ROOM",
+               "VAR_ACTIVE_ACTOR",
+               "VAR_OVERRIDE",
+               None,
+               # 8
+               "VAR_IS_SOUND_RUNNING",
+               "VAR_ACTIVE_VERB",
+               "VAR_CHARCOUNT",
+               None)
+
+_var_names2 = ("VAR_EGO",
+               "VAR_RESULT",
+               "VAR_CAMERA_POS_X",
+               "VAR_HAVE_MSG",
+               # 4
+               "VAR_ROOM",
+               "VAR_OVERRIDE",
+               "VAR_MACHINE_SPEED",
+               "VAR_CHARCOUNT",
+               # 8
+               "VAR_ACTIVE_VERB",
+               "VAR_ACTIVE_OBJECT1",
+               "VAR_ACTIVE_OBJECT2",
+               "VAR_NUM_ACTOR",
+               # 12
+               "VAR_CURRENT_LIGHTS",
+               "VAR_CURRENTDRIVE",
+               None,
+               None,
+               # 16
+               None,
+               "VAR_MUSIC_TIMER",
+               "VAR_VERB_ALLOWED",
+               "VAR_ACTOR_RANGE_MIN",
+               # 20
+               "VAR_ACTOR_RANGE_MAX",
+               None,
+               None,
+               "VAR_CAMERA_MIN_X",
+               # 24
+               "VAR_CAMERA_MAX_X",
+               "VAR_TIMER_NEXT",
+               "VAR_SENTENCE_VERB",
+               "VAR_SENTENCE_OBJECT1",
+               # 28
+               "VAR_SENTENCE_OBJECT2",
+               "VAR_SENTENCE_PREPOSITION",
+               "VAR_VIRT_MOUSE_X",
+               "VAR_VIRT_MOUSE_Y",
+               # 32
+               "VAR_CLICK_AREA",
+               "VAR_CLICK_VERB",
+               None,
+               "VAR_CLICK_OBJECT",
+               # 36
+               "VAR_ROOM_RESOURCE",
+               "VAR_LAST_SOUND",
+               "VAR_BACKUP_VERB",
+               "VAR_KEYPRESS",
+               # 40
+               "VAR_CUTSCENEEXIT_KEY",
+               "VAR_TALK_ACTOR",
+               None,
+               None)
+
+_var_names3 = ("VAR_RESULT",
+               "VAR_EGO",
+               "VAR_CAMERA_POS_X",
+               "VAR_HAVE_MSG",
+               # 4
+               "VAR_ROOM",
+               "VAR_OVERRIDE",
+               "VAR_MACHINE_SPEED",
+               "VAR_ME",
+               # 8
+               "VAR_NUM_ACTOR",
+               "VAR_CURRENT_LIGHTS",
+               "VAR_CURRENTDRIVE",
+               "VAR_TMR_1",
+               # 12
+               "VAR_TMR_2",
+               "VAR_TMR_3",
+               "VAR_MUSIC_TIMER",
+               "VAR_ACTOR_RANGE_MIN",
+               # 16
+               "VAR_ACTOR_RANGE_MAX",
+               "VAR_CAMERA_MIN_X",
+               "VAR_CAMERA_MAX_X",
+               "VAR_TIMER_NEXT",
+               # 20
+               "VAR_VIRT_MOUSE_X",
+               "VAR_VIRT_MOUSE_Y",
+               "VAR_ROOM_RESOURCE",
+               "VAR_LAST_SOUND",
+               # 24
+               "VAR_CUTSCENEEXIT_KEY",
+               "VAR_TALK_ACTOR",
+               "VAR_CAMERA_FAST_X",
+               None,
+               # 28
+               "VAR_ENTRY_SCRIPT",
+               "VAR_ENTRY_SCRIPT2",
+               "VAR_EXIT_SCRIPT",
+               "VAR_EXIT_SCRIPT2",
+               # 32
+               "VAR_VERB_SCRIPT",
+               "VAR_SENTENCE_SCRIPT",
+               "VAR_INVENTORY_SCRIPT",
+               "VAR_CUTSCENE_START_SCRIPT",
+               # 36
+               "VAR_CUTSCENE_END_SCRIPT",
+               "VAR_CHARINC",
+               "VAR_WALKTO_OBJ",
+               None,
+               # 40
+               None,
+               None,
+               "VAR_RESTART_KEY",
+               "VAR_PAUSE_KEY",
+               # 44
+               "VAR_MOUSE_X",
+               "VAR_MOUSE_Y",
+               "VAR_TIMER",
+               "VAR_TMR_4",
+               # 48
+               "VAR_SOUNDCARD",
+               "VAR_VIDEOMODE",
+               None,
+               None)
+
+_var_names4 = ("VAR_RESULT",
+               "VAR_EGO",
+               "VAR_CAMERA_POS_X",
+               "VAR_HAVE_MSG",
+               # 4
+               "VAR_ROOM",
+               "VAR_OVERRIDE",
+               "VAR_MACHINE_SPEED",
+               "VAR_ME",
+               # 8
+               "VAR_NUM_ACTOR",
+               "VAR_CURRENT_LIGHTS",
+               "VAR_CURRENTDRIVE",
+               "VAR_TMR_1",
+               # 12
+               "VAR_TMR_2",
+               "VAR_TMR_3",
+               "VAR_MUSIC_TIMER",
+               "VAR_ACTOR_RANGE_MIN",
+               # 16
+               "VAR_ACTOR_RANGE_MAX",
+               "VAR_CAMERA_MIN_X",
+               "VAR_CAMERA_MAX_X",
+               "VAR_TIMER_NEXT",
+               # 20
+               "VAR_VIRT_MOUSE_X",
+               "VAR_VIRT_MOUSE_Y",
+               "VAR_ROOM_RESOURCE",
+               "VAR_LAST_SOUND",
+               # 24
+               "VAR_CUTSCENEEXIT_KEY",
+               "VAR_TALK_ACTOR",
+               "VAR_CAMERA_FAST_X",
+               "VAR_SCROLL_SCRIPT",
+               # 28
+               "VAR_ENTRY_SCRIPT",
+               "VAR_ENTRY_SCRIPT2",
+               "VAR_EXIT_SCRIPT",
+               "VAR_EXIT_SCRIPT2",
+               # 32
+               "VAR_VERB_SCRIPT",
+               "VAR_SENTENCE_SCRIPT",
+               "VAR_INVENTORY_SCRIPT",
+               "VAR_CUTSCENE_START_SCRIPT",
+               # 36
+               "VAR_CUTSCENE_END_SCRIPT",
+               "VAR_CHARINC",
+               "VAR_WALKTO_OBJ",
+               "VAR_DEBUGMODE",
+               # 40
+               "VAR_HEAPSPACE",
+               None,
+               "VAR_RESTART_KEY",
+               "VAR_PAUSE_KEY",
+               # 44
+               "VAR_MOUSE_X",
+               "VAR_MOUSE_Y",
+               "VAR_TIMER",
+               "VAR_TMR_4",
+               # 48
+               "VAR_SOUNDCARD",
+               "VAR_VIDEOMODE",
+               "VAR_MAINMENU_KEY",
+               "VAR_FIXEDDISK",
+               # 52
+               "VAR_CURSORSTATE",
+               "VAR_USERPUT",
+               "VAR_V5_TALK_STRING_Y",
+               None,
+               # 56
+               None,
+               None,
+               None,
+               None,
+               # 60
+               "VAR_NOSUBTITLES",
+               None,
+               None,
+               None,
+               # 64
+               "VAR_SOUNDPARAM",
+               "VAR_SOUNDPARAM2",
+               "VAR_SOUNDPARAM3",
+               None)
+
+_var_names5 = ("VAR_RESULT",
+               "VAR_EGO",
+               "VAR_CAMERA_POS_X",
+               "VAR_HAVE_MSG",
+               # 4
+               "VAR_ROOM",
+               "VAR_OVERRIDE",
+               "VAR_MACHINE_SPEED",
+               "VAR_ME",
+               # 8
+               "VAR_NUM_ACTOR",
+               "VAR_CURRENT_LIGHTS",
+               "VAR_CURRENTDRIVE",
+               "VAR_TMR_1",
+               # 12
+               "VAR_TMR_2",
+               "VAR_TMR_3",
+               "VAR_MUSIC_TIMER",
+               "VAR_ACTOR_RANGE_MIN",
+               # 16
+               "VAR_ACTOR_RANGE_MAX",
+               "VAR_CAMERA_MIN_X",
+               "VAR_CAMERA_MAX_X",
+               "VAR_TIMER_NEXT",
+               # 20
+               "VAR_VIRT_MOUSE_X",
+               "VAR_VIRT_MOUSE_Y",
+               "VAR_ROOM_RESOURCE",
+               "VAR_LAST_SOUND",
+               # 24
+               "VAR_CUTSCENEEXIT_KEY",
+               "VAR_TALK_ACTOR",
+               "VAR_CAMERA_FAST_X",
+               "VAR_SCROLL_SCRIPT",
+               # 28
+               "VAR_ENTRY_SCRIPT",
+               "VAR_ENTRY_SCRIPT2",
+               "VAR_EXIT_SCRIPT",
+               "VAR_EXIT_SCRIPT2",
+               # 32
+               "VAR_VERB_SCRIPT",
+               "VAR_SENTENCE_SCRIPT",
+               "VAR_INVENTORY_SCRIPT",
+               "VAR_CUTSCENE_START_SCRIPT",
+               # 36
+               "VAR_CUTSCENE_END_SCRIPT",
+               "VAR_CHARINC",
+               "VAR_WALKTO_OBJ",
+               "VAR_DEBUGMODE",
+               # 40
+               "VAR_HEAPSPACE",
+               None,
+               "VAR_RESTART_KEY",
+               "VAR_PAUSE_KEY",
+               # 44
+               "VAR_MOUSE_X",
+               "VAR_MOUSE_Y",
+               "VAR_TIMER",
+               "VAR_TMR_4",
+               # 48
+               "VAR_SOUNDCARD",
+               "VAR_VIDEOMODE",
+               "VAR_MAINMENU_KEY",
+               "VAR_FIXEDDISK",
+               # 52
+               "VAR_CURSORSTATE",
+               "VAR_USERPUT",
+               None,
+               None,
+               # 56
+               "VAR_SOUNDRESULT",
+               "VAR_TALKSTOP_KEY",
+               None,
+               "VAR_FADE_DELAY",
+               # 60
+               "VAR_NOSUBTITLES",
+               None,
+               None,
+               None,
+               # 64
+               "VAR_SOUNDPARAM",
+               "VAR_SOUNDPARAM2",
+               "VAR_SOUNDPARAM3",
+               "VAR_INPUTMODE",
+               # 68
+               "VAR_MEMORY_PERFORMANCE",
+               "VAR_VIDEO_PERFORMANCE",
+               "VAR_ROOM_FLAG",
+               "VAR_GAME_LOADED",
+               # 72
+               "VAR_NEW_ROOM",
+               None,
+               None,
+               None,
+               # 76
+               None,
+               None,
+               None,
+               None)
+
+pmasks = (0x80, 0x40, 0x20)  # paramater bit masks
+
+
+## ByteCode implementations ##
+
+class SCUMM(bytecode.ByteCode):
+    """SCUMM bytecode variants base."""
+
+    # get_complex constants
+    b = 0      # byte
+    w = 1      # word
+    v = 2      # var
+    vob = 3    # var or byte
+    vow = 4    # var or word
+    asc = 5    # ascii
+    lst = 6    # list
+    dps = 7    # decode parse string
+
+    def __init__(self, init, version,
+                 zak_flag=False, indy_flag=False,
+                 unblocked=False, halt_on_error=True):
+        self.version = version
+        self.zak_flag = zak_flag
+        self.indy_flag = indy_flag
+        self.unblocked = unblocked
+        self.halt_on_error = halt_on_error
+        self.script_start = 0
+
+        bytecode.ByteCode.__init__(self, init, SCUMM.get_byte)
+
+    def skip_verb_header(self, off, ofetch, cfetch=0):
+        min_offset = 255
+        offset = off
+        cfetch = cfetch or self.fetch_u8
+        self.seek(offset)
+        print "Events:"
+        code = cfetch()
+        while code != 0:
+            offset = ofetch()
+            print "  %2X - %.4X" % (code, offset)
+            if min_offset > offset:
+                min_offset = offset
+            code = cfetch()
+        try:
+            self.seek(min_offset, 1)
+        except bytecode.OutOfBoundsError:
+            self.seek(len(self), 1)
+
+    def parse_header(self):
+        def calc_magic(string):
+            m = 0
+            bits = len(string) * 8
+            for b in map(ord, string):
+                bits -= 8
+                m |= b << bits
+            return m
+        ssize = len(self)
+        if self.unblocked:
+            if ssize < 4:
+                raise ScriptTooSmallError
+            if self.fetch_le_u32(True) == len(self):
+                if self.version == 0:
+                    self.skip_verb_header(14, self.fetch_u8)
+                elif self.version <= 2:
+                    self.skip_verb_header(15, self.fetch_u8)
+                else:
+                    self.skip_verb_header(17, self.fetch_le_u16)
+            else:
+                self.seek(4)
+        elif self.version >= 5:
+            if ssize < ((self.version == 5 and 8) or 9):
+                raise ScriptTooSmallError
+            magic = self.fetch_be_u32(True)
+            if magic == calc_magic('LSC2'):
+                if ssize <= 12:
+                    raise ScriptTooSmallError
+                self.seek(8)
+                print "Script# %d" % self.fetch_le_u32()
+            elif magic == calc_magic('LSCR'):
+                if self.version == 8:
+                    if ssize <= 12:
+                        raise ScriptTooSmallError
+                    self.seek(8)
+                    print "Script# %d" % self.fetch_le_u32()
+                elif self.version == 7:
+                    if ssize <= 10:
+                        raise ScriptTooSmallError
+                    self.seek(8)
+                    print "Script# %d" % self.fetch_le_u16()
+                else:
+                    if ssize <= 9:
+                        raise ScriptTooSmallError
+                    self.seek(8)
+                    print "Script# %d" % self.fetch_u8()
+            elif magic == calc_magic('SCRP'):
+                self.seek(8)
+            elif magic == calc_magic('ENCD'):
+                self.seek(8)
+            elif magic == calc_magic('EXCD'):
+                self.seek(8)
+            elif magic == calc_magic('VERB'):
+                if self.version == 8:
+                    self.seek(8)  # funny ...
+                    self.skip_verb_header(0, self.fetch_le_u32, self.fetch_le_u32)
+                else:
+                    self.skip_verb_header(8, self.fetch_le_u16)
+            else:
+                raise UnknownScriptTypeError
+        else:
+            if ssize < 6:
+                raise ScriptTooSmallError
+            self.seek(4)
+            magic = self.fetch_be_u16(True)
+            self.seek(0, 1)
+            if magic == calc_magic('LS'):
+                self.seek(6)
+                print "Script# %d" % self.fetch_u8()
+            elif magic == calc_magic('SC'):
+                self.seek(6)
+            elif magic == calc_magic('EN'):
+                self.seek(6)
+            elif magic == calc_magic('EX'):
+                self.seek(6)
+            elif magic == calc_magic('OC'):
+                self.skip_verb_header(19, self.fetch_le_u16)
+            else:
+                raise UnknownScriptTypeError
+        self.script_start = self.get_pos()
+
+    def get_byte(self):
+        return self.fetch_u8()
+
+    def get_word(self):
+        return self.fetch_le_u16()
+
+    def get_num_string(self, i):
+        s = ""
+        if i & 0x8000:
+            i &= 0xfff
+            if i >= 0x800:
+                s = "??Bit??"
+            else:
+                s = "Bit"
+        elif i & 0x4000:
+            i &= 0xfff
+            if i > 0x10:
+                s = "??Local??"
+            else:
+                s = "Local"
+        else:
+            i &= 0xfff
+            if i >= 0x320:
+                s = "??Var??"
+            else:
+                s = "Var"
+        if self.halt_on_error and s[0] == '?':
+            raise VarIndexOutOfRangeError, "%s, was %d" % (s, i)
+        return s
+
+    def get_var(self):
+        i = 0
+        if self.version <= 2:
+            i = self.get_byte()
+        else:
+            i = self.get_word()
+        assert(i >= 0)
+
+        ret = ''
+        if self.version >= 5 and i < len(_var_names5) and \
+                _var_names5[i]:
+            return _var_names5[i]
+        elif self.version >= 4 and i < len(_var_names4) and \
+                _var_names4[i]:
+            return _var_names4[i]
+        elif self.version >= 3 and i < len(_var_names3) and \
+                _var_names3[i]:
+            return _var_names3[i]
+        elif self.version >= 1 and i < len(_var_names2) and \
+                _var_names2[i]:
+            return _var_names2[i]
+        elif self.version >= 0 and i < len(_var_names0) and \
+                _var_names0[i]:
+            return _var_names0[i]
+        elif self.version <= 2 and self.zak_flag and \
+                (i == 234 or i == 235):
+            return (i == 234 and "ZERO") or "ONE"
+        elif (i & 0x8000) and (self.unblocked or self.zak_flag):
+            ret = "Var[%d Bit %d" % ((i & 0x0fff) >> 4, i & 0x000f)
+        else:
+            ret = "%s[%d" % (self.get_num_string(i), i & 0xfff)
+
+        if i & 0x2000:
+            j = self.get_word()
+            if j & 0x2000:
+                j ^= 0x2000
+                ret += " + %s[%d]" % (self.get_num_string(j), j & 0xfff)
+            else:
+                ret += " + %d" % (j & 0xfff)
+
+        ret += "]"
+        return ret
+
+    def get_var_or_byte(self, op, mask):
+        if op & mask:
+            return self.get_var()
+        else:
+            return self.get_byte()
+
+    def get_var_or_word(self, op, mask):
+        if op & mask:
+            return self.get_var()
+        else:
+            return self.get_word()
+
+    def get_list(self):
+        first = 1
+        j = 0
+        ret = '['
+        while 1:
+            i = self.get_byte()
+            if i == 0xff:
+                break
+            if not first:
+                ret += ', '
+            first = 0
+            ret += str(self.get_var_or_word(i, pmasks[0]))
+            j += 1
+            if j > 16:
+                if self.halt_on_error:
+                    raise ArgListVarNumError, \
+                        "too many variables in argument list"
+                break
+        ret += ']'
+        return ret
+
+    def get_ascii(self):
+        def pascii(i):
+            if i > 31 and i < 128:
+                return chr(i)
+            else:
+                return "^%d" % i
+        buf = '"'
+        while 1:
+            i = self.get_byte()
+            if not i:
+                break
+            buf += pascii(i)
+            if i == 0xff:
+                i = self.get_byte()
+                buf += pascii(i)
+                # Workaround for a script bug in Indy3
+                if i == 46 and self.version == 3 and self.indy_flag:
+                    continue
+
+                if i != 1 and i != 2 and i != 3 and i != 8:
+                    buf += pascii(self.get_byte())
+                    buf += pascii(self.get_byte())
+        buf += '"'
+        return buf
+
+    def decode_parse_string(self):
+        buf = '"'
+        c = self.get_byte()
+        while c:
+            flag = (c & 0x80) != 0
+            c &= 0x7f
+            if c < 8:
+                buf += "^%d" % c
+                if c > 3:
+                    buf += "^%d" % self.get_byte()
+            else:
+                buf += chr(c)
+            if flag:
+                buf += ' '
+            c = self.get_byte()
+        buf += '"'
+        return buf
+
+    def get_complex(self, opcode, specs):
+        vals = []
+        mask_index = 0
+        for spec in specs:
+            if spec == self.b:
+                vals.append(self.get_byte())
+            elif spec == self.w:
+                vals.append(self.get_word())
+            elif spec == self.v:
+                vals.append(self.get_var())
+            elif spec == self.vob:
+                vals.append(self.get_var_or_byte(opcode, pmasks[mask_index]))
+                mask_index += 1
+            elif spec == self.vow:
+                vals.append(self.get_var_or_word(opcode, pmasks[mask_index]))
+                mask_index += 1
+            elif spec == self.asc:
+                vals.append(self.get_ascii())
+            elif spec == self.lst:
+                vals.append(self.get_list())
+            elif spec == self.dps:
+                vals.append(self.decode_parse_string())
+        return vals
+
+    def produce_instr(self, name, opcode, *specs):
+        return Instr(name, self.get_complex(opcode, specs))
+
+    def get_masks(self, specs):
+        maskss = ((0x00,),
+                  (0x00, 0x80),
+                  (0x00, 0x80, 0x40, 0x80 | 0x40),
+                  (0x00, 0x80, 0x40, 0x20,
+                   0x80 | 0x40 | 0x20, 0x80 | 0x40, 0x80 | 0x20, 0x40 | 0x20))
+        lspecs = list(specs)
+        npbits = lspecs.count(self.vob)+lspecs.count(self.vow)
+        assert(npbits <= 3)
+        return maskss[npbits]
+
+    def register_complex(self, name, base_code, *specs):
+        def handler(opcode):
+            return Instr(name, self.get_complex(opcode, specs))
+        for mask in self.get_masks(specs):
+            self.register_opcode(base_code | mask, handler)
+
+    def register_complex_set(self, name, base_code, *specs):
+        if not specs: specs = [self.vob]
+        def handler(opcode):
+            return AssgnInstr('=',
+                              self.get_var(),
+                              Instr(name, self.get_complex(opcode, specs)))
+        for mask in self.get_masks(specs):
+            self.register_opcode(base_code | mask, handler)
+
+    def register_simple_set(self, name, opcodes, *specs):
+        def handler(opcode):
+            return AssgnInstr('=',
+                              self.get_var(),
+                              Instr(name, self.get_complex(opcode, specs)))
+        self.register_opcodes(opcodes, handler)
+
+    def register_simple(self, name, opcodes, *specs):
+        def handler(opcode):
+            return Instr(name, self.get_complex(opcode, specs))
+        self.register_opcodes(opcodes, handler)
+
+    def calc_abs_jump(self, relative):
+        return 0x7fff & (relative + (self.get_pos() - self.script_start))
+
+    def make_jump(self, condition=0):
+        offset = self.get_word()
+        to = self.calc_abs_jump(offset)
+        if condition:
+            return CondJump(to, condition)
+        else:
+            return Jump(to)
+
+    def register_if(self, name, base_code, *specs):
+        def handler(opcode):
+            return self.make_jump(Instr(name, self.get_complex(opcode, specs)))
+        for mask in self.get_masks(specs):
+            self.register_opcode(base_code | mask, handler)
+
+
+class SCUMM12(SCUMM):
+    """ByteCode class for SCUMM versions 1 and 2."""
+
+    def populate(self):
+        """Populate self.optable with opcode handlers for versions 1 and 2."""
+        self.register_simple("stopObjectCode", [0x00, 0xa0])
+        self.register_complex("putActor", 0x01, self.vob, self.vob, self.vob)
+        self.register_complex("startMusic", 0x02, self.vob)
+        self.register_complex("startSound", 0x1c, self.vob)
+        self.register_complex_set("getActorRoom", 0x03)
+        self.register_opcodes([0x04, 0x84,
+                               0x48, 0xc8,
+                               0x78, 0xf8,
+                               0x44, 0xc4,
+                               0x08, 0x88,
+                               0x38, 0xb8,
+                               0x28, 0xa8], self.do_if_code)
+        self.register_complex("drawObject", 0x05, self.vow, self.vob, self.vob)
+        self.register_complex_set("getActorElevation", 0x06)
+        # UNCLEAR: descumm and scummvm are in conflict over the second argument
+        # based on scummvm
+        self.register_complex("faceActor", 0x09, self.vob, self.vow)
+        self.register_opcodes([0x2A, 0xAA, 0x3A, 0xBA,
+                               0x6A, 0xEA, 0x0A, 0x8A,
+                               0x1A, 0x5A, 0x9A, 0xDA], self.do_varset)
+        self.register_complex("setObjPreposition", 0x0b, self.vow, self.b)
+        self.register_complex("setObjPreposition", 0x4b, self.vow, self.b)
+        self.register_opcodes([0x0c, 0x8c], self.do_resource)
+        self.register_complex("walkActorToActor", 0x0d, self.vob, self.vob, self.b)
+        self.register_complex("putActorAtObject", 0x0e, self.vob, self.vow)
+        self.register_opcodes([0x3F, 0xBF,
+                               0x5F, 0xDF,
+                               0x2F, 0xAF,
+                               0x0F, 0x8F,
+                               0x7F, 0xFF,
+                               0x1F, 0x9F,
+                               0x6F, 0xEF,
+                               0x4F, 0xCF], self.do_if_state_code)
+        self.register_complex_set("getObjectOwner", 0x10, self.vow)
+        self.register_complex("animateActor", 0x11, self.vob, self.vob)
+        self.register_complex("panCameraTo", 0x12, self.vob)
+        self.register_opcodes([0x13, 0x53, 0x93, 0xd3], self.do_actor_ops)
+        self.register_complex("beginOverride", 0x58)
+        self.register_complex("actorFollowCamera", 0x52, self.vob)
+        self.register_complex_set("actorFromPos", 0x15, self.vob, self.vob)
+        self.register_opcode(0x2c, self.do_varset)
+        self.register_complex("breakHere", 0x80)
+        self.register_complex("chainScript", 0x4a, self.vob)
+        self.register_opcodes([0x60, 0xe0], self.do_cursor_command)
+        self.register_complex("cutscene", 0x40)
+        self.register_complex("endCutscene", 0xc0)
+        self.register_opcodes([0x46, 0xc6], self.do_varset)
+        self.register_opcode(0x2e, self.do_delay)
+        self.register_complex("delayVariable", 0x2b, self.v)
+        self.register_opcodes([0x19, 0x39, 0x59, 0x79,
+                               0x99, 0xb9, 0xd9, 0xf9],
+                              self.do_sentence)
+        self.register_complex("drawSentence", 0xac)
+        self.register_opcodes([0x5c, 0x6b, 0x6e, 0xab, 0xdc, 0xeb, 0xee],
+                              self.do_dummy)
+        self.register_complex("findObject", 0x35, self.vow, self.vow)
+        self.register_complex_set("getActorCostume", 0x71)
+        self.register_complex_set("getActorFacing", 0x63)
+        self.register_complex_set("getActorMoving", 0x56)
+        self.register_complex_set("getActorWalkBox", 0x7b)
+        self.register_complex_set("getActorX", 0x43)
+        self.register_complex_set("getActorY", 0x23)
+        self.register_complex_set("getBitVar", 0x31, self.w, self.vob)
+        self.register_complex_set("setBitVar", 0x1b, self.w, self.vob, self.vob)
+        self.register_complex_set("getClosestObjActor", 0x66, self.vow)
+        self.register_complex_set("getDist", 0x34, self.vow, self.vow)
+        self.register_complex_set("getObjPreposition", 0x6c, self.vow)
+        self.register_complex_set("getRandomNr", 0x16)
+        self.register_if("classOfIs", 0x1d, self.vow, self.vob)
+        self.register_complex_set("isScriptRunning", 0x68)
+        self.register_complex_set("isSoundRunning", 0x7c)
+        self.register_opcode(0x18, self.do_jump)
+        self.register_complex("lights", 0x70, self.vob, self.b, self.b)
+        self.register_complex("loadRoom", 0x72, self.vob)
+        self.register_complex("loadRoomWithEgo", 0x24,
+                              self.vow, self.vob, self.b, self.b)
+        self.register_complex("setBoxFlags", 0x30, self.vob, self.b)
+        self.register_complex("pickupObject", 0x50, self.vow)
+        self.register_complex("print", 0x14, self.vob, self.dps)
+        self.register_complex("printEgo", 0xd8, self.dps)
+        self.register_opcode(0xcc, self.do_pseudo_room)
+        self.register_complex("putActorInRoom", 0x2d, self.vob, self.vob)
+        self.register_complex("restart", 0x98)
+        self.register_opcodes([0x33, 0x73, 0xb3, 0xf3], self.do_room_ops_old)
+        self.register_complex_set("saveLoadGame", 0x22, self.vob)
+        self.register_complex("setActorElevation", 0x3d, self.vob, self.vob)
+        self.register_complex("setCameraAt", 0x32, self.vob)
+        self.register_complex("setObjectName", 0x54, self.vow, self.asc)
+        self.register_complex("setOwnerOf", 0x29, self.vow, self.vob)
+        self.register_complex("clearState01", 0x77, self.vow)
+        self.register_complex("clearState02", 0x17, self.vow)
+        self.register_complex("clearState04", 0x67, self.vow)
+        self.register_complex("clearState08", 0x47, self.vow)
+        self.register_complex("setState01", 0x37, self.vow)
+        self.register_complex("setState02", 0x57, self.vow)
+        self.register_complex("setState04", 0x27, self.vow)
+        self.register_complex("setState08", 0x07, self.vow)
+        self.register_opcodes([0x26, 0xa6], self.do_var_range)
+        self.register_complex("stopScript", 0x62, self.vob)
+        self.register_complex("stopSound", 0x3c, self.vob)
+        self.register_complex("stopMusic", 0x20)
+        self.register_opcodes([0x7a, 0xfa], self.do_verbops)
+        self.register_complex("waitForActor", 0x3b, self.vob)
+        self.register_complex("waitForSentence", 0x4c)
+        self.register_complex("waitForMessage", 0xae)
+        self.register_complex("walkActorTo", 0x1e, self.vob, self.vob, self.vob)
+        self.register_complex("walkActorToObject", 0x36, self.vob, self.vow)
+        self.register_complex("startScript", 0x42, self.vob)
+
+    def do_var_range(self, opcode):
+        var = self.get_var()
+        i = self.get_byte()
+        nums = []
+        j = i
+        while j > 0:
+            if opcode & 0x80:
+                nums.append(self.get_word())
+            else:
+                nums.append(self.get_byte())
+            j -= 1
+        return Instr("setVarRange", [var, i, nums])
+
+    def do_jump(self, _):
+        return self.make_jump()
+
+    def do_dummy(self, opcode):
+        return Instr("dummy", ["%.2X" % opcode])
+
+    def do_sentence(self, opcode):
+        if (not (opcode & 0x80)) and self.fetch_u8(True) == 0xfc:
+            args = ["STOP"]
+            self.seek(1)
+        elif (not (opcode & 0x80)) and self.fetch_u8(True) == 0xfb:
+            args = ["Reset"]
+            self.seek(1)
+        else:
+            args = self.get_complex(opcode,
+                                    [self.vob, self.vow,
+                                     self.vow, self.b])
+        return Instr("doSentence", args)
+
+    def do_delay(self, _):
+        d = self.get_byte()
+        d |= self.get_byte() << 8
+        d |= self.get_byte() << 16
+        d = 0xffffff - d
+        return Instr("delay", [d])
+
+    def do_cursor_command(self, opcode):
+        if opcode & 0x80:
+            tmp = str(self.get_var())
+            return Instr("cursorCommand", ["Hi(%s)" % tmp, "Lo(%s)" % tmp])
+        else:
+            tmp = self.get_word()
+            return Instr("cursorCommand", [(tmp >> 8) & 0xff, tmp & 0xff])
+
+    def do_actor_ops(self, opcode):
+        args = [self.get_var_or_byte(opcode, pmasks[0])]
+        arg2 = self.get_var_or_byte(opcode, pmasks[1])
+
+        subop = self.get_byte()
+        if subop == 1:
+            args.append(Instr("Sound", [arg2]))
+        elif subop == 2:
+            if self.version == 1:
+                args.append(Instr("Color", [arg2]))
+            else:
+                args.append(Instr("Color", [self.get_byte(), arg2]))
+        elif subop == 3:
+            args.append(Instr("Name", [self.get_ascii()]))
+        elif subop == 4:
+            args.append(Instr("Costume", [arg2]))
+        elif subop == 5:
+            args.append(Instr("TalkColor", [arg2]))
+        else:
+            raise UnknownSubOpError, \
+                "SCUMM12.do_actor_ops: %d" % subop
+        return Instr("ActorOps", args)
+
+    def do_resource(self, opcode):
+        res_types = ("UnkResType0",
+                     "UnkResType1",
+                     "Costume",
+                     "Room",
+                     "UnkResType4",
+                     "Script",
+                     "Sound")
+        resid = self.get_var_or_byte(opcode, pmasks[0])
+        subop = self.get_byte()
+        typ = subop >> 4
+        assert(0 <= typ < len(res_types))
+        if (subop & 0x0f) == 0 or (subop & 0x0f) == 1:
+            if subop & 1:
+                buf = "load"
+            else:
+                buf = "nuke"
+        else:
+            if subop & 1:
+                buf = "lock"
+            else:
+                buf = "unlock"
+        return Instr(buf + res_types[typ], [resid])
+
+    def do_pseudo_room(self, _):
+        args = [self.get_byte()]
+        while 1:
+            j = self.get_byte()
+            if not j:
+                break
+            if j & 128:
+                args.append(j & 127)
+            else:
+                args.append('IG')
+        return Instr("PseudoRoom", args)
+
+    def do_room_ops_old(self, opcode):
+        if self.version <= 2:
+            a, b = self.get_complex(opcode, [self.vob, self.vob])
+        elif self.version == 3:
+            a, b = self.get_complex(opcode, [self.vow, self.vow])
+        opc = self.get_byte()
+        opcm = opc & 0x1f
+        if 0x01 <= opcm <= 0x04:
+            if self.version > 3:
+                a, b = self.get_complex(opc, [self.vow, self.vow])
+            return Instr({0x01 : "RoomScroll",
+                          0x02 : "RoomColor",
+                          0x03 : "SetScreen",
+                          0x04 : "SetPalColor"}[opcm],
+                         [a, b])
+        elif 0x05:
+            return Instr("ShakeOn", [])
+        elif 0x06:
+            return Instr("ShakeOff", [])
+        else:
+            raise UnknownSubOpError, \
+                "SCUMM12.do_room_ops_old: unknown subop %d" % opcm
+
+    def do_verbops(self, opcode):
+        subop = self.get_byte()
+        if subop == 0x00:
+            return self.produce_instr("VerbOpsDelete", opcode, self.vob)
+        elif subop == 0xff:
+            return self.produce_instr("VerbOpsState", opcode, self.b, self.b)
+        else:
+            return self.produce_instr("VerbOpsNew-%d" % subop, opcode,
+                                      self.b, self.b, self.vob,
+                                      self.b, self.asc)
+
+    def do_varset(self, opcode):
+        if self.version <= 2 and ((opcode & 0x7f) == 0x0a or
+                                  (opcode & 0x7f) == 0x2a or
+                                  (opcode & 0x7f) == 0x6a):
+            dst = "Var[Var[%d]]" % self.get_byte()
+        else:
+            dst = self.get_var()
+        opcm = opcode & 0x7f
+        if opcm in (0x0a, 0x1a, 0x2c):
+            asgop = '='
+        elif opcm == 0x1b:
+            asgop = '*='
+        elif opcm in (0x3a, 0x6a) or (opcm == 0x46 and opcode & 128):
+            asgop = '-='
+        elif opcm == 0x57:
+            asgop = '|='
+        elif opcm in (0x2a, 0x5a) or opcm == 0x46:
+            asgop = '+='
+        elif opcm == 0x5b:
+            asgop = '/='
+        elif opcm == 0x17:
+            asgop = '&='
+        else:
+            raise UnknownSubOpError, \
+                "SCUMM12.do_varset: unknown varset %d" % opcode
+        if self.version <= 2 and opcm == 0x2c:
+            val = self.get_byte()
+        elif opcm == 0x46:
+            val = 1
+        elif self.version == 0:
+            val = self.get_var_or_byte(opcode, pmasks[0])
+        else:
+            val = self.get_var_or_word(opcode, pmasks[0])
+        return AssgnInstr(asgop, dst, val)
+
+    def do_if_code(self, opcode):
+        cmp_texts = (' >= ', ' < ', ' <= ', ' > ', ' == ', ' != ', '!', '')
+        if opcode in (0x28, 0xa8):
+            a = ''
+        else:
+            a = self.get_var()
+        opcm = opcode & 0x7f
+        # The following might raise a KeyError exception
+        comp = cmp_texts[{ 0x38 : 0,
+                           0x04 : 2,
+                           0x08 : 5,
+                           0x48 : 4,
+                           0x78 : 1,
+                           0x44 : 3,
+                           0x28 : ((opcode & 128) and 7) or 6 }[opcm]]
+        if opcode in (0x28, 0xa8):
+            b = self.get_var()
+        elif self.version == 0:
+            b = self.get_var_or_byte(opcode, pmasks[0])
+        else:
+            b = self.get_var_or_word(opcode, pmasks[0])
+        return self.make_jump("%s%s%s" % (str(a), comp, str(b)))
+
+    def do_if_state_code(self, opcode):
+        var = ''
+        if self.version == 0:
+            if opcode & 0x40:
+                var = 'activeObject'
+            else:
+                var = self.get_byte()
+        else:
+            var = self.get_var_or_word(opcode, pmasks[0])
+        if self.version > 2:
+            opcm = opcode & 0x2f
+            if opcm == 0x0f:
+                neg = 0
+            elif opcm == 0x2f:
+                neg = 1
+            else:
+                raise Error, "SCUMM12.do_if_state_code .. weird"
+            tmp = self.get_var_or_byte(opcode, pmasks[1])
+        else:
+            if self.version == 0:
+                # The following might rais a KeyError exception
+                state, neg = { 0x7f : (2, 1), 0xbf : (2, 1),
+                               0x9f : (4, 1), 0xdf : (4, 1),
+                               0xaf : (8, 1), 0xef : (8, 1),
+                               0x3f : (2, 0), 0xff : (2, 0),
+                               0x1f : (4, 0), 0x5f : (4, 0),
+                               0x2f : (8, 0), 0x6f : (8, 0) }[opcode]
+            else:
+                state, neg = { 0x3f : (1, 1), 0xbf : (1, 1),
+                               0x5f : (2, 1), 0xdf : (2, 1),
+                               0x2f : (4, 1), 0xaf : (4, 1),
+                               0x0f : (8, 1), 0x8f : (8, 1),
+                               0x7f : (1, 0), 0xff : (1, 0),
+                               0x1f : (2, 0), 0x9f : (2, 0),
+                               0x6f : (4, 0), 0xef : (4, 0),
+                               0x4f : (8, 0), 0xcf : (8, 0) }[opcode]
+        if self.version > 2:
+            return self.make_jump("getState(%s)%s%s" % \
+                                  (var, (neg and ' != ') or ' == ', tmp))
+        return self.make_jump("%sgetState%02d(%s)" % \
+                              ((neg and '!') or '', state, var))
+
+
+class SCUMM0(SCUMM12):
+    """Bytecode class for SCUMM version 0."""
+
+    def populate(self):
+        """Populate self.optable with opcode handlers for version 0."""
+        SCUMM12.populate(self)
+
+        self.register_simple("doSentence", [0x03, 0x43, 0x83, 0xc3],
+                             self.b, self.b, self.b)
+        self.register_simple("stopCurrentScript",
+                             [0x05, 0x09, 0x0A, 0x19, 0x23, 0x2C,
+                              0x35, 0x39, 0x3B, 0x45, 0x49, 0x59,
+                              0x63, 0x65, 0x6A, 0x6C, 0x79, 0x7A,
+                              0x7B, 0x80, 0x82, 0x85, 0x89, 0x8A,
+                              0x8D, 0x96, 0x99, 0xA3, 0xA6, 0xAA,
+                              0xAC, 0xB5, 0xB9, 0xBB, 0xC5, 0xC9,
+                              0xD8, 0xD9, 0xE3, 0xE6, 0xEA, 0xEC,
+                              0xF5, 0xF9, 0xFA, 0xFB])
+        self.register_complex_set("getDist", 0x34, self.vob, self.vob)
+        self.register_simple_set("getDist", 0x06, self.vob, self.vob)
+        self.register_simple_set("getActorRoom", 0x07, self.vob)
+        self.register_complex("setActorBitVar", 0x0b, self.vob, self.vob, self.vob)
+        self.register_simple("loadSound", [0x0c, 0x8c], self.b)
+        self.register_simple("printEgo_c64", [0x0d, 0x75], self.dps)
+        self.register_complex("putActorAtObject", 0x0e, self.vob, self.b)
+        self.register_complex("putActorAtObject", 0x4e, self.vob, self.b)
+        self.register_simple("breakHere", [0x10])
+
+        def mak_state_handler(name):
+            def handler(opcode):
+                if opcode & 0x40:
+                    return Instr(name, 0)
+                return Instr(name, self.get_byte())
+            return handler
+        self.register_opcodes([0x0f, 0x4f], mak_state_handler("clearState02"))
+        self.register_opcodes([0x37, 0x77], mak_state_handler("clearState04"))
+        self.register_opcodes([0x17, 0x57], mak_state_handler("clearState08"))
+        self.register_opcodes([0x8f, 0xcf], mak_state_handler("setState02"))
+        self.register_opcodes([0xb7, 0xf7], mak_state_handler("setState04"))
+        self.register_opcodes([0x97, 0xd7], mak_state_handler("setState08"))
+        self.register_complex("animateActor", 0x11, self.vob, self.vob, self.b)
+        self.register_complex("lockCostume", 0x13, self.b)
+        self.register_complex("lockRoom", 0x4d, self.b)
+        self.register_complex("unlockRoom", 0xcd, self.b)
+        self.register_complex("unlockCostume", 0x93, self.b)
+        self.register_complex("print_c64", 0x2e, self.vob, self.dps)
+        # these are just weird. funny code reuse in scummvm and "code reuse"
+        # in descumm.  unnecessary checks for opcode parameter bits.
+        self.register_simple("walkActorToActor",
+                             [0x15, 0x55],
+                             self.vob, self.vob, self.b)
+        self.register_simple("getRandomNr", [0x16], self.vob)
+        self.register_complex_set("getActorBitVar", 0x1b, self.vob, self.vob)
+        # descumm is wrong about this.
+        self.register_complex("setBitVar", 0x1d, self.vob, self.vob, self.vob)
+        self.register_complex("unknown2", 0x24, self.vob)
+        self.register_complex("loadRoom", 0x25, self.vob)
+        # another weird one
+        self.register_simple("getClosestObjActor", [0x26, 0x66], self.vob)
+        self.register_complex("getActorY", 0x27)
+        self.register_complex("setOwnerOf", 0x29, self.vob, self.vob)
+        self.register_opcode(0x2a, self.do_delay)
+        self.register_complex("loadCostume", 0x30, self.vob)
+        self.register_complex_set("getBitVar", 0x31, self.vob, self.vob)
+        self.register_complex("lockScript", 0x33, self.b)
+        self.register_complex("cutscene", 0x40)
+        self.register_complex_set("getActorX", 0x47)
+        self.register_complex("loadRoom_c64", 0x4a, self.vob)
+        self.register_complex("loadScript", 0x4c, self.vob)
+        self.register_complex("lockRoom", 0x4d, self.b)
+        self.register_simple("nop", [0x50, 0x72, 0xd0, 0xf2])
+        self.register_complex("lockSound", 0x54, self.b)
+        self.register_simple("setObjectName", [0x54, 0xd4], self.b, self.asc)
+        self.register_complex_set("getActorMoving", 0x56)
+        self.register_complex("beginOverride", 0x58, self.b, self.w)
+        self.register_complex("cursorCommand", 0x60, self.vob)
+        self.register_opcodes([0x64, 0xe4], self.do_if_active_object)
+        self.register_complex_set("getActorFacing", 0x67, self.b, self.vob)
+        self.register_complex("lights", 0x70, self.vob)
+        self.register_complex_set("getObjectOwner", 0x73)
+        self.register_complex("pickupObject", 0x90, self.b)
+        self.register_complex("unlockCostume", 0x93, self.b)
+        self.register_complex("unlockScript", 0xb3, self.b)
+        self.register_complex("unlockRoom", 0xcd, self.b)
+        self.register_complex("unlockSound", 0xd3, self.b)
+        self.register_complex("loadRoomWithEgo", 0xe5, self.b, self.b)
+
+    def do_if_active_object(self, _):
+        return self.make_jump("activeObject2 == " % self.get_byte())
+
+
+class SCUMM345(SCUMM12):
+    """ByteCode class for SCUMM versions 3, 4 and 5."""
+
+    def populate(self):
+        """Populate self.optable with opcode handlers for versions 3, 4 and 5."""
+        SCUMM12.populate(self)
+
+        self.register_complex("putActor", 0x01, self.vob, self.vow, self.vow)
+        if self.zak_flag:
+            self.register_complex_set("startMusic", 0x02, self.vob)
+        if self.version == 5:
+            self.register_opcodes([0x05, 0x45, 0x85, 0xc5],
+                                  self.do_draw_object_v5)
+        else:
+            self.register_complex("drawObject", 0x05,
+                                  self.vow, self.vow, self.vow)
+        self.register_complex("setState", 0x07, self.vow, self.vob)
+        self.register_simple("startScript",
+                             [0x0A, 0x8A, 0x2A, 0xAA, 0x4A, 0xCA, 0x6A, 0xEA],
+                             self.vob, self.lst)
+        self.register_complex_set("getVerbEntryPoint", 0x0b, self.vow, self.vow)
+        self.register_opcodes([0x0c, 0x8c], self.do_resource)
+        self.register_opcodes([0x0f, 0x8f,
+                               0x2f, 0x4f,
+                               0x6f, 0xaf,
+                               0xcf, 0xef], self.do_if_state_code)
+        if self.version == 5:
+            self.register_complex_set("getObjectState", 0x0f, self.vow)
+        self.register_complex("panCameraTo", 0x12, self.vow)
+        self.register_opcodes([0x13, 0x53, 0x93, 0xd3], self.do_actor_ops)
+        self.register_complex_set("actorFromPos", 0x15, self.vow, self.vow)
+        self.register_opcodes([0x17, 0x97,
+                               0x1a, 0x9a,
+                               0x1b, 0x9b,
+                               0x3a, 0xba,
+                               0x46, 0xc6,
+                               0x57, 0xd7,
+                               0x5a, 0xda,
+                               0x5b, 0xdb], self.do_varset)
+        self.register_opcodes([0x19, 0x39, 0x59, 0x79, 0x99, 0xb9, 0xd9, 0xf9],
+                              self.do_sentence)
+        self.register_if("classOfIs", 0x1d, self.vow, self.lst)
+        self.register_complex("walkActorTo", 0x1e, self.vob, self.vow, self.vow)
+        self.register_if("isActorInBox", 0x1f, self.vob, self.vob)
+        if self.version == 5:
+            self.register_complex_set("getAnimCounter", 0x22)
+        else:
+            self.register_complex_set("saveLoadGame", 0x22)
+        if self.indy_flag:
+            self.register_complex_set("getActorY", 0x23)
+            self.register_complex_set("getActorX", 0x43)
+        else:
+            self.register_complex_set("getActorY", 0x23, self.vow)
+            self.register_complex_set("getActorX", 0x43, self.vow)
+        self.register_complex("loadRoomWithEgo", 0x24,
+                              self.vow, self.vob, self.w, self.w)
+        if self.version == 5:
+            self.register_complex("pickupObject", 0x25, self.vow, self.vob)
+        else:
+            self.register_simple("drawObject",
+                                 [0x25, 0x65, 0xa5, 0xe5],
+                                 self.vow, self.vow, self.vow)
+        self.register_opcode(0x27, self.do_string_ops)
+        self.register_complex("setOwnerOf", 0x29, self.vow, self.vob)
+        self.register_opcode(0x2c, self.do_cursor_command)
+        self.register_complex("putActorInRoom", 0x2d, self.vob, self.vob)
+        self.register_opcode(0x2e, self.do_delay)
+        if self.version == 3:
+            self.register_complex("setBoxFlags", 0x30, self.vob, self.b)
+        else:
+            self.register_opcodes([0x30, 0xb0], self.do_matrix_ops)
+        self.register_complex_set("getInventoryCount", 0x31)
+        self.register_complex("setCameraAt", 0x32, self.vow)
+        if self.version == 5:
+            self.register_opcodes([0x33, 0x73, 0xb3, 0xf3], self.do_room_ops)
+        else:
+            self.register_opcodes([0x33, 0x73, 0xb3, 0xf3], self.do_room_ops_old)
+        self.register_complex_set("findObject", 0x35, self.vow, self.vow)
+        self.register_complex("walkActorToObject", 0x36, self.vob, self.vow)
+        self.register_complex("startObject", 0x37, self.vow, self.vob, self.lst)
+        if self.indy_flag:
+            self.register_complex("waitForActor", 0x3b, self.vob)
+        else:
+            self.register_complex_set("getActorScale", 0x3b)
+        self.register_complex_set("findInventory", 0x3d, self.vob, self.vob)
+        self.register_opcodes([0x3f, 0x7f, 0xbf, 0xff], self.do_draw_box)
+        self.register_complex("cutscene", 0x40, self.lst)
+        self.register_complex("chainScript", 0x42, self.vob, self.lst)
+        if self.version <= 3:
+            self.register_complex("waitForSentence", 0x4c)
+        else:
+            self.register_complex("soundKludge", 0x4c, self.lst)
+        self.register_complex("pickupObject", 0x50, self.vow)
+        self.register_opcode(0x58, self.do_begin_override)
+        self.register_opcode(0x5c, self.do_old_room_effect)
+        self.register_complex("setClass", 0x5d, self.vow, self.lst)
+        self.register_complex("freezeScripts", 0x60, self.vob)
+        self.register_complex("stopScript", 0x62, self.vob)
+        self.register_complex_set("getStringWidth", 0x67)
+        # descumm seems to miss 0xeb
+        self.register_complex("debug", 0x6b, self.vow)
+        self.register_complex_set("getActorWidth", 0x6c)
+        self.register_complex("stopObjectScript", 0x6e, self.vow)
+        self.register_complex("lights", 0x70, self.vob, self.b, self.b)
+        self.register_opcodes([0x7a, 0xfa], self.do_verbops)
+        self.register_complex_set("getActorWalkBox", 0x7b)
+        self.register_complex("systemOps", 0x98, self.b)
+        if self.version == 5:
+            self.register_opcode(0xa7, self.do_dummy)
+        else:
+            self.register_opcode(0xa7, self.do_save_load_vars)
+        self.register_opcode(0xab, self.do_save_restore_verbs)
+        self.register_opcode(0xac, self.do_expression)
+        self.register_opcode(0xae, self.do_wait)
+        self.register_complex("endCutscene", 0xc0)
+
+    def do_wait(self, _):
+        if self.indy_flag:
+            opc = 2
+        else:
+            opc = self.get_byte()
+        if opc in (0x01, 0x81):
+            return self.produce_instr("WaitForActor", opc, self.vob)
+        elif opc == 0x02:
+            return Instr("WaitForMessage", [])
+        elif opc == 0x03:
+            return Instr("WaitForCamera", [])
+        elif opc == 0x04:
+            return Instr("WaitForSentence", [])
+        else:
+            raise UnknownSubOpError, \
+                "SCUMM345.do_wait: unknown subop %d" % opc
+
+    def do_save_restore_verbs(self, _):
+        opc = self.get_byte()
+        opcm = opc & 0x1f
+        if opcm == 0x01:
+            return self.produce_instr("saveVerbs", opc,
+                                      self.vob, self.vob, self.vob)
+        elif opcm == 0x02:
+            return self.produce_instr("restoreVerbs", opc,
+                                      self.vob, self.vob, self.vob)
+        elif opcm == 0x03:
+            return self.produce_instr("deleteVerbs", opc,
+                                      self.vob, self.vob, self.vob)
+        else:
+            raise UnknownSubOpError, \
+                "SCUMM345.do_save_restore_verbs: unknown subop %d" % opcm
+
+    def do_save_load_vars(self, _):
+        opc = self.get_byte()
+        if opc == 1:
+            name = "saveVars"
+        else:
+            name = "loadVars"
+        args = []
+        opc = self.get_byte()
+        while opc:
+            opcm = opc & 0x1f
+            if opcm == 0x01:
+                args.append(self.produce_instr("VarRange", opc, self.v, self.v))
+            elif opcm == 0x02:
+                args.append(self.produce_instr("StringRange", opc,
+                                               self.vob, self.vob))
+            elif opcm == 0x03:
+                args.append(self.produce_instr("Open", opc, self.asc))
+            elif opcm == 0x04:
+                args.append(Instr("Append", []))
+            elif opcm == 0x1f:
+                args.append(Instr("Close", []))
+            opc = self.get_byte()
+        return Instr(name, args)
+
+    def do_old_room_effect(self, opcode):
+        d = self.get_byte()
+        if (d & 0x1f) == 3:
+            return Instr("oldRoomEffect-set",
+                         self.get_var_or_word(opcode, pmasks[0]))
+        return Instr("oldRoomEffect-fadein",
+                     self.get_var_or_word(opcode, pmasks[0]))
+
+    def do_begin_override(self, _):
+        d = self.get_byte()
+        if d:
+            return Instr("beginOverride", [])
+        return Instr("endOverride", [])
+
+    def do_draw_box(self, opcode):
+        args = self.get_complex(opcode, [self.vow, self.vow])
+        opcode = self.get_byte()
+        args += self.get_complex(opcode, [self.vow, self.vow, self.vob])
+        return Instr("drawBox", args)
+
+    def do_delay(self, _):
+        d = self.get_byte()
+        d |= self.get_byte() << 8
+        d |= self.get_byte() << 16
+        return Instr("delay", [d])
+
+    def do_string_ops(self, _):
+        opc = self.get_byte()
+        opcm = opc & 0x1f
+        if opcm == 0x01:
+            instr = self.produce_instr("PutCodeInString", opc, self.vob, self.asc)
+        elif opcm == 0x02:
+            instr = self.produce_instr("CopyString", opc, self.vob, self.vob)
+        elif opcm == 0x03:
+            instr = self.produce_instr("SetStringChar", opc,
+                                       self.vob, self.vob, self.vob)
+        elif opcm == 0x04:
+            instr = AssgnInstr('=',
+                               self.get_var(),
+                               self.produce_instr("GetStringChar",
+                                                  opc,
+                                                  self.vob,
+                                                  self.vob))
+        elif opcm == 0x05:
+            instr = self.produce_instr("CreateString", opc, self.vob, self.vob)
+        else:
+            raise UnknownSubOpError, \
+                "SCUMM345.do_string_ops: unknown string func %d" % opcm
+        return instr
+
+    def do_sentence(self, opcode):
+        name = "doSentence"
+        verb = self.get_var_or_byte(opcode, pmasks[0])
+        if verb == 0xfe:
+            return Instr(name, ["STOP"])
+        return Instr(name, [verb,
+                            self.get_var_or_word(opcode, pmasks[1]),
+                            self.get_var_or_word(opcode, pmasks[2])])
+
+    def do_draw_object_v5(self, opcode):
+        args = self.get_complex(opcode, [self.vow])
+        opc = self.get_byte()
+        opcm = opc & 0x1f
+        if opcm == 1:
+            args.append(self.produce_instr("setXY", opc, self.vow, self.vow))
+        elif opcm == 2:
+            args.append(self.produce_instr("setImage", opc, self.vow))
+        return Instr("drawObject", args)
+
+    def do_actor_ops(self, opcode):
+        convert_table = \
+            (1, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9,
+             10, 11, 12, 13, 14, 15, 16, 17, 20)
+
+        args = [self.get_var_or_byte(opcode, pmasks[0])]
+        instrs = []
+
+        while 1:
+            opc = self.get_byte()
+            if opc == 0xff:
+                break
+            if self.version < 5:
+                opc = (opc & 0xe0) | convert_table[(opc & 0x1f) - 1]
+            opcm = opc & 0x1f
+            if opcm == 0x00:
+                instrs.append(self.produce_instr("Unknown", opc, self.vob))
+            elif opcm == 0x01:
+                instrs.append(self.produce_instr("Costume", opc, self.vob))
+            elif opcm == 0x02:
+                instrs.append(self.produce_instr("WalkSpeed",
+                                                 opc,
+                                                 self.vob,
+                                                 self.vob))
+            elif opcm == 0x03:
+                instrs.append(self.produce_instr("Sound", opc, self.vob))
+            elif opcm == 0x04:
+                instrs.append(self.produce_instr("WalkAnimNr", opc, self.vob))
+            elif opcm == 0x05:
+                instrs.append(self.produce_instr("TalkAnimNr",
+                                                 opc,
+                                                 self.vob,
+                                                 self.vob))
+            elif opcm == 0x06:
+                instrs.append(self.produce_instr("StandAnimNr", opc, self.vob))
+            elif opcm == 0x07:
+                instrs.append(self.produce_instr("Nothing",
+                                                 opc,
+                                                 self.vob,
+                                                 self.vob,
+                                                 self.vob))
+            elif opcm == 0x08:
+                instrs.append(Instr("Init", []))
+            elif opcm == 0x09:
+                instrs.append(self.produce_instr("Elevation", opc, self.vow))
+            elif opcm == 0x0a:
+                instrs.append(Instr("DefaultAnims", []))
+            elif opcm == 0x0b:
+                instrs.append(self.produce_instr("Palette",
+                                                 opc,
+                                                 self.vob,
+                                                 self.vob))
+            elif opcm == 0x0c:
+                instrs.append(self.produce_instr("TalkColor", opc, self.vob))
+            elif opcm == 0x0d:
+                instrs.append(self.produce_instr("Name", opc, self.asc))
+            elif opcm == 0x0e:
+                instrs.append(self.produce_instr("InitAnimNr", opc, self.vob))
+#             elif opcm == 0x0f:
+#                 instrs.append(self.produce_instr("PaletteList", opc, self.lst))
+            elif opcm == 0x10:
+                instrs.append(self.produce_instr("Width", opc, self.vob))
+            elif opcm == 0x11:
+                if self.version == 5:
+                    instrs.append(self.produce_instr("Scale",
+                                                     opc,
+                                                     self.vob,
+                                                     self.vob))
+                else:
+                    instrs.append(self.produce_instr("Scale", opc, self.vob))
+            elif opcm == 0x12:
+                instrs.append(Instr("NeverZClip", []))
+            elif opcm == 0x13:
+                instrs.append(self.produce_instr("SetZClip", opc, self.vob))
+            elif opcm == 0x14:
+                instrs.append(Instr("IgnoreBoxes", []))
+            elif opcm == 0x15:
+                instrs.append(Instr("FollowBoxes", []))
+            elif opcm == 0x16:
+                instrs.append(self.produce_instr("AnimeSpeed", opc, self.vob))
+            elif opcm == 0x16:
+                instrs.append(self.produce_instr("ShadowMode", opc, self.vob))
+            else:
+                raise UnknownSubOpError, \
+                    "SCUMM345.do_actor_ops: %d" % opcm
+        return Instr("ActorOps", args + instrs)
+
+    def do_expression(self, _):
+        dst = self.get_var()
+        expr_stack = []
+        while 1:
+            i = self.get_byte()
+            if i == 0xff:
+                break;
+            im = i & 0x1f
+            if not 0x1 <= im <= 0x6:
+                raise InvalidExpressionCodeError, \
+                    "SCUMM345.handle_expression: %d is not a valid expression code" % im
+            elif im == 0x1:
+                expr_stack.append(str(self.get_var_or_word(i, pmasks[0])))
+            elif im == 0x6:
+                expr_stack.append("<%s>" % self.decode_next())
+            else:
+                exop = { 0x2 : '+', 0x3 : '-', 0x4 : '*', 0x5 : '/'}[im]
+                b = expr_stack.pop()
+                a = expr_stack.pop()
+                expr_stack.append("(%s %s %s)" % (a, exop, b))
+        return AssgnInstr('=', dst, expr_stack.pop())
+
+    def do_resource(self, _):
+        opc = self.get_byte()
+        if self.version != 5:  # FIXME - should only be done for Zak256
+            subop = opc & 0x3f
+        else:
+            subop = opc & 0x1f
+
+        if subop == 0x1:
+            instr = self.produce_instr("loadScript", opc, self.vob)
+        elif subop == 0x2:
+            instr = self.produce_instr("loadSound", opc, self.vob)
+        elif subop == 0x3:
+            instr = self.produce_instr("loadCostume", opc, self.vob)
+        elif subop == 0x4:
+            instr = self.produce_instr("loadRoom", opc, self.vob)
+        elif subop == 0x5:
+            instr = self.produce_instr("nukeScript", opc, self.vob)
+        elif subop == 0x6:
+            instr = self.produce_instr("nukeSound", opc, self.vob)
+        elif subop == 0x7:
+            instr = self.produce_instr("nukeCostume", opc, self.vob)
+        elif subop == 0x8:
+            instr = self.produce_instr("nukeRoom", opc, self.vob)
+        elif subop == 0x9:
+            instr = self.produce_instr("lockScript", opc, self.vob)
+        elif subop == 0xa:
+            instr = self.produce_instr("lockSound", opc, self.vob)
+        elif subop == 0xb:
+            instr = self.produce_instr("lockCostume", opc, self.vob)
+        elif subop == 0xc:
+            instr = self.produce_instr("lockRoom", opc, self.vob)
+        elif subop == 0xd:
+            instr = self.produce_instr("unlockScript", opc, self.vob)
+        elif subop == 0xe:
+            instr = self.produce_instr("unlockSound", opc, self.vob)
+        elif subop == 0xf:
+            instr = self.produce_instr("unlockCostume", opc, self.vob)
+        elif subop == 0x10:
+            instr = self.produce_instr("unlockRoom", opc, self.vob)
+        elif subop == 0x11:
+            instr = Instr("clearHeap", [])
+        elif subop == 0x12:
+            instr = self.produce_instr("loadCharset", opc, self.vob)
+        elif subop == 0x13:
+            instr = self.produce_instr("nukeCharset", opc, self.vob)
+        elif subop == 0x14:
+            instr = self.produce_instr("loadFlObject", opc,
+                                       self.vob, self.vow)
+        elif subop == 0x22+1:
+            instr = self.produce_instr("resUnk1", opc,
+                                       self.vob, self.vob)
+        elif subop == 0x23+1:
+            instr = self.produce_instr("resUnk2", opc,
+                                       self.vob, self.vob, self.b)
+        elif subop == 0x24+1:
+            instr = self.produce_instr("resUnk3", opc,
+                                       self.vob, self.vob)
+        else:
+            raise UnknownSubOpError, \
+                "SCUMM345.do_resource: %d is not a known subop" % subop
+        return instr
+
+    def do_room_ops(self, _):
+        opc = self.get_byte()
+        opcm = opc & 0x1f
+        if opcm == 0x01:
+            instr = self.produce_instr("RoomScroll", opc,
+                                       self.vow, self.vow)
+        elif opcm == 0x02:
+            instr = Instr("RoomColor", [])
+        elif opcm == 0x03:
+            instr = self.produce_instr("SetScreen", opc,
+                                       self.vow, self.vow)
+        elif opcm == 0x04:
+            args = self.get_complex(opc, [self.vow, self.vow, self.vow])
+            instr = Instr("SetPalColor",
+                          args + self.get_complex(self.get_byte(), [self.vob]))
+        elif opcm == 0x05:
+            instr = Instr("ShakeOn", [])
+        elif opcm == 0x06:
+            instr = Instr("ShakeOff", [])
+        elif opcm == 0x07:
+            instr = Instr("Unused", [])
+        elif opcm == 0x08:

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list