Sign in to follow this  
Followers 0
mikew

Interpretation of SSD files

101 posts in this topic

Let's start a thread to define a method of dealing with these things. Hopefully things will become clearer with a methodical approach.

Step 1 will be to read the first 10 bytes (Block1), which according to current knowledge gives the following information:

Byte 0 = Size of local variable block

Byte 1 = Number of shapes

Bytes 2 & 3 = Currently unknown, but would appear to be connected as one word

Byte 4 = Currently unknown, but could help in defining ssd type

Byte 5 = Currently unknown, but always in range 0-3 for TFX2 and 28-31 for TFX3, so can be used to differentiate them.

Bytes 6 & 7 = always has value 0xFFFF

Byte 8 = Number of 'Actions'---more later

Byte 9 = Number of shape coordinates with 6 bytes per coordinate.

To be continued...

Share this post


Link to post
Share on other sites

Note that TFX2 and TFX3 differ in that there is a 100 byte block (Block2) in TFX3's all SSD files which is missing for TFX2. This affects the next step of calculating the base address for the block of pointers (which we'll call Block4) defining a 'Bytecode' section, where all actions are performed.

After Block2 will come a list of coordinates (Block3) if Byte 9 of Block1 is non-zero.

So, for TFX2, Block4 will start at offset

10+6*(*Block1_byte9)

...and for TFX3,

110+6*(*Block1_byte9)

When the supershape is 'addressed' in the game, this number will act as the base address.

Share this post


Link to post
Share on other sites

The next step will be to inspect the last word in the file. If this is non-zero then there will be a list of pointers giving information about the supershape. This pointer list is located at the end of the file and each entry consists of 2 words. The first giving an index to the file ssinfo.lab (giving a tag of what the data contains),and the second the offset to this data in the SSD file.

For TFX3, ssinfo.lab contains the following tags. I'll (eventually) add the expected length of each data section in order to make reading easier.

I need to work out how to format this table since this site software is crap and deletes my tabs... :(


Tag               Index       Size (Bytes)

-------------------------------------------

0                   0

COLLISION_BOXES     1           Not fully understood---will deal with this later.

LOCAL_GLOBALS       2           2

VIEW_DIST           3           2

NB_SMOKE            4           2

SMOKE_INFO          5     	8 * NB_SMOKE

SMOKE0_VAL          6           2

SMOKE1_VAL          7           2

SMOKE2_VAL          8           2

SMOKE3_VAL          9           2

SMOKE4_VAL          10          2

SFXFLAGS            11          2

SFXFREQS            12          2

SFXPOS              13          2

SFXINFO             14    	First 2 bytes give number of entries, then 18 bytes per entry

PYLONS              15    	6 bytes per pylon, nut not sure where number of pylons comes from

COLS_CAM1           16    	10

COLLISION_TRIANGLES 17          First 2 bytes give number of triangles, then 74 bytes per triangle

TERRAIN 	    18          2

WATER               19          2

CLOUD_BOXES         20    	Not fully understood---will deal with this later. 

TARGET_AREA_DATA    21          4

TARGETS             22          20 * second word of TARGET_AREA_DATA

NB_ROUTES           23          2

ROUTES              24    	NB_ROUTES *(14+4*(last word of 14 byte block))

CENTRE_GRAVITY      25          6

SMOKE5_VAL          26          2

SMOKE6_VAL          27          2

SMOKE7_VAL          28          2

SMOKE8_VAL          29          2

BOMB_BAY_VAL        30          2

SFXVOLS             31          2

CAMERA_NUMBERS      32          2

CAMERA_POS          33          6

FLYBY               34          Never used

ENGINES             35    	2

AIRFIELD_TYPE       36          ASCII Cstring

AIRFIELD_ALTITUDE   37		2

TURRET_NUM          38		2

TURRET_LAUNCH_POS   39    	18 * TURRET_NUM

ROTATION_SEM        40		2

RELOAD              41		2

MOBILE_CAPACITY     42		2

CANOPY_VAL          43		2

Oh, I ######ing give up. This site SW must have been written by SAP. :angry:

I'll fill in the table later and supply a screenshot.

...and here it is:

ssinfo_lab_zps06876b88.png

Share this post


Link to post
Share on other sites

When we want to create an ingame object, we need to run the initiation part of the bytecode by addressing pointer 0 of Block4.

This takes us to Block5, which is a list of indices of shapes used in the supershape. This block starts with 0x7a00 and ends with 0xffff.

The shape index maps to the file ssinfo.fn.

(Note that in TFX2, this is not quite true, especially for vehicles---further investigation required)

Next comes Block6, which adds information about the scale and rotation of each shape in the supershape. The shape index is also in this block, so Block5 could be ignored.

In Block 6, entries come in one of two forms, either 14 or 6 bytes:


05000700df0401000000a5ef0000; Object 7 Scale 1 Rot X 0.0 Rot Y -23.0 Rot Z 0.0  ROOF_180.3

03000800d504; Object 8  CYLINDRI.3

The second byte of Block1 gives the number of shapes in Blocks 5 & 6, although this shouldn't be used to calculate the size of these blocks as in c17.ssd, the same object is described twice.

Share this post


Link to post
Share on other sites

The contents of Block7 depend on the supershape 'type'. Here local variables or state are set up.

For simpler objects this block is empty except for a jump to where data used to address the COLLISION_BOX system is located.

The destination of this jump can also be reached from the last pointer of Block4. The significance of this is not yet known.

That's it for the general stuff!

The rest of the SSD files contain various 'actions' that can be triggered by supplying the appropriate Block4 pointer. Which actions are relevant depends on the type of supershape.

Share this post


Link to post
Share on other sites

Hmmn, I've just reread what I wrote on saturday, and I guess it doesn't make much sense. All that was posted after numerous pints of european lager though.

So, after even more lager (Becks), we continue...

Applying the above theory to the file 'ZSU_23_4.SSD' works perfectly..at least to the point where we 'initialize' the object we invoking 'Action code 0'

This is the prototype script (which needs expanding for other opcodes)


import os

testfile='zsu_23_4.ssd'

command=104


if os.name=='posix':

didpath= "./"

dirss=os.listdir(didpath+"ss") #dirss=list of files in 'ss' folder

sspath='./ss/'

txtsspath='./txtss/'

utilpath='./util/'

metapath='./meta/'

else:

didpath= ".\\"

dirss=os.listdir(didpath+"ss") #dirss=list of files in 'ss' folder

sspath='.\\ss\\'

txtsspath='.\\txtss\\'

utilpath='.\\util\\'

metapath='.\\meta\\'



#Get ssinfo.lab

input=file(sspath+"ssinfo.lab","r")

sslabraw=input.readlines()

lab_names=[]

for line in sslabraw:

sline=line.split()

lab_names.append(sline[0])

#Get ssinfo.fn

input=file(sspath+"ssinfo.fn","r")

ssinforaw=input.readlines()

fn_names=[]

for line in ssinforaw:

sline=line.split()

sline1=sline[0]

sline1=sline1[1:len(sline1)-1]

fn_names.append(sline1)

get_rid_of_first_item=fn_names.pop(0)

#input=file(sspath+dirss[index],"rb")

input=file(sspath+testfile,"rb")

raw=input.read()

rawlen=len(raw)

outfile=file(metapath+testfile+"_meta.txt","w")

outfile.write("File :"+testfile+"\n")

outfile.write("Size :"+str(rawlen)+"\n")

#Read in Block1 info and interpret

locals_size=ord(raw[0])

e=0

locals=[]

while e<locals_size/2:

locals.append(0)

e+=1

num_shapes=ord(raw[1])

e=0

shapes=[]

while e<num_shapes:

shapes.append('SOMESHAPE')

e+=1

block1_23= ord(raw[2])+256*ord(raw[3])

block1_4=ord(raw[4])

block1_5=ord(raw[5])

num_actions=ord(raw[8])

num_coord=ord(raw[9])

if block1_5>3:

game_type='TFX3'

action_base=110+6*num_coord

else:

game_type='TFX2'

action_base=10+6*num_coord


outfile.write("Game ;"+game_type+"\n\n")


#This reads the information at the end of the file which gives the number of entries (num_lab) from ssinfo.lab

#The last 2 bytes give the number of properties which defines the block above, which will start at lab_base

#In turn this block contains 4 bytes for each property, 2 for the enum of the property and 2 for the offset from the start of the ssd file.

lab_list=[]

num_lab=ord(raw[rawlen-2])+ord(raw[rawlen-1])*256

lab_base=rawlen-((num_lab*4)+2)

if num_lab==0: #helps later on if there is no lab list

lab_base=rawlen

#We then create a list of the property indices and offsets

e=0

while e<num_lab*4:

lind=ord(raw[lab_base+e])+ord(raw[lab_base+e+1])*256

loff=ord(raw[lab_base+e+2])+ord(raw[lab_base+e+3])*256

lab_list.append((lind,loff))

e+=4	


#Now work through the list

e=0

outfile.write("Entries used from ssinfo.lab :"+"\n\n")

while e<num_lab:

labcode,labadd=lab_list[e]

comment=""

if labcode==1:

	 comment="Starts at Offset : "

	 outfile.write(lab_names[labcode]+"\t"+comment+str(labadd)+"\n")	

elif labcode==2:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (Variable bytes) at address : "+hex(data1)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")									

elif labcode==3:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Distance used by Smartview (and maybe elsewhere) : "+hex(data1)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")			

elif labcode==4:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Number of entries in SMOKE_INFO list : "+hex(data1)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")								

elif labcode==5:

	 comment="Starts at Offset : "

	 outfile.write(lab_names[labcode]+"\t"+comment+str(labadd)+"\n")		

elif labcode==6:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (2 bytes) at address : "+hex(data1*2)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")		

elif labcode==7:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (2 bytes) at address : "+hex(data1*2)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")		

elif labcode==8:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (2 bytes) at address : "+hex(data1*2)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")						

elif labcode==9:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (2 bytes) at address : "+hex(data1*2)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")		

elif labcode==10:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")					

elif labcode==11:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (6 bytes) at address : "+hex(data1*2)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")		

elif labcode==12:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (4 bytes) at address : "+hex(data1*2)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")							

elif labcode==13:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==14:

	 comment="Starts at Offset : "

	 outfile.write(lab_names[labcode]+"\t\t"+comment+str(labadd)+"\n")							

elif labcode==15:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==16:

		 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")				

elif labcode==17:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")	

elif labcode==18:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")						

elif labcode==19:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==20:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")					

elif labcode==21:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==22:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")						

elif labcode==23:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==24:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")					

elif labcode==25:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==26:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")						

elif labcode==27:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==28:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")					

elif labcode==29:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==30:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")						

elif labcode==31:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==32:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")					

elif labcode==33:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==34:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")						

elif labcode==35:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==36:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")					

elif labcode==37:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==38:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Number of Turrets : "+hex(data1)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")											

elif labcode==39:

	 comment="Starts at Offset : "

	 outfile.write(lab_names[labcode]+"\t"+comment+str(labadd)+"\n")		

elif labcode==40:

	 data1=ord(raw[labadd])+ord(raw[labadd+1])*256

	 comment="Local Variable (6 bytes) at address : "+hex(data1*2)

	 outfile.write(lab_names[labcode]+"\t"+comment+"\n")							

elif labcode==41:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")

elif labcode==42:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")						

elif labcode==43:

	 outfile.write(lab_names[labcode]+"\t"+str(labadd)+"\n")		

else:

	 pass		


e+=1


#Run 'setup' action 0

command=0

command=command*2

action_ind=(ord(raw[command+action_base])+256*ord(raw[command+action_base+1]))*2 +action_base+command

action_done=0

while action_done!=1:

codei=ord(raw[action_ind])+ord(raw[action_ind+1])*256

code=hex(codei)

code=code[2:]

action_ind+=2


if code=='7a': #Deal with Block5 and ignore it for now

	 flag_7a=0

	 while flag_7a!=1:	

		 data=ord(raw[action_ind])+ord(raw[action_ind+1])*256

		 action_ind+=2

		 if data==65535:

			 flag_7a=1


elif code=='3':

	 data1=ord(raw[action_ind])+ord(raw[action_ind+1])*256	

	 data2=ord(raw[action_ind+2])+ord(raw[action_ind+3])*256

	 shapes[data1]=fn_names[data2]

	 action_ind+=4

elif code=='b':

	 data1=ord(raw[action_ind])+ord(raw[action_ind+1])*256	

	 data2=ord(raw[action_ind+2])+ord(raw[action_ind+3])*256

	 locals[data1]=data2

	 action_ind+=4

elif code=='a':

	 data1=ord(raw[action_ind])+ord(raw[action_ind+1])*256	

	 data2=ord(raw[action_ind+2])+ord(raw[action_ind+3])*256

	 action_ind+=4		

	 e=0

	 while e<data2:

		 data=ord(raw[action_ind])+ord(raw[action_ind+1])*256

		 locals[data1]=data

		 data1+=1

		 action_ind+=2

		 e+=1

elif code=='7c':

	 data1=ord(raw[action_ind])+ord(raw[action_ind+1])*256	

	 data2=ord(raw[action_ind+2])+ord(raw[action_ind+3])*256

	 data3=ord(raw[action_ind+4])+ord(raw[action_ind+5])*256		

	 locals[data1]=data2

	 locals[data1+1]=data3	

	 action_ind+=6	

elif code=='1':	

	 data1=ord(raw[action_ind])+ord(raw[action_ind+1])*256

	 action_ind+=data1*2


elif code=='0':

	 action_done=1


else:

	 action_done=1

	 print 'unhandled opcode',code


outfile.write("\n\nShape list contains :\n\n")

e=0

while e <len(shapes):

outfile.write(shapes[e]+"\n")

e+=1

outfile.close

For the ZSU, this produces a file:

File :zsu_23_4.ssd

Size :1740

Game ;TFX3

Entries used from ssinfo.lab :

COLLISION_BOXES Starts at Offset : 1482

VIEW_DIST Distance used by Smartview (and maybe elsewhere) : 0xa

NB_SMOKE Number of entries in SMOKE_INFO list : 0x3

SMOKE_INFO Starts at Offset : 1604

SMOKE0_VAL Local Variable (2 bytes) at address : 0x0

SMOKE1_VAL Local Variable (2 bytes) at address : 0x2

SMOKE2_VAL Local Variable (2 bytes) at address : 0x4

SFXFLAGS Local Variable (6 bytes) at address : 0x6

SFXFREQS Local Variable (4 bytes) at address : 0xc

SFXINFO Starts at Offset : 1640

TURRET_NUM Number of Turrets : 0x1

TURRET_LAUNCH_POS Starts at Offset : 1584

ROTATION_SEM Local Variable (6 bytes) at address : 0xc


Shape list contains :

ZSU_23_4

I can probably produce a general script to 'initialize' each ssd file, but to deal with individual actions, eg extending landing gear, will require some specialisation.

EDIT:

Please treat the script as pseudo-code. It won't run as a Python script as the site has shagged the formatting.

Share this post


Link to post
Share on other sites

I can probably produce a general script to 'initialize' each ssd file

That's not quite true, as there are some 'actions' set up in the initiation process in what we call Block7. So, we have to deal with these sooner rather than later.

For example, in this ship model, the wake is set up to simulate movement:

From oliver.ssd

1a00 Manipulate Parameter 0006 of shape

0100 Shape = IB_WAKE.3

0600 Number of words following in 'action'

000001000308feff0500

....and in this airbase, the windsock moves up and down.

gen_1rwy.ssd

1400 Manipulate Parameter 0000 of shape

1100 Shape = AWIND.3

2400 Number of words following in 'action'

0000000100020003000400050005000500050005

0005000500050005000400030002000100000000

0000000000000000000000000000000000000000

0000000000000400deff

At least in the second example, the bytecode can be interpreted as change parameter 0000 of awind.3 from value 0->1->2 etc until we reach the 0400 which may mean repeat with a jump backwards of deff (-34) words.

What's interesting is the mix of big-endian and little-endian words. I've done some trial and error measurements, and these types of actions run at a fixed speed of about 60ms per step, giving about 2 seconds per windsock cycle.

I do not yet have a theory of how to interpret the bytecode in the first wake example...

Any ideas? I believe the 3View program already implements this in some way...

Share this post


Link to post
Share on other sites
I do not yet have a theory of how to interpret the bytecode in the first wake example...

Any ideas? I believe the 3View program already implements this in some way...

No; 3View does not yet do anything with supershape bytecode. In fact, I didn't even know for certain which block the bytecode is in until you mentioned it in this thread ...

Share this post


Link to post
Share on other sites

Unfortunately, I can't run 3view just now to check but it may have been the broken dam spray that I was thinking about, which is definitely animated.

I assume you've come up with your own solution, as I don't think there are opcodes in the .3 files to control self-animation.

From the dam_1.ssd file, the spray animation looks like it is controlled from this sequence of bytecode:

1b00 = Manipulate Parameter 0007 of shape

0000

0b00

000307001100000300030004010003e2feff0500

This is part of the 'collision' process though, rather than supershape initialization, so I was going to worry about it later.

Share this post


Link to post
Share on other sites

The animation is realized via the 0077 shape opcode. It pushes a transformation matrix for a sprite onto the transformation stack, which is slightly randomized frame to frame, so the particles look like shaking water waves (or like explosions, that's what TFX2 uses the opcode for).

I didn't get any instructions from the supershape to do so. However, there is scratch space in the opcode ---- it might be possible the supershape bytecode writes down some transformation numbers there. Consider, however, that this effect is only visible in software mode ---- Glide or Direct3D will show static waves only! That's why I'm pretty sure this is implemented in the renderer (i.e., in the shape interpreter) rather than in the supershape's bytecode.

Share this post


Link to post
Share on other sites

Sounds plausible.

...and I selected that part of the dam_1.ssd code since it is the only place where what looks like a repeating animation is defined, so it must control the spray. Maybe an assumption too far...

There are some ssd files where there are 'actions' that the associated shape looks like it cannot possibly perform, so there may not be a 1:1 relationship between supershape actions and shape response.

I'm getting sidetracked a bit now. I should just determine the opcode lengths at this stage, and jump over them.

Share this post


Link to post
Share on other sites

...and total success for TAW's SSD files. :)

All of them follow the 'new' rules.

Not so good with the TFX2 files though. While lots of them are fine, there are many that just seem malformed and I'd rather prove that they are actually used before dealing with them.

The next step, I think, is to define the different categories of files....

Share this post


Link to post
Share on other sites

Well, before categorizing the files, I've tried running through each file with every 'action code' and handling every opcode as they are encountered. The handling right now only consists of noting the length of the command string and jumping to next opcode.

Anyway, with one exception, the code always encountered a closing 0000, and exited gracefully.

The exception is dam_2.ssd, where for a nomal terrain tile 'Action code 2' usually points to a 0000 and returns, a bit like a NOP.

In dam_2 this 0000 is missing, so the bytecode engine tries to run the COLLISION_BOX data.

These are the opcodes encountered so far, with some conjecture.


0000 Return


0100 Jump (only used in Block7)

0300 Handle shape (Block6 only)

0500 Handle shape with parameters (Block6 only)

0700 Load shape into some list? (only used for Action code 1?)

0800 Load shape with coordinates (only used for Action code 1?)

0a00 Write multiple Local State words

0b00 Write a Local State word

1300 ?? (only used in Block7 aircraft SSDs)


1400 Manipulate Shape parameter 0

1500 Manipulate Shape parameter 1

1600 Manipulate Shape parameter 2

1700 Manipulate Shape parameter 3

1800 Manipulate Shape parameter 4

1900 Manipulate Shape parameter 5

1a00 Manipulate Shape parameter 6

1b00 Manipulate Shape parameter 7


2500 Decision (Jump if Local state variable = )

3a00 Decision (Jump if Local state variable > )

3c00 Similar to 0700 (maybe for non-player planes)

5300 ??

5b00 ??

6b00 Similar to 0800 (maybe for non-player planes)

7c00 Load 2 Local State words, sound related.

8300 Turn sound on (continuous like engines)

8400 Turn sound off

8500 Play sound (one-off like explosion)


8600 Manipulate Shape parameter 8 (F22 only)

8700 Manipulate Shape parameter 9 (F22 only)

8800 Manipulate Shape parameter 10 (F22 only)

8900 Manipulate Shape parameter 11 (F22 only)

8a00 Manipulate Shape parameter 12 (F22 only)

8b00 Manipulate Shape parameter 13 (F22 only)

8c00 Manipulate Shape parameter 14 (F22 only)

9000 Manipulate Shape parameter 15 (F22 only)

9100 Manipulate Shape parameter 16 (F22 only)

9200 Manipulate Shape parameter 17 (F22 only)

9300 Manipulate Shape parameter 18 (F22 only)

There is another level of bytecode triggered by some of those opcodes, where opcode 0700, for example, has a completely different function.

We can deal with that when we decode the individual actions.

Share this post


Link to post
Share on other sites

The block of code triggered by 'Action code 1' is also common to all ssd files, and would seem to produce a list of shapes. I guess this is for the benefit of the renderer.

The shape index is loaded with opcodes 0700 or 3c00 if the shape is located at the origin, and opcodes 0800 and 6b00 are used if the shape is not at the origin, in which case an index to the coordinate (Block3) is added. These opcodes are only used in this process (Action 1).

I have no idea what determines whether 0700/0800 are used instead of 3c00/6b00

...and in TFX2, 7e00 is used instead of 6b00.

For airplane models, some decision is made (maybe based on damage) about which shapes to load, and I think the logic is as follows:


01: 3a000c0000000500 ;If local state value at 0x0c != 0 then jump 5 words (line 04)

02: 07000000

03: 3c000000

04: 3a000c0001001900 ;If local state value at 0x0c != 1 then jump 0x19 words (line 15)

05: 07000000

06: 6b0002000000

07: 6b0003000000

08: 6b0004000000

09: 6b0005000000

10: 07000600

11: 07000700

12: 07000800

13: 07000900

14: 3c000000

15: 3a000c0002001900 ;If local state value at 0x0c != 2 then jump 0x19 words (line 26)

16: 07000000

17: 6b0002000000

18: 6b0003000000

19: 6b0004000000

20: 6b0005000000

21: 07000600

22: 07000700

23: 07000800

24: 07000900

25: 3c000000

26: 3a000c0003000700 ;If local state value at 0x0c != 3 then jump 7 words (line 30)

27: 07000000

28: 07000100

29: 3c000000

30: 0000
Note that for this to work, 3a00 must mean 'not equal to' instead of 'greater than' which I indicated earlier, otherwise we'd never get to the terminating 0000. For F22.ssd, which is the only place the 2500 opcode is found, things are more obvious...

2500400000003500 ; If local state value at 0x40 = 0 then jump 0x35 words
...which will lead to a block like this, where each block has a terminating 0000:

07000300

07001400

07001700

07001100

3c001400

3c001700

3c001100

0000

Here, the criteria is not damage, but which model to use (USA1/USA2/SAUDI/EGYPT) etc.

Share this post


Link to post
Share on other sites

Well, that's about all we need to know to deal with terrain tiles. In TFX3 these come in two types, those with 4 actions and those with 7.

So, for if the 9th byte of Block1=4, the actions are as follows.

0 Initialize

1 Create shape list

2 Do nothing

3 Set up collision box pointers (will be clarified later when actually needed)

if 9th byte of Block1=7:

0 Initialize

1 Create shape list

2 Do nothing

3 Set detail=1 (which is the most detailed? I'm not sure without checking the shape file)

4 Set detail=2

5 Set detail=3

6 Set up collision box pointers

EDIT:

A bit more information is needed about that detail level, so here's an example:


;Block4_Pointer_3 Starts 1266 Length.42

14000000030000020500

14000200030000020500

14001f00030000020500

14002000030000020500

0000


;Block4_Pointer_4 Starts 1308 Length.42

14000000030000010500

14000200030000010500

14001f00030000010500

14002000030000010500

0000


;Block4_Pointer_5 Starts 1350 Length.42

14000000030000000500

14000200030000000500

14001f00030000000500

14002000030000000500

0000

So, if we want 'Action code 3', we interpret the bytecode as follows:

1400 XXXX 0300 YYYY 0500

where XXXX= shape index, in this case 0,2,1f & 20 (little endian)

and YYYY=parameter operand for shape file, in this case 2. (big endian)

...and opcode 1400 means that it's Parameter 0 of the shapes are we are manipulating.

Share this post


Link to post
Share on other sites

Now, we need to understand the bytecode sequences that are model specific. For aircraft, 'Action Code 3' always extends the landing gear with the most complicated example being the F22.

Here's the whole sequence.


;Block4_Pointer_3 Starts 1968 Length.426

140000000c0000000001000200030004000500060007000800090500

140004000c0000000001000200030004000500060007000800090500

140005000c0000000001000200030004000500060007000800090500

140006000c0000000001000200030004000500060007000800090500

14000f000c0000000001000200030004000500060007000800090500

140010000c0000000001000200030004000500060007000800090500

140011000c0000000001000200030004000500060007000800090500

140012000c0000000001000200030004000500060007000800090500

140013000c0000000001000200030004000500060007000800090500

140014000c0000000001000200030004000500060007000800090500

140015000c0000000001000200030004000500060007000800090500

140016000c0000000001000200030004000500060007000800090500

140017000c0000000001000200030004000500060007000800090500

14002a000e000700100000000001000200030004000500060007000800090500

0b003f000100

0000

8500290000000200a0000a006400000001000000

0000
The model indices in the sequence, we know from Block6:

0000 Object 0 F22USA1

0400 Object 4 F22USA2

0500 Object 5 F22SAUDI

0600 Object 6 F22EGYPT

0f00 Object 15 F22S1US1

1000 Object 16 F22CLUS1

1100 Object 17 F22SIMP2

1200 Object 18 F22S1US2

1300 Object 19 F22S1SAU

1400 Object 20 F22S1EGY

1500 Object 21 F22CLUS2

1600 Object 22 F22CLSAU

1700 Object 23 F22CLEGY

2a00 Object 42 SOUND

Note, that only a few of these models would be 'in use' at any one time (defined in Action 1), so this should be taken into account by the bytecode engine.

So, first we need to deal with the first 1400 opcode:

140000000c0000000001000200030004000500060007000800090500 , which I interpret as:

1400 Shape parameter 0000 will be manipulated

0000 Shape 0000 (in this case F22USA1)

0C00 Number of words in this sequence (including the 0c00) and Start some clock

Now, send update Parameter 0000 of F22USA to value ->0->1->2->3->4->5->6->7->8->9 at roughly 60ms per step.

0500 Stop the clock and end sequence.

Once we've started this action we can't wait for it to finish,it needs to be autonomous so we can carry on down the list.

We should eventually get to the line dealing with sound.3:

14002a000e000700100000000001000200030004000500060007000800090500

This appears to act as some 'virtual' shape as although sound.3 exists, it doesn't contain much, and the 0-9 sequence is meaningless in terms of visible effect but may act as a delay to ensure the sound effect plays correctly.

The sound is ordered by the 8500 opcode, with the number immediately following giving the sound effect index number (2900 = fx040.wav). I have no idea yet what the the rest of the 8500 line does.

In this case, the 8500 is a subroutine called from the last 1400 line. Immediately after the length 0e00 word, is the GOSUB command (0700) and we're jumping 0x1000 or 16 words. After kicking off the sound, we immediately return, where the next word which is the start of to 0->9 sequence.

Finally, we have the line:

0b003f000100

...which updates the local state, where address 0x3f is set to 1.

We then reach the final 0000, so we're done. :)

Anyway, that's one of the easier Actions to understand....

Share this post


Link to post
Share on other sites
Next comes Block6, which adds information about the scale and rotation of each shape in the supershape. The shape index is also in this block, so Block5 could be ignored.
I used block 5 indices at the very beginning of 3View, and if I remember correctly, this yielded wrong results. (I guess some airfields looked wrong with block 5 shape indices, but this could also have been a bug in my code.) I'm using block 6 indices since then.

I just checked, and indeed blocks 5 & 6 are identical. My bad.

The second byte of Block1 gives the number of shapes in Blocks 5 & 6, although this shouldn't be used to calculate the size of these blocks as in c17.ssd, the same object is described twice.
This is valuable; thank you.

Share this post


Link to post
Share on other sites

Some do, some don't. Whether that's because a lot of the TFX2 files are malformed, I don't know.

There appears to be a lot of junk TFX2 ssd files, (as there is with the .3 files). Of course, there may be some obfuscation process at work, but I doubt it.

I did some tests on zsu_23_4.ssd by modifying some bytes, then looking at the result in the game with the following results:

1. Modifying the Block5 index did not have any visible effect, but the Block6 index did.

2. Changing the starting value of the 'SMOKE' local values did not result in a smoking ZSU on startup. I get the impression that those starting values are for the benefit of a design tool rather than the game itself.

Share this post


Link to post
Share on other sites

I see. Some TFX2 shapes do have a block 5 (e.g. 737), others don't (e.g. 707_vip).

First of all: The general structure seems to work, even for some TFX2 supershapes. This is ss\09_rway1.ssd, the first TFX2 supershape I ever displayed:

ef20k09rway1ssd.png

However, I think the ssinfo.fn indices are completely f***ed up. Mountains and towns of different kinds, even clouds, are scattered all over the landscape, and how else could one explain that there are planes of different scale factors appearing in ss\36_rway1.ssd?

tfx236rway1ssd.png

(This looked like an Ekranoplan first.)

I think this is way easier to debug for me since I have direct visual feedback, so I suppose I should have a look at those issues.

Share this post


Link to post
Share on other sites

Just to clarify my last post, the ZSU_23_4 tests were done in TFX3.

Yes, some of the ssinfo.fn indices in TFX2 are completely 'wrong'. and I assume it's because they are not actually used. But then the question becomes. where does the valid information come from?

It might be easier/better to 'remaster' the TFX2 files to TFX3 standard.

Share this post


Link to post
Share on other sites

For TFX2 terrain, I guess you should only try to use those that are present in 'norway.dat' for now.

ie, these:


SEA

CM3_P

CM3_P2

CM3_P3

CM3_P4

CM3_S

CM3_C

CM3_I

CM2_P

CM2_P2

CM2_P3

CM2_P4

CM2_S

CM2_I

CM2_C

CM1_P

CM1_P2

CM1_P3

CM1_S

CM1_I

CM1_C

CM0_G

CM0_G2

CM0_G3

CM0_G4

CM0_G5

CM0_G6

CM0_G7

FCM1_P

FCM1_P2

FCM1_PC

FCM1_PS

FCM1_PI

COAST_S

COAST_S1

COAST_S2

COAST_I

COAST_C

COCLCONL

COCLCONR

CLIF1S2S

CLIF1S_S

CLIF1S2W

CLIF1S_W

CLIF1S2N

CLIF1S_N

CLIF1S2E

CLIF1S_E

CLIFC_SE

CLIFC_SW

CLIFC_NW

CLIFC_NE

CLIFI_SE

CLIFI_SW

CLIFI_NW

CLIFI_NE

CLIF2S2S

CLIF2S_S

CLIF2S2W

CLIF2S_W

CLIF2S2N

CLIF2S_N

CLIF21S2

CLIF2S_E

CLF2C_SE

CLF2C_SW

CLF2C_NW

CLF2C_NE

CLF2I_SE

CLF2I_SW

CLF2I_NW

CLF2I_NE

FCM1_S

FCM1_C

FCM1_I

CMG_I

CMG_C

CMG_S

CMG_M

RRVAL_S

RRVAL_CR

RRVALXCR

RRVAL_CL

RRVALXCL

RRJUNC_2

RRJUNC_4

RRJUNC_3

RRJUNC_1

RRFLT_S

RRFLT_CR

RRFLTXCR

RRFLT_CL

RRFLTXCL

RRFLTC_2

RRFLTC_4

RRFLTC_3

RRFLTC_1

RRVAL_E2

RRVAL_E

FYORD_S

FYORD_E

FYORD_C

FY_START

TEST

TSTPLANE

CLIFCOSL

CLIFCOWL

CLIFCONL

CLIFCOEL

CLIFCOSR

CLIFCOWR

CLIFCONR

CLIFCOER

PAST0_S

PAST0_C

PAST0_I

PAST0_M

PAST1_M

PAST1_S

PAST1_C

PAST1_I

MARSH_S

MARSH_M

MARSH_M2

MARSH_M3

MARSH_M4

MARSH_C

MARSH_I

VPAST0_S

VPAST0_C

VPAS0_ST

VPAST0_E

VALLEY_S

START

VALLEY_E

VALLEY_C

CITY_S

CITY_C

CITY_CR

CITY_CL

CITY_I

RIVER_S

RIVER_C

ESTSOUTH

ESTWEST

ESTNORTH

ESTEAST

RIVER_ST

BRIDGE1

DAM

RIG_1

RYGGEQ

BARDU

BODO

TROND

ANDOYA

OSLO

ORLAND

AIRFLD_1

EARLY1

ARMYDOK

POLITDOK

POWERDOK

OIL_DOK

SUPLYDOK

PORTDOK

V_AMYTWN

V_C4TWN

V_POLTWN

V_PWRTWN

V_OIL

V_SUPTWN

F_AMYTWN

F_C4TWN

F_POLTWN

F_PWRTWN

F_OILTWN

F_SUPTWN

CTYDOC_C

CTYDOCCL

CTYDOCCR

CTYDOC_I

S_OSLO

S_HELSIN

S_STOCK

STPETE_S

ISL_1

ISL_2

ISL_3

ISL_4

ISL_5

ISL_6

TREEISL1

TREEISL2

TREEISL3

TREEISL4

TREEISL5

PASRIV_E

MARSHCOL

MARSHCOR

TUN_RL1

TUN_RR1

ICEBERG1

ICEBERG2

ICEBERG3

ICEBERG4

ICEBERG5

ICEFLW_S

ICEFLW_C

RRFOR_S

RRFOR_CR

RRFORXCR

RRFOR_CL

RRFORXCL

RRFOR_E2

RRFOR_E

Remember that TFX2 has a tile rotation mechanism that is not used in TFX3.

Share this post


Link to post
Share on other sites

If my program works correctly, then there are 573 supershapes in lev\norway.dat but only 502 in norway.asc. Also, ss\sea.ssd seems damaged or malformed. Wat?!

SEA

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "SEA"

CM3_P

CM3_P2

CM3_P3

CM3_P4

CM3_S

CM3_S

CM3_S

CM3_S

CM3_C

CM3_C

CM3_C

CM3_C

CM3_I

CM3_I

CM3_I

CM3_I

CM2_P

CM2_P2

CM2_P3

CM2_P4

CM2_S

CM2_S

CM2_S

CM2_S

CM2_I

CM2_I

CM2_I

CM2_I

CM2_C

CM2_C

CM2_C

CM2_C

CM1_P

CM1_P2

CM1_P3

CM1_S

CM1_S

CM1_S

CM1_S

CM1_I

CM1_I

CM1_I

CM1_I

CM1_C

CM1_C

CM1_C

CM1_C

CM0_G

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CM0_G"

CM0_G2

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CM0_G2"

CM0_G3

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CM0_G3"

CM0_G4

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CM0_G4"

CM0_G5

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CM0_G5"

CM0_G6

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CM0_G6"

CM0_G7

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CM0_G7"

FCM1_P

FCM1_P2

FCM1_PC

FCM1_PC

FCM1_PC

FCM1_PC

FCM1_PS

FCM1_PS

FCM1_PS

FCM1_PS

FCM1_PI

FCM1_PI

FCM1_PI

FCM1_PI

CM1_S

CM1_S

CM1_S

CM1_S

CM1_I

CM1_I

CM1_I

CM1_I

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_I

COAST_I

COAST_I

COAST_I

COAST_C

COAST_C

COAST_C

COAST_C

SEA

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "SEA"

CM1_C

CM1_C

CM1_C

CM1_C

COCLCONL

COCLCONL

COCLCONL

COCLCONL

COCLCONR

COCLCONR

COCLCONR

COCLCONR

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_C

COAST_C

COAST_C

COAST_C

COAST_I

COAST_I

COAST_I

COAST_I

CLIF1S2S

CLIF1S_S

CLIF1S2W

CLIF1S_W

CLIF1S2N

CLIF1S_N

CLIF1S2E

CLIF1S_E

CLIFC_SE

CLIFC_SW

CLIFC_NW

CLIFC_NE

CLIFI_SE

CLIFI_SW

CLIFI_NW

CLIFI_NE

CLIF2S2S

CLIF2S_S

CLIF2S2W

CLIF2S_W

CLIF2S2N

CLIF2S_N

CLIF21S2

CLIF2S_E

CLF2C_SE

CLF2C_SW

CLF2C_NW

CLF2C_NE

CLF2I_SE

CLF2I_SW

CLF2I_NW

CLF2I_NE

FCM1_S

FCM1_S

FCM1_S

FCM1_S

FCM1_C

FCM1_C

FCM1_C

FCM1_C

FCM1_I

FCM1_I

FCM1_I

FCM1_I

FCM1_C

FCM1_C

FCM1_C

FCM1_C

FCM1_I

FCM1_I

FCM1_I

FCM1_I

FCM1_S

FCM1_S

FCM1_S

FCM1_S

CMG_I

CMG_I

CMG_I

CMG_I

CMG_C

CMG_C

CMG_C

CMG_C

CMG_S

CMG_S

CMG_S

CMG_S

CMG_M

RRVAL_S

RRVAL_S

RRVAL_CR

RRVALXCR

RRVAL_CL

RRVALXCL

RRJUNC_2

RRJUNC_4

RRJUNC_3

RRJUNC_1

RRFLT_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "RRFLT_S"

RRFLT_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "RRFLT_S"

RRFLT_CR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "RRFLT_CR"

RRFLTXCR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "RRFLTXCR"

RRFLT_CL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "RRFLT_CL"

RRFLTXCL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "RRFLTXCL"

RRFLTC_2

RRFLTC_4

RRFLTC_3

RRFLTC_1

RRVAL_E2

RRVAL_E2

RRVAL_E

RRVAL_E

FYORD_S

FYORD_S

FYORD_E

FYORD_E

FYORD_E

FYORD_E

FYORD_C

FYORD_C

FYORD_C

FYORD_C

FY_START

FY_START

FY_START

FY_START

TEST

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "TEST"

TSTPLANE

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "TSTPLANE"

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_S

COAST_S1

COAST_S2

COAST_I

COAST_I

COAST_I

COAST_I

COAST_C

COAST_C

COAST_C

COAST_C

COCLCONL

COCLCONL

COCLCONL

COCLCONL

COCLCONR

COCLCONR

COCLCONR

COCLCONR

CLIFCOSL

CLIFCOWL

CLIFCONL

CLIFCOEL

CLIFCOSR

CLIFCOWR

CLIFCONR

CLIFCOER

COCLCONL

COCLCONL

COCLCONL

COCLCONL

COCLCONR

COCLCONR

COCLCONR

COCLCONR

PAST0_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_S"

PAST0_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_S"

PAST0_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_S"

PAST0_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_S"

PAST0_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_C"

PAST0_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_C"

PAST0_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_C"

PAST0_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_C"

PAST0_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_I"

PAST0_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_I"

PAST0_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_I"

PAST0_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_I"

PAST0_M

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "PAST0_M"

PAST1_M

PAST1_S

PAST1_S

PAST1_S

PAST1_S

PAST1_C

PAST1_C

PAST1_C

PAST1_C

PAST1_I

PAST1_I

PAST1_I

PAST1_I

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_M

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M"

MARSH_M2

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M2"

MARSH_M3

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M3"

MARSH_M4

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M4"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSH_M

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M"

MARSH_M2

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M2"

MARSH_M3

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M3"

MARSH_M4

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_M4"

VPAST0_S

VPAST0_S

VPAST0_S

VPAST0_S

VPAST0_S

VPAST0_S

VPAST0_C

VPAST0_C

VPAST0_C

VPAST0_C

VPAS0_ST

VPAS0_ST

VPAS0_ST

VPAS0_ST

VPAST0_E

VPAST0_E

VPAST0_E

VPAST0_E

VALLEY_S

VALLEY_S

START

START

START

START

VALLEY_E

VALLEY_E

VALLEY_E

VALLEY_E

VALLEY_C

VALLEY_C

VALLEY_C

VALLEY_C

CITY_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_S"

CITY_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_S"

CITY_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_S"

CITY_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_S"

CITY_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_C"

CITY_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_C"

CITY_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_C"

CITY_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_C"

CITY_CR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CR"

CITY_CR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CR"

CITY_CR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CR"

CITY_CR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CR"

CITY_CL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CL"

CITY_CL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CL"

CITY_CL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CL"

CITY_CL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_CL"

CITY_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_I"

CITY_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_I"

CITY_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_I"

CITY_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "CITY_I"

RIVER_S

RIVER_S

RIVER_C

RIVER_C

RIVER_C

RIVER_C

ESTSOUTH

ESTWEST

ESTNORTH

ESTEAST

ESTSOUTH

ESTWEST

ESTNORTH

ESTEAST

CLIF1S2S

CLIF1S_S

CLIF1S2W

CLIF1S_W

CLIF1S2N

CLIF1S_N

CLIF1S2E

CLIF1S_E

CLIFI_SE

CLIFI_SW

CLIFI_NW

CLIFI_NE

CLIFC_SE

CLIFC_SW

CLIFC_NW

CLIFC_NE

RIVER_ST

RIVER_ST

RIVER_ST

RIVER_ST

BRIDGE1

BRIDGE1

DAM

DAM

DAM

DAM

RIG_1

RYGGEQ

BARDU

BODO

TROND

ANDOYA

OSLO

ORLAND

AIRFLD_1

EARLY1

ARMYDOK

ARMYDOK

ARMYDOK

ARMYDOK

POLITDOK

POLITDOK

POLITDOK

POLITDOK

POWERDOK

POWERDOK

POWERDOK

POWERDOK

OIL_DOK

OIL_DOK

OIL_DOK

OIL_DOK

SUPLYDOK

SUPLYDOK

SUPLYDOK

SUPLYDOK

PORTDOK

PORTDOK

PORTDOK

PORTDOK

V_AMYTWN

V_AMYTWN

V_C4TWN

V_C4TWN

V_POLTWN

V_POLTWN

V_PWRTWN

V_PWRTWN

V_OIL

V_OIL

V_SUPTWN

V_SUPTWN

F_AMYTWN

F_AMYTWN

F_C4TWN

F_C4TWN

F_POLTWN

F_POLTWN

F_PWRTWN

F_PWRTWN

F_OILTWN

F_OILTWN

F_SUPTWN

F_SUPTWN

CTYDOC_C

CTYDOC_C

CTYDOC_C

CTYDOC_C

CTYDOCCL

CTYDOCCL

CTYDOCCL

CTYDOCCL

CTYDOCCR

CTYDOCCR

CTYDOCCR

CTYDOCCR

CTYDOC_I

CTYDOC_I

CTYDOC_I

CTYDOC_I

S_OSLO

S_OSLO

S_OSLO

S_OSLO

S_HELSIN

S_HELSIN

S_HELSIN

S_HELSIN

S_STOCK

S_STOCK

S_STOCK

S_STOCK

STPETE_S

STPETE_S

STPETE_S

STPETE_S

ISL_1

ISL_2

ISL_3

ISL_4

ISL_5

ISL_6

TREEISL1

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "TREEISL1"

TREEISL2

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "TREEISL2"

TREEISL3

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "TREEISL3"

TREEISL4

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "TREEISL4"

TREEISL5

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "TREEISL5"

PASRIV_E

PASRIV_E

PASRIV_E

PASRIV_E

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_S

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_S"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_C

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_C"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSH_I

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSH_I"

MARSHCOL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOL"

MARSHCOL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOL"

MARSHCOL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOL"

MARSHCOL

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOL"

MARSHCOR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOR"

MARSHCOR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOR"

MARSHCOR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOR"

MARSHCOR

invalid .ssd: unexpected end of file in block 1 or 2

skipping supershape "MARSHCOR"

TUN_RL1

TUN_RL1

TUN_RR1

TUN_RR1

ICEBERG1

ICEBERG2

ICEBERG3

ICEBERG4

ICEBERG5

ICEFLW_S

ICEFLW_S

ICEFLW_S

ICEFLW_S

ICEFLW_C

ICEFLW_C

ICEFLW_C

ICEFLW_C

RRFOR_S

RRFOR_S

RRFOR_CR

RRFORXCR

RRFOR_CL

RRFORXCL

RRFOR_E2

RRFOR_E2

RRFOR_E

RRFOR_E

Share this post


Link to post
Share on other sites

I don't see anything 'wrong' with sea.ssd, it 's as simple as they come:


;File ;sea.ssd

;Size ;44

;Block1 0 10

;Block2 10 0

;Block3 10 0

;Block4 10 8

;Block5 18 6

;Block6 24 6

;Block7 30 4

;Block4_Pointer_1 34 6

;Block4_Pointer_2 40 2

;Block4_Pointer_3 42 2

;Lab_Block 44 0

;Block1 Starts 0 Length.10

0001e8030700ffff0400

;Block2 Starts 10 Length.0


;Block3 Starts 10 Length.0


;Block4 Starts 10 Length.8

04000b000d000d00

;Block5 Starts 18 Length.6

7a00

c900; SEA

ffff

;Block6 Starts 24 Length.6

03000000c900; Object 0 SEA

;Block7 Starts 30 Length.4

01000500

;Block4_Pointer_1 Starts 34 Length.6

07000000

0000

;Block4_Pointer_2 Starts 40 Length.2

0000

;Block4_Pointer_3 Starts 42 Length.2

0000

;Lab_Block Starts 44 Length.0

Note that there are no COLLISION_TRIANGLES as in TFX3. In TFX2 these don't seem to be used if everything is height=0. I haven't looked at the TFX2 lev folder since about 2007, but the the .env (actually, combined .ev & .ev2) can index 0-501 (as indicated by the .asc file), but a lot of these index numbers are not used, and a lot of the names are repeated. The list I posted earlier are the unique names from norway.dat. I also produced a list of how many times each index is used (for some reason), and it looks very inefficient...

Check out the posts from Roger Godfrey on this page. I'm beginning to see what he was on about....

http://www.combatsim...=1&t=000016&p=2


0						 77927

1						 1322

2						 534

3						 448

4						 507

.

.

26						 835

27						 16514

28						 810

29						 629

.

.

.

242						 112

243						 62

244						 75

245						 70

246						 83

247						 388

248						 0

249						 0

250						 0

251						 0

252						 0

253						 0

254						 0

255						 0

256						 0

257						 0

258						 0

259						 0

260						 0

261						 0

262						 0

263						 0

264						 0

265						 0

266						 0

267						 0

268						 0

269						 0

270						 0

271						 0

272						 0

273						 0

274						 1681

275						 9

.

.

.

.

485						 0

486						 0

487						 0

488						 0

489						 0

490						 0

491						 0

492						 100

493						 76

494						 29

495						 27

496						 30

497						 25

498						 18

499						 16

500						 17

501						 13

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0