1 #ifndef H_FORMAT
2 #define H_FORMAT
3 
4 #include "utils.h"
5 #include "gameflow.h"
6 #include "savegame.h"
7 
8 #define MAX_RESERVED_ENTITIES 128
9 #define MAX_TRIGGER_COMMANDS  32
10 #define MAX_MESHES            1024
11 #define MAX_WEAPONS           4
12 #define MAX_JOINTS            32
13 
14 // Lara's height in units / height in meters
15 #define ONE_METER             (768.0f / 1.8f)
16 
17 #define TR1_TYPES_START       0
18 #define TR2_TYPES_START       1000
19 #define TR3_TYPES_START       2000
20 #define TR4_TYPES_START       3000
21 
22 
23 #define TR_TYPES(E) \
24     E( LARA                  = TR1_TYPES_START) \
25     E( LARA_PISTOLS          ) \
26     E( LARA_SHOTGUN          ) \
27     E( LARA_MAGNUMS          ) \
28     E( LARA_UZIS             ) \
29     E( LARA_SPEC             ) \
30     E( ENEMY_DOPPELGANGER    ) \
31     E( ENEMY_WOLF            ) \
32     E( ENEMY_BEAR            ) \
33     E( ENEMY_BAT             ) \
34     E( ENEMY_CROCODILE_LAND  ) \
35     E( ENEMY_CROCODILE_WATER ) \
36     E( ENEMY_LION_MALE       ) \
37     E( ENEMY_LION_FEMALE     ) \
38     E( ENEMY_PUMA            ) \
39     E( ENEMY_GORILLA         ) \
40     E( ENEMY_RAT_LAND        ) \
41     E( ENEMY_RAT_WATER       ) \
42     E( ENEMY_REX             ) \
43     E( ENEMY_RAPTOR          ) \
44     E( ENEMY_MUTANT_1        ) \
45     E( ENEMY_MUTANT_2        ) \
46     E( ENEMY_MUTANT_3        ) \
47     E( ENEMY_CENTAUR         ) \
48     E( ENEMY_MUMMY           ) \
49     E( UNUSED_1              ) \
50     E( UNUSED_2              ) \
51     E( ENEMY_LARSON          ) \
52     E( ENEMY_PIERRE          ) \
53     E( ENEMY_SKATEBOARD      ) \
54     E( ENEMY_SKATEBOY        ) \
55     E( ENEMY_COWBOY          ) \
56     E( ENEMY_MR_T            ) \
57     E( ENEMY_NATLA           ) \
58     E( ENEMY_GIANT_MUTANT    ) \
59     E( TRAP_FLOOR            ) \
60     E( TRAP_SWING_BLADE      ) \
61     E( TRAP_SPIKES           ) \
62     E( TRAP_BOULDER          ) \
63     E( DART                  ) \
64     E( TRAP_DART_EMITTER     ) \
65     E( DRAWBRIDGE            ) \
66     E( TRAP_SLAM             ) \
67     E( TRAP_SWORD            ) \
68     E( HAMMER_HANDLE         ) \
69     E( HAMMER_BLOCK          ) \
70     E( LIGHTNING             ) \
71     E( MOVING_OBJECT         ) \
72     E( BLOCK_1               ) \
73     E( BLOCK_2               ) \
74     E( BLOCK_3               ) \
75     E( BLOCK_4               ) \
76     E( MOVING_BLOCK          ) \
77     E( TRAP_CEILING_1        ) \
78     E( TRAP_CEILING_2        ) \
79     E( SWITCH                ) \
80     E( SWITCH_WATER          ) \
81     E( DOOR_1                ) \
82     E( DOOR_2                ) \
83     E( DOOR_3                ) \
84     E( DOOR_4                ) \
85     E( DOOR_5                ) \
86     E( DOOR_6                ) \
87     E( DOOR_7                ) \
88     E( DOOR_8                ) \
89     E( TRAP_DOOR_1           ) \
90     E( TRAP_DOOR_2           ) \
91     E( UNUSED_3              ) \
92     E( BRIDGE_1              ) \
93     E( BRIDGE_2              ) \
94     E( BRIDGE_3              ) \
95     E( INV_PASSPORT          ) \
96     E( INV_COMPASS           ) \
97     E( INV_HOME              ) \
98     E( GEARS_1               ) \
99     E( GEARS_2               ) \
100     E( GEARS_3               ) \
101     E( CUT_1                 ) \
102     E( CUT_2                 ) \
103     E( CUT_3                 ) \
104     E( CUT_4                 ) \
105     E( INV_PASSPORT_CLOSED   ) \
106     E( INV_MAP               ) \
107     E( CRYSTAL               ) \
108     E( PISTOLS               ) \
109     E( SHOTGUN               ) \
110     E( MAGNUMS               ) \
111     E( UZIS                  ) \
112     E( AMMO_PISTOLS          ) \
113     E( AMMO_SHOTGUN          ) \
114     E( AMMO_MAGNUMS          ) \
115     E( AMMO_UZIS             ) \
116     E( EXPLOSIVE             ) \
117     E( MEDIKIT_SMALL         ) \
118     E( MEDIKIT_BIG           ) \
119     E( INV_DETAIL            ) \
120     E( INV_SOUND             ) \
121     E( INV_CONTROLS          ) \
122     E( INV_GAMMA             ) \
123     E( INV_PISTOLS           ) \
124     E( INV_SHOTGUN           ) \
125     E( INV_MAGNUMS           ) \
126     E( INV_UZIS              ) \
127     E( INV_AMMO_PISTOLS      ) \
128     E( INV_AMMO_SHOTGUN      ) \
129     E( INV_AMMO_MAGNUMS      ) \
130     E( INV_AMMO_UZIS         ) \
131     E( INV_EXPLOSIVE         ) \
132     E( INV_MEDIKIT_SMALL     ) \
133     E( INV_MEDIKIT_BIG       ) \
134     E( PUZZLE_1              ) \
135     E( PUZZLE_2              ) \
136     E( PUZZLE_3              ) \
137     E( PUZZLE_4              ) \
138     E( INV_PUZZLE_1          ) \
139     E( INV_PUZZLE_2          ) \
140     E( INV_PUZZLE_3          ) \
141     E( INV_PUZZLE_4          ) \
142     E( PUZZLE_HOLE_1         ) \
143     E( PUZZLE_HOLE_2         ) \
144     E( PUZZLE_HOLE_3         ) \
145     E( PUZZLE_HOLE_4         ) \
146     E( PUZZLE_DONE_1         ) \
147     E( PUZZLE_DONE_2         ) \
148     E( PUZZLE_DONE_3         ) \
149     E( PUZZLE_DONE_4         ) \
150     E( LEADBAR               ) \
151     E( INV_LEADBAR           ) \
152     E( MIDAS_HAND            ) \
153     E( KEY_ITEM_1            ) \
154     E( KEY_ITEM_2            ) \
155     E( KEY_ITEM_3            ) \
156     E( KEY_ITEM_4            ) \
157     E( INV_KEY_ITEM_1        ) \
158     E( INV_KEY_ITEM_2        ) \
159     E( INV_KEY_ITEM_3        ) \
160     E( INV_KEY_ITEM_4        ) \
161     E( KEY_HOLE_1            ) \
162     E( KEY_HOLE_2            ) \
163     E( KEY_HOLE_3            ) \
164     E( KEY_HOLE_4            ) \
165     E( UNUSED_4              ) \
166     E( UNUSED_5              ) \
167     E( SCION_PICKUP_QUALOPEC ) \
168     E( SCION_PICKUP_DROP     ) \
169     E( SCION_TARGET          ) \
170     E( SCION_PICKUP_HOLDER   ) \
171     E( SCION_HOLDER          ) \
172     E( UNUSED_6              ) \
173     E( UNUSED_7              ) \
174     E( INV_SCION             ) \
175     E( EXPLOSION             ) \
176     E( UNUSED_8              ) \
177     E( WATER_SPLASH          ) \
178     E( UNUSED_9              ) \
179     E( BUBBLE                ) \
180     E( UNUSED_10             ) \
181     E( UNUSED_11             ) \
182     E( BLOOD                 ) \
183     E( UNUSED_12             ) \
184     E( SMOKE                 ) \
185     E( CENTAUR_STATUE        ) \
186     E( CABIN                 ) \
187     E( MUTANT_EGG_SMALL      ) \
188     E( RICOCHET              ) \
189     E( SPARKLES              ) \
190     E( MUZZLE_FLASH          ) \
191     E( UNUSED_13             ) \
192     E( UNUSED_14             ) \
193     E( VIEW_TARGET           ) \
194     E( WATERFALL             ) \
195     E( NATLA_BULLET          ) \
196     E( MUTANT_BULLET         ) \
197     E( CENTAUR_BULLET        ) \
198     E( UNUSED_16             ) \
199     E( UNUSED_17             ) \
200     E( LAVA_PARTICLE         ) \
201     E( TRAP_LAVA_EMITTER     ) \
202     E( FLAME                 ) \
203     E( TRAP_FLAME_EMITTER    ) \
204     E( TRAP_LAVA             ) \
205     E( MUTANT_EGG_BIG        ) \
206     E( BOAT                  ) \
207     E( EARTHQUAKE            ) \
208     E( UNUSED_18             ) \
209     E( UNUSED_19             ) \
210     E( UNUSED_20             ) \
211     E( UNUSED_21             ) \
212     E( UNUSED_22             ) \
213     E( LARA_BRAID            ) \
214     E( GLYPHS                ) \
215     E( TR1_TYPE_MAX          ) \
216     E( _LARA                 = TR2_TYPES_START ) \
217     E( _LARA_PISTOLS         ) \
218     E( _LARA_BRAID           ) \
219     E( _LARA_SHOTGUN         ) \
220     E( LARA_AUTOPISTOLS      ) \
221     E( _LARA_UZIS            ) \
222     E( LARA_M16              ) \
223     E( LARA_GRENADE          ) \
224     E( LARA_HARPOON          ) \
225     E( LARA_FLARE            ) \
226     E( LARA_SNOWMOBILE       ) \
227     E( LARA_BOAT             ) \
228     E( _LARA_SPEC            ) \
229     E( VEHICLE_SNOWMOBILE_RED ) \
230     E( VEHICLE_BOAT          ) \
231     E( ENEMY_DOG             ) \
232     E( ENEMY_GOON_MASK_1     ) \
233     E( ENEMY_GOON_MASK_2     ) \
234     E( ENEMY_GOON_MASK_3     ) \
235     E( ENEMY_GOON_KNIFE      ) \
236     E( ENEMY_GOON_SHOTGUN    ) \
237     E( ENEMY_RAT             ) \
238     E( ENEMY_DRAGON_FRONT    ) \
239     E( ENEMY_DRAGON_BACK     ) \
240     E( GONDOLA               ) \
241     E( ENEMY_SHARK           ) \
242     E( ENEMY_MORAY_1         ) \
243     E( ENEMY_MORAY_2         ) \
244     E( ENEMY_BARACUDA        ) \
245     E( ENEMY_DIVER           ) \
246     E( ENEMY_GUNMAN_1        ) \
247     E( ENEMY_GUNMAN_2        ) \
248     E( ENEMY_GOON_STICK_1    ) \
249     E( ENEMY_GOON_STICK_2    ) \
250     E( ENEMY_GOON_FLAME      ) \
251     E( UNUSED_23             ) \
252     E( ENEMY_SPIDER          ) \
253     E( ENEMY_SPIDER_GIANT    ) \
254     E( ENEMY_CROW            ) \
255     E( ENEMY_TIGER           ) \
256     E( ENEMY_MARCO           ) \
257     E( ENEMY_GUARD_SPEAR     ) \
258     E( ENEMY_GUARD_SPEAR_STATUE )\
259     E( ENEMY_GUARD_SWORD     ) \
260     E( ENEMY_GUARD_SWORD_STATUE ) \
261     E( ENEMY_YETI            ) \
262     E( ENEMY_BIRD_MONSTER    ) \
263     E( ENEMY_EAGLE           ) \
264     E( ENEMY_MERCENARY_1     ) \
265     E( ENEMY_MERCENARY_2     ) \
266     E( ENEMY_MERCENARY_3     ) \
267     E( VEHICLE_SNOWMOBILE_BLACK ) \
268     E( ENEMY_MERCENARY_SNOWMOBILE ) \
269     E( ENEMY_MONK_1          ) \
270     E( ENEMY_MONK_2          ) \
271     E( _TRAP_FLOOR           ) \
272     E( UNUSED_24             ) \
273     E( TRAP_BOARDS           ) \
274     E( TRAP_SWING_BAG        ) \
275     E( _TRAP_SPIKES          ) \
276     E( _TRAP_BOULDER         ) \
277     E( _DART                 ) \
278     E( _TRAP_DART_EMITTER    ) \
279     E( _DRAWBRIDGE           ) \
280     E( _TRAP_SLAM            ) \
281     E( ELEVATOR              ) \
282     E( MINISUB               ) \
283     E( _BLOCK_1              ) \
284     E( _BLOCK_2              ) \
285     E( _BLOCK_3              ) \
286     E( _BLOCK_4              ) \
287     E( LAVA_BOWL             ) \
288     E( WINDOW_1              ) \
289     E( WINDOW_2              ) \
290     E( UNUSED_25             ) \
291     E( UNUSED_26             ) \
292     E( PROPELLER_PLANE       ) \
293     E( SAW                   ) \
294     E( HOOK                  ) \
295     E( _TRAP_CEILING_1       ) \
296     E( TRAP_SPINDLE          ) \
297     E( TRAP_BLADE_WALL       ) \
298     E( TRAP_BLADE_STATUE     ) \
299     E( TRAP_BOULDERS         ) \
300     E( TRAP_ICICLES          ) \
301     E( TRAP_SPIKES_WALL      ) \
302     E( JUMPPAD               ) \
303     E( TRAP_SPIKES_CEILING   ) \
304     E( BELL                  ) \
305     E( WAKE_BOAT             ) \
306     E( WAKE_SNOWMOBILE       ) \
307     E( SNOWMOBILE_BELT       ) \
308     E( WHEEL_KNOB            ) \
309     E( SWITCH_BIG            ) \
310     E( PROPELLER_WATER       ) \
311     E( PROPELLER_AIR         ) \
312     E( TRAP_SWING_BOX        ) \
313     E( _CUT_1                ) \
314     E( _CUT_2                ) \
315     E( _CUT_3                ) \
316     E( UI_FRAME              ) \
317     E( ROLLING_DRUMS         ) \
318     E( ZIPLINE_HANDLE        ) \
319     E( SWITCH_BUTTON         ) \
320     E( _SWITCH               ) \
321     E( _SWITCH_WATER         ) \
322     E( _DOOR_1               ) \
323     E( _DOOR_2               ) \
324     E( _DOOR_3               ) \
325     E( _DOOR_4               ) \
326     E( _DOOR_5               ) \
327     E( _DOOR_6               ) \
328     E( _DOOR_7               ) \
329     E( _DOOR_8               ) \
330     E( _TRAP_DOOR_1          ) \
331     E( _TRAP_DOOR_2          ) \
332     E( TRAP_DOOR_3           ) \
333     E( _BRIDGE_1             ) \
334     E( _BRIDGE_2             ) \
335     E( _BRIDGE_3             ) \
336     E( _INV_PASSPORT         ) \
337     E( INV_STOPWATCH         ) \
338     E( _INV_HOME             ) \
339     E( _CUT_4                ) \
340     E( CUT_5                 ) \
341     E( CUT_6                 ) \
342     E( CUT_7                 ) \
343     E( CUT_8                 ) \
344     E( CUT_9                 ) \
345     E( CUT_10                ) \
346     E( CUT_11                ) \
347     E( UNUSED_27             ) \
348     E( UNUSED_28             ) \
349     E( _INV_PASSPORT_CLOSED  ) \
350     E( _INV_MAP              ) \
351     E( _PISTOLS              ) \
352     E( _SHOTGUN              ) \
353     E( AUTOPISTOLS           ) \
354     E( _UZIS                 ) \
355     E( HARPOON               ) \
356     E( M16                   ) \
357     E( GRENADE               ) \
358     E( _AMMO_PISTOLS         ) \
359     E( _AMMO_SHOTGUN         ) \
360     E( AMMO_AUTOPISTOLS      ) \
361     E( _AMMO_UZIS            ) \
362     E( AMMO_HARPOON          ) \
363     E( AMMO_M16              ) \
364     E( AMMO_GRENADE          ) \
365     E( _MEDIKIT_SMALL        ) \
366     E( _MEDIKIT_BIG          ) \
367     E( FLARES                ) \
368     E( FLARE                 ) \
369     E( _INV_DETAIL           ) \
370     E( _INV_SOUND            ) \
371     E( _INV_CONTROLS         ) \
372     E( UNUSED_29             ) \
373     E( _INV_PISTOLS          ) \
374     E( _INV_SHOTGUN          ) \
375     E( INV_AUTOPISTOLS       ) \
376     E( _INV_UZIS             ) \
377     E( INV_HARPOON           ) \
378     E( INV_M16               ) \
379     E( INV_GRENADE           ) \
380     E( _INV_AMMO_PISTOLS     ) \
381     E( _INV_AMMO_SHOTGUN     ) \
382     E( INV_AMMO_AUTOPISTOLS  ) \
383     E( _INV_AMMO_UZIS        ) \
384     E( INV_AMMO_HARPOON      ) \
385     E( INV_AMMO_M16          ) \
386     E( INV_AMMO_GRENADE      ) \
387     E( _INV_MEDIKIT_SMALL    ) \
388     E( _INV_MEDIKIT_BIG      ) \
389     E( INV_FLARES            ) \
390     E( _PUZZLE_1             ) \
391     E( _PUZZLE_2             ) \
392     E( _PUZZLE_3             ) \
393     E( _PUZZLE_4             ) \
394     E( _INV_PUZZLE_1         ) \
395     E( _INV_PUZZLE_2         ) \
396     E( _INV_PUZZLE_3         ) \
397     E( _INV_PUZZLE_4         ) \
398     E( _PUZZLE_HOLE_1        ) \
399     E( _PUZZLE_HOLE_2        ) \
400     E( _PUZZLE_HOLE_3        ) \
401     E( _PUZZLE_HOLE_4        ) \
402     E( _PUZZLE_DONE_1        ) \
403     E( _PUZZLE_DONE_2        ) \
404     E( _PUZZLE_DONE_3        ) \
405     E( _PUZZLE_DONE_4        ) \
406     E( SECRET_1              ) \
407     E( SECRET_2              ) \
408     E( SECRET_3              ) \
409     E( _KEY_ITEM_1           ) \
410     E( _KEY_ITEM_2           ) \
411     E( _KEY_ITEM_3           ) \
412     E( _KEY_ITEM_4           ) \
413     E( _INV_KEY_ITEM_1       ) \
414     E( _INV_KEY_ITEM_2       ) \
415     E( _INV_KEY_ITEM_3       ) \
416     E( _INV_KEY_ITEM_4       ) \
417     E( _KEY_HOLE_1           ) \
418     E( _KEY_HOLE_2           ) \
419     E( _KEY_HOLE_3           ) \
420     E( _KEY_HOLE_4           ) \
421     E( QUEST_ITEM_1          ) \
422     E( QUEST_ITEM_2          ) \
423     E( INV_QUEST_ITEM_1      ) \
424     E( INV_QUEST_ITEM_2      ) \
425     E( DRAGON_EXPLOSION_1    ) \
426     E( DRAGON_EXPLOSION_2    ) \
427     E( DRAGON_EXPLOSION_3    ) \
428     E( SOUND_ALARM           ) \
429     E( SOUND_WATER           ) \
430     E( _ENEMY_REX            ) \
431     E( SOUND_BIRD            ) \
432     E( SOUND_CLOCK           ) \
433     E( SOUND_PLACEHOLDER     ) \
434     E( DRAGON_BONES_FRONT    ) \
435     E( DRAGON_BONES_BACK     ) \
436     E( TRAP_EXTRA_FIRE       ) \
437     E( TRAP_MINE             ) \
438     E( UNUSED_30             ) \
439     E( INV_BACKGROUND        ) \
440     E( GRAY_DISK             ) \
441     E( GONG_STICK            ) \
442     E( GONG                  ) \
443     E( DETONATOR             ) \
444     E( HELICOPTER            ) \
445     E( _EXPLOSION            ) \
446     E( _WATER_SPLASH         ) \
447     E( _BUBBLE               ) \
448     E( UNUSED_31             ) \
449     E( _BLOOD                ) \
450     E( UNUSED_32             ) \
451     E( FLARE_SPARKLES        ) \
452     E( MUZZLE_GLOW           ) \
453     E( UNUSED_33             ) \
454     E( _RICOCHET             ) \
455     E( UNUSED_34             ) \
456     E( _MUZZLE_FLASH         ) \
457     E( MUZZLE_FLASH_M16      ) \
458     E( UNUSED_35             ) \
459     E( _VIEW_TARGET          ) \
460     E( _WATERFALL            ) \
461     E( HARPOON_WTF           ) \
462     E( UNUSED_36             ) \
463     E( UNUSED_37             ) \
464     E( GRENADE_BULLET        ) \
465     E( HARPOON_BULLET        ) \
466     E( _LAVA_PARTICLE        ) \
467     E( _TRAP_LAVA_EMITTER    ) \
468     E( _FLAME                ) \
469     E( _TRAP_FLAME_EMITTER   ) \
470     E( SKY                   ) \
471     E( _GLYPHS               ) \
472     E( ENEMY_MONK_3          ) \
473     E( SOUND_DOOR_BELL       ) \
474     E( SOUND_ALARM_BELL      ) \
475     E( HELICOPTER_FLYING     ) \
476     E( ENEMY_WINSTON         ) \
477     E( UNUSED_38             ) \
478     E( LARA_END_PLACE        ) \
479     E( LARA_END_SHOTGUN      ) \
480     E( DRAGON_EXPLSION_EMITTER ) \
481     E( TR2_TYPE_MAX          ) \
482     E( __LARA                = TR3_TYPES_START ) \
483     E( __LARA_PISTOLS        ) \
484     E( __LARA_BRAID          ) \
485     E( __LARA_SHOTGUN        ) \
486     E( LARA_DESERT_EAGLE     ) \
487     E( __LARA_UZIS           ) \
488     E( LARA_MP5              ) \
489     E( LARA_ROCKET           ) \
490     E( __LARA_GRENADE        ) \
491     E( __LARA_HARPOON        ) \
492     E( __LARA_FLARE          ) \
493     E( LARA_UPV              ) \
494     E( VEHICLE_UPV           ) \
495     E( UNUSED_TR3_13         ) \
496     E( VEHICLE_KAYAK         ) \
497     E( __VEHICLE_BOAT        ) \
498     E( VEHICLE_QUADBIKE      ) \
499     E( VEHICLE_MINECART      ) \
500     E( BIG_GUN               ) \
501     E( HYDRO_PROPELLER       ) \
502     E( ENEMY_TRIBESMAN_AXE   ) \
503     E( ENEMY_TRIBESMAN_DART  ) \
504     E( __ENEMY_DOG           ) \
505     E( __ENEMY_RAT           ) \
506     E( KILL_ALL_TRIGGERS     ) \
507     E( ENEMY_WHALE           ) \
508     E( __ENEMY_DIVER         ) \
509     E( __ENEMY_CROW          ) \
510     E( __ENEMY_TIGER         ) \
511     E( ENEMY_VULTURE         ) \
512     E( ASSAULT_TARGET        ) \
513     E( ENEMY_CRAWLER_MUTANT_1  ) \
514     E( ENEMY_ALLIGATOR       ) \
515     E( UNUSED_TR3_33         ) \
516     E( ENEMY_COMPSOGNATHUS   ) \
517     E( ENEMY_LIZARD_MAN      ) \
518     E( ENEMY_PUNA            ) \
519     E( ENEMY_MERCENARY       ) \
520     E( ENEMY_RAPTOR_HUNG     ) \
521     E( ENEMY_RX_TECH_GUY_1   ) \
522     E( ENEMY_RX_TECH_GUY_2   ) \
523     E( ENEMY_ANTARC_DOG      ) \
524     E( ENEMY_CRAWLER_MUTANT_2  ) \
525     E( UNUSED_TR3_43         ) \
526     E( ENEMY_TINNOS_WASP     ) \
527     E( ENEMY_TINNOS_MONSTER  ) \
528     E( ENEMY_BRUTE_MUTANT    ) \
529     E( RESPAWN_TINNOS_WASP   ) \
530     E( RESPAWN_RAPTOR        ) \
531     E( ENEMY_WILLARD_SPIDER  ) \
532     E( ENEMY_RX_TECH_FLAME_GUY ) \
533     E( ENEMY_LONDON_MERCENARY  ) \
534     E( UNUSED_TR3_52         ) \
535     E( ENEMY_PUNK            ) \
536     E( UNUSED_TR3_54         ) \
537     E( UNUSED_TR3_55         ) \
538     E( ENEMY_LONDON_GUARD    ) \
539     E( ENEMY_SOPHIA          ) \
540     E( CLEANER_ROBOT         ) \
541     E( UNUSED_TR3_59         ) \
542     E( ENEMY_MILITARY_1      ) \
543     E( ENEMY_MILITARY_2      ) \
544     E( PRISONER              ) \
545     E( ENEMY_MILITARY_3      ) \
546     E( GUN_TURRET            ) \
547     E( ENEMY_DAM_GUARD       ) \
548     E( TRIPWIRE              ) \
549     E( ELECTRIC_WIRE         ) \
550     E( KILLER_TRIPWIRE       ) \
551     E( ENEMY_COBRA           ) \
552     E( ENEMY_SHIVA           ) \
553     E( ENEMY_MONKEY          ) \
554     E( UNUSED_TR3_72         ) \
555     E( ENEMY_TONY            ) \
556     E( AI_GUARD              ) \
557     E( AI_AMBUSH             ) \
558     E( AI_PATROL_1           ) \
559     E( AI_MODIFY             ) \
560     E( AI_FOLLOW             ) \
561     E( AI_PATROL_2           ) \
562     E( AI_PATH               ) \
563     E( AI_CHECK              ) \
564     E( UNUSED_TR3_82         ) \
565     E( __TRAP_FLOOR          ) \
566     E( UNUSED_TR3_84         ) \
567     E( UNUSED_TR3_85         ) \
568     E( TRAP_SWING_THING      ) \
569     E( __TRAP_SPIKES         ) \
570     E( __TRAP_BOULDER        ) \
571     E( TRAP_BOULDER_GIANT    ) \
572     E( __DART                ) \
573     E( __TRAP_DART_EMITTER   ) \
574     E( UNUSED_TR3_92         ) \
575     E( UNUSED_TR3_93         ) \
576     E( TRAP_SKELETON         ) \
577     E( __BLOCK_1             ) \
578     E( __BLOCK_2             ) \
579     E( __BLOCK_3             ) \
580     E( __BLOCK_4             ) \
581     E( UNUSED_TR3_99         ) \
582     E( UNUSED_TR3_100        ) \
583     E( __WINDOW_1            ) \
584     E( __WINDOW_2            ) \
585     E( UNUSED_TR3_103        ) \
586     E( UNUSED_TR3_104        ) \
587     E( UNUSED_TR3_105        ) \
588     E( AREA51_SWINGER        ) \
589     E( __TRAP_CEILING_1      ) \
590     E( __TRAP_SPINDLE        ) \
591     E( UNUSED_TR3_109        ) \
592     E( SUBWAY_TRAIN          ) \
593     E( TRAP_WALL_KNIFE_BLADE ) \
594     E( UNUSED_TR3_112        ) \
595     E( __TRAP_ICICLES        ) \
596     E( __TRAP_SPIKES_WALL    ) \
597     E( UNUSED_TR3_115        ) \
598     E( TRAP_SPIKES_VERT      ) \
599     E( __WHEEL_KNOB          ) \
600     E( __SWITCH_BIG          ) \
601     E( __CUT_1               ) \
602     E( __CUT_2               ) \
603     E( __CUT_3               ) \
604     E( SHIVA_STATUE          ) \
605     E( MONKEY_MEDIPACK       ) \
606     E( MONKEY_KEY            ) \
607     E( __UI_FRAME            ) \
608     E( UNUSED_TR3_126        ) \
609     E( __ZIPLINE_HANDLE      ) \
610     E( __SWITCH_BUTTON       ) \
611     E( __SWITCH              ) \
612     E( __SWITCH_WATER        ) \
613     E( __DOOR_1              ) \
614     E( __DOOR_2              ) \
615     E( __DOOR_3              ) \
616     E( __DOOR_4              ) \
617     E( __DOOR_5              ) \
618     E( __DOOR_6              ) \
619     E( __DOOR_7              ) \
620     E( __DOOR_8              ) \
621     E( __TRAP_DOOR_1         ) \
622     E( __TRAP_DOOR_2         ) \
623     E( __TRAP_DOOR_3         ) \
624     E( __BRIDGE_1            ) \
625     E( __BRIDGE_2            ) \
626     E( __BRIDGE_3            ) \
627     E( __INV_PASSPORT        ) \
628     E( __INV_STOPWATCH       ) \
629     E( __INV_HOME            ) \
630     E( __CUT_4               ) \
631     E( __CUT_5               ) \
632     E( __CUT_6               ) \
633     E( __CUT_7               ) \
634     E( __CUT_8               ) \
635     E( __CUT_9               ) \
636     E( __CUT_10              ) \
637     E( __CUT_11              ) \
638     E( CUT_12                ) \
639     E( UNUSED_TR3_157        ) \
640     E( __INV_PASSPORT_CLOSED ) \
641     E( __INV_MAP             ) \
642     E( __PISTOLS             ) \
643     E( __SHOTGUN             ) \
644     E( DESERT_EAGLE          ) \
645     E( __UZIS                ) \
646     E( __HARPOON             ) \
647     E( MP5                   ) \
648     E( ROCKET                ) \
649     E( __GRENADE             ) \
650     E( __AMMO_PISTOLS        ) \
651     E( __AMMO_SHOTGUN        ) \
652     E( AMMO_DESERT_EAGLE     ) \
653     E( __AMMO_UZIS           ) \
654     E( __AMMO_HARPOON        ) \
655     E( AMMO_MP5              ) \
656     E( AMMO_ROCKET           ) \
657     E( __AMMO_GRENADE        ) \
658     E( __MEDIKIT_SMALL       ) \
659     E( __MEDIKIT_BIG         ) \
660     E( __FLARES              ) \
661     E( __FLARE               ) \
662     E( CRYSTAL_PICKUP        ) \
663     E( __INV_DETAIL          ) \
664     E( __INV_SOUND           ) \
665     E( __INV_CONTROLS        ) \
666     E( INV_GLOBE             ) \
667     E( __INV_PISTOLS         ) \
668     E( __INV_SHOTGUN         ) \
669     E( INV_DESERT_EAGLE      ) \
670     E( __INV_UZIS            ) \
671     E( __INV_HARPOON         ) \
672     E( INV_MP5               ) \
673     E( INV_ROCKET            ) \
674     E( __INV_GRENADE         ) \
675     E( __INV_AMMO_PISTOLS    ) \
676     E( __INV_AMMO_SHOTGUN    ) \
677     E( INV_AMMO_DESERT_EAGLE ) \
678     E( __INV_AMMO_UZIS       ) \
679     E( __INV_AMMO_HARPOON    ) \
680     E( INV_AMMO_MP5          ) \
681     E( INV_AMMO_ROCKET       ) \
682     E( __INV_AMMO_GRENADE    ) \
683     E( __INV_MEDIKIT_SMALL   ) \
684     E( __INV_MEDIKIT_BIG     ) \
685     E( __INV_FLARES          ) \
686     E( INV_CRYSTAL           ) \
687     E( __PUZZLE_1            ) \
688     E( __PUZZLE_2            ) \
689     E( __PUZZLE_3            ) \
690     E( __PUZZLE_4            ) \
691     E( __INV_PUZZLE_1        ) \
692     E( __INV_PUZZLE_2        ) \
693     E( __INV_PUZZLE_3        ) \
694     E( __INV_PUZZLE_4        ) \
695     E( __PUZZLE_HOLE_1       ) \
696     E( __PUZZLE_HOLE_2       ) \
697     E( __PUZZLE_HOLE_3       ) \
698     E( __PUZZLE_HOLE_4       ) \
699     E( __PUZZLE_DONE_1       ) \
700     E( __PUZZLE_DONE_2       ) \
701     E( __PUZZLE_DONE_3       ) \
702     E( __PUZZLE_DONE_4       ) \
703     E( UNUSER_TR3_121        ) \
704     E( UNUSER_TR3_122        ) \
705     E( UNUSER_TR3_123        ) \
706     E( __KEY_ITEM_1          ) \
707     E( __KEY_ITEM_2          ) \
708     E( __KEY_ITEM_3          ) \
709     E( __KEY_ITEM_4          ) \
710     E( __INV_KEY_ITEM_1      ) \
711     E( __INV_KEY_ITEM_2      ) \
712     E( __INV_KEY_ITEM_3      ) \
713     E( __INV_KEY_ITEM_4      ) \
714     E( __KEY_HOLE_1          ) \
715     E( __KEY_HOLE_2          ) \
716     E( __KEY_HOLE_3          ) \
717     E( __KEY_HOLE_4          ) \
718     E( __QUEST_ITEM_1        ) \
719     E( __QUEST_ITEM_2        ) \
720     E( __INV_QUEST_ITEM_1    ) \
721     E( __INV_QUEST_ITEM_2    ) \
722     E( STONE_ITEM_1          ) \
723     E( STONE_ITEM_2          ) \
724     E( STONE_ITEM_3          ) \
725     E( STONE_ITEM_4          ) \
726     E( INV_STONE_ITEM_1      ) \
727     E( INV_STONE_ITEM_2      ) \
728     E( INV_STONE_ITEM_3      ) \
729     E( INV_STONE_ITEM_4      ) \
730     E( UNUSED_TR3_248        ) \
731     E( UNUSED_TR3_249        ) \
732     E( UNUSED_TR3_250        ) \
733     E( UNUSED_TR3_251        ) \
734     E( UNUSED_TR3_252        ) \
735     E( UNUSED_TR3_253        ) \
736     E( UNUSED_TR3_254        ) \
737     E( UNUSED_TR3_255        ) \
738     E( UNUSED_TR3_256        ) \
739     E( UNUSED_TR3_257        ) \
740     E( UNUSED_TR3_258        ) \
741     E( UNUSED_TR3_259        ) \
742     E( UNUSED_TR3_260        ) \
743     E( UNUSED_TR3_261        ) \
744     E( UNUSED_TR3_262        ) \
745     E( UNUSED_TR3_263        ) \
746     E( UNUSED_TR3_264        ) \
747     E( UNUSED_TR3_265        ) \
748     E( UNUSED_TR3_266        ) \
749     E( UNUSED_TR3_267        ) \
750     E( UNUSED_TR3_268        ) \
751     E( UNUSED_TR3_269        ) \
752     E( UNUSED_TR3_270        ) \
753     E( UNUSED_TR3_271        ) \
754     E( KEYS_SPRITE_1         ) \
755     E( KEYS_SPRITE_2         ) \
756     E( UNUSED_TR3_274        ) \
757     E( UNUSED_TR3_275        ) \
758     E( STONE_ITEM_PLACE_1    ) \
759     E( STONE_ITEM_PLACE_2    ) \
760     E( STONE_ITEM_PLACE_3    ) \
761     E( STONE_ITEM_PLACE_4    ) \
762     E( UNUSED_TR3_280        ) \
763     E( UNUSED_TR3_281        ) \
764     E( DRAGON_STATUE         ) \
765     E( UNUSED_TR3_283        ) \
766     E( UNUSED_TR3_284        ) \
767     E( UNKNOWN_VISIBLE       ) \
768     E( UNUSED_TR3_286        ) \
769     E( __ENEMY_REX           ) \
770     E( __ENEMY_RAPTOR        ) \
771     E( UNUSED_TR3_289        ) \
772     E( UNUSED_TR3_290        ) \
773     E( LASER_SWEEPER         ) \
774     E( ELECTRIC_FILER        ) \
775     E( UNUSED_TR3_293        ) \
776     E( SHADOW_SPRITE         ) \
777     E( __DETONATOR           ) \
778     E( MISC_SPRITES          ) \
779     E( __BUBBLE              ) \
780     E( UNUSED_TR3_298        ) \
781     E( __MUZZLE_GLOW         ) \
782     E( __MUZZLE_FLASH        ) \
783     E( MUZZLE_FLASH_MP5      ) \
784     E( UNUSED_TR3_302        ) \
785     E( UNUSED_TR3_303        ) \
786     E( __VIEW_TARGET         ) \
787     E( __WATERFALL           ) \
788     E( __HARPOON_WTF         ) \
789     E( UNUSED_TR3_307        ) \
790     E( UNUSED_TR3_308        ) \
791     E( BULLET_ROCKET         ) \
792     E( BULLET_HARPOON        ) \
793     E( BULLET_GRENADE        ) \
794     E( BIG_MISSILE           ) \
795     E( __SMOKE               ) \
796     E( MOVABLE_BOOM          ) \
797     E( LARA_SKIN             ) \
798     E( GLOW_2                ) \
799     E( UNKNONW_TR3_VISIBLE   ) \
800     E( LIGHT_1               ) \
801     E( LIGHT_2               ) \
802     E( LIGHT_3               ) \
803     E( LIGHT_4               ) \
804     E( LIGHT_5               ) \
805     E( LIGHT_6               ) \
806     E( LIGHT_7               ) \
807     E( LIGHT_8               ) \
808     E( LIGHT_9               ) \
809     E( LIGHT_10              ) \
810     E( LIGHT_11              ) \
811     E( UNUSED_TR3_329        ) \
812     E( PARTICLE_FIRE_1       ) \
813     E( PARTICLE_FIRE_2       ) \
814     E( PARTICLE_FIRE_3       ) \
815     E( PARTICLE_FIRE_4       ) \
816     E( PARTICLE_SMOKE_1      ) \
817     E( PARTICLE_SMOKE_2      ) \
818     E( PARTICLE_SMOKE_3      ) \
819     E( PARTICLE_SMOKE_4      ) \
820     E( ENEMY_PIRANHAS        ) \
821     E( ENEMY_FISH            ) \
822     E( UNUSED_TR3_340        ) \
823     E( UNUSED_TR3_341        ) \
824     E( UNUSED_TR3_342        ) \
825     E( UNUSED_TR3_343        ) \
826     E( UNUSED_TR3_344        ) \
827     E( UNUSED_TR3_345        ) \
828     E( UNUSED_TR3_346        ) \
829     E( ENEMY_BAT_SWARM       ) \
830     E( UNUSED_TR3_348        ) \
831     E( ANIMATING_1           ) \
832     E( ANIMATING_2           ) \
833     E( ANIMATING_3           ) \
834     E( ANIMATING_4           ) \
835     E( ANIMATING_5           ) \
836     E( ANIMATING_6           ) \
837     E( __SKY                 ) \
838     E( __GLYPHS              ) \
839     E( __SOUND_DOOR_BELL     ) \
840     E( UNUSED_TR3_358        ) \
841     E( UNUSED_TR3_359        ) \
842     E( __ENEMY_WINSTON       ) \
843     E( ENEMY_WINSTON_CAMO    ) \
844     E( GLYPHS_TIMER          ) \
845     E( UNUSED_TR3_363        ) \
846     E( UNUSED_TR3_364        ) \
847     E( __EARTHQUAKE          ) \
848     E( GUN_SHELL_1           ) \
849     E( GUN_SHELL_2           ) \
850     E( UNUSED_TR3_368        ) \
851     E( UNUSED_TR3_369        ) \
852     E( TINNOS_LIGHT_SHAFT    ) \
853     E( UNUSED_TR3_371        ) \
854     E( UNUSED_TR3_372        ) \
855     E( ELECTRIC_SWITCH       ) \
856     E( TR3_TYPE_MAX          ) \
857     E( ___LARA               = TR4_TYPES_START ) \
858     E( ___LARA_PISTOLS       ) \
859     E( ___LARA_UZIS          ) \
860     E( ___LARA_SHOTGUN       ) \
861     E( LARA_CROSSBOW         ) \
862     E( ___LARA_GRENADE       ) \
863     E( LARA_REVOLVER         ) \
864     E( ___LARA_FLARE         ) \
865     E( ___LARA_SKIN          ) \
866     E( LARA_SKIN_JOINTS      ) \
867     E( LARA_SCREAM           ) \
868     E( LARA_CROSSBOW_LASER   ) \
869     E( LARA_REVOLVER_LASER   ) \
870     E( LARA_HOLSTERS         ) \
871     E( LARA_HOLSTERS_PISTOLS ) \
872     E( LARA_HOLSTERS_UZIS    ) \
873     E( LARA_HOLSTERS_REVOLVER ) \
874     E( LARA_HEAD1            ) \
875     E( LARA_HEAD2            ) \
876     E( LARA_HEAD3            ) \
877     E( LARA_HEAD4            ) \
878     E( ACTOR1_HEAD1          ) \
879     E( ACTOR1_HEAD2          ) \
880     E( ACTOR2_HEAD1          ) \
881     E( ACTOR2_HEAD2          ) \
882     E( LARA_WATER_MESH       ) \
883     E( LARA_PETROL_MESH      ) \
884     E( LARA_DIRT_MESH        ) \
885     E( CROWBAR_ANIM          ) \
886     E( TORCH_ANIM            ) \
887     E( ___LARA_BRAID         ) \
888     E( MOTORBIKE             ) \
889     E( JEEP                  ) \
890     E( VEHICLE_EXTRA         ) \
891     E( ENEMY_JEEP            ) \
892     E( SKELETON              ) \
893     E( SKELETON_MIP          ) \
894     E( GUIDE                 ) \
895     E( GUIDE_MIP             ) \
896     E( VON_CROY              ) \
897     E( VON_CROY_MIP          ) \
898     E( BADDY_1               ) \
899     E( BADDY_1_MIP           ) \
900     E( BADDY_2               ) \
901     E( BADDY_2_MIP           ) \
902     E( SETHA                 ) \
903     E( SETHA_MIP             ) \
904     E( MUMMY                 ) \
905     E( MUMMY_MIP             ) \
906     E( SPHINX                ) \
907     E( SPHINX_MIP            ) \
908     E( CROCODILE             ) \
909     E( CROCODILE_MIP         ) \
910     E( HORSEMAN              ) \
911     E( HORSEMAN_MIP          ) \
912     E( SCORPION              ) \
913     E( SCORPION_MIP          ) \
914     E( JEAN_YVES             ) \
915     E( JEAN_YVES_MIP         ) \
916     E( TROOPS                ) \
917     E( TROOPS_MIP            ) \
918     E( KNIGHTS_TEMPLAR       ) \
919     E( KNIGHTS_TEMPLAR_MIP   ) \
920     E( MUTANT                ) \
921     E( MUTANT_MIP            ) \
922     E( HORSE                 ) \
923     E( HORSE_MIP             ) \
924     E( BABOON_NORMAL         ) \
925     E( BABOON_NORMAL_MIP     ) \
926     E( BABOON_INV            ) \
927     E( BABOON_INV_MIP        ) \
928     E( BABOON_SILENT         ) \
929     E( BABOON_SILENT_MIP     ) \
930     E( WILD_BOAR             ) \
931     E( WILD_BOAR_MIP         ) \
932     E( HARPY                 ) \
933     E( HARPY_MIP             ) \
934     E( DEMIGOD1              ) \
935     E( DEMIGOD1_MIP          ) \
936     E( DEMIGOD2              ) \
937     E( DEMIGOD2_MIP          ) \
938     E( DEMIGOD3              ) \
939     E( DEMIGOD3_MIP          ) \
940     E( LITTLE_BEETLE         ) \
941     E( BIG_BEETLE            ) \
942     E( BIG_BEETLE_MIP        ) \
943     E( WRAITH1               ) \
944     E( WRAITH2               ) \
945     E( WRAITH3               ) \
946     E( WRAITH4               ) \
947     E( BAT                   ) \
948     E( DOG                   ) \
949     E( DOG_MIP               ) \
950     E( HAMMERHEAD            ) \
951     E( HAMMERHEAD_MIP        ) \
952     E( SAS                   ) \
953     E( SAS_MIP               ) \
954     E( SAS_DYING             ) \
955     E( SAS_DYING_MIP         ) \
956     E( SAS_CAPTAIN           ) \
957     E( SAS_CAPTAIN_MIP       ) \
958     E( SAS_DRAG_BLOKE        ) \
959     E( AHMET                 ) \
960     E( AHMET_MIP             ) \
961     E( LARA_DOUBLE           ) \
962     E( LARA_DOUBLE_MIP       ) \
963     E( SMALL_SCORPION        ) \
964     E( LOCUST_EMITTER        ) \
965     E( GAME_PIECE1           ) \
966     E( GAME_PIECE2           ) \
967     E( GAME_PIECE3           ) \
968     E( ENEMY_PIECE           ) \
969     E( WHEEL_OF_FORTUNE      ) \
970     E( SCALES                ) \
971     E( DARTS                 ) \
972     E( DART_EMITTER          ) \
973     E( HOMING_DART_EMITTER   ) \
974     E( FALLING_CEILING       ) \
975     E( FALLING_BLOCK         ) \
976     E( FALLING_BLOCK2        ) \
977     E( SMASHABLE_BIKE_WALL   ) \
978     E( SMASHABLE_BIKE_FLOOR  ) \
979     E( TRAPDOOR1             ) \
980     E( TRAPDOOR2             ) \
981     E( TRAPDOOR3             ) \
982     E( FLOOR_TRAPDOOR1       ) \
983     E( FLOOR_TRAPDOOR2       ) \
984     E( CEILING_TRAPDOOR1     ) \
985     E( CEILING_TRAPDOOR2     ) \
986     E( SCALING_TRAPDOOR      ) \
987     E( ROLLINGBALL           ) \
988     E( SPIKEY_FLOOR          ) \
989     E( TEETH_SPIKES          ) \
990     E( JOBY_SPIKES           ) \
991     E( SLICER_DICER          ) \
992     E( CHAIN                 ) \
993     E( PLOUGH                ) \
994     E( STARGATE              ) \
995     E( HAMMER                ) \
996     E( BURNING_FLOOR         ) \
997     E( COG                   ) \
998     E( SPIKEBALL             ) \
999     E( ___FLAME              ) \
1000     E( ___TRAP_FLAME_EMITTER ) \
1001     E( TRAP_FLAME_EMITTER2   ) \
1002     E( TRAP_FLAME_EMITTER3   ) \
1003     E( ROPE                  ) \
1004     E( FIREROPE              ) \
1005     E( POLEROPE              ) \
1006     E( ONEBLOCK_PLATFORM     ) \
1007     E( TWOBLOCK_PLATFORM     ) \
1008     E( RAISING_BLOCK1        ) \
1009     E( RAISING_BLOCK2        ) \
1010     E( EXPANDING_PLATFORM    ) \
1011     E( SQUISHY_BLOCK1        ) \
1012     E( SQUISHY_BLOCK2        ) \
1013     E( ___BLOCK_1            ) \
1014     E( ___BLOCK_2            ) \
1015     E( ___BLOCK_3            ) \
1016     E( ___BLOCK_4            ) \
1017     E( BLOCK_5               ) \
1018     E( ___TRIPWIRE           ) \
1019     E( SENTRY_GUN            ) \
1020     E( MINE                  ) \
1021     E( MAPPER                ) \
1022     E( OBELISK               ) \
1023     E( FLOOR_4BLADE          ) \
1024     E( ROOF_4BLADE           ) \
1025     E( BIRD_BLADE            ) \
1026     E( CATWALK_BLADE         ) \
1027     E( MOVING_BLADE          ) \
1028     E( PLINTH_BLADE          ) \
1029     E( SETH_BLADE            ) \
1030     E( LIGHTNING_CONDUCTOR   ) \
1031     E( ELEMENT_PUZZLE        ) \
1032     E( PUZZLE_ITEM1          ) \
1033     E( PUZZLE_ITEM2          ) \
1034     E( PUZZLE_ITEM3          ) \
1035     E( PUZZLE_ITEM4          ) \
1036     E( PUZZLE_ITEM5          ) \
1037     E( PUZZLE_ITEM6          ) \
1038     E( PUZZLE_ITEM7          ) \
1039     E( PUZZLE_ITEM8          ) \
1040     E( PUZZLE_ITEM9          ) \
1041     E( PUZZLE_ITEM10         ) \
1042     E( PUZZLE_ITEM11         ) \
1043     E( PUZZLE_ITEM12         ) \
1044     E( PUZZLE_ITEM1_COMBO1   ) \
1045     E( PUZZLE_ITEM1_COMBO2   ) \
1046     E( PUZZLE_ITEM2_COMBO1   ) \
1047     E( PUZZLE_ITEM2_COMBO2   ) \
1048     E( PUZZLE_ITEM3_COMBO1   ) \
1049     E( PUZZLE_ITEM3_COMBO2   ) \
1050     E( PUZZLE_ITEM4_COMBO1   ) \
1051     E( PUZZLE_ITEM4_COMBO2   ) \
1052     E( PUZZLE_ITEM5_COMBO1   ) \
1053     E( PUZZLE_ITEM5_COMBO2   ) \
1054     E( PUZZLE_ITEM6_COMBO1   ) \
1055     E( PUZZLE_ITEM6_COMBO2   ) \
1056     E( PUZZLE_ITEM7_COMBO1   ) \
1057     E( PUZZLE_ITEM7_COMBO2   ) \
1058     E( PUZZLE_ITEM8_COMBO1   ) \
1059     E( PUZZLE_ITEM8_COMBO2   ) \
1060     E( KEY_ITEM1             ) \
1061     E( KEY_ITEM2             ) \
1062     E( KEY_ITEM3             ) \
1063     E( KEY_ITEM4             ) \
1064     E( KEY_ITEM5             ) \
1065     E( KEY_ITEM6             ) \
1066     E( KEY_ITEM7             ) \
1067     E( KEY_ITEM8             ) \
1068     E( KEY_ITEM9             ) \
1069     E( KEY_ITEM10            ) \
1070     E( KEY_ITEM11            ) \
1071     E( KEY_ITEM12            ) \
1072     E( KEY_ITEM1_COMBO1      ) \
1073     E( KEY_ITEM1_COMBO2      ) \
1074     E( KEY_ITEM2_COMBO1      ) \
1075     E( KEY_ITEM2_COMBO2      ) \
1076     E( KEY_ITEM3_COMBO1      ) \
1077     E( KEY_ITEM3_COMBO2      ) \
1078     E( KEY_ITEM4_COMBO1      ) \
1079     E( KEY_ITEM4_COMBO2      ) \
1080     E( KEY_ITEM5_COMBO1      ) \
1081     E( KEY_ITEM5_COMBO2      ) \
1082     E( KEY_ITEM6_COMBO1      ) \
1083     E( KEY_ITEM6_COMBO2      ) \
1084     E( KEY_ITEM7_COMBO1      ) \
1085     E( KEY_ITEM7_COMBO2      ) \
1086     E( KEY_ITEM8_COMBO1      ) \
1087     E( KEY_ITEM8_COMBO2      ) \
1088     E( PICKUP_ITEM1          ) \
1089     E( PICKUP_ITEM2          ) \
1090     E( PICKUP_ITEM3          ) \
1091     E( PICKUP_ITEM4          ) \
1092     E( PICKUP_ITEM1_COMBO1   ) \
1093     E( PICKUP_ITEM1_COMBO2   ) \
1094     E( PICKUP_ITEM2_COMBO1   ) \
1095     E( PICKUP_ITEM2_COMBO2   ) \
1096     E( PICKUP_ITEM3_COMBO1   ) \
1097     E( PICKUP_ITEM3_COMBO2   ) \
1098     E( PICKUP_ITEM4_COMBO1   ) \
1099     E( PICKUP_ITEM4_COMBO2   ) \
1100     E( EXAMINE1              ) \
1101     E( EXAMINE2              ) \
1102     E( EXAMINE3              ) \
1103     E( CROWBAR_ITEM          ) \
1104     E( BURNING_TORCH_ITEM    ) \
1105     E( CLOCKWORK_BEETLE      ) \
1106     E( CLOCKWORK_BEETLE_COMBO1 ) \
1107     E( CLOCKWORK_BEETLE_COMBO2 ) \
1108     E( MINE_DETECTOR         ) \
1109     E( QUEST_ITEM1           ) \
1110     E( QUEST_ITEM2           ) \
1111     E( QUEST_ITEM3           ) \
1112     E( QUEST_ITEM4           ) \
1113     E( QUEST_ITEM5           ) \
1114     E( QUEST_ITEM6           ) \
1115     E( MAP                   ) \
1116     E( SECRET_MAP            ) \
1117     E( PUZZLE_HOLE1          ) \
1118     E( PUZZLE_HOLE2          ) \
1119     E( PUZZLE_HOLE3          ) \
1120     E( PUZZLE_HOLE4          ) \
1121     E( PUZZLE_HOLE5          ) \
1122     E( PUZZLE_HOLE6          ) \
1123     E( PUZZLE_HOLE7          ) \
1124     E( PUZZLE_HOLE8          ) \
1125     E( PUZZLE_HOLE9          ) \
1126     E( PUZZLE_HOLE10         ) \
1127     E( PUZZLE_HOLE11         ) \
1128     E( PUZZLE_HOLE12         ) \
1129     E( PUZZLE_DONE1          ) \
1130     E( PUZZLE_DONE2          ) \
1131     E( PUZZLE_DONE3          ) \
1132     E( PUZZLE_DONE4          ) \
1133     E( PUZZLE_DONE5          ) \
1134     E( PUZZLE_DONE6          ) \
1135     E( PUZZLE_DONE7          ) \
1136     E( PUZZLE_DONE8          ) \
1137     E( PUZZLE_DONE9          ) \
1138     E( PUZZLE_DONE10         ) \
1139     E( PUZZLE_DONE11         ) \
1140     E( PUZZLE_DONE12         ) \
1141     E( KEY_HOLE1             ) \
1142     E( KEY_HOLE2             ) \
1143     E( KEY_HOLE3             ) \
1144     E( KEY_HOLE4             ) \
1145     E( KEY_HOLE5             ) \
1146     E( KEY_HOLE6             ) \
1147     E( KEY_HOLE7             ) \
1148     E( KEY_HOLE8             ) \
1149     E( KEY_HOLE9             ) \
1150     E( KEY_HOLE10            ) \
1151     E( KEY_HOLE11            ) \
1152     E( KEY_HOLE12            ) \
1153     E( WATERSKIN1_EMPTY      ) \
1154     E( WATERSKIN1_1          ) \
1155     E( WATERSKIN1_2          ) \
1156     E( WATERSKIN1_3          ) \
1157     E( WATERSKIN2_EMPTY      ) \
1158     E( WATERSKIN2_1          ) \
1159     E( WATERSKIN2_2          ) \
1160     E( WATERSKIN2_3          ) \
1161     E( WATERSKIN2_4          ) \
1162     E( WATERSKIN2_5          ) \
1163     E( SWITCH_TYPE1          ) \
1164     E( SWITCH_TYPE2          ) \
1165     E( SWITCH_TYPE3          ) \
1166     E( SWITCH_TYPE4          ) \
1167     E( SWITCH_TYPE5          ) \
1168     E( SWITCH_TYPE6          ) \
1169     E( SWITCH_TYPE7          ) \
1170     E( SWITCH_TYPE8          ) \
1171     E( UNDERWATER_SWITCH1    ) \
1172     E( UNDERWATER_SWITCH2    ) \
1173     E( TURN_SWITCH           ) \
1174     E( COG_SWITCH            ) \
1175     E( LEVER_SWITCH          ) \
1176     E( JUMP_SWITCH           ) \
1177     E( CROWBAR_SWITCH        ) \
1178     E( PULLEY                ) \
1179     E( DOOR_TYPE1            ) \
1180     E( DOOR_TYPE2            ) \
1181     E( DOOR_TYPE3            ) \
1182     E( DOOR_TYPE4            ) \
1183     E( DOOR_TYPE5            ) \
1184     E( DOOR_TYPE6            ) \
1185     E( DOOR_TYPE7            ) \
1186     E( DOOR_TYPE8            ) \
1187     E( PUSHPULL_DOOR1        ) \
1188     E( PUSHPULL_DOOR2        ) \
1189     E( KICK_DOOR1            ) \
1190     E( KICK_DOOR2            ) \
1191     E( UNDERWATER_DOOR       ) \
1192     E( DOUBLE_DOORS          ) \
1193     E( BRIDGE_FLAT           ) \
1194     E( BRIDGE_TILT1          ) \
1195     E( BRIDGE_TILT2          ) \
1196     E( SARCOPHAGUS           ) \
1197     E( SEQUENCE_DOOR1        ) \
1198     E( SEQUENCE_SWITCH1      ) \
1199     E( SEQUENCE_SWITCH2      ) \
1200     E( SEQUENCE_SWITCH3      ) \
1201     E( SARCOPHAGUS_CUT       ) \
1202     E( HORUS_STATUE          ) \
1203     E( GOD_HEAD              ) \
1204     E( SETH_DOOR             ) \
1205     E( STATUE_PLINTH         ) \
1206     E( PISTOLS_ITEM          ) \
1207     E( PISTOLS_AMMO_ITEM     ) \
1208     E( UZI_ITEM              ) \
1209     E( UZI_AMMO_ITEM         ) \
1210     E( SHOTGUN_ITEM          ) \
1211     E( SHOTGUN_AMMO1_ITEM    ) \
1212     E( SHOTGUN_AMMO2_ITEM    ) \
1213     E( CROSSBOW_ITEM         ) \
1214     E( CROSSBOW_AMMO1_ITEM   ) \
1215     E( CROSSBOW_AMMO2_ITEM   ) \
1216     E( CROSSBOW_AMMO3_ITEM   ) \
1217     E( CROSSBOW_BOLT         ) \
1218     E( GRENADE_GUN_ITEM      ) \
1219     E( GRENADE_GUN_AMMO1_ITEM ) \
1220     E( GRENADE_GUN_AMMO2_ITEM ) \
1221     E( GRENADE_GUN_AMMO3_ITEM ) \
1222     E( ___GRENADE            ) \
1223     E( REVOLVER_ITEM         ) \
1224     E( REVOLVER_AMMO_ITEM    ) \
1225     E( ___INV_MEDIKIT_BIG    ) \
1226     E( ___INV_MEDIKIT_SMALL  ) \
1227     E( LASERSIGHT_ITEM       ) \
1228     E( BINOCULARS_ITEM       ) \
1229     E( ___FLARES             ) \
1230     E( ___INV_FLARES         ) \
1231     E( ___INV_PASSPORT       ) \
1232     E( ___INV_COMPASS        ) \
1233     E( MEMCARD_LOAD_INV_ITEM ) \
1234     E( MEMCARD_SAVE_INV_ITEM ) \
1235     E( PC_LOAD_INV_ITEM      ) \
1236     E( PC_SAVE_INV_ITEM      ) \
1237     E( SMOKE_EMITTER_WHITE   ) \
1238     E( SMOKE_EMITTER_BLACK   ) \
1239     E( STEAM_EMITTER         ) \
1240     E( ___EARTHQUAKE         ) \
1241     E( BUBBLES               ) \
1242     E( WATERFALLMIST         ) \
1243     E( GUNSHELL              ) \
1244     E( SHOTGUNSHELL          ) \
1245     E( ___MUZZLE_FLASH       ) \
1246     E( BUTTERFLY             ) \
1247     E( SPRINKLER             ) \
1248     E( RED_LIGHT             ) \
1249     E( GREEN_LIGHT           ) \
1250     E( BLUE_LIGHT            ) \
1251     E( AMBER_LIGHT           ) \
1252     E( WHITE_LIGHT           ) \
1253     E( BLINKING_LIGHT        ) \
1254     E( LENS_FLARE            ) \
1255     E( ___AI_GUARD           ) \
1256     E( ___AI_AMBUSH          ) \
1257     E( AI_PATROL1            ) \
1258     E( ___AI_MODIFY          ) \
1259     E( ___AI_FOLLOW          ) \
1260     E( AI_PATROL2            ) \
1261     E( AI_X1                 ) \
1262     E( AI_X2                 ) \
1263     E( LARA_START_POS        ) \
1264     E( ___KILL_ALL_TRIGGERS  ) \
1265     E( TRIGGER_TRIGGERER     ) \
1266     E( SMASH_OBJECT1         ) \
1267     E( SMASH_OBJECT2         ) \
1268     E( SMASH_OBJECT3         ) \
1269     E( SMASH_OBJECT4         ) \
1270     E( SMASH_OBJECT5         ) \
1271     E( SMASH_OBJECT6         ) \
1272     E( SMASH_OBJECT7         ) \
1273     E( SMASH_OBJECT8         ) \
1274     E( MESHSWAP1             ) \
1275     E( MESHSWAP2             ) \
1276     E( MESHSWAP3             ) \
1277     E( DEATH_SLIDE           ) \
1278     E( BODY_PART             ) \
1279     E( CAMERA_TARGET         ) \
1280     E( WATERFALL1            ) \
1281     E( WATERFALL2            ) \
1282     E( WATERFALL3            ) \
1283     E( PLANET_EFFECT         ) \
1284     E( ANIMATING1            ) \
1285     E( ANIMATING1_MIP        ) \
1286     E( ANIMATING2            ) \
1287     E( ANIMATING2_MIP        ) \
1288     E( ANIMATING3            ) \
1289     E( ANIMATING3_MIP        ) \
1290     E( ANIMATING4            ) \
1291     E( ANIMATING4_MIP        ) \
1292     E( ANIMATING5            ) \
1293     E( ANIMATING5_MIP        ) \
1294     E( ANIMATING6            ) \
1295     E( ANIMATING6_MIP        ) \
1296     E( ANIMATING7            ) \
1297     E( ANIMATING7_MIP        ) \
1298     E( ANIMATING8            ) \
1299     E( ANIMATING8_MIP        ) \
1300     E( ANIMATING9            ) \
1301     E( ANIMATING9_MIP        ) \
1302     E( ANIMATING10           ) \
1303     E( ANIMATING10_MIP       ) \
1304     E( ANIMATING11           ) \
1305     E( ANIMATING11_MIP       ) \
1306     E( ANIMATING12           ) \
1307     E( ANIMATING12_MIP       ) \
1308     E( ANIMATING13           ) \
1309     E( ANIMATING13_MIP       ) \
1310     E( ANIMATING14           ) \
1311     E( ANIMATING14_MIP       ) \
1312     E( ANIMATING15           ) \
1313     E( ANIMATING15_MIP       ) \
1314     E( ANIMATING16           ) \
1315     E( ANIMATING16_MIP       ) \
1316     E( ___SKY                ) \
1317     E( SKY_GRAPHICS          ) \
1318     E( BINOCULAR_GRAPHICS    ) \
1319     E( TARGET_GRAPHICS       ) \
1320     E( ___GLYPHS             ) \
1321     E( ___MISC_SPRITES       ) \
1322     E( MOTOR_BOAT            ) \
1323     E( MOTOR_BOAT_LARA       ) \
1324     E( RUBBER_BOAT           ) \
1325     E( RUBBER_BOAT_LARA      ) \
1326     E( MOTORBIKE_LARA        ) \
1327     E( FONT_GRAPHICS         ) \
1328     E( PARALLEL_BARS         ) \
1329     E( PANEL_BORDER          ) \
1330     E( PANEL_MIDDLE          ) \
1331     E( PANEL_CORNER          ) \
1332     E( PANEL_DIAGONAL        ) \
1333     E( PANEL_STRIP           ) \
1334     E( PANEL_HALF_BORDER1    ) \
1335     E( PANEL_HALF_BORDER2    ) \
1336     E( PANEL_MIDDLE_CORNER   ) \
1337     E( TIGHT_ROPE            ) \
1338     E( LASER_HEAD            ) \
1339     E( LASER_HEAD_BASE       ) \
1340     E( LASER_HEAD_TENTACLE   ) \
1341     E( HYDRA                 ) \
1342     E( HYDRA_MISSILE         ) \
1343     E( ENEMY_SUB_MARINE      ) \
1344     E( ENEMY_SUB_MARINE_MIP  ) \
1345     E( SUB_MARINE_MISSILE    ) \
1346     E( FROG_MAN              ) \
1347     E( FROG_MAN_HARPOON      ) \
1348     E( FISH_EMITTER          ) \
1349     E( KAYAK                 ) \
1350     E( KAYAK_LARA            ) \
1351     E( CUSTOM_SPRITES        ) \
1352     E( BRIDGE_TILT3          ) \
1353     E( BRIDGE_TILT4          ) \
1354     E( BRIDGE_CUSTOM         ) \
1355     E( ROBOT_CLEANER         ) \
1356     E( ROBOT_STAR_WARS       ) \
1357     E( MECH_WARRIOR          ) \
1358     E( MECH_WARRIOR_LARA     ) \
1359     E( UW_PROPULSOR          ) \
1360     E( UW_PROPULSOR_LARA     ) \
1361     E( MINE_CART             ) \
1362     E( MINE_CART_LARA        ) \
1363     E( NEW_SLOT5             ) \
1364     E( NEW_SLOT6             ) \
1365     E( NEW_SLOT7             ) \
1366     E( NEW_SLOT8             ) \
1367     E( NEW_SLOT9             ) \
1368     E( NEW_SLOT10            ) \
1369     E( NEW_SLOT11            ) \
1370     E( NEW_SLOT12            ) \
1371     E( NEW_SLOT13            ) \
1372     E( NEW_SLOT14            ) \
1373     E( NEW_SLOT15            ) \
1374     E( NEW_SLOT16            ) \
1375     E( NEW_SLOT17            ) \
1376     E( NEW_SLOT18            ) \
1377     E( TR4_TYPE_MAX          )
1378 
1379 namespace TR {
1380 
1381     struct Level;
1382 
1383     enum {
1384         NO_FLOOR = -127,
1385         NO_ROOM  = 0xFF,
1386         NO_BOX   = 0xFFFF,
1387         NO_WATER = 0x7FFFFFFF,
1388         ACTIVE   = 0x1F,
1389     };
1390 
1391     enum {
1392         ANIM_CMD_NONE       ,
1393         ANIM_CMD_OFFSET     ,
1394         ANIM_CMD_JUMP       ,
1395         ANIM_CMD_EMPTY      ,
1396         ANIM_CMD_KILL       ,
1397         ANIM_CMD_SOUND      ,
1398         ANIM_CMD_EFFECT     ,
1399     };
1400 
1401     struct Effect {
1402         enum Type {
1403             NONE           = -1,
1404             ROTATE_180     ,
1405             FLOOR_SHAKE    ,
1406             LARA_NORMAL    ,
1407             LARA_BUBBLES   ,
1408             FINISH_LEVEL   ,
1409             EARTHQUAKE     ,
1410             FLOOD          ,
1411             UNK1           ,
1412             STAIRS2SLOPE   ,
1413             UNK3           ,
1414             UNK4           ,
1415             EXPLOSION      ,
1416             LARA_HANDSFREE ,
1417             FLIP_MAP       ,
1418             DRAW_RIGHTGUN  ,
1419             DRAW_LEFTGUN   ,
1420             SHOT_RIGHTGUN  ,
1421             SHOT_LEFTGUN   ,
1422             MESH_SWAP_1    ,
1423             MESH_SWAP_2    ,
1424             MESH_SWAP_3    ,
1425             INV_ON         ,
1426             INV_OFF        ,
1427             DYN_ON         ,
1428             DYN_OFF        ,
1429             STATUE_FX      ,
1430             RESET_HAIR     ,
1431             BOILER_FX      ,
1432             ASSAULT_RESET  ,
1433             ASSAULT_STOP   ,
1434             ASSAULT_START  ,
1435             ASSAULT_FINISH ,
1436             FOOTPRINT      ,
1437         // specific
1438             TR1_FLICKER    = 16,
1439         };
1440     };
1441 
1442     enum {
1443         SND_NO              = 2,
1444 
1445         SND_LANDING         = 4,
1446 
1447         SND_UNHOLSTER       = 6,
1448         SND_HOLSTER         = 7,
1449         SND_PISTOLS_SHOT    = 8,
1450         SND_SHOTGUN_RELOAD  = 9,
1451         SND_RICOCHET        = 10,
1452 
1453         SND_HIT_BEAR        = 16,
1454         SND_HIT_WOLF        = 20,
1455 
1456         SND_SCREAM          = 30,
1457         SND_HIT             = 31,
1458 
1459         SND_WATER_SPLASH    = 33,
1460 
1461         SND_BUBBLE          = 37,
1462 
1463         SND_UZIS_SHOT       = 43,
1464         SND_MAGNUMS_SHOT    = 44,
1465         SND_SHOTGUN_SHOT    = 45,
1466         SND_EMPTY           = 48,
1467         SND_HIT_UNDERWATER  = 50,
1468 
1469         SND_UNDERWATER      = 60,
1470 
1471         SND_BOULDER         = 70,
1472 
1473         SND_FLOOD           = 81,
1474 
1475         SND_HIT_LION        = 85,
1476 
1477         SND_HIT_RAT         = 95,
1478 
1479         SND_LIGHTNING       = 98,
1480         SND_ROCK            = 99,
1481 
1482         SND_SWORD           = 103,
1483         SND_EXPLOSION       = 104,
1484 
1485         SND_INV_SPIN        = 108,
1486         SND_INV_HOME        = 109,
1487         SND_INV_CONTROLS    = 110,
1488         SND_INV_SHOW        = 111,
1489         SND_INV_HIDE        = 112,
1490         SND_INV_COMPASS     = 113,
1491         SND_INV_WEAPON      = 114,
1492         SND_INV_PAGE        = 115,
1493         SND_HEALTH          = 116,
1494 
1495         SND_STAIRS2SLOPE    = 119,
1496 
1497         SND_NATLA_SHOT      = 123,
1498 
1499         SND_HIT_SKATEBOY    = 132,
1500 
1501         SND_HIT_MUTANT      = 142,
1502         SND_STOMP           = 147,
1503 
1504         SND_LAVA            = 149,
1505         SND_FLAME           = 150,
1506         SND_DART            = 151,
1507 
1508         SND_TNT             = 170,
1509         SND_MUTANT_DEATH    = 171,
1510         SND_SECRET          = 173,
1511 
1512         SND_HELICOPTER      = 297,
1513 
1514         SND_WINSTON_SCARED  = 344,
1515         SND_WINSTON_WALK    = 345,
1516         SND_WINSTON_PUSH    = 346,
1517         SND_WINSTON_TRAY    = 347,
1518     };
1519 
1520     enum {
1521         MODEL_LARA          = 0,
1522         MODEL_PISTOLS       = 1,
1523         MODEL_SHOTGUN       = 2,
1524         MODEL_MAGNUMS       = 3,
1525         MODEL_UZIS          = 4,
1526         MODEL_LARA_SPEC     = 5,
1527     };
1528 
1529     enum HitType {
1530         HIT_DEFAULT,
1531         HIT_FALL,
1532         HIT_DART,
1533         HIT_BLADE,
1534         HIT_BOULDER,
1535         HIT_SPIKES,
1536         HIT_SWORD,
1537         HIT_LAVA,
1538         HIT_SLAM,
1539         HIT_REX,
1540         HIT_LIGHTNING,
1541         HIT_MIDAS,
1542         HIT_GIANT_MUTANT,
1543     };
1544 
1545     struct Action {
1546         enum Type {
1547             ACTIVATE        ,   // activate item
1548             CAMERA_SWITCH   ,   // switch to camera
1549             FLOW            ,   // underwater flow
1550             FLIP            ,   // flip map
1551             FLIP_ON         ,   // flip on
1552             FLIP_OFF        ,   // flip off
1553             CAMERA_TARGET   ,   // look at item
1554             END             ,   // end level
1555             SOUNDTRACK      ,   // play soundtrack
1556             EFFECT          ,   // special effect trigger
1557             SECRET          ,   // secret found
1558             CLEAR_BODIES    ,   // clear all dead bodies
1559             FLYBY           ,   // play flyby camera sequence
1560             CUTSCENE        ,   // play cutscene
1561         };
1562     };
1563 
1564     namespace Limits {
1565 
1566         struct Limit {
1567             float  dy, dz, ay;
1568             ::Box  box;
1569             bool   alignAngle;
1570             bool   alignHoriz;
1571         };
1572 
1573         Limit SWITCH = {
1574             0, 376, 30,     ::Box(vec3(-200, 0, 312), vec3(200, 0, 512)), true, false
1575         };
1576 
1577         Limit SWITCH_UNDERWATER = {
1578             0, 100, 80,     ::Box(vec3(-1024, -1024, -1024), vec3(1024, 1024, 512)), true, true
1579         };
1580 
1581         Limit SWITCH_BUTTON = {
1582             0, 292, 30,     ::Box(vec3(-200, 0, 250), vec3(200, 0, 512)), true, true
1583         };
1584 
1585         Limit PICKUP = {
1586             0, -100, 180,   ::Box(vec3(-256, -100, -256), vec3(256, 100, 100)), false, true
1587         };
1588 
1589         Limit PICKUP_UNDERWATER = {
1590             -200, -350, 45, ::Box(vec3(-512, -512, -512), vec3(512, 512, 512)), false, true
1591         };
1592 
1593         Limit KEY_HOLE = {
1594             0, 362, 30,     ::Box(vec3(-200, 0, 312), vec3(200, 0, 512)), true, true
1595         };
1596 
1597         Limit PUZZLE_HOLE = {
1598             0, 327, 30,     ::Box(vec3(-200, 0, 312), vec3(200, 0, 512)), true, true
1599         };
1600 
1601         Limit BLOCK = {
1602             0, -612, 30,    ::Box(vec3(-300, 0, -692), vec3(300, 0, -512)), true, false
1603         };
1604 
1605         Limit MIDAS = {
1606             512, -612, 30,  ::Box(vec3(-700, 284, -700), vec3(700, 996, 700)), true, false
1607         };
1608 
1609         Limit SCION = {
1610             640, -202, 30,  ::Box(vec3(-256, 540, -350), vec3(256, 740, -200)), false, false
1611         };
1612 
1613         Limit SCION_HOLDER = {
1614             640, -202, 10,  ::Box(vec3(-256, 206, -862), vec3(256, 306, -200)), true, false
1615         };
1616     }
1617 
1618     union fixed {
1619         uint32 value;
1620         struct {
1621             uint16 L;
1622             int16  H;
1623         };
1624 
1625         operator float() const {
1626             return H + L / 65535.0f;
1627         }
1628     };
1629 
1630     struct angle {
1631         uint16 value;
1632 
angleangle1633         angle() {}
angleangle1634         angle(uint16 value) : value(value) {}
angleangle1635         angle(float value) : value(uint16(value / (PI * 0.5f) * 16384.0f)) {}
1636         operator float() const { return value / 16384.0f * PI * 0.5f; };
1637     };
1638 
1639     enum TextureType {
1640         TEX_TYPE_ROOM,
1641         TEX_TYPE_ITEM,
1642         TEX_TYPE_OBJECT,
1643         TEX_TYPE_SPRITE,
1644     };
1645 
1646     struct TextureInfo {
1647         TextureType  type;     // determines in which atlas this texture will be stored
1648         TextureType  dataType; // original texture type from file
1649         uint16       index;
1650         uint16       clut;
1651         uint16       tile;
1652         uint32       attribute:15, animated:1;    // 0 - opaque, 1 - transparent, 2 - blend additive, animated, triangle
1653         short2       texCoord[4];
1654         short2       texCoordAtlas[4];
1655         int16        l, t, r, b;
1656 
1657         uint16       sub[4], i5;
1658 
TextureInfoTextureInfo1659         TextureInfo() {}
1660 
TextureInfoTextureInfo1661         TextureInfo(TextureType type, int16 l, int16 t, int16 r, int16 b, uint8 tx, uint8 ty, uint8 tw, uint8 th) : type(type), dataType(type), attribute(1), l(l), t(t), r(r), b(b) {
1662             texCoord[0] = texCoordAtlas[0] = short2( tx,          ty          );
1663             texCoord[1] = texCoordAtlas[1] = short2( tx + tw - 1, ty + th - 1 );
1664         }
1665 
getMinMaxTextureInfo1666         short4 getMinMax() const {
1667             if (dataType == TEX_TYPE_SPRITE)
1668                 return short4( texCoord[0].x, texCoord[0].y, texCoord[1].x, texCoord[1].y );
1669 
1670             return short4(
1671                 min(min(texCoord[0].x, texCoord[1].x), texCoord[2].x),
1672                 min(min(texCoord[0].y, texCoord[1].y), texCoord[2].y),
1673                 max(max(texCoord[0].x, texCoord[1].x), texCoord[2].x),
1674                 max(max(texCoord[0].y, texCoord[1].y), texCoord[2].y)
1675             );
1676         }
1677 
getMinMaxAtlasTextureInfo1678         short4 getMinMaxAtlas() const {
1679             if (dataType == TEX_TYPE_SPRITE)
1680                 return short4( texCoordAtlas[0].x, texCoordAtlas[0].y, texCoordAtlas[1].x, texCoordAtlas[1].y );
1681 
1682             return short4(
1683                 min(min(texCoordAtlas[0].x, texCoordAtlas[1].x), texCoordAtlas[2].x),
1684                 min(min(texCoordAtlas[0].y, texCoordAtlas[1].y), texCoordAtlas[2].y),
1685                 max(max(texCoordAtlas[0].x, texCoordAtlas[1].x), texCoordAtlas[2].x),
1686                 max(max(texCoordAtlas[0].y, texCoordAtlas[1].y), texCoordAtlas[2].y)
1687             );
1688         }
1689     };
1690 
1691     // used for access from ::cmp func
1692     static TextureInfo   *gObjectTextures = NULL;
1693     static TextureInfo   *gSpriteTextures = NULL;
1694     static int            gObjectTexturesCount;
1695     static int            gSpriteTexturesCount;
1696 
1697     struct Face {
1698         union {
1699             struct { uint16 texture:15, doubleSided:1; };
1700             uint16 value;
1701         } flags;
1702 
1703         union {
1704             struct { uint16 additive:1, env:1, shininess:6; };
1705             uint16 value;
1706         } effects;
1707 
1708         short3 normal;
1709         uint16 vertices[4];
1710         uint8  triangle:1, colored:1, water:1, flip:5;
1711 
FaceFace1712         Face() : triangle(0), colored(0), water(0), flip(0) {
1713             flags.value   = 0;
1714             effects.value = 0;
1715         }
1716 
cmpFace1717         static int cmp(const Face &a, const Face &b) {
1718             int aIndex = a.flags.texture;
1719             int bIndex = b.flags.texture;
1720             if (aIndex >= gObjectTexturesCount)
1721                 return 1;
1722             if (bIndex >= gObjectTexturesCount)
1723                 return -1;
1724 
1725             ASSERT(aIndex < gObjectTexturesCount);
1726             ASSERT(bIndex < gObjectTexturesCount);
1727 
1728             TextureInfo &ta = gObjectTextures[aIndex];
1729             TextureInfo &tb = gObjectTextures[bIndex];
1730 
1731             if (ta.tile < tb.tile)
1732                 return -1;
1733             if (ta.tile > tb.tile)
1734                 return  1;
1735 
1736             #ifdef SPLIT_BY_CLUT
1737                 if (ta.clut < tb.clut)
1738                     return -1;
1739                 if (ta.clut > tb.clut)
1740                     return  1;
1741             #endif
1742 
1743             if (aIndex < bIndex)
1744                 return -1;
1745             if (aIndex > bIndex)
1746                 return  1;
1747 
1748             return 0;
1749         }
1750     };
1751 
1752     #define FACE4_SIZE (sizeof(uint16) + sizeof(uint16) * 4) // flags + vertices[4]
1753     #define FACE3_SIZE (FACE4_SIZE - sizeof(uint16))
1754 
1755     struct Room {
1756 
1757         struct Info {
1758             int32 x, z;
1759             int32 yBottom, yTop;
1760         } info;
1761 
1762         struct Data {
1763             uint32      size;       // Number of data words (uint16_t's)
1764 
1765             int16       vCount;
1766             int16       tCount;
1767             int16       rCount;
1768             int16       fCount;
1769             int16       sCount;
1770 
1771             Face        *faces;
1772 
1773             struct Vertex {
1774                 short3  pos;
1775                 int16   unused_lighting;   // 0 (bright) .. 0x1FFF (dark)
1776                 uint16  attributes;
1777                 Color32 color;
1778             } *vertices;
1779 
1780             struct Sprite {
1781                 int16 vertexIndex;
1782                 int16 texture;
1783 
cmpRoom::Data::Sprite1784                 static int cmp(const Sprite &a, const Sprite &b) {
1785                     ASSERT(a.texture < gSpriteTexturesCount);
1786                     ASSERT(b.texture < gSpriteTexturesCount);
1787 
1788                     TextureInfo &ta = gSpriteTextures[a.texture];
1789                     TextureInfo &tb = gSpriteTextures[b.texture];
1790 
1791                     if (ta.tile < tb.tile)
1792                         return -1;
1793                     if (ta.tile > tb.tile)
1794                         return  1;
1795 
1796                     #ifdef SPLIT_BY_CLUT
1797                         if (ta.clut < tb.clut)
1798                             return -1;
1799                         if (ta.clut > tb.clut)
1800                             return  1;
1801                     #endif
1802 
1803                     if (a.texture < b.texture)
1804                         return -1;
1805                     if (a.texture > b.texture)
1806                         return  1;
1807 
1808                     return 0;
1809                 }
1810 
1811             } *sprites;
1812         } data;
1813 
1814         uint16  portalsCount;
1815         uint16  zSectors;
1816         uint16  xSectors;
1817         uint16  ambient;    // 0 (bright) .. 0x1FFF (dark)
1818         uint16  ambient2;
1819         uint16  lightMode;
1820         uint16  lightsCount;
1821         uint16  meshesCount;
1822         int16   alternateRoom;
1823         union {
1824             struct {
1825                 uint16 water:1, :2, sky:1, :1, wind:1, unused:9, visible:1;
1826             };
1827             uint16 value;
1828         } flags;
1829         uint8   waterScheme;
1830         uint8   reverbType;
1831         uint8   filter;
1832         uint8   align;
1833         int32   waterLevel[2]; // water level for normal and flipped level state
1834         int32   waterLevelSurface;
1835 
1836         struct DynLight {
1837             int32 id;
1838             vec4  pos;
1839             vec4  color;
1840         } dynLights[2]; // 1 is reserved for main light
1841 
1842         int32 dynLightsCount;
1843 
1844         struct Portal {
1845             uint16 roomIndex;
1846             short3 normal;
1847             short3 vertices[4];
1848 
getCenterRoom::Portal1849             vec3 getCenter() const {
1850                 return vec3(float( (int(vertices[0].x) + int(vertices[1].x) + int(vertices[2].x) + int(vertices[3].x)) / 4 ),
1851                             float( (int(vertices[0].y) + int(vertices[1].y) + int(vertices[2].y) + int(vertices[3].y)) / 4 ),
1852                             float( (int(vertices[0].z) + int(vertices[1].z) + int(vertices[2].z) + int(vertices[3].z)) / 4 ));
1853             }
1854 
getSizeRoom::Portal1855             vec3 getSize() const {
1856                 return vec3(float( abs(int(vertices[0].x) - int(vertices[2].x)) / 2 ),
1857                             float( abs(int(vertices[0].y) - int(vertices[2].y)) / 2 ),
1858                             float( abs(int(vertices[0].z) - int(vertices[2].z)) / 2 ));
1859             }
1860         } *portals;
1861 
1862         struct Sector {
1863             uint32  material;
1864             uint16  floorIndex; // Index into FloorData[]
1865             uint16  boxIndex;   // Index into Boxes[] (-1 if none)
1866             uint8   roomBelow;  // 255 is none
1867             int8    floor;      // Absolute height of floor * 256
1868             uint8   roomAbove;  // 255 if none
1869             int8    ceiling;    // Absolute height of ceiling * 256
1870         } *sectors;
1871 
1872         struct Light {
1873 
1874             enum Type {
1875                 DIRECT, POINT, SPOT, SHADOW, FOG
1876             };
1877 
1878             int32   x, y, z;
1879             uint32  radius;
1880             int32   intensity;
1881             Color24 color;
1882             float   in, out;
1883             float   length, cutoff;
1884             vec3    dir;
1885             uint8   type;
1886         } *lights;
1887 
1888         struct Mesh {
1889             int32   x, y, z;
1890             angle   rotation;
1891             uint16  meshID;
1892             Color32 color;
1893             uint32  meshIndex; // index into static meshes array
1894         } *meshes;
1895 
containsRoom1896         bool contains(const vec3 &p) const {
1897             return p.x >= info.x && p.x <= info.x + xSectors * 1024 && p.z >= info.z && p.z <= info.z + zSectors * 1024 && p.y >= info.yTop && p.y <= info.yBottom;
1898         }
1899 
getOffsetRoom1900         vec3 getOffset() const {
1901             return vec3(float(info.x), 0.0f, float(info.z));
1902         }
1903 
getCenterRoom1904         vec3 getCenter() const {
1905             return vec3(info.x + xSectors * 512.0f, (info.yBottom + info.yTop) * 0.5f, info.z + zSectors * 512.0f);
1906         }
1907 
getSectorRoom1908         Sector* getSector(int sx, int sz) {
1909             if (sz <= 0 || sz >= zSectors - 1) {
1910                 sz = clamp(sz, 0, zSectors - 1);
1911                 sx = clamp(sx, 1, xSectors - 2);
1912             } else
1913                 sx = clamp(sx, 0, xSectors - 1);
1914 
1915             ASSERT(sx >= 0 && sx < xSectors && sz >= 0 && sz < zSectors);
1916             return sectors + sx * zSectors + sz;
1917         }
1918 
1919         void addDynLight(int32 id, const vec4 &pos, const vec4 &color, bool priority = false) {
1920             DynLight *light = NULL;
1921             for (int i = 0; i < dynLightsCount; i++)
1922                 if (dynLights[i].id == id) {
1923                     float maxRadius = min(dynLights[i].color.w, color.w); // radius is invSqrt
1924                     light = &dynLights[i];
1925                     light->color.w = maxRadius;
1926                     break;
1927                 }
1928 
1929             // 1 is additional second light, can be overridden
1930             if (!light) {
1931                 if (dynLightsCount < COUNT(dynLights))
1932                     light = &dynLights[dynLightsCount++];
1933                 else
1934                     light = &dynLights[1];
1935             }
1936 
1937             light->id    = id;
1938             light->pos   = pos;
1939             light->color = color;
1940 
1941             if (priority && dynLights[0].id != id)
1942                 swap(dynLights[0], dynLights[1]);
1943         }
1944 
removeDynLightRoom1945         void removeDynLight(int32 id) {
1946             for (int i = 0; i < dynLightsCount; i++)
1947                 if (dynLights[i].id == id) {
1948                     if (i == 0) dynLights[0] = dynLights[1];
1949                     dynLightsCount--;
1950                     break;
1951                 }
1952         }
1953 
1954         int getAmbient(int x, int y, int z, Light **nearLight = NULL) const {
1955             if (!lightsCount) {
1956                 return ambient;
1957             }
1958 
1959             int ambientInv = 0x1FFF - ambient;
1960             int maxValue   = 0;
1961 
1962             for (int i = 0; i < lightsCount; i++) {
1963                 Light &light = lights[i];
1964                 if (light.intensity > 8192)
1965                     continue;
1966 
1967                 int dx = x - light.x;
1968                 int dy = y - light.y;
1969                 int dz = z - light.z;
1970 
1971                 int D = (SQR(dx) + SQR(dy) + SQR(dz)) >> 12;
1972                 int R = SQR(light.radius >> 1) >> 12;
1973                 int M = max(1, D + R); // TODO TR4
1974 
1975                 int value = min(0x1FFF, (light.intensity * R) / M + ambientInv);
1976 
1977                 if (maxValue < value) {
1978                     if (nearLight) {
1979                         *nearLight = &light;
1980                     }
1981                     maxValue = value;
1982                 }
1983             }
1984 
1985             return 0x1FFF - (maxValue + ambientInv) / 2;
1986         }
1987     };
1988 
1989     union FloorData {
1990         uint16 value;
1991         union Command {
1992             struct {
1993                 uint16 func:5, tri:3, sub:7, end:1;
1994             };
1995             struct {
1996                 int16 :5, a:5, b:5, :1;
1997             } triangle;
1998         } cmd;
1999         struct {
2000             int16 slantX:8, slantZ:8;
2001         };
2002         struct {
2003             uint16 a:4, b:4, c:4, d:4;
2004         };
2005         struct TriggerInfo {
2006             uint16  timer:8, once:1, mask:5, :2;
2007         } triggerInfo;
2008         union TriggerCommand {
2009             struct {
2010                 uint16 args:10, action:5, end:1;
2011             };
2012             struct {
2013                 uint16 timer:8, once:1, speed:5, :2;
2014             };
2015         } triggerCmd;
2016 
2017         enum {
2018               NONE
2019             , PORTAL
2020             , FLOOR
2021             , CEILING
2022             , TRIGGER
2023             , LAVA
2024             , CLIMB
2025             , FLOOR_NW_SE_SOLID
2026             , FLOOR_NE_SW_SOLID
2027             , CEILING_NW_SE_SOLID
2028             , CEILING_NE_SW_SOLID
2029             , FLOOR_NW_SE_PORTAL_SE
2030             , FLOOR_NW_SE_PORTAL_NW
2031             , FLOOR_NE_SW_PORTAL_SW
2032             , FLOOR_NE_SW_PORTAL_NE
2033             , CEILING_NW_SE_PORTAL_SE
2034             , CEILING_NW_SE_PORTAL_NW
2035             , CEILING_NE_SW_PORTAL_SW
2036             , CEILING_NE_SW_PORTAL_NE
2037             , MONKEY
2038             , MINECART_LEFT
2039             , MINECART_RIGHT
2040         };
2041     };
2042 
2043     union Overlap {
2044         struct { uint16 boxIndex:15, end:1; };
2045         uint16 value;
2046     };
2047 
2048     struct Flags {
2049         uint16 :8, once:1, active:5, :2;
2050     };
2051 
2052     // internal mesh structure
2053     struct Mesh {
2054 
2055         struct Vertex {
2056             short4 coord;
2057             short4 normal;
2058         };
2059 
2060         short3      center;
2061         int16       radius;
2062         union {
2063             struct {
2064                 uint16 isStatic:1, reserved:15;
2065             };
2066             uint16 value;
2067         }           flags;
2068         int16       vCount;
2069         int16       tCount;
2070         int16       rCount;
2071         int16       fCount;
2072 
2073         int32       offset;
2074         Vertex      *vertices;
2075         Face        *faces;
2076 
MeshMesh2077         Mesh() : vertices(0), faces(0) {}
~MeshMesh2078         ~Mesh() {
2079             delete[] vertices;
2080             delete[] faces;
2081         }
2082     };
2083 
2084     struct Entity {
2085         enum ActiveState { asNone, asActive, asInactive };
2086         enum Type        { NONE = 0, TR_TYPES(DECL_ENUM) TYPE_MAX = 0xFFFF };
2087 
2088         Type    type;
2089         int16   room;
2090         int32   x, y, z;
2091         angle   rotation;
2092         int16   intensity;
2093         union {
2094             int16 intensity2;
2095             int16 OCB;
2096         };
2097         union Flags {
2098             struct {
2099                 uint16 state:2, unused:3, smooth:1, :1, invisible:1, once:1, active:5, reverse:1, rendered:1;
2100             };
2101             uint16 value;
2102         } flags;
2103     // not exists in file
2104         int32   modelIndex;     // index of representation in models (index + 1) or spriteSequences (-(index + 1)) arrays
2105         void    *controller;    // Controller implementation or NULL
2106 
remapEntity2107         static Type remap(Version version, Type type) {
2108             if (version & VER_TR1)
2109                 return type;
2110 
2111             if (version & VER_TR2)
2112                 type = Type(type + TR2_TYPES_START);
2113 
2114             if (version & VER_TR3)
2115                 type = Type(type + TR3_TYPES_START);
2116 
2117             if (version & VER_TR4)
2118                 type = Type(type + TR4_TYPES_START);
2119 
2120             #define REMAP_2(TYPE) case _##TYPE   : return TYPE
2121             #define REMAP_3(TYPE) case __##TYPE  : return TYPE
2122             #define REMAP_4(TYPE) case ___##TYPE : return TYPE
2123 
2124             switch (type) {
2125             // TR2
2126                 REMAP_2( LARA                 );
2127                 REMAP_2( LARA_PISTOLS         );
2128                 REMAP_2( LARA_BRAID           );
2129                 REMAP_2( LARA_SHOTGUN         );
2130                 REMAP_2( LARA_UZIS            );
2131                 REMAP_2( LARA_SPEC            );
2132                 REMAP_2( TRAP_FLOOR           );
2133                 REMAP_2( TRAP_SPIKES          );
2134                 REMAP_2( TRAP_BOULDER         );
2135                 REMAP_2( DART                 );
2136                 REMAP_2( TRAP_DART_EMITTER    );
2137                 REMAP_2( DRAWBRIDGE           );
2138                 REMAP_2( TRAP_SLAM            );
2139                 REMAP_2( BLOCK_1              );
2140                 REMAP_2( BLOCK_2              );
2141                 REMAP_2( BLOCK_3              );
2142                 REMAP_2( BLOCK_4              );
2143                 REMAP_2( TRAP_CEILING_1       );
2144                 REMAP_2( CUT_1                );
2145                 REMAP_2( CUT_2                );
2146                 REMAP_2( CUT_3                );
2147                 REMAP_2( SWITCH               );
2148                 REMAP_2( SWITCH_WATER         );
2149                 REMAP_2( DOOR_1               );
2150                 REMAP_2( DOOR_2               );
2151                 REMAP_2( DOOR_3               );
2152                 REMAP_2( DOOR_4               );
2153                 REMAP_2( DOOR_5               );
2154                 REMAP_2( DOOR_6               );
2155                 REMAP_2( DOOR_7               );
2156                 REMAP_2( DOOR_8               );
2157                 REMAP_2( TRAP_DOOR_1          );
2158                 REMAP_2( TRAP_DOOR_2          );
2159                 REMAP_2( BRIDGE_1             );
2160                 REMAP_2( BRIDGE_2             );
2161                 REMAP_2( BRIDGE_3             );
2162                 REMAP_2( INV_PASSPORT         );
2163                 REMAP_2( INV_HOME             );
2164                 REMAP_2( CUT_4                );
2165                 REMAP_2( INV_PASSPORT_CLOSED  );
2166                 REMAP_2( INV_MAP              );
2167                 REMAP_2( PISTOLS              );
2168                 REMAP_2( SHOTGUN              );
2169                 REMAP_2( UZIS                 );
2170                 REMAP_2( AMMO_PISTOLS         );
2171                 REMAP_2( AMMO_SHOTGUN         );
2172                 REMAP_2( AMMO_UZIS            );
2173                 REMAP_2( MEDIKIT_SMALL        );
2174                 REMAP_2( MEDIKIT_BIG          );
2175                 REMAP_2( INV_DETAIL           );
2176                 REMAP_2( INV_SOUND            );
2177                 REMAP_2( INV_CONTROLS         );
2178                 REMAP_2( INV_PISTOLS          );
2179                 REMAP_2( INV_SHOTGUN          );
2180                 REMAP_2( INV_UZIS             );
2181                 REMAP_2( INV_AMMO_PISTOLS     );
2182                 REMAP_2( INV_AMMO_SHOTGUN     );
2183                 REMAP_2( INV_AMMO_UZIS        );
2184                 REMAP_2( INV_MEDIKIT_SMALL    );
2185                 REMAP_2( INV_MEDIKIT_BIG      );
2186                 REMAP_2( PUZZLE_1             );
2187                 REMAP_2( PUZZLE_2             );
2188                 REMAP_2( PUZZLE_3             );
2189                 REMAP_2( PUZZLE_4             );
2190                 REMAP_2( INV_PUZZLE_1         );
2191                 REMAP_2( INV_PUZZLE_2         );
2192                 REMAP_2( INV_PUZZLE_3         );
2193                 REMAP_2( INV_PUZZLE_4         );
2194                 REMAP_2( PUZZLE_HOLE_1        );
2195                 REMAP_2( PUZZLE_HOLE_2        );
2196                 REMAP_2( PUZZLE_HOLE_3        );
2197                 REMAP_2( PUZZLE_HOLE_4        );
2198                 REMAP_2( PUZZLE_DONE_1        );
2199                 REMAP_2( PUZZLE_DONE_2        );
2200                 REMAP_2( PUZZLE_DONE_3        );
2201                 REMAP_2( PUZZLE_DONE_4        );
2202                 REMAP_2( KEY_ITEM_1           );
2203                 REMAP_2( KEY_ITEM_2           );
2204                 REMAP_2( KEY_ITEM_3           );
2205                 REMAP_2( KEY_ITEM_4           );
2206                 REMAP_2( INV_KEY_ITEM_1       );
2207                 REMAP_2( INV_KEY_ITEM_2       );
2208                 REMAP_2( INV_KEY_ITEM_3       );
2209                 REMAP_2( INV_KEY_ITEM_4       );
2210                 REMAP_2( KEY_HOLE_1           );
2211                 REMAP_2( KEY_HOLE_2           );
2212                 REMAP_2( KEY_HOLE_3           );
2213                 REMAP_2( KEY_HOLE_4           );
2214                 REMAP_2( ENEMY_REX            );
2215                 REMAP_2( EXPLOSION            );
2216                 REMAP_2( WATER_SPLASH         );
2217                 REMAP_2( BUBBLE               );
2218                 REMAP_2( BLOOD                );
2219                 REMAP_2( RICOCHET             );
2220                 REMAP_2( MUZZLE_FLASH         );
2221                 REMAP_2( VIEW_TARGET          );
2222                 REMAP_2( WATERFALL            );
2223                 REMAP_2( LAVA_PARTICLE        );
2224                 REMAP_2( TRAP_LAVA_EMITTER    );
2225                 REMAP_2( FLAME                );
2226                 REMAP_2( TRAP_FLAME_EMITTER   );
2227                 REMAP_2( GLYPHS               );
2228             // TR3
2229                 REMAP_3( LARA                 );
2230                 REMAP_3( LARA_PISTOLS         );
2231                 REMAP_3( LARA_BRAID           );
2232                 REMAP_3( LARA_SHOTGUN         );
2233                 REMAP_3( LARA_UZIS            );
2234                 REMAP_3( LARA_GRENADE         );
2235                 REMAP_3( LARA_HARPOON         );
2236                 REMAP_3( LARA_FLARE           );
2237                 REMAP_3( VEHICLE_BOAT         );
2238                 REMAP_3( ENEMY_DOG            );
2239                 REMAP_3( ENEMY_RAT            );
2240                 REMAP_3( ENEMY_DIVER          );
2241                 REMAP_3( ENEMY_CROW           );
2242                 REMAP_3( ENEMY_TIGER          );
2243                 REMAP_3( TRAP_FLOOR           );
2244                 REMAP_3( TRAP_SPIKES          );
2245                 REMAP_3( TRAP_BOULDER         );
2246                 REMAP_3( DART                 );
2247                 REMAP_3( TRAP_DART_EMITTER    );
2248                 REMAP_3( BLOCK_1              );
2249                 REMAP_3( BLOCK_2              );
2250                 REMAP_3( BLOCK_3              );
2251                 REMAP_3( BLOCK_4              );
2252                 REMAP_3( WINDOW_1             );
2253                 REMAP_3( WINDOW_2             );
2254                 REMAP_3( TRAP_CEILING_1       );
2255                 REMAP_3( TRAP_SPINDLE         );
2256                 REMAP_3( TRAP_ICICLES         );
2257                 REMAP_3( TRAP_SPIKES_WALL     );
2258                 REMAP_3( WHEEL_KNOB           );
2259                 REMAP_3( SWITCH_BIG           );
2260                 REMAP_3( CUT_1                );
2261                 REMAP_3( CUT_2                );
2262                 REMAP_3( CUT_3                );
2263                 REMAP_3( UI_FRAME             );
2264                 REMAP_3( ZIPLINE_HANDLE       );
2265                 REMAP_3( SWITCH_BUTTON        );
2266                 REMAP_3( SWITCH               );
2267                 REMAP_3( SWITCH_WATER         );
2268                 REMAP_3( DOOR_1               );
2269                 REMAP_3( DOOR_2               );
2270                 REMAP_3( DOOR_3               );
2271                 REMAP_3( DOOR_4               );
2272                 REMAP_3( DOOR_5               );
2273                 REMAP_3( DOOR_6               );
2274                 REMAP_3( DOOR_7               );
2275                 REMAP_3( DOOR_8               );
2276                 REMAP_3( TRAP_DOOR_1          );
2277                 REMAP_3( TRAP_DOOR_2          );
2278                 REMAP_3( TRAP_DOOR_3          );
2279                 REMAP_3( BRIDGE_1             );
2280                 REMAP_3( BRIDGE_2             );
2281                 REMAP_3( BRIDGE_3             );
2282                 REMAP_3( INV_PASSPORT         );
2283                 REMAP_3( INV_STOPWATCH        );
2284                 REMAP_3( INV_HOME             );
2285                 REMAP_3( CUT_4                );
2286                 REMAP_3( CUT_5                );
2287                 REMAP_3( CUT_6                );
2288                 REMAP_3( CUT_7                );
2289                 REMAP_3( CUT_8                );
2290                 REMAP_3( CUT_9                );
2291                 REMAP_3( CUT_10               );
2292                 REMAP_3( CUT_11               );
2293                 REMAP_3( INV_PASSPORT_CLOSED  );
2294                 REMAP_3( INV_MAP              );
2295                 REMAP_3( PISTOLS              );
2296                 REMAP_3( SHOTGUN              );
2297                 REMAP_3( UZIS                 );
2298                 REMAP_3( HARPOON              );
2299                 REMAP_3( GRENADE              );
2300                 REMAP_3( AMMO_PISTOLS         );
2301                 REMAP_3( AMMO_SHOTGUN         );
2302                 REMAP_3( AMMO_UZIS            );
2303                 REMAP_3( AMMO_HARPOON         );
2304                 REMAP_3( AMMO_GRENADE         );
2305                 REMAP_3( MEDIKIT_SMALL        );
2306                 REMAP_3( MEDIKIT_BIG          );
2307                 REMAP_3( FLARES               );
2308                 REMAP_3( FLARE                );
2309                 REMAP_3( INV_DETAIL           );
2310                 REMAP_3( INV_SOUND            );
2311                 REMAP_3( INV_CONTROLS         );
2312                 REMAP_3( INV_PISTOLS          );
2313                 REMAP_3( INV_SHOTGUN          );
2314                 REMAP_3( INV_UZIS             );
2315                 REMAP_3( INV_HARPOON          );
2316                 REMAP_3( INV_GRENADE          );
2317                 REMAP_3( INV_AMMO_PISTOLS     );
2318                 REMAP_3( INV_AMMO_SHOTGUN     );
2319                 REMAP_3( INV_AMMO_UZIS        );
2320                 REMAP_3( INV_AMMO_HARPOON     );
2321                 REMAP_3( INV_AMMO_GRENADE     );
2322                 REMAP_3( INV_MEDIKIT_SMALL    );
2323                 REMAP_3( INV_MEDIKIT_BIG      );
2324                 REMAP_3( INV_FLARES           );
2325                 REMAP_3( PUZZLE_1             );
2326                 REMAP_3( PUZZLE_2             );
2327                 REMAP_3( PUZZLE_3             );
2328                 REMAP_3( PUZZLE_4             );
2329                 REMAP_3( INV_PUZZLE_1         );
2330                 REMAP_3( INV_PUZZLE_2         );
2331                 REMAP_3( INV_PUZZLE_3         );
2332                 REMAP_3( INV_PUZZLE_4         );
2333                 REMAP_3( PUZZLE_HOLE_1        );
2334                 REMAP_3( PUZZLE_HOLE_2        );
2335                 REMAP_3( PUZZLE_HOLE_3        );
2336                 REMAP_3( PUZZLE_HOLE_4        );
2337                 REMAP_3( PUZZLE_DONE_1        );
2338                 REMAP_3( PUZZLE_DONE_2        );
2339                 REMAP_3( PUZZLE_DONE_3        );
2340                 REMAP_3( PUZZLE_DONE_4        );
2341                 REMAP_3( KEY_ITEM_1           );
2342                 REMAP_3( KEY_ITEM_2           );
2343                 REMAP_3( KEY_ITEM_3           );
2344                 REMAP_3( KEY_ITEM_4           );
2345                 REMAP_3( INV_KEY_ITEM_1       );
2346                 REMAP_3( INV_KEY_ITEM_2       );
2347                 REMAP_3( INV_KEY_ITEM_3       );
2348                 REMAP_3( INV_KEY_ITEM_4       );
2349                 REMAP_3( KEY_HOLE_1           );
2350                 REMAP_3( KEY_HOLE_2           );
2351                 REMAP_3( KEY_HOLE_3           );
2352                 REMAP_3( KEY_HOLE_4           );
2353                 REMAP_3( QUEST_ITEM_1         );
2354                 REMAP_3( QUEST_ITEM_2         );
2355                 REMAP_3( INV_QUEST_ITEM_1     );
2356                 REMAP_3( INV_QUEST_ITEM_2     );
2357                 REMAP_3( ENEMY_REX            );
2358                 REMAP_3( ENEMY_RAPTOR         );
2359                 REMAP_3( DETONATOR            );
2360                 REMAP_3( BUBBLE               );
2361                 REMAP_3( MUZZLE_GLOW          );
2362                 REMAP_3( MUZZLE_FLASH         );
2363                 REMAP_3( VIEW_TARGET          );
2364                 REMAP_3( WATERFALL            );
2365                 REMAP_3( HARPOON_WTF          );
2366                 REMAP_3( SMOKE                );
2367                 REMAP_3( SKY                  );
2368                 REMAP_3( GLYPHS               );
2369                 REMAP_3( SOUND_DOOR_BELL      );
2370                 REMAP_3( ENEMY_WINSTON        );
2371                 REMAP_3( EARTHQUAKE           );
2372             // TR4
2373                 REMAP_4( LARA                 );
2374                 REMAP_4( LARA_PISTOLS         );
2375                 REMAP_4( LARA_UZIS            );
2376                 REMAP_4( LARA_SHOTGUN         );
2377                 REMAP_4( LARA_GRENADE         );
2378                 REMAP_4( LARA_FLARE           );
2379                 REMAP_4( LARA_SKIN            );
2380                 REMAP_4( LARA_BRAID           );
2381                 REMAP_4( FLAME                );
2382                 REMAP_4( TRAP_FLAME_EMITTER   );
2383                 REMAP_4( TRIPWIRE             );
2384                 REMAP_4( BLOCK_1              );
2385                 REMAP_4( BLOCK_2              );
2386                 REMAP_4( BLOCK_3              );
2387                 REMAP_4( BLOCK_4              );
2388                 REMAP_4( GRENADE              );
2389                 REMAP_4( INV_MEDIKIT_BIG      );
2390                 REMAP_4( INV_MEDIKIT_SMALL    );
2391                 REMAP_4( FLARES               );
2392                 REMAP_4( INV_FLARES           );
2393                 REMAP_4( INV_PASSPORT         );
2394                 REMAP_4( INV_COMPASS          );
2395                 REMAP_4( EARTHQUAKE           );
2396                 REMAP_4( MUZZLE_FLASH         );
2397                 REMAP_4( AI_GUARD             );
2398                 REMAP_4( AI_AMBUSH            );
2399                 REMAP_4( AI_MODIFY            );
2400                 REMAP_4( AI_FOLLOW            );
2401                 REMAP_4( KILL_ALL_TRIGGERS    );
2402                 REMAP_4( SKY                  );
2403                 //REMAP_4( GLYPHS               );
2404                 REMAP_4( MISC_SPRITES         );
2405 
2406                 default : return type;
2407             }
2408 
2409             #undef REMAP
2410         }
2411 
2412 
isEnemyEntity2413         bool isEnemy() const {
2414             return (type >= ENEMY_DOPPELGANGER && type <= ENEMY_GIANT_MUTANT) || type == SCION_TARGET ||
2415                    (type >= ENEMY_DOG && type <= ENEMY_DRAGON_BACK) ||
2416                    (type >= ENEMY_SHARK && type <= ENEMY_MONK_2);
2417         }
2418 
isBigEnemyEntity2419         bool isBigEnemy() const {
2420             return type == ENEMY_REX || type == ENEMY_MUTANT_1 || type == ENEMY_CENTAUR;
2421         }
2422 
isVehicleEntity2423         bool isVehicle() const {
2424             return type == VEHICLE_BOAT || type == VEHICLE_SNOWMOBILE_RED || type == VEHICLE_SNOWMOBILE_BLACK;
2425         }
2426 
isDoorEntity2427         bool isDoor() const {
2428             return type >= DOOR_1 && type <= DOOR_8;
2429         }
2430 
isPuzzleItemEntity2431         static bool isPuzzleItem(Type type) {
2432             return (type >= PUZZLE_1 && type <= PUZZLE_4) || (type >= INV_PUZZLE_1 && type <= INV_PUZZLE_4);
2433         }
2434 
isKeyItemEntity2435         static bool isKeyItem(Type type) {
2436             return (type >= KEY_ITEM_1 && type <= KEY_ITEM_4) || (type >= INV_KEY_ITEM_1 && type <= INV_KEY_ITEM_4);
2437         }
2438 
isWeaponEntity2439         static bool isWeapon(Type type) {
2440             return (type >= PISTOLS && type <= AMMO_UZIS) ||
2441                    (type == M16 || type == AMMO_M16) ||
2442                    (type == MP5 || type == AMMO_MP5) ||
2443                    (type == AUTOPISTOLS || type == AMMO_AUTOPISTOLS) ||
2444                    (type == DESERT_EAGLE || type == AMMO_DESERT_EAGLE) ||
2445                    (type == GRENADE || type == AMMO_GRENADE) ||
2446                    (type == ROCKET || type == AMMO_ROCKET) ||
2447                    (type == HARPOON || type == AMMO_HARPOON);
2448         }
2449 
isPickupEntity2450         static bool isPickup(Type type) {
2451             return isPuzzleItem(type) ||
2452                    isKeyItem(type) ||
2453                    isWeapon(type) ||
2454                    (type == MEDIKIT_SMALL || type == MEDIKIT_BIG) ||
2455                    (type == SCION_PICKUP_QUALOPEC || type == SCION_PICKUP_DROP || type == SCION_PICKUP_HOLDER || type == LEADBAR) ||
2456                    (type == CRYSTAL) ||
2457                    (type >= SECRET_1 && type <= SECRET_3) ||
2458                    (type == FLARES || type == FLARE) ||
2459                    (type >= STONE_ITEM_1 && type <= STONE_ITEM_4);
2460         }
2461 
isInventoryItemEntity2462         static bool isInventoryItem(Type type) {
2463             return type == INV_PASSPORT
2464                 || type == INV_PASSPORT_CLOSED
2465                 || type == INV_MAP
2466                 || type == INV_COMPASS
2467                 || type == INV_STOPWATCH
2468                 || type == INV_HOME
2469                 || type == INV_DETAIL
2470                 || type == INV_SOUND
2471                 || type == INV_CONTROLS
2472                 || type == INV_GAMMA
2473                 || type == INV_PISTOLS
2474                 || type == INV_SHOTGUN
2475                 || type == INV_MAGNUMS
2476                 || type == INV_UZIS
2477                 || type == INV_AMMO_PISTOLS
2478                 || type == INV_AMMO_SHOTGUN
2479                 || type == INV_AMMO_MAGNUMS
2480                 || type == INV_AMMO_UZIS
2481                 || type == INV_EXPLOSIVE
2482                 || type == INV_MEDIKIT_SMALL
2483                 || type == INV_MEDIKIT_BIG
2484                 || type == INV_PUZZLE_1
2485                 || type == INV_PUZZLE_2
2486                 || type == INV_PUZZLE_3
2487                 || type == INV_PUZZLE_4
2488                 || type == INV_KEY_ITEM_1
2489                 || type == INV_KEY_ITEM_2
2490                 || type == INV_KEY_ITEM_3
2491                 || type == INV_KEY_ITEM_4
2492                 || type == INV_LEADBAR
2493                 || type == INV_SCION;
2494         }
2495 
isCrossLevelItemEntity2496         static bool isCrossLevelItem(Type type) {
2497             return isPickup(type) && !isPuzzleItem(type) && !isKeyItem(type) && (type != LEADBAR) && !(type >= SECRET_1 && type <= SECRET_3);
2498         }
2499 
isPickupEntity2500         bool isPickup() const {
2501             return isPickup(type);
2502         }
2503 
isActorEntity2504         bool isActor() const {
2505             return (type >= CUT_1 && type <= CUT_4) || (type >= CUT_5 && type <= CUT_11) || (type == CUT_12);
2506         }
2507 
isPuzzleHoleEntity2508         bool isPuzzleHole() const {
2509             return type >= PUZZLE_HOLE_1 && type <= PUZZLE_HOLE_4;
2510         }
2511 
isBlockEntity2512         bool isBlock() const {
2513             return type == BLOCK_1 || type == BLOCK_2 || type == BLOCK_3 || type == BLOCK_4 || type == BLOCK_5;
2514         }
2515 
isLaraEntity2516         bool isLara() const {
2517             return type == LARA;
2518         }
2519 
isSpriteEntity2520         bool isSprite() const {
2521             return type == EXPLOSION || type == WATER_SPLASH || type == BUBBLE ||
2522                    type == BLOOD || type == SMOKE || type == FLAME ||
2523                    type == RICOCHET || type == SPARKLES || type == LAVA_PARTICLE;
2524         }
2525 
castShadowEntity2526         bool castShadow() const {
2527             return isLara() || isEnemy() || isVehicle() || isActor() || type == DART || type == TRAP_SWORD || type == ENEMY_WINSTON || type == ENEMY_WINSTON_CAMO;
2528         }
2529 
getAxisEntity2530         void getAxis(int &dx, int &dz) {
2531             switch (rotation.value / 0x4000) {
2532                 case 0  : dx =  0; dz =  1; break;
2533                 case 1  : dx =  1; dz =  0; break;
2534                 case 2  : dx =  0; dz = -1; break;
2535                 case 3  : dx = -1; dz =  0; break;
2536                 default : dx =  0; dz =  0; break;
2537             }
2538         }
2539 
getItemForHoleEntity2540         static Type getItemForHole(Type hole) {
2541             switch (hole) {
2542                 case PUZZLE_HOLE_1 : return PUZZLE_1;
2543                 case PUZZLE_HOLE_2 : return PUZZLE_2;
2544                 case PUZZLE_HOLE_3 : return PUZZLE_3;
2545                 case PUZZLE_HOLE_4 : return PUZZLE_4;
2546                 case KEY_HOLE_1    : return KEY_ITEM_1;
2547                 case KEY_HOLE_2    : return KEY_ITEM_2;
2548                 case KEY_HOLE_3    : return KEY_ITEM_3;
2549                 case KEY_HOLE_4    : return KEY_ITEM_4;
2550                 case MIDAS_HAND    : return LEADBAR;
2551                 default            : return LARA;
2552             }
2553         }
2554 
fixOpaqueEntity2555         static void fixOpaque(Type type, bool &opaque) { // to boost performance on mobile devices
2556             if (type >= LARA && type <= ENEMY_GIANT_MUTANT
2557                 && type != ENEMY_REX
2558                 && type != ENEMY_RAPTOR
2559                 && type != ENEMY_MUTANT_1
2560                 && type != ENEMY_MUTANT_2
2561                 && type != ENEMY_MUTANT_3
2562                 && type != ENEMY_CENTAUR
2563                 && type != ENEMY_GIANT_MUTANT
2564                 && type != ENEMY_MUMMY
2565                 && type != ENEMY_NATLA)
2566                 opaque = true;
2567             if (type == SWITCH || type == SWITCH_WATER || type == CUT_1)
2568                 opaque = true;
2569             if ((type >= PUZZLE_HOLE_1 && type <= PUZZLE_HOLE_4) || type == LIGHTNING)
2570                 opaque = false;
2571         }
2572     };
2573 
2574     #define INV_ITEM_PAIR(TYPE) { Entity::TYPE, Entity::INV_##TYPE }
2575 
2576     static struct {
2577         Entity::Type src, dst;
2578     } ITEM_TO_INV[] = {
2579     // weapon
2580         INV_ITEM_PAIR(PISTOLS),
2581         INV_ITEM_PAIR(SHOTGUN),
2582         INV_ITEM_PAIR(MAGNUMS),
2583         INV_ITEM_PAIR(UZIS),
2584         INV_ITEM_PAIR(AUTOPISTOLS),
2585         INV_ITEM_PAIR(HARPOON),
2586         INV_ITEM_PAIR(M16),
2587         INV_ITEM_PAIR(GRENADE),
2588     // ammo
2589         INV_ITEM_PAIR(AMMO_PISTOLS),
2590         INV_ITEM_PAIR(AMMO_SHOTGUN),
2591         INV_ITEM_PAIR(AMMO_MAGNUMS),
2592         INV_ITEM_PAIR(AMMO_UZIS),
2593         INV_ITEM_PAIR(AMMO_AUTOPISTOLS),
2594         INV_ITEM_PAIR(AMMO_HARPOON),
2595         INV_ITEM_PAIR(AMMO_M16),
2596         INV_ITEM_PAIR(AMMO_GRENADE),
2597     // items
2598         INV_ITEM_PAIR(MEDIKIT_BIG),
2599         INV_ITEM_PAIR(MEDIKIT_SMALL),
2600         INV_ITEM_PAIR(FLARES),
2601     // key items
2602         INV_ITEM_PAIR(KEY_ITEM_1),
2603         INV_ITEM_PAIR(KEY_ITEM_2),
2604         INV_ITEM_PAIR(KEY_ITEM_3),
2605         INV_ITEM_PAIR(KEY_ITEM_4),
2606     // puzzle items
2607         INV_ITEM_PAIR(PUZZLE_1),
2608         INV_ITEM_PAIR(PUZZLE_2),
2609         INV_ITEM_PAIR(PUZZLE_3),
2610         INV_ITEM_PAIR(PUZZLE_4),
2611     // other items
2612         INV_ITEM_PAIR(LEADBAR),
2613         INV_ITEM_PAIR(QUEST_ITEM_1),
2614         INV_ITEM_PAIR(QUEST_ITEM_2),
2615         { Entity::SCION_PICKUP_DROP,     Entity::INV_SCION },
2616         { Entity::SCION_PICKUP_QUALOPEC, Entity::INV_SCION },
2617     };
2618 
2619     #undef INV_ITEM_PAIR
2620 
2621     struct Animation {
2622         uint32  frameOffset;
2623         uint8   frameRate;
2624         uint8   frameSize;
2625 
2626         uint16  state;
2627 
2628         fixed   speed;
2629         fixed   accel;
2630 
2631         fixed   speedLateral;
2632         fixed   accelLateral;
2633 
2634         uint16  frameStart;
2635         uint16  frameEnd;
2636         uint16  nextAnimation;
2637         uint16  nextFrame;
2638 
2639         uint16  scCount;
2640         uint16  scOffset;
2641 
2642         uint16  acCount;
2643         uint16  animCommand;
2644     };
2645 
2646     struct AnimState {
2647         uint16  state;
2648         uint16  rangesCount;
2649         uint16  rangesOffset;
2650     };
2651 
2652     struct AnimRange {
2653         int16   low;            // Lowest frame that uses this range
2654         int16   high;           // Highest frame that uses this range
2655         int16   nextAnimation;  // Animation to dispatch to
2656         int16   nextFrame;      // Frame offset to dispatch to
2657     };
2658 
2659     struct MinMax {
2660         int16 minX, maxX, minY, maxY, minZ, maxZ;
2661 
minMinMax2662         vec3 min() const { return vec3((float)minX, (float)minY, (float)minZ); }
maxMinMax2663         vec3 max() const { return vec3((float)maxX, (float)maxY, (float)maxZ); }
2664     };
2665 
2666     struct AnimFrame {
2667         MinMax  box;
2668         short3  pos;
2669         uint16  angles[1];  // angle frames in YXZ order, first angle must be skipped in TR1
2670 
2671         #define ANGLE_SCALE (PI2 / 1024.0f)
2672 
unpackAnimFrame2673         vec3 unpack(uint16 a, uint16 b) {
2674             return vec3(float((a & 0x3FF0) >> 4), float( ((a & 0x000F) << 6) | ((b & 0xFC00) >> 10)), float(b & 0x03FF)) * ANGLE_SCALE;
2675         }
2676 
getAngleAnimFrame2677         vec3 getAngle(Version version, int joint) {
2678             int index = 0;
2679 
2680             if (version & VER_TR1) {
2681                 index = joint * 2 + 1;
2682                 uint16 b = angles[index++];
2683                 uint16 a = angles[index++];
2684                 if (version & VER_SAT) {
2685                     swap(a, b);
2686                 }
2687                 return unpack(a, b);
2688             } else {
2689                 // TODO: optimize this !!!
2690                 for (int i = 0; i < joint; i++) {
2691                     if (!(angles[index++] & 0xC000)) {
2692                         index++;
2693                     }
2694                 }
2695 
2696                 uint16 a = angles[index++];
2697 
2698                 float rot;
2699                 if (((version & VER_VERSION) >= VER_TR4)) {
2700                     rot = float(a & 0x0FFF) * (PI2 / 4096.0f);
2701                 } else {
2702                     rot = float(a & 0x03FF) * (PI2 / 1024.0f);
2703                 }
2704 
2705                 switch (a & 0xC000) {
2706                     case 0x4000 : return vec3(rot, 0, 0);
2707                     case 0x8000 : return vec3(0, rot, 0);
2708                     case 0xC000 : return vec3(0, 0, rot);
2709                     default     : return unpack(a, angles[index++]);
2710                 }
2711             }
2712 
2713             return vec3(0);
2714         }
2715 
2716         #undef ANGLE_SCALE
2717     };
2718 
2719     struct AnimTexture {
2720         uint16 count;
2721         uint16 *textures;
2722     };
2723 
2724     struct Node {
2725         uint32  flags;
2726         int32   x, y, z;
2727     };
2728 
2729     struct Model {
2730         Entity::Type type;
2731         uint16       index;
2732         uint16       mCount;
2733         uint16       mStart;
2734         uint32       node;
2735         uint32       frame;
2736         uint16       animation;
2737         uint16       align;
2738     };
2739 
2740     struct StaticMesh {
2741         uint32  id;
2742         uint16  mesh;
2743         MinMax  vbox;
2744         MinMax  cbox;
2745         uint16  flags;
2746 
getBoxStaticMesh2747         void getBox(bool collision, angle rotation, ::Box &box) {
2748             int k = rotation.value / 0x4000;
2749 
2750             MinMax &m = collision ? cbox : vbox;
2751 
2752             ASSERT(m.minX <= m.maxX && m.minY <= m.maxY && m.minZ <= m.maxZ);
2753 
2754             box = ::Box(m.min(), m.max());
2755             box.rotate90(k);
2756 
2757             ASSERT(box.min.x <= box.max.x && box.min.y <= box.max.y && box.min.z <= box.max.z);
2758         }
2759     };
2760 
2761     struct SpriteSequence {
2762         Entity::Type type;
2763         uint16       unused;
2764         int16        sCount;
2765         int16        sStart;
2766         uint8        transp;
2767     };
2768 
2769     struct Camera {
2770         int32   x, y, z;
2771         union {
2772             int16   room;   // for camera
2773             int16   speed;  // for sink (underwater current)
2774         };
2775         union {
2776             struct { uint16 :8, once:1, :5, :2; };
2777             uint16 boxIndex;
2778         } flags;
2779     };
2780 
2781     struct FlybyCamera {
2782         int32   x, y, z;
2783         int32   dx, dy, dz;
2784         uint8   sequence;
2785         uint8   index;
2786         uint16  fov;
2787         int16   roll;
2788         uint16  timer;
2789         uint16  speed;
2790         uint16  flags;
2791         uint32  room;
2792     };
2793 
2794     struct CameraFrame {
2795         short3  target;
2796         short3  pos;
2797         int16   fov;
2798         int16   roll;
2799     };
2800 
2801     struct AIObject {
2802         uint16 type;
2803         uint16 room;
2804         int32  x, y, z;
2805         uint16 OCB;
2806         uint16 flags;
2807         int32  angle;
2808     };
2809 
2810     struct SoundSource {
2811         int32   x, y, z;    // absolute position of sound source (world coordinates)
2812         uint16  id;         // internal sample index
2813         uint16  flags;      // 0x40, 0x80, or 0xC0
2814     };
2815 
2816     struct Box {
2817         union {
2818             struct {
2819                 int32 minZ, maxZ; // Horizontal dimensions in global units
2820                 int32 minX, maxX;
2821             };
2822             int32 sides[4];
2823         };
2824 
2825         int16   floor; // Height value in global units
2826         union {
2827             struct {
2828                 uint16 index:14, block:1, blockable:1;    // Index into Overlaps[].
2829             };
2830             uint16 value;
2831         } overlap;
2832 
containsBox2833         bool contains(int32 x, int32 z) const {
2834             return z >= minZ && z <= maxZ && x >= minX && x <= maxX;
2835         }
2836 
expandBox2837         void expand(int32 value) {
2838             minZ -= value;
2839             minX -= value;
2840             maxZ += value;
2841             maxX += value;
2842         }
2843 
clipBox2844         void clip(const Box &box) {
2845             minZ = max(minZ, box.minZ);
2846             minX = max(minX, box.minX);
2847             maxZ = min(maxZ, box.maxZ);
2848             maxX = min(maxX, box.maxX);
2849         }
2850     };
2851 
2852     struct Zone {
2853         uint16 *ground1;
2854         uint16 *ground2;
2855         uint16 *ground3;
2856         uint16 *ground4;
2857         uint16 *fly;
2858     };
2859 
2860     struct SoundInfo {
2861         float  volume;
2862         float  chance;
2863         float  range;
2864         float  pitch;
2865         uint16 index;
2866         union {
2867             struct { uint16 mode:2, count:4, unused:6, camera:1, pitch:1, gain:1, :1; };
2868             uint16 value;
2869         } flags;
2870     };
2871 
2872     struct Location {
2873         int16  room;
2874         uint16 box;
2875         vec3   pos;
2876     };
2877 
2878     struct Level {
2879         Version         version;
2880         LevelID         id;
2881 
2882         int32           tilesCount;
2883 
2884         uint16          roomsCount;
2885         Room            *rooms;
2886 
2887         int32           floorsCount;
2888         FloorData       *floors;
2889 
2890         int16           meshesCount;
2891         Mesh            meshes[MAX_MESHES];
2892 
2893         int32           meshDataSize;
2894         uint16          *meshData;
2895 
2896         int32           meshOffsetsCount;
2897         int32           *meshOffsets;
2898 
2899         int32           animsCount;
2900         Animation       *anims;
2901 
2902         int32           statesCount;
2903         AnimState       *states;
2904 
2905         int32           rangesCount;
2906         AnimRange       *ranges;
2907 
2908         int32           commandsCount;
2909         int16           *commands;
2910 
2911         int32           nodesDataSize;
2912         uint32          *nodesData;
2913 
2914         int32           frameDataSize;
2915         uint16          *frameData;
2916 
2917         int32           modelsCount;
2918         Model           *models;
2919 
2920         int32           staticMeshesCount;
2921         StaticMesh      *staticMeshes;
2922 
2923         int32           objectTexturesBaseCount;
2924         int32           objectTexturesCount;
2925         TextureInfo     *objectTextures;
2926 
2927         int32           objectTexturesDataSize;
2928         uint8           *objectTexturesData;
2929 
2930         int32           roomTexturesCount;
2931         TextureInfo     *roomTextures;
2932 
2933         int32           roomTexturesDataSize;
2934         uint8           *roomTexturesData;
2935 
2936         int32           itemTexturesCount;
2937         TextureInfo     *itemTextures;
2938 
2939         int32           itemTexturesBaseCount;
2940         int32           itemTexturesDataSize;
2941         uint8           *itemTexturesData;
2942 
2943         int32           spriteTexturesCount;
2944         TextureInfo     *spriteTextures;
2945 
2946         int32           spriteSequencesCount;
2947         SpriteSequence  *spriteSequences;
2948 
2949         int32           spriteTexturesDataSize;
2950         uint8           *spriteTexturesData;
2951 
2952         int32           camerasCount;
2953         Camera          *cameras;
2954 
2955         int32           flybyCamerasCount;
2956         FlybyCamera     *flybyCameras;
2957 
2958         int32           soundSourcesCount;
2959         SoundSource     *soundSources;
2960 
2961         int32           boxesCount;
2962         Box             *boxes;
2963         int32           overlapsCount;
2964         Overlap         *overlaps;
2965         Zone            zones[2];   // default and alternative
2966 
2967         int16           animTexturesCount;
2968         AnimTexture     *animTextures;
2969 
2970         int32           entitiesBaseCount;
2971         int32           entitiesCount;
2972         Entity          *entities;
2973 
2974         uint8           lightmap[32 * 256]; // color indices table for 32 shades
2975         Color24         *palette;
2976         Color32         *palette32;
2977 
2978         uint16          kanjiSprite;
2979         int32           clutsCount;
2980         CLUT            *cluts;
2981 
2982         Tile4           *tiles4;
2983         Tile8           *tiles8;
2984         Tile16          *tiles16;
2985         Tile32          *tiles32;
2986         Tile32          *tilesMisc;
2987 
2988 
2989         uint16          cameraFramesCount;
2990         CameraFrame     *cameraFrames;
2991 
2992         AIObject        *AIObjects;
2993         uint32          AIObjectsCount;
2994 
2995         uint16          demoDataSize;
2996         uint8           *demoData;
2997 
2998         int16           *soundsMap;
2999 
3000         int32           soundsInfoCount;
3001         SoundInfo       *soundsInfo;
3002 
3003         int32           soundsCount;
3004         int32           soundDataSize;
3005         uint8           *soundData;
3006 
3007         int32           soundOffsetsCount;
3008         uint32          *soundOffsets;
3009         uint32          *soundSize;
3010 
3011         Color32         skyColor;
3012 
3013    // common
3014         struct Trigger {
3015             enum Type {
3016                 ACTIVATE    ,
3017                 PAD         ,
3018                 SWITCH      ,
3019                 KEY         ,
3020                 PICKUP      ,
3021                 HEAVY       ,
3022                 ANTIPAD     ,
3023                 COMBAT      ,
3024                 DUMMY       ,
3025             };
3026         };
3027 
3028         struct FloorInfo {
3029         // TODO reduse type sizes
3030             float roomFloor, roomCeiling;
3031             int roomNext, roomBelow, roomAbove;
3032             float floor, ceiling;
3033             int slantX, slantZ;
3034             int floorIndex;
3035             int boxIndex;
3036             int lava;
3037             int climb;
3038             int trigCmdCount;
3039             Trigger::Type trigger;
3040             FloorData::TriggerInfo trigInfo;
3041             FloorData::TriggerCommand trigCmd[MAX_TRIGGER_COMMANDS];
3042 
getNormalLevel::FloorInfo3043             vec3 getNormal() {
3044                 return vec3((float)-slantX, -4.0f, (float)-slantZ).normal();
3045             }
3046 
getSlantLevel::FloorInfo3047             vec3 getSlant(const vec3 &dir) {
3048                 // project floor normal into plane(dir, up)
3049                 vec3 r = vec3(dir.z, 0.0f, -dir.x); // up(0, 1, 0).cross(dir)
3050                 vec3 n = getNormal();
3051                 n = n - r * r.dot(n);
3052                 // project dir into plane(dir, n)
3053                 return n.cross(dir.cross(n)).normal();
3054             }
3055         };
3056 
3057         SaveState    state;
3058 
3059         int     cutEntity;
3060         mat4    cutMatrix;
3061         bool    isDemoLevel;
3062         bool    simpleItems;
3063 
3064         struct Extra {
3065 
getWeaponIndexLevel::Extra3066             static int getWeaponIndex(Entity::Type type) {
3067                 #if MAX_WEAPONS != 4
3068                     #error update this func first
3069                 #endif
3070 
3071                 switch (type) {
3072                 // pistols
3073                     case Entity::LARA_PISTOLS      :
3074                     case Entity::INV_PISTOLS       :
3075                     case Entity::INV_AMMO_PISTOLS  :
3076                     case Entity::AMMO_PISTOLS      :
3077                     case Entity::PISTOLS           : return  0;
3078                 // shotgun
3079                     case Entity::LARA_SHOTGUN      :
3080                     case Entity::INV_SHOTGUN       :
3081                     case Entity::INV_AMMO_SHOTGUN  :
3082                     case Entity::AMMO_SHOTGUN      :
3083                     case Entity::SHOTGUN           : return  1;
3084                 // magnums
3085                     case Entity::LARA_MAGNUMS      :
3086                     case Entity::INV_MAGNUMS       :
3087                     case Entity::INV_AMMO_MAGNUMS  :
3088                     case Entity::AMMO_MAGNUMS      :
3089                     case Entity::MAGNUMS           : return  2;
3090                 // uzis
3091                     case Entity::LARA_UZIS         :
3092                     case Entity::INV_UZIS          :
3093                     case Entity::INV_AMMO_UZIS     :
3094                     case Entity::AMMO_UZIS         :
3095                     case Entity::UZIS              : return  3;
3096 
3097                     default : ASSERT(false);
3098                 }
3099                 return 0;
3100             }
3101 
3102             int16 muzzleFlash;
3103             int16 puzzleDone[4];
3104             int16 braid;
3105             int16 laraSpec;
3106             int16 laraSkin;
3107             int16 laraJoints;
3108             int16 meshSwap[3];
3109             int16 sky;
3110             int16 smoke;
3111             int16 waterSplash;
3112             int16 glyphs;
3113 
3114             struct Weapon {
3115                 int16 items[MAX_WEAPONS];
3116                 int16& operator[] (Entity::Type type) {
3117                     return items[getWeaponIndex(type)];
3118                 };
3119             } weapons;
3120 
3121             struct Inventory {
3122                 int16 passport;
3123                 int16 passport_closed;
3124                 int16 map;
3125                 int16 compass;
3126                 int16 stopwatch;
3127                 int16 home;
3128                 int16 detail;
3129                 int16 sound;
3130                 int16 controls;
3131                 int16 gamma;
3132                 int16 explosive;
3133 
3134                 struct Weapon {
3135                     int16 items[MAX_WEAPONS];
3136                     int16& operator[] (Entity::Type type) {
3137                         return items[getWeaponIndex(type)];
3138                     };
3139                 } weapons;
3140 
3141                 struct Ammo {
3142                     int16 items[MAX_WEAPONS];
3143                     int16& operator[] (Entity::Type type) {
3144                         return items[getWeaponIndex(type)];
3145                     };
3146                 } ammo;
3147 
3148                 int16 medikit[2];
3149                 int16 puzzle[4];
3150                 int16 key[4];
3151 
3152                 int16 leadbar;
3153                 int16 scion;
3154             } inv;
3155         } extra;
3156 
3157         uint32 tsubCount;
3158         uint8 *tsub;
3159 
LevelLevel3160         Level(Stream &stream) {
3161             memset(this, 0, sizeof(*this));
3162             version     = VER_UNKNOWN;
3163             cutEntity   = -1;
3164             meshesCount = 0;
3165 
3166             uint32 magic;
3167 
3168             #define MAGIC_TR1_PC  0x00000020
3169             #define MAGIC_TR1_PSX 0x56414270
3170             #define MAGIC_TR1_SAT 0x4D4F4F52
3171             #define MAGIC_TR2_PC  0x0000002D
3172             #define MAGIC_TR3_PC1 0xFF080038
3173             #define MAGIC_TR3_PC2 0xFF180038
3174             #define MAGIC_TR3_PC3 0xFF180034
3175             #define MAGIC_TR3_PSX 0xFFFFFFC8
3176             #define MAGIC_TR4_PC  0x00345254
3177 
3178             id = TR::getLevelID(stream.size, stream.name, version, isDemoLevel);
3179 
3180             if (version == VER_UNKNOWN || version == VER_TR1_PC || version == VER_TR1_PSX || version == VER_TR1_SAT || version == VER_TR3_PSX) {
3181                 stream.read(magic);
3182 
3183                 if (magic != MAGIC_TR1_PC  &&
3184                     magic != MAGIC_TR1_SAT &&
3185                     magic != MAGIC_TR2_PC  &&
3186                     magic != MAGIC_TR3_PC1 &&
3187                     magic != MAGIC_TR3_PC2 &&
3188                     magic != MAGIC_TR3_PC3 &&
3189                     magic != MAGIC_TR3_PSX &&
3190                     magic != MAGIC_TR4_PC) {
3191                     stream.read(magic);
3192                 }
3193 
3194                 switch (magic) {
3195                     case MAGIC_TR1_PC  : version = VER_TR1_PC;  break;
3196                     case MAGIC_TR1_PSX : version = VER_TR1_PSX; break;
3197                     case MAGIC_TR1_SAT : version = VER_TR1_SAT; break;
3198                     case MAGIC_TR2_PC  : version = VER_TR2_PC;  break;
3199                     case MAGIC_TR3_PC1 :
3200                     case MAGIC_TR3_PC2 :
3201                     case MAGIC_TR3_PC3 : version = VER_TR3_PC;  break;
3202                     case MAGIC_TR3_PSX : version = VER_TR3_PSX; break;
3203                     case MAGIC_TR4_PC  : version = VER_TR4_PC;  break;
3204                     default            : ;
3205                 }
3206             }
3207 
3208             if (version == VER_UNKNOWN) {
3209                 LOG("unsupported level format\n");
3210                 ASSERT(false);
3211                 return;
3212             }
3213 
3214         #ifdef _GAPI_SW
3215             ASSERT((version & VER_TR1_PC) == VER_TR1_PC);
3216             if ((version & VER_TR1_PC) != VER_TR1_PC) {
3217                 return;
3218             }
3219         #endif
3220 
3221         #ifdef _GAPI_GU
3222             ASSERT((version & VER_TR1_PSX) == VER_TR1_PSX);
3223             if ((version & VER_TR1_PSX) != VER_TR1_PSX) {
3224                 return;
3225             }
3226         #endif
3227 
3228             switch (version) {
3229                 case VER_TR1_PC   : loadTR1_PC  (stream); break;
3230                 case VER_TR1_PSX  : loadTR1_PSX (stream); break;
3231                 case VER_TR1_SAT  : loadTR1_SAT (stream); break;
3232                 case VER_TR2_PC   : loadTR2_PC  (stream); break;
3233                 case VER_TR2_PSX  : loadTR2_PSX (stream); break;
3234                 case VER_TR3_PC   : loadTR3_PC  (stream); break;
3235                 case VER_TR3_PSX  : loadTR3_PSX (stream); break;
3236             #ifdef USE_INFLATE
3237                 case VER_TR4_PC   : loadTR4_PC  (stream); break;
3238             #endif
3239                 case VER_TR4_PSX  : loadTR4_PSX (stream); break;
3240                 case VER_TR4_SDC  : loadTR4_SDC (stream); break;
3241                 case VER_TR5_PC   : loadTR5_PC  (stream); break;
3242                 case VER_TR5_PSX  : loadTR5_PSX (stream); break;
3243                 case VER_TR5_SDC  : loadTR5_SDC (stream); break;
3244                 default           : ASSERT(false);
3245             }
3246 
3247             prepare();
3248         }
3249 
~LevelLevel3250         ~Level() {
3251         // rooms
3252             for (int i = 0; i < roomsCount; i++) {
3253                 Room &r = rooms[i];
3254                 delete[] r.data.vertices;
3255                 delete[] r.data.faces;
3256                 delete[] r.data.sprites;
3257                 delete[] r.portals;
3258                 delete[] r.sectors;
3259                 delete[] r.lights;
3260                 delete[] r.meshes;
3261             }
3262             delete[] rooms;
3263             delete[] floors;
3264             delete[] meshOffsets;
3265             delete[] anims;
3266             delete[] states;
3267             delete[] ranges;
3268             delete[] commands;
3269             delete[] nodesData;
3270             delete[] frameData;
3271             delete[] models;
3272             delete[] staticMeshes;
3273             delete[] objectTextures;
3274             delete[] objectTexturesData;
3275             delete[] roomTextures;
3276             delete[] roomTexturesData;
3277             delete[] itemTextures;
3278             delete[] itemTexturesData;
3279             delete[] spriteTextures;
3280             delete[] spriteSequences;
3281             delete[] spriteTexturesData;
3282             delete[] cameras;
3283             delete[] flybyCameras;
3284             delete[] soundSources;
3285             delete[] boxes;
3286             delete[] overlaps;
3287             for (int i = 0; i < 2; i++) {
3288                 delete[] zones[i].ground1;
3289                 delete[] zones[i].ground2;
3290                 delete[] zones[i].ground3;
3291                 delete[] zones[i].ground4;
3292                 delete[] zones[i].fly;
3293             }
3294             for (int i = 0; i < animTexturesCount; i++)
3295                 delete[] animTextures[i].textures;
3296             delete[] animTextures;
3297             delete[] entities;
3298             delete[] palette;
3299             delete[] palette32;
3300             delete[] cluts;
3301             delete[] tiles4;
3302             delete[] tiles8;
3303             delete[] tiles16;
3304             delete[] tiles32;
3305             delete[] tilesMisc;
3306             delete[] cameraFrames;
3307             delete[] AIObjects;
3308             delete[] demoData;
3309             delete[] soundsMap;
3310             delete[] soundsInfo;
3311             delete[] soundData;
3312             delete[] soundOffsets;
3313             delete[] soundSize;
3314 
3315             delete[] tsub;
3316         }
3317 
loadTR1_PCLevel3318         void loadTR1_PC (Stream &stream) {
3319             stream.read(tiles8, stream.read(tilesCount));
3320 
3321             readDataArrays(stream);
3322             readObjectTex(stream);
3323             readSpriteTex(stream);
3324 
3325             if (isDemoLevel) {
3326                 stream.read(palette, 256);
3327             }
3328 
3329             readCameras(stream);
3330             readSoundSources(stream);
3331             readBoxes(stream);
3332             readOverlaps(stream);
3333             readZones(stream);
3334             readAnimTex(stream);
3335             readEntities(stream);
3336             readLightMap(stream);
3337 
3338             if (!isDemoLevel) {
3339                 stream.read(palette, 256);
3340             }
3341 
3342             readCameraFrames(stream);
3343             readDemoData(stream);
3344             readSoundMap(stream);
3345             readSoundData(stream);
3346             readSoundOffsets(stream);
3347         }
3348 
loadTR1_PSXLevel3349         void loadTR1_PSX (Stream &stream) {
3350             if (!isCutsceneLevel()) {
3351                 uint32 offsetTexTiles;
3352                 stream.seek(8);
3353                 stream.read(offsetTexTiles);
3354             // sound offsets
3355                 uint16 numSounds;
3356                 stream.setPos(22);
3357                 stream.read(numSounds);
3358                 stream.setPos(2086 + numSounds * 512);
3359                 soundOffsetsCount = numSounds;
3360                 soundOffsets = new uint32[soundOffsetsCount];
3361                 soundSize    = new uint32[soundOffsetsCount];
3362                 soundDataSize = 0;
3363                 for (int i = 0; i < soundOffsetsCount; i++) {
3364                     soundOffsets[i] = soundDataSize;
3365                     uint16 size;
3366                     stream.read(size);
3367                     soundDataSize += soundSize[i] = size * 8;
3368                 }
3369             // sound data
3370                 stream.setPos(2600 + numSounds * 512);
3371                 stream.read(soundData, soundDataSize);
3372                 stream.setPos(offsetTexTiles + 8);
3373             }
3374 
3375             stream.read(tiles4, tilesCount = 13);
3376             stream.read(cluts,  clutsCount = 1024);
3377 
3378             readDataArrays(stream);
3379             readObjectTex(stream);
3380             readSpriteTex(stream);
3381             readCameras(stream);
3382             readSoundSources(stream);
3383             readBoxes(stream);
3384             readOverlaps(stream);
3385             readZones(stream);
3386             readAnimTex(stream);
3387             readEntities(stream);
3388             readSoundMap(stream);
3389             stream.seek(4);
3390             readCameraFrames(stream);
3391         }
3392 
loadTR1_SATLevel3393         void loadTR1_SAT (Stream &stream) {
3394             stream.seek(-4); // no magic header
3395 
3396         // get file name without extension
3397             size_t len = strlen(stream.name);
3398             char *name = new char[len + 1];
3399             memcpy(name, stream.name, len);
3400             for (int i = int(len) - 1; i >= 0; i--) {
3401                 if (name[i] == '/' || name[i] == '\\')
3402                     break;
3403                 if (name[i] == '.') {
3404                     len = i;
3405                     break;
3406                 }
3407             }
3408             name[len] = 0;
3409 
3410             LOG("load Sega Saturn level: %s\n", name);
3411 
3412             strcat(name, ".SAD");
3413             Stream sad(name);
3414             name[len] = '\0';
3415             strcat(name, ".SPR");
3416             Stream spr(name);
3417             name[len] = '\0';
3418             strcat(name, ".SND");
3419             Stream snd(name);
3420             name[len] = '\0';
3421             strcat(name, ".CIN");
3422 
3423             Stream *cin = NULL;
3424             if (Stream::existsContent(name)) {
3425                 cin = new Stream(name);
3426             } else {
3427                 len = strlen(name);
3428                 for (int i = int(len) - 1; i >= 0; i--)
3429                     if (name[i] == '/' || name[i] == '\\') {
3430                         char *newName = new char[len + 11 + 1];
3431                         name[i] = 0;
3432                         strcpy(newName, name);
3433                         strcat(newName, "/../CINDATA/");
3434                         strcat(newName, name + i + 1);
3435                         delete[] name;
3436                         name = newName;
3437                         break;
3438                     }
3439 
3440                 if (Stream::existsContent(name))
3441                     cin = new Stream(name);
3442             }
3443 
3444             delete[] name;
3445 
3446             readSAT(sad);
3447             readSAT(spr);
3448             readSAT(snd);
3449             if (cin) {
3450                 readCIN(*cin);
3451                 delete cin;
3452             }
3453             readSAT(stream); // sat
3454         }
3455 
loadTR2_PCLevel3456         void loadTR2_PC (Stream &stream) {
3457             stream.read(palette,   256);
3458             stream.read(palette32, 256);
3459             stream.read(tiles8, stream.read(tilesCount));
3460             stream.read(tiles16, tilesCount);
3461 
3462             readDataArrays(stream);
3463             readObjectTex(stream);
3464             readSpriteTex(stream);
3465             readCameras(stream);
3466             readSoundSources(stream);
3467             readBoxes(stream);
3468             readOverlaps(stream);
3469             readZones(stream);
3470             readAnimTex(stream);
3471             readEntities(stream);
3472             readLightMap(stream);
3473             readCameraFrames(stream);
3474             readDemoData(stream);
3475             readSoundMap(stream);
3476             readSoundOffsets(stream);
3477 
3478             new Stream(getGameSoundsFile(version), sfxLoadAsync, this);
3479         }
3480 
loadTR2_PSXLevel3481         void loadTR2_PSX (Stream &stream) {
3482             stream.read(soundOffsets, stream.read(soundOffsetsCount) + 1);
3483             soundSize = new uint32[soundOffsetsCount];
3484             soundDataSize = 0;
3485             for (int i = 0; i < soundOffsetsCount; i++) {
3486                 ASSERT(soundOffsets[i] < soundOffsets[i + 1]);
3487                 soundSize[i]    = soundOffsets[i + 1] - soundOffsets[i];
3488                 soundOffsets[i] = soundDataSize;
3489                 soundDataSize  += soundSize[i];
3490             }
3491             stream.read(soundData, soundDataSize);
3492 
3493             readDataArrays(stream);
3494 
3495             stream.read(tiles4, stream.read(tilesCount));
3496             stream.read(clutsCount);
3497             if (clutsCount > 1024) { // check for japanese version (read kanji CLUT index)
3498                 kanjiSprite = clutsCount & 0xFFFF;
3499                 stream.seek(-2);
3500                 stream.read(clutsCount);
3501             }
3502             stream.read(cluts, clutsCount);
3503             stream.seek(4);
3504             readObjectTex(stream);
3505             readSpriteTex(stream);
3506             readCameras(stream);
3507             readSoundSources(stream);
3508             readBoxes(stream);
3509             readOverlaps(stream);
3510             readZones(stream);
3511             readAnimTex(stream);
3512             readEntities(stream);
3513             stream.seek(4);
3514             readSoundMap(stream);
3515             stream.seek(4);
3516             readCameraFrames(stream);
3517         }
3518 
loadTR3_PCLevel3519         void loadTR3_PC (Stream &stream) {
3520             stream.read(palette,   256);
3521             stream.read(palette32, 256);
3522             stream.read(tiles8, stream.read(tilesCount));
3523             stream.read(tiles16, tilesCount);
3524 
3525             readDataArrays(stream);
3526             readSpriteTex(stream);
3527             readCameras(stream);
3528             readSoundSources(stream);
3529             readBoxes(stream);
3530             readOverlaps(stream);
3531             readZones(stream);
3532             readAnimTex(stream);
3533             readObjectTex(stream);
3534             readEntities(stream);
3535             readLightMap(stream);
3536             readCameraFrames(stream);
3537             readDemoData(stream);
3538             readSoundMap(stream);
3539             readSoundOffsets(stream);
3540             new Stream(getGameSoundsFile(version), sfxLoadAsync, this);
3541         }
3542 
loadTR3_PSXLevel3543         void loadTR3_PSX (Stream &stream) {
3544             readSoundOffsets(stream);
3545             if (soundOffsetsCount) {
3546                 readSoundData(stream);
3547                 soundSize = new uint32[soundOffsetsCount];
3548                 int size = 0;
3549                 for (int i = 0; i < soundOffsetsCount - 1; i++) {
3550                     ASSERT(soundOffsets[i] < soundOffsets[i + 1]);
3551                     size += soundSize[i] = soundOffsets[i + 1] - soundOffsets[i];
3552                 }
3553 
3554                 if (soundOffsetsCount) {
3555                     soundSize[soundOffsetsCount - 1] = soundDataSize;
3556                     if (soundOffsetsCount > 1) {
3557                         soundSize[soundOffsetsCount - 1] -= soundSize[soundOffsetsCount - 2];
3558                     }
3559                 }
3560             }
3561 
3562         // skip code modules
3563             int size;
3564             for (int i = 0; i < 13; i++) {
3565                 stream.read(size);
3566                 if (size) {
3567                     stream.seek(size);
3568                     stream.read(size);
3569                     stream.seek(size);
3570                 }
3571             }
3572 
3573             readDataArrays(stream);
3574 
3575             stream.read(tiles4, stream.read(tilesCount));
3576             stream.read(clutsCount);
3577             if (clutsCount > 1024) { // check for japanese version (read kanji CLUT index)
3578                 kanjiSprite = clutsCount & 0xFFFF;
3579                 stream.seek(-2);
3580                 stream.read(clutsCount);
3581             }
3582             clutsCount *= 2; // read underwater cluts too
3583             stream.read(cluts, clutsCount);
3584 
3585             readObjectTex(stream);
3586             readSpriteTex(stream);
3587             readCameras(stream);
3588             readSoundSources(stream);
3589             readBoxes(stream);
3590             readOverlaps(stream);
3591             readZones(stream);
3592             readAnimTex(stream);
3593             readEntities(stream);
3594 
3595             stream.read(skyColor);
3596 
3597             roomTexturesCount = stream.readLE32();
3598 
3599             if (roomTexturesCount) {
3600                 roomTextures = new TextureInfo[roomTexturesCount];
3601 
3602             // load room textures
3603                 for (int i = 0; i < roomTexturesCount; i++) {
3604                     readObjectTex(stream, roomTextures[i], TEX_TYPE_ROOM);
3605                     stream.seek(2 * 16); // skip 2 mipmap levels
3606                 }
3607             }
3608 
3609             readSoundMap(stream);
3610             stream.seek(4);
3611             readCameraFrames(stream);
3612         }
3613 
3614     #ifdef USE_INFLATE
loadTR4_PCLevel3615         void loadTR4_PC (Stream &stream) {
3616             uint16 roomTilesCount, objTilesCount, bumpTilesCount;
3617             uint32 sizeD, sizeC, sizeR;
3618             uint8  *dataC, *dataD;
3619 
3620             stream.read(roomTilesCount);
3621             stream.read(objTilesCount);
3622             stream.read(bumpTilesCount);
3623 
3624         // tiles32
3625             stream.read(sizeD);
3626             stream.read(dataC, stream.read(sizeC));
3627             ASSERT(sizeD == sizeof(Tile32) * (roomTilesCount + objTilesCount + bumpTilesCount));
3628             tiles32 = new Tile32[roomTilesCount + objTilesCount + bumpTilesCount];
3629             tinf_uncompress(tiles32, &sizeR, dataC + 2, 0);
3630             ASSERT(sizeD == sizeR);
3631             delete[] dataC;
3632 
3633         // tiles16
3634             stream.read(sizeD);
3635             stream.read(sizeC);
3636             stream.seek(sizeC); // skip compressed 16-bit tiles
3637 
3638         // tiles16
3639             stream.read(sizeD);
3640             stream.read(dataC, stream.read(sizeC));
3641             ASSERT(sizeD == sizeof(Tile32) * 2);
3642             tilesMisc = new Tile32[2];
3643             tinf_uncompress(tilesMisc, &sizeR, dataC + 2, 0);
3644             ASSERT(sizeD == sizeR);
3645             delete[] dataC;
3646 
3647             stream.read(sizeD);
3648             stream.read(dataC, stream.read(sizeC));
3649             dataD = new uint8[sizeD];
3650             tinf_uncompress(dataD, &sizeR, dataC + 2, 0);
3651             ASSERT(sizeD == sizeR);
3652             delete[] dataC;
3653 
3654             {
3655                 Stream stream(NULL, dataD, sizeD);
3656                 readDataArrays(stream);
3657                 stream.seek(3); // SPR
3658                 readSpriteTex(stream);
3659                 readCameras(stream);
3660                 readFlybyCameras(stream);
3661                 readSoundSources(stream);
3662                 readBoxes(stream);
3663                 readOverlaps(stream);
3664                 readZones(stream);
3665                 readAnimTex(stream);
3666                 stream.seek(3); // TEX
3667                 readObjectTex(stream);
3668                 readEntities(stream);
3669                 readAIObjects(stream);
3670                 readDemoData(stream);
3671                 readSoundMap(stream);
3672                 readSoundOffsets(stream);
3673             }
3674             delete[] dataD;
3675 
3676             stream.read(soundsCount);
3677             if (soundOffsetsCount <= 0 && soundsCount > 0) {
3678                 soundOffsetsCount = soundsCount;
3679                 soundOffsets = new uint32[soundOffsetsCount];
3680             }
3681             soundDataSize = stream.size - stream.pos;
3682             soundData = new uint8[soundDataSize];
3683             soundDataSize = 0;
3684             for (int i = 0; i < soundsCount; i++) {
3685                 stream.read(sizeD);
3686                 stream.read(sizeC);
3687                 soundOffsets[i] = soundDataSize;
3688                 stream.raw(soundData + soundDataSize, sizeC);
3689                 soundDataSize += sizeC;
3690             }
3691         }
3692     #endif
3693 
loadTR4_PSXLevel3694         void loadTR4_PSX (Stream &stream) {
3695 
3696         }
3697 
loadTR4_SDCLevel3698         void loadTR4_SDC (Stream &stream) {
3699 
3700         }
3701 
loadTR5_PCLevel3702         void loadTR5_PC (Stream &stream) {
3703 
3704         }
3705 
loadTR5_PSXLevel3706         void loadTR5_PSX (Stream &stream) {
3707 
3708         }
3709 
loadTR5_SDCLevel3710         void loadTR5_SDC (Stream &stream) {
3711 
3712         }
3713 
readDataArraysLevel3714         void readDataArrays(Stream &stream) {
3715             if (version != VER_TR3_PSX) {
3716                 stream.seek(4);
3717             }
3718 
3719             rooms = stream.read(roomsCount) ? new Room[roomsCount] : NULL;
3720             for (int i = 0; i < roomsCount; i++) {
3721                 readRoom(stream, i);
3722             }
3723 
3724             stream.read(floors, stream.read(floorsCount));
3725 
3726             if (version == VER_TR3_PSX) {
3727                 // outside room offsets
3728                 stream.seek(27 * 27 * 2);
3729                 // outside rooms table
3730                 int size;
3731                 stream.read(size);
3732                 stream.seek(size);
3733                 // room mesh bbox
3734                 stream.read(size);
3735                 stream.seek(8 * size);
3736             }
3737 
3738             stream.read(meshData,    stream.read(meshDataSize));
3739             stream.read(meshOffsets, stream.read(meshOffsetsCount));
3740 
3741             readAnims(stream);
3742 
3743             stream.read(states,      stream.read(statesCount));
3744             stream.read(ranges,      stream.read(rangesCount));
3745             stream.read(commands,    stream.read(commandsCount));
3746             stream.read(nodesData,   stream.read(nodesDataSize));
3747             stream.read(frameData,   stream.read(frameDataSize));
3748 
3749             readModels(stream);
3750 
3751             stream.read(staticMeshes, stream.read(staticMeshesCount));
3752         }
3753 
readAnimsLevel3754         void readAnims(Stream &stream) {
3755             stream.read(animsCount);
3756             anims = animsCount ? new Animation[animsCount] : NULL;
3757             for (int i = 0; i < animsCount; i++) {
3758                 Animation &anim = anims[i];
3759                 stream.read(anim.frameOffset);
3760                 stream.read(anim.frameRate);
3761                 stream.read(anim.frameSize);
3762                 stream.read(anim.state);
3763                 stream.read(anim.speed);
3764                 stream.read(anim.accel);
3765                 if (version & (VER_TR4 | VER_TR5)) {
3766                     stream.read(anim.speedLateral);
3767                     stream.read(anim.accelLateral);
3768                 } else {
3769                     anim.speedLateral.value = 0;
3770                     anim.accelLateral.value = 0;
3771                 }
3772                 stream.read(anim.frameStart);
3773                 stream.read(anim.frameEnd);
3774                 stream.read(anim.nextAnimation);
3775                 stream.read(anim.nextFrame);
3776                 stream.read(anim.scCount);
3777                 stream.read(anim.scOffset);
3778                 stream.read(anim.acCount);
3779                 stream.read(anim.animCommand);
3780             }
3781 
3782         }
3783 
readModelsLevel3784         void readModels(Stream &stream) {
3785             models = stream.read(modelsCount) ? new Model[modelsCount] : NULL;
3786             for (int i = 0; i < modelsCount; i++) {
3787                 Model &m = models[i];
3788                 uint16 type;
3789                 m.type = Entity::Type(stream.read(type));
3790                 stream.seek(sizeof(m.index));
3791                 m.index = i;
3792                 stream.read(m.mCount);
3793                 stream.read(m.mStart);
3794                 stream.read(m.node);
3795                 stream.read(m.frame);
3796                 stream.read(m.animation);
3797                 if (version & VER_PSX) {
3798                     stream.seek(2);
3799                 }
3800             }
3801         }
3802 
readCamerasLevel3803         void readCameras(Stream &stream) {
3804             stream.read(cameras, stream.read(camerasCount));
3805         }
3806 
readFlybyCamerasLevel3807         void readFlybyCameras(Stream &stream) {
3808             stream.read(flybyCameras, stream.read(flybyCamerasCount));
3809         }
3810 
readSoundSourcesLevel3811         void readSoundSources(Stream &stream) {
3812             stream.read(soundSources, stream.read(soundSourcesCount));
3813         }
3814 
readBoxesLevel3815         void readBoxes(Stream &stream) {
3816             boxes = stream.read(boxesCount) ? new Box[boxesCount] : NULL;
3817             for (int i = 0; i < boxesCount; i++) {
3818                 Box &b = boxes[i];
3819                 if (version & VER_TR1) {
3820                     stream.read(b.minZ);
3821                     stream.read(b.maxZ);
3822                     stream.read(b.minX);
3823                     stream.read(b.maxX);
3824                 }
3825 
3826                 if (version & (VER_TR2 | VER_TR3 | VER_TR4 | VER_TR5)) {
3827                     uint8 value;
3828                     b.minZ = stream.read(value) * 1024;
3829                     b.maxZ = stream.read(value) * 1024;
3830                     b.minX = stream.read(value) * 1024;
3831                     b.maxX = stream.read(value) * 1024;
3832                 }
3833 
3834                 stream.read(b.floor);
3835                 stream.read(b.overlap.value);
3836             }
3837         }
3838 
readOverlapsLevel3839         void readOverlaps(Stream &stream) {
3840             stream.read(overlaps, stream.read(overlapsCount));
3841         }
3842 
readZonesLevel3843         void readZones(Stream &stream) {
3844             for (int i = 0; i < 2; i++) {
3845                 stream.read(zones[i].ground1, boxesCount);
3846                 stream.read(zones[i].ground2, boxesCount);
3847                 if (!(version & VER_TR1)) {
3848                     stream.read(zones[i].ground3, boxesCount);
3849                     stream.read(zones[i].ground4, boxesCount);
3850                 } else {
3851                     zones[i].ground3 = NULL;
3852                     zones[i].ground4 = NULL;
3853                 }
3854                 stream.read(zones[i].fly, boxesCount);
3855             }
3856         }
3857 
readLightMapLevel3858         void readLightMap(Stream &stream) {
3859             stream.raw(lightmap, 32 * 256);
3860             for (int i = 0; i < 32; i++) {
3861                 lightmap[i * 256] = 0;
3862             }
3863         }
3864 
readCameraFramesLevel3865         void readCameraFrames(Stream &stream) {
3866             stream.read(cameraFrames, stream.read(cameraFramesCount));
3867         }
3868 
readAIObjectsLevel3869         void readAIObjects(Stream &stream) {
3870             stream.read(AIObjects, stream.read(AIObjectsCount));
3871         }
3872 
readDemoDataLevel3873         void readDemoData(Stream &stream) {
3874             stream.read(demoData, stream.read(demoDataSize));
3875         }
3876 
readSoundMapLevel3877         void readSoundMap(Stream &stream) {
3878             soundsCount = (version & VER_TR1) ? 256 : 370;
3879             stream.read(soundsMap, soundsCount);
3880             soundsInfo = (stream.read(soundsInfoCount) > 0) ? new SoundInfo[soundsInfoCount] : NULL;
3881             for (int i = 0; i < soundsInfoCount; i++) {
3882                 SoundInfo &s = soundsInfo[i];
3883 
3884                 stream.read(s.index);
3885                 if (version & (VER_TR1 | VER_TR2)) {
3886                     uint16 v;
3887                     stream.read(v); s.volume = float(v) / 0x7FFF;
3888                     stream.read(v); s.chance = float(v) / 0xFFFF;
3889                     s.range = 8 * 1024;
3890                     s.pitch = 0.2f;
3891                 } else {
3892                     uint8 v;
3893                     stream.read(v); s.volume = float(v) / 0xFF;
3894                     stream.read(v); s.range  = float(v) * 1024;
3895                     stream.read(v); s.chance = float(v) / 0xFF;
3896                     stream.read(v); s.pitch  = float(v) / 0xFF;
3897                 }
3898 
3899                 stream.read(s.flags.value);
3900 
3901                 ASSERT(s.volume <= 1.0f);
3902             }
3903         }
3904 
readSoundDataLevel3905         void readSoundData(Stream &stream) {
3906             stream.read(soundDataSize) > 0 ? stream.read(soundData, soundDataSize) : NULL;
3907         }
3908 
readSoundOffsetsLevel3909         void readSoundOffsets(Stream &stream) {
3910             stream.read(soundOffsetsCount) > 0 ? stream.read(soundOffsets, soundOffsetsCount) : NULL;
3911         }
3912 
3913         #define CHUNK(str) ((uint64)((const char*)(str))[0]        | ((uint64)((const char*)(str))[1] << 8)  | ((uint64)((const char*)(str))[2] << 16) | ((uint64)((const char*)(str))[3] << 24) | \
3914                            ((uint64)((const char*)(str))[4] << 32) | ((uint64)((const char*)(str))[5] << 40) | ((uint64)((const char*)(str))[6] << 48) | ((uint64)((const char*)(str))[7] << 56))
3915 
3916         #define SAT_ROOMFILE 0x454C49464D4F4F52ULL  /* CHUNK("ROOMFILE") */
3917         #define SAT_ROOMTINF 0x464E49544D4F4F52ULL  /* CHUNK("ROOMTINF") */
3918         #define SAT_ROOMTQTR 0x525451544D4F4F52ULL  /* CHUNK("ROOMTQTR") */
3919         #define SAT_ROOMTSUB 0x425553544D4F4F52ULL  /* CHUNK("ROOMTSUB") */
3920         #define SAT_ROOMTPAL 0x4C4150544D4F4F52ULL  /* CHUNK("ROOMTPAL") */
3921         #define SAT_ROOMSPAL 0x4C4150534D4F4F52ULL  /* CHUNK("ROOMSPAL") */
3922         #define SAT_ROOMDATA 0x415441444D4F4F52ULL  /* CHUNK("ROOMDATA") */
3923         #define SAT_ROOMNUMB 0x424D554E4D4F4F52ULL  /* CHUNK("ROOMNUMB") */
3924         #define SAT_MESHPOS_ 0x20534F504853454DULL  /* CHUNK("MESHPOS ") */
3925         #define SAT_MESHSIZE 0x455A49534853454DULL  /* CHUNK("MESHSIZE") */
3926         #define SAT_DOORDATA 0x41544144524F4F44ULL  /* CHUNK("DOORDATA") */
3927         #define SAT_FLOORDAT 0x544144524F4F4C46ULL  /* CHUNK("FLOORDAT") */
3928         #define SAT_FLOORSIZ 0x5A4953524F4F4C46ULL  /* CHUNK("FLOORSIZ") */
3929         #define SAT_FLORDATA 0x41544144524F4C46ULL  /* CHUNK("FLORDATA") */
3930         #define SAT_LIGHTAMB 0x424D41544847494CULL  /* CHUNK("LIGHTAMB") */
3931         #define SAT_RM_FLIP_ 0x2050494C465F4D52ULL  /* CHUNK("RM_FLIP ") */
3932         #define SAT_RM_FLAGS 0x5347414C465F4D52ULL  /* CHUNK("RM_FLAGS") */
3933         #define SAT_LIGHTSIZ 0x5A4953544847494CULL  /* CHUNK("LIGHTSIZ") */
3934         #define SAT_CAMERAS_ 0x20534152454D4143ULL  /* CHUNK("CAMERAS ") */
3935         #define SAT_SOUNDFX_ 0x205846444E554F53ULL  /* CHUNK("SOUNDFX ") */
3936         #define SAT_BOXES___ 0x2020205345584F42ULL  /* CHUNK("BOXES   ") */
3937         #define SAT_OVERLAPS 0x5350414C5245564FULL  /* CHUNK("OVERLAPS") */
3938         #define SAT_GND_ZONE 0x454E4F5A5F444E47ULL  /* CHUNK("GND_ZONE") */
3939         #define SAT_GND_ZON2 0x324E4F5A5F444E47ULL  /* CHUNK("GND_ZON2") */
3940         #define SAT_FLY_ZONE 0x454E4F5A5F594C46ULL  /* CHUNK("FLY_ZONE") */
3941         #define SAT_ARANGES_ 0x205345474E415241ULL  /* CHUNK("ARANGES ") */
3942         #define SAT_ITEMDATA 0x415441444D455449ULL  /* CHUNK("ITEMDATA") */
3943         #define SAT_ROOMEND_ 0x20444E454D4F4F52ULL  /* CHUNK("ROOMEND ") */
3944         #define SAD_OBJFILE_ 0x20454C49464A424FULL  /* CHUNK("OBJFILE ") */
3945         #define SAD_ANIMS___ 0x202020534D494E41ULL  /* CHUNK("ANIMS   ") */
3946         #define SAD_CHANGES_ 0x205345474E414843ULL  /* CHUNK("CHANGES ") */
3947         #define SAD_RANGES_z 0x00205345474E4152ULL  /* CHUNK("RANGES \0") */
3948         #define SAD_COMMANDS 0x53444E414D4D4F43ULL  /* CHUNK("COMMANDS") */
3949         #define SAD_ANIBONES 0x53454E4F42494E41ULL  /* CHUNK("ANIBONES") */
3950         #define SAD_ANIMOBJ_ 0x204A424F4D494E41ULL  /* CHUNK("ANIMOBJ ") */
3951         #define SAD_STATOBJ_ 0x204A424F54415453ULL  /* CHUNK("STATOBJ ") */
3952         #define SAD_FRAMES__ 0x202053454D415246ULL  /* CHUNK("FRAMES  ") */
3953         #define SAD_MESHPTRS 0x535254504853454DULL  /* CHUNK("MESHPTRS") */
3954         #define SAD_MESHDATA 0x415441444853454DULL  /* CHUNK("MESHDATA") */
3955         #define SAD_OTEXTINF 0x464E49545845544FULL  /* CHUNK("OTEXTINF") */
3956         #define SAD_OTEXTDAT 0x544144545845544FULL  /* CHUNK("OTEXTDAT") */
3957         #define SAD_ITEXTINF 0x464E495458455449ULL  /* CHUNK("ITEXTINF") */
3958         #define SAD_ITEXTDAT 0x5441445458455449ULL  /* CHUNK("ITEXTDAT") */
3959         #define SAD_OBJEND__ 0x2020444E454A424FULL  /* CHUNK("OBJEND  ") */
3960         #define SPR_SPRFILE_ 0x20454C4946525053ULL  /* CHUNK("SPRFILE ") */
3961         #define SPR_SPRITINF 0x464E495449525053ULL  /* CHUNK("SPRITINF") */
3962         #define SPR_SPRITDAT 0x5441445449525053ULL  /* CHUNK("SPRITDAT") */
3963         #define SPR_OBJECTS_ 0x20535443454A424FULL  /* CHUNK("OBJECTS ") */
3964         #define SPR_SPRITEND 0x444E455449525053ULL  /* CHUNK("SPRITEND") */
3965         #define SND_SAMPLUT_ 0x2054554C504D4153ULL  /* CHUNK("SAMPLUT ") */
3966         #define SND_SAMPINFS 0x53464E49504D4153ULL  /* CHUNK("SAMPINFS") */
3967         #define SND_SAMPLE__ 0x2020454C504D4153ULL  /* CHUNK("SAMPLE  ") */
3968         #define SND_ENDFILEz 0x00454C4946444E45ULL  /* CHUNK("ENDFILE\0") */
3969 
readSATLevel3970         void readSAT(Stream &stream) {
3971         #if !defined(_OS_PSP)
3972             Room *room = NULL;
3973 
3974             while (stream.pos < stream.size) {
3975                 uint64 chunkType = stream.read64();
3976                 /*
3977                 {
3978                         char buf[9];
3979                         memcpy(buf, &chunkType, 8);
3980                         buf[8] = 0;
3981                         LOG("chunk: \"%s\"\n", buf);
3982                 }
3983                 */
3984 
3985                 switch (chunkType) {
3986                 // SAT
3987                     case SAT_ROOMFILE :
3988                         ASSERTV(stream.readBE32() == 0x00000000);
3989                         ASSERTV(stream.readBE32() == 0x00000020);
3990                         break;
3991                     case SAT_ROOMTINF :
3992                         ASSERTV(stream.readBE32() == 0x00000010);
3993                         roomTexturesCount = stream.readBE32();
3994                         roomTextures = roomTexturesCount ? new TextureInfo[roomTexturesCount] : NULL;
3995                         for (int i = 0; i < roomTexturesCount; i++)
3996                             readObjectTex(stream, roomTextures[i], TEX_TYPE_ROOM);
3997                         break;
3998                     case SAT_ROOMTQTR : {
3999                         ASSERTV(stream.readBE32() == 0x00000001);
4000                         roomTexturesDataSize = stream.readBE32();
4001                         roomTexturesData = roomTexturesDataSize ? new uint8[roomTexturesDataSize] : NULL;
4002                         stream.raw(roomTexturesData, roomTexturesDataSize);
4003 /*
4004                         int32 count = stream.readBE32();
4005                         stream.seek(count);
4006                     */
4007                         break;
4008                     }
4009                     case SAT_ROOMTSUB :
4010                         ASSERTV(stream.readBE32() == 0x00000001);
4011                         /*
4012                         roomTexturesDataSize = stream.readBE32();
4013                         roomTexturesData = roomTexturesDataSize ? new uint8[roomTexturesDataSize] : NULL;
4014                         stream.raw(roomTexturesData, roomTexturesDataSize);
4015                         */
4016 
4017                         tsubCount = stream.readBE32();
4018                         tsub = new uint8[tsubCount];
4019                         stream.raw(tsub, sizeof(uint8) * tsubCount);
4020 
4021                         break;
4022                     case SAT_ROOMTPAL : {
4023                         ASSERTV(stream.readBE32() == 0x00000003);
4024                         stream.seek(stream.readBE32() * 3);
4025                         break;
4026                     }
4027                     case SAT_ROOMSPAL : {
4028                         ASSERTV(stream.readLE32() == 0x02000000);
4029                         stream.seek(stream.readBE32() * 2);
4030                         break;
4031                     }
4032                     case SAT_ROOMDATA :
4033                         ASSERTV(stream.readBE32() == 0x00000044);
4034                         roomsCount = stream.readBE32();
4035                         rooms = new Room[roomsCount];
4036                         memset(rooms, 0, sizeof(Room) * roomsCount);
4037                         break;
4038                     case SAT_ROOMNUMB :
4039                         ASSERTV(stream.readBE32() == 0x00000000);
4040                         room = &rooms[stream.readBE32()];
4041                         break;
4042                     case SAT_MESHPOS_ :
4043                         ASSERT(room);
4044                         room->info.x       = stream.readBE32();
4045                         room->info.z       = stream.readBE32();
4046                         room->info.yBottom = stream.readBE32();
4047                         room->info.yTop    = stream.readBE32();
4048                         break;
4049                     case SAT_MESHSIZE : {
4050                         ASSERT(room);
4051                         uint32 flag = stream.readBE32();
4052                         if (flag == 0x00000014) {
4053                             room->meshesCount = stream.readBE32();
4054 
4055                             room->meshes = room->meshesCount ? new Room::Mesh[room->meshesCount] : NULL;
4056                             for (int i = 0; i < room->meshesCount; i++) {
4057                                 Room::Mesh &m = room->meshes[i];
4058                                 m.x = stream.readBE32();
4059                                 m.y = stream.readBE32();
4060                                 m.z = stream.readBE32();
4061                                 m.rotation.value = stream.readBE16();
4062                                 uint16 intensity = stream.readBE16();
4063                                 stream.readBE16();
4064                                 int value = clamp((intensity > 0x1FFF) ? 255 : (255 - (intensity >> 5)), 0, 255);
4065                                 m.color.r = m.color.g = m.color.b = value;
4066                                 m.color.a = 0;
4067                                 m.meshID = stream.readBE16();
4068                             }
4069 
4070                             //stream.seek(20 * count); // unknown
4071                             break;
4072                         }
4073                         ASSERT(flag == 0x00000002);
4074 
4075                         Room::Data &data = room->data;
4076 
4077                         data.size = stream.readBE32();
4078                         data.vCount = stream.readBE16();
4079                         data.vertices = new Room::Data::Vertex[data.vCount];
4080                         for (int j = 0; j < data.vCount; j++) {
4081                             Room::Data::Vertex &v = data.vertices[j];
4082                             v.pos.x      = stream.readBE16();
4083                             v.pos.y      = stream.readBE16();
4084                             v.pos.z      = stream.readBE16();
4085                             v.color      = Color16(stream.readBE16());
4086                             v.attributes = 0;
4087                         }
4088 
4089                         data.fCount  = stream.readBE16();
4090                         data.faces   = new Face[data.fCount];
4091                         data.sprites = new Room::Data::Sprite[data.fCount];
4092 
4093                         enum {
4094                             TYPE_R_TRANSP    = 33,
4095                             TYPE_T_INVISIBLE = 34,
4096                             TYPE_R_INVISIBLE = 35,
4097                             TYPE_T_SOLID     = 36,
4098                             TYPE_R_SOLID     = 37,
4099                             TYPE_SPRITE      = 39,
4100                         };
4101 
4102                         int fIndex = 0;
4103 
4104                         uint16 typesCount = stream.readBE16();
4105                         for (int j = 0; j < typesCount; j++) {
4106                             uint16 type  = stream.readBE16();
4107                             uint16 count = stream.readBE16();
4108                             //LOG(" type:%d count:%d\n", (int)type, (int)count);
4109                             for (int k = 0; k < count; k++) {
4110                                 ASSERT(fIndex < data.fCount);
4111 
4112                                 Face &f = data.faces[fIndex++];
4113                                 switch (type) {
4114                                     case TYPE_SPRITE       : {
4115                                         Room::Data::Sprite &sprite = data.sprites[data.sCount++];
4116                                         sprite.vertexIndex = (stream.readBE16() >> 4);
4117                                         sprite.texture     = (stream.readBE16() >> 4);
4118                                         fIndex--;
4119                                         break;
4120                                     }
4121                                     case TYPE_T_INVISIBLE  :
4122                                     case TYPE_T_SOLID      :
4123                                         f.triangle    = true;
4124                                         f.vertices[0] = (stream.readBE16() >> 4);
4125                                         f.vertices[1] = (stream.readBE16() >> 4);
4126                                         f.vertices[2] = (stream.readBE16() >> 4);
4127                                         f.vertices[3] = 0;
4128                                         ASSERT(f.vertices[0] < data.vCount && f.vertices[1] < data.vCount && f.vertices[2] < data.vCount);
4129                                         f.flags.value = stream.readBE16();
4130                                         if (type == TYPE_T_INVISIBLE) {
4131                                             fIndex--;
4132                                             continue;
4133                                         }
4134                                         data.tCount++;
4135                                         break;
4136                                     case TYPE_R_INVISIBLE  :
4137                                     case TYPE_R_TRANSP     :
4138                                     case TYPE_R_SOLID      :
4139                                         f.vertices[0] = (stream.readBE16() >> 4);
4140                                         f.vertices[1] = (stream.readBE16() >> 4);
4141                                         f.vertices[2] = (stream.readBE16() >> 4);
4142                                         f.vertices[3] = (stream.readBE16() >> 4);
4143                                         ASSERT(f.vertices[0] < data.vCount && f.vertices[1] < data.vCount && f.vertices[2] < data.vCount && f.vertices[3] < data.vCount);
4144                                         f.flags.value = stream.readBE16();
4145                                         if (type == TYPE_R_INVISIBLE) {
4146                                             fIndex--;
4147                                             continue;
4148                                         }
4149                                         data.rCount++;
4150                                         break;
4151                                     default :
4152                                         LOG("! unknown face type: %d\n", type);
4153                                         ASSERT(false);
4154                                 }
4155 
4156                                 if (type != TYPE_SPRITE) {
4157                                     ASSERT(f.flags.value % 16 == 0);
4158                                     ASSERT(f.flags.value / 16 < roomTexturesCount);
4159                                     f.flags.value /= 16;
4160                                 }
4161 
4162                                 if (type == TYPE_R_TRANSP) {
4163                                     roomTextures[f.flags.texture].attribute = 1;
4164                                 }
4165                             }
4166                         }
4167                         data.fCount = fIndex;
4168                         break;
4169                     }
4170                     case SAT_DOORDATA : {
4171                         int32 roomIndex = stream.readBE32();
4172                         ASSERT(roomIndex < roomsCount);
4173                         Room *room = &rooms[roomIndex];
4174                         ASSERT(room && room->sectors == NULL);
4175 
4176                         room->portalsCount = stream.readBE32();
4177                         room->portals = new Room::Portal[room->portalsCount];
4178 
4179                         for (int j = 0; j < room->portalsCount; j++) {
4180                             Room::Portal &p = room->portals[j];
4181                             p.roomIndex = stream.readBE16();
4182                             p.normal.x  = stream.readBE16();
4183                             p.normal.y  = stream.readBE16();
4184                             p.normal.z  = stream.readBE16();
4185                             for (int k = 0; k < 4; k++) {
4186                                 p.vertices[k].x = stream.readBE16();
4187                                 p.vertices[k].y = stream.readBE16();
4188                                 p.vertices[k].z = stream.readBE16();
4189                             }
4190                         }
4191                         break;
4192                     }
4193                     case SAT_FLOORDAT :
4194                         ASSERT(room);
4195                         room->zSectors = stream.readBE32();
4196                         room->xSectors = stream.readBE32();
4197                         break;
4198                     case SAT_FLOORSIZ : {
4199                         ASSERTV(stream.readBE32() == 0x00000008);
4200                         ASSERT(room && room->sectors == NULL);
4201 
4202                         int32 count = stream.readBE32();
4203                         ASSERT(count == room->xSectors * room->zSectors);
4204 
4205                         room->sectors = count ? new Room::Sector[count] : NULL;
4206 
4207                         for (int i = 0; i < count; i++) {
4208                             Room::Sector &s = room->sectors[i];
4209                             s.material   = 0;
4210                             s.floorIndex = stream.readBE16();
4211                             s.boxIndex   = stream.readBE16();
4212                             stream.read(s.roomBelow);
4213                             stream.read(s.floor);
4214                             stream.read(s.roomAbove);
4215                             stream.read(s.ceiling);
4216                         }
4217                         break;
4218                     }
4219                     case SAT_FLORDATA :
4220                         ASSERTV(stream.readBE32() == 0x00000002);
4221                         ASSERT(floors == NULL);
4222                         floorsCount = stream.readBE32();
4223                         floors = new FloorData[floorsCount];
4224                         for (int i = 0; i < floorsCount; i++)
4225                             floors[i].value = stream.readBE16();
4226                         break;
4227                     case SAT_LIGHTAMB :
4228                         ASSERT(room);
4229                         room->ambient  = stream.readBE32();
4230                         room->ambient2 = stream.readBE32();
4231                         break;
4232                     case SAT_RM_FLIP_ : {
4233                         ASSERTV(stream.readBE32() == 0x00000002);
4234                         uint32 value = stream.readBE32();
4235                         room->alternateRoom = value == 0xFFFFFFFF ? -1 : value;
4236                         break;
4237                     }
4238                     case SAT_RM_FLAGS : {
4239                         ASSERT(room);
4240                         ASSERTV(stream.readBE32() == 0x00000002);
4241                         uint32 value = stream.readBE32();
4242                         room->flags.water = (value & 0x01) != 0;
4243                         break;
4244                     }
4245                     case SAT_LIGHTSIZ : {
4246                         ASSERTV(stream.readBE32() == 0x00000014);
4247                         ASSERT(room && room->lights == NULL);
4248                         room->lightsCount = stream.readBE32();
4249                         room->lights = room->lightsCount ? new Room::Light[room->lightsCount] : NULL;
4250                         for (int i = 0; i < room->lightsCount; i++) {
4251                             Room::Light &light = room->lights[i];
4252                             light.x = stream.readBE32();
4253                             light.y = stream.readBE32();
4254                             light.z = stream.readBE32();
4255 
4256                             int16 intensity  = stream.readBE16();
4257                             int16 intensity2 = stream.readBE16();
4258                             ASSERTV(intensity == intensity2);
4259                             int value = clamp((intensity > 0x1FFF) ? 0 : (intensity >> 5), 0, 255);
4260                             light.color.r = light.color.g = light.color.b = value;
4261                             light.intensity = intensity;
4262 
4263                             light.radius = stream.readBE32() * 2;
4264                         }
4265                         break;
4266                     }
4267                     case SAT_CAMERAS_ :
4268                         ASSERTV(stream.readBE32() == 0x00000010);
4269                         ASSERT(cameras == NULL);
4270                         camerasCount = stream.readBE32();
4271                         cameras = camerasCount ? new Camera[camerasCount] : NULL;
4272                         for (int i = 0; i < camerasCount; i++) {
4273                             Camera &cam = cameras[i];
4274                             cam.x = stream.readBE32();
4275                             cam.y = stream.readBE32();
4276                             cam.z = stream.readBE32();
4277                             cam.room = stream.readBE16();
4278                             cam.flags.boxIndex = stream.readBE16();
4279                         }
4280                         break;
4281                     case SAT_SOUNDFX_ : {
4282                         uint32 flag = stream.readBE32();
4283                         if (flag == 0x00000000) { // SND
4284                             ASSERTV(stream.readBE32() == 0x00000000);
4285 
4286                             int pos = stream.pos;
4287                             stream.setPos(0);
4288                             soundDataSize = stream.size;
4289                             soundData = new uint8[soundDataSize];
4290                             stream.raw(soundData, soundDataSize);
4291                             soundOffsetsCount = 256;
4292                             soundOffsets = new uint32[soundOffsetsCount];
4293                             soundSize    = new uint32[soundOffsetsCount];
4294                             memset(soundOffsets, 0, soundOffsetsCount * sizeof(uint32));
4295                             memset(soundSize,    0, soundOffsetsCount * sizeof(uint32));
4296                             stream.setPos(pos);
4297 
4298                             break;
4299                         }
4300                         ASSERT(flag == 0x00000010); // SAT
4301 
4302                         ASSERT(soundSources == NULL);
4303                         soundSourcesCount = stream.readBE32();
4304                         soundSources = soundSourcesCount ? new SoundSource[soundSourcesCount] : NULL;
4305                         for (int i = 0; i < soundSourcesCount; i++) {
4306                             SoundSource &s = soundSources[i];
4307                             s.x     = stream.readBE32();
4308                             s.y     = stream.readBE32();
4309                             s.z     = stream.readBE32();
4310                             s.id    = stream.readBE16();
4311                             s.flags = stream.readBE16();
4312                         }
4313                         break;
4314                     }
4315                     case SAT_BOXES___ :
4316                         ASSERTV(stream.readBE32() == 0x00000014);
4317                         ASSERT(boxes == NULL);
4318                         boxesCount = stream.readBE32();
4319                         boxes = boxesCount ? new Box[boxesCount] : NULL;
4320                         for (int i = 0; i < boxesCount; i++) {
4321                             Box &b = boxes[i];
4322                             b.minZ          = stream.readBE32();
4323                             b.maxZ          = stream.readBE32();
4324                             b.minX          = stream.readBE32();
4325                             b.maxX          = stream.readBE32();
4326                             b.floor         = stream.readBE16();
4327                             b.overlap.value = stream.readBE16();
4328                         }
4329                         break;
4330                     case SAT_OVERLAPS :
4331                         ASSERTV(stream.readBE32() == 0x00000002);
4332                         ASSERT(overlaps == NULL);
4333                         overlapsCount = stream.readBE32();
4334                         overlaps = overlapsCount ? new Overlap[overlapsCount] : NULL;
4335                         for (int i = 0; i < overlapsCount; i++)
4336                             overlaps[i].value = stream.readBE16();
4337                         break;
4338                     case SAT_GND_ZONE :
4339                     case SAT_GND_ZON2 :
4340                     case SAT_FLY_ZONE : {
4341                         ASSERTV(stream.readBE32() == 0x00000002);
4342                         uint16 **ptr;
4343 
4344                         switch (chunkType) {
4345                             case SAT_GND_ZONE : ptr = zones[0].ground1 ? &zones[1].ground1 : &zones[0].ground1; break;
4346                             case SAT_GND_ZON2 : ptr = zones[0].ground2 ? &zones[1].ground2 : &zones[0].ground2; break;
4347                             case SAT_FLY_ZONE : ptr = zones[0].fly     ? &zones[1].fly     : &zones[0].fly;     break;
4348                             default                : ptr = NULL;
4349                         }
4350 
4351                         ASSERT(ptr != NULL);
4352                         ASSERT(*ptr == NULL);
4353 
4354                         int32 count = stream.readBE32();
4355                         *ptr = count ? new uint16[count] : NULL;
4356                         for (int i = 0; i < count; i++)
4357                             (*ptr)[i] = stream.readBE16();
4358                         break;
4359                     }
4360                     case SAT_ARANGES_ : {
4361                         ASSERTV(stream.readBE32() == 0x00000008);
4362                         animTexturesCount = stream.readBE32();
4363                         animTextures = new AnimTexture[animTexturesCount];
4364                         for (int i = 0; i < animTexturesCount; i++) {
4365                             AnimTexture &animTex = animTextures[i];
4366                             uint32 first = stream.readBE32();
4367                             uint32 last  = stream.readBE32();
4368                             animTex.count    = last - first + 1;
4369                             animTex.textures = new uint16[animTex.count];
4370                             for (int j = 0; j < animTex.count; j++)
4371                                 animTex.textures[j] = first + j;
4372                         }
4373                         break;
4374                     }
4375                     case SAT_ITEMDATA : {
4376                         ASSERTV(stream.readBE32() == 0x00000014);
4377                         entitiesBaseCount = stream.readBE32();
4378                         entitiesCount = entitiesBaseCount + MAX_RESERVED_ENTITIES;
4379                         entities = new Entity[entitiesCount];
4380                         for (int i = 0; i < entitiesBaseCount; i++) {
4381                             Entity &e = entities[i];
4382                             e.type = Entity::Type(stream.readBE16());
4383                             e.room = stream.readBE16();
4384                             e.x    = stream.readBE32();
4385                             e.y    = stream.readBE32();
4386                             e.z    = stream.readBE32();
4387                             e.rotation.value = stream.readBE16();
4388                             e.intensity      = stream.readBE16();
4389                             e.intensity2     = stream.readBE16();
4390                             e.flags.value    = stream.readBE16();
4391                         }
4392                         break;
4393                     }
4394                     case SAT_ROOMEND_ :
4395                         ASSERTV(stream.readBE32() == 0x00000000);
4396                         ASSERTV(stream.readBE32() == 0x00000000);
4397                         break;
4398                 // SAD
4399                     case SAD_OBJFILE_ :
4400                         ASSERTV(stream.readBE32() == 0x00000000);
4401                         ASSERTV(stream.readBE32() == 0x00000020);
4402                         break;
4403                     case SAD_ANIMS___ :
4404                         ASSERTV(stream.readBE32() == 0x00000022);
4405                         ASSERT(anims == NULL);
4406                         animsCount = stream.readBE32();
4407                         anims = animsCount ? new Animation[animsCount] : NULL;
4408                         for (int i = 0; i < animsCount; i++) {
4409                             Animation &anim = anims[i];
4410                             anim.frameOffset   = stream.readBE32();
4411                             anim.frameSize     = stream.read();
4412                             anim.frameRate     = stream.read();
4413                             anim.state         = stream.readBE16();
4414                             anim.speed.H       = stream.readBE16();
4415                             anim.speed.L       = stream.readBE16();
4416                             anim.accel.H       = stream.readBE16();
4417                             anim.accel.L       = stream.readBE16();
4418                             anim.frameStart    = stream.readBE16();
4419                             anim.frameEnd      = stream.readBE16();
4420                             anim.nextAnimation = stream.readBE16();
4421                             anim.nextFrame     = stream.readBE16();
4422                             anim.scCount       = stream.readBE16();
4423                             anim.scOffset      = stream.readBE16();
4424                             anim.acCount       = stream.readBE16();
4425                             anim.animCommand   = stream.readBE16();
4426                         }
4427                         break;
4428                     case SAD_CHANGES_ :
4429                         ASSERTV(stream.readBE32() == 0x00000008);
4430                         ASSERT(states == NULL);
4431                         statesCount = stream.readBE32();
4432                         states = statesCount ? new AnimState[statesCount] : NULL;
4433                         for (int i = 0; i < statesCount; i++) {
4434                             AnimState &state = states[i];
4435                             state.state         = stream.readBE16();
4436                             state.rangesCount   = stream.readBE16();
4437                             state.rangesOffset  = stream.readBE16();
4438                             ASSERTV(stream.readBE16() == state.rangesOffset); // dummy
4439                         }
4440                         break;
4441                     case SAD_RANGES_z :
4442                         ASSERTV(stream.readBE32() == 0x00000008);
4443                         ASSERT(ranges == NULL);
4444                         rangesCount = stream.readBE32();
4445                         ranges = rangesCount ? new AnimRange[rangesCount] : NULL;
4446                         for (int i = 0; i < rangesCount; i++) {
4447                             AnimRange &range = ranges[i];
4448                             range.low           = stream.readBE16();
4449                             range.high          = stream.readBE16();
4450                             range.nextAnimation = stream.readBE16();
4451                             range.nextFrame     = stream.readBE16();
4452                         }
4453                         break;
4454                     case SAD_COMMANDS :
4455                         ASSERTV(stream.readBE32() == 0x00000002);
4456                         ASSERT(commands == NULL);
4457                         commandsCount = stream.readBE32();
4458                         commands = commandsCount ? new int16[commandsCount] : NULL;
4459                         for (int i = 0; i < commandsCount; i++)
4460                             commands[i] = stream.readBE16();
4461                         break;
4462                     case SAD_ANIBONES :
4463                         ASSERTV(stream.readBE32() == 0x00000004);
4464                         ASSERT(nodesData == NULL);
4465                         nodesDataSize = stream.readBE32();
4466                         nodesData = nodesDataSize ? new uint32[nodesDataSize] : NULL;
4467                         for (int i = 0; i < nodesDataSize; i++)
4468                             nodesData[i] = stream.readBE32();
4469                         break;
4470                     case SAD_ANIMOBJ_ :
4471                         ASSERTV(stream.readBE32() == 0x00000038);
4472                         ASSERT(models == NULL);
4473                         modelsCount = stream.readBE32();
4474                         models = modelsCount ? new Model[modelsCount] : NULL;
4475                         for (int i = 0; i < modelsCount; i++) {
4476                             Model &model = models[i];
4477                             ASSERTV(stream.readBE16() == 0x0000);
4478                             model.index     = i;
4479                             model.type      = Entity::Type(stream.readBE16());
4480                             model.mCount    = stream.readBE16();
4481                             model.mStart    = stream.readBE16();
4482                             model.node      = stream.readBE32();
4483                             model.frame     = stream.readBE32();
4484                             model.animation = stream.readBE16();
4485                             ASSERTV(stream.readBE16() == model.animation);
4486                         }
4487                         break;
4488                     case SAD_STATOBJ_ :
4489                         ASSERTV(stream.readBE32() == 0x00000020);
4490                         ASSERT(staticMeshes == NULL);
4491                         staticMeshesCount = stream.readBE32();
4492                         staticMeshes = staticMeshesCount ? new StaticMesh[staticMeshesCount] : NULL;
4493                         for (int i = 0; i < staticMeshesCount; i++) {
4494                             StaticMesh &mesh = staticMeshes[i];
4495                             mesh.id        = stream.readBE32();
4496                             mesh.mesh      = stream.readBE16();
4497                             mesh.vbox.minX = stream.readBE16();
4498                             mesh.vbox.maxX = stream.readBE16();
4499                             mesh.vbox.minY = stream.readBE16();
4500                             mesh.vbox.maxY = stream.readBE16();
4501                             mesh.vbox.minZ = stream.readBE16();
4502                             mesh.vbox.maxZ = stream.readBE16();
4503                             mesh.cbox.minX = stream.readBE16();
4504                             mesh.cbox.maxX = stream.readBE16();
4505                             mesh.cbox.minY = stream.readBE16();
4506                             mesh.cbox.maxY = stream.readBE16();
4507                             mesh.cbox.minZ = stream.readBE16();
4508                             mesh.cbox.maxZ = stream.readBE16();
4509                             mesh.flags     = stream.readBE16();
4510                         }
4511                         break;
4512                     case SAD_FRAMES__ :
4513                         ASSERTV(stream.readBE32() == 0x00000002);
4514                         ASSERT(frameData == NULL);
4515                         frameDataSize = stream.readBE32();
4516                         frameData = frameDataSize ? new uint16[frameDataSize] : NULL;
4517                         for (int i = 0; i < frameDataSize; i++)
4518                             frameData[i] = stream.readBE16();
4519                         break;
4520                     case SAD_MESHPTRS :
4521                         ASSERTV(stream.readBE32() == 0x00000004);
4522                         ASSERT(meshOffsets == NULL);
4523                         meshOffsetsCount = stream.readBE32();
4524                         meshOffsets = meshOffsetsCount ? new int32[meshOffsetsCount] : NULL;
4525                         for (int i = 0; i < meshOffsetsCount; i++)
4526                             meshOffsets[i] = stream.readBE32();
4527                         break;
4528                     case SAD_MESHDATA :
4529                         ASSERTV(stream.readBE32() == 0x00000002);
4530                         ASSERT(meshData == NULL);
4531                         meshDataSize = stream.readBE32();
4532                         meshData = meshDataSize ? new uint16[meshDataSize] : NULL;
4533                         stream.raw(meshData, sizeof(uint16) * meshDataSize);
4534                         break;
4535                     case SAD_OTEXTINF :
4536                         ASSERTV(stream.readBE32() == 0x00000010);
4537                         ASSERT(objectTextures == NULL);
4538                         objectTexturesCount = stream.readBE32();
4539                         objectTextures = objectTexturesCount ? new TextureInfo[objectTexturesCount * 5] : NULL;
4540                         for (int i = 0; i < objectTexturesCount; i++)
4541                             readObjectTex(stream, objectTextures[i], TEX_TYPE_OBJECT);
4542                         objectTexturesBaseCount = objectTexturesCount;
4543                         expandObjectTex(objectTextures, objectTexturesCount);
4544                         break;
4545                     case SAD_OTEXTDAT : {
4546                         ASSERTV(stream.readBE32() == 0x00000001);
4547                         objectTexturesDataSize = stream.readBE32();
4548                         objectTexturesData = objectTexturesDataSize ? new uint8[objectTexturesDataSize] : NULL;
4549                         stream.raw(objectTexturesData, objectTexturesDataSize);
4550                         break;
4551                     }
4552                     case SAD_ITEXTINF : {
4553                         ASSERTV(stream.readBE32() == 0x00000014);
4554                         itemTexturesCount = stream.readBE32();
4555                         itemTextures = itemTexturesCount ? new TextureInfo[itemTexturesCount * 5] : NULL;
4556                         for (int i = 0; i < itemTexturesCount; i++)
4557                             readObjectTex(stream, itemTextures[i], TEX_TYPE_ITEM);
4558                         itemTexturesBaseCount = itemTexturesCount;
4559                         expandObjectTex(itemTextures, itemTexturesCount);
4560                         break;
4561                     }
4562                     case SAD_ITEXTDAT : {
4563                         ASSERTV(stream.readBE32() == 0x00000001);
4564                         itemTexturesDataSize = stream.readBE32();
4565                         itemTexturesData = itemTexturesDataSize ? new uint8[itemTexturesDataSize] : NULL;
4566                         stream.raw(itemTexturesData, itemTexturesDataSize);
4567                         break;
4568                     }
4569                     case SAD_OBJEND__ :
4570                         ASSERTV(stream.readBE32() == 0x00000000);
4571                         ASSERTV(stream.readBE32() == 0x00000000);
4572                         break;
4573                 // SPR
4574                     case SPR_SPRFILE_ :
4575                         ASSERTV(stream.readBE32() == 0x00000000);
4576                         ASSERTV(stream.readBE32() == 0x00000020);
4577                         break;
4578                     case SPR_SPRITINF : {
4579                         ASSERTV(stream.readBE32() == 0x00000010);
4580                         spriteTexturesCount = stream.readBE32();
4581                         spriteTextures = spriteTexturesCount ? new TextureInfo[spriteTexturesCount] : NULL;
4582                         for (int i = 0; i < spriteTexturesCount; i++)
4583                             readSpriteTex(stream, spriteTextures[i]);
4584                         break;
4585                     }
4586                     case SPR_SPRITDAT : {
4587                         ASSERTV(stream.readBE32() == 0x00000001);
4588                         spriteTexturesDataSize = stream.readBE32();
4589                         spriteTexturesData = spriteTexturesDataSize ? new uint8[spriteTexturesDataSize] : NULL;
4590                         stream.raw(spriteTexturesData, spriteTexturesDataSize);
4591                         break;
4592                     }
4593                     case SPR_OBJECTS_ : {
4594                         ASSERTV(stream.readBE32() == 0x00000000);
4595                         spriteSequencesCount = stream.readBE32();
4596                         spriteSequences = spriteSequencesCount ? new SpriteSequence[spriteSequencesCount] : NULL;
4597                         for (int i = 0; i < spriteSequencesCount; i++) {
4598                             SpriteSequence &s = spriteSequences[i];
4599                             ASSERTV(stream.readBE16() == 0);
4600                             s.type   = Entity::remap(version, Entity::Type(stream.readBE16()));
4601                             s.sCount = (s.type >= Entity::TR1_TYPE_MAX) ? 1 : -stream.readBE16();
4602                             s.sStart = stream.readBE16();
4603                             s.transp = 1;
4604                         }
4605                         break;
4606                     }
4607                     case SPR_SPRITEND :
4608                         ASSERTV(stream.readBE32() == 0x00000000);
4609                         ASSERTV(stream.readBE32() == 0x00000000);
4610                         break;
4611                 // SND
4612                     case SND_SAMPLUT_ : {
4613                         ASSERTV(stream.readBE32() == 0x00000002);
4614                         int count = stream.readBE32();
4615                         soundsMap = new int16[count];
4616                         for (int i = 0; i < count; i++)
4617                             soundsMap[i] = stream.readBE16();
4618                         break;
4619                     }
4620                     case SND_SAMPINFS : {
4621                         ASSERTV(stream.readBE32() == 0x00000008);
4622                         soundsInfoCount = stream.readBE32();
4623                         soundsInfo = soundsInfoCount ? new SoundInfo[soundsInfoCount] : NULL;
4624                         for (int i = 0; i < soundsInfoCount; i++) {
4625                             SoundInfo &s = soundsInfo[i];
4626                             s.index       = stream.readBE16();
4627                             s.volume      = float(stream.readBE16()) / 0x7FFF;
4628                             s.chance      = float(stream.readBE16()) / 0xFFFF;
4629                             s.range       = 8 * 1024;
4630                             s.pitch       = 0.2f;
4631                             s.flags.value = stream.readBE16();
4632                         }
4633                         break;
4634                     }
4635                     case SND_SAMPLE__ : {
4636                         int32 index = stream.readBE32();
4637                         int32 size  = stream.readBE32();
4638                         ASSERT(index < soundOffsetsCount);
4639                         soundOffsets[index] = stream.pos - 4;
4640                         soundSize[index]    = size - 4; // trim last samples (clicks)
4641                         *((uint32*)(&soundData[soundOffsets[index]])) = FOURCC("SEGA"); // mark sample as SEGA PCM
4642                         stream.seek(size);
4643                         break;
4644                     }
4645                     case SND_ENDFILEz :
4646                         ASSERTV(stream.readBE32() == 0x00000000);
4647                         ASSERTV(stream.readBE32() == 0x00000000);
4648                         break;
4649                     default : {
4650                         char buf[9];
4651                         memcpy(buf, &chunkType, 8);
4652                         buf[8] = 0;
4653                         LOG("! unknown chunk type: \"%s\"\n", buf);
4654                         ASSERT(false);
4655                         break;
4656                     }
4657                 }
4658             }
4659         #endif
4660         }
4661 
readCINLevel4662         void readCIN(Stream &stream) {
4663             stream.seek(2); // skip unknown word
4664             cameraFramesCount = (stream.size - 2) / 16;
4665             cameraFrames = cameraFramesCount ? new CameraFrame[cameraFramesCount] : NULL;
4666             stream.raw(cameraFrames, cameraFramesCount * 16);
4667         }
4668 
appendObjectTexLevel4669         void appendObjectTex(TextureInfo *&objTex, int32 &count) {
4670             if (!objTex) return;
4671             TextureInfo *newObjectTextures = new TextureInfo[objectTexturesCount + count];
4672             memcpy(newObjectTextures,                       objectTextures,   sizeof(TextureInfo) * objectTexturesCount);
4673             memcpy(newObjectTextures + objectTexturesCount, objTex,           sizeof(TextureInfo) * count);
4674             delete[] objectTextures;
4675             objectTextures       = newObjectTextures;
4676             objectTexturesCount += count;
4677 
4678             delete[] objTex;
4679             objTex = NULL;
4680             count  = 0;
4681         }
4682 
expandObjectTexLevel4683         void expandObjectTex(TextureInfo *textures, int32 &count) {
4684             for (int i = 0; i < count; i++)
4685                 for (int j = 0; j < 4; j++) {
4686                     int idx = count * (1 + j) + i;
4687                     textures[idx] = textures[i];
4688                     textures[idx].tile = textures[idx].sub[j];
4689                 }
4690             count *= 5;
4691         }
4692 
getItemTexureByIndexLevel4693         int getItemTexureByIndex(uint16 index) {
4694             for (int i = 0; i < itemTexturesCount; i++)
4695                 if (itemTextures[i].index == index)
4696                     return i;
4697             ASSERT(false);
4698             return 0;
4699         }
4700 
prepareLevel4701         void prepare() {
4702             if (version == VER_TR1_PC) {
4703             // Amiga -> PC color palette for TR1 PC
4704                 ASSERT(palette);
4705                 Color24 *c = palette;
4706                 for (int i = 0; i < 256; i++) {
4707                     c->r <<= 2;
4708                     c->g <<= 2;
4709                     c->b <<= 2;
4710                     c++;
4711                 }
4712             }
4713 
4714             for (int i = 0; i < modelsCount; i++) {
4715                 Model &model = models[i];
4716                 model.type = Entity::remap(version, model.type);
4717 
4718                 for (int j = 0; j < model.mCount; j++) {
4719                     initMesh(model.mStart + j, model.type);
4720                 }
4721             }
4722 
4723             for (int i = 0; i < staticMeshesCount; i++) {
4724                 initMesh(staticMeshes[i].mesh);
4725             }
4726 
4727             remapMeshOffsetsToIndices();
4728 
4729             delete[] meshData;
4730             meshData = NULL;
4731 
4732             LOG("meshes: %d\n", meshesCount);
4733 
4734             for (int i = 0; i < entitiesBaseCount; i++) {
4735                 Entity &e = entities[i];
4736                 e.type = Entity::remap(version, e.type);
4737 
4738                 e.controller = NULL;
4739                 e.modelIndex = 0;
4740 
4741             // turn off interpolation for some entities
4742                 e.flags.smooth = !((id == LVL_TR2_CUT_1 && (e.type == Entity::CUT_6 || e.type == Entity::CUT_8 || e.type == Entity::CUT_9))
4743                                     || e.type == Entity::SWITCH_BUTTON);
4744             }
4745 
4746             for (int i = entitiesBaseCount; i < entitiesCount; i++)
4747                 entities[i].controller = NULL;
4748 
4749             if (isCutsceneLevel()) {
4750                 for (int i = 0; i < entitiesBaseCount; i++) {
4751                     Entity &e = entities[i];
4752                     if ((((version & VER_TR1)) && e.type == Entity::CUT_1) ||
4753                         (((version & (VER_TR2 | VER_TR3))) && e.isLara())) {
4754                         cutEntity = i;
4755                         break;
4756                     }
4757                 }
4758             }
4759 
4760             if (roomTextures) {
4761                 // remap texture indices for room faces
4762                 for (int i = 0; i < roomsCount; i++) {
4763                     Room::Data &data = rooms[i].data;
4764                     for (int j = 0; j < data.fCount; j++)
4765                         data.faces[j].flags.texture += objectTexturesCount;
4766                 }
4767 
4768                 for (int i = 0; i < animTexturesCount; i++)
4769                     for (int j = 0; j < animTextures[i].count; j++)
4770                         animTextures[i].textures[j] += objectTexturesCount;
4771 
4772                 appendObjectTex(roomTextures, roomTexturesCount);
4773             }
4774 
4775             if (itemTextures) {
4776                 // remap texture indices for inventory items
4777                 for (int i = 0; i < modelsCount; i++) {
4778                     Model &model = models[i];
4779                     if (Entity::isInventoryItem(model.type)) {
4780                         for (int j = model.mStart; j < model.mStart + model.mCount; j++) {
4781                             Mesh &mesh = meshes[meshOffsets[j]];
4782                             for (int k = 0; k < mesh.fCount; k++)
4783                                 if (!mesh.faces[k].colored) {
4784                                     mesh.faces[k].flags.texture += objectTexturesCount;
4785                                 }
4786                         }
4787                     }
4788                 }
4789 
4790                 appendObjectTex(itemTextures, itemTexturesCount);
4791             }
4792 
4793             if (version == VER_TR1_SAT) {
4794                 for (int i = 0; i < objectTexturesCount; i++) {
4795                     if (objectTextures[i].tile == 1)
4796                         objectTextures[i].tile = 0xFFFF;    // mark as unused
4797                 }
4798             }
4799 
4800             initRoomMeshes();
4801             initAnimTex();
4802             initExtra();
4803             initCutscene();
4804             initTextureTypes();
4805 
4806             gObjectTextures      = objectTextures;
4807             gSpriteTextures      = spriteTextures;
4808             gObjectTexturesCount = objectTexturesCount;
4809             gSpriteTexturesCount = spriteTexturesCount;
4810         }
4811 
readSamplesLevel4812         void readSamples(Stream &stream) {
4813             stream.read(soundData, soundDataSize = stream.size);
4814 
4815             int32 dataOffsets[512];
4816             int32 dataOffsetsCount = 0;
4817             int32 dataOffset = 0;
4818 
4819             while (dataOffset < soundDataSize) {
4820                 ASSERT(FOURCC(soundData + dataOffset) == FOURCC("RIFF"));
4821                 dataOffsets[dataOffsetsCount++] = dataOffset;
4822                 dataOffset += FOURCC(soundData + dataOffset + 4) + 8; // add chunk size
4823             }
4824 
4825             for (int i = 0; i < soundOffsetsCount; i++) {
4826                 soundOffsets[i] = dataOffsets[soundOffsets[i]];
4827             }
4828         }
4829 
sfxLoadAsyncLevel4830         static void sfxLoadAsync(Stream *stream, void *userData) {
4831             if (!stream) {
4832                 LOG("! can't load MAIN.SFX\n");
4833                 return;
4834             }
4835             ((Level*)userData)->readSamples(*stream);
4836             delete stream;
4837         }
4838 
4839 
initExtraLevel4840         void initExtra() {
4841         // get special models indices
4842             memset(&extra, 0xFF, sizeof(extra));
4843 
4844             for (int i = 0; i < modelsCount; i++) {
4845                 Entity::Type type = models[i].type;
4846 
4847                 switch (type) {
4848                     case Entity::MUZZLE_FLASH        : extra.muzzleFlash     = i; break;
4849                     case Entity::PUZZLE_DONE_1       : extra.puzzleDone[0]   = i; break;
4850                     case Entity::PUZZLE_DONE_2       : extra.puzzleDone[1]   = i; break;
4851                     case Entity::PUZZLE_DONE_3       : extra.puzzleDone[2]   = i; break;
4852                     case Entity::PUZZLE_DONE_4       : extra.puzzleDone[3]   = i; break;
4853                     case Entity::LARA_BRAID          : extra.braid           = i; break;
4854                     case Entity::LARA_SPEC           : extra.laraSpec        = i; break;
4855                     case Entity::LARA_SKIN           : extra.laraSkin        = i; break;
4856                     case Entity::LARA_SKIN_JOINTS    : extra.laraJoints      = i; break;
4857                     case Entity::CUT_1               : extra.meshSwap[0]     = i; break;
4858                     case Entity::CUT_2               : extra.meshSwap[1]     = i; break;
4859                     case Entity::CUT_3               : extra.meshSwap[2]     = i; break;
4860 
4861                     case Entity::INV_PASSPORT        : extra.inv.passport    = i; break;
4862                     case Entity::INV_PASSPORT_CLOSED : extra.inv.passport_closed = i; break;
4863                     case Entity::INV_MAP             : extra.inv.map         = i; break;
4864                     case Entity::INV_COMPASS         : extra.inv.compass     = i; break;
4865                     case Entity::INV_STOPWATCH       : extra.inv.stopwatch   = i; break;
4866                     case Entity::INV_HOME            : extra.inv.home        = i; break;
4867                     case Entity::INV_DETAIL          : extra.inv.detail      = i; break;
4868                     case Entity::INV_SOUND           : extra.inv.sound       = i; break;
4869                     case Entity::INV_CONTROLS        : extra.inv.controls    = i; break;
4870                     case Entity::INV_GAMMA           : extra.inv.gamma       = i; break;
4871                     case Entity::INV_EXPLOSIVE       : extra.inv.explosive   = i; break;
4872 
4873                     case Entity::LARA_PISTOLS        :
4874                     case Entity::LARA_SHOTGUN        :
4875                     case Entity::LARA_MAGNUMS        :
4876                     case Entity::LARA_UZIS           : extra.weapons[type]     = i; break;
4877 
4878                     case Entity::INV_PISTOLS         :
4879                     case Entity::INV_SHOTGUN         :
4880                     case Entity::INV_MAGNUMS         :
4881                     case Entity::INV_UZIS            : extra.inv.weapons[type] = i; break;
4882 
4883                     case Entity::INV_AMMO_PISTOLS    :
4884                     case Entity::INV_AMMO_SHOTGUN    :
4885                     case Entity::INV_AMMO_MAGNUMS    :
4886                     case Entity::INV_AMMO_UZIS       : extra.inv.ammo[type]  = i; break;
4887 
4888                     case Entity::INV_MEDIKIT_SMALL   : extra.inv.medikit[0]  = i; break;
4889                     case Entity::INV_MEDIKIT_BIG     : extra.inv.medikit[1]  = i; break;
4890 
4891                     case Entity::INV_PUZZLE_1        : extra.inv.puzzle[0]   = i; break;
4892                     case Entity::INV_PUZZLE_2        : extra.inv.puzzle[1]   = i; break;
4893                     case Entity::INV_PUZZLE_3        : extra.inv.puzzle[2]   = i; break;
4894                     case Entity::INV_PUZZLE_4        : extra.inv.puzzle[3]   = i; break;
4895 
4896                     case Entity::INV_KEY_ITEM_1      : extra.inv.key[0]      = i; break;
4897                     case Entity::INV_KEY_ITEM_2      : extra.inv.key[1]      = i; break;
4898                     case Entity::INV_KEY_ITEM_3      : extra.inv.key[2]      = i; break;
4899                     case Entity::INV_KEY_ITEM_4      : extra.inv.key[3]      = i; break;
4900 
4901                     case Entity::INV_LEADBAR         : extra.inv.leadbar     = i; break;
4902                     case Entity::INV_SCION           : extra.inv.scion       = i; break;
4903 
4904                     case Entity::SKY                 : extra.sky = i; break;
4905 
4906                     default : ;
4907                 }
4908             }
4909 
4910             for (int i = 0; i < spriteSequencesCount; i++)
4911                 switch (spriteSequences[i].type) {
4912                     case Entity::SMOKE        : extra.smoke        = i; break;
4913                     case Entity::WATER_SPLASH : extra.waterSplash  = i; break;
4914                     case Entity::GLYPHS       : extra.glyphs       = i; break;
4915                     default : ;
4916                 }
4917 
4918             //ASSERT(extra.glyphs != -1);
4919         }
4920 
initCutsceneLevel4921         void initCutscene() {
4922             if (id == LVL_TR3_CUT_2 || id == LVL_TR3_CUT_6)
4923                 cutEntity = 1; // TODO TR3
4924         // init cutscene transform
4925             cutMatrix.identity();
4926             if (cutEntity > -1) {
4927                 Entity &e = entities[cutEntity];
4928                 switch (id) { // HACK to detect cutscene level number
4929                     case LVL_TR1_CUT_1 :
4930                         cutMatrix.translate(vec3(36668, float(e.y), 63180));
4931                         cutMatrix.rotateY(-23312.0f / float(0x4000) * PI * 0.5f);
4932                         break;
4933                     case LVL_TR1_CUT_2 :
4934                         cutMatrix.translate(vec3(51962, float(e.y), 53760));
4935                         cutMatrix.rotateY(16380.0f / float(0x4000) * PI * 0.5f);
4936                         break;
4937                     case LVL_TR1_CUT_3 :
4938                         flipMap();
4939                     case LVL_TR1_CUT_4 :
4940                         cutMatrix.translate(vec3(float(e.x), float(e.y), float(e.z)));
4941                         cutMatrix.rotateY(PI * 0.5f);
4942                         break;
4943                     default :
4944                         cutMatrix.translate(vec3(float(e.x), float(e.y), float(e.z)));
4945                         cutMatrix.rotateY(e.rotation);
4946                 }
4947             }
4948         }
4949 
initTextureTypesLevel4950         void initTextureTypes() {
4951             // rooms geometry
4952             for (int roomIndex = 0; roomIndex < roomsCount; roomIndex++) {
4953                 Room       &room = rooms[roomIndex];
4954                 Room::Data &data = room.data;
4955                 for (int i = 0; i < data.fCount; i++) {
4956                     Face &f = data.faces[i];
4957                     ASSERT(!f.colored);
4958                     ASSERT(f.flags.texture < objectTexturesCount);
4959                     TextureInfo &t = objectTextures[f.flags.texture];
4960                     t.type = TEX_TYPE_ROOM;
4961                 }
4962             }
4963 
4964             // rooms static meshes
4965             for (int staticMeshIndex = 0; staticMeshIndex < staticMeshesCount; staticMeshIndex++) {
4966                 StaticMesh *staticMesh = &staticMeshes[staticMeshIndex];
4967                 if (!meshOffsets[staticMesh->mesh]) continue;
4968                 Mesh &mesh = meshes[meshOffsets[staticMesh->mesh]];
4969 
4970                 for (int i = 0; i < mesh.fCount; i++) {
4971                     Face &f = mesh.faces[i];
4972                     ASSERT(f.colored || f.flags.texture < objectTexturesCount);
4973                     if (f.colored) continue;
4974                     TextureInfo &t = objectTextures[f.flags.texture];
4975                     t.type = TEX_TYPE_ROOM;
4976                 }
4977             }
4978 
4979             // animated textures
4980             for (int animTextureIndex = 0; animTextureIndex < animTexturesCount; animTextureIndex++) {
4981                 AnimTexture &animTex = animTextures[animTextureIndex];
4982 
4983                 for (int j = 0; j < animTex.count; j++) {
4984                     TextureInfo &t = objectTextures[animTex.textures[j]];
4985                     t.type = TEX_TYPE_ROOM;
4986                 }
4987             }
4988 
4989             // objects (duplicate all textures that are simultaneously used for static meshes)
4990             TextureInfo *dupObjTex = NULL;
4991             int         dupObjTexCount = 0;
4992 
4993             for (int modelIndex = 0; modelIndex < modelsCount; modelIndex++) {
4994                 Model &model = models[modelIndex];
4995                 for (int meshIndex = model.mStart; meshIndex < model.mStart + model.mCount; meshIndex++) {
4996                     Mesh &mesh = meshes[meshOffsets[meshIndex]];
4997 
4998                     for (int i = 0; i < mesh.fCount; i++) {
4999                         Face &f = mesh.faces[i];
5000 //                        ASSERT(f.colored || f.flags.texture < objectTexturesCount);
5001 
5002                         if (f.flags.texture >= objectTexturesCount) {
5003                             f.colored = true;
5004                         }
5005 
5006                         if (f.colored) continue;
5007                         TextureInfo &t = objectTextures[f.flags.texture];
5008                         if (t.type != TEX_TYPE_OBJECT) {
5009                             if (!dupObjTex) {
5010                                 dupObjTex = new TextureInfo[256];
5011                             }
5012 
5013                             int index = 0;
5014                             while (index < dupObjTexCount) {
5015                                 TextureInfo &ot = dupObjTex[index];
5016                                 if (ot.tile == t.tile && ot.clut == t.clut && ot.texCoord[0] == t.texCoord[0] && ot.texCoord[1] == t.texCoord[1])
5017                                     break;
5018                                 index++;
5019                             }
5020 
5021                             if (index == dupObjTexCount) {
5022                                 ASSERT(index <= 256);
5023                                 dupObjTex[dupObjTexCount] = t;
5024                                 dupObjTex[dupObjTexCount].type = TEX_TYPE_OBJECT;
5025                                 dupObjTexCount++;
5026                             }
5027 
5028                             f.flags.texture = objectTexturesCount + index;
5029                         }
5030                     }
5031                 }
5032             }
5033 
5034             appendObjectTex(dupObjTex, dupObjTexCount);
5035         }
5036 
convToInvLevel5037         static Entity::Type convToInv(Entity::Type type) {
5038             for (int j = 0; j < COUNT(ITEM_TO_INV); j++)
5039                 if (type == ITEM_TO_INV[j].src) {
5040                     return ITEM_TO_INV[j].dst;
5041                 }
5042             return type;
5043         }
5044 
convFromInvLevel5045         static Entity::Type convFromInv(Entity::Type type) {
5046             for (int j = 0; j < COUNT(ITEM_TO_INV); j++)
5047                 if (type == ITEM_TO_INV[j].dst) {
5048                     return ITEM_TO_INV[j].src;
5049                 }
5050             return type;
5051         }
5052 
initModelIndicesLevel5053         void initModelIndices() {
5054             for (int i = 0; i < entitiesCount; i++) {
5055                 TR::Entity &e = entities[i];
5056                 e.modelIndex = getModelIndex(e.type);
5057             }
5058         }
5059 
getTitleIdLevel5060         LevelID getTitleId() const {
5061             return TR::getTitleId(version);
5062         }
5063 
getHomeIdLevel5064         LevelID getHomeId() const {
5065             return TR::getHomeId(version);
5066         }
5067 
getStartIdLevel5068         LevelID getStartId() const {
5069             return TR::getStartId(version);
5070         }
5071 
getEndIdLevel5072         LevelID getEndId() const {
5073             return TR::getEndId(version);
5074         }
5075 
isTitleLevel5076         bool isTitle() const {
5077             return id == getTitleId();
5078         }
5079 
isHomeLevel5080         bool isHome() const {
5081             return id == getHomeId();
5082         }
5083 
isEndLevel5084         bool isEnd() const {
5085             return id == getEndId();
5086         }
5087 
isCutsceneLevelLevel5088         bool isCutsceneLevel() const {
5089             return TR::isCutsceneLevel(id);
5090         }
5091 
readFaceLevel5092         void readFace(Stream &stream, Face &f, bool colored, bool triangle, bool isRoomMesh) {
5093             f.triangle = triangle;
5094 
5095             for (int i = 0; i < (triangle ? 3 : 4); i++) {
5096                 stream.read(f.vertices[i]);
5097             }
5098 
5099             if (triangle) {
5100                 f.vertices[3] = 0;
5101             }
5102 
5103             stream.read(f.flags.value);
5104 
5105             if (!isRoomMesh && (version & (VER_TR4 | VER_TR5))) {
5106                 stream.read(f.effects.value);
5107             }
5108 
5109             f.colored = colored;
5110         }
5111 
readRoomLevel5112         void readRoom(Stream &stream, int roomIndex) {
5113             Room &r = rooms[roomIndex];
5114             Room::Data &d = r.data;
5115         // room info
5116             stream.read(r.info);
5117         // room data
5118             stream.read(d.size);
5119             int startOffset = stream.pos;
5120             if (version == VER_TR1_PSX) {
5121                 stream.seek(2);
5122             }
5123 
5124             // only for TR3 PSX
5125             int32 partsCount;
5126             int32 parts[16];
5127 
5128             if (version == VER_TR3_PSX) {
5129                 d.vCount = d.tCount = d.rCount = d.fCount = 0;
5130             // pre-calculate number of vertices, triangles and rectangles for TR3 PSX format
5131                 stream.read(partsCount);
5132                 stream.raw(parts, sizeof(parts));
5133 
5134                 for (int pIndex = 0; pIndex < partsCount; pIndex++) {
5135                     stream.setPos(startOffset + parts[pIndex] + 6);
5136 
5137                     uint8 tmpV, tmpT;
5138                     d.vCount += stream.read(tmpV);
5139                     d.tCount += stream.read(tmpT);
5140 
5141                     stream.seek(tmpV * 4 + tmpT * 4); // skip vertices and triangles
5142 
5143                     int q = 0;
5144                     uint32 info;
5145                     while (1) {
5146                         if (!q) {
5147                             stream.read(info);
5148                             q = 3;
5149                         }
5150                         uint32 texture = info & 0x03FF;
5151                         if (texture == 0x03FF) // ending flag
5152                             break;
5153                         info >>= 10;
5154                         stream.seek(4); // skip rectangle indices
5155                         d.rCount++;
5156                         q--;
5157                     }
5158                 }
5159 
5160                 ASSERT(int(d.size * 2) >= stream.pos - startOffset);
5161                 stream.setPos(startOffset + d.size * 2);
5162 
5163                 d.fCount   = d.rCount + d.tCount;
5164                 d.faces    = d.fCount ? new Face[d.fCount] : NULL;
5165                 d.vertices = d.vCount ? new Room::Data::Vertex[d.vCount] : NULL;
5166 
5167                 d.vCount = d.fCount = 0;
5168             } else {
5169                 d.vertices = stream.read(d.vCount) ? new Room::Data::Vertex[d.vCount] : NULL;
5170             }
5171 
5172             if (version == VER_TR3_PSX) {
5173                 for (int pIndex = 0; pIndex < partsCount; pIndex++) {
5174                     stream.setPos(startOffset + parts[pIndex] + 4);
5175 
5176                     uint8 rIndex, rFlags;
5177                     stream.read(rIndex); // room index
5178                     stream.read(rFlags); // room flags
5179 
5180                     ASSERT(rIndex == roomIndex);
5181                     r.flags.value = rFlags;
5182 
5183                     uint8 vCount, tCount;
5184                     stream.read(vCount);
5185                     stream.read(tCount);
5186 
5187                     int32 vStart = d.vCount;
5188                 // read vertices
5189                     for (uint8 i = 0; i < vCount; i++) {
5190                         Room::Data::Vertex &v = d.vertices[d.vCount++];
5191 
5192                         struct {
5193                             uint32 z:5, y:5, x:5, color:15, flags:2;
5194                         } cv;
5195 
5196                         stream.raw(&cv, sizeof(cv));
5197                         //ASSERT(cv.attribute == 0);
5198                         v.pos.x      = (cv.x << 10);
5199                         v.pos.y      = (cv.y << 8) + r.info.yTop;
5200                         v.pos.z      = (cv.z << 10);
5201                         v.attributes = 0;
5202                         v.color      = Color16(cv.color);
5203                     }
5204 
5205                 // read triangles
5206                     for (uint8 i = 0; i < tCount; i++) {
5207                         struct {
5208                             uint32 i0:7, i1:7, i2:7, texture:10, unknown:1;
5209                         } t;
5210 
5211                         stream.raw(&t, sizeof(t));
5212 
5213                         ASSERT(t.unknown == 0);
5214 
5215                         Face &f = d.faces[d.fCount++];
5216                         f.flags.texture = t.texture;
5217                         f.triangle      = true;
5218                         f.vertices[0]   = vStart + t.i0;
5219                         f.vertices[1]   = vStart + t.i1;
5220                         f.vertices[2]   = vStart + t.i2;
5221                         f.vertices[3]   = 0;
5222                         ASSERT(f.vertices[0] < d.vCount);
5223                         ASSERT(f.vertices[1] < d.vCount);
5224                         ASSERT(f.vertices[2] < d.vCount);
5225                     }
5226                 // read rectangles
5227                     int q = 0;
5228                     uint32 info;
5229                     while (1) {
5230                         if (!q) {
5231                             stream.read(info);
5232                             q = 3;
5233                         }
5234 
5235                         uint32 texture = info & 0x03FF;
5236                         if (texture == 0x3FF)
5237                             break;
5238                         info >>= 10;
5239 
5240                         struct {
5241                             uint32 i0:7, i1:7, i2:7, i3:7, unknown:4;
5242                         } r;
5243                         stream.raw(&r, sizeof(r));
5244 
5245                         ASSERT(r.unknown == 0);
5246 
5247                         Face &f = d.faces[d.fCount++];
5248                         f.flags.texture = texture;
5249                         f.vertices[0]   = vStart + r.i0;
5250                         f.vertices[1]   = vStart + r.i1;
5251                         f.vertices[2]   = vStart + r.i2;
5252                         f.vertices[3]   = vStart + r.i3;
5253 
5254                         ASSERT(f.vertices[0] < d.vCount);
5255                         ASSERT(f.vertices[1] < d.vCount);
5256                         ASSERT(f.vertices[2] < d.vCount);
5257                         ASSERT(f.vertices[3] < d.vCount);
5258 
5259                         q--;
5260                     }
5261                 }
5262             } else {
5263                 for (int i = 0; i < d.vCount; i++) {
5264                     Room::Data::Vertex &v = d.vertices[i];
5265 
5266                     uint16 lighting;
5267 
5268                     if (version == VER_TR2_PSX) {
5269                         struct {
5270                             uint32 lighting:8, attributes:8, z:5, y:5, x:5, w:1;
5271                         } cv;
5272 
5273                         stream.raw(&cv, sizeof(cv));
5274 
5275                         v.pos.x       = (cv.x << 10);
5276                         v.pos.y       = (cv.y << 8) + r.info.yTop;
5277                         v.pos.z       = (cv.z << 10);
5278                         lighting      = cv.lighting;
5279                         v.attributes  = cv.attributes;
5280 
5281                         lighting = 0x1FFF - (lighting << 5); // TODO: calc lighting by lighting = [0..255] and mode = [0..31] values
5282                     } else {
5283                         stream.read(v.pos.x);
5284                         stream.read(v.pos.y);
5285                         stream.read(v.pos.z);
5286                         stream.read(lighting);
5287 
5288                         if (version == VER_TR2_PC || version == VER_TR3_PC || version == VER_TR4_PC) {
5289                             stream.read(v.attributes);
5290                         }
5291 
5292                         if (version == VER_TR2_PC) {
5293                             stream.read(lighting); // real lighting value
5294                         }
5295 
5296                         if (version == VER_TR3_PC || version == VER_TR4_PC) {
5297                             Color16 color;
5298                             stream.read(color.value);
5299                             v.color = color;
5300                         }
5301                     }
5302 
5303                     if (version == VER_TR1_PSX || version == VER_TR3_PSX) {
5304                         lighting = 0x1FFF - (lighting << 5); // convert vertex luminance from PSX to PC format
5305                     }
5306 
5307                     if ((version & VER_VERSION) < VER_TR3) { // lighting to color conversion
5308                         int value = clamp((lighting > 0x1FFF) ? 255 : (255 - (lighting >> 5)), 0, 255);
5309                         v.color.r = v.color.g = v.color.b = value;
5310                         v.color.a = 255;
5311                     }
5312                 }
5313 
5314                 if (version == VER_TR2_PSX) {
5315                     stream.seek(2);
5316                 }
5317 
5318                 int tmp = stream.pos;
5319                 if (version == VER_TR2_PSX) {
5320                     stream.read(d.rCount);
5321                     stream.seek(sizeof(uint16) * d.rCount);
5322                     if ((stream.pos - startOffset) % 4) stream.seek(2);
5323                     stream.seek(sizeof(uint16) * 4 * d.rCount);
5324                 } else {
5325                     stream.seek(stream.read(d.rCount) * FACE4_SIZE); // uint32 colored (not existing in file)
5326                 }
5327                 stream.read(d.tCount);
5328                 stream.setPos(tmp);
5329 
5330                 d.fCount = d.rCount + d.tCount;
5331                 d.faces  = d.fCount ? new Face[d.fCount] : NULL;
5332 
5333                 int idx = 0;
5334 
5335                 int16 tmpCount;
5336                 stream.read(tmpCount);
5337                 ASSERT(tmpCount == d.rCount);
5338 
5339                 if (version == VER_TR2_PSX) {
5340                     for (int i = 0; i < d.rCount; i++)
5341                         stream.raw(&d.faces[i].flags.value, sizeof(uint16));
5342 
5343                     if ((stream.pos - startOffset) % 4) {
5344                         stream.seek(2);
5345                     }
5346 
5347                     for (int i = 0; i < d.rCount; i++) {
5348                         Face &f = d.faces[i];
5349                         stream.raw(f.vertices, sizeof(uint16) * 4);
5350                         f.vertices[0] >>= 2;
5351                         f.vertices[1] >>= 2;
5352                         f.vertices[2] >>= 2;
5353                         f.vertices[3] >>= 2;
5354                     }
5355                 } else {
5356                     for (int i = 0; i < d.rCount; i++) {
5357                         readFace(stream, d.faces[idx++], false, false, true);
5358                     }
5359                 }
5360 
5361                 stream.read(tmpCount);
5362                 ASSERT(tmpCount == d.tCount);
5363 
5364                 if (version == VER_TR2_PSX) {
5365                     stream.seek(2);
5366                     for (int i = 0; i < d.tCount; i++) {
5367                         Face &f = d.faces[d.rCount + i];
5368                         stream.raw(&f.flags.value, sizeof(uint16));
5369                         stream.raw(f.vertices, sizeof(uint16) * 3);
5370                         f.vertices[0] >>= 2;
5371                         f.vertices[1] >>= 2;
5372                         f.vertices[2] >>= 2;
5373                         f.vertices[3] = 0;
5374                         f.triangle    = true;
5375                     }
5376                 } else {
5377                     for (int i = 0; i < d.tCount; i++) {
5378                         readFace(stream, d.faces[idx++], false, true, true);
5379                     }
5380                 }
5381             }
5382 
5383             if (version & VER_PSX) { // swap indices (quad strip -> quad list) only for PSX version
5384                 for (int j = 0; j < d.fCount; j++) {
5385                     if (!d.faces[j].triangle) {
5386                         swap(d.faces[j].vertices[2], d.faces[j].vertices[3]);
5387                     }
5388                 }
5389             }
5390 
5391         // room sprites
5392             if (version == VER_TR2_PSX || version == VER_TR3_PSX) { // there is no room sprites
5393                 d.sprites = NULL;
5394                 d.sCount  = 0;
5395             } else {
5396                 stream.read(d.sprites, stream.read(d.sCount));
5397             }
5398 
5399             if (version == VER_TR3_PSX && partsCount != 0) {
5400                 stream.seek(4); // skip unknown shit
5401             }
5402 
5403             ASSERT(int(d.size * 2) >= stream.pos - startOffset);
5404             stream.setPos(startOffset + d.size * 2);
5405 
5406         // portals
5407             stream.read(r.portals, stream.read(r.portalsCount));
5408 
5409             if (version == VER_TR2_PSX || version == VER_TR3_PSX) {
5410                 for (int i = 0; i < r.portalsCount; i++) {
5411                     r.portals[i].vertices[0].y += r.info.yTop;
5412                     r.portals[i].vertices[1].y += r.info.yTop;
5413                     r.portals[i].vertices[2].y += r.info.yTop;
5414                     r.portals[i].vertices[3].y += r.info.yTop;
5415                 }
5416             }
5417 
5418         // sectors
5419             stream.read(r.zSectors);
5420             stream.read(r.xSectors);
5421             r.sectors = (r.zSectors * r.xSectors > 0) ? new Room::Sector[r.zSectors * r.xSectors] : NULL;
5422 
5423             for (int i = 0; i < r.zSectors * r.xSectors; i++) {
5424                 Room::Sector &s = r.sectors[i];
5425 
5426                 stream.read(s.floorIndex);
5427                 stream.read(s.boxIndex);
5428                 stream.read(s.roomBelow);
5429                 stream.read(s.floor);
5430                 stream.read(s.roomAbove);
5431                 stream.read(s.ceiling);
5432 
5433                 if (version & (VER_TR1 | VER_TR2)) {
5434                     s.material = 0;
5435                 } else {
5436                     s.material = s.boxIndex & 0x0F;
5437                     s.boxIndex = s.boxIndex >> 4;
5438                     if (s.boxIndex == 2047) {
5439                         s.boxIndex = 0; // TODO TR3 slide box indices
5440                     }
5441                 }
5442             }
5443 
5444         // ambient light luminance
5445             stream.read(r.ambient);
5446 
5447             if (version != VER_TR3_PSX) {
5448                 if (version & (VER_TR2 | VER_TR3 | VER_TR4))
5449                     stream.read(r.ambient2);
5450 
5451                 if (version & VER_TR2)
5452                     stream.read(r.lightMode);
5453             } else {
5454                 r.ambient = 0x1FFF - r.ambient;
5455                 stream.read(r.ambient2);
5456             }
5457 
5458         // lights
5459             r.lights = stream.read(r.lightsCount) ? new Room::Light[r.lightsCount] : NULL;
5460             for (int i = 0; i < r.lightsCount; i++) {
5461                 Room::Light &light = r.lights[i];
5462                 stream.read(light.x);
5463                 stream.read(light.y);
5464                 stream.read(light.z);
5465 
5466                 uint16 intensity;
5467 
5468                 if (version & (VER_TR3 | VER_TR4)) {
5469                     stream.read(light.color);
5470                     stream.read(light.type);
5471                 }
5472 
5473                 if (version & VER_TR4) {
5474                     uint8 unknown;
5475                     stream.read(unknown);
5476                     //ASSERT(unknown == 0x00 || unknown == 0xFF);
5477                     uint8 byteIntensity;
5478                     intensity = stream.read(byteIntensity);
5479                     stream.read(light.in);
5480                     stream.read(light.out);
5481                     stream.read(light.length);
5482                     stream.read(light.cutoff);
5483                     stream.read(light.dir);
5484                     light.radius = uint32(light.length);
5485                 } else {
5486                     stream.read(intensity);
5487                 }
5488 
5489                 if (version == VER_TR1_PSX) {
5490                     stream.seek(2);
5491                 }
5492 
5493                 if (version & (VER_TR2 | VER_TR3)) {
5494                     stream.seek(2); // intensity2
5495                 }
5496 
5497                 if (version != VER_TR4_PC) {
5498                     stream.read(light.radius);
5499                 }
5500 
5501                 if (version & VER_TR2) {
5502                     stream.seek(4); // radius2
5503                 }
5504 
5505                 if ((version & VER_VERSION) < VER_TR3) {
5506                     int value = clamp((intensity > 0x1FFF) ? 0 : (intensity >> 5), 0, 255);
5507                     light.color.r = light.color.g = light.color.b = value;
5508                 }
5509 
5510                 light.intensity = intensity;
5511 
5512                 if (version == VER_TR3_PSX) {
5513                     light.radius >>= 2;
5514                 }
5515 
5516                 light.radius *= 2;
5517             }
5518         // meshes
5519             stream.read(r.meshesCount);
5520             r.meshes = r.meshesCount ? new Room::Mesh[r.meshesCount] : NULL;
5521             for (int i = 0; i < r.meshesCount; i++) {
5522                 Room::Mesh &m = r.meshes[i];
5523                 stream.read(m.x);
5524                 stream.read(m.y);
5525                 stream.read(m.z);
5526                 stream.read(m.rotation.value);
5527                 if (version & (VER_TR3 | VER_TR4)) {
5528                     Color16 color;
5529                     stream.read(color.value);
5530                     m.color = color;
5531                     stream.seek(2);
5532                 } else {
5533                     if (version & VER_TR2) {
5534                         stream.seek(2);
5535                     }
5536 
5537                     uint16 intensity;
5538                     stream.read(intensity);
5539                     if ((version & VER_VERSION) < VER_TR3) {
5540                         int value = clamp((intensity > 0x1FFF) ? 255 : (255 - (intensity >> 5)), 0, 255);
5541                         m.color.r = m.color.g = m.color.b = value;
5542                         m.color.a = 0;
5543                     }
5544                 }
5545 
5546                 stream.read(m.meshID);
5547                 if (version == VER_TR1_PSX) {
5548                     stream.seek(2); // skip padding
5549                 }
5550             }
5551 
5552         // misc flags
5553             stream.read(r.alternateRoom);
5554             stream.read(r.flags.value);
5555             if (version & (VER_TR3 | VER_TR4)) {
5556                 stream.read(r.waterScheme);
5557                 stream.read(r.reverbType);
5558                 stream.read(r.filter);
5559             }
5560 
5561             r.dynLightsCount = 0;
5562         }
5563 
5564         void initMesh(int mIndex, Entity::Type type = Entity::NONE) {
5565             int offset = meshOffsets[mIndex];
5566             for (int i = 0; i < meshesCount; i++) {
5567                 if (meshes[i].offset == offset) {
5568                     return;
5569                 }
5570             }
5571 
5572             Stream stream(NULL, &meshData[offset / 2], 1024 * 1024);
5573 
5574             Mesh &mesh = meshes[meshesCount++];
5575             mesh.offset = offset;
5576 
5577             uint32 fOffset = 0xFFFFFFFF;
5578 
5579             if (type == Entity::SKY && version == VER_TR3_PSX) {
5580                 mesh.center.x    =
5581                 mesh.center.y    =
5582                 mesh.center.z    =
5583                 mesh.radius      =
5584                 mesh.tCount      = 0;
5585                 mesh.flags.value = 0x80;
5586                 stream.read(mesh.vCount);
5587                 stream.read(mesh.rCount);
5588             } else {
5589                 stream.read(mesh.center);
5590                 stream.read(mesh.radius);
5591 
5592                 if (version == VER_TR3_PSX) {
5593                     uint8  tmp;
5594                     uint16 tmpOffset;
5595                     mesh.vCount      = stream.read(tmp);
5596                     mesh.flags.value = stream.read(tmp);
5597                     stream.read(tmpOffset);
5598                     fOffset          = stream.pos + tmpOffset;
5599                 } else {
5600                     stream.read(mesh.flags.value);
5601                     stream.read(mesh.vCount);
5602                 }
5603 
5604                 if (version == VER_TR1_SAT) {
5605                     mesh.center.x    = swap16(mesh.center.x);
5606                     mesh.center.y    = swap16(mesh.center.y);
5607                     mesh.center.z    = swap16(mesh.center.z);
5608                     mesh.radius      = swap16(mesh.radius);
5609                     mesh.flags.value = swap16(mesh.flags.value);
5610                     mesh.vCount      = swap16(mesh.vCount);
5611                 }
5612             }
5613 
5614             switch (version) {
5615                 case VER_TR1_SAT : {
5616                     mesh.vertices = new Mesh::Vertex[mesh.vCount];
5617                     for (int i = 0; i < mesh.vCount; i++) {
5618                         short4 &c = mesh.vertices[i].coord;
5619                         c.x = stream.readBE16();
5620                         c.y = stream.readBE16();
5621                         c.z = stream.readBE16();
5622                     }
5623                     int16 nCount = stream.readBE16();
5624                     ASSERT(mesh.vCount == abs(nCount));
5625                     for (int i = 0; i < mesh.vCount; i++) {
5626                         short4 &c = mesh.vertices[i].coord;
5627                         short4 &n = mesh.vertices[i].normal;
5628                         if (nCount > 0) { // normal
5629                             n.x = stream.readBE16();
5630                             n.y = stream.readBE16();
5631                             n.z = stream.readBE16();
5632                             n.w = 1;
5633                             c.w = 0x1FFF;
5634                         } else { // intensity
5635                             c.w = stream.readBE16();
5636                             n = short4( 0, 0, 0, 0 );
5637                         }
5638                     }
5639 
5640                     mesh.fCount = stream.readBE16();
5641                     mesh.faces = new Face[mesh.fCount];
5642                     mesh.tCount = mesh.rCount = 0;
5643 
5644                     enum {
5645                         TYPE_T_TEX_UNK        = 2,
5646                         TYPE_T_COLOR          = 4,
5647                         TYPE_T_TEX            = 8,
5648                         TYPE_T_TEX_TRANSP     = 16,
5649                         TYPE_R_COLOR          = 5,
5650                         TYPE_R_TEX            = 9,
5651                         TYPE_R_TRANSP         = 17,
5652                         TYPE_R_FLIP_TEX       = 49,
5653                         TYPE_R_FLIP_TRANSP    = 57,
5654                     };
5655 
5656                     TextureInfo   *textures;
5657                     int           texturesCount;
5658                     int           texturesBaseCount;
5659 
5660                     if (itemTexturesCount && Entity::isInventoryItem(type)) {
5661                         textures          = itemTextures;
5662                         texturesCount     = itemTexturesCount;
5663                         texturesBaseCount = itemTexturesBaseCount;
5664                     } else {
5665                         textures          = objectTextures;
5666                         texturesCount     = objectTexturesCount;
5667                         texturesBaseCount = objectTexturesBaseCount;
5668                     }
5669 
5670                     int fIndex = 0;
5671                     uint16 typesCount = stream.readBE16();
5672                     for (int j = 0; j < typesCount; j++) {
5673                         uint16 type  = stream.readBE16();
5674                         uint16 count = stream.readBE16();
5675                         for (int k = 0; k < count; k++) {
5676                             ASSERT(fIndex < mesh.fCount);
5677                             Face &f = mesh.faces[fIndex++];
5678                             switch (type) {
5679                                 case TYPE_T_COLOR      : f.colored = true;
5680                                 case TYPE_T_TEX_UNK    :
5681                                 case TYPE_T_TEX        :
5682                                 case TYPE_T_TEX_TRANSP :
5683                                     f.triangle    = true;
5684                                     f.vertices[0] = (stream.readBE16() >> 5);
5685                                     f.vertices[1] = (stream.readBE16() >> 5);
5686                                     f.vertices[2] = (stream.readBE16() >> 5);
5687                                     f.vertices[3] = 0;
5688                                     f.flags.value = stream.readBE16();
5689                                     ASSERT(f.vertices[0] < mesh.vCount && f.vertices[1] < mesh.vCount && f.vertices[2] < mesh.vCount);
5690                                     mesh.tCount++;
5691 
5692                                     if (!f.colored) {
5693                                         union {
5694                                             struct { uint16 texture:12, flip:4; };
5695                                             uint16 value;
5696                                         } tri;
5697 
5698                                         tri.value = f.flags.value;
5699                                         f.flags.value = tri.texture;
5700                                         f.flip        = tri.flip;
5701 
5702                                         if (textures == itemTextures)
5703                                             f.flags.value = getItemTexureByIndex(f.flags.value);
5704 
5705                                         f.flags.value += texturesBaseCount;
5706 
5707                                         if (f.flip != 0 && f.flip != 2 && f.flip != 4 && f.flip != 6 && f.flip != 8 && f.flip != 10 && f.flip != 12 && f.flip != 14) {
5708                                             // TODO puma flip 14 bug
5709                                             ASSERT(false);
5710                                             f.colored = true;
5711                                             f.flags.value = 0x00FF;
5712                                         }
5713 
5714                                         if (f.flip == 6 || f.flip == 12) { // 3 bit
5715                                             f.flags.value += texturesBaseCount + texturesBaseCount + texturesBaseCount;
5716                                         }
5717 
5718                                         if (f.flip == 4 || f.flip == 14) {
5719                                             f.flags.value += texturesBaseCount + texturesBaseCount;
5720                                         }
5721 
5722                                         if (f.flip == 2 || f.flip == 8) {
5723                                             f.flags.value += texturesBaseCount;
5724                                         }
5725                                     }
5726 
5727                                     break;
5728                                 case TYPE_R_COLOR       : f.colored = true;
5729                                 case TYPE_R_FLIP_TEX    :
5730                                 case TYPE_R_FLIP_TRANSP : f.flip = 1;
5731                                 case TYPE_R_TEX         :
5732                                 case TYPE_R_TRANSP      :
5733                                     f.vertices[0] = (stream.readBE16() >> 5);
5734                                     f.vertices[1] = (stream.readBE16() >> 5);
5735                                     f.vertices[2] = (stream.readBE16() >> 5);
5736                                     f.vertices[3] = (stream.readBE16() >> 5);
5737                                     f.flags.value = stream.readBE16();
5738                                     ASSERT(f.vertices[0] < mesh.vCount && f.vertices[1] < mesh.vCount && f.vertices[2] < mesh.vCount && f.vertices[3] < mesh.vCount);
5739                                     mesh.rCount++;
5740 
5741                                     f.flip = (type == TYPE_R_FLIP_TEX || type == TYPE_R_FLIP_TRANSP);
5742 
5743                                     if (!f.colored) {
5744                                         ASSERT(f.flags.value % 16 == 0);
5745                                         f.flags.value /= 16;
5746 
5747                                         if (textures == itemTextures)
5748                                             f.flags.value = getItemTexureByIndex(f.flags.value);
5749                                     }
5750 
5751                                     break;
5752                                 default :
5753                                     LOG("! unknown face type: %d\n", type);
5754                                     ASSERT(false);
5755                             }
5756 
5757                             ASSERT(f.colored || f.flags.value < texturesCount);
5758 
5759                             if (type == TYPE_R_TRANSP || type == TYPE_R_FLIP_TRANSP || type == TYPE_T_TEX_TRANSP)
5760                                 textures[f.flags.texture].attribute = 1;
5761 
5762                         }
5763                     }
5764                     ASSERT(fIndex == mesh.fCount);
5765                     break;
5766                 }
5767                 case VER_TR1_PC :
5768                 case VER_TR2_PC :
5769                 case VER_TR3_PC :
5770                 case VER_TR4_PC :
5771                 case VER_TR5_PC : {
5772                     mesh.vertices = new Mesh::Vertex[mesh.vCount];
5773                     for (int i = 0; i < mesh.vCount; i++) {
5774                         short4 &c = mesh.vertices[i].coord;
5775                         stream.read(c.x);
5776                         stream.read(c.y);
5777                         stream.read(c.z);
5778                     }
5779                     int16 nCount;
5780                     stream.read(nCount);
5781                     ASSERT(mesh.vCount == abs(nCount));
5782                     for (int i = 0; i < mesh.vCount; i++) {
5783                         short4 &c = mesh.vertices[i].coord;
5784                         short4 &n = mesh.vertices[i].normal;
5785                         if (nCount > 0) { // normal
5786                             stream.read(n.x);
5787                             stream.read(n.y);
5788                             stream.read(n.z);
5789                             n.w = 1;
5790                             c.w = 0x1FFF;
5791                         } else { // intensity
5792                             stream.read(c.w);
5793                             n = short4( 0, 0, 0, 0 );
5794                         }
5795                     }
5796 
5797                     uint16 rCount, tCount, crCount = 0, ctCount = 0;
5798 
5799                     int faceSize4 = FACE4_SIZE;
5800                     int faceSize3 = FACE3_SIZE;
5801                     if (version & (VER_TR4 | VER_TR5)) {
5802                         faceSize4 += 2;
5803                         faceSize3 += 2;
5804                     }
5805 
5806                     int tmp = stream.pos;
5807                     stream.seek(stream.read(rCount) * faceSize4); // uint32 colored (not existing in file)
5808                     stream.seek(stream.read(tCount) * faceSize3);
5809                     if (!(version & (VER_TR4 | VER_TR5))) {
5810                         stream.seek(stream.read(crCount) * faceSize4);
5811                         stream.seek(stream.read(ctCount) * faceSize3);
5812                     }
5813                     stream.setPos(tmp);
5814 
5815                     mesh.rCount = rCount + crCount;
5816                     mesh.tCount = tCount + ctCount;
5817                     mesh.fCount = mesh.rCount + mesh.tCount;
5818                     mesh.faces  = mesh.fCount ? new Face[mesh.fCount] : NULL;
5819 
5820                     int idx = 0;
5821                     stream.seek(sizeof(rCount));  for (int i = 0; i < rCount; i++)  readFace(stream, mesh.faces[idx++], false, false, false);
5822                     stream.seek(sizeof(tCount));  for (int i = 0; i < tCount; i++)  readFace(stream, mesh.faces[idx++], false,  true, false);
5823                     if (!(version & (VER_TR4 | VER_TR5))) {
5824                         stream.seek(sizeof(crCount)); for (int i = 0; i < crCount; i++) readFace(stream, mesh.faces[idx++],  true, false, false);
5825                         stream.seek(sizeof(ctCount)); for (int i = 0; i < ctCount; i++) readFace(stream, mesh.faces[idx++],  true,  true, false);
5826                     }
5827 
5828                 #ifdef _DEBUG
5829                     for (int i = 0; i < mesh.fCount; i++) {
5830                         Face &f = mesh.faces[i];
5831                         for (int j = 0; j < (f.triangle ? 3 : 4); j++) {
5832                             ASSERT(f.vertices[j] < mesh.vCount);
5833                         }
5834                     }
5835                 #endif
5836 
5837                     break;
5838                 }
5839                 case VER_TR1_PSX :
5840                 case VER_TR2_PSX : {
5841                     int nCount = mesh.vCount;
5842                     mesh.vCount = abs(mesh.vCount);
5843                     mesh.vertices = new Mesh::Vertex[mesh.vCount];
5844 
5845                     for (int i = 0; i < mesh.vCount; i++)
5846                         stream.read(mesh.vertices[i].coord);
5847 
5848                     for (int i = 0; i < mesh.vCount; i++) {
5849                         short4 &c = mesh.vertices[i].coord;
5850                         short4 &n = mesh.vertices[i].normal;
5851                         if (nCount > 0) { // normal
5852                             stream.read(n);
5853                             n.w = 1;
5854                             c.w = 0x1FFF;
5855                         } else { // intensity
5856                             stream.read(c.w);
5857                             n = short4( 0, 0, 0, 0 );
5858                         }
5859                     }
5860 
5861                     if ((version & VER_TR2) && nCount > 0) { // TODO probably for unused meshes only but need to check
5862                         uint16 crCount = 0, ctCount = 0;
5863                         stream.read(crCount);
5864                         stream.seek((FACE4_SIZE + 2) * crCount);
5865                         stream.read(ctCount);
5866                         stream.seek((FACE3_SIZE + 2) * ctCount);
5867                     }
5868 
5869                     int tmp = stream.pos;
5870                     stream.seek(stream.read(mesh.rCount) * FACE4_SIZE); // uint32 colored (not existing in file)
5871                     stream.seek(stream.read(mesh.tCount) * FACE3_SIZE);
5872                     stream.setPos(tmp);
5873 
5874                     mesh.fCount = mesh.rCount + mesh.tCount;
5875                     mesh.faces  = mesh.fCount ? new Face[mesh.fCount] : NULL;
5876 
5877                     int idx = 0;
5878                     stream.seek(sizeof(mesh.rCount)); for (int i = 0; i < mesh.rCount; i++) readFace(stream, mesh.faces[idx++], false, false, false);
5879                     stream.seek(sizeof(mesh.tCount)); for (int i = 0; i < mesh.tCount; i++) readFace(stream, mesh.faces[idx++], false,  true, false);
5880 
5881                     if (!mesh.fCount)
5882                         LOG("! warning: mesh %d has no geometry with %d vertices\n", meshesCount - 1, mesh.vCount);
5883                     //ASSERT(mesh.rCount != 0 || mesh.tCount != 0);
5884 
5885                     for (int i = 0; i < mesh.fCount; i++) {
5886                         Face &f = mesh.faces[i];
5887                         #ifndef SPLIT_BY_TILE
5888                             f.colored = (f.flags.texture < 256) ? true : false;
5889                         #endif
5890 
5891                         if (version == VER_TR2_PSX) {
5892                             f.vertices[0] >>= 3;
5893                             f.vertices[1] >>= 3;
5894                             f.vertices[2] >>= 3;
5895                             f.vertices[3] >>= 3;
5896                         }
5897                     }
5898 
5899                     break;
5900                 }
5901                 case VER_TR3_PSX : {
5902                     mesh.tCount = 0;
5903                     mesh.rCount = 0;
5904                     mesh.fCount = 0;
5905 
5906                     if (!mesh.vCount) {
5907                         mesh.vertices = NULL;
5908                         mesh.faces    = NULL;
5909                         break;
5910                     }
5911 
5912                     mesh.vertices = new Mesh::Vertex[mesh.vCount];
5913 
5914                     for (int i = 0; i < mesh.vCount; i++)
5915                         stream.read(mesh.vertices[i].coord);
5916 
5917                     if (mesh.flags.value & 0x80) { // static mesh without normals
5918                         for (int i = 0; i < mesh.vCount; i++)
5919                             mesh.vertices[i].normal = short4( 0, 0, 0, 0 );
5920                     } else {
5921                         for (int i = 0; i < mesh.vCount; i++)
5922                             stream.read(mesh.vertices[i].normal);
5923                     }
5924 
5925                     if (type != Entity::SKY) {
5926                         ASSERT(stream.pos == fOffset);
5927 
5928                         stream.setPos(fOffset);
5929                         stream.read(mesh.tCount);
5930                         stream.read(mesh.rCount);
5931                     }
5932                     mesh.fCount = mesh.rCount + mesh.tCount;
5933                     mesh.faces  = mesh.fCount ? new Face[mesh.fCount] : NULL;
5934 
5935                 // read triangles
5936                     int idx = 0;
5937                     uint32 info;
5938 
5939                     for (int i = 0; i < mesh.tCount; i++) {
5940                         if (!(i % 4))
5941                             stream.read(info);
5942 
5943                         struct {
5944                             uint32 i0:8, i1:8, i2:8, tex:8;
5945                         } r;
5946                         stream.raw(&r, sizeof(r));
5947 
5948                         Face &f = mesh.faces[idx++];
5949                         f.flags.texture     = (info & 0xFF) | (r.tex << 8);
5950                         f.triangle          = true;
5951 
5952                         f.vertices[0] = r.i0;
5953                         f.vertices[1] = r.i1;
5954                         f.vertices[2] = r.i2;
5955                         f.vertices[3] = 0;
5956 
5957                         info >>= 8;
5958                     }
5959 
5960                 // read rectangles
5961                     for (int i = 0; i < mesh.rCount; i++) {
5962                         if (!(i % 2))
5963                             stream.read(info);
5964 
5965                         Face &f = mesh.faces[idx++];
5966                         f.flags.texture = info & 0xFFFF;
5967 
5968                         struct {
5969                             uint32 i0:8, i1:8, i2:8, i3:8;
5970                         } r;
5971                         stream.raw(&r, sizeof(r));
5972 
5973                         f.vertices[0] = r.i0;
5974                         f.vertices[1] = r.i1;
5975                         f.vertices[2] = r.i3;
5976                         f.vertices[3] = r.i2;
5977 
5978                         info >>= 16;
5979                     }
5980 
5981                     break;
5982                 }
5983                 default : ASSERT(false);
5984             }
5985 
5986             #define RECALC_ZERO_NORMALS(mesh, face)\
5987                 int fn = -1;\
5988                 for (int j = 0; j < (face.triangle ? 3 : 4); j++) {\
5989                     Mesh::Vertex &v = mesh.vertices[face.vertices[j]];\
5990                     short4 &n = v.normal;\
5991                     if (!(n.x | n.y | n.z)) {\
5992                         if (fn > -1) {\
5993                             n = mesh.vertices[face.vertices[fn]].normal;\
5994                             continue;\
5995                         }\
5996                         vec3 o = mesh.vertices[face.vertices[0]].coord;\
5997                         vec3 a = o - mesh.vertices[face.vertices[1]].coord;\
5998                         vec3 b = o - mesh.vertices[face.vertices[2]].coord;\
5999                         o = b.cross(a).normal() * 16300.0f;\
6000                         n.x = (int)o.x;\
6001                         n.y = (int)o.y;\
6002                         n.z = (int)o.z;\
6003                         fn = j;\
6004                     }\
6005                 }
6006 
6007         // recalc zero normals
6008             for (int i = 0; i < mesh.fCount; i++) {
6009                 Face &f = mesh.faces[i];
6010                 RECALC_ZERO_NORMALS(mesh, f);
6011             }
6012 
6013             #undef RECALC_ZERO_NORMALS
6014         }
6015 
remapMeshOffsetsToIndicesLevel6016         void remapMeshOffsetsToIndices() {
6017             for (int i = 0; i < meshOffsetsCount; i++) {
6018                 int index = -1;
6019                 for (int j = 0; j < meshesCount; j++)
6020                     if (meshes[j].offset == meshOffsets[i]) {
6021                         index = j;
6022                         break;
6023                     }
6024                 meshOffsets[i] = index;
6025             }
6026         }
6027 
6028         void readObjectTex(Stream &stream, TextureInfo &t, TextureType type = TEX_TYPE_OBJECT) {
6029             #define SET_PARAMS(t, d, c) {\
6030                     t.clut        = c;\
6031                     t.tile        = d.tile;\
6032                     t.attribute   = d.attribute;\
6033                     t.animated    = false;\
6034                     t.texCoord[0] = t.texCoordAtlas[0] = short2( d.x0, d.y0 );\
6035                     t.texCoord[1] = t.texCoordAtlas[1] = short2( d.x1, d.y1 );\
6036                     t.texCoord[2] = t.texCoordAtlas[2] = short2( d.x2, d.y2 );\
6037                     t.texCoord[3] = t.texCoordAtlas[3] = short2( d.x3, d.y3 );\
6038                 }
6039 
6040             t.type = t.dataType = type;
6041 
6042             switch (version) {
6043                 case VER_TR1_SAT : {
6044                     struct {
6045                         uint16  attribute;
6046                         uint16  tile;
6047                         uint16  clut;
6048                         uint8   w, h;
6049                         uint8   x0, y0;
6050                         uint8   x1, y1;
6051                         uint8   x2, y2;
6052                         uint8   x3, y3;
6053                     } d;
6054 
6055                     t.index = 0;
6056                     if (type == TEX_TYPE_ITEM)
6057                         t.index = stream.readBE16();
6058 
6059                     d.attribute = 0;
6060                     d.tile   = stream.readBE16(); // offset to 4-bit indices
6061                     t.sub[0] = stream.readBE16();
6062                     t.sub[1] = stream.readBE16();
6063                     t.sub[2] = stream.readBE16();
6064                     t.sub[3] = stream.readBE16();
6065                     d.clut   = stream.readBE16(); // offset to color palette
6066                     d.w      = stream.read() * 8;
6067                     d.h      = stream.read();
6068                     t.i5     = stream.readBE16();
6069 
6070                     if (type == TEX_TYPE_ROOM) { // for room tiles we will use fullres TSUB textures instead of mips TQTR
6071                         d.w *= 2;
6072                         d.h *= 2;
6073                     }
6074 
6075                     if (type == TEX_TYPE_ITEM)
6076                         ASSERTV(stream.readBE16() == t.i5);
6077 
6078                     d.x0 = d.y0 = d.x3 = d.y1 = 0;
6079                     d.x1 = d.x2 = max(0, d.w - 1);
6080                     d.y2 = d.y3 = max(0, d.h - 1);
6081 
6082                     SET_PARAMS(t, d, d.clut);
6083 
6084                     //if (type == TEX_TYPE_ITEM) {
6085                     //    LOG("%d %d | %d %d %d %d | %d %d %dx%d | %d\n", t.index, t.tile, t.sub[0], t.sub[1], t.sub[2], t.sub[3], t.clut, t.i5, d.w, d.h, bi);
6086                     //}
6087 
6088                     break;
6089                 }
6090                 case VER_TR1_PC :
6091                 case VER_TR2_PC :
6092                 case VER_TR3_PC : {
6093                     struct {
6094                         uint16  attribute;
6095                         uint16  tile:14, :2;
6096                         uint8   xh0, x0, yh0, y0;
6097                         uint8   xh1, x1, yh1, y1;
6098                         uint8   xh2, x2, yh2, y2;
6099                         uint8   xh3, x3, yh3, y3;
6100                     } d;
6101 
6102                     stream.raw(&d, sizeof(d));
6103                     SET_PARAMS(t, d, 0);
6104                     break;
6105                 }
6106                 case VER_TR4_PC :
6107                 case VER_TR5_PC : {
6108                     struct {
6109                         uint16  attribute;
6110                         uint16  tile:14, :2;
6111                         uint16  flags;
6112                         uint8   xh0, x0, yh0, y0;
6113                         uint8   xh1, x1, yh1, y1;
6114                         uint8   xh2, x2, yh2, y2;
6115                         uint8   xh3, x3, yh3, y3;
6116                     } d;
6117 
6118                     struct {
6119                         uint32 U, V, W, H;
6120                     } duv;
6121 
6122                     stream.raw(&d,   sizeof(d));
6123                     stream.raw(&duv, sizeof(duv));
6124                     SET_PARAMS(t, d, 0);
6125                     break;
6126                 }
6127                 case VER_TR1_PSX :
6128                 case VER_TR2_PSX :
6129                 case VER_TR3_PSX : {
6130                     struct {
6131                         uint8   x0, y0;
6132                         uint16  clut;
6133                         uint8   x1, y1;
6134                         uint16  tile:14, :2;
6135                         uint8   x2, y2;
6136                         uint16  unknown2;
6137                         uint8   x3, y3;
6138                         uint16  attribute;
6139                     } d;
6140                     stream.raw(&d, sizeof(d));
6141                     if (version == VER_TR3_PSX) {
6142                         if (d.attribute == 0)
6143                             d.attribute = 0;
6144                         else if (d.attribute == 2)
6145                             d.attribute = 2;
6146                         else if (d.attribute == 0xFFFF)
6147                             d.attribute = 1;
6148                         else {
6149                             //ASSERT(false);
6150                             d.attribute = 0;
6151                         }
6152                     }
6153                     SET_PARAMS(t, d, d.clut);
6154                     break;
6155                 }
6156                 default : ASSERT(false);
6157             }
6158 
6159             #undef SET_PARAMS
6160         }
6161 
readObjectTexLevel6162         void readObjectTex(Stream &stream) {
6163             objectTextures = stream.read(objectTexturesCount) ? new TextureInfo[objectTexturesCount] : NULL;
6164             for (int i = 0; i < objectTexturesCount; i++) {
6165                 readObjectTex(stream, objectTextures[i]);
6166             }
6167         }
6168 
readSpriteTexLevel6169         void readSpriteTex(Stream &stream, TextureInfo &t) {
6170             #define SET_PARAMS(t, d, c) {\
6171                     t.clut = c;\
6172                     t.tile = d.tile;\
6173                     t.l    = d.l;\
6174                     t.t    = d.t;\
6175                     t.r    = d.r;\
6176                     t.b    = d.b;\
6177                 }
6178 
6179             t.type      = TEX_TYPE_SPRITE;
6180             t.dataType  = TEX_TYPE_SPRITE;
6181             t.attribute = 1;
6182 
6183             switch (version) {
6184                 case VER_TR1_SAT : {
6185                     struct {
6186                         uint16 tile;
6187                         uint16 clut;
6188                         uint8  w, h;
6189                         int16  l, t, r, b;
6190                     } d;
6191                     d.tile = stream.readBE16(); // offset to 4-bit indices
6192                     d.clut = stream.readBE16() - d.tile; // offset to 16-bit color table (16 colors)
6193                     d.w    = stream.read();     // texture width div 8
6194                     d.h    = stream.read();     // texture height
6195                     d.l    = stream.readBE16();
6196                     d.t    = stream.readBE16();
6197                     d.r    = stream.readBE16();
6198                     d.b    = stream.readBE16();
6199                     ASSERTV((int16)stream.readBE16() == d.b);
6200                     SET_PARAMS(t, d, d.clut);
6201                     t.texCoord[0] = t.texCoordAtlas[0] = short2( 0,                     0                );
6202                     t.texCoord[1] = t.texCoordAtlas[1] = short2( ((int16)d.w << 3) - 1, ((int16)d.h) - 1 );
6203                     break;
6204                 }
6205                 case VER_TR1_PC :
6206                 case VER_TR2_PC :
6207                 case VER_TR3_PC :
6208                 case VER_TR4_PC :
6209                 case VER_TR5_PC : {
6210                     struct {
6211                         uint16  tile;
6212                         uint8   u, v;
6213                         uint16  w, h;
6214                         int16   l, t, r, b;
6215                     } d;
6216                     stream.raw(&d, sizeof(d));
6217                     SET_PARAMS(t, d, 0);
6218                     t.texCoord[0] = t.texCoordAtlas[0] = short2( d.u,                       d.v                       );
6219                     t.texCoord[1] = t.texCoordAtlas[1] = short2( (uint8)(d.u + (d.w >> 8)), (uint8)(d.v + (d.h >> 8)) );
6220                     break;
6221                 }
6222                 case VER_TR1_PSX :
6223                 case VER_TR2_PSX :
6224                 case VER_TR3_PSX : {
6225                     struct {
6226                         int16   l, t, r, b;
6227                         uint16  clut;
6228                         uint16  tile;
6229                         uint8   u0, v0;
6230                         uint8   u1, v1;
6231                     } d;
6232                     stream.raw(&d, sizeof(d));
6233                     SET_PARAMS(t, d, d.clut);
6234                     t.texCoord[0] = t.texCoordAtlas[0] = short2( d.u0, d.v0 );
6235                     t.texCoord[1] = t.texCoordAtlas[1] = short2( d.u1, d.v1 );
6236                     break;
6237                 }
6238                 default : ASSERT(false);
6239             }
6240 
6241             #undef SET_PARAMS
6242         }
6243 
readSpriteTexLevel6244         void readSpriteTex(Stream &stream) {
6245             spriteTextures = stream.read(spriteTexturesCount) ? new TextureInfo[spriteTexturesCount] : NULL;
6246             for (int i = 0; i < spriteTexturesCount; i++)
6247                 readSpriteTex(stream, spriteTextures[i]);
6248 
6249             spriteSequences = stream.read(spriteSequencesCount) ? new SpriteSequence[spriteSequencesCount] : NULL;
6250             for (int i = 0; i < spriteSequencesCount; i++) {
6251                 SpriteSequence &s = spriteSequences[i];
6252                 uint16 type;
6253                 stream.read(type);
6254                 s.type = Entity::remap(version, Entity::Type(type));
6255                 stream.read(s.unused);
6256                 stream.read(s.sCount);
6257                 stream.read(s.sStart);
6258                 s.sCount = -s.sCount;
6259                 s.transp = 1;
6260             }
6261 
6262         // remove unavailable sprites (check EGYPT.PHD)
6263             for (int roomIndex = 0; roomIndex < roomsCount; roomIndex++) {
6264                 Room::Data &data = rooms[roomIndex].data;
6265 
6266                 int i = 0;
6267                 while (i < data.sCount)
6268                     if (data.sprites[i].vertexIndex >= data.vCount || data.sprites[i].texture >= spriteTexturesCount) {
6269                         LOG("! room %d has wrong sprite %d (v:%d/%d t:%d/%d)\n", roomIndex, i, data.sprites[i].vertexIndex, data.vCount, data.sprites[i].texture, spriteTexturesCount);
6270                         ASSERT(false);
6271                         data.sprites[i] = data.sprites[--data.sCount];
6272                     } else
6273                         i++;
6274 
6275                 if (!data.sCount && data.sprites) {
6276                     delete[] data.sprites;
6277                     data.sprites = NULL;
6278                 }
6279             }
6280         }
6281 
readAnimTexLevel6282         void readAnimTex(Stream &stream) {
6283             uint32 animTexBlockSize;
6284             stream.read(animTexBlockSize);
6285 
6286             if (animTexBlockSize) {
6287                 uint16 *animTexBlock = new uint16[animTexBlockSize];
6288                 for (uint32 i = 0; i < animTexBlockSize; i++) {
6289                     animTexBlock[i] = stream.readLE16();
6290                 }
6291 
6292                 uint16 *ptr = animTexBlock;
6293 
6294                 animTexturesCount = *(ptr++);
6295                 animTextures = animTexturesCount ? new AnimTexture[animTexturesCount] : NULL;
6296 
6297                 for (int i = 0; i < animTexturesCount; i++) {
6298                     AnimTexture &animTex = animTextures[i];
6299                     animTex.count    = *(ptr++) + 1;
6300                     animTex.textures = new uint16[animTex.count];
6301                     for (int j = 0; j < animTex.count; j++)
6302                         animTex.textures[j] = *(ptr++);
6303                 }
6304                 delete[] animTexBlock;
6305             }
6306 
6307             if (version & (VER_TR4 | VER_TR5)) {
6308                 uint8 animTexUVs;
6309                 stream.read(animTexUVs);
6310             }
6311         }
6312 
readEntitiesLevel6313         void readEntities(Stream &stream) {
6314             entitiesCount = stream.read(entitiesBaseCount) + MAX_RESERVED_ENTITIES;
6315             entities = new Entity[entitiesCount];
6316             for (int i = 0; i < entitiesBaseCount; i++) {
6317                 Entity &e = entities[i];
6318                 uint16 type;
6319                 e.type = Entity::Type(stream.read(type));
6320                 stream.read(e.room);
6321                 stream.read(e.x);
6322                 stream.read(e.y);
6323                 stream.read(e.z);
6324                 stream.read(e.rotation.value);
6325                 stream.read(e.intensity);
6326                 if (version & (VER_TR2 | VER_TR3)) {
6327                     stream.read(e.intensity2);
6328                 }
6329                 if (version & (VER_TR4 | VER_TR5)) {
6330                     stream.read(e.OCB);
6331                 }
6332                 stream.read(e.flags.value);
6333             }
6334         }
6335 
initRoomMeshesLevel6336         void initRoomMeshes() {
6337             for (int i = 0; i < roomsCount; i++) {
6338                 Room &room = rooms[i];
6339                 for (int j = 0; j < room.meshesCount; j++)
6340                     room.meshes[j].meshIndex = getMeshByID(room.meshes[j].meshID);
6341             }
6342         }
6343 
initAnimTexLevel6344         void initAnimTex() {
6345             for (int i = 0; i < animTexturesCount; i++) {
6346                 uint8 transp = 0;
6347                 for (int j = 0; j < animTextures[i].count; j++) {
6348                     TextureInfo &t = objectTextures[animTextures[i].textures[j]];
6349                     t.animated = true;
6350                     if (t.attribute != 0)
6351                         transp = t.attribute;
6352                 }
6353 
6354                 if (transp) {
6355                     for (int j = 0; j < animTextures[i].count; j++) {
6356                         TextureInfo &t = objectTextures[animTextures[i].textures[j]];
6357                         t.attribute = transp;
6358                     }
6359                 }
6360             }
6361         }
6362 
shiftAnimTexLevel6363         void shiftAnimTex() {
6364             for (int i = 0; i < animTexturesCount; i++) {
6365                 AnimTexture &animTex = animTextures[i];
6366                 TextureInfo tmp = objectTextures[animTex.textures[0]];
6367                 for (int j = 0; j < animTex.count - 1; j++)
6368                     objectTextures[animTex.textures[j]] = objectTextures[animTex.textures[j + 1]];
6369                 objectTextures[animTex.textures[animTex.count - 1]] = tmp;
6370             }
6371         }
6372 
fillObjectTexture32Level6373         void fillObjectTexture32(AtlasTile *dst, const Color32 *data, const short4 &uv, TextureInfo *t) {
6374             AtlasColor *ptr = &dst->color[uv.y * 256];
6375             for (int y = uv.y; y < uv.w; y++) {
6376                 for (int x = uv.x; x < uv.z; x++) {
6377                     ptr[x] = data[y * 256 + x];
6378                 }
6379                 ptr += 256;
6380             }
6381             premultiplyAlpha(dst->color, uv);
6382         }
6383 
fillObjectTextureLevel6384         void fillObjectTexture(AtlasTile *dst, const short4 &uv, TextureInfo *t) {
6385         // convert to RGBA
6386             switch (version) {
6387                 case VER_TR1_SAT : {
6388                     uint32 iOffset = uint32(uint16(t->tile)) << 3;
6389                     uint32 cOffset = uint32(uint16(t->clut + t->tile)) << 3;
6390 
6391                     uint8 *data = NULL;
6392                     switch (t->dataType) {
6393                         case TEX_TYPE_ROOM   : data = roomTexturesData;   break;
6394                         case TEX_TYPE_ITEM   : data = itemTexturesData;   break;
6395                         case TEX_TYPE_OBJECT : data = objectTexturesData; break;
6396                         case TEX_TYPE_SPRITE : data = spriteTexturesData; break;
6397                     }
6398 
6399                     ASSERT(data != NULL);
6400 
6401                     ColorIndex4 *indices = (ColorIndex4*) (data + iOffset);
6402                     CLUT        *clut    = (CLUT*)        (data + cOffset);
6403 
6404                     int h = uv.w - uv.y;
6405                     int w = uv.z - uv.x;
6406                     ASSERT(w <= 256 && h <= 256);
6407 
6408                     for (int y = 0; y < h; y++)
6409                         for (int x = 0; x < w; x++) {
6410                             ColorIndex4 *index;
6411 
6412                             if (t->dataType == TEX_TYPE_ROOM) {
6413                                 int iw = w / 2;
6414                                 int ih = h / 2;
6415                                 int ix = x % iw;
6416                                 int iy = y % ih;
6417 
6418                                 int offset = uint32(uint16(t->sub[y >= ih ? (x >= iw ? 2 : 3) : (x >= iw ? 1 : 0)])) << 3;
6419 
6420                                 offset += (iy * iw + ix) / 2;
6421                                 index = (ColorIndex4*) (tsub + offset);
6422                             } else
6423                                 index = indices + (y * w + x) / 2;
6424 
6425                             int idx = (x % 2) ? index->a : index->b;
6426                             ColorCLUT &c = clut->color[idx];
6427 
6428                             if (t->attribute == 1 && idx == 0)
6429                                 dst->color[y * 256 + x].value = 0;
6430                             else
6431                                 dst->color[y * 256 + x] = ColorCLUT(swap16(c.value));
6432                         }
6433 
6434                     break;
6435                 }
6436                 case VER_TR1_PC : {
6437                     ASSERT(tiles8);
6438                     ASSERT(palette);
6439 
6440                     AtlasColor *ptr = &dst->color[uv.y * 256];
6441                     for (int y = uv.y; y < uv.w; y++) {
6442                         for (int x = uv.x; x < uv.z; x++) {
6443                             ASSERT(x >= 0 && y >= 0 && x < 256 && y < 256);
6444                             uint8 index = tiles8[t->tile].index[y * 256 + x];
6445                             if (index != 0) {
6446                                 ptr[x] = palette[index];
6447                             } else
6448                                 ptr[x].value = 0;
6449                         }
6450                         ptr += 256;
6451                     }
6452                     break;
6453                 }
6454                 case VER_TR2_PC :
6455                 case VER_TR3_PC : {
6456                     ASSERT(tiles16);
6457 
6458                     AtlasColor *ptr = &dst->color[uv.y * 256];
6459                     for (int y = uv.y; y < uv.w; y++) {
6460                         for (int x = uv.x; x < uv.z; x++) {
6461                             ptr[x] = tiles16[t->tile].color[y * 256 + x];
6462                         }
6463                         ptr += 256;
6464                     }
6465                     break;
6466                 }
6467                 case VER_TR4_PC :
6468                 case VER_TR5_PC : {
6469                     ASSERT(tiles32);
6470 
6471                     AtlasColor *ptr = &dst->color[uv.y * 256];
6472                     for (int y = uv.y; y < uv.w; y++) {
6473                         for (int x = uv.x; x < uv.z; x++) {
6474                             Color32 c = tiles32[t->tile].color[y * 256 + x];
6475                             swap(c.r, c.b);
6476                             ptr[x] = c;
6477                         }
6478                         ptr += 256;
6479                     }
6480                     break;
6481                 }
6482                 case VER_TR1_PSX :
6483                 case VER_TR2_PSX :
6484                 case VER_TR3_PSX : {
6485                     ASSERT(tiles4);
6486                     ASSERT(cluts);
6487 
6488                     CLUT   &clut = cluts[t->clut];
6489                     Tile4  &src  = tiles4[t->tile];
6490                     for (int y = uv.y; y < uv.w; y++) {
6491                         for (int x = uv.x; x < uv.z; x++) {
6492                             dst->color[y * 256 + x] = clut.color[(x % 2) ? src.index[(y * 256 + x) / 2].b : src.index[(y * 256 + x) / 2].a];
6493                         }
6494                     }
6495                     break;
6496                 }
6497                 default : ASSERT(false);
6498             }
6499 
6500             premultiplyAlpha(dst->color, uv);
6501         }
6502 
premultiplyAlphaLevel6503         void premultiplyAlpha(AtlasColor *data, const short4 &uv) {
6504         // pre-multiple alpha
6505             for (int y = uv.y; y < uv.w; y++)
6506                 for (int x = uv.x; x < uv.z; x++) {
6507                     AtlasColor &c = data[y * 256 + x];
6508                 #ifdef USE_ATLAS_RGBA16
6509                     if (c.a == 0) {
6510                         c.value = 0;
6511                     }
6512                 #else
6513                     c.r = uint8((uint16(c.r) * c.a) / 255);
6514                     c.g = uint8((uint16(c.g) * c.a) / 255);
6515                     c.b = uint8((uint16(c.b) * c.a) / 255);
6516                 #endif
6517                 }
6518         }
6519 
6520     // common methods
getColorLevel6521         Color32 getColor(int texture) const {
6522             switch (version) {
6523                 case VER_TR1_SAT : return ColorCLUT((uint16)texture);
6524                 case VER_TR1_PC  :
6525                     #ifdef _GAPI_SW
6526                         return Color32(texture & 0xFF, 0, 0, 142);
6527                     #else
6528                         return palette[texture & 0xFF];
6529                     #endif
6530                 case VER_TR2_PC  :
6531                 case VER_TR3_PC  : return palette32[(texture >> 8) & 0xFF];
6532                 case VER_TR1_PSX :
6533                 case VER_TR2_PSX :
6534                 case VER_TR3_PSX : {
6535                     ASSERT((texture & 0x7FFF) < 256);
6536                     TextureInfo &t = objectTextures[texture & 0x7FFF];
6537                     int idx  = (t.texCoord[0].y * 256 + t.texCoord[0].x) / 2;
6538                     int part = t.texCoord[0].x % 2;
6539                     Tile4 &tile = tiles4[t.tile];
6540                     CLUT  &clut = cluts[t.clut];
6541                     return clut.color[part ? tile.index[idx].b : tile.index[idx].a];
6542                 }
6543                 case VER_TR4_PC : break;
6544                 default : ASSERT(false);
6545             }
6546             return Color32(255, 0, 255, 255);
6547         }
6548 
getSampleStreamLevel6549         Stream* getSampleStream(int index) const {
6550             if (!soundOffsets || !soundData) return NULL;
6551             uint8 *data = soundData + soundOffsets[index];
6552             uint32 size = 0;
6553             switch (version) {
6554                 case VER_TR1_SAT : size = soundSize[index]; break;
6555                 case VER_TR1_PC  :
6556                 case VER_TR2_PC  :
6557                 case VER_TR3_PC  :
6558                 case VER_TR4_PC  : size = FOURCC(data + 4) + 8; break; // read size from wave header
6559                 case VER_TR1_PSX :
6560                 case VER_TR2_PSX :
6561                 case VER_TR3_PSX : size = soundSize[index]; break;
6562                 default          : ASSERT(false);
6563             }
6564             return new Stream(NULL, data, size);
6565         }
6566 
getMeshByIDLevel6567         int getMeshByID(uint32 id) const {
6568             for (int i = 0; i < staticMeshesCount; i++)
6569                 if (staticMeshes[i].id == id)
6570                     return i;
6571             ASSERT(false);
6572             return 0;
6573         }
6574 
getModelIndexLevel6575         int16 getModelIndex(Entity::Type type) const {
6576             if (!simpleItems)
6577                 type = convToInv(type);
6578 
6579         //#ifndef _DEBUG
6580             if ((type >= Entity::AI_GUARD && type <= Entity::AI_CHECK) ||
6581                 (type >= Entity::GLOW_2 && type <= Entity::ENEMY_BAT_SWARM) ||
6582                 type == Entity::WATERFALL || type == Entity::KILL_ALL_TRIGGERS || type == Entity::VIEW_TARGET || type == Entity::SOUND_DOOR_BELL || type == Entity::SOUND_ALARM_BELL || type == Entity::TRIPWIRE)
6583                 return 0;
6584         //#endif
6585 
6586             if (type == Entity::ENEMY_MUTANT_2 || type == Entity::ENEMY_MUTANT_3)
6587                 type = Entity::ENEMY_MUTANT_1; // hardcoded mutant models remapping
6588 
6589             if (((version & VER_TR3)) && (type == Entity::RICOCHET || type == Entity::WATER_SPLASH || type == Entity::BLOOD || type == Entity::FLAME)) {
6590                 type = Entity::MISC_SPRITES; // TODO TR3
6591             }
6592 
6593             for (int i = 0; i < modelsCount; i++)
6594                 if (type == models[i].type)
6595                     return i + 1;
6596 
6597             for (int i = 0; i < spriteSequencesCount; i++)
6598                 if (type == spriteSequences[i].type)
6599                     return -(i + 1);
6600 
6601             return 0;
6602         }
6603 
flipMapLevel6604         void flipMap() {
6605             for (int i = 0; i < roomsCount; i++)
6606                 if (rooms[i].alternateRoom > -1) {
6607                     Room &src = rooms[i];
6608                     Room &dst = rooms[src.alternateRoom];
6609 
6610                     swap(src, dst);
6611                     swap(src.alternateRoom, dst.alternateRoom);
6612                 }
6613             state.flags.flipped = !state.flags.flipped;
6614         }
6615 
floorSkipCommandLevel6616         void floorSkipCommand(FloorData* &fd, int func) {
6617             switch (func) {
6618                 case FloorData::PORTAL  :
6619                 case FloorData::FLOOR   :
6620                 case FloorData::CEILING :
6621                     fd++;
6622                     break;
6623 
6624                 case FloorData::FLOOR_NW_SE_SOLID       :
6625                 case FloorData::FLOOR_NE_SW_SOLID       :
6626                 case FloorData::CEILING_NW_SE_SOLID     :
6627                 case FloorData::CEILING_NE_SW_SOLID     :
6628                 case FloorData::FLOOR_NW_SE_PORTAL_NW   :
6629                 case FloorData::FLOOR_NW_SE_PORTAL_SE   :
6630                 case FloorData::FLOOR_NE_SW_PORTAL_NE   :
6631                 case FloorData::FLOOR_NE_SW_PORTAL_SW   :
6632                 case FloorData::CEILING_NW_SE_PORTAL_NW :
6633                 case FloorData::CEILING_NW_SE_PORTAL_SE :
6634                 case FloorData::CEILING_NE_SW_PORTAL_NE :
6635                 case FloorData::CEILING_NE_SW_PORTAL_SW :
6636                     fd++;
6637                     break;
6638 
6639                 case FloorData::TRIGGER :
6640                     fd++;
6641                     do {} while (!(*fd++).triggerCmd.end);
6642                     break;
6643 
6644                 case FloorData::LAVA :
6645                 case FloorData::CLIMB :
6646                 case FloorData::MONKEY         :
6647                 case FloorData::MINECART_LEFT  :
6648                 case FloorData::MINECART_RIGHT :
6649                     break;
6650 
6651                 default : LOG("unknown func to skip: %d\n", func);
6652             }
6653         }
6654 
getNextRoomLevel6655         int getNextRoom(const Room::Sector *sector) const {
6656             ASSERT(sector);
6657             if (!sector->floorIndex) return NO_ROOM;
6658             FloorData *fd = &floors[sector->floorIndex];
6659         // floor data always in this order
6660             if (   fd->cmd.func == FloorData::FLOOR
6661                 || fd->cmd.func == FloorData::FLOOR_NW_SE_SOLID
6662                 || fd->cmd.func == FloorData::FLOOR_NE_SW_SOLID
6663                 || fd->cmd.func == FloorData::FLOOR_NW_SE_PORTAL_SE
6664                 || fd->cmd.func == FloorData::FLOOR_NW_SE_PORTAL_NW
6665                 || fd->cmd.func == FloorData::FLOOR_NE_SW_PORTAL_SW
6666                 || fd->cmd.func == FloorData::FLOOR_NE_SW_PORTAL_NE) {
6667 
6668                 if (fd->cmd.end) return NO_ROOM;
6669                 fd += 2;
6670             }
6671 
6672             if (   fd->cmd.func == FloorData::CEILING
6673                 || fd->cmd.func == FloorData::CEILING_NE_SW_SOLID
6674                 || fd->cmd.func == FloorData::CEILING_NW_SE_SOLID
6675                 || fd->cmd.func == FloorData::CEILING_NE_SW_PORTAL_SW
6676                 || fd->cmd.func == FloorData::CEILING_NE_SW_PORTAL_NE
6677                 || fd->cmd.func == FloorData::CEILING_NW_SE_PORTAL_SE
6678                 || fd->cmd.func == FloorData::CEILING_NW_SE_PORTAL_NW) {
6679 
6680                 if (fd->cmd.end) return NO_ROOM;
6681                 fd += 2;
6682             }
6683 
6684             if (fd->cmd.func == FloorData::PORTAL)
6685                 return (++fd)->value;
6686 
6687             return NO_ROOM;
6688         }
6689 
getSectorLevel6690         Room::Sector& getSector(int roomIndex, int x, int z, int &dx, int &dz) const {
6691             ASSERT(roomIndex >= 0 && roomIndex < roomsCount);
6692 
6693             Room &room = rooms[roomIndex];
6694 
6695             int sx = x - room.info.x;
6696             int sz = z - room.info.z;
6697 
6698             sx = clamp(sx, 0, room.xSectors * 1024 - 1);
6699             sz = clamp(sz, 0, room.zSectors * 1024 - 1);
6700 
6701             dx = sx % 1024;
6702             dz = sz % 1024;
6703             sx /= 1024;
6704             sz /= 1024;
6705 
6706             return room.sectors[sx * room.zSectors + sz];
6707         }
6708 
getSectorLevel6709         Room::Sector& getSector(int roomIndex, int x, int z, int &sectorIndex) {
6710             ASSERT(roomIndex >= 0 && roomIndex < roomsCount);
6711             Room &room = rooms[roomIndex];
6712             x -= room.info.x;
6713             z -= room.info.z;
6714             x /= 1024;
6715             z /= 1024;
6716             return room.sectors[sectorIndex = (x * room.zSectors + z)];
6717         }
6718 
getSectorLevel6719         Room::Sector* getSector(int16 &roomIndex, const vec3 &pos) {
6720             ASSERT(roomIndex >= 0 && roomIndex <= roomsCount);
6721 
6722             Room::Sector *sector = NULL;
6723 
6724             int x = int(pos.x);
6725             int y = int(pos.y);
6726             int z = int(pos.z);
6727 
6728         // check horizontal
6729             int16 prevRoom = roomIndex;
6730 
6731             while (1) { // Let's Rock!
6732                 Room &room = rooms[roomIndex];
6733 
6734                 int sx = (x - room.info.x) / 1024;
6735                 int sz = (z - room.info.z) / 1024;
6736                 sector = room.getSector(sx, sz);
6737 
6738                 int nextRoom = getNextRoom(sector);
6739                 if (nextRoom == NO_ROOM || nextRoom == prevRoom)
6740                     break;
6741 
6742                 prevRoom  = roomIndex;
6743                 roomIndex = nextRoom;
6744             };
6745 
6746         // check vertical
6747             while (sector->roomAbove != NO_ROOM && y < sector->ceiling * 256) {
6748                 Room &room = rooms[roomIndex = sector->roomAbove];
6749                 sector = room.getSector((x - room.info.x) / 1024, (z - room.info.z) / 1024);
6750             }
6751 
6752             while (sector->roomBelow != NO_ROOM && y >= sector->floor * 256) {
6753                 Room &room = rooms[roomIndex = sector->roomBelow];
6754                 sector = room.getSector((x - room.info.x) / 1024, (z - room.info.z) / 1024);
6755             }
6756 
6757             return sector;
6758         }
6759 
6760         float getFloor(const Room::Sector *sector, const vec3 &pos, int16 *roomIndex = NULL) {
6761             int x = int(pos.x);
6762             int z = int(pos.z);
6763             int dx = x & 1023;
6764             int dz = z & 1023;
6765 
6766             while (sector->roomBelow != NO_ROOM) {
6767                 Room &room = rooms[sector->roomBelow];
6768                 if (roomIndex)
6769                     *roomIndex = sector->roomBelow;
6770                 sector = room.getSector((x - room.info.x) / 1024, (z - room.info.z) / 1024);
6771             }
6772 
6773             int floor = sector->floor * 256;
6774 
6775             if (!sector->floorIndex)
6776                 return float(floor);
6777 
6778             FloorData *fd = &floors[sector->floorIndex];
6779             FloorData::Command cmd;
6780 
6781             do {
6782                 cmd = (*fd++).cmd;
6783 
6784                 switch (cmd.func) {
6785                     case TR::FloorData::FLOOR                 :
6786                     case TR::FloorData::FLOOR_NW_SE_SOLID     :
6787                     case TR::FloorData::FLOOR_NE_SW_SOLID     :
6788                     case TR::FloorData::FLOOR_NW_SE_PORTAL_SE :
6789                     case TR::FloorData::FLOOR_NW_SE_PORTAL_NW :
6790                     case TR::FloorData::FLOOR_NE_SW_PORTAL_SW :
6791                     case TR::FloorData::FLOOR_NE_SW_PORTAL_NE : {
6792                         int sx, sz;
6793 
6794                         if (cmd.func == TR::FloorData::FLOOR) {
6795                             sx = fd->slantX;
6796                             sz = fd->slantZ;
6797                         } else {
6798                             if (cmd.func == TR::FloorData::FLOOR_NW_SE_SOLID     ||
6799                                 cmd.func == TR::FloorData::FLOOR_NW_SE_PORTAL_SE ||
6800                                 cmd.func == TR::FloorData::FLOOR_NW_SE_PORTAL_NW) {
6801                                 if (dx <= 1024 - dz) {
6802                                     floor += cmd.triangle.b * 256;
6803                                     sx = fd->a - fd->b;
6804                                     sz = fd->c - fd->b;
6805                                 } else {
6806                                     floor += cmd.triangle.a * 256;
6807                                     sx = fd->d - fd->c;
6808                                     sz = fd->d - fd->a;
6809                                 }
6810                             } else {
6811                                 if (dx <= dz) {
6812                                     floor += cmd.triangle.b * 256;
6813                                     sx = fd->d - fd->c;
6814                                     sz = fd->c - fd->b;
6815                                 } else {
6816                                     floor += cmd.triangle.a * 256;
6817                                     sx = fd->a - fd->b;
6818                                     sz = fd->d - fd->a;
6819                                 }
6820                             }
6821                         }
6822                         fd++;
6823 
6824                         floor -= sx * (sx > 0 ? (dx - 1023) : dx) >> 2;
6825                         floor -= sz * (sz > 0 ? (dz - 1023) : dz) >> 2;
6826                         break;
6827                     }
6828 
6829                     case FloorData::TRIGGER :  {
6830                         fd++;
6831                         FloorData::TriggerCommand trigCmd;
6832                         do {
6833                             trigCmd = (*fd++).triggerCmd;
6834                             if (trigCmd.action != Action::ACTIVATE)
6835                                 continue;
6836                             // TODO controller[trigCmd.args]->getFloor(&floor, x, y, z);
6837                         } while (!trigCmd.end);
6838                         break;
6839                     }
6840 
6841                     default : floorSkipCommand(fd, cmd.func);
6842                 }
6843             } while (!cmd.end);
6844 
6845             return float(floor);
6846         }
6847 
getCeilingLevel6848         float getCeiling(const Room::Sector *sector, const vec3 &pos) {
6849             int x = int(pos.x);
6850             int z = int(pos.z);
6851             int dx = x & 1023;
6852             int dz = z & 1023;
6853 
6854             ASSERT(sector);
6855             while (sector->roomAbove != NO_ROOM) {
6856                 Room &room = rooms[sector->roomAbove];
6857                 sector = room.getSector((x - room.info.x) / 1024, (z - room.info.z) / 1024);
6858             }
6859 
6860             int ceiling = sector->ceiling * 256;
6861 
6862             if (!sector->floorIndex)
6863                 return float(ceiling);
6864 
6865             FloorData *fd = &floors[sector->floorIndex];
6866             FloorData::Command cmd;
6867 
6868             do {
6869                 cmd = (*fd++).cmd;
6870 
6871                 switch (cmd.func) {
6872                     case TR::FloorData::CEILING                 :
6873                     case TR::FloorData::CEILING_NE_SW_SOLID     :
6874                     case TR::FloorData::CEILING_NW_SE_SOLID     :
6875                     case TR::FloorData::CEILING_NE_SW_PORTAL_SW :
6876                     case TR::FloorData::CEILING_NE_SW_PORTAL_NE :
6877                     case TR::FloorData::CEILING_NW_SE_PORTAL_SE :
6878                     case TR::FloorData::CEILING_NW_SE_PORTAL_NW : {
6879                         int sx, sz;
6880 
6881                         if (cmd.func == TR::FloorData::CEILING) {
6882                             sx = fd->slantX;
6883                             sz = fd->slantZ;
6884                         } else {
6885                             if (cmd.func == TR::FloorData::CEILING_NW_SE_SOLID     ||
6886                                 cmd.func == TR::FloorData::CEILING_NW_SE_PORTAL_SE ||
6887                                 cmd.func == TR::FloorData::CEILING_NW_SE_PORTAL_NW) {
6888                                 if (dx <= 1024 - dz) {
6889                                     ceiling += cmd.triangle.b * 256;
6890                                     sx = fd->c - fd->d;
6891                                     sz = fd->b - fd->c;
6892                                 } else {
6893                                     ceiling += cmd.triangle.a * 256;
6894                                     sx = fd->b - fd->a;
6895                                     sz = fd->a - fd->d;
6896                                 }
6897                             } else {
6898                                 if (dx <= dz) {
6899                                     ceiling += cmd.triangle.b * 256;
6900                                     sx = fd->b - fd->a;
6901                                     sz = fd->b - fd->c;
6902                                 } else {
6903                                     ceiling += cmd.triangle.a * 256;
6904                                     sx = fd->c - fd->d;
6905                                     sz = fd->a - fd->d;
6906                                 }
6907                             }
6908                         }
6909                         fd++;
6910 
6911                         ceiling -= sx * (sx < 0 ? (dx - 1023) : dx) >> 2;
6912                         ceiling += sz * (sz > 0 ? (dz - 1023) : dz) >> 2;
6913                         break;
6914                     }
6915 
6916                     case FloorData::TRIGGER :  {
6917                         fd++;
6918                         FloorData::TriggerCommand trigCmd;
6919                         do {
6920                             trigCmd = (*fd++).triggerCmd;
6921                             if (trigCmd.action != Action::ACTIVATE)
6922                                 continue;
6923                             // TODO controller[trigCmd.args]->getCeiling(&ceiling, x, y, z);
6924                         } while (!trigCmd.end);
6925                         break;
6926                     }
6927 
6928                     default : floorSkipCommand(fd, cmd.func);
6929                 }
6930             } while (!cmd.end);
6931 
6932             return float(ceiling);
6933         }
6934 
getWaterLevelSectorLevel6935         Room::Sector* getWaterLevelSector(int16 &roomIndex, const vec3 &pos) {
6936             int x = int(pos.x);
6937             int z = int(pos.z);
6938 
6939             Room *room = &rooms[roomIndex];
6940             Room::Sector *sector = room->getSector((x - room->info.x) / 1024, (z - room->info.z) / 1024);
6941 
6942             if (room->flags.water) { // go up to the air
6943                 while (sector->roomAbove != NO_ROOM) {
6944                     room = &rooms[sector->roomAbove];
6945                     if (!room->flags.water)
6946                         return sector;
6947                     roomIndex = sector->roomAbove;
6948                     sector = room->getSector((x - room->info.x) / 1024, (z - room->info.z) / 1024);
6949                 }
6950             } else { // go down to the water
6951                 while (sector->roomBelow != NO_ROOM) {
6952                     room   = &rooms[roomIndex = sector->roomBelow];
6953                     sector = room->getSector((x - room->info.x) / 1024, (z - room->info.z) / 1024);
6954                     if (room->flags.water)
6955                         return sector;
6956                 }
6957             }
6958             return NULL;
6959         }
6960 
getWaterInfoLevel6961         void getWaterInfo(int16 roomIndex, const vec3 &pos, float &level, float &depth) {
6962             depth = 0.0f;
6963             level = 0.0f;
6964 
6965             Room::Sector *sector = getWaterLevelSector(roomIndex, pos);
6966             if (!sector)
6967                 return;
6968 
6969             level = sector->ceiling * 256.0f;
6970 
6971             if (pos.y < level)
6972                 depth = pos.y - level;
6973             else
6974                 depth = getFloor(sector, pos) - level;
6975         }
6976 
isBlockedLevel6977         bool isBlocked(int16 &roomIndex, const vec3 &pos) {
6978             Room::Sector *sector = getSector(roomIndex, pos);
6979             return pos.y >= getFloor(sector, pos) || pos.y <= getCeiling(sector, pos);
6980         }
6981 
6982     }; // struct Level
6983 }
6984 
6985 #endif
6986