Epic GTA2 Script Decompiler (AKA SCR Decompiler)

Anything to do with GTA1/GTA2 modding (tools, scripts and more).
Post Reply
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Epic GTA2 Script Decompiler (AKA SCR Decompiler)

Post by T.M. »

This program decompiles GTA2 .scr files into .mis script files. Supports all commands except IF/WHILE structures.

Note: SCR Decompiler is now part of Epic GTA2 Map Editor.

Full source code:
EpicGTA2ScriptDecompilerDLL.7z
Epic GTA2 Script Decompiler DLL source code
(29.89 KiB) Downloaded 2577 times
Todo:
- IF/WHILE structures.

Documentation:
http://gtamp.com/forum/viewtopic.php?f=4&t=560&p=6750
Last edited by T.M. on 15 Oct 2012, 18:23, edited 23 times in total.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: SCR decompiler

Post by B-$hep »

Thanks alot T.M.

I told ya, you are better with C++, and code is much cleaner at first look.
My code was a big mess, once again: my C++ sucks and it was pretty quick convert.

I better stay with Delphi (Pascal)


Only the macros like: #define SCR_CMD_FORMAT... ARRRRRRRRRRRRRRRRRRRRRRRRRGH :-)
Always wear safety glasses while programming.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: SCR decompiler

Post by B-$hep »

Just compiled your code and found that your code even finds a LEVELEND (LEVELSTART) from bil.scr.

My code failed to do that. Sometimes it found the commands in some .scr's, sometimes not.

Just excellent work T.M. Two heads are better than one.
I think i will modify my code in Pascal to your "methods" and tricks and will use it as base.
Always wear safety glasses while programming.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

Edit: updated lots of my code so i hope i can just include the file here. i got kinda crazy in coding again, couldnt control myself, i am sorry :D

I added CAR_DATA and SOUND and OBJ_DATA name strings! i also allowed negative float values to be read (i think its possible in SCR), and changed/added some structs like SCR_XY -> SCR_XY_f and added SCR_XY_c for the conveyor speeds x/y. later i/you/we will add SCR_XY(Z)_uc if need unsigned chars (possibly for block coords).

Code is long so its best to just put it here:
*updated again, see few posts below*

Note: the new structs i made are probably useless since i think GTA2 doesnt support CAR_DATA declarations to be like that, not sure though. but anyways, theres still lots work to do since theres different combinations of the declarations i think. also CREATE_CAR command must be done, im too lazy to figure those out now.
Last edited by T.M. on 17 Oct 2011, 18:17, edited 1 time in total.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

I realised Vike already made those lists earlier, they seem to match my lists 100% so i made Vike's lists into simpler C arrays.

This list works just like mine: SCR value = index into those arrays.

I removed some stuff like "NONE" because i think those arent used (they were always in end of arrays).

Note: the indexes might be incorrect, you might need to add extra item at beginning, or not. But so far i fixed SCR_COMMANDS, SCR_CARS, SCR_OBJECTS, SCR_SOUNDS to have correct indexes.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

I made some extreme changes again, now it should be super easy for anyone to contribute their findings!
I included Vike's arrays in the files etc. and changed the file structure a lot.

Download:
*updated again, check few post below*

What you need to do is only this:

Code: Select all

#define SCRCMD_SOUND 327 // SCR command value
struct SCR_SOUND {
	SCR_CMD_FORMAT(
		SCR_XYZ_f pos;
		Uint8 sound_id;
		Uint8 play_type;
		Uint16 padding;
	);
};
string read_SOUND(FPStruct &params){
	SCR_SOUND data = read_scr_type(SCR_SOUND, params.script, params.point);
	return sprintf_str("SOUND sound%d = (%.2f, %.2f, %.2f) %s %s", 
		varnames[params.type]+1, scr_f(data.pos.x), scr_f(data.pos.y), scr_f(data.pos.z), SCR_SOUNDS[data.sound_id].c_str(), SCR_PLAY_FOR[data.play_type].c_str()
	);
}
And this:

Code: Select all

Functions[SCRCMD_SOUND] = &read_SOUND;
So its super easy now! i can just copy your crap and stick it in my crap pile and be done with it. SUPAH!
Last edited by T.M. on 19 Oct 2011, 12:31, edited 2 times in total.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: SCR decompiler

Post by B-$hep »

Thanks alot. I have many commands already done in my Delphi code, the command indexes, parameter counts and expected parameters etc. Not for all yet, but for many.

It's very boring work to add all at once.
Always wear safety glasses while programming.
BenMillard
Immortal
Posts: 889
Joined: 16 May 2009, 06:14
GH nick: BenMillard
Location: London, UK
Contact:

Re: SCR decompiler

Post by BenMillard »

Amazing progress!
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

Thanks ben!
B-$hep wrote:Thanks alot. I have many commands already done in my Delphi code, the command indexes, parameter counts and expected parameters etc. Not for all yet, but for many.

It's very boring work to add all at once.
I think its best if you listed here the stuff you figured out so we dont re-figure out stuff twice, waste of time then. Are you using my method (structs) to read the data from SCR ? then it should be easy to just paste here the structs you found out. I will do that too if i start to find them out again. btw why dont you code in c++ ? werent you going to learn it anyways? and you said you already compiled my program so i dont see point using delphi, since its much inferior anyways.

Edit: i think i should change the "SCR_PLAYER_PED data = ..." etc into references instead so it doesnt copy them (faster), i used this method in my SCR file tests too: i used reference and just changed the data directly by just "data.pos.x = ..." and then later i saved the "script" array to a file. i dont know why i didnt use reference at all times... maybe because i was thinking to push those into a new array or something.
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: SCR decompiler

Post by B-$hep »

T.M. wrote:btw why dont you code in c++ ? werent you going to learn it anyways? and you said you already compiled my program so i dont see point using delphi, since its much inferior anyways.
Your are right about this. But it's like with girlfriends.
It's not easy to forget and leave her alone if you have been with her over 5 years.
Same with Delphi.

But i see power of C++ in every "step". Same with your C++ code.
I love the STL stuff. Maps, vectors, lists. Delphi doesn't have so powerful things (at least D7).
Delphi 2009 - Delphi XE has TDictionary, that is like std::map but still, not exactly same.

The main reason i use it, is that it's easy to quickly create something working.
Like ScriptPad, i couldn't imagine doing all the stuff in pure WinAPI and C++. It would be nightmare. The other thing is C++ Builder. It's good. The fast GUI and C/C++ all in one.

Maybe i should switch to that.

If you could push me somehow to drop Delphi, then i will.

333 posts. Nice number.
Always wear safety glasses while programming.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

So you dont want to share your findings here then? (the structs)
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: SCR decompiler

Post by B-$hep »

I haven't debugged them yet. They don't seem to work correctly.
If you work on some specific commands, then let me know. It's pointless to do same work twice.
As you said also. And im not so fast at adding them. Because of the new methods.

I wanted to ask about the commands like: COUNTER.
Not COUNTER xxx = # but just COUNTER countername.

We can't store strings. There is just our own string added and the counter nr we counted when decompiling: counter ctr1, counter ctr2 etc.

How the struct should look like then?
Always wear safety glasses while programming.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

B-$hep wrote:How the struct should look like then?
i dont know, you can figure it out, just create 6 counters and give them specific information which you can later see clearly in the hex editor. variables arent stored there, they probably have the same value as the pointers have at beginning of file, so variable = pointer.

i can guess it would look something like this when using "COUNTER name = value":

Code: Select all

struct SCR_COUNTER {
   SCR_CMD_FORMAT(
      Uint16 value;
      Uint16 padding; // padding probably because i think structs must be divisible by 4 bytes, header/footer was 12bytes
   );
};
Im thinking that maybe i could automate this whole figuring out process... it would work like: add every possible command parameter combination one by one, and each time it would automatically compile the script, and then it would automatically read the SCR file and see which parts had been added there. as it looks very simple format, i think this could actually work. so if i tested command "OBJ_DATA keke = (1.1,2.2,3.3) 0 BIN" i would create scripts for testing:

Code: Select all

OBJ_DATA keke = (1.1,2.2,3.3) 0 BIN // first compile, values to compare to.
OBJ_DATA keke = (-1.0,2.2,3.3) 0 BIN // second compile (-1 should make FFFFFFFF or etc, so i see exactly where the whole variable is)
OBJ_DATA keke = (1.1,-1.0,3.3) 0 BIN // ...
OBJ_DATA keke = (1.1,2.2,-1.0) 0 BIN
OBJ_DATA keke = (1.1,2.2,3.3) -1 BIN
OBJ_DATA keke = (1.1,2.2,3.3) 0 REMOTE
As you see i would just change one variable at once and then check what changed. this would make it easy for a computer to figure it out. using negative numbers is also a nice trick since it should fill all the bytes with FF.

But there is always problems, like i need to know the highest values for the things that uses strings for values, and even then it might make error for example this program might say some variable is only 8bits when it really is 16 bits but the values never reach over 255. although i think that could be figure out since so far they have been using 8bit variables when there is no need for larger. but all in all i think if i made this program it would speed up the findings about 9001% :D

edit: i noticed there are actually own functions for 2d/3d coords, for example OBJ_DATA 3d=16 and 2d=15 - the format is the same, only the type variable will change in my structs. so i can just do this:

Code: Select all

	Functions[SCRCMD_OBJ_DECSET_2D]		= &read_OBJ_DATA_DEC1;
	Functions[SCRCMD_OBJ_DECSET_3D]		= &read_OBJ_DATA_DEC1;
So there is no need to declare two different structs or functions. just link the types into the same function like above. this should work because the 2d coord function actually stores 3d coords and the z-coord is set to 255.0
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

I made some "extreme" updates again:

Download:
(see first post)
- Vike's arrays were corrupt! partly my fault, but some of the items were missing too, so im now using my arrays i made at the first place.
- added macro for functions: get_data(SCR_PLAYER_PED, data) to reduce repetition/errors (no need to type & anymore).
- added macro for funclinks: LinkToFunc(SCRCMD_PLAYER_PED, read_PLAYER_PED) to reduce errors (no need to type & for funcs anymore). i also moved these into own file "scr_funcmap.h" so you dont have to touch in middle of the .cpp file at all anymore.
- added list of all possible SCR commands! thanks to Vike, i think this list is complete. i also edited the list a lot to be able to use it as enums. you should use this list when you link a type to a function (LinkToFunc).
- renamed obj/car reader functions a little bit.
Last edited by T.M. on 22 Nov 2011, 14:45, edited 1 time in total.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

WOW
i found out something cool.

I can make the trailers work with car declarations now! i was figuring out the formats again and noticed the "unknown" variable in car_data was actually the trailer model, so when i set a trailer to the car, it changed that trailer variable, but it changed it INCORRECTLY! it always set the trailer same value as the car model was!

so i opened the SCR file in hexeditor and set the trailer variable to TANKER and woohoo! it actually worked in game! so this is some sort of compiler bug only! if we can fix this then my editor would also show these correctly (atm my editor doesnt show trailers in the bugged way), although theres no way of knowing which method of display it should use if some maps were compiled old and some new compiler. blah. maybe i should just make the script editor to parse the SCR file instead and perhaps allow editing it too. that would be epicer.

Code: Select all

CAR_DATA auto1 = (114.5, 210.0) 1 0 TRUKCAB2 TANKER 
this is what im talking about. it doesnt work properly when compiler, it makes trailer into TRUKCAB2 in the example above. i think it works properly if using CREATE_CAR ?
User avatar
B-$hep
Immortal
Posts: 568
Joined: 24 Apr 2009, 21:43
GH nick: B-Shep
Location: EU

Re: SCR decompiler

Post by B-$hep »

At each step, we only find GTA2 bugs.
Very sad. Even in miss2. Although it's very critical piece of software, GTA2 stability actually depends on scripts generated by miss2.


I also thought about adding some sort of scr editing capability into ScriptPad.
First idea was just add script decompiler and automatically open decompiled script for editing.
Always wear safety glasses while programming.
User avatar
elypter
Immortal
Posts: 1120
Joined: 26 Dec 2009, 23:53
GH nick: elypter

Re: SCR decompiler

Post by elypter »

an unlocked feature. thats awesome !!
yur sa'nok ngeyä
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

Phew, got DOOR_DATA working, perfectly:

.mis:

Code: Select all

PLAYER_PED p1 = (115.5, 210.5, 255.0) 12 90
CHAR_DATA mydude1
CHAR_DATA mydude2
CAR_DATA mycar
CHAR_DATA mydude3
CHAR_DATA mydude4
CHAR_DATA mydude5
DOOR_DATA door2 = SINGLE (31, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 0 ANY_PLAYER CLOSE_NEVER 10 FLIP_RIGHT REVERSED
DOOR_DATA door3 = SINGLE (34, 213, 3) (118.00, 130.00, 2.00,  0.00, 0.00) RIGHT 1 ANY_CAR CLOSE_NEVER 11 FLIP_RIGHT REVERSED
DOOR_DATA door4 = SINGLE (33, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) TOP 2 ONE_CAR CLOSE_WHEN_CLEAR 12 FLIP_RIGHT NOT_REVERSED mycar
DOOR_DATA door5 = SINGLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) BOTTOM 3 ONE_MODEL CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED TANK
DOOR_DATA door6 = SINGLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LID 3 ONE_CHAR_ON_FOOT CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED mydude4
DOOR_DATA door7 = SINGLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 3 ANY_PLAYER_ONE_CAR CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED 1337
DOOR_DATA door8 = DOUBLE (31, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 0 ANY_PLAYER CLOSE_NEVER 10 FLIP_RIGHT REVERSED
DOOR_DATA door9 = DOUBLE (34, 213, 3) (118.00, 130.00, 2.00,  0.00, 0.00) RIGHT 1 ANY_CAR CLOSE_NEVER 11 FLIP_RIGHT REVERSED
DOOR_DATA doora = DOUBLE (33, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) TOP 2 ONE_CAR CLOSE_WHEN_CLEAR 12 FLIP_RIGHT NOT_REVERSED mycar
DOOR_DATA doorb = DOUBLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) BOTTOM 3 ONE_MODEL CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED TANK
DOOR_DATA doorc = DOUBLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LID 3 ONE_CHAR_ON_FOOT CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED mydude4
DOOR_DATA doord = DOUBLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 3 ANY_PLAYER_ONE_CAR CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED 13337
decompiled .scr:

Code: Select all

PLAYER_PED p1 = (115.50, 210.50, 255.00) 12 90
CHAR_DATA chrdec1
CHAR_DATA chrdec2
CAR_DATA autodec1
CHAR_DATA chrdec3
CHAR_DATA chrdec4
CHAR_DATA chrdec5
DOOR_DATA door1 = SINGLE (31, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 0 ANY_PLAYER CLOSE_NEVER 10 FLIP_RIGHT REVERSED
DOOR_DATA door2 = SINGLE (34, 213, 3) (118.00, 130.00, 2.00,  0.00, 0.00) RIGHT 1 ANY_CAR CLOSE_NEVER 11 FLIP_RIGHT REVERSED
DOOR_DATA door3 = SINGLE (33, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) TOP 2 ONE_CAR CLOSE_WHEN_CLEAR 12 FLIP_RIGHT NOT_REVERSED autodec1
DOOR_DATA door4 = SINGLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) BOTTOM 3 ONE_MODEL CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED TANK
DOOR_DATA door5 = SINGLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LID 3 ONE_CHAR_ON_FOOT CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED chrdec4
DOOR_DATA door6 = SINGLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 3 ANY_PLAYER_ONE_CAR CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED 1337
DOOR_DATA door7 = DOUBLE (31, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 0 ANY_PLAYER CLOSE_NEVER 10 FLIP_RIGHT REVERSED
DOOR_DATA door8 = DOUBLE (34, 213, 3) (118.00, 130.00, 2.00,  0.00, 0.00) RIGHT 1 ANY_CAR CLOSE_NEVER 11 FLIP_RIGHT REVERSED
DOOR_DATA door9 = DOUBLE (33, 206, 3) (118.00, 130.00, 2.00,  0.00, 0.00) TOP 2 ONE_CAR CLOSE_WHEN_CLEAR 12 FLIP_RIGHT NOT_REVERSED autodec1
DOOR_DATA door10 = DOUBLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) BOTTOM 3 ONE_MODEL CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED TANK
DOOR_DATA door11 = DOUBLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LID 3 ONE_CHAR_ON_FOOT CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED chrdec4
DOOR_DATA door12 = DOUBLE (28, 208, 3) (118.00, 130.00, 2.00,  0.00, 0.00) LEFT 3 ANY_PLAYER_ONE_CAR CLOSE_WHEN_OPEN_RULE_FAILS 13 FLIP_RIGHT NOT_REVERSED 13337
c++:

Code: Select all

struct SCR_DOOR_DATA_DEC {
	SCR_CMD_FORMAT(
		SCR_XYZ_uc block;
		Uint8 face;
		Uint8 gr_id;
		Uint8 open_type;
		Uint8 close_type;
		Uint8 delay;
		SCR_Rect_f check; // (order: xyz_f pos, xy_f size)
		Uint8 flip;
		Uint8 reversed;
		Uint16 somename; // id of car/model/char or integer (not supported)
	);
};
string get_door_opt_param(FPStruct &params, const Uint16 &somename, const Uint8 &open_type, const int &type1, const int &type2){
	if(params.type == type1){
		if(open_type == 3){ // ONE_MODEL
			return " "+SCR_CARS[somename]; // model
		}else{
			return " "+getname(somename); // var
		}
	}else if(params.type == type2){
		return sprintf_str(" %d", somename); // int
	}else{
		return "";
	}
}
string read_DOOR_DATA_DEC(FPStruct &params){
	get_data(SCR_DOOR_DATA_DEC, data);
	if(params.type >= SCRCMD_DOOR_DECLARE_S1 && params.type <= SCRCMD_DOOR_DECLARE_S3){
		string optional = get_door_opt_param(params, data.somename, data.open_type, SCRCMD_DOOR_DECLARE_S2, SCRCMD_DOOR_DECLARE_S3);
		return sprintf_str("DOOR_DATA %s = SINGLE (%d, %d, %d) (%.2f, %.2f, %.2f,  %.2f, %.2f) %s %d %s %s %d %s %s%s", 
			setgetname("door").c_str(), data.block.x, data.block.y, data.block.z, scr_f(data.check.pos.x), scr_f(data.check.pos.y), scr_f(data.check.pos.z), 
			scr_f(data.check.size.x), scr_f(data.check.size.y), SCR_BLOCK_FACES[data.face].c_str(), data.gr_id, SCR_DOOR_OPENTYPES[data.open_type].c_str(), 
			SCR_DOOR_CLOSETYPES[data.close_type].c_str(), data.delay, SCR_DOOR_FLIPTYPES[data.flip].c_str(), SCR_DOOR_REVERSED[data.reversed].c_str(), optional.c_str()
		);
	}else{
		string optional = get_door_opt_param(params, data.somename, data.open_type, SCRCMD_DOOR_DECLARE_D2, SCRCMD_DOOR_DECLARE_D3);
		return sprintf_str("DOOR_DATA %s = DOUBLE (%d, %d, %d) (%.2f, %.2f, %.2f,  %.2f, %.2f) %s %d %s %s %d %s %s%s", 
			setgetname("door").c_str(), data.block.x, data.block.y, data.block.z, scr_f(data.check.pos.x), scr_f(data.check.pos.y), scr_f(data.check.pos.z), 
			scr_f(data.check.size.x), scr_f(data.check.size.y), SCR_BLOCK_FACES[data.face].c_str(), data.gr_id, SCR_DOOR_OPENTYPES[data.open_type].c_str(), 
			SCR_DOOR_CLOSETYPES[data.close_type].c_str(), data.delay, SCR_DOOR_FLIPTYPES[data.flip].c_str(), SCR_DOOR_REVERSED[data.reversed].c_str(), optional.c_str()
		);
	}
}
LinkToFunc(SCRCMD_DOOR_DECLARE_S1, read_DOOR_DATA_DEC);
LinkToFunc(SCRCMD_DOOR_DECLARE_S2, read_DOOR_DATA_DEC);
LinkToFunc(SCRCMD_DOOR_DECLARE_S3, read_DOOR_DATA_DEC);
LinkToFunc(SCRCMD_DOOR_DECLARE_D1, read_DOOR_DATA_DEC);
LinkToFunc(SCRCMD_DOOR_DECLARE_D2, read_DOOR_DATA_DEC);
LinkToFunc(SCRCMD_DOOR_DECLARE_D3, read_DOOR_DATA_DEC);
apparently i have changed my c++ format again XD will post whole code later.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

If someone wants to hack more, i made it very easy for you people, by compiling a list of nicely formatted hex dump from each of the commands i had in my .mis file.
your job is to figure out which parameter is at which location in the bytestream.

Use these datatypes for the variables in your struct:

Code: Select all

struct SCR_XYZ_f {
	Sint32 x,y,z;
};
struct SCR_XY_f {
	Sint32 x,y;
};
struct SCR_XY_c {
	Sint8 x,y;
};
struct SCR_XYZ_c {
	Sint8 x,y,z;
};
struct SCR_XY_uc {
	Uint8 x,y;
};
struct SCR_XYZ_uc {
	Uint8 x,y,z;
};
struct SCR_Rect_f {
	SCR_XYZ_f pos;
	SCR_XY_f size;
};

And this system for most of the structs you make (some structs might not be using this, but so far all has been):

Code: Select all

struct SCR_BLOCK_HEADER {
	Uint16 type;
	Uint16 cmd;
	Uint16 unknown;
	Uint32 padding;
};
struct SCR_BLOCK_FOOTER {
	Uint16 cmd;
};

// 10 + ? + 2 bytes:
#define SCR_CMD_FORMAT(code) \
	SCR_BLOCK_HEADER header; \
	code; \
	SCR_BLOCK_FOOTER footer; \


So your struct would look like:

Code: Select all

struct SCR_CHAR_DATA_DEC {
	SCR_CMD_FORMAT(
		SCR_XYZ_f pos;
		Uint16 rot;
		Sint16 remap; // note: signed int, use them where possible.
		Uint16 occupation;
		Uint16 padding;
	);
};

Here is the hex dump i made today earlier, but didnt have time to finish it:

Code: Select all




SET_STATION_INFO (trak01, 1, 2, 3)
SET_STATION_INFO (trak02, 4, 5, 6)
SET_STATION_INFO (trak03, 7, 8, 9)
SET_STATION_INFO (trak10, 10, 11, 12)
SET_STATION_INFO (trak11, 13, 14, 15)
SET_STATION_INFO (trak12, 16, 17, 18)
SET_STATION_INFO (trak13, 19, 20, 21)
SET_STATION_INFO (trak20, 22, 23, 24)
SET_STATION_INFO (trak21, 25, 26, 27)
SET_STATION_INFO (trak22, 28, 29, 30)

1D01 1900 0000 1800 0102 0300 0000 1900 
1D01 1A00 0000 1900 0405 0600 0000 1A00 
1D01 1B00 0000 1A00 0708 0900 0000 1B00 
1D01 1C00 0000 1B00 0A0B 0C00 0000 1C00 
1D01 1D00 0000 1C00 0D0E 0F00 0000 1D00 
1D01 1E00 0000 1D00 1011 1200 0000 1E00 
1D01 1F00 0000 1E00 1314 1500 0000 1F00 
1D01 2000 0000 1F00 1617 1800 0000 2000 
1D01 2100 0000 2000 191A 1B00 0000 2100 
1D01 2200 0000 2100 1C1D 1E00 0000 2200 





RADIO_STATION radio1 = STATION_INDUSTRIAL (53.0, -1.0)
RADIO_STATION radio2 = STATION_ZAIBATSU (97.5, -1.0)
RADIO_STATION radio3 = STATION_YAKUZA (-1.0, 227.9)
RADIO_STATION radio4 = STATION_LOONIE (-1.0, 228.1)

1F01 2300 0000 0040 0D00 00C0 FFFF 0400 0000 2300 
1F01 2400 0000 0060 1800 00C0 FFFF 0500 0000 2400 
1F01 2500 0000 00C0 FFFF 99F9 3800 0600 0000 2500 
1F01 2600 0000 00C0 FFFF 6606 3900 0700 0000 2600





SET_GANG_INFO (gng1, 10, PISTOL, MOLOTOV, ELECTRO_BATON, 1, 1.5, 255.0, -1.0, 30, SWATVAN, 12)
SET_GANG_INFO (gng2, 11, MOLOTOV, ELECTRO_BATON, PISTOL, 2, 255.0, -1.0, 1.5, 31, COPCAR, 13)

DF00 2700 0000 2600 0A00 0407 011E 0060 0000 00C0 3F00 00C0 FFFF 3400 0C00 2700 
DF00 2800 0000 2700 0B04 0700 021F 00C0 3F00 00C0 FFFF 0060 0000 0C00 0D00 2800





MAP_ZONE gng1map = ( 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 )
MAP_ZONE gng2map = ( 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 )

6600 2900 0000 0A00 0B00 0C00 0D00 0E00 0F00 1000 1100 1200 1300 1400 0000 2900 
6600 2A00 0000 0B00 0C00 0D00 0E00 0F00 1000 1100 1200 1300 1400 1500 0000 2A00





CRANE_DATA crane1 = (120.5, 198.5) 1 NO_HOMECRANE FIRST (222.2, -1.0) 10
CRANE_DATA crane2 = (198.5, 198.5) 2 NO_HOMECRANE SECOND (333.2, -1.0) 11
CRANE_DATA crane3 = (198.5, 214.5) 3 NO_HOMECRANE SECOND (-1.0, 333.2) 12
CRANE_DATA crane4 = (214.5, 120.5) 4 NO_HOMECRANE FIRST (-1.0, 444.2) 13 SECOND (222.2, 333.2) 14

2600 2B00 0000 C909 0000 0000 0000 0020 1E00 00A0 3100 0100 0000 CC8C 3700 00C0 FFFF 0A00 0000 2B00 
2600 2C00 0000 0000 0000 0000 0000 00A0 3100 00A0 3100 0200 0100 CD4C 5300 00C0 FFFF 0B00 0000 2C00 
2600 2D00 0000 0000 0000 0000 0000 00A0 3100 00A0 3500 0300 0100 00C0 FFFF CD4C 5300 0C00 0000 2D00 
2500 2E00 0000 0000 0000 0000 0000 00A0 3500 0020 1E00 0400 0000 00C0 FFFF CD0C 6F00 0D00 0E00 CC8C 3700 CD4C 5300 2E00





CRUSHER crusher1 = (121.5, 220.5)
CRUSHER crusher1b = (121.5, -1.0)

2800 2F00 0000 0000 0000 0060 1E00 0020 3700 2F00 
2800 3000 0000 0000 0000 0060 1E00 00C0 FFFF 3000





CONVEYOR con1 = (72.5, 203.0)       (4.0, -1.0) 10 1
CONVEYOR con2 = (72.5, 203.0, -1.0) (6.0, 4.0) 11 2

1A00 3100 0000 0000 0000 0020 1200 00C0 3200 00C0 3F00 0000 0100 00C0 FFFF 0A01 0000 3100 
1B00 3200 0000 0000 0000 0020 1200 00C0 3200 00C0 FFFF 0080 0100 0000 0100 0B02 0000 3200 





DESTRUCTOR des1 = (26.0, 232.0)       (2.0, -1.0)
DESTRUCTOR des2 = (26.0, 232.0, -1.0) (1.0, 2.0)

2200 3300 0000 0000 0000 0080 0600 0000 3A00 00C0 3F00 0080 0000 00C0 FFFF 3300 
2300 3400 0000 0000 0000 0080 0600 0000 3A00 00C0 FFFF 0040 0000 0080 0000 3400 





SOUND sound01 = (97.5, 6.0, 2.0) WIND PLAY_FOREVER
SOUND sound02 = (97.5, 6.0, -1.0) BOWLING_ALLEY PLAY_INSTANT

4701 3500 0000 0000 0000 0060 1800 0080 0100 0080 0000 0100 0000 3500 
4701 3600 0000 0000 0000 0060 1800 0080 0100 00C0 FFFF 1C01 0000 3600






obj = CREATE_OBJ (18.8, 220.5)		 1 TOWER END
obj = CREATE_OBJ (19.2, 220.5, -1.0) 2 TUNNEL_BLOCKER END

3400 3800 0100 0300 0000 33B3 0400 0020 3700 00C0 3F00 1900 0100 3800 
3100 3900 0100 0300 0000 CCCC 0400 0020 3700 00C0 FFFF 2601 0200 3900






LEVELSTART
3B00 3700 0000 3700

// figured these out once i added CREATE_OBJ

LEVELEND
3C00 FFFF





auto = CREATE_CAR (32.8, 197.7)		  10 1 BANKVAN END
auto = CREATE_CAR (27.4, 193.0, -1.0) 11 2 BMW END

2B00 3A00 0000 0500 0000 3333 0800 CC6C 3100 00C0 3F00 0100 0A00 0400 FFFF 3A00
2C00 3B00 0000 0500 0000 99D9 0600 0040 3000 00C0 FFFF 0200 0B00 0500 FFFF 3B00






auto = CREATE_CAR (76.3, 194.7) 10 1 GT24640 END
SET_CAR_NUMBER_GRAPHIC (auto, 7)
auto = CREATE_CAR (75.6, 194.7) 11 2 GT24640 END
SET_CAR_NUMBER_GRAPHIC (auto, 8)
auto = CREATE_CAR (74.9, 194.7) 12 3 GT24640 END
SET_CAR_NUMBER_GRAPHIC (auto, 9)

2B00 3C00 0000 0500 0000 3313 1300 CCAC 3000 00C0 3F00 0100 0A00 1300 FFFF 3C00
2F01 3D00 0000 0500 0000 0700 0000 3D00 
2B00 3E00 0000 0500 0000 66E6 1200 CCAC 3000 00C0 3F00 0200 0B00 1300 FFFF 3E00
2F01 3F00 0000 0500 0000 0800 0000 3F00 
2B00 4000 0000 0500 0000 99B9 1200 CCAC 3000 00C0 3F00 0300 0C00 1300 FFFF 4000
2F01 4100 0000 0500 0000 0900 0000 4100






auto = CREATE_CAR (28.5, 224.1) 10 1 TRUKCAB2 TANKER END
auto = CREATE_CAR (28.5, 224.1) 11 2 TRUKCAB2 TRUKTRNS END
auto = CREATE_CAR (29.5, 224.1) 12 3 TRUKCAB1 TANKER END
auto = CREATE_CAR (30.5, 224.1) 13 4 TRUKCAB1 TRUKTRNS END
auto = CREATE_CAR (28.5, 224.1, -1.0) 10 1 TRUKCAB2 TANKER END
auto = CREATE_CAR (28.5, 224.1, -1.0) 11 2 TRUKCAB2 TRUKTRNS END
auto = CREATE_CAR (29.5, 224.1, -1.0) 12 3 TRUKCAB1 TANKER END
auto = CREATE_CAR (30.5, 224.1, -1.0) 13 4 TRUKCAB1 TRUKTRNS END

2D00 4200 0000 0500 0000 0020 0700 6606 3800 00C0 3F00 0100 0A00 4000 3700 4200
2D00 4300 0000 0500 0000 0020 0700 6606 3800 00C0 3F00 0200 0B00 4000 4200 4300
2D00 4400 0000 0500 0000 0060 0700 6606 3800 00C0 3F00 0300 0C00 3F00 3700 4400
2D00 4500 0000 0500 0000 00A0 0700 6606 3800 00C0 3F00 0400 0D00 3F00 4200 4500
2E00 4600 0000 0500 0000 0020 0700 6606 3800 00C0 FFFF 0100 0A00 4000 3700 4600
2E00 4700 0000 0500 0000 0020 0700 6606 3800 00C0 FFFF 0200 0B00 4000 4200 4700
2E00 4800 0000 0500 0000 0060 0700 6606 3800 00C0 FFFF 0300 0C00 3F00 3700 4800
2E00 4900 0000 0500 0000 00A0 0700 6606 3800 00C0 FFFF 0400 0D00 3F00 4200 4900




auto = CREATE_CAR (36.5, 5.0)	   10 1 GT24640 END
trailer = CREATE_CAR (18.9, 224.3) 11 2 TRUKTRNS END
PUT_CAR_ON_TRAILER (auto, trailer)

auto = CREATE_CAR (35.5, 5.0)	   10 1 GT24640 END
trailer = CREATE_CAR (21.9, 224.3) 11 2 TRUKTRNS END
PUT_CAR_ON_TRAILER (auto, trailer)

auto = CREATE_CAR (34.5, 5.0)	   10 1 TVVAN END
trailer = CREATE_CAR (20.9, 224.3) 11 2 TRUKCONT END
PUT_CAR_ON_TRAILER (auto, trailer)

auto = CREATE_CAR (37.5, 5.0)	   10 1 TVVAN END
trailer = CREATE_CAR (19.9, 224.3) 11 2 TRUKCONT END
PUT_CAR_ON_TRAILER (auto, trailer)

2B00 4A00 0000 0500 0000 0020 0900 0040 0100 00C0 3F00 0100 0A00 1300 FFFF 4A00
2B00 4B00 0000 0600 0000 99B9 0400 3313 3800 00C0 3F00 0200 0B00 4200 FFFF 4B00
3C01 4C00 0000 0500 0600 4C00

2B00 4D00 0000 0500 0000 00E0 0800 0040 0100 00C0 3F00 0100 0A00 1300 FFFF 4D00
2B00 4E00 0000 0600 0000 9979 0500 3313 3800 00C0 3F00 0200 0B00 4200 FFFF 4E00
3C01 4F00 0000 0500 0600 4F00

2B00 5000 0000 0500 0000 00A0 0800 0040 0100 00C0 3F00 0100 0A00 4300 FFFF 5000
2B00 5100 0000 0600 0000 9939 0500 3313 3800 00C0 3F00 0200 0B00 4100 FFFF 5100
3C01 5200 0000 0500 0600 5200

2B00 5300 0000 0500 0000 0060 0900 0040 0100 00C0 3F00 0100 0A00 4300 FFFF 5300
2B00 5400 0000 0600 0000 99F9 0400 3313 3800 00C0 3F00 0200 0B00 4100 FFFF 5400
3C01 5500 0000 0500 0600 5500




gang_car = CREATE_GANG_CAR (24.7, 203.7)	   10 1 ICECREAM END
gang_car = CREATE_GANG_CAR (20.5, 203.7)	   11 2 VTYPE END
gang_car = CREATE_GANG_CAR (18.9, 203.7, -1.0) 12 3 ICECREAM END
gang_car = CREATE_GANG_CAR (19.5, 203.7, -1.0) 13 4 VTYPE END

8A01 5600 0000 0700 0000 CC2C 0600 CCEC 3200 00C0 3F00 0100 0A00 1B00 FFFF 5600 
8A01 5700 0000 0700 0000 0020 0500 CCEC 3200 00C0 3F00 0200 0B00 4600 FFFF 5700 
8B01 5800 0000 0700 0000 99B9 0400 CCEC 3200 00C0 FFFF 0300 0C00 1B00 FFFF 5800 
8B01 5900 0000 0700 0000 00E0 0400 CCEC 3200 00C0 FFFF 0400 0D00 4600 FFFF 5900





chr1 = CREATE_CHAR (29.6, 208.8)	   10 1 PLAYER END
chr2 = CREATE_CHAR (30.6, 208.1, -1.0) 11 2 DUMMY END

2900 5A00 0000 0800 0000 6666 0700 3333 3400 00C0 3F00 0100 0A00 0000 0000 5A00
2A00 5B00 0000 0900 0000 66A6 0700 6606 3400 00C0 FFFF 0200 0B00 0300 0000 5B00






chr1 = CREATE_CHAR (29.3, 210.8) 10 1 ANY_EMERGENCY_SERVICE_MAN END
SET_CHAR_GRAPHIC_TYPE (chr1, EMERG_GRAPHIC, -2)
chr1 = CREATE_CHAR (29.8, 210.8) 11 2 ANY_GANG_MEMBER END
SET_CHAR_GRAPHIC_TYPE (chr1, DUMMY_GRAPHIC, -1)
chr1 = CREATE_CHAR (29.3, 211.4) 12 3 ANY_ELVIS END
SET_CHAR_GRAPHIC_TYPE (chr1, EMERG_GRAPHIC, 1)
chr1 = CREATE_CHAR (29.8, 211.4) 13 4 NO_OCCUPATION END
SET_CHAR_GRAPHIC_TYPE (chr1, DUMMY_GRAPHIC, 2)

2900 5C00 0000 0800 0000 3353 0700 33B3 3400 00C0 3F00 0100 0A00 2F00 0000 5C00
6C01 5D00 0000 0800 FEFF 0200 0000 5D00 
2900 5E00 0000 0800 0000 3373 0700 33B3 3400 00C0 3F00 0200 0B00 3000 0000 5E00
6C01 5F00 0000 0800 FFFF 0000 0000 5F00 
2900 6000 0000 0800 0000 3353 0700 99D9 3400 00C0 3F00 0300 0C00 3100 0000 6000
6C01 6100 0000 0800 0100 0200 0000 6100 
2900 6200 0000 0800 0000 3373 0700 99D9 3400 00C0 3F00 0400 0D00 3300 0000 6200
6C01 6300 0000 0800 0200 0000 0000 6300





ADD_PATROL_POINT (chrp1, 29.5, 209.5, -1.0)
ADD_PATROL_POINT (chrp1, 30.5, 209.5, -1.0)
ADD_PATROL_POINT (chrp1, 31.5, 209.5, -1.0)
ADD_PATROL_POINT (chrp1, 33.5, 209.5, -1.0)
ADD_PATROL_POINT (chrp1, 32.5, 209.5, -1.0)
ADD_PATROL_POINT (chrp2, 29.5, 207.5, -1.0)
ADD_PATROL_POINT (chrp2, 31.5, 207.5, -1.0)
ADD_PATROL_POINT (chrp2, 32.5, 207.5, -1.0)
ADD_PATROL_POINT (chrp2, 33.5, 207.5, -1.0)
ADD_PATROL_POINT (chrp2, 30.5, 207.5, -1.0)

CD00 6600 0000 0A00 0000 0060 0700 0060 3400 00C0 FFFF 6600
CD00 6700 0000 0A00 0000 00A0 0700 0060 3400 00C0 FFFF 6700
CD00 6800 0000 0A00 0000 00E0 0700 0060 3400 00C0 FFFF 6800
CD00 6900 0000 0A00 0000 0060 0800 0060 3400 00C0 FFFF 6900
CD00 6A00 0000 0A00 0000 0020 0800 0060 3400 00C0 FFFF 6A00
CD00 6B00 0000 0B00 0000 0060 0700 00E0 3300 00C0 FFFF 6B00
CD00 6C00 0000 0B00 0000 00E0 0700 00E0 3300 00C0 FFFF 6C00
CD00 6D00 0000 0B00 0000 0020 0800 00E0 3300 00C0 FFFF 6D00
CD00 6E00 0000 0B00 0000 0060 0800 00E0 3300 00C0 FFFF 6E00
CD00 6F00 0000 0B00 0000 00A0 0700 00E0 3300 00C0 FFFF 6F00





LOWER_LEVEL (255, 255) (255, 255)
LOWER_LEVEL (255, 255) (0, 0)
LOWER_LEVEL (0, 0) (255, 255)

B800 7000 0000 FFFF FFFF 7000
B800 7100 0000 FFFF 0000 7100
B800 7200 0000 0000 FFFF 7200





EXPLODE			(118.8, 205.8, -1.0)
EXPLODE_SMALL	(120.3, 210.2, -1.0)
EXPLODE_NO_RING (108.5, 210.4, -1.0)
EXPLODE_LARGE	(112.7, 208.0, -1.0)
EXPLODE_WALL	(118.0, 208.6, -1.0) LEFT
EXPLODE_WALL	(118.0, 208.6, -1.0) RIGHT
EXPLODE_WALL	(118.0, 208.6, -1.0) TOP
EXPLODE_WALL	(118.0, 208.6, -1.0) BOTTOM

8E00 7300 0000 33B3 1D00 3373 3300 00C0 FFFF 7300
9401 7400 0000 3313 1E00 CC8C 3400 00C0 FFFF 7400
9601 7500 0000 0020 1B00 9999 3400 00C0 FFFF 7500
8F01 7600 0000 CC2C 1C00 0000 3400 00C0 FFFF 7600
8F00 7700 0000 0080 1D00 6626 3400 00C0 FFFF 0100 0000 7700
8F00 7800 0000 0080 1D00 6626 3400 00C0 FFFF 0200 0000 7800
8F00 7900 0000 0080 1D00 6626 3400 00C0 FFFF 0300 0000 7900
8F00 7A00 0000 0080 1D00 6626 3400 00C0 FFFF 0400 0000 7A00





CHANGE_BLOCK LID (32, 232, 255) NOT_FLAT NOT_FLIP 0 1 255
CHANGE_BLOCK LID (31, 233, 255) FLAT FLIP 1 2 254
CHANGE_BLOCK LID (32, 234, 255) NOT_FLAT NOT_FLIP 2 3 253
CHANGE_BLOCK LID (32, 233, 255) NOT_FLAT NOT_FLIP 3 4 252
CHANGE_BLOCK LID (31, 232, 255) NOT_FLAT NOT_FLIP 2 5 251
CHANGE_BLOCK LID (33, 232, 255) NOT_FLAT NOT_FLIP 1 6 250
CHANGE_BLOCK SIDE (34, 232, 255) LEFT NOT_WALL NOT_BULLET FLAT NOT_FLIP 10 110
CHANGE_BLOCK SIDE (34, 232, 255) RIGHT WALL BULLET NOT_FLAT FLIP 11 109
CHANGE_BLOCK SIDE (34, 232, 255) TOP NOT_WALL NOT_BULLET FLAT NOT_FLIP 12 108
CHANGE_BLOCK SIDE (34, 232, 255) BOTTOM WALL BULLET NOT_FLAT FLIP 13 107

BA00 7B00 0000 20E8 FF05 FF00 0000 7B00
BA00 7C00 0000 1FE9 FF05 FE34 0000 7C00
BA00 7D00 0000 20EA FF05 FD08 0000 7D00
BA00 7E00 0000 20E9 FF05 FC0C 0000 7E00
BA00 7F00 0000 1FE8 FF05 FB08 0000 7F00
BA00 8000 0000 21E8 FF05 FA04 0000 8000
B900 8100 0000 22E8 FF01 6E10 0000 8100
B900 8200 0000 22E8 FF02 6D2C 0000 8200
B900 8300 0000 22E8 FF03 6C10 0000 8300
B900 8400 0000 22E8 FF04 6B2C 0000 8400

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

Re: SCR decompiler

Post by B-$hep »

You asked what i have figured out. basically the stuff you posted.
I just made simple mis file, compiled and in scr file just looked for command index:
for player_ped its: 3B, level_end 3C. And so on. I started with simpler commands.

Vike posted a table of commands extracted from miss2.exe
So i just used this table to find command index value.

For parameters, i just skipped zero bytes and most of the time i assumed that each parameter is in same order. And most of the stuff is saved in same format.
I changed stuff in scr and looked at the same place again, if something changed there, i wrote it down, that way i figured out the location of current modified parameter in scr

For ex:
Your last piece of dump:

Code: Select all

CHANGE_BLOCK LID (32, 232, 255) NOT_FLAT NOT_FLIP 0 1 255


BA00 7B00 0000 20E8 FF05 FF00 0000 7B00
BA00 is 186 in decimal, so: GOTO line 186 in list and voila.
Image

Indeed, we have CHANGE_BLOCK LID

This way i checked if i got the correct command

I worked a damn one year on that crap, and you assume i don't know nothing about it?
Why i started working on my compiler then, if i wouldn't know anything about it?


I will try to make commands with your hex dumps. maybe it makes things easier.
Always wear safety glasses while programming.
Post Reply