Epic GTA2 Script Decompiler (AKA SCR Decompiler)

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

Re: SCR decompiler

Post by T.M. »

maybe its a checksum
then it should change on every file... so no.


@T.B.: huhut puhuu että oot suomest, ookkos kauanki haksoroinu geeteeaata? :D en oo sua nähny tääl ennen.

--

Edit: I put together the current changes and released full source code, i also added license.txt in it etc. Its using GNU General Public License.
Download:
(see first post)

A lot changes in that version:
- fixed/added/edited some string arrays.
- fixed the offset T.B. talked about.
- fixed some functions to work properly and linked them with similar commands that use identical structs.
- added some functions: DOOR_DATA, SET_STATION_INFO, GENERATOR, LEVELSTART, LEVELEND. etc.
- the output has the raw hex data for those commands that are unknown for the moment.
- fixed some of the command enums to more informative.
- (some) 3d coordinates wont show 255.0 as z-coord anymore, but shows them as 2d coordinates instead.
- made it much easier to add new functions again, everything in one stream of code now :D

Enjoy!
Last edited by T.M. on 22 Nov 2011, 14:42, edited 1 time in total.
T.B.
Jaywalker
Jaywalker
Posts: 7
Joined: 20 Oct 2011, 18:12
GH nick: tnick

Re: SCR decompiler

Post by T.B. »

@T.M. About the smaller .scr files: Mission scripts? Looking at bil_end.scr, the commands seem to start at 0x0C00 and continue to EOF. Last command is 0x0111 MISSIONEND.
However, the pointer table doesn't fit in like in a main script though. Maybe requires some extra math due to how a mission is linked in to the main script, but sorry, I have no info on that.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

Jaksaisitko vastata kysymykseeni? o.o (sen minkä laitoin suomeks...)
T.B.
Jaywalker
Jaywalker
Posts: 7
Joined: 20 Oct 2011, 18:12
GH nick: tnick

Re: SCR decompiler

Post by T.B. »

T.M. wrote:Jaksaisitko vastata kysymykseeni? o.o (sen minkä laitoin suomeks...)
Oon, en.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

I would like to know if anyone has figured out any commands yet. B-$hep ? anything ?

If you are going to figure out something, please tell which commands you are going to figure out, and once you have finished, tell here about it as soon as possible.

Here is the list of commands i have done so far:

Code: Select all

PLAYER_PED = 5 = 0500
CHAR_DEC = 6 = 0600
CHAR_DECSET_2D = 7 = 0700
CHAR_DECSET_3D = 8 = 0800
CAR_DEC = 9 = 0900
CAR_DECSET_2D = 10 = 0A00
CAR_DECSET_3D = 11 = 0B00
OBJ_DEC = 14 = 0E00
OBJ_DECSET_2D = 15 = 0F00
OBJ_DECSET_3D = 16 = 1000
OBJ_DECSET_2D_INT = 17 = 1100
OBJ_DECSET_3D_INT = 18 = 1200
OBJ_DECSET_2D_STR = 19 = 1300
OBJ_DECSET_3D_STR = 20 = 1400
COUNTER = 21 = 1500
ARROW_DEC = 23 = 1700
CONVEYOR_DECSET1 = 26 = 1A00
CONVEYOR_DECSET2 = 27 = 1B00
GENERATOR_DECSET1 = 29 = 1D00
GENERATOR_DECSET2 = 30 = 1E00
GENERATOR_DECSET3 = 31 = 1F00
GENERATOR_DECSET4 = 32 = 2000
DESTRUCTOR_DECSET1 = 34 = 2200
DESTRUCTOR_DECSET2 = 35 = 2300
CRANE_BASIC_DEC = 37 = 2500
CRANE_TARGET_DEC = 38 = 2600
CRUSHER_BASIC = 40 = 2800
CREATE_CHAR_2D = 41 = 2900
CREATE_CHAR_3D = 42 = 2A00
CREATE_CAR_2D = 43 = 2B00
CREATE_CAR_3D = 44 = 2C00
CREATE_CAR_2D_STR = 45 = 2D00
CREATE_CAR_3D_STR = 46 = 2E00
CREATE_OBJ_3D_INT = 49 = 3100
CREATE_OBJ_2D_STR = 52 = 3400
LEVELSTART = 59 = 3B00
LEVELEND = 60 = 3C00
MAP_ZONE_SET = 102 = 6600
EXPLODE = 142 = 8E00
EXPLODE_BUILDING = 143 = 8F00
LOWER_LEVEL = 184 = B800
CHANGE_BLOCK_SIDE = 185 = B900
CHANGE_BLOCK_LID = 186 = BA00
ADD_PATROL_POINT = 205 = CD00
SET_GANG_INFO1 = 223 = DF00
TIMER_DECLARE = 233 = E900
SWITCH_GENERATOR1 = 268 = 0C01
SET_STATION = 285 = 1D01
RADIOSTATION_DEC = 287 = 1F01
CREATE_LIGHT2 = 302 = 2E01
SET_CAR_GRAPHIC = 303 = 2F01
PUT_CAR_ON_TRAILER = 316 = 3C01
SOUND = 326 = 4601
SOUND_DECSET = 327 = 4701
SET_COUNTER_INT = 340 = 5401
PED_GRAPHIC = 364 = 6C01
DOOR_DECLARE_S1 = 375 = 7701
DOOR_DECLARE_S2 = 376 = 7801
DOOR_DECLARE_S3 = 377 = 7901
DOOR_DECLARE_D1 = 378 = 7A01
DOOR_DECLARE_D2 = 379 = 7B01
DOOR_DECLARE_D3 = 380 = 7C01
CREATE_GANG_CAR1 = 394 = 8A01
CREATE_GANG_CAR2 = 395 = 8B01
EXPLODE_LARGE2 = 399 = 8F01
BONUS_DECLARE = 401 = 9101
EXPLODE_SMALL2 = 404 = 9401
EXPLODE_MEDIUM_NO_RING2 = 406 = 9601
ONSCREEN_COUNTER_DEC = 413 = 9D01
PARKED_CAR_DECSET_2D = 425 = A901
PARKED_CAR_DECSET_3D = 426 = AA01
PARKED_CAR_DECSET_2D_ST = 427 = AB01
PARKED_CAR_DECSET_3D_ST = 428 = AC01
DO_CRANE_POWERUP = 439 = B701
Total 74 commands that my decompiler can decompile.
There arent that many functions/structs since many commands can use same function/struct.

I just finished CHANGE_BLOCK, damn that was a bitch to do!
All the settings were bit-packed in nasty way:

Code: Select all

// one of the 16 bit blocks were bit-packed in two different formats:
union SCR_BLOCK_SETTINGS {
	struct {
		Uint16 tile_id:10;
		Uint16 lighting:2;
		Uint16 flat:1;
		Uint16 flip:1;
		Uint16 rot:2;
	} lid;
	struct {
		Uint16 tile_id:10;
		Uint16 wall_type:1;
		Uint16 bullet_type:1;
		Uint16 flat:1;
		Uint16 flip:1;
		Uint16 rot:2;
	} side;
	Uint16 DATA; // in case we need to copy all settings at once.
};
struct SCR_CHANGE_BLOCK {
	SCR_CMD_SHORT_FORMAT(
		Uint16 padding;
		SCR_XYZ_uc pos;
		Uint8 side_or_flat;
		SCR_BLOCK_SETTINGS block;
		Uint16 padding2;
	);
};
string read_CHANGE_BLOCK(FPStruct &params){
	get_data(SCR_CHANGE_BLOCK, data);
	if(params.type == SCRCMD_CHANGE_BLOCK_LID){
		return sprintf_str("CHANGE_BLOCK LID (%s) %s %s %d %s %d", 
			scr_coord(data.pos).c_str(), SCR_BLOCK_FLATTYPES[data.block.lid.flat].c_str(), SCR_BLOCK_FLIPTYPES[data.block.lid.flip].c_str(), 
			data.block.lid.lighting, SCR_ROT_LIST[data.block.lid.rot].c_str(), data.block.lid.tile_id
		);
	}else{
		return sprintf_str("CHANGE_BLOCK SIDE (%s) %s %s %s %s %s %s %d", 
			scr_coord(data.pos).c_str(), SCR_BLOCK_FACES[data.side_or_flat].c_str(), SCR_WALL_TYPES[data.block.side.wall_type].c_str(), 
			SCR_BULLETWALL_TYPES[data.block.side.bullet_type].c_str(), SCR_BLOCK_FLATTYPES[data.block.side.flat].c_str(),
			SCR_BLOCK_FLIPTYPES[data.block.side.flip].c_str(), SCR_ROT_LIST[data.block.side.rot].c_str(), data.block.side.tile_id
		);
	}
}
LinkToFunc(SCRCMD_CHANGE_BLOCK_LID, read_CHANGE_BLOCK);
LinkToFunc(SCRCMD_CHANGE_BLOCK_SIDE, read_CHANGE_BLOCK);
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

ste.scr is building up pretty well now, here is the decompiled .mis:
ste.mis
decompiled ste.scr
(79.38 KiB) Downloaded 850 times
Some screenies from my editor:
Image

Image
Here you can see clearly why this crane powerup thing didnt work: it spawns right on top of destructor!

Image
User avatar
Pyro
Immortal
Posts: 414
Joined: 17 Mar 2010, 04:07
GH nick: Pyro
Location: Wales, UK

Re: SCR decompiler

Post by Pyro »

Very nice indeed!

Quite funny to see an NPC in your first picture that's from the start of STE when Redneck, Zaibatsu and Scientist all fight each other by spawn. :P

As for the Redneck crane bug, wasn't there a fix for that a while ago (think it was from B-$hep)? Not sure if the fixed ste.scr was included with the stripped version of GTA2 on GTAMP site, pretty sure I have the fixed one but not sure if it included the KF car/trailer fix as well (was it ste.scr?).

Either way, excellent progress! STE is my favourite map/city from the official levels and always been curious to know what's inside the SCR, especially how they did Wang Cars (I know how to recreate most of it anyway). Maybe I should do an un-official add-on for BIL so that the 'Foo Cars' garage actually has similar ones to STE :D
User avatar
Sektor
Boss
Boss
Posts: 1423
Joined: 04 Mar 2008, 06:51
GH nick: Sektor
Location: GTAMP.com
Contact:

Re: SCR decompiler

Post by Sektor »

B-$hep did the crane fix on an old ste.scr (9.6 or 9.6f version). Trailer kill frenzy work around was applied to the ste.scr that was included with v10.3. I might be wrong about the versions but I don't have a ste.scr with both fixes.
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 »

So stripped GTA2 still has crane bug in scr?
Or you fixed it?

It would be awesome to see the decompiled script before and after the fix.
If we get so far T.M?
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:It would be awesome to see the decompiled script before and after the fix.
If we get so far T.M?
which file is it actually? i think you fixed the multiplayer script, this is the singleplayer mission script i showed. i cant find fixed version from the script i showed, and all versions i can find from multiplayer script looks like working correctly :/ where can i find the original gta2 map scripts?
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

I added the last missing commands to finish the multiplayer map Residential (res-6p.scr) decompiling completely !

Except there is some weird "RETURN" code in end... dunno wtf is it doing there. perhaps some empty function...

Download:
res6p_dec.mis
Residential map decompiled completely
(21.78 KiB) Downloaded 814 times
i tried compiling that .mis file and it resulted almost identical to res-6p.scr: only that return command is missing, which probably isnt doing anything anyways. you can also see some random bytes added there :S i noticed the "crazy" first pointer data also changes, maybe it has something to do with the other random crap that changed. ive tested before and its possible to actually fill in some of the random crap any data you want without affecting anything at all. so maybe its something like uninitialized memory ?
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

Im trying to figure out the mission .scr format, i think i made some progress: the first 2 bytes seem to describe the amount of pointers from the base-scr file, for example bil.scr has 1129 total pointers used, and the first value in each of the "data/bil/" folder .scr files is exactly 1129! I also found out that the pointers block size is only 3080 bytes in the mission scripts whereas its 12000 in the bil.scr.

So i think it works just by copy/paste: missions provide pointers which could point either the base-script or its own script, and in the end those two scripts are just merged into one big script so all the pointers will work perfectly. I havent tested this idea yet, gonna test later.

I think this also unveils the mystery of first pointer: zero might mean "this is base file" or etc.
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

I thought of converting the hex strings into binary strings from the zero pointer values:

Code: Select all

011101110000000010010111101111010100000000000000 = wil.SCR
000100100000000011101000111101000001001000000000 = naglez_map6p.SCR
000100100000000011010100111101000001001000000000 = scrtest1 – Kopio.SCR
000100100000000001111000111101000001001000000000 = zooka_arena5-6.SCR
000100100000000001100000111101000001001000000000 = wsrace.scr
000000000000000011111000111111010001001000000000 = rob-3p.scr
000000000000000011101000111111010010001000000000 = naglez_map2p.SCR
000000000000000011101000111111010001001100000000 = VenericIsle.SCR
000000000000000011101000111111010001001000000000 = zombie.SCR
000000000000000011010100111101000001100000000000 = tytyty.SCR
000000000000000011001000111110110111110000000000 = super2.SCR
000000000000000011000100111110110111110000000000 = trains.SCR
000000000000000010010000111111010001001000000000 = uk_Intro London NEW_1.SCR
000000000000000010000100111111010001001100000000 = ptb.SCR
000000000000000010000100111111010001001000000000 = ztest.SCR
000000000000000001100000111111010001001000000000 = jailbreak.scr
000000000000000001001000111101000001011100000000 = 57thDV.SCR
000000000000000000010000111110110111111000000000 = zaibatsu_city.SCR
There is definitely some pattern, i think its just boolean list of settings or something like that! Or it could also be its just garbage data from uninitialized memory... hard to say.

edit: noticed that the nullpointer 8byte garbage is injected into the 5120 byte stream everywhere, but slightly different (last 2 bytes doesnt seem to match). i have no idea what that all means... it still could be a sign of uninitialized memory.

For example the nullpointer in some map has the bytes:
40FD 1200 60F4 1200
and the last 8 bytes from the file are:
40FD 1200 1101 0000

and those bytes at end of file are repeated lots of times in the 5120 bytes stream in end of file.
User avatar
elypter
Immortal
Posts: 1120
Joined: 26 Dec 2009, 23:53
GH nick: elypter

Re: SCR decompiler

Post by elypter »

the complete decompiler should also output the garbage bytes. because it can contain personal information you maybe want to check whats in the scr before uploading somewhere.
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. »

thats more like a compiler job to do.

anyways, i think i can write a program that will clean all the garbage bytes into zeroes, i havent tested it fully yet, but i think its possible, i already found out that the 5120 bytes in end of file can be cut as big as the string array containing zonenames etc. and if theres no zonenames used in script then the array must be minimum of 4 bytes of nulls. although.. as i said i havent tested this completely, but it looks very promising.
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 want to remove that garbage at the end of scr completely?
Is this what you meant?

Removing that garbage for example from bil.scr just crashes the game.
So GTA2 needs it. Dunno why.
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:Removing that garbage for example from bil.scr just crashes the game.
So GTA2 needs it. Dunno why.
thats because it has the strings array there. i figured out the format and my decompiler parses that array (check from my sources how), and if you remove everything after that array ends, it should work just fine! i just tested it and no crashes! this also raises new hope of actually storing all the variable names directly into SCR file so we can decompile it perfectly later. perhaps even code comments LOL. i gotta test if i can extend that strings array to maximum length of 65k bytes, that should be more than enough for variable names in any map ^^
User avatar
Vike the Hube
Hitman
Hitman
Posts: 145
Joined: 28 Feb 2010, 22:34
GH nick: vike

Re: SCR decompiler

Post by Vike the Hube »

T.M. wrote:so maybe its something like uninitialized memory ?
Yeah I said a while ago that's probably what it is. The actual variables. Most variables don't need an initial value so they don't have one.
T.M. wrote:I think this also unveils the mystery of first pointer: zero might mean "this is base file" or etc.
Excellent, I can stop work ;-) I was hunting through miss2.exe to find out what it is. But does that cover the cases you list in that first post? (7700 = wil.SCR, 1200 = naglez_map6p.SCR, 1200 = scrtest1 – Kopio.SCR, 1200 = zooka_arena5-6.SCR, 1200 = wsrace.scr)

I can tell you what the next 4 bytes after that first pointer are: garbage. There's a buffer overrun in the code that writes the first command to the .scr, and that value is actually an address of a variable on the stack. Which is why it changes all the time, but also why sometimes it's the same :lol:
User avatar
T.M.
Immortal
Posts: 960
Joined: 29 Jan 2010, 15:00
Location: F21B3EED

Re: SCR decompiler

Post by T.M. »

Vike the Hube wrote:But does that cover the cases you list in that first post? (7700 = wil.SCR, 1200 = naglez_map6p.SCR, 1200 = scrtest1 – Kopio.SCR, 1200 = zooka_arena5-6.SCR, 1200 = wsrace.scr)
I meant the first value (=first pointer) in the .scr file (2 bytes) tells you if its a mission(>0) or base-script(==0). and if its a mission, it tells you how many pointers the base-script has.
Vike the Hube wrote:I can tell you what the next 4 bytes after that first pointer are: garbage. There's a buffer overrun in the code that writes the first command to the .scr, and that value is actually an address of a variable on the stack. Which is why it changes all the time, but also why sometimes it's the same :lol:
how did you find out this? nevertheless, im happy to hear the mystery is solved :-)

--

Edit: 145 commands done now. tomorrow i will do around 135 more commands (very simple ones) and then i think its pretty much done, and then i or someone else can take a look at the mysteries of the if/else structures. perhaps you Vike can take a look :D ? Here is the dafes map again (its so good example map, lots of commands) decompiled .scr and original .mis:
dafesmap_orig.mis
original .mis file
(134.09 KiB) Downloaded 811 times
dafesmap_decompiled.mis
decompiled .scr file
(136.21 KiB) Downloaded 788 times
Last edited by T.M. on 23 Oct 2011, 01:26, edited 1 time in total.
User avatar
Vike the Hube
Hitman
Hitman
Posts: 145
Joined: 28 Feb 2010, 22:34
GH nick: vike

Re: SCR decompiler

Post by Vike the Hube »

T.M. wrote:I meant the first value (=first pointer) in the .scr file (2 bytes) tells you if its a mission(>0) or base-script(==0). and if its a mission, it tells you how many pointers the base-script has.
Ah, fair enough. I guess the first two bytes of still have a purpose then though... will have to look into it.
T.M. wrote:how did you find out this? nevertheless, im happy to hear the mystery is solved :-)
Debugging miss2.exe:
1. Check out file functions it uses... looks like C fopen etc. Locate calls to fopen. Breakpoint, wait till it opens .scr.
2. Get rid of fopen breakpoints and set one on fwrite.
3. Wait till it writes those bytes, then set a hardware on-write breakpoint on the array they come from, restart.
4. It breaks on a memcpy call with n=8, even though the function that calls memcpy only gets one 32-bit parameter passed in ;-)
Post Reply