Documentation

dumpopo

  1. Usage
  2. Overview
  3. Decode support
  4. Decompilation

Usage

Syntax: dumpopo.lua <filename> [options] [<procName> [<startAddr>]]

Prints information about the specified OPO (compiled OPL) file.

If just a filename is specified, prints information about the file and all the
procedures it contains. With --all or a <procName>, prints an assembly listing
of all procedures or the specified procedure, respectively. The <startAddr>
argument can be used to skip over some amount of the procedure code, which can
be useful when debugging code using obfuscation techniques.

Options:

    --all, -a
        Prints assembly listing of all procedures, if neither <procName> or
        --decompile is specified.

    --decompile, -d
        Convert the compiled code back to OPL source code and print to stdout.
        Decompiles all procedures unless <procName> is specified.

    --annotate, -t
        Adds some annotations to the output of --decompile, such as labels and
        GOTOs that normally wouldn't appear in the source.

    --name <proc>:<name>=<newname>
        Manually specify a name for a local in the given proc. Can be used
        multiple times for multiple variables. For example to rename local_00AC%
        to event% in the MAIN proc, specify --name MAIN:local_00AC=event. Has
        no effect unless --decompile is specified.

    --aif <path>, -i <path>
        Adds an APP...ENDA block to the decompile output based on the given AIF
        file.

Overview

Parses compiled-OPL programs, optionally decoding or decompiling the QCode.

For example, when run with no additional arguments, the structure of the file and the procedures it contains are listed. For example, when run on the very basic example program simple.opo:

$ ./bin/dumpopo.lua examples/Tests/simple.opo
UID2: 0x10000073
UID3: 0x10000168
translatorVersion: 0x200A minRunVersion: 0x200A
Source name: D:\Program
procTableIdx: 0x0000006B
1: TEST @ 0x0000001F code=0x00000036 size=0x00000018 line=0
    Subproc "WAT" offset=0x0012 nargs=0
    maxStack: 8
    iDataSize: 23 (0x00000017)
    iTotalTableSize: 5 (0x00000005)
2: WAT @ 0x0000004E code=0x00000060 size=0x0000000B line=6
    maxStack: 0
    iDataSize: 18 (0x00000012)
    iTotalTableSize: 0 (0x00000000)

Decode support

If a procedure name or --all is given, the procedure QCode is decoded:

$ ./bin/dumpopo.lua examples/Tests/simple.opo --all
UID2: 0x10000073
UID3: 0x10000168
translatorVersion: 0x200A minRunVersion: 0x200A
Source name: D:\Program
procTableIdx: 0x0000006B
1: TEST @ 0x0000001F code=0x00000036 size=0x00000018 line=0
    Subproc "WAT" offset=0x0012 nargs=0
    maxStack: 8
    iDataSize: 23 (0x00000017)
    iTotalTableSize: 5 (0x00000005)
00000036: 2B [ConstantString] "Hello world!"
00000044: 8B [PrintString]
00000045: 92 [PrintCarriageReturn]
00000046: 53 [RunProcedure] 0x0012 (name="WAT" nargs=0)
00000049: 82 [DropFloat]
0000004A: 57 [CallFunction] 0x0A (Get)
0000004C: 80 [DropInt]
0000004D: 76 [ZeroReturnFloat]
2: WAT @ 0x0000004E code=0x00000060 size=0x0000000B line=6
    maxStack: 0
    iDataSize: 18 (0x00000012)
    iTotalTableSize: 0 (0x00000000)
00000060: 2B [ConstantString] "Waaaat"
00000068: 8B [PrintString]
00000069: 92 [PrintCarriageReturn]
0000006A: 76 [ZeroReturnFloat]

Decompilation

If --decompile is given, an attempt is made to convert the QCode back to OPL source code. While the OPL compiler is not hugely complex, not all information is preserved so the source code is unlikely to be identical to the original - in particular, names of local variables are thrown away by the compiler so the decompiler will generate new names for them based on their location in the procedure. In the case of simple.opo which has no variables or complex flow control, the output is very close to the original:

$ ./bin/dumpopo.lua examples/Tests/simple.opo --decompile
PROC TEST:
    PRINT "Hello world!"
    WAT:
    GET
ENDP

PROC WAT:
    PRINT "Waaaat"
ENDP