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 §orIndex) { 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