[UTILITY] Lua 5.1 tools: compiler, decompiler, snippets & extendable lua.dll with SDK

Search This thread

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
Can you think of any reason why luadec (version 6 and now 7) with the -l option wouldn't output anything?

I tried it with and without the -l option. With the -l option just prints the following,
Code:
C:\Documents and Settings\user1\My Documents\My Software\Mobile Software\lua51_tf3d_beta_6>luadec -l ;;0,11,32;;0,17,38;;;;;;;5;;0,3,6,16,26;0,34;14,35;;;;;;;49,100,221;;0,0,223;;;;21,29;;;;;;;;;;;;;;;19;;0,0,5;8;;;;; .\27a13690_hd\27a13690_manila.luac
-- Decompiled using luadec 0.7 by sztupy (http://winmo.sztupy.hu)
-- Command line was: -l ;;0,11,32;;0,17,38;;;;;;;5;;0,3,6,16,26;0,34;14,35;;;;;;;49,100,221;;0,0,223;;;;21,29;;;;;;;;;;;;;;;19;;0,0,5;8;;;;; .\27a13690_hd\27a13690_manila.luac

without the -l it outputs the decompile fine, but not as helpful.

Also, I tried it with the version 5 and it works fine with the -l option. So I re-downloaded version 6 tried it again and installed the version 7 both with the same results when it comes to the -l option.

It looks like it crashed. Does it output anything with -d option set?
 

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
That's what a crash looks like? Yeah, about 15K lines of info (see attached).

Your LDS string is wrong somewhere. Unfortunatley when luadec crashes you can't use > to print its debug output to a file, because the last lines will be missing (which are the lines that have the information on where the problem might be), so can't find any useful information. Could you send me the luac file you're working on? I'll send you back the correct LDS
 

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
Your LDS string is wrong somewhere. Unfortunatley when luadec crashes you can't use > to print its debug output to a file, because the last lines will be missing (which are the lines that have the information on where the problem might be), so can't find any useful information. Could you send me the luac file you're working on? I'll send you back the correct LDS

Sure thing, there's 4 files,
27a13690_manila
27a13690_manila.luac
27a13690_manila.luac.dis
27a13690_manila.luac.guess​
does that mean a possible bug in the luadecguess or something else you think?
 

Attachments

  • 27a13690_manila.zip
    54 KB · Views: 3

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
Sure thing, there's 4 files,
27a13690_manila
27a13690_manila.luac
27a13690_manila.luac.dis
27a13690_manila.luac.guess​
does that mean a possible bug in the luadecguess or something else you think?

It's not a bug, luadecguess can't determine the correct place of the locals. If it guesses wrong then it might make luadec crash, that's a known problem, and there is no workaround (well, except for knowing exactly where locals are defined and released... but if we knew this then decompiling would be much-much easier) So to correct this one has to look at the debug output and correct the LDS. This is the "find a smaller number" thing I was talking about earlier.

I attached the beta version of luadec 1.0 (the upcoming version) with an (incorrectly) decompiled file that has to be corrected. It also includes the LDS2 string I used.
 

Attachments

  • 27a13690_manila.zip
    83.7 KB · Views: 5

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
Well, with your tutorial I now understand what I have to do to decompile the scripts, HUGE help. Still trying to piece together the issue with the LDS, but it'll come I'm sure, just have to play with it more. Now I just have to figure out how to fix the decompiled code.

If I'm understanding it right, you should beable to (to a certain extent) recreate the function(s) within a LUA file just by looking at the disassembled output and piecing it back together. Looking at the first file within the play.zip you posted, I can see what the disassembled output is saying, but when I try to recreate the code based on what it says, the compare says I'm completely wrong.

For instance, this is what I see within the disassembly output for function 1 (or function 0 as it shows in the output),
Code:
  1 [-]: GETGLOBAL R2 K0        ; R2 := _config_os
  2 [-]: EQ        0 R2 K1      ; if R2 != "windowsmobile" then PC := 12
  3 [-]: JMP       12
  4 [-]: GETTABLE  R2 R0 K2     ; R2 := R0["FilePath"]
  5 [-]: GETTABLE  R3 R1 K2     ; R3 := R1["FilePath"]
  6 [-]: EQ        1 R2 R3      ; if R2 == R3 then PC := 9
  7 [-]: JMP       9
  8 [-]: LOADBOOL  R2 0 1       ; R2 := false; PC := 10
  9 [-]: LOADBOOL  R2 1 0       ; R2 := true
 10 [-]: RETURN    R2 2         ; return R2
 11 [-]: JMP       17           ; PC := 17
 12 [-]: EQ        1 R0 R1      ; if R0 == R1 then PC := 15
 13 [-]: JMP       15
 14 [-]: LOADBOOL  R2 0 1       ; R2 := false; PC := 16
 15 [-]: LOADBOOL  R2 1 0       ; R2 := true
 16 [-]: RETURN    R2 2         ; return R2
 17 [-]: RETURN    R0 1         ; return

Now, if I was to try to recreate what this says, this is what I believe it should look like,

Code:
RadioList_TestEqual = function(l_1_0, l_1_1)
   local l_1_2 = _config_os
   if l_1_2 == "windowsmobile" then
      l_1_2 = l_1_0.FilePath
      l_1_3 = l_1_1.FilePath
      l_1_2 = l_1_2 == l_1_3
      return l_1_2
   elseif l_1_0 ~= l_1_1 then
      l_1_2 = l_1_0 ~= l_1_1
      return l_1_2
   end
end
Problem is, compare mentions nothing about a R3 (l_1_3), it also says my line count and opcode count are WAY off.
 
Last edited:

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
Well, with your tutorial I now understand what I have to do to decompile the scripts, HUGE help. Still trying to piece together the issue with the LDS, but it'll come I'm sure, just have to play with it more. Now I just have to figure out how to fix the decompiled code.

If I'm understanding it right, you should beable to (to a certain extent) recreate the function(s) within a LUA file just by looking at the disassembled output and piecing it back together. Looking at the first file within the play.zip you posted, I can see what the disassembled output is saying, but when I try to recreate the code based on what it says, the compare says I'm completely wrong.

For instance, this is what I see within the disassembly output for function 1 (or function 0 as it shows in the output),
Code:
  1 [-]: GETGLOBAL R2 K0        ; R2 := _config_os
  2 [-]: EQ        0 R2 K1      ; if R2 != "windowsmobile" then PC := 12
  3 [-]: JMP       12
  4 [-]: GETTABLE  R2 R0 K2     ; R2 := R0["FilePath"]
  5 [-]: GETTABLE  R3 R1 K2     ; R3 := R1["FilePath"]
  6 [-]: EQ        1 R2 R3      ; if R2 == R3 then PC := 9
  7 [-]: JMP       9
  8 [-]: LOADBOOL  R2 0 1       ; R2 := false; PC := 10
  9 [-]: LOADBOOL  R2 1 0       ; R2 := true
 10 [-]: RETURN    R2 2         ; return R2
 11 [-]: JMP       17           ; PC := 17
 12 [-]: EQ        1 R0 R1      ; if R0 == R1 then PC := 15
 13 [-]: JMP       15
 14 [-]: LOADBOOL  R2 0 1       ; R2 := false; PC := 16
 15 [-]: LOADBOOL  R2 1 0       ; R2 := true
 16 [-]: RETURN    R2 2         ; return R2
 17 [-]: RETURN    R0 1         ; return

Now, if I was to try to recreate what this says, this is what I believe it should look like,

Code:
RadioList_TestEqual = function(l_1_0, l_1_1)
   local l_1_2 = _config_os
   if l_1_2 == "windowsmobile" then
      l_1_2 = l_1_0.FilePath
      l_1_3 = l_1_1.FilePath
      l_1_2 = l_1_2 == l_1_3
      return l_1_2
   elseif l_1_0 ~= l_1_1 then
      l_1_2 = l_1_0 ~= l_1_1
      return l_1_2
   end
end
Problem is, compare mentions nothing about a R3 (l_1_3), it also says my line count and opcode count are WAY off.

you can recreate a function but that's hard, and you should only resort to this when there is no other way :)

Your decompileation looks fine btw, but there are too much locals. R2 is not a local in this example (well, this example you posted me is not a straightforward one), correctly this should read:

Code:
RadioList_TestEqual = function(l_1_0, l_1_1)
   if _config_os == "windowsmobile" then
      return l_1_0.FilePath == l_1_1.FilePath
   else
      return l_1_0 == l_1_1
   end
end

Lines like this:
Code:
  8 [-]: LOADBOOL  R2 0 1       ; R2 := false; PC := 10
  9 [-]: LOADBOOL  R2 1 0       ; R2 := true

always mean that conditional statements are assigned to a register, in this case R2
 

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
you can recreate a function but that's hard, and you should only resort to this when there is no other way :)

Your decompileation looks fine btw, but there are too much locals. R2 is not a local in this example (well, this example you posted me is not a straightforward one), correctly this should read:

Code:
RadioList_TestEqual = function(l_1_0, l_1_1)
   if _config_os == "windowsmobile" then
      return l_1_0.FilePath == l_1_1.FilePath
   else
      return l_1_0 == l_1_1
   end
end

Lines like this:
Code:
  8 [-]: LOADBOOL  R2 0 1       ; R2 := false; PC := 10
  9 [-]: LOADBOOL  R2 1 0       ; R2 := true

always mean that conditional statements are assigned to a register, in this case R2

Right, a LOADBOOL (boolean logic) returns a TRUE or FALSE, 1 or 0 type result. :)

That's how I would have created it if I was writing it from scratch, but the disassembly showed multiple locals. The first being the R2 and the second being the R3 that seemed to get created without a local call. I was thinking the idea was to try to match what the disassembly showed. The compare wasn't too bad, other then a few jmp differences. Which is why I tried to at least match the disassembly to show you what I mean.

BTW, this is what was created by luadec which is why I thought the locals were required, even if I wouldn't have normally used them. :D

Code:
RadioList_TestEqual = function(l_1_0, l_1_1)
   local l_1_2 = _config_os
   if l_1_2 == "windowsmobile" then
      l_1_2 = l_1_0.FilePath
      l_1_2 = l_1_2 == l_1_1.FilePath
      return l_1_2
   elseif l_1_0 ~= l_1_1 then
       -- DECOMPILER ERROR: Attempted to build a boolean expression without a pending context

      l_1_2 = error_maybe_false
      return l_1_2
   end
end

So what I'm gathering is, use the disassembly as a guide to recreating the code but don't use it verbatim as it results in badly written code (at least in my opinion).

BTW, that was the easier function, function 3 is harder and has even more compare differences. :rolleyes:
 

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
Right, a LOADBOOL (boolean logic) returns a TRUE or FALSE, 1 or 0 type result. :)

That's how I would have created it if I was writing it from scratch, but the disassembly showed multiple locals. The first being the R2 and the second being the R3 that seemed to get created without a local call. I was thinking the idea was to try to match what the disassembly showed. The compare wasn't too bad, other then a few jmp differences. Which is why I tried to at least match the disassembly to show you what I mean.

BTW, this is what was created by luadec which is why I thought the locals were required, even if I wouldn't have normally used them. :D

Code:
RadioList_TestEqual = function(l_1_0, l_1_1)
   local l_1_2 = _config_os
   if l_1_2 == "windowsmobile" then
      l_1_2 = l_1_0.FilePath
      l_1_2 = l_1_2 == l_1_1.FilePath
      return l_1_2
   elseif l_1_0 ~= l_1_1 then
       -- DECOMPILER ERROR: Attempted to build a boolean expression without a pending context

      l_1_2 = error_maybe_false
      return l_1_2
   end
end

So what I'm gathering is, use the disassembly as a guide to recreating the code but don't use it verbatim as it results in badly written code (at least in my opinion).

BTW, that was the easier function, function 3 is harder and has even more compare differences. :rolleyes:

sometimes you don't have to believe luadec / luadecguess :) You can always believe luadisasm! The fact that it says R2 and R3 is that the VM uses the 2nd and third register to store data, because it needs to use them to store data. This doesn't mean R2 or R3 are locals. But if at some point R2 is declared as local in the script you'll see, that only R3,R4, etc. are used mainly in the disassembly and R2 is usually left alone.
 

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
Another question regarding compare this time. When you run compare and you see results like the following, what do they mean?

Code:
Function 3:
  1>  1 [-]: GETTABLE  R2 R0 K0     ; R2 := R0["Namespace"]
  2>  1 [-]: GETTABLE  R2 R0 K1     ; R2 := R0["Namespace"]
  1>  2 [-]: SELF      R2 R2 K1     ; R3 := R2; R2 := R2["FindName"]
  2>  2 [-]: SELF      R2 R2 K2     ; R3 := R2; R2 := R2["FindName"]
  1>  3 [-]: LOADK     R4 K2        ; R4 := "Text"
  2>  3 [-]: LOADK     R4 K3        ; R4 := "Text"

Other then the K0, K1, K2 and K3, they are the same, but obviously not the same. So what am I missing or not seeing?

Its a LOCAL, isn't it?
 
Last edited:

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
Another question regarding compare this time. When you run compare and you see results like the following, what do they mean?

Code:
Function 3:
  1>  1 [-]: GETTABLE  R2 R0 K0     ; R2 := R0["Namespace"]
  2>  1 [-]: GETTABLE  R2 R0 K1     ; R2 := R0["Namespace"]
  1>  2 [-]: SELF      R2 R2 K1     ; R3 := R2; R2 := R2["FindName"]
  2>  2 [-]: SELF      R2 R2 K2     ; R3 := R2; R2 := R2["FindName"]
  1>  3 [-]: LOADK     R4 K2        ; R4 := "Text"
  2>  3 [-]: LOADK     R4 K3        ; R4 := "Text"

Other then the K0, K1, K2 and K3, they are the same, but obviously not the same. So what am I missing or not seeing?

Its a LOCAL, isn't it?

No, it's a constant. Everything is a constant that is not a local :) For example in a line like Namespace.Findname("Text") Namespace, Findname and Text are all three constants. The number after the K represents which constant that char is. Constants are added by the lua compiler as they are encountered, so if you have K1 while the original has K0 that means that you have added something before the K1 in this example.

Usually this means missing locals as usual :) so if you have a line like

A=b.c

then refactor to

local x = b.c
A=x

this way "b" will be K0 and not "A"
 

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
No, it's a constant. Everything is a constant that is not a local :) For example in a line like Namespace.Findname("Text") Namespace, Findname and Text are all three constants. The number after the K represents which constant that char is. Constants are added by the lua compiler as they are encountered, so if you have K1 while the original has K0 that means that you have added something before the K1 in this example.

Usually this means missing locals as usual :) so if you have a line like

A=b.c

then refactor to

local x = b.c
A=x

this way "b" will be K0 and not "A"

Constants huh?

When I originally ran the compare and got the results I pasted I had written the line like this,
Code:
l_4_2 = l_4_0.Namespace.Findname("Text")
I ended up fixing it by changing it to this,
Code:
local l_4_2 = l_4_0.Namespace.Findname("Text")
but didn't understand it, that's why I thought it was locals. :)

I think it makes sense now with your explanation.
 
Last edited:

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
I'm so close on that last function in the 1f3be060_manila_1583A file from your play.zip other then a couple jump differences, everything matches except for a variable difference that I'm trying to resolve.

For instance,
Code:
  1> 53 [-]: GETGLOBAL R3 K22       ; R3 := RadioButton_Initialize
  2> 53 [-]: GETGLOBAL R4 K22       ; R4 := RadioButton_Initialize
  1> 54 [-]: MOVE      R4 R0        ; R4 := R0
  2> 54 [-]: MOVE      R5 R0        ; R5 := R0
  1> 55 [-]: LOADBOOL  R5 1 0       ; R5 := true
  2> 55 [-]: LOADBOOL  R6 1 0       ; R6 := true
  1> 56 [-]: CALL      R3 3 1       ; R3(R4,R5)
  2> 56 [-]: CALL      R4 3 1       ; R4(R5,R6)

Definitely not as quick as you, as I've been working on this function for about 2.5 hours, but I'm coming along I think. :)
 

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
I'm so close on that last function in the 1f3be060_manila_1583A file from your play.zip other then a couple jump differences, everything matches except for a variable difference that I'm trying to resolve.

For instance,
Code:
  1> 53 [-]: GETGLOBAL R3 K22       ; R3 := RadioButton_Initialize
  2> 53 [-]: GETGLOBAL R4 K22       ; R4 := RadioButton_Initialize
  1> 54 [-]: MOVE      R4 R0        ; R4 := R0
  2> 54 [-]: MOVE      R5 R0        ; R5 := R0
  1> 55 [-]: LOADBOOL  R5 1 0       ; R5 := true
  2> 55 [-]: LOADBOOL  R6 1 0       ; R6 := true
  1> 56 [-]: CALL      R3 3 1       ; R3(R4,R5)
  2> 56 [-]: CALL      R4 3 1       ; R4(R5,R6)

Definitely not as quick as you, as I've been working on this function for about 2.5 hours, but I'm coming along I think. :)

I think what I will say will freak you out: you have TOO MUCH locals declared :)
 

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
Son of a ....

Well. I probably wouldn't have thought of that, so it's a good thing you mentioned it. Is it the fact that my version shows 1 more then the original version? Is that what the clue?
 

smotrs

Senior Member
Nov 16, 2008
632
0
So. Calif.
Ok, I finished the 1f3be060_manila but have a question before I post it. One of the lines in the disassembly shows this,
Code:
 19 [-]: EQ        0 R3 K10     ; if R3 != 3.23791e-319 then PC := 41

should the code be written as
Code:
        if bFromContactCard == 3.23791e-319 then

I don't think that's right though. What luadec tried to create and looks more logical was this,
Code:
        if bFromContactCard == 1 then

Now if I compile my code with the 3.23791e-319 number and then disassemble it, the output looks like this,

Code:
 19 [-]: EQ        0 R3 K10     ; if R3 != 0 then PC := 41

which leads me to think that maybe the number wasn't converted correctly or interpreted correctly by the disassembler.

I just can't imagine the 3.23... being correct though. The reason I bring this up is that there are a BUNCH of these in the 3e5b35f2_manila disassembly output.
 
Last edited:

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
Ok, I finished the 1f3be060_manila but have a question before I post it. One of the lines in the disassembly shows this,
Code:
 19 [-]: EQ        0 R3 K10     ; if R3 != 3.23791e-319 then PC := 41

should the code be written as
Code:
        if bFromContactCard == 3.23791e-319 then

I don't think that's right though. What luadec tried to create and looks more logical was this,
Code:
        if bFromContactCard == 1 then

Now if I compile my code with the 3.23791e-319 number and then disassemble it, the output looks like this,

Code:
 19 [-]: EQ        0 R3 K10     ; if R3 != 0 then PC := 41

which leads me to think that maybe the number wasn't converted correctly or interpreted correctly by the disassembler.

I just can't imagine the 3.23... being correct though. The reason I bring this up is that there are a BUNCH of these in the 3e5b35f2_manila disassembly output.

the disassembler was written for generic lua 5.1 scripts, but HTC uses the Q16.16 numeric format. The disassembler thinks it's a standard double and interprets it as is, this is why you'll see that 1 is actually 3.23791e-319 in the disassembly.
 

6Fg8

Retired Senior Moderator
Apr 13, 2008
1,150
7
Vienna
the disassembler was written for generic lua 5.1 scripts, but HTC uses the Q16.16 numeric format. The disassembler thinks it's a standard double and interprets it as is, this is why you'll see that 1 is actually 3.23791e-319 in the disassembly.
I could change that in the conversion routines so that Q16.16 values are written as doubles in the ANSI converted output. Would be a more clean approach, but you would have to change the decompiler. What do you think?
 

sztupy

Inactive Recognized Developer
Dec 21, 2008
1,061
877
Edinburgh
sztupy.hu
I could change that in the conversion routines so that Q16.16 values are written as doubles in the ANSI converted output. Would be a more clean approach, but you would have to change the decompiler. What do you think?

I don't think it's worth the effort. I already built the tools for Q16.16 (luac, lua and luadec), so if someone wants a disassembly he can use luac -l instead of luadisasm to get the values of the numeric constants
 

Top Liked Posts

  • There are no posts matching your filters.
  • 1
    I still haven't been able to figure out where this is actually referring too. I see similar situation in other lua files. But in each case, I've been unable to locate where or what it's actually trying to do. :confused:

    They are dialogs (as their name suggests). They are defined in manila.xml (26948339_manila). They seem to be like some kind of "embedded mode9" files

    Example:
    Code:
    <PageGroup Name="settings">
    (...)
      <PageGroup Name="updatesanddata">
        <Page Order="0" Name="updatesanddata.page" PackageName="HTC" Title="[[IDS_UPDATESANDDATA]]" Default="true" >
          <ComponentReference Name="page"  Mode9Path="HTC\settings.mode9" Component="UpdatesAndDataPageComponent" SmartComponent="true"  />
        </Page>
      </PageGroup>
    (...)
    </PageGroup>