sfall decompiler(int2ssl Author Program Anchorite)

sfall compiler(modder_pack from sfall site) for compiling,and int2ssl for decompiling,standard watcom(or other precompiler) is needed

btw i decompiled all the vanilla scripts with int2ssl,all of them decompiled,3 of them would not then(without editing) re-compile,the rest compiled just fine

evidentaly Jordan fixed the
Code:
lvar0 := 0;
lvar1 := 0;
lvar2 := 0;
lvar3 := 0;
 return 0;

bug
:)

Nirran
 
Alchemist said:
Nirran said:
In this case I don't really understand why you rely on Noid's syntax/opcodes. Int2ssl provides native Interplay's syntax of SSL language. And speaking about errors with original opcodes check following thread in TeamX's forums. Automatic translations is not always adequate but mostly satisfactory. Jordan've been made same thing for an older version of Sfall. It is outdated indeed but some fixes related to the original opcodes would be helpful. Links to source code samples are given in that thread.
And one more thing, pretty please, do not reproduce Jordan's mistake when there where two binaries with the same version stamp but different functionality. If you plan to make and release your very own and tweaked build of the utility, either fork it completely from the original project or make a well visible notice to be displayed on a program start. So people could clearly see that it's special Sfall/Noid edition of the utility. Thanks in advance.

i probably confused the purpous of that by posting it in this thread,it is actualy a completely seperate thing(was sleepy when i answered before) one is the int2ssl with all current sfall opcodes,the other is ruby compile/decompile files with all sfall opcodes

in both of them i fixed some errors in the vanilla fo2 opcodes(did not mess with fo1 in ruby),sorry for the confusion

and to clarify the 3 scripts that failed to re-compile with int2ssl and sfall compiler,it was actualy bugs that i think were present in the vanilla compiler the dev's used

dccraps.int and zccrpdel.int(both have similar code)
this one is coded
Code:
if (local_var(x  bwand y) then
and should be
Code:
 if ((local_var(x bawnd y) == 1) then
int2ssl fails to translate correctly,resulting in code that will not recompiel
edit : dccraps.int also has multiple lines of
Code:
local_var(x);
no expression pointing to a script var or setting the local,script fails to recompile because of original code

another is mckarl.int
Code:
 "--" actual line is item_caps_adjust(x_ptr, -- lvar)
should simply be
Code:
 "-" or items_caps_adjust(x_ptr, - lvar)
again resulting in code that will not compile
script fails to recompile because of original code

i will try to fix these,in that way allowing all vanilla scripts to decompile,then without editing,recompile(it may be a while,my c++ isnt that great)
that was my original intention,but as these 3 scripts(of about 1400 in vanilla game) are results of bad code that bugs in the original compiler failed to catch and are exceedingly rare,im not going to bother

edit : the other script that wont recompile is surf.int and it is a mess,multiple procedures are declared and some of them are even referenced,but the bodies of the procedures are not written(in other words not the decompiler,was original code)
edit : surf.int is not even in the scripts.lst of the vanilla game,heh

edit : in regards to the thread link,i read most of it,but i recieved the source dirrectly from Jordan,he even fixed a few bugs present when i tried to compile it the first few times,any fixes he may have done are included,thank you though

Nirran
 
Nirran said:
sfall compiler(modder_pack from sfall site) for compiling,and int2ssl for decompiling,standard watcom(or other precompiler) is needed

btw i decompiled all the vanilla scripts with int2ssl,all of them decompiled,3 of them would not then(without editing) re-compile,the rest compiled just fine

evidentaly Jordan fixed the
Code:
lvar0 := 0;
lvar1 := 0;
lvar2 := 0;
lvar3 := 0;
 return 0;

bug
:)

Nirran

spoke too soon :(

edit : this bug is actualy when the script was compiled in ruby,and then decompiled with int2ssl,ruby decompiles it correctly but int2ssl doesnt,only happens when a script variable is declared in the procedure

edit : added stop on error command line swicth,uploaded

edit : ruby and int2ssl updated for sfall vrs 2.8,uploaded

Nirran
 
Nirran said:
Nirran said:
evidentaly Jordan fixed the
Code:
lvar0 := 0;
lvar1 := 0;
lvar2 := 0;
lvar3 := 0;
 return 0;

bug
:)
spoke too soon :(

edit : this bug is actualy when the script was compiled in ruby,and then decompiled with int2ssl,ruby decompiles it correctly but int2ssl doesnt,only happens when a script variable is declared in the procedure
This isn't a bug as such; that's really how the script is compiled by sslc. All variables are initialised to 0, and an extra 'return 0;' is added at the end to make sure flow control never drops off the end of a procedure. Having the :=0 assignment when variables are declared isn't a problem, because it wont make any difference to the emitted code. The extra return is more of an issue because it'll end up doubling up each time you decompile. In my experience with your int2ssl, it strips out the last return but not the :=0 assignments.

Anyway, the reason I'm mentioning it now is because I've tried adjusting sslc to be more intelligent about the code it emits, and I'm trying to use int2ssl to check that its output is correct. One of the obvious things was to not emit that return when it's not needed. Unfortunately that's resulting in int2ssl giving an incorrect decompilation because of the way it's hiding the final return.

Ideally you'd need to check if the value being returned is a constant int with a value of 0. If it is it's safe to not emit the return, but otherwise it's needed.

For example, this test script:
Code:
pure procedure foo begin
  return 1;
end

procedure start begin
	variable a, b;
	a:=foo();
	a:=1;
	foreach a in list_as_array(0) begin
		display_msg(a);
	end
	foreach b in list_as_array(0) begin
		display_msg(b);
	end
end

is currently decompiling as:
Code:
procedure foo begin
//Note the missing return 1 here!
end

procedure start begin
	variable LVar0 := 0;
	variable LVar1 := 0;
	variable LVar2 := 0;
	variable LVar3 := 0;
	LVar0 := foo;
	LVar0 := 1;
	LVar2 := list_as_array(0);
	LVar1 := 0;
	LVar3 := len_array(LVar2);
	while(LVar1 < LVar3) do begin
		LVar0 := get_array(LVar2, LVar1);
		display_msg(LVar0);
		LVar1 := LVar1 + 1;
	end
	LVar3 := list_as_array(0);
	LVar0 := 0;
	LVar2 := len_array(LVar3);
	while(LVar0 < LVar2) do begin
		LVar1 := get_array(LVar3, LVar0);
		display_msg(LVar1);
		LVar0 := LVar0 + 1;
	end
end

For reference, decompiling the output of the 2.10 compiler with optimization turned off gives:
Code:
procedure foo begin
	return 1; //Back again. :)
end

procedure start begin
	variable LVar0 := 0;
	<snip lots more vars>
	variable LVar7 := 0;
	LVar0 := foo;
	LVar0 := 1;
	LVar2 := list_as_array(0);
	LVar4 := 0;
	LVar3 := len_array(LVar2);
	while(LVar4 < LVar3) do begin
		LVar0 := get_array(LVar2, LVar4);
		display_msg(LVar0);
		LVar4 := LVar4 + 1;
	end
	LVar5 := list_as_array(0);
	LVar7 := 0;
	LVar6 := len_array(LVar5);
	while(LVar7 < LVar6) do begin
		LVar1 := get_array(LVar5, LVar7);
		display_msg(LVar1);
		LVar7 := LVar7 + 1;
	end
end
So the return 1 shows up successfully.
 
i have been negligent of my fo2 mods and int2ssl along with the ruby sfall opcodes files

i will recrifiy that in a few days

Nirran
 
i have dropped win9x support and now this program will only run in xp+,will be adding the new op_code get_sfall_args soon

uploaded

Nirran
 
Uopdated with the new op_code get_sfall_args

uploaded both int2ssl and ruby op codes

Nirran
 
What about that problem with it hiding important returns rather than just the final return 0's? Did you ever fix that.
 
not yet,the main problem is that when the decompiler does that it skips the finnal end of that procedure

edit : @Timeslip - what is the optomization doing that causes the return to not be emitted?

Nirran
 
Nirran said:
edit : @Timeslip - what is the optomization doing that causes the return to not be emitted?
Removing unreachable code. The compiler always adds a 'return 0;' to the end of every function, so if you write:
Code:
procedure foo begin
  return 1;
end
Then the compiler generates:
Code:
procedure foo begin
  return 1;
  return 0;
end
My optimizer sees that the second return will never be executed and removes it again, leaving just the return 1. int2ssl removes the last return from the function, which normally gets rid of the automatic return 0, but in this case takes out the return 1 instead since the return 0 had already been removed. When you recompile the int2sse output you then end up with
Code:
procedure foo begin
  return 0;
end
which is incorrect.

There's some other stuff that decompiles differently to what the input was, (I think I showed most of it in my other post,) but it's all functionally equivalent so there's no need to change any of it. (And it would be insanely hard to change anyway.) The return is the only one that could possibly lead to broken code. (But even then it's unlikely, so it's not a huge bother.)
 
pretty sure this is the code causing it,i dont know how to retrieve the value return has

Code:
	if ((NodeArray[nLastNodeIndex].m_Opcode.GetOperator() == COpcode::O_POP_RETURN) &&
		(NodeArray[nLastNodeIndex].m_Arguments[0].m_Opcode.GetOperator() == COpcode::O_INTOP)){
		ulOffset = NodeArray[nLastNodeIndex].m_ulOffset;
		NodeArray[nLastNodeIndex] = c_NodeEndOfBlock;
		NodeArray[nLastNodeIndex].m_ulOffset = ulOffset;
	}

i also belive it is what is causing the var,var,return when the script was compiled with ruby,donno alot about c++ :(

edit : closer look at the code ruby compiled then decompiled with int2ssl shows the lvar1 :=0; etc is placed after the return,may be able to fix that with the ruby files,change the order

Nirran
 
Nirran said:
Nirran said:
sfall compiler(modder_pack from sfall site) for compiling,and int2ssl for decompiling,standard watcom(or other precompiler) is needed

btw i decompiled all the vanilla scripts with int2ssl,all of them decompiled,3 of them would not then(without editing) re-compile,the rest compiled just fine

evidentaly Jordan fixed the
Code:
lvar0 := 0;
lvar1 := 0;
lvar2 := 0;
lvar3 := 0;
 return 0;

bug
:)

Nirran

spoke too soon :(

edit : this bug is actualy when the script was compiled in ruby,and then decompiled with int2ssl,ruby decompiles it correctly but int2ssl doesnt,only happens when a script variable is declared in the procedure

edit : added stop on error command line swicth,uploaded

edit : ruby and int2ssl updated for sfall vrs 2.8,uploaded

Nirran

this is actualy a ruby bug,found the cause and fixed it,uploaded

edit :
Timeslip said:
There's some other stuff that decompiles differently to what the input was, (I think I showed most of it in my other post,) but it's all functionally equivalent so there's no need to change any of it. (And it would be insanely hard to change anyway.) The return is the only one that could possibly lead to broken code. (But even then it's unlikely, so it's not a huge bother.)
may not be a big deal but i want to fix it,at least i have identified the code that is causing it,pretty simple what has to be done,just need to learn how to do it lol

Nirran
 
Timeslip said:
Nirran said:
Nirran said:
evidentaly Jordan fixed the
Code:
lvar0 := 0;
lvar1 := 0;
lvar2 := 0;
lvar3 := 0;
 return 0;

bug
:)
spoke too soon :(

edit : this bug is actualy when the script was compiled in ruby,and then decompiled with int2ssl,ruby decompiles it correctly but int2ssl doesnt,only happens when a script variable is declared in the procedure
This isn't a bug as such; that's really how the script is compiled by sslc. All variables are initialised to 0, and an extra 'return 0;' is added at the end to make sure flow control never drops off the end of a procedure. Having the :=0 assignment when variables are declared isn't a problem, because it wont make any difference to the emitted code. The extra return is more of an issue because it'll end up doubling up each time you decompile. In my experience with your int2ssl, it strips out the last return but not the :=0 assignments.

Anyway, the reason I'm mentioning it now is because I've tried adjusting sslc to be more intelligent about the code it emits, and I'm trying to use int2ssl to check that its output is correct. One of the obvious things was to not emit that return when it's not needed. Unfortunately that's resulting in int2ssl giving an incorrect decompilation because of the way it's hiding the final return.

Ideally you'd need to check if the value being returned is a constant int with a value of 0. If it is it's safe to not emit the return, but otherwise it's needed.

For example, this test script:
Code:
pure procedure foo begin
  return 1;
end

procedure start begin
	variable a, b;
	a:=foo();
	a:=1;
	foreach a in list_as_array(0) begin
		display_msg(a);
	end
	foreach b in list_as_array(0) begin
		display_msg(b);
	end
end

is currently decompiling as:
Code:
procedure foo begin
//Note the missing return 1 here!
end

procedure start begin
	variable LVar0 := 0;
	variable LVar1 := 0;
	variable LVar2 := 0;
	variable LVar3 := 0;
	LVar0 := foo;
	LVar0 := 1;
	LVar2 := list_as_array(0);
	LVar1 := 0;
	LVar3 := len_array(LVar2);
	while(LVar1 < LVar3) do begin
		LVar0 := get_array(LVar2, LVar1);
		display_msg(LVar0);
		LVar1 := LVar1 + 1;
	end
	LVar3 := list_as_array(0);
	LVar0 := 0;
	LVar2 := len_array(LVar3);
	while(LVar0 < LVar2) do begin
		LVar1 := get_array(LVar3, LVar0);
		display_msg(LVar1);
		LVar0 := LVar0 + 1;
	end
end

For reference, decompiling the output of the 2.10 compiler with optimization turned off gives:
Code:
procedure foo begin
	return 1; //Back again. :)
end

procedure start begin
	variable LVar0 := 0;
	<snip>
	variable LVar7 := 0;
	LVar0 := foo;
	LVar0 := 1;
	LVar2 := list_as_array(0);
	LVar4 := 0;
	LVar3 := len_array(LVar2);
	while(LVar4 < LVar3) do begin
		LVar0 := get_array(LVar2, LVar4);
		display_msg(LVar0);
		LVar4 := LVar4 + 1;
	end
	LVar5 := list_as_array(0);
	LVar7 := 0;
	LVar6 := len_array(LVar5);
	while(LVar7 < LVar6) do begin
		LVar1 := get_array(LVar5, LVar7);
		display_msg(LVar1);
		LVar7 := LVar7 + 1;
	end
end
So the return 1 shows up successfully.

fixed the return not being emitted in int2ssl,uploaded

edit : forgot to mention that the fix only affects newly compiled scripts,previous compiled scripts will have the error,and that it only effects scripts compiled with ruby then decompiled with int2ssl
edit : vague response,this is in reference to the ruby bug that happens when compiled by ruby and decompiled with int2ssl,previously compiled script will return with this(not in source code)
Code:
return 0;
lvar1 := 0;
lvar2 := 0;
etc,then finnal end missing
now with the files i uploaded,compiled in ruby and decompiled with int2ssl will work properly,but again,only with scripts compiled with the files i uploaded,not previous compiled scripts

Nirran
 
is this a problem?ive been working to get rid of the wandering end else begin, if () begin bug,example

Code:
	if (LVar0 == 3) then begin
		if (LVar0 == 4) then begin
			return LVar0;
		end
		else begin
			if (LVar0 == 5) then begin
				return LVar0;
			end
			else begin
				return LVar0;
			end
		end
		return LVar0;
	end
	else begin
		if (LVar0 == 6) then begin
			if (LVar0 == 7) then begin
				return LVar0;
			end
			else begin
				if (LVar0 == 8) then begin
					return LVar0;
				end
				else begin
					return LVar0;
				end
			end
			return LVar0;
		end
		else begin
			if (LVar0 == 9) then begin
				if (LVar0 == 1) then begin
					return LVar0;
				end
				else begin
					if (LVar0 == 10) then begin
						return LVar0;
					end
					else begin
						return LVar0;
					end
				end
				return LVar0;
			end
			else begin
				if (LVar0 == 11) then begin
					if (LVar0 == 12) then begin
						return LVar0;
					end
					else begin
						if (LVar0 == 13) then begin
							return LVar0;
						end
						else begin
							return LVar0;
						end
					end
					return LVar0;
				end
				else begin
					if (LVar0 == 14) then begin
						return LVar0;
					end
					else begin
						if (LVar0 == 15) then begin
							return LVar0;
						end
						else begin
							return LVar0;
						end
					end
					return LVar0;
				end
			end
		end
	end

i have it working and it recompiles,but it changes the code a little,wondering if this matters

source <snip>
Code:
   end else begin 
      if(tester == 14) then begin 
         return tester;
         return tester;
         return tester;
         return tester;
         return tester;
         return tester;
         return tester;
         return tester;
         return tester;
         return tester;
      end else if(tester == 15) then begin 
         return tester;
      end else begin 
         return tester;
      end
   end

result <snip>
Code:
	end
	else
	if (LVar0 == 14) then begin
		return LVar0;
		return LVar0;
		return LVar0;
		return LVar0;
		return LVar0;
		return LVar0;
		return LVar0;
		return LVar0;
		return LVar0;
		return LVar0;
	end
	else
	if (LVar0 == 15) then begin
		return LVar0;
	end
	else begin
		return LVar0;
	end

if not i have fixed an annoying bug

edit : for reference ruby does the same thing to the code

Nirran
 
Nirran said:
edit : forgot to mention that the fix only affects newly compiled scripts,previous compiled scripts will have the error,and that it only effects scripts compiled with ruby then decompiled with int2ssl
hmm? But the bug I was talking about happened when you compiled scripts with sfall's compiler and decompiled with int2ssl. ruby wasn't involved. :?

What was it you just fixed there exactly?

Nirran said:
if not i have fixed an annoying bug
In the specific case that you showed, no, it doesn't matter. I can think of constructs where that same manipulation will result in broken code though.
Code:
variable v:=2;
if v == 0 then begin
  display_msg("1");
end else if v == 1 then begin
  if v == 2 then begin
    display_msg("2");
  end else begin
      display_msg("3");
  end
end else begin
    display_msg("4");
end
This structure should display 4, but with your manipulation as far as I can see the result wont even compile, and if it does it will output 2.
Edit: Actually, maybe that wont happen... I can't quite see what you've done there from that single example, but if it's only the final else that's getting merged in, then it should be safe.

This is a case exactly the same as the 'variable:=0;' lines, or the way that the line array[1]:=2 will decompile as set_array(array, 1, 2). It is really what the compiler generates. There is no such thing as an 'else if' construct in the compiled code, just like how all variable decelerations in the compiled code require an initial value, and how there's not really any such thing as arrays.
 
i fixed the return being hidded in int2ssl,uploaded that a few days ago,i also fixed the ruby then int2ssl decompile bug that lists the returns and skips the finnal end,upload couple days ago,now im working on the wandering indent,yes the only thing that isnt decompiled exactly is the finnal end else begin,then only if the statement has

end else begin
if () begin

other then that it is exact

thnx Timeslip

edit : completed the wandering indent bug,now if the source has
Code:
if () then begin
bla bla
end else if() then begin
bla bla
end
the decompiler will put that instead of
Code:
end else begin
   if () then begin

tested it by decompiling all the scripts that come with vanilla game,all but 3 recompiled and after looking at them,they are the same scripts that failed to re-compile when i did my other test,months ago(previous in this thread),will be uploading the fix shortly

edit : uploaded

edit : forgot to update the version number,corrected and uploaded

Nirran
 
fixed a bug with script editer optomized code missing a finnal end when decompiled

uploaded

Nirran
 
Back
Top