IF logic .scr files

Anything to do with GTA1/GTA2 modding (tools, scripts and more).
Jones
Psycho
Psycho
Posts: 51
Joined: 08 Aug 2012, 21:25

IF logic .scr files

Post by Jones »

Hi,
maybe we can solve together the problem how IF conditions are compiled. Here is a bit what I got so far, given code:

[mis]PLAYER_PED p1 = ( 0.0 , 0.0 , 0.0 ) 0 0

COUNTER a=0
COUNTER b=0

LEVELSTART

IF ( a=2 )
DO_NOWT
ENDIF

LEVELEND[/mis]

Here is the relevant bytecode how it could look:

Code: Select all

5E 00 // SCRCMD_S_EQUAL_I 
07 00 00 00 //address for S_EQUAL_I ?
02 00 // index of variable ?
02 00 // 2. operand
05 00  // address
01 01 // SCRCMD_DO_NOWT 257
08 00 00 00 07 00 // address for DO_NOWT?
62 00 // SCRCMD_IF_JUMP
05 00 00 00 00 00 08 00 08 00 //address
Descriptions are taken from scr_commands.h in T.M.'s decompiler. Next thing we have to figure out how those address bytes are computed :)
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: IF logic .scr files

Post by T.M. »

Dont forget the while logic as well! ;)

Here's what i know so far:

Nested ELSE's will result in bugged compiled code. Such as:

Code: Select all

if(...){
    if(...){
        // should work
    }else{
         // buggg
    }
}
Not sure exactly if that will make bug, maybe the first IF needs else too.

I think it should be possible to fix that by writing own compiler, GTA2 should be able to read it correctly, if it was compiled correctly.

Here is the commented out code from my decompiler scr_functions.h, i have added there few lines:

[mis]

struct SCR_IF_JUMP {
    SCR_CMD_FORMAT(
        Uint16 logical_operator; // seems to be 0 for AND command and 1 for OR command.
        Uint16 else_jump; // where will it jump if check was false.
    );
};
string read_IF_JUMP(FPStruct &params){
    get_data(SCR_IF_JUMP, data);
    if(params.header->return_value == 0 && data.logical_operator == 0){ // not sure about this.
        return sprintf_str("ENDIF %s", hexdump(params,0).c_str());
    }else{
        return sprintf_str("%s", hexdump(params,1).c_str());
    }
}
//LinkToFunc(SCRCMD_IF_JUMP, read_IF_JUMP);

//ZERO_PARAMS_LAYOUT_BOOL(NOT, "NOT"); // this will be wrapped around the previous 
//comparison command or function with braces! (is not included atm because it causes
// parse errors in the compiler because its not wrapped around the IF's yet).


// TODO:
//TWO_PARAMS_LAYOUT(GOTO, sprintf_str("GOTO"); // correct struct, but format not 
//figured out yet; probably not visible in code at all and used only in while loops etc.
[/mis]

GOTO's seem to be used with while loops. Or maybe with user defined functions as well?

For what i know, the IF command executes the boolean function, takes its return value, and then uses it as a parameter for the S_EQUAL_I etc functions. Same goes with NOT(), its just another function which only inverts the return value.

[mis]struct SCR_CMD_HEADER {
Uint16 cmd_this; // current pointer index.
Uint16 type; // which function type, PLAYER_PED etc.
Uint16 cmd_next; // next pointer index.
Uint16 return_value; // used by IF_JUMP's and boolean functions,
//seems to be return value for boolean functions, and endif marker for if_jumps (if zero).
};
[/mis]
BenMillard
Immortal
Posts: 889
Joined: 16 May 2009, 06:14
GH nick: BenMillard
Location: London, UK
Contact:

Re: IF logic .scr files

Post by BenMillard »

If ELSE only errors while nested then Ben's understanding equals true.

A cookie for whomever can write that as a .mis sample!
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

I have been working also on IF stuff but im at home atm and i dont have the text file that describes all the stuff i have found. Its in my laptop which is far away currently. Maybe at the end of the week i will get to it.

I dont know what addresses you talk about but i didnt know about such thing.
If i remember it was pretty clear how IF is done but was too lazy (not enough patience) to implement it in my compiler.

Also my compiler has many more "fun" commands implemented but i didn't post it no-one cares about it anyway. And TM probably is creating his own compiler so there is no point.

I will try to get the IF stuff info to here asap.
While_exec and such of course were more complicated but also i never thought about nested IF's.
First the "usual" IFs should be made to work.

But TM is right about that miss2 compiles sometimes garbage into .scr and these "junk" bytes confuse things even more. These must be filtered out by: hex_edit-run-crash, hex_edit-run-crash etc. Until no crash.


Should i continue compiler or not?
There is no point creating 2 compilers.
Always wear safety glasses while programming.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: IF logic .scr files

Post by T.M. »

B-$hep wrote:If i remember it was pretty clear how IF is done but was too lazy (not enough patience) to implement it in my compiler.
Yeah the logic is pretty easy, i think. The hard part is to convert the binary code back to .mis code.
B-$hep wrote:Also my compiler has many more "fun" commands implemented but i didn't post it no-one cares about it anyway. And TM probably is creating his own compiler so there is no point.
Oh stop it. Im not creating my own compiler.

Nobody cared about my decompiler either, but yet somehow i managed to finish it. Why? You need to think, for whom are you coding for? Yourself, or some imaginary person?

Anyways... you still havent released the source. And It's getting superbly annoying to hear this in a continuous loop:

Code: Select all

while(TM hasn't yet made his own compiler){
    SendMSG("Hey, made some progress, added this and that.");
    Sleep(2 months);
    SendMSG("So you dont care? Whats the point making this if nobody cares. I quit!");
    SendMSG("TM probably makes his own compiler, so whats the point?");
}
User avatar
Sektor
Boss
Boss
Posts: 1423
Joined: 04 Mar 2008, 06:51
GH nick: Sektor
Location: GTAMP.com
Contact:

Re: IF logic .scr files

Post by Sektor »

I care about the decompiler. I decompiled many SCR files that didn't have mis files so I could improve them or copy parts of their code.

At the moment I'm writing lots of scripts in scriptpad for use with the peek/poke functions in the next gta2.exe, so it'd be great if B-$hep could fix the minor scriptpad bugs.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

I actually even tried to write out some IF stuff into .scr. not much but there were some "unusual things" i had to make. I will try to find this also. Could be useful.

But if you implement IF and other things in your decompiler then better diy.
For me personally its hard to make any additions into scr decompiler of yours.
Its hard because i didnt wrote it and its big source.
Easier to rewrite whole thing and integrate all that stuff
Always wear safety glasses while programming.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: IF logic .scr files

Post by T.M. »

B-$hep wrote:For me personally its hard to make any additions into scr decompiler of yours.
Its hard because i didnt wrote it and its big source.
Easier to rewrite whole thing and integrate all that stuff
Yeah probably needs rewrite just for the IF/WHILE's. The way it works, works linearly, and IF/WHILE's arent linear; need to handle multiple places from output at same time. So you are right about rewriting. Im not afraid of it though.

"To help" does not mean always "to do it all yourself and write code all yourself".

The logic behind it can be represented with simple pseudocode.

That would be very helpful.

Think it like writing a manual for how SCR files work. You dont need a working program to represent the logic.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

TM
Lets take a simplest script with WHILE_EXEC:

Code: Select all

counter endlessloop=1

PARKED_CAR_DATA c1 = ( 5.5 , 5.5 , 2.0 ) 25 180 copcar
PLAYER_PED p1 = ( 4.5 , 4.0 , 2.0 ) 25 0      

levelstart

WHILE_EXEC ( endlessloop = 1 )
 IF (IS_CAR_WRECKED(c1))
  DISPLAY_BRIEF ( 1019 )
 ENDIF
ENDWHILE

levelend
The compiled version of it is in attachement.
The black rectangle at 2F70 shows the unknown bytes / bits (whatever): 0100 0A00
The "4D00" is "GOTO".
The 05 next to it is the COMMAND INDEX to GOTO in this case goto WHILE_EXEC

If we think about unknown bits like command indexes, then 01 would be COUNTER and 0A (10) would be LEVELEND.

But i dont think so.
I just zeroed them out and script still works fine, i blow up car, the brief is displayed, no GTA2 crashes.


So. Any ideas TM what the hell they are? Random junk again?

I dont see GOTO is used in IF..ELSE..ENDIF.
What else there may use GOTO?

I actually implemented the WHILE_EXEC completely in my compiler (ok 99.9% because of the unknown bits) but again, what are these 01 and 0A in this case? I just zero them out atm.
WHILE_EXEC was real and i mean REAL pita to implement. I still have to test it, to be completely sure it works in all conditions..



The unknown bits of course differ in different compiled scripts and depend what order of script commands are etc. You know...

EDIT: after a bit of thinking, i will do few test scripts or add more commands. Maybe i will see the logic and figure out what are they.
Maybe just left over from something again.
Attachments
unknownbits.JPG
unknownbits.JPG (49.29 KiB) Viewed 44659 times
Always wear safety glasses while programming.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: IF logic .scr files

Post by T.M. »

From scr_functions.h:
[mis]//TWO_PARAMS_LAYOUT(GOTO, sprintf_str("GOTO"); // correct struct, but format not figured out yet; probably not visible in code at all and used only in while loops etc.[/mis]
and:
[mis]struct SCR_CMD_HEADER { // copied to every function.
Uint16 cmd_this; // current pointer index.
Uint16 type; // which function type, PLAYER_PED etc.
Uint16 cmd_next; // next pointer index.
Uint16 return_value; // used by IF_JUMP's and boolean functions, seems to be return value for boolean functions, and endif marker for if_jumps (if zero).
};
[/mis]
Each command is saved as:
SCR_CMD_HEADER+params
if it has 2 params, then there is header + 2 params (2x 16bit variables).

So the GOTO command has header (4 variables of 16bit) and 2 variables of 16bit.

Using this information, i can see that:
0D00 = SCR_CMD_HEADER.cmd_this
4D00 = SCR_CMD_HEADER.type
0500 = SCR_CMD_HEADER.cmd_next
0100 = SCR_CMD_HEADER.return_value

I dont know what the rest 0A00 and 0000 are... Probably i have made mistake while writing "correct struct" for that GOTO command... Try to set them to FFFF and FFFF and see if stuff blows up...

3C00 = SCRCMD_LEVELEND, so 0E00 belongs to that command, and rest are just the header information. (levelend command has no params).

Try spamming commands which creates GOTO commands and see if those unknown bytes change with any logic.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

Lets say i have simple script like this:

Code: Select all

COUNTER c1 = 44
COUNTER c2 = 66

PLAYER_PED player = (49.5, 46.5, 5.0) 1 0

levelstart

if(c1=44)
  if (c2=66)
     //Nicely done
     DISPLAY_BRIEF (7032)
  else
     // useless
     DISPLAY_BRIEF (7064)
   endif
else
    // Frenzy passed
    DISPLAY_BRIEF (7033)
endif

levelend
We compile and run it, it shows first the message: "Nicely done..." and after that "Frenzy passed" (7033).
Why it displays the 7033 if the c1 is indeed 44 and the comparison is TRUE?

I check: if c1 is 44 ?
Yes. So we have no reason to show 7033.
We must show it only if c1 <> 44.

Seems like im too sleepy and the compiler is correct about this (maybe another GTA2 weirdness), or its indeed bug.
And it kinda "falls through" the ELSE ?

Any ideas? Is this the bug you guys talked about?
Always wear safety glasses while programming.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: IF logic .scr files

Post by T.M. »

Its a bug in miss2 compiler. I angried my blood with that too, once: http://gtamp.com/forum/viewtopic.php?p=5335#p5335 There you can see how i fixed it. If you want to make scripts, tip: dont use ELSE's, unless its really never going to be nested.

There should not be any reason why these nested ELSE's wouldnt work in GTA2 if it was just compiled correctly.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

Ok. im not home atm, but if i remember correctly then the brief 7032 points directly to 7033.
thats why its displayed. next command after the 7032 should be levelend.

i modified the scr by hand and pointed it to levelend.
7033 disappeared. and no crashes.

so consider it fixed. unless there are other else bugs.

in other words the next cmd index generated for 7032 is wrong.

will do more testing at home.
Always wear safety glasses while programming.
BenMillard
Immortal
Posts: 889
Joined: 16 May 2009, 06:14
GH nick: BenMillard
Location: London, UK
Contact:

Re: IF logic .scr files

Post by BenMillard »

Ah, that explains it.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

Hi all.
I have some script.

Code: Select all

COUNTER c1 = 44
COUNTER c2 = 66
levelstart
				if(c1=44)
					do_nowt
					do_nowt
						if(c1=44) // If_Nr_2
							do_nowt
							do_nowt  // AA
		
						endif
				else do_nowt  // BB
					do_nowt

				endif
// Here
levelend
I cant understand the logic. Maybe its totally wrong in miss2.
Thats why i ask. I added some comments.

Where should the ENDIF after the DO_NOWT (AA) go?
Into ELSE at the BB or directly to "levelend"?

Miss2 points to "ELSE" at "// BB".
But in my eyes it looks wrong.

Because i think that and it seems so:

If "// If_Nr_2" c1=44 returns false then it should go to levelend.
But at the moment it jumps into ELSE.

Another example:

Code: Select all

COUNTER c1 = 44
COUNTER c2 = 66
PLAYER_PED p1 = (88.5, 106.5, 255.0) 10  0  //ste.gmp
levelstart
				if(c1=44)
					DISPLAY_BRIEF ( 4069 ) //It doesn't work! What is this SHIT?
						if(c2=44)
							DISPLAY_BRIEF ( 1117 ) // PLEASE REPORT DEAD BRIEF 1117 TO ALAN JACK AND WILLY MILLS!
							
						endif
				else DISPLAY_BRIEF ( 1111 ) //You expect the Zaibatsu to respect YOU

				endif
levelend

In this case it displays both: 4069 and 1111.
Miss2 compiles it so it jumps into else. But c1 IS 44 so it should NOT jump into else at all.

If i change c2 to: if(c2=45)

Then it displays 1111. Which also seems wrong.
Because if c2<>44 then it should not jump into some ELSE statement that doesnt belong to him.

If c2 is not 44 then i think it should jump out of these if statements.
Directly after final ENDIF in this case.


Im wrong or im correct?
Always wear safety glasses while programming.
User avatar
Sektor
Boss
Boss
Posts: 1423
Joined: 04 Mar 2008, 06:51
GH nick: Sektor
Location: GTAMP.com
Contact:

Re: IF logic .scr files

Post by Sektor »

Welcome back. Your logic makes sense for every other programming language, miss2 just does it wrong.

miss2 seems to move the endif on a nested if statement, so the else can only be used on the inner check and not the outer check.
[mis]
COUNTER c1 = 44
COUNTER c2 = 66
PLAYER_PED p1 = (88.5, 106.5, 255.0) 10 0 //ste.gmp
levelstart
if(c1=44)
DISPLAY_BRIEF ( 4069 ) //It doesn't work! What is this SHIT?
if(c2=44)
DISPLAY_BRIEF ( 1117 ) // PLEASE REPORT DEAD BRIEF 1117 TO ALAN JACK AND WILLY MILLS!
else DISPLAY_BRIEF ( 1111 ) //You expect the Zaibatsu to respect YOU
endif
endif
levelend
[/mis]
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

Hi Sektor.

So theoretically correct way is to allow ELSE for both inner and outer checks?
I work on the compiler and dont want to generate bad stuff.

Im at work atm. But i will try both methods at home.
Always wear safety glasses while programming.
User avatar
Sektor
Boss
Boss
Posts: 1423
Joined: 04 Mar 2008, 06:51
GH nick: Sektor
Location: GTAMP.com
Contact:

Re: IF logic .scr files

Post by Sektor »

There are some nested ELSE in official script, I wonder if they work.

bil_ke2:
[mis]
IF ( ( ( NOT ( LOCATE_CHARACTER_BY_CAR ( shaft , 176.5 , 249.5 , 3.0 , 7.0 , 7.0 ) ) )
AND ( IS_CHARACTER_IN_MODEL ( shaft , copcar ) ) )
AND ( k_e_2_copcar_at_cranes = 1 ) )
SET k_e_2_copcar_at_cranes = 0
// SET k_e_2_in_copcar = 0
// POINT_ARROW_AT ( arrow , 176.5 , 249.5 , 2.0 )
DISPLAY_BRIEF_NOW ( 3489 ) // "Stop wasting time, now bring the copcar to the cranes to be crushed!"
ELSE

IF ( ( NOT ( LOCATE_CHARACTER_ANY_MEANS ( shaft , 176.5 , 249.5 , 3.0 , 7.0 , 7.0 ) ) )
AND ( k_e_2_copcar_at_cranes = 1 ) )
SET k_e_2_copcar_at_cranes = 0
// SET k_e_2_in_copcar = 1
// DISPLAY_BRIEF_NOW ( 3490 ) // "Stop wasting time, now bring the copcar to the cranes to be crushed!"
/* ELSE

IF ( ( NOT ( LOCATE_CHARACTER_BY_CAR ( shaft , 176.5 , 249.5 , 2.0 , 7.0 , 7.0 ) ) )
AND ( k_e_2_copcar_at_cranes = 1 ) )
SET k_e_2_copcar_at_cranes = 0
SET k_e_2_in_copcar = 1
DISPLAY_BRIEF_NOW ( 3491 ) // "Stop wasting time, now bring the copcar to the cranes to be crushed!"
ENDIF
*/ ENDIF
ENDIF
[/mis]
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: IF logic .scr files

Post by B-$hep »

I will test this piece in my compiler.
Its complex enough. But it should work without problems.

I also wonder, because there are some parts that are commented out.

In bil.mis and its mission scripts and in your piece.
Maybe they commented them out because of bugs in compiler/script.

EDIT: your script from here:
http://gtamp.com/forum/viewtopic.php?p=9510#p9510

actually crashes the miss2.
Always wear safety glasses while programming.
User avatar
Sektor
Boss
Boss
Posts: 1423
Joined: 04 Mar 2008, 06:51
GH nick: Sektor
Location: GTAMP.com
Contact:

Re: IF logic .scr files

Post by Sektor »

I didn't have a LEVELEND command on that script, added now. Weird that it crashes without that, I would just expect the compiler to tell me it's missing.
Post Reply