Thursday, March 20, 2014

Working on Understanding the Function from the Other Side

Continued from the previous entry

After our work from the previous post, we have a skeleton of the functionality provided by the Lua command we're working on. However, working from assembly isn't always the best approach. For EMI, we already have a whole lot of help from the excellent work done by the developers who previously worked on Grim Fandango, EMI and Myst3 support in ResidualVM! In this project, they have provided us with code and tools to inspect the scripts that are being run in the game. Let's inspect a script that called the function stub we're working on.

First, let's take a look at the game scripts. In EMI, the game scripts can be found in the file local.m4b. This file is actually a bundle of files, which can be extracted using the tool unlab, found in the residualvm-utils repository. Once you've built this utility, let's unpack it so we can get at the Lua scripts that make up the game. In the directory with the EMI data files:
  • mkdir local
  • cd local
  • unlab ../local.m4b
After running this command, inside the local directory there will be a large number of files, the most important for us now are the files that end in .lua. If you inspect these files, you'll see that they're not text, but a binary format. To make the scripts readable, we'll use the tool delua, also found in the residualvm-utils repository. To make this easier, we'll just decode all of the scripts in the directory at once so we can easily search through them:
  • mkdir scripts
  • for i in *.lua; do delua $i > scripts/$i; done
  • cd scripts
 With the scripts converted into a readable format, we can now search through them for instances where our function of interest is used:
  •  grep SetActorLocalAlpha *.lua
From this, we can see that when SetActorLocalAlpha is called, it's called with 4 arguments. These correspond with the 4 calls to lua_lua2C at the beginning of the disassembled function from the previous entry. Importantly, we also see that the first variable passed is arg1.hActor. This is useful information because it gives us context for the type of the variable and hints as to how its used in the code. We can also look at other Lua functions that  are called from SetActorLocalAlpha to find the types of the variables used.

Before we go back to SetActorLocalAlpha, let's examine the set_vertex_alpha_mode Lua function more closely. As you can see in the code listing above, there are a bunch of unnamed variables. Let's figure out what they mean so that we can better identify the arguments to SetActorLocalAlpha. Let's start with the function arguments.

In Lua, a method function can be called in two different ways, with a period between the class and the method or a colon. These methods differ in that the second transparently passes a reference to the object as the first argument. In most applications, we name this argument "self". In wed.lua, we see that the set_vertex_alpha_mode method is called using the colon operator. Because of this, we know that the first argument is really the "self" variable. Once we have identified a variable like this, we'll update the rest of the function to reflect this new knowledge. We'll continue this process, using cues from the calling function and the contents of the function to name the rest of the arguments and the local variables

With all of this additional information, we can now continue filling in the details for the SetActorLocalAlpha function.

No comments:

Post a Comment