Difference between revisions of "Elma 2/Technical"

From Elma Wiki
Jump to navigation Jump to search
(Created page with "== Elasto Mania 2 == === Levels === How to parse a level byte by byte. Remember little-endianess. WIP Polygon objects are oriented so for y, up is negative and down is posit...")
 
 
(109 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Elasto Mania 2 ==
+
== Levels ==
=== Levels ===
 
 
How to parse a level byte by byte. Remember little-endianess.
 
How to parse a level byte by byte. Remember little-endianess.
 
WIP
 
  
 
Polygon objects are oriented so for y, up is negative and down is positive.
 
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.
 
Line objects are inverted so for y, up is positive and down is negative.
  
 +
 +
=== Main .lev Structure ===
 
{| class="wikitable"
 
{| class="wikitable"
 
! Offset || Type || Bytes || Description
 
! Offset || Type || Bytes || Description
Line 29: Line 28:
 
| style="text-align:right;" | 102 || byte[20] || style="text-align:right;" | 20 || '''Unused''': ? Appears to be useless. Can be hex-edited
 
| style="text-align:right;" | 102 || byte[20] || style="text-align:right;" | 20 || '''Unused''': ? Appears to be useless. Can be hex-edited
 
|-
 
|-
| style="text-align:right;" | 122 || int || style="text-align:right;" | 4 || Shareware check. Shareware editor always saves this value as 115. Shareware game cannot open any number greater than 120. Full game is probably 135 but to confirm with real game version
+
| 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 || Number of polygons + 0.4643643. Maximum 2000.
 
|-
 
|-
| style="text-align:right;" | 134 || 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
 
|-
 
|-
| style="text-align:right;" | ? || object1 || style="text-align:right;" | ? || Only exists if no topology error, otherwise this object is skipped. "Processed" data for when you actually open a level.
+
| style="text-align:right;" | ? || [[Elma2/Technical#Compile Object|compile]] || style="text-align:right;" | ? || Only exists if no topology error, otherwise this object is skipped. "Processed" data for when you actually open a level.
 
|-
 
|-
 
| style="text-align:right;" | ? || byte || style="text-align:right;" | 1 || 0x2B
 
| style="text-align:right;" | ? || byte || style="text-align:right;" | 1 || 0x2B
 
|-
 
|-
| x ||To be continued... Work in progress
+
| 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 || Number of objects + 0.4643643. Maximum 500.
 
|-
 
|-
| x ||To be continued... Work in progress
+
| 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;" | ? || [[Elma2/Technical#Picture Object|picture]] || style="text-align:right;" | ? || Sequential list of pictures
 
|-
 
|-
 
|}
 
|}
  
 +
=== Polygon ===
 +
Orientation: positive y is down. These polygons are edited by the editor. The editor uses this info to generate [[Elma2/Technical#Line Object|Line Object]]s
 
{| class="wikitable"
 
{| class="wikitable"
 
|+ Polygon structure
 
|+ Polygon structure
Line 56: Line 61:
 
| style="text-align:right;" | 4 || int ||  style="text-align:right;" | 4 || Path Subtype: Door=1, Elevator=2, Falling=3, Continuous Oneway=4, Continuous Twoway=5
 
| style="text-align:right;" | 4 || int ||  style="text-align:right;" | 4 || Path Subtype: Door=1, Elevator=2, Falling=3, Continuous Oneway=4, Continuous Twoway=5
 
|-
 
|-
| style="text-align:right;" | 8 || int ||  style="text-align:right;" | 4 || Platform's Platform ID or Path's Path ID: 0-999
+
| style="text-align:right;" | 8 || int ||  style="text-align:right;" | 4 || Platform id: 0-999
 
|-
 
|-
| style="text-align:right;" | 12 || int ||  style="text-align:right;" | 4 || Path's Platform ID: 0-999
+
| style="text-align:right;" | 12 || int ||  style="text-align:right;" | 4 || Path ID: 0-999
 
|-
 
|-
 
| style="text-align:right;" | 16 || int ||  style="text-align:right;" | 4 || Path's Speed at top
 
| style="text-align:right;" | 16 || int ||  style="text-align:right;" | 4 || Path's Speed at top
Line 88: Line 93:
 
| style="text-align:right;" | 68 || int ||  style="text-align:right;" | 4 || Distance
 
| style="text-align:right;" | 68 || int ||  style="text-align:right;" | 4 || Distance
 
|-
 
|-
| style="text-align:right;" | 72 || int ||  style="text-align:right;" | 4 || Probably always 0. Probably not important as not included in Balazs' debug file (0040F1FB)
+
| style="text-align:right;" | 72 || int ||  style="text-align:right;" | 4 || 0x00000000
 
|-
 
|-
| style="text-align:right;" | 76 || byte[300] ||  style="text-align:right;" | 300 || Probably just padding
+
| style="text-align:right;" | 76 || byte[300] ||  style="text-align:right;" | 300 || Used by Csaba as a secret comment section. Not included in normal editor
 
|-
 
|-
 
| style="text-align:right;" | 376 || int ||  style="text-align:right;" | 4 || Number of vertices
 
| style="text-align:right;" | 376 || int ||  style="text-align:right;" | 4 || Number of vertices
Line 97: Line 102:
 
|}
 
|}
  
 +
=== Compile Object ===
 
{| class="wikitable"
 
{| class="wikitable"
|+ Object1
+
|+ Compile Object
 
|-
 
|-
 
! Offset || Type || Bytes || Description
 
! Offset || Type || Bytes || Description
 
|-
 
|-
| style="text-align:right;" | 0 || int ||  style="text-align:right;" | 4 || Total number of vertices across all polygons of type 1 + 5 only.
+
| style="text-align:right;" | 0 || int ||  style="text-align:right;" | 4 || '''n:''' Total number of vertices across all polygons of type 1 + 5 only.
 +
|-
 +
| style="text-align:right;" | 4 || [[Elma2/Technical#Line Object|line]]*n ||  style="text-align:right;" | 72*n || Sequential list of ''n'' [[Elma2/Technical#Line Object|line object]]s
 +
|-
 +
| style="text-align:right;" | 4+72*n || double ||  style="text-align:right;" | 8 || ?Probably constant value of 60.0
 +
|-
 +
| style="text-align:right;" | 12+72*n || int ||  style="text-align:right;" | 4 || Random number based on current time. SIGNED integer; crashes if negative number
 +
|-
 +
| style="text-align:right;" | 16+72*n || byte ||  style="text-align:right;" | 1 || 1=Beginning of a platform object. 0=No platforms
 +
|-
 +
| style="text-align:right;" | ? || [[Elma2/Technical#Platform Object|platform]] ||  style="text-align:right;" | ? || Sequential list of all platform objects, as long as previous byte is 1
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 0x58h
 
|-
 
|-
| style="text-align:right;" | 4 || byte[72]*n ||  style="text-align:right;" | 72*n || LineObject
+
| style="text-align:right;" | ? || double ||  style="text-align:right;" | 8 || -406.64166666666665 in default shareware levels, but varies - unknown function
 
|-
 
|-
| x ||To be continued... Work in progress
+
| style="text-align:right;" | ? || double ||  style="text-align:right;" | 8 || -74.99166666666666 in default shareware levels, but varies - unknown function
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 1=Beginning of a path object. 0=No path objects
 +
|-
 +
| style="text-align:right;" | ? || [[Elma2/Technical#Path Object|path]] ||  style="text-align:right;" | ? || 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.
  
 
{| class="wikitable"
 
{| class="wikitable"
|+ LineObject
+
|+ LineObject (72 bytes)
 
|-
 
|-
 
! Offset || Type || Bytes || Description
 
! Offset || Type || Bytes || Description
Line 130: Line 154:
 
| style="text-align:right;" | 48 || double ||  style="text-align:right;" | 8 || '''g:''' Line length - sqrt(c^2+d^2)
 
| style="text-align:right;" | 48 || double ||  style="text-align:right;" | 8 || '''g:''' Line length - sqrt(c^2+d^2)
 
|-
 
|-
| style="text-align:right;" | 56 || int ||  style="text-align:right;" | 4 || Texture ID (draws to right of the line)
+
| style="text-align:right;" | 56 || int ||  style="text-align:right;" | 4 || [[Elma2/Technical#Texture IDs|Texture ID]] (draws to right of the line)
 
|-
 
|-
 
| style="text-align:right;" | 60 || int ||  style="text-align:right;" | 4 || 0 if solid, 1 if cannot touch
 
| style="text-align:right;" | 60 || int ||  style="text-align:right;" | 4 || 0 if solid, 1 if cannot touch
Line 139: Line 163:
 
|-
 
|-
 
|}
 
|}
 +
 +
=== Object Object ===
 +
{| class="wikitable"
 +
|+ Object (344 bytes)
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || double ||  style="text-align:right;" | 8 || x
 +
|-
 +
| style="text-align:right;" | 8 || double ||  style="text-align:right;" | 8 || y
 +
|-
 +
| style="text-align:right;" | 16 || int ||  style="text-align:right;" | 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
 +
|-
 +
| style="text-align:right;" | 20 || int ||  style="text-align:right;" | 4 || Group id
 +
|-
 +
| style="text-align:right;" | 24 || int ||  style="text-align:right;" | 4 || Path id or Condition 2 Path id
 +
|-
 +
| style="text-align:right;" | 28 || int ||  style="text-align:right;" | 4 || Opener/Closer: 1=A/opener, 0=B/closer
 +
|-
 +
| style="text-align:right;" | 32 || int ||  style="text-align:right;" | 4 || Card color: 0=None, 1=Red, 2=Yellow, 3=Blue
 +
|-
 +
| style="text-align:right;" | 36 || int ||  style="text-align:right;" | 4 || Condition 2 State: 1=Up, 0=Down
 +
|-
 +
| style="text-align:right;" | 40 || int ||  style="text-align:right;" | 4 || Platform id
 +
|-
 +
| style="text-align:right;" | 44 || byte[300] ||  style="text-align:right;" | 300 || Used by Csaba as a secret comment section. Not included in normal editor
 +
|-
 +
|}
 +
 +
=== Picture Object ===
 +
Same as in elma1
 +
 +
{| class="wikitable"
 +
|+ Picture (54 bytes)
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || string ||  style="text-align:right;" | 10 || Picture name
 +
|-
 +
| style="text-align:right;" | 10 || string ||  style="text-align:right;" | 10 || Unused: Texture name
 +
|-
 +
| style="text-align:right;" | 20 || string ||  style="text-align:right;" | 10 || Unused: Mask name
 +
|-
 +
| style="text-align:right;" | 30 || double ||  style="text-align:right;" | 8 || X
 +
|-
 +
| style="text-align:right;" | 38 || double ||  style="text-align:right;" | 8 || Y
 +
|-
 +
| style="text-align:right;" | 46 || int ||  style="text-align:right;" | 4 || Distance
 +
|-
 +
| style="text-align:right;" | 50 || int ||  style="text-align:right;" | 4 || Clipping; 0=U, 1=G, 2=S
 +
|-
 +
|}
 +
 +
=== Platform Object ===
 +
This contains info about the lines in a platform for the purposes of collision
 +
 +
{| class="wikitable"
 +
|+ Platform
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || double ||  style="text-align:right;" | 8 || 0 - x_min(2)-0.0500000
 +
|-
 +
| style="text-align:right;" | 8 || double ||  style="text-align:right;" | 8 || 1 - y_min(3)-0.0500000
 +
|-
 +
| style="text-align:right;" | 16 || double ||  style="text-align:right;" | 8 || 2 - x_min of all point.y-platform_reference_object.y
 +
|-
 +
| style="text-align:right;" | 24 || double ||  style="text-align:right;" | 8 || 3 - y_min of all point.y-platform_reference_object.y
 +
|-
 +
| style="text-align:right;" | 32 || double ||  style="text-align:right;" | 8 || 4 - x_max of all point.x-platform_reference_object.x
 +
|-
 +
| style="text-align:right;" | 40 || double ||  style="text-align:right;" | 8 || 5 - y_max of all point.y-platform_reference_object.y
 +
|-
 +
| style="text-align:right;" | 48 || double ||  style="text-align:right;" | 8 || 6 - x_min(2)-0.3300000
 +
|-
 +
| style="text-align:right;" | 56 || double ||  style="text-align:right;" | 8 || 7 - y_min(3)-0.3300000
 +
|-
 +
| style="text-align:right;" | 64 || double ||  style="text-align:right;" | 8 || 8 - same as 2
 +
|-
 +
| style="text-align:right;" | 72 || double ||  style="text-align:right;" | 8 || 9 - same as 3
 +
|-
 +
| style="text-align:right;" | 80 || double ||  style="text-align:right;" | 8 || 10 - same as 4
 +
|-
 +
| style="text-align:right;" | 88 || double ||  style="text-align:right;" | 8 || 11 - same as 5
 +
|-
 +
| style="text-align:right;" | 96 || double ||  style="text-align:right;" | 8 || 12 - Platform reference object X
 +
|-
 +
| style="text-align:right;" | 104 || double ||  style="text-align:right;" | 8 || 13 - Platform reference object Y
 +
|-
 +
| style="text-align:right;" | 112 || int ||  style="text-align:right;" | 4 || 0 - Width of the polygon image probably
 +
|-
 +
| style="text-align:right;" | 116|| int ||  style="text-align:right;" | 4 || 1 - Height of the polygon image probably
 +
|-
 +
| style="text-align:right;" | 120 || int ||  style="text-align:right;" | 4 || 2 - ?Approximately width/6
 +
|-
 +
| style="text-align:right;" | 124 || int ||  style="text-align:right;" | 4 || 3 - ?Approximately height/6
 +
|-
 +
| style="text-align:right;" | 128 || int ||  style="text-align:right;" | 4 || 4 - Platform ID of the set
 +
|-
 +
| style="text-align:right;" | 132 || int ||  style="text-align:right;" | 4 || 5 - ? defaults to 0
 +
|-
 +
| style="text-align:right;" | 136 || int ||  style="text-align:right;" | 4 || 6 - ? defaults to 0
 +
|-
 +
| style="text-align:right;" | 140 || int ||  style="text-align:right;" | 4 || 7 - ? defaults to 0
 +
|-
 +
| style="text-align:right;" | 144 || int ||  style="text-align:right;" | 4 || 8 - ? defaults to 0
 +
|-
 +
| style="text-align:right;" | 148 || int ||  style="text-align:right;" | 4 || 9 - ? defaults to 0
 +
|-
 +
| style="text-align:right;" | 152 || int ||  style="text-align:right;" | 4 || 10 - ? defaults to 0
 +
|-
 +
| style="text-align:right;" | 156 || int ||  style="text-align:right;" | 4 || 11 - ? defaults to 0
 +
|-
 +
| style="text-align:right;" | 160 || int ||  style="text-align:right;" | 4 || 12 - Texture id of center part
 +
|-
 +
| style="text-align:right;" | 164 || int ||  style="text-align:right;" | 4 || 13 - Texture id of border
 +
|-
 +
| style="text-align:right;" | 168 || int ||  style="text-align:right;" | 4 || 14 - Always 1478256389
 +
|-
 +
| style="text-align:right;" | 172|| int ||  style="text-align:right;" | 4 || 15 - Probably null-padding
 +
|-
 +
| style="text-align:right;" | 176 || int ||  style="text-align:right;" | 4 || 16 - Number of vertices of all polygons belonging to the same platform, excluding non-solid vertices/lines.
 +
|-
 +
| style="text-align:right;" | 180 || [[Elma2/Technical#Line Object|line]]*n ||  style="text-align:right;" | 72*n || Sequential list of ''n'' [[Elma2/Technical#Line Object|line object]]s. 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.
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 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
 +
 +
{| class="wikitable"
 +
|+ Path
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || byte[24] ||  style="text-align:right;" | 24 || Null-padding
 +
|-
 +
| style="text-align:right;" | 24 || int ||  style="text-align:right;" | 4 || path id
 +
|-
 +
| style="text-align:right;" | 28 || int ||  style="text-align:right;" | 4 || platform id
 +
|-
 +
| style="text-align:right;" | 32 || int ||  style="text-align:right;" | 4 || pathsubtype
 +
|-
 +
| style="text-align:right;" | 36 || int ||  style="text-align:right;" | 4 || speedattop
 +
|-
 +
| style="text-align:right;" | 40 || int ||  style="text-align:right;" | 4 || speedatbottom
 +
|-
 +
| style="text-align:right;" | 44 || int ||  style="text-align:right;" | 4 || opendelay
 +
|-
 +
| style="text-align:right;" | 48 || int ||  style="text-align:right;" | 4 || closedelay
 +
|-
 +
| style="text-align:right;" | 52 || int ||  style="text-align:right;" | 4 || reopendelay
 +
|-
 +
| style="text-align:right;" | 56 || int ||  style="text-align:right;" | 4 || reclosedelay
 +
|-
 +
| style="text-align:right;" | 60 || int ||  style="text-align:right;" | 4 || initially
 +
|-
 +
| style="text-align:right;" | 64 || int ||  style="text-align:right;" | 4 || noplatforms
 +
|-
 +
| style="text-align:right;" | 68 || byte[16] ||  style="text-align:right;" | 16 || Null padding
 +
|-
 +
| style="text-align:right;" | 84 || int ||  style="text-align:right;" | 4 || f=number of frames to do forward animation path
 +
|-
 +
| style="text-align:right;" | 88 || int ||  style="text-align:right;" | 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
 +
|-
 +
| style="text-align:right;" | 92 || byte[4] ||  style="text-align:right;" | 4 || Null padding
 +
|-
 +
| style="text-align:right;" | 96 || int ||  style="text-align:right;" | 4 || 0 ?pointer
 +
|-
 +
| style="text-align:right;" | 100 || int ||  style="text-align:right;" | 4 || 1 ?pointer
 +
|-
 +
| style="text-align:right;" | 104 || int ||  style="text-align:right;" | 4 || 2 ?pointer
 +
|-
 +
| style="text-align:right;" | 108 || int ||  style="text-align:right;" | 4 || 3 ?pointer
 +
|-
 +
| style="text-align:right;" | 112 || int ||  style="text-align:right;" | 4 || 4 ?pointer
 +
|-
 +
| style="text-align:right;" | 116 || byte[20] ||  style="text-align:right;" | 20 || Null padding
 +
|-
 +
| style="text-align:right;" | 136 || int ||  style="text-align:right;" | 4 || x=?always 0
 +
|-
 +
| style="text-align:right;" | 140|| int ||  style="text-align:right;" | 4 || identical to x
 +
|-
 +
| style="text-align:right;" | 144 || int ||  style="text-align:right;" | 4 || identical to x
 +
|-
 +
| style="text-align:right;" | 148 || int ||  style="text-align:right;" | 4 || identical to x
 +
|-
 +
| style="text-align:right;" | 152 || int ||  style="text-align:right;" | 4 || identical to x
 +
|-
 +
| style="text-align:right;" | 156 || int ||  style="text-align:right;" | 4 || identical to x
 +
|-
 +
| style="text-align:right;" | 160 || int ||  style="text-align:right;" | 4 || Always=1236278137
 +
|-
 +
| style="text-align:right;" | 164 || byte[4] ||  style="text-align:right;" | 4 || Null padding
 +
 +
|-
 +
| style="text-align:right;" | 168 || int?*ft ||  style="text-align:right;" | 4*ft || mozg_x (4 bytes per frame) mozg="movement"
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 0x15
 +
|-
 +
| style="text-align:right;" | ? || int?*ft ||  style="text-align:right;" | 4*ft || mozg_y (4 bytes per frame)
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 0x15
 +
|-
 +
| style="text-align:right;" | ? || int?*ft ||  style="text-align:right;" | 4*ft || seb_x (4 bytes per frame) seb="velocity"
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 0x15
 +
|-
 +
| style="text-align:right;" | ? || int?*ft ||  style="text-align:right;" | 4*ft || seb_y (4 bytes per frame)
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 0x15
 +
|-
 +
| style="text-align:right;" | ? || int?*ft ||  style="text-align:right;" | 4*ft || plat_x (4 bytes per frame)
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 0x15
 +
|-
 +
| style="text-align:right;" | ? || int?*ft ||  style="text-align:right;" | 4*ft || plat_y (4 bytes per frame)
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 0x15
 +
|-
 +
| style="text-align:right;" | ? || byte ||  style="text-align:right;" | 1 || 1=Beginning of another path object. 0=No more path obj to read
 +
|-
 +
|}
 +
 +
== Replay file ==
 +
Runs at about 240 fps (compared to elma1 60 fps)
 +
 +
=== Main structure ===
 +
{| class="wikitable"
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || int || style="text-align:right;" | 4 || Constant: 0x211A3591
 +
|-
 +
| style="text-align:right;" | 4 || int || style="text-align:right;" | 4 || Constant: 0x66
 +
|-
 +
| style="text-align:right;" | 8 || int || style="text-align:right;" | 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
 +
|-
 +
| style="text-align:right;" | 12 || int || style="text-align:right;" | 4 || Constant: 0x2C. Size of the fileinfo block
 +
|-
 +
| style="text-align:right;" | 16 || int || style="text-align:right;" | 4 || Fileinfo block: Corresponding level's random identifier (in lev.compile)
 +
|-
 +
| style="text-align:right;" | 20 || int || style="text-align:right;" | 4 || Fileinfo block: 1 if internal level replay, 0 if external level replay
 +
|-
 +
| style="text-align:right;" | 24 || int || style="text-align:right;" | 4 || Fileinfo block: If Internal -> Pack id (0-3 for A-D), else 0
 +
|-
 +
| style="text-align:right;" | 28 || int || style="text-align:right;" | 4 || Fileinfo block: If Internal -> Level number (0-7 for Levels 1-8), else 0
 +
|-
 +
| style="text-align:right;" | 32 || char[28] || style="text-align:right;" | 28 || Fileinfo block: If external -> levelname.lev, null-terminated, or else null
 +
|-
 +
| style="text-align:right;" | 60 || int || style="text-align:right;" | 4 || n1 - Number of frames: Number must be from 0 to 216000
 +
|-
 +
| style="text-align:right;" | 64 || int || style="text-align:right;" | 4 || n2 - Number of events: Number from 0 to 10000
 +
|-
 +
| style="text-align:right;" | 68 || frame[n1] || style="text-align:right;" | n1*32 || sequential list of n1 frames
 +
|-
 +
| style="text-align:right;" | 68+n1*32 || event[n2] || style="text-align:right;" | n2*16 || sequential list of n2 events
 +
|-
 +
| style="text-align:right;" | 68+n1*32+n2*16 || int || style="text-align:right;" | 4 || Constant: 0x211A3591
 +
|-
 +
|}
 +
 +
=== Frame Object ===
 +
{| class="wikitable"
 +
|+ Frame (32 bytes)
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || float ||  style="text-align:right;" | 4 || Bike x position
 +
|-
 +
| style="text-align:right;" | 4 || float ||  style="text-align:right;" | 4 || Bike y position
 +
|-
 +
| style="text-align:right;" | 8 || short ||  style="text-align:right;" | 2 || Left wheel x
 +
|-
 +
| style="text-align:right;" | 10 || short ||  style="text-align:right;" | 2 || Left wheel y
 +
|-
 +
| style="text-align:right;" | 12 || short ||  style="text-align:right;" | 2 || Right wheel x
 +
|-
 +
| style="text-align:right;" | 14 || short ||  style="text-align:right;" | 2 || Right wheel y
 +
|-
 +
| style="text-align:right;" | 16 || short ||  style="text-align:right;" | 2 || Head x
 +
|-
 +
| style="text-align:right;" | 18 || short ||  style="text-align:right;" | 2 || Head y
 +
|-
 +
| style="text-align:right;" | 20 || short ||  style="text-align:right;" | 2 || Rotation of left wheel. Number from 0 to 9999(?) (I think it's rotation modulo 10000 but not 100% sure)
 +
|-
 +
| style="text-align:right;" | 22 || short ||  style="text-align:right;" | 2 || Rotation of right wheel. Number from 0 to 9999(?) (I think it's rotation modulo 10000 but not 100% sure)
 +
|-
 +
| style="text-align:right;" | 24 || short ||  style="text-align:right;" | 2 || Rotation of bike. Number from 0 to 9999(?) (I think it's rotation modulo 10000 but not 100% sure)
 +
|-
 +
| style="text-align:right;" | 26 || short ||  style="text-align:right;" | 2 || Absolute value of the current rotation speed of the back wheel of the bike (based on the turn direction), normalized so that non-rotating is 1000 and max throttle is 2000. Numbers higher than max throttle are capped at 2000 and the number is clockwise/counterclockwise-independent
 +
|-
 +
| style="text-align:right;" | 30 || int ||  style="text-align:right;" | 4 || Number of frames since the back wheel of the bike has touched a polygon. (if you lift backwheel off the ground, the numbers for the subsequent frames will be 1,2,3,4,5,6 etc). 0 if first frame or if the wheel is touching ground. If the wheel was already in the air and you then turn around in the air, you will get something like (0,0,0,56,57,58 etc). This is most likely used for calculating the throttle sound.
 +
|-
 +
|}
 +
 +
=== 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
 +
 +
{| class="wikitable"
 +
|+ Event (16 bytes)
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || int ||  style="text-align:right;" | 4 || Frame at which event takes place
 +
|-
 +
| style="text-align:right;" | 4 || int ||  style="text-align:right;" | 4 || event_id. If 0, it's an object-touch event, or else (1-7) it's a sound/motion event
 +
|-
 +
| style="text-align:right;" | 8 || int ||  style="text-align:right;" | 4 || object_id. Array id of touched object. 0xFFFFFFFF if event_id != 0
 +
|-
 +
| style="text-align:right;" | 12 || int ||  style="text-align:right;" | 4 || Always 0?
 +
|-
 +
|}
 +
 +
 +
{| class="wikitable"
 +
|+ Sound/Motion Event
 +
|-
 +
! 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 ===
 +
{| class="wikitable"
 +
|+ Mif file
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || int ||  style="text-align:right;" | 4 || .mif header: 100
 +
|-
 +
| style="text-align:right;" | 4 || int ||  style="text-align:right;" | 4 || Length of filename dataset. Fixed at 180,000 or else crash
 +
|-
 +
| style="text-align:right;" | 8 || int ||  style="text-align:right;" | 4 || n: Number of files in filename dataset. Restricted to number 1-1800 inclusive.
 +
|-
 +
| style="text-align:right;" | 12 || fileset ||  style="text-align:right;" | 180000 || List of n filesets, then padded with 0xCD to a length of 180000
 +
|-
 +
| style="text-align:right;" | 180012 || int ||  style="text-align:right;" | 4 || 5B7AAB9Eh
 +
|-
 +
| style="text-align:right;" | 180016 || bytes[?] ||  style="text-align:right;" | ? || Raw stream of all files in a row with no separation. Find the file using the fileset information.
 +
|-
 +
| style="text-align:right;" | ? || int ||  style="text-align:right;" | 4 || 5B7AAB9Eh
 +
|-
 +
|}
 +
 +
=== Fileset ===
 +
 +
{| class="wikitable"
 +
|+ Fileset
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || char[92] ||  style="text-align:right;" | 92 || Filename, null-terminated and padded with 0xCD. e.g. ('example.txt\0\0xCD\0xCD...\0xCD')
 +
|-
 +
| style="text-align:right;" | 92 || int ||  style="text-align:right;" | 4 || Reading from the start of default.mif, the location of the above file (e.g. f.seek(x,0))
 +
|-
 +
| style="text-align:right;" | 96 || int ||  style="text-align:right;" | 4 || Length of the file
 +
|-
 +
|}
 +
 +
=== What files are contained in .mif file? ===
 +
 +
{| class="wikitable"
 +
|+ Fileset
 +
|-
 +
! 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 ==
  
 
{| class="wikitable"
 
{| class="wikitable"
|+ TextureID - some examples (more exist - would be easier to extract all somewhere)
+
|+ State.dat
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || int ||  style="text-align:right;" | 4 || Header: 0x000000D1
 +
|-
 +
| style="text-align:right;" | 4 || int ||  style="text-align:right;" | 8 || 1=Sound on, 0=Sound off
 +
|-
 +
| style="text-align:right;" | 8 || player[20] ||  style="text-align:right;" | 3120 || Sorted list of 20 player objects. If less than 20 players, pad with 0s to maintain full size
 +
|-
 +
| style="text-align:right;" | 3128 || . ||  style="text-align:right;" | . || More stuff... not yet decoded
 +
|-
 +
|}
 +
 
 +
=== Player ===
 +
Contains player settings etc
 +
 
 +
{| class="wikitable"
 +
|+ Player object (156 bytes)
 +
|-
 +
! Offset || Type || Bytes || Description
 +
|-
 +
| style="text-align:right;" | 0 || chr[16] ||  style="text-align:right;" | 16 || Player name
 +
|-
 +
| style="text-align:right;" | 16 || byte[104] ||  style="text-align:right;" | 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
 +
|-
 +
| style="text-align:right;" | 120 || int ||  style="text-align:right;" | 4|| 1=Volts enabled, 0=Volts disabled
 +
|-
 +
| style="text-align:right;" | 124 || int ||  style="text-align:right;" | 4||
 +
|-
 +
| style="text-align:right;" | 128 || int ||  style="text-align:right;" | 4|| 1=Normal keyboard settings. 0=Only one volt button and game chooses volt direction
 +
|-
 +
| style="text-align:right;" | 132 || int ||  style="text-align:right;" | 4||
 +
|-
 +
| style="text-align:right;" | 136 || int ||  style="text-align:right;" | 4|| Some key code representing button for "Thrust"
 
|-
 
|-
! Id || Texture
+
| style="text-align:right;" | 140 || int ||  style="text-align:right;" | 4|| Some key code representing button for "Brake"
 
|-
 
|-
| style="text-align:right;" | 0 || Do not draw
+
| style="text-align:right;" | 144 || int ||  style="text-align:right;" | 4|| Some key code representing button for "Left rotation"
 
|-
 
|-
| style="text-align:right;" | 10 || Border texture (solid medium-colored beige)
+
| style="text-align:right;" | 148 || int ||  style="text-align:right;" | 4|| Some key code representing button for "Right rotation"
 
|-
 
|-
| style="text-align:right;" | 100 || Default ground (sandy rocks)
+
| style="text-align:right;" | 152 || int ||  style="text-align:right;" | 4|| Some key code representing button for "Turn"
 
|-
 
|-
| style="text-align:right;" | 105 || Solid dark green
 
 
|}
 
|}

Latest revision as of 08:56, 11 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 30 if unlocked level, 0 if locked level. Otherwise, assertion error
9 short 2 1 if topology error, 0 if no topology error.
11 int 4 1 if start out facing right (autoturn at level start)
15 char[51] 51 Unused: Level name/description. "Unnamed". Unused but can be hex-edited
66 char[16] 16 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 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 Number of objects + 0.4643643. Maximum 500.
? object ? Sequential list of objects
? double 8 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

Polygon structure
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 id: 0-999
12 int 4 Path 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

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.

LineObject (72 bytes)
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

Object (344 bytes)
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

Picture (54 bytes)
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

Platform
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

Path
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

Runs at about 240 fps (compared to elma1 60 fps)

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

Frame (32 bytes)
Offset Type Bytes Description
0 float 4 Bike x position
4 float 4 Bike y position
8 short 2 Left wheel x
10 short 2 Left wheel y
12 short 2 Right wheel x
14 short 2 Right wheel y
16 short 2 Head x
18 short 2 Head y
20 short 2 Rotation of left wheel. Number from 0 to 9999(?) (I think it's rotation modulo 10000 but not 100% sure)
22 short 2 Rotation of right wheel. Number from 0 to 9999(?) (I think it's rotation modulo 10000 but not 100% sure)
24 short 2 Rotation of bike. Number from 0 to 9999(?) (I think it's rotation modulo 10000 but not 100% sure)
26 short 2 Absolute value of the current rotation speed of the back wheel of the bike (based on the turn direction), normalized so that non-rotating is 1000 and max throttle is 2000. Numbers higher than max throttle are capped at 2000 and the number is clockwise/counterclockwise-independent
30 int 4 Number of frames since the back wheel of the bike has touched a polygon. (if you lift backwheel off the ground, the numbers for the subsequent frames will be 1,2,3,4,5,6 etc). 0 if first frame or if the wheel is touching ground. If the wheel was already in the air and you then turn around in the air, you will get something like (0,0,0,56,57,58 etc). This is most likely used for calculating the throttle sound.

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

Event (16 bytes)
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?


Sound/Motion Event
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

Mif file
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

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?

Fileset
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

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

Player object (156 bytes)
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"