Difference between revisions of "Elma 2/Technical"
Line 12: | Line 12: | ||
| style="text-align:right;" | 0 || char[5] || style="text-align:right;" | 5 || "POT35" for Elma 2 levels | | style="text-align:right;" | 0 || char[5] || style="text-align:right;" | 5 || "POT35" for Elma 2 levels | ||
|- | |- | ||
− | | style="text-align:right;" | 5 || int || style="text-align:right;" | 4 || 30 if unlocked level, 0 if locked level. Otherwise, assertion error | + | | style="text-align:right;" | 5 || int || style="text-align:right;" | 4 || '''level.locked''' - 30 if unlocked level, 0 if locked level. Otherwise, assertion error |
|- | |- | ||
− | | style="text-align:right;" | 9 || short || style="text-align:right;" | 2 || 1 if topology error, 0 if no topology error. | + | | style="text-align:right;" | 9 || short || style="text-align:right;" | 2 || '''level.topology_error''' - 1 if topology error, 0 if no topology error. |
|- | |- | ||
− | | style="text-align:right;" | 11 || int || style="text-align:right;" | 4 || 1 if start out facing right (autoturn at level start) | + | | style="text-align:right;" | 11 || int || style="text-align:right;" | 4 || '''level.face_right''' - 1 if start out facing right (autoturn at level start) |
|- | |- | ||
− | | style="text-align:right;" | 15 || char[51] || style="text-align:right;" | 51 || ''' | + | | style="text-align:right;" | 15 || char[51] || style="text-align:right;" | 51 || '''level.name''' - Level name/description. "Unnamed". Unused but can be hex-edited |
|- | |- | ||
− | | style="text-align:right;" | 66 || char[16] || style="text-align:right;" | 16 || LGR name. Unchangeable except by hex edit. Always "default" | + | | style="text-align:right;" | 66 || char[16] || style="text-align:right;" | 16 || '''level.lgr''' - LGR name. Unchangeable except by hex edit. Always "default" |
|- | |- | ||
| style="text-align:right;" | 82 || char[10] || style="text-align:right;" | 10 || '''Unused''': Ground texture name. Unused. Value always overwritten to "texturea" on save. If missing on open, defaults as "ground" | | style="text-align:right;" | 82 || char[10] || style="text-align:right;" | 10 || '''Unused''': Ground texture name. Unused. Value always overwritten to "texturea" on save. If missing on open, defaults as "ground" | ||
Line 30: | Line 30: | ||
| style="text-align:right;" | 122 || int || style="text-align:right;" | 4 || Shareware level: 115. Full game: 135. Shareware can't open any number greater than 120 | | style="text-align:right;" | 122 || int || style="text-align:right;" | 4 || Shareware level: 115. Full game: 135. Shareware can't open any number greater than 120 | ||
|- | |- | ||
− | | style="text-align:right;" | 126 || double || style="text-align:right;" | 8 || Number of polygons + 0.4643643. Maximum 2000. | + | | style="text-align:right;" | 126 || double || style="text-align:right;" | 8 || '''level.number_of_polygons''' - Number of polygons + 0.4643643. Maximum 2000. |
|- | |- | ||
| style="text-align:right;" | 134 || [[Elma2/Technical#Polygon|polygon]] || style="text-align:right;" | ? || Sequential list of polygons with data. "Raw" data for editor purposes | | style="text-align:right;" | 134 || [[Elma2/Technical#Polygon|polygon]] || style="text-align:right;" | ? || Sequential list of polygons with data. "Raw" data for editor purposes | ||
Line 40: | Line 40: | ||
| style="text-align:right;" | ? || int || style="text-align:right;" | 1 || dec: 192356446 (0x0B77205Eh) | | style="text-align:right;" | ? || int || style="text-align:right;" | 1 || dec: 192356446 (0x0B77205Eh) | ||
|- | |- | ||
− | | style="text-align:right;" | ? || double || style="text-align:right;" | 8 || Number of objects + 0.4643643. Maximum 500. | + | | style="text-align:right;" | ? || double || style="text-align:right;" | 8 || '''level.number_of_objects''' - Number of objects + 0.4643643. Maximum 500. |
|- | |- | ||
| style="text-align:right;" | ? || [[Elma2/Technical#Object Object|object]] || style="text-align:right;" | ? || Sequential list of objects | | style="text-align:right;" | ? || [[Elma2/Technical#Object Object|object]] || style="text-align:right;" | ? || Sequential list of objects | ||
|- | |- | ||
− | | style="text-align:right;" | ? || double || style="text-align:right;" | 8 || Number of pictures + 0.2345672. Maximum 5000. | + | | style="text-align:right;" | ? || double || style="text-align:right;" | 8 || '''level.number_of_pictures''' - Number of pictures + 0.2345672. Maximum 5000. |
|- | |- | ||
| style="text-align:right;" | ? || [[Elma2/Technical#Picture Object|picture]] || style="text-align:right;" | ? || Sequential list of pictures | | style="text-align:right;" | ? || [[Elma2/Technical#Picture Object|picture]] || style="text-align:right;" | ? || Sequential list of pictures |
Revision as of 23:48, 10 January 2018
Levels
How to parse a level byte by byte. Remember little-endianess.
Polygon objects are oriented so for y, up is negative and down is positive. Line objects are inverted so for y, up is positive and down is negative.
Main .lev Structure
Offset | Type | Bytes | Description |
---|---|---|---|
0 | char[5] | 5 | "POT35" for Elma 2 levels |
5 | int | 4 | level.locked - 30 if unlocked level, 0 if locked level. Otherwise, assertion error |
9 | short | 2 | level.topology_error - 1 if topology error, 0 if no topology error. |
11 | int | 4 | level.face_right - 1 if start out facing right (autoturn at level start) |
15 | char[51] | 51 | level.name - Level name/description. "Unnamed". Unused but can be hex-edited |
66 | char[16] | 16 | level.lgr - LGR name. Unchangeable except by hex edit. Always "default" |
82 | char[10] | 10 | Unused: Ground texture name. Unused. Value always overwritten to "texturea" on save. If missing on open, defaults as "ground" |
92 | char[10] | 10 | Unused: Sky texture name. Unused. Value always overwritten to "qgrass" on save. If missing on open, defaults as "sky" |
102 | byte[20] | 20 | Unused: ? Appears to be useless. Can be hex-edited |
122 | int | 4 | Shareware level: 115. Full game: 135. Shareware can't open any number greater than 120 |
126 | double | 8 | level.number_of_polygons - Number of polygons + 0.4643643. Maximum 2000. |
134 | polygon | ? | Sequential list of polygons with data. "Raw" data for editor purposes |
? | compile | ? | Only exists if no topology error, otherwise this object is skipped. "Processed" data for when you actually open a level. |
? | byte | 1 | 0x2B |
? | int | 1 | dec: 192356446 (0x0B77205Eh) |
? | double | 8 | level.number_of_objects - Number of objects + 0.4643643. Maximum 500. |
? | object | ? | Sequential list of objects |
? | double | 8 | level.number_of_pictures - Number of pictures + 0.2345672. Maximum 5000. |
? | picture | ? | Sequential list of pictures |
Polygon
Orientation: positive y is down. These polygons are edited by the editor. The editor uses this info to generate Line Objects
Offset | Type | Bytes | Description |
---|---|---|---|
0 | int | 4 | Type: 1=Normal, 2=Inactive, 3=Platform, 4=Path, 5=Autogenerated Border Polygon |
4 | int | 4 | Path Subtype: Door=1, Elevator=2, Falling=3, Continuous Oneway=4, Continuous Twoway=5 |
8 | int | 4 | Platform's Platform ID or Path's Path ID: 0-999 |
12 | int | 4 | Path's Platform ID: 0-999 |
16 | int | 4 | Path's Speed at top |
20 | int | 4 | Path's Speed at bottom |
24 | int | 4 | Path's Open delay |
28 | int | 4 | Path's Close delay |
32 | int | 4 | Path's ReOpen delay |
36 | int | 4 | Path's ReClose delay |
40 | int | 4 | Path's Initially flag: 1=Up, 0=Down |
44 | int | 4 | Path's No of platforms |
48 | int | 4 | Override flag: 1=Polygon interacts with biker |
52 | int | 4 | Style index |
56 | int | 4 | Override flag: 1=Border on |
60 | int | 4 | Override flag: 1=Border off |
64 | int | 4 | Override flag: 1=Whole polygon border colored |
68 | int | 4 | Distance |
72 | int | 4 | 0x00000000 |
76 | byte[300] | 300 | Used by Csaba as a secret comment section. Not included in normal editor |
376 | int | 4 | Number of vertices |
380 | vertex (double * 2)[?] | vertices * 16 | X and Y as two doubles. |
Compile Object
Offset | Type | Bytes | Description |
---|---|---|---|
0 | int | 4 | n: Total number of vertices across all polygons of type 1 + 5 only. |
4 | line*n | 72*n | Sequential list of n line objects |
4+72*n | double | 8 | ?Probably constant value of 60.0 |
12+72*n | int | 4 | Random number based on current time. SIGNED integer; crashes if negative number |
16+72*n | byte | 1 | 1=Beginning of a platform object. 0=No platforms |
? | platform | ? | Sequential list of all platform objects, as long as previous byte is 1 |
? | byte | 1 | 0x58h |
? | double | 8 | -406.64166666666665 in default shareware levels, but varies - unknown function |
? | double | 8 | -74.99166666666666 in default shareware levels, but varies - unknown function |
? | byte | 1 | 1=Beginning of a path object. 0=No path objects |
? | path | ? | Sequential list of all path objects, as long as previous byte is 1 |
Line Object
Orientation: positive y is up. Each line object is used by the game to draw on the screen and to make lines solid/non-solid.
Offset | Type | Bytes | Description |
---|---|---|---|
0 | double | 8 | a: Vertex's x |
8 | double | 8 | b: (-1)*Vertex's y |
16 | double | 8 | c: Delta x to reach the next vertex |
24 | double | 8 | d: (-1)*Delta y to reach the next vertex |
32 | double | 8 | e: Delta x to move one unit towards the next vertex - c/g - 1=sqrt(e^2+f^2) |
40 | double | 8 | f: Delta y to move one unit towards the next vertex - d/g - 1=sqrt(e^2+f^2) |
48 | double | 8 | g: Line length - sqrt(c^2+d^2) |
56 | int | 4 | Texture ID (draws to right of the line) |
60 | int | 4 | 0 if solid, 1 if cannot touch |
64 | int | 4 | Distance (border polygons copy base polygon distance) |
68 | int | 4 | Do not draw to the right of the line if = 1 (equivalent to texture id of 0), otherwise draw texture. Not sure if actually used by the default editor but that's what editing this value does |
Object Object
Offset | Type | Bytes | Description |
---|---|---|---|
0 | double | 8 | x |
8 | double | 8 | y |
16 | int | 4 | Type:
1=Flower 2=Food 3=Killer 4=Start 5=Bonus 6=Card 7=Switch 8=Group switch 9=Platform reference (10="stage") - internal error (11="fordit") "turn" - no object appears ingame (12="ugrat") "jump" - black square with no effect 13=Teleport |
20 | int | 4 | Group id |
24 | int | 4 | Path id or Condition 2 Path id |
28 | int | 4 | Opener/Closer: 1=A/opener, 0=B/closer |
32 | int | 4 | Card color: 0=None, 1=Red, 2=Yellow, 3=Blue |
36 | int | 4 | Condition 2 State: 1=Up, 0=Down |
40 | int | 4 | Platform id |
44 | byte[300] | 300 | Used by Csaba as a secret comment section. Not included in normal editor |
Picture Object
Same as in elma1
Offset | Type | Bytes | Description |
---|---|---|---|
0 | string | 10 | Picture name |
10 | string | 10 | Unused: Texture name |
20 | string | 10 | Unused: Mask name |
30 | double | 8 | X |
38 | double | 8 | Y |
46 | int | 4 | Distance |
50 | int | 4 | Clipping; 0=U, 1=G, 2=S |
Platform Object
This contains info about the lines in a platform for the purposes of collision
Offset | Type | Bytes | Description |
---|---|---|---|
0 | double | 8 | 0 - x_min(2)-0.0500000 |
8 | double | 8 | 1 - y_min(3)-0.0500000 |
16 | double | 8 | 2 - x_min of all point.y-platform_reference_object.y |
24 | double | 8 | 3 - y_min of all point.y-platform_reference_object.y |
32 | double | 8 | 4 - x_max of all point.x-platform_reference_object.x |
40 | double | 8 | 5 - y_max of all point.y-platform_reference_object.y |
48 | double | 8 | 6 - x_min(2)-0.3300000 |
56 | double | 8 | 7 - y_min(3)-0.3300000 |
64 | double | 8 | 8 - same as 2 |
72 | double | 8 | 9 - same as 3 |
80 | double | 8 | 10 - same as 4 |
88 | double | 8 | 11 - same as 5 |
96 | double | 8 | 12 - Platform reference object X |
104 | double | 8 | 13 - Platform reference object Y |
112 | int | 4 | 0 - Width of the polygon image probably |
116 | int | 4 | 1 - Height of the polygon image probably |
120 | int | 4 | 2 - ?Approximately width/6 |
124 | int | 4 | 3 - ?Approximately height/6 |
128 | int | 4 | 4 - Platform ID of the set |
132 | int | 4 | 5 - ? defaults to 0 |
136 | int | 4 | 6 - ? defaults to 0 |
140 | int | 4 | 7 - ? defaults to 0 |
144 | int | 4 | 8 - ? defaults to 0 |
148 | int | 4 | 9 - ? defaults to 0 |
152 | int | 4 | 10 - ? defaults to 0 |
156 | int | 4 | 11 - ? defaults to 0 |
160 | int | 4 | 12 - Texture id of center part |
164 | int | 4 | 13 - Texture id of border |
168 | int | 4 | 14 - Always 1478256389 |
172 | int | 4 | 15 - Probably null-padding |
176 | int | 4 | 16 - Number of vertices of all polygons belonging to the same platform, excluding non-solid vertices/lines. |
180 | line*n | 72*n | Sequential list of n line objects. Note that the 4 int variables are ignored and set to 0. The position of these line objects describe the platform's initial position based on the platform reference object, ignoring the path. This data is only used for to make the platforms solid and is not used to draw the platforms. |
? | byte | 1 | 1=Beginning of another platform object. 0=No more platforms to read |
Path Object
Path objects contain the info used to graphically draw platforms
Offset | Type | Bytes | Description |
---|---|---|---|
0 | byte[24] | 24 | Null-padding |
24 | int | 4 | path id |
28 | int | 4 | platform id |
32 | int | 4 | pathsubtype |
36 | int | 4 | speedattop |
40 | int | 4 | speedatbottom |
44 | int | 4 | opendelay |
48 | int | 4 | closedelay |
52 | int | 4 | reopendelay |
56 | int | 4 | reclosedelay |
60 | int | 4 | initially |
64 | int | 4 | noplatforms |
68 | byte[16] | 16 | Null padding |
84 | int | 4 | f=number of frames to do forward animation path |
88 | int | 4 | f2=total number of frames to do forward and backwards animation path. Always f*2 except continuous one-way, where it is (f+1). Also different for multiple platforms |
92 | byte[4] | 4 | Null padding |
96 | int | 4 | 0 ?pointer |
100 | int | 4 | 1 ?pointer |
104 | int | 4 | 2 ?pointer |
108 | int | 4 | 3 ?pointer |
112 | int | 4 | 4 ?pointer |
116 | byte[20] | 20 | Null padding |
136 | int | 4 | x=?always 0 |
140 | int | 4 | identical to x |
144 | int | 4 | identical to x |
148 | int | 4 | identical to x |
152 | int | 4 | identical to x |
156 | int | 4 | identical to x |
160 | int | 4 | Always=1236278137 |
164 | byte[4] | 4 | Null padding |
168 | int?*ft | 4*ft | mozg_x (4 bytes per frame) mozg="movement" |
? | byte | 1 | 0x15 |
? | int?*ft | 4*ft | mozg_y (4 bytes per frame) |
? | byte | 1 | 0x15 |
? | int?*ft | 4*ft | seb_x (4 bytes per frame) seb="velocity" |
? | byte | 1 | 0x15 |
? | int?*ft | 4*ft | seb_y (4 bytes per frame) |
? | byte | 1 | 0x15 |
? | int?*ft | 4*ft | plat_x (4 bytes per frame) |
? | byte | 1 | 0x15 |
? | int?*ft | 4*ft | plat_y (4 bytes per frame) |
? | byte | 1 | 0x15 |
? | byte | 1 | 1=Beginning of another path object. 0=No more path obj to read |
Replay file
Main structure
Offset | Type | Bytes | Description |
---|---|---|---|
0 | int | 4 | Constant: 0x211A3591 |
4 | int | 4 | Constant: 0x66 |
8 | int | 4 | 0 if no restore points used, 1 if restore points used. If level was completed, the finish-time will have 5 minutes added to the time on replay |
12 | int | 4 | Constant: 0x2C. Size of the fileinfo block |
16 | int | 4 | Fileinfo block: Corresponding level's random identifier (in lev.compile) |
20 | int | 4 | Fileinfo block: 1 if internal level replay, 0 if external level replay |
24 | int | 4 | Fileinfo block: If Internal -> Pack id (0-3 for A-D), else 0 |
28 | int | 4 | Fileinfo block: If Internal -> Level number (0-7 for Levels 1-8), else 0 |
32 | char[28] | 28 | Fileinfo block: If external -> levelname.lev, null-terminated, or else null |
60 | int | 4 | n1 - Number of frames: Number must be from 0 to 216000 |
64 | int | 4 | n2 - Number of events: Number from 0 to 10000 |
68 | frame[n1] | n1*32 | sequential list of n1 frames |
68+n1*32 | event[n2] | n2*16 | sequential list of n2 events |
68+n1*32+n2*16 | int | 4 | Constant: 0x211A3591 |
Frame Object
TODO
Event Object
Unlike in elma1, in elma2, there are only object-touch events for flowers (and I'm guessing switches) if the object is "activated". A flower will have an object-touch event when you finished the level successfully.
A level that starts facing right does not include the autogenerated first turn event
Offset | Type | Bytes | Description |
---|---|---|---|
0 | int | 4 | Frame at which event takes place |
4 | int | 4 | event_id. If 0, it's an object-touch event, or else (1-7) it's a sound/motion event |
8 | int | 4 | object_id. Array id of touched object. 0xFFFFFFFF if event_id != 0 |
12 | int | 4 | Always 0? |
event_id | Meaning |
---|---|
0 | Object-touch event (Bike touches object indicated by object_id - killer causes a death event only) |
1 | Nothing (error) |
2 | Death - records time of death. In a replay, it will only play the sound but not abort the replay |
3 | Right volt |
4 | Left volt |
5 | Turn |
6 | Turn on gas sound |
7 | Turn off gas sound |
8-9 | Invalid (probably same as 0) |
.mif
Python code to open files: Elma_2/Code#Python: .mif parser
Main structure
Offset | Type | Bytes | Description |
---|---|---|---|
0 | int | 4 | .mif header: 100 |
4 | int | 4 | Length of filename dataset. Fixed at 180,000 or else crash |
8 | int | 4 | n: Number of files in filename dataset. Restricted to number 1-1800 inclusive. |
12 | fileset | 180000 | List of n filesets, then padded with 0xCD to a length of 180000 |
180012 | int | 4 | 5B7AAB9Eh |
180016 | bytes[?] | ? | Raw stream of all files in a row with no separation. Find the file using the fileset information. |
? | int | 4 | 5B7AAB9Eh |
Fileset
Offset | Type | Bytes | Description |
---|---|---|---|
0 | char[92] | 92 | Filename, null-terminated and padded with 0xCD. e.g. ('example.txt\0\0xCD\0xCD...\0xCD') |
92 | int | 4 | Reading from the start of default.mif, the location of the above file (e.g. f.seek(x,0)) |
96 | int | 4 | Length of the file |
What files are contained in .mif file?
File | Description |
---|---|
abc/abc_kicsi.abc | kicsi="small": Contains a bunch of .spr files? Also maybe other stuff. These 4 files probably different possible alphabets in sprite form |
kisbetu 1/2 .abc | "lowercase": Contains a bunch of .spr files? Also maybe other stuff. These 4 files probably different possible alphabets in sprite form |
felhok.dat | "Clouds" |
hangok.dat | "Noises" |
propri%i.dat | List of level filenames for the 4 internal packs in format "%Sx.leb" where S=string.touppercase() |
.led | Internal pack levels |
.lev | Default tutorial levels |
pl.txt | List of pictures and textures with default distance and clipping. "vegesorszo" means end of list |
c_szoveg_x.tga | Images of copyright text |
c_x.tga | Bike special effects: Teleport clouds and bang head |
qp_%s_%i_%s_%i.tga | Images related to specific internal pack levels. Unknown exact use |
t_%I_%s.tga | Texture files. I: textureid. s: texture name |
wq_.tga | Small icons used in game instructions, screen-press showing action, or used in editor |
other.tga | images used by pl.txt |
default.txs | Maps desired game style to texture/border/distance |
.wav | Sound effects in-game. Restricted to a certain filesize but otherwise can have varying frequencies etc |
menupalhoz.pcx | Probably the background shading image for menu |
State.dat
Offset | Type | Bytes | Description |
---|---|---|---|
0 | int | 4 | Header: 0x000000D1 |
4 | int | 8 | 1=Sound on, 0=Sound off |
8 | player[20] | 3120 | Sorted list of 20 player objects. If less than 20 players, pad with 0s to maintain full size |
3128 | . | . | More stuff... not yet decoded |
Player
Contains player settings etc
Offset | Type | Bytes | Description |
---|---|---|---|
0 | chr[16] | 16 | Player name |
16 | byte[104] | 104 | Null-padding. There may be some data in here that I don't know about, but haven't looked into it. Grossly editing this part doesn't seem to have any noticeable effect but I could be wrong |
120 | int | 4 | 1=Volts enabled, 0=Volts disabled |
124 | int | 4 | |
128 | int | 4 | 1=Normal keyboard settings. 0=Only one volt button and game chooses volt direction |
132 | int | 4 | |
136 | int | 4 | Some key code representing button for "Thrust" |
140 | int | 4 | Some key code representing button for "Brake" |
144 | int | 4 | Some key code representing button for "Left rotation" |
148 | int | 4 | Some key code representing button for "Right rotation" |
152 | int | 4 | Some key code representing button for "Turn" |