FORUMS
Remove All Ads from XDA

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

1,061 posts
Thanks Meter: 877
 
Post Reply Email Thread
3rd March 2009, 05:33 PM |#181  
sztupy's Avatar
OP Inactive Recognized Developer
Flag London
Thanks Meter: 877
 
Donate to Me
More
Quote:
Originally Posted by 12aon

In my case I should change the l_0_0 and l_1_0 etc right? You added an entire landscape function set that the original didn't have, that's because it's an example or is this the actual code I should use?

No, I only fixed the decompilation of the main body (removed the l_0_0 lines because they don't have to be there) and put the first 8 lines of the function to both to the landscpae and the portrait part of the conditional statement. If you look closer the function body you'll see it's the same except for these 8 lines
 
 
3rd March 2009, 06:19 PM |#182  
smotrs's Avatar
Senior Member
Flag So. Calif.
Thanks Meter: 0
 
More
Quote:
Originally Posted by sztupy

you have to disassemble it using luadisasm

Hmm, must have missed that part somewhere. I thought the luadisasm program was run by the luadecguess program?

So which file do you run against the luadisasm program? And is this where you would see a line similar to the 121 closure?
3rd March 2009, 08:59 PM |#183  
sztupy's Avatar
OP Inactive Recognized Developer
Flag London
Thanks Meter: 877
 
Donate to Me
More
Quote:
Originally Posted by smotrs

Hmm, must have missed that part somewhere. I thought the luadisasm program was run by the luadecguess program?

So which file do you run against the luadisasm program? And is this where you would see a line similar to the 121 closure?

all of my tool (except luadec) uses the disassembled output of luadisasm to analyze the file (imho it's a great tool, better than chunkspy to help analyze files). For complex scripts where the decompiler failed (usually complex conditional statements) I use it's output to help me correct the file.

Of course you have to run luadisasm on the original (ascii) compiled lua file and analyze that yourselves. You'll find the appropriate line in the beginning (around line 121+10 more exactly)
4th March 2009, 05:10 AM |#184  
mun_rus's Avatar
Senior Member
Thanks Meter: 0
 
More
Just want to say thanx for your work
Its making manila development easier)
Btw, I reversed by myself several scripts long time ago and know wht's a boring operations (especialy where many IF and ELSE operations present)

Just for information:
Your tool shows this after decompiling homebackground.luac
Code:
BackgroundImageLoaded = function(loc_0, loc_1)
   if loc_1 == 1 then
      HomeBackground.TextureCoords.width = loc_0.TextureCoords.width
      HomeBackground.TextureCoords.height = loc_0.TextureCoords.height
       -- DECOMPILER ERROR: Confused about usage of registers, missing locals? Creating them

      local loc_3 = loc_0.TextureCoords.height * loc_0.Image.Height
       -- DECOMPILER ERROR: Confused about usage of registers, missing locals? Creating them

      local loc_2 = loc_0.TextureCoords.width * loc_0.Image.Width
      if loc_0.TextureCoords.width * loc_0.Image.Width / BackgroundWidth < loc_0.TextureCoords.height * loc_0.Image.Height / BackgroundHeight then
         HomeBackground.Size.height = loc_3 / (loc_2) * BackgroundWidth
         HomeBackground.Size.width = BackgroundWidth
      else
         HomeBackground.Size.width = loc_2 / loc_3 * BackgroundHeight
         HomeBackground.Size.height = BackgroundHeight
      end
      HomeBackground.Position.x = (BackgroundWidth - HomeBackground.Size.width) / 2
      HomeBackground.Position.y = -(BackgroundHeight - HomeBackground.Size.height) / 2
      HomeBackground:SetTexture(loc_0.Image)
      InterpolateOpacity(100, HomeBackground)
      if HomeTitleBar ~= nil and _application.Store:GetIntValue(Lifetime_Application, "ShowCacheHomePage") == 1 then
         HomeTitleBar.Opacity.value = 60
         _application.Navigation.TabTrayOpacity = 60
      else
         loc_2 = LoadDefaultBackground
         loc_2()
      end
      loc_2 = collectgarbage
      loc_3 = "collect"
      loc_2(loc_3)
      loc_2 = nil
      BackgroundAsyncImageLoader = loc_2
       -- Warning: missing end command somewhere! Added here
   end
end
When I manually reversed same script before (in manila 1) I got
Code:
function BackgroundImageLoaded(param0,param1)
	if(param1==1) then
		HomeBackground.TextureCoords.width = param0.TextureCoords.width;
		HomeBackground.TextureCoords.height = param0.TextureCoords.height;
		local loc2 = param0.TextureCoords.width * param0.Image.Width;
		local loc3 = param0.TextureCoords.height * param0.Image.Height;
		local loc4 = loc2/BackgroundWidth;
		local loc5 = loc3/BackgroundHeight;
		if (loc4<loc5) then
			HomeBackground.Size.height = loc3/loc2*BackgroundWidth;
			HomeBackground.Size.width = BackgroundWidth;
		else
			HomeBackground.Size.width = loc2/loc3*BackgroundHeight;
			HomeBackground.Size.height = BackgroundHeight;
		end
		HomeBackground.Position.x = (BackgroundWidth - HomeBackground.Size.width)/2;
		HomeBackground.Position.y = -(BackgroundHeight - HomeBackground.Size.height)/2;
		HomeBackground:SetTexture(param0.Image);
		InterpolateOpacity(100,HomeBackground);
		if (HomeTitleBar~=nil and _application.Store:GetIntValue(Lifetime_Application, "ShowCacheHomePage") ) then
			HomeTitleBar.Opacity.value = 60;
			_application.Navigation.TabTrayOpacity = 60;
		end
	else
	LoadDefaultBackground();
end
BackgroundAsyncImageLoader = nil;
collectgarbage("collect");
And this is an absolutly right code for this function. May be this info can help you somehow
4th March 2009, 04:30 PM |#185  
sztupy's Avatar
OP Inactive Recognized Developer
Flag London
Thanks Meter: 877
 
Donate to Me
More
damn... this is getting easier... I miss the 50+ function scripts

273 scripts ready. This new package includes
  • two embedded scripts from somewhere
  • ringtone
  • stock
  • stock_rearrange
  • transitiondelay
  • weathercitypicker
  • email/email_letterlist
  • internetportal/google_search
  • people/peoplecategoryglobal

I've found another undecompilable "error" (the last one was a rounding error introduced by using Q16.16->double->Q16.16 conversions). In one of the scripts (stock.lua) I've found a part where it reads "R3 < K25". But no matter what I tried I could only compile to "K25 > R3" Gave up after 15 minutes trying to solve this, so this one minor error is kept (I think the compiler was a bit changed in lua 5.1.4, HTC used lua 5.1.2). R3 < K25 is equal to K25 > R3 anyway...

Oh, and I forgot to mention the ususal disclaimer: If you use these scripts then blahblahblah
Attached Files
File Type: zip touchpro2_manila3d_declua.zip - [Click for QR Code] (657.8 KB, 101 views)
5th March 2009, 12:12 AM |#186  
smotrs's Avatar
Senior Member
Flag So. Calif.
Thanks Meter: 0
 
More
Quote:
Originally Posted by sztupy

damn... this is getting easier... I miss the 50+ function scripts

You suck, I haven't even been able to decompile the one file I've been working on the last couple weeks.

Wanna help me out since your flying through the ones your working on?
5th March 2009, 05:08 PM |#187  
sztupy's Avatar
OP Inactive Recognized Developer
Flag London
Thanks Meter: 877
 
Donate to Me
More
Quote:
Originally Posted by smotrs

You suck, I haven't even been able to decompile the one file I've been working on the last couple weeks.

Wanna help me out since your flying through the ones your working on?

First I want to finish this TP2 project

Here are today's additions:
  • WorldClock/TimeUI
  • digitalclock
  • inforstocklistview
  • simpledialogscript
  • album/albumlistview
  • calendar/calendardayviewscript
  • people/peoplecalllog
  • people/peopleemail
  • people/peoplemessageselector
  • people/peopleselectaccountpage
  • worldclock/alarmedit
  • 4 embedded scripts from somewhere

Total body count: 288
Only 68 left. Enjoy.
Attached Files
File Type: zip touchpro2_manila3d_declua.zip - [Click for QR Code] (770.2 KB, 45 views)
5th March 2009, 05:37 PM |#188  
smotrs's Avatar
Senior Member
Flag So. Calif.
Thanks Meter: 0
 
More
Quote:
Originally Posted by sztupy

First I want to finish this TP2 project

Hey, I'll take whatever help you can give. In the meantime, I'll continue trying to figure it out mainly because I want to learn it and be able to do it whenever I need to as well.

Hey, I was also thinking, what if you updated your earlier tutorial and showed a step by step (with your current tools) on one of the files your currently working on? That would be a great help as well. But I don't want to take you away from pumping out the ones you are.
5th March 2009, 07:29 PM |#189  
sztupy's Avatar
OP Inactive Recognized Developer
Flag London
Thanks Meter: 877
 
Donate to Me
More
Decompiling tutorial part 1

First you have to get acquainted to the disassembly output of a script. There are two tools that will disassemble lua scripts: luadisasm and chunkspy. I usually prefer the first, because it's output is easier to read, but it doesn't output numbers in Q16.16 format. For chunkspy D-MAN made a Q16.16 version, but I don't really like chunkspy's output.

EDIT: luadec 1.9 and 2.0 can now diassembly scripts, so luadisasm is not needed anymore. Use luadec -dis filename to get a disassembly view of the lua files. Also luaconv is no more needed, if I refer to luaconv/luadisasm in this tutorial then don't care about them. Compare and luadecguess still works, but luadecguess is usually not needed anymore, because luadec 2.0 has built-in guessing capabilities (but they might break, so feel free to read theese sections too)

For scripts larger than 10kb, or for scripts where there are too many differences according to compare's output you simply can't live without the disassembled output

So first do this:

Code:
luadisasm.exe 1a335681_manila.luac > dis
If I'm disassembling at job where I have two monitors I usually put the disassembly on the secondary monitor, so I can always look at it.

Let's look at it's output. It is separated into functions, beginning with the main block. For each function (including the main block) it outputs the disassembly of the opcodes it encounters. Lets look at an opcode line:

Code:
 50 [-]: LOADNIL   R0 R0        ; R0 := nil
Each line of the disassembled output consits of the opcode number (50), the opcode (LOADNIL), the parameters of the operator (R0 K0) and a readable output after the semicolon (R0 := nil). I usually only read the part after the semicolon, because it usually tells you everything you have to know. As you have already lua uses registers to store information while running, and these registers are called R0, R1, R2, etc. Local variable declarations are also stored in registers, so if you declare a local in the file, lua will reserve the next free register to this new local variable. This is important, because it will show us where locals have been defined.

Let's look at another output we will analyze:

Code:
; Function #5:
;
; Name:            
; Defined at line: 170
; #Upvalues:       0
; #Parameters:     2 (R0, R1)
; Is_vararg:       0
; Max Stack Size:  16
;
; No locals information
; No upvalues

  1 [-]: GETTABLE  R2 R1 K0     ; R2 := R1["Namespace"]
  2 [-]: SELF      R2 R2 K1     ; R3 := R2; R2 := R2["FindName"]
  3 [-]: LOADK     R4 K2        ; R4 := "PhotoFrame"
  4 [-]: CALL      R2 3 2       ; R2 := R2(R3,R4)
  5 [-]: GETTABLE  R3 R1 K0     ; R3 := R1["Namespace"]
  6 [-]: SELF      R3 R3 K1     ; R4 := R3; R3 := R3["FindName"]
  7 [-]: LOADK     R5 K3        ; R5 := "Icon"
  8 [-]: CALL      R3 3 2       ; R3 := R3(R4,R5)
  9 [-]: GETTABLE  R4 R1 K0     ; R4 := R1["Namespace"]
 10 [-]: SELF      R4 R4 K1     ; R5 := R4; R4 := R4["FindName"]
 11 [-]: LOADK     R6 K4        ; R6 := "Title"
 12 [-]: CALL      R4 3 2       ; R4 := R4(R5,R6)
 13 [-]: GETTABLE  R5 R1 K0     ; R5 := R1["Namespace"]
 14 [-]: SELF      R5 R5 K1     ; R6 := R5; R5 := R5["FindName"]
 15 [-]: LOADK     R7 K5        ; R7 := "Select"
 16 [-]: CALL      R5 3 2       ; R5 := R5(R6,R7)
 ...
This is function number 5 (0 based, so this is function 5+1=6 in the decompiled output, with paramters like l_6_0, l_6_1, etc.), which has two parameters (R0, R1). Parameters, just like locals, take avay the free register slots. As you can see the first operator will operate on register R2, because R0 and R1 are taken.

Lua will always use the first free register to store it's data. If you have something like:

Code:
l_6_1.Namespace:FindName("PhotoFrame")
1st opcode: It will first load the "Namespace" component of R1 (l_6_1) into register 2.
2nd opcode: Then it will copy R2 to register R3, then replace R2 with "Namespace:Findname" (it will discard the old value of R2 (Namespace) because it's not needed anymore)
3rd opcode: It will load a string "PhotoFrame" into the next free register, which is R4, because both R2 and R3 are needed for the next opcode:
4th opcode: This will call the FindName function (stored in R2). This function takes two parameters: self (stored in R3) and "PhotoFrame" (stored in R4). After the call it will put it's result BACK into R2.

Why is the last sentence so important? Let's look at the 5th opcode. It will load l_6_1.Namespace into register R3. But why register R3? Because R2 is taken! And why is it taken? Because it seems we have declared a local at opcode 4!

This way the LDS for the first 5 opcode of this function would look like: ;;;;;;0,0,4 (declare R2 as local in the 6th function at opcode number 4. there are two zeros, which mean R0 and R1 are unneded, because they are parameters)

For knowing where to declare locals it's usually enough to look at the output and see which the first free register is. If, for a while you can only see things like R2 := xxx, or R2[xxx] := xxx, or R2(xxx,xxx,xxx) then R2 is usually not a local. But after a while you stop getting R2's and start gettin R3's then you can be sure that the last line you encountered an assignment to R2 (Something like R2 := xxx), then there is R2 defined as a local.
5th March 2009, 07:30 PM |#190  
sztupy's Avatar
OP Inactive Recognized Developer
Flag London
Thanks Meter: 877
 
Donate to Me
More
Decompiling tutorial part 2

After you have guessed where locals are, have run luadec with the LDS, and after it had output something (and did not crash), and it's output looks nice (there aren't too many "DECOMPILER ERROR"s in the output), then it's time to start fixing the output. Fixing is usually done by running the compare script:

Code:
compare.exe 1a335681_manila.luac 1a335681_manila.luac.lua
This will compile the second parameter, and compare it's disassembly output to the disassembly of the first parameter (original). If there are compile errors you have to correct them. If you can't correct them, it's usually easier to simply comment out the block where the errors are. USually the problems are with missing, or too much "end" commands, or with too much "else", etc. The other usual bug with the decompiled output is when the decompiler declares too much local (yes, it's a problem too ) This is very easy to spot. Let's look at a usual bug:

Code:
l_3_0 = trace
l_3_1 = "CheckValidItem IsRmovePage"
l_3_0(l_3_1)
l_3_0 = OnRemoveItemPress
l_3_0()
Here. the decompiler thought both R0 and R1 are locals, but they are not. Fixing this is easy, but gets boring after a while:

Code:
trace("CheckValidItem IsRmovePage")
OnRemoveItemPress()
This bug gets very ugly, if it involves class function calls:

Code:
l_3_0 = _application
l_3_0(l_3_0, Softkey(Locale:GetString(""), Emptyfunction))
l_3_0 = l_3_0:SetRightSoftkey
This is fixed as below:

Code:
_application:SetRightSoftkey(Softkey(Locale:GetString(""), Emptyfunction))
As you can see I had to get the original object from line 1, the function from line 3, and the parameters from line 2. I also had to clear the first parameter, because this is a class function call, where the first parameter is always the caller (self)

If there are around 200 lines of code like this my eyeballs usually pop out but before I start compiling and comparing I have to do this tedious job of cleaning the output...
5th March 2009, 07:31 PM |#191  
sztupy's Avatar
OP Inactive Recognized Developer
Flag London
Thanks Meter: 877
 
Donate to Me
More
Decompiling tutorial part 3

So, we have cleaned the output, and running compare will not output a compilation error, but a comparison of the two scripts. Let's continue from here.

What you love:

Code:
Main block:
Same
What you hate:

Code:
Function 3:
  1> 11 [-]: GETGLOBAL R1 K0        ; R1 := PeopleListView
  ...
And if you only get outputs from the first type, then you are very very happy

Now, let's start fixing the output.
I always look at the first bug:

Code:
Function 3:
  1> 11 [-]: GETGLOBAL R1 K0        ; R1 := PeopleListView
  2> 11 [-]: GETGLOBAL R0 K0        ; R0 := PeopleListView
Compare will always print out the differences in the two files. odd lines will be from the original, even lines will be from the decompiled script. Let's look at the usual bugs.

In the previous code output you can clearly see, that in the original PeopleListView is assigned to R1, but in out script it's assigned to R0. What does this mean? LOCALS! Yep, you have to declare something as a local in function #3 (which is the fourth(!) function, never forget!) And it's around opcode number 11, which is around the beginning of the file. To fix it you can either search for the string "PeopleListView" around the beginning of function 4, and declare something BEFORE that as a local. If you don't know what to declare as local, then look at the opcode line 10 (or 9, or something), and declare that as local.

For example in our example the original line was:

Code:
   if PeopleListView:GetLayout() == nil then
      return 
   end
   if PeopleListView:GetGenerator() == nil then
      return 
   end
I added some comments:

Code:
   -- this is opcode number 7. Here the disassembly output is:
   -- 7 [-]: CALL      R0 2 2       ; R0 := R0(R1)
   -- this is where PeopleListView:GetLayout() was declared as a local
   if PeopleListView:GetLayout() == nil then
      return 
   end
   -- this is opcode number 11. Here is the PeopleListView that is shown in the
   -- disassembly output 
   if PeopleListView:GetGenerator() == nil then
      return 
   end
The fixed output is:
Code:
   local l_4_0 = PeopleListView:GetLayout()
   if l_4_0 == nil then
      return 
   end
   if PeopleListView:GetGenerator() == nil then
      return 
   end
Post Reply Subscribe to Thread

Tags
lua, manila, mod, tf3d, touchflo

Guest Quick Reply (no urls or BBcode)
Message:
Previous Thread Next Thread
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes