mirror of
https://github.com/XProger/OpenLara.git
synced 2025-03-14 16:19:41 +01:00
#15 easy start feature (WIP)
This commit is contained in:
parent
58f6188c1d
commit
e99e23a724
487
src/format.h
487
src/format.h
@ -2,6 +2,7 @@
|
|||||||
#define H_FORMAT
|
#define H_FORMAT
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "gameflow.h"
|
||||||
|
|
||||||
#define MAX_RESERVED_ENTITIES 128
|
#define MAX_RESERVED_ENTITIES 128
|
||||||
#define MAX_FLIPMAP_COUNT 32
|
#define MAX_FLIPMAP_COUNT 32
|
||||||
@ -850,281 +851,13 @@
|
|||||||
|
|
||||||
namespace TR {
|
namespace TR {
|
||||||
|
|
||||||
enum Version : uint32 {
|
|
||||||
VER_UNKNOWN = 0,
|
|
||||||
|
|
||||||
VER_PC = 256,
|
|
||||||
VER_PSX = 512,
|
|
||||||
VER_SEGA = 1024,
|
|
||||||
|
|
||||||
VER_TR1 = 1,
|
|
||||||
VER_TR2 = 2,
|
|
||||||
VER_TR3 = 4,
|
|
||||||
VER_TR4 = 8,
|
|
||||||
VER_TR5 = 16,
|
|
||||||
|
|
||||||
VER_VERSION = VER_TR1 | VER_TR2 | VER_TR3 | VER_TR4 | VER_TR5,
|
|
||||||
VER_PLATFORM = VER_PC | VER_PSX | VER_SEGA,
|
|
||||||
|
|
||||||
VER_TR1_PC = VER_TR1 | VER_PC,
|
|
||||||
VER_TR1_PSX = VER_TR1 | VER_PSX,
|
|
||||||
VER_TR1_SEGA = VER_TR1 | VER_SEGA,
|
|
||||||
|
|
||||||
VER_TR2_PC = VER_TR2 | VER_PC,
|
|
||||||
VER_TR2_PSX = VER_TR2 | VER_PSX,
|
|
||||||
VER_TR3_PC = VER_TR3 | VER_PC,
|
|
||||||
VER_TR3_PSX = VER_TR3 | VER_PSX,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NO_FLOOR = -127,
|
NO_FLOOR = -127,
|
||||||
NO_ROOM = 0xFF,
|
NO_ROOM = 0xFF,
|
||||||
NO_BOX = 0xFFFF,
|
NO_BOX = 0xFFFF,
|
||||||
NO_TRACK = 0xFF,
|
|
||||||
ACTIVE = 0x1F,
|
ACTIVE = 0x1F,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LevelID : uint32 {
|
|
||||||
LVL_CUSTOM,
|
|
||||||
// TR1
|
|
||||||
LVL_TR1_TITLE,
|
|
||||||
LVL_TR1_GYM,
|
|
||||||
LVL_TR1_1,
|
|
||||||
LVL_TR1_2,
|
|
||||||
LVL_TR1_3A,
|
|
||||||
LVL_TR1_3B,
|
|
||||||
LVL_TR1_CUT_1,
|
|
||||||
LVL_TR1_4,
|
|
||||||
LVL_TR1_5,
|
|
||||||
LVL_TR1_6,
|
|
||||||
LVL_TR1_7A,
|
|
||||||
LVL_TR1_7B,
|
|
||||||
LVL_TR1_CUT_2,
|
|
||||||
LVL_TR1_8A,
|
|
||||||
LVL_TR1_8B,
|
|
||||||
LVL_TR1_8C,
|
|
||||||
LVL_TR1_10A,
|
|
||||||
LVL_TR1_CUT_3,
|
|
||||||
LVL_TR1_10B,
|
|
||||||
LVL_TR1_CUT_4,
|
|
||||||
LVL_TR1_10C,
|
|
||||||
LVL_TR1_EGYPT,
|
|
||||||
LVL_TR1_CAT,
|
|
||||||
LVL_TR1_END,
|
|
||||||
LVL_TR1_END2,
|
|
||||||
// TR2
|
|
||||||
LVL_TR2_TITLE,
|
|
||||||
LVL_TR2_ASSAULT,
|
|
||||||
LVL_TR2_WALL,
|
|
||||||
LVL_TR2_CUT_1,
|
|
||||||
LVL_TR2_BOAT,
|
|
||||||
LVL_TR2_VENICE,
|
|
||||||
LVL_TR2_OPERA,
|
|
||||||
LVL_TR2_CUT_2,
|
|
||||||
LVL_TR2_RIG,
|
|
||||||
LVL_TR2_PLATFORM,
|
|
||||||
LVL_TR2_CUT_3,
|
|
||||||
LVL_TR2_UNWATER,
|
|
||||||
LVL_TR2_KEEL,
|
|
||||||
LVL_TR2_LIVING,
|
|
||||||
LVL_TR2_DECK,
|
|
||||||
LVL_TR2_SKIDOO,
|
|
||||||
LVL_TR2_MONASTRY,
|
|
||||||
LVL_TR2_CATACOMB,
|
|
||||||
LVL_TR2_ICECAVE,
|
|
||||||
LVL_TR2_EMPRTOMB,
|
|
||||||
LVL_TR2_FLOATING,
|
|
||||||
LVL_TR2_CUT_4,
|
|
||||||
LVL_TR2_XIAN,
|
|
||||||
LVL_TR2_HOUSE,
|
|
||||||
// TR3
|
|
||||||
LVL_TR3_TITLE,
|
|
||||||
LVL_TR3_HOUSE,
|
|
||||||
LVL_TR3_JUNGLE,
|
|
||||||
LVL_TR3_CUT_6,
|
|
||||||
LVL_TR3_TEMPLE,
|
|
||||||
LVL_TR3_CUT_9,
|
|
||||||
LVL_TR3_QUADCHAS,
|
|
||||||
LVL_TR3_TONYBOSS,
|
|
||||||
LVL_TR3_SHORE,
|
|
||||||
LVL_TR3_CUT_1,
|
|
||||||
LVL_TR3_CRASH,
|
|
||||||
LVL_TR3_CUT_4,
|
|
||||||
LVL_TR3_RAPIDS,
|
|
||||||
LVL_TR3_TRIBOSS,
|
|
||||||
LVL_TR3_ROOFS,
|
|
||||||
LVL_TR3_CUT_2,
|
|
||||||
LVL_TR3_SEWER,
|
|
||||||
LVL_TR3_CUT_5,
|
|
||||||
LVL_TR3_TOWER,
|
|
||||||
LVL_TR3_CUT_11,
|
|
||||||
LVL_TR3_OFFICE,
|
|
||||||
LVL_TR3_NEVADA,
|
|
||||||
LVL_TR3_CUT_7,
|
|
||||||
LVL_TR3_COMPOUND,
|
|
||||||
LVL_TR3_CUT_8,
|
|
||||||
LVL_TR3_AREA51,
|
|
||||||
LVL_TR3_ANTARC,
|
|
||||||
LVL_TR3_CUT_3,
|
|
||||||
LVL_TR3_MINES,
|
|
||||||
LVL_TR3_CITY,
|
|
||||||
LVL_TR3_CUT_12,
|
|
||||||
LVL_TR3_CHAMBER,
|
|
||||||
LVL_TR3_STPAUL,
|
|
||||||
|
|
||||||
LVL_MAX,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
// TR1
|
|
||||||
TRACK_TR1_TITLE = 2,
|
|
||||||
TRACK_TR1_CAVES = 5,
|
|
||||||
TRACK_TR1_SECRET = 13,
|
|
||||||
TRACK_TR1_CISTERN = 57,
|
|
||||||
TRACK_TR1_EGYPT = 58,
|
|
||||||
TRACK_TR1_MINE = 59,
|
|
||||||
TRACK_TR1_CUT_1 = 23,
|
|
||||||
TRACK_TR1_CUT_2 = 25,
|
|
||||||
TRACK_TR1_CUT_3 = 24,
|
|
||||||
TRACK_TR1_CUT_4 = 22,
|
|
||||||
// TR2
|
|
||||||
TRACK_TR2_TITLE = 64,
|
|
||||||
TRACK_TR2_CHINA_1 = 33,
|
|
||||||
TRACK_TR2_CHINA_2 = 59,
|
|
||||||
TRACK_TR2_ITALY = 31,
|
|
||||||
TRACK_TR2_RIG = 58,
|
|
||||||
TRACK_TR2_UNWATER_1 = 34,
|
|
||||||
TRACK_TR2_UNWATER_2 = 31,
|
|
||||||
TRACK_TR2_TIBET_1 = 33,
|
|
||||||
TRACK_TR2_TIBET_2 = 31,
|
|
||||||
TRACK_TR2_CUT_1 = 3,
|
|
||||||
TRACK_TR2_CUT_2 = 4,
|
|
||||||
TRACK_TR2_CUT_3 = 5,
|
|
||||||
TRACK_TR2_CUT_4 = 30,
|
|
||||||
// TR3
|
|
||||||
TRACK_TR3_TITLE = 5,
|
|
||||||
TRACK_TR3_HOUSE = 2,
|
|
||||||
TRACK_TR3_CAVES = 30,
|
|
||||||
TRACK_TR3_INDIA_1 = 34,
|
|
||||||
TRACK_TR3_INDIA_2 = 30,
|
|
||||||
TRACK_TR3_SOUTH_1 = 32,
|
|
||||||
TRACK_TR3_SOUTH_2 = 33,
|
|
||||||
TRACK_TR3_SOUTH_3 = 36,
|
|
||||||
TRACK_TR3_LONDON_1 = 73,
|
|
||||||
TRACK_TR3_LONDON_2 = 74,
|
|
||||||
TRACK_TR3_LONDON_3 = 31,
|
|
||||||
TRACK_TR3_LONDON_4 = 78,
|
|
||||||
TRACK_TR3_NEVADA_1 = 33,
|
|
||||||
TRACK_TR3_NEVADA_2 = 27,
|
|
||||||
TRACK_TR3_ANTARC_1 = 28,
|
|
||||||
TRACK_TR3_ANTARC_2 = 30,
|
|
||||||
TRACK_TR3_ANTARC_3 = 26,
|
|
||||||
TRACK_TR3_CUT_1 = 68,
|
|
||||||
TRACK_TR3_CUT_2 = 67,
|
|
||||||
TRACK_TR3_CUT_3 = 62,
|
|
||||||
TRACK_TR3_CUT_4 = 65,
|
|
||||||
TRACK_TR3_CUT_5 = 63,
|
|
||||||
TRACK_TR3_CUT_6 = 64,
|
|
||||||
TRACK_TR3_CUT_7 = 72,
|
|
||||||
TRACK_TR3_CUT_8 = 70,
|
|
||||||
TRACK_TR3_CUT_9 = 69,
|
|
||||||
TRACK_TR3_CUT_11 = 71,
|
|
||||||
TRACK_TR3_CUT_12 = 66,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
const char *title;
|
|
||||||
int ambientTrack;
|
|
||||||
} LEVEL_INFO[LVL_MAX] = {
|
|
||||||
// TR1
|
|
||||||
{ "" , "Custom Level", TRACK_TR1_CAVES },
|
|
||||||
{ "TITLE" , "", TRACK_TR1_TITLE },
|
|
||||||
{ "GYM" , "Lara's Home", NO_TRACK },
|
|
||||||
{ "LEVEL1" , "Caves", TRACK_TR1_CAVES },
|
|
||||||
{ "LEVEL2" , "City of Vilcabamba", TRACK_TR1_CAVES },
|
|
||||||
{ "LEVEL3A" , "Lost Valley", TRACK_TR1_CAVES },
|
|
||||||
{ "LEVEL3B" , "Tomb of Qualopec", TRACK_TR1_CAVES },
|
|
||||||
{ "CUT1" , "", TRACK_TR1_CUT_1 },
|
|
||||||
{ "LEVEL4" , "St. Francis' Folly", TRACK_TR1_CAVES },
|
|
||||||
{ "LEVEL5" , "Colosseum", TRACK_TR1_CAVES },
|
|
||||||
{ "LEVEL6" , "Palace Midas", TRACK_TR1_CAVES },
|
|
||||||
{ "LEVEL7A" , "The Cistern", TRACK_TR1_CISTERN },
|
|
||||||
{ "LEVEL7B" , "Tomb of Tihocan", TRACK_TR1_CISTERN },
|
|
||||||
{ "CUT2" , "", TRACK_TR1_CUT_2 },
|
|
||||||
{ "LEVEL8A" , "City of Khamoon", TRACK_TR1_EGYPT },
|
|
||||||
{ "LEVEL8B" , "Obelisk of Khamoon", TRACK_TR1_EGYPT },
|
|
||||||
{ "LEVEL8C" , "Sanctuary of the Scion", TRACK_TR1_EGYPT },
|
|
||||||
{ "LEVEL10A" , "Natla's Mines", TRACK_TR1_MINE },
|
|
||||||
{ "CUT3" , "", TRACK_TR1_CUT_3 },
|
|
||||||
{ "LEVEL10B" , "Atlantis", TRACK_TR1_MINE },
|
|
||||||
{ "CUT4" , "", TRACK_TR1_CUT_4 },
|
|
||||||
{ "LEVEL10C" , "The Great Pyramid", TRACK_TR1_MINE },
|
|
||||||
{ "EGYPT" , "Return to Egypt", TRACK_TR1_EGYPT },
|
|
||||||
{ "CAT" , "Temple of the Cat", TRACK_TR1_EGYPT },
|
|
||||||
{ "END" , "Atlantean Stronghold", TRACK_TR1_EGYPT },
|
|
||||||
{ "END2" , "The Hive", TRACK_TR1_EGYPT },
|
|
||||||
// TR2
|
|
||||||
{ "TITLE" , "", TRACK_TR2_TITLE },
|
|
||||||
{ "ASSAULT" , "Lara's Home", NO_TRACK },
|
|
||||||
{ "WALL" , "The Great Wall", TRACK_TR2_CHINA_1 },
|
|
||||||
{ "CUT1" , "", TRACK_TR2_CUT_1 },
|
|
||||||
{ "BOAT" , "Venice", NO_TRACK },
|
|
||||||
{ "VENICE" , "Bartoli's Hideout", NO_TRACK },
|
|
||||||
{ "OPERA" , "Opera House", TRACK_TR2_ITALY },
|
|
||||||
{ "CUT2" , "", TRACK_TR2_CUT_2 },
|
|
||||||
{ "RIG" , "Offshore Rig", TRACK_TR2_RIG },
|
|
||||||
{ "PLATFORM" , "Diving Area", TRACK_TR2_RIG },
|
|
||||||
{ "CUT3" , "", TRACK_TR2_CUT_3 },
|
|
||||||
{ "UNWATER" , "40 Fathoms", TRACK_TR2_UNWATER_1 },
|
|
||||||
{ "KEEL" , "Wreck of the Maria Doria", TRACK_TR2_UNWATER_2 },
|
|
||||||
{ "LIVING" , "Living Quarters", TRACK_TR2_UNWATER_1 },
|
|
||||||
{ "DECK" , "The Deck", TRACK_TR2_UNWATER_2 },
|
|
||||||
{ "SKIDOO" , "Tibetan Foothills", TRACK_TR2_TIBET_1 },
|
|
||||||
{ "MONASTRY" , "Barkhang Monastery", NO_TRACK },
|
|
||||||
{ "CATACOMB" , "Catacombs of the Talion", TRACK_TR2_TIBET_2 },
|
|
||||||
{ "ICECAVE" , "Ice Palace", TRACK_TR2_TIBET_2 },
|
|
||||||
{ "EMPRTOMB" , "Temple of Xian", TRACK_TR2_CHINA_2 },
|
|
||||||
{ "FLOATING" , "Floating Islands", TRACK_TR2_CHINA_2 },
|
|
||||||
{ "CUT4" , "", TRACK_TR2_CUT_4 },
|
|
||||||
{ "XIAN" , "The Dragon's Lair", TRACK_TR2_CHINA_2 },
|
|
||||||
{ "HOUSE" , "Home Sweet Home", NO_TRACK },
|
|
||||||
// TR3
|
|
||||||
{ "TITLE", "", TRACK_TR3_TITLE },
|
|
||||||
{ "HOUSE", "Lara's House", NO_TRACK },
|
|
||||||
{ "JUNGLE", "Jungle", TRACK_TR3_INDIA_1 },
|
|
||||||
{ "CUT6", "", TRACK_TR3_CUT_6 },
|
|
||||||
{ "TEMPLE", "Temple Ruins", TRACK_TR3_INDIA_1 },
|
|
||||||
{ "CUT9", "", TRACK_TR3_CUT_9 },
|
|
||||||
{ "QUADCHAS", "The River Ganges", TRACK_TR3_INDIA_1 },
|
|
||||||
{ "TONYBOSS", "Caves Of Kaliya", TRACK_TR3_INDIA_2 },
|
|
||||||
{ "SHORE", "Coastal Village", TRACK_TR3_SOUTH_1 },
|
|
||||||
{ "CUT1", "", TRACK_TR3_CUT_1 },
|
|
||||||
{ "CRASH", "Crash Site", TRACK_TR3_SOUTH_2 },
|
|
||||||
{ "CUT4", "", TRACK_TR3_CUT_4 },
|
|
||||||
{ "RAPIDS", "Madubu Gorge", TRACK_TR3_SOUTH_3 },
|
|
||||||
{ "TRIBOSS", "Temple Of Puna", TRACK_TR3_CAVES },
|
|
||||||
{ "ROOFS", "Thames Wharf", TRACK_TR3_LONDON_1 },
|
|
||||||
{ "CUT2", "", TRACK_TR3_CUT_2 },
|
|
||||||
{ "SEWER", "Aldwych", TRACK_TR3_LONDON_2 },
|
|
||||||
{ "CUT5", "", TRACK_TR3_CUT_5 },
|
|
||||||
{ "TOWER", "Lud's Gate", TRACK_TR3_LONDON_3 },
|
|
||||||
{ "CUT11", "", TRACK_TR3_CUT_11 },
|
|
||||||
{ "OFFICE", "City", TRACK_TR3_LONDON_4 },
|
|
||||||
{ "NEVADA", "Nevada Desert", TRACK_TR3_NEVADA_1 },
|
|
||||||
{ "CUT7", "", TRACK_TR3_CUT_7 },
|
|
||||||
{ "COMPOUND", "High Security Compound", TRACK_TR3_NEVADA_2 },
|
|
||||||
{ "CUT8", "", TRACK_TR3_CUT_8 },
|
|
||||||
{ "AREA51", "Area 51", TRACK_TR3_NEVADA_2 },
|
|
||||||
{ "ANTARC", "Antarctica", TRACK_TR3_ANTARC_1 },
|
|
||||||
{ "CUT3", "", TRACK_TR3_CUT_3 },
|
|
||||||
{ "MINES", "RX-Tech Mines", TRACK_TR3_ANTARC_2 },
|
|
||||||
{ "CITY", "Lost City Of Tinnos", TRACK_TR3_ANTARC_3 },
|
|
||||||
{ "CUT12", "", TRACK_TR3_CUT_12 },
|
|
||||||
{ "CHAMBER", "Meteorite Cavern", TRACK_TR3_ANTARC_3 },
|
|
||||||
{ "STPAUL", "All Hallows", TRACK_TR3_CAVES },
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ANIM_CMD_NONE ,
|
ANIM_CMD_NONE ,
|
||||||
ANIM_CMD_OFFSET ,
|
ANIM_CMD_OFFSET ,
|
||||||
@ -2560,7 +2293,6 @@ namespace TR {
|
|||||||
int cutEntity;
|
int cutEntity;
|
||||||
mat4 cutMatrix;
|
mat4 cutMatrix;
|
||||||
bool isDemoLevel;
|
bool isDemoLevel;
|
||||||
bool isHomeLevel;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int16 muzzleFlash;
|
int16 muzzleFlash;
|
||||||
@ -2619,7 +2351,7 @@ namespace TR {
|
|||||||
#define MAGIC_TR3_PC2 0xFF180038
|
#define MAGIC_TR3_PC2 0xFF180038
|
||||||
#define MAGIC_TR3_PC3 0xFF180034
|
#define MAGIC_TR3_PC3 0xFF180034
|
||||||
|
|
||||||
id = getLevelID(stream.size);
|
id = TR::getLevelID(stream.size, version, isDemoLevel);
|
||||||
|
|
||||||
if (version == VER_UNKNOWN || version == VER_TR1_PSX) {
|
if (version == VER_UNKNOWN || version == VER_TR1_PSX) {
|
||||||
stream.read(magic);
|
stream.read(magic);
|
||||||
@ -2876,7 +2608,7 @@ namespace TR {
|
|||||||
|
|
||||||
if (version == VER_TR2_PC || version == VER_TR3_PC) {
|
if (version == VER_TR2_PC || version == VER_TR3_PC) {
|
||||||
stream.read(soundOffsets, stream.read(soundOffsetsCount));
|
stream.read(soundOffsets, stream.read(soundOffsetsCount));
|
||||||
new Stream(version == VER_TR2_PC ? "audio/2/MAIN.SFX" : "audio/3/MAIN.SFX", sfxLoadAsync, this);
|
new Stream(getGameSoundsFile(version), sfxLoadAsync, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cinematic frames for cameras (PSX)
|
// cinematic frames for cameras (PSX)
|
||||||
@ -2953,179 +2685,6 @@ namespace TR {
|
|||||||
delete[] soundSize;
|
delete[] soundSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelID getLevelID(int size) {
|
|
||||||
isDemoLevel = false;
|
|
||||||
isHomeLevel = false;
|
|
||||||
switch (size) {
|
|
||||||
// TR1
|
|
||||||
case 508614 : version = VER_TR1_PSX;
|
|
||||||
case 316138 :
|
|
||||||
case 316460 : return LVL_TR1_TITLE;
|
|
||||||
case 1074234 : version = VER_TR1_PSX;
|
|
||||||
case 3236806 :
|
|
||||||
case 3237128 : isHomeLevel = true; return LVL_TR1_GYM;
|
|
||||||
case 1448896 : version = VER_TR1_PSX;
|
|
||||||
case 2533312 :
|
|
||||||
case 2533634 : return LVL_TR1_1;
|
|
||||||
case 2873406 : isDemoLevel = true; return LVL_TR1_2;
|
|
||||||
case 1535734 : version = VER_TR1_PSX;
|
|
||||||
case 2873128 :
|
|
||||||
case 2873450 : return LVL_TR1_2;
|
|
||||||
case 1630560 : version = VER_TR1_PSX;
|
|
||||||
case 2934408 :
|
|
||||||
case 2934730 : return LVL_TR1_3A;
|
|
||||||
case 1506614 : version = VER_TR1_PSX;
|
|
||||||
case 2737936 :
|
|
||||||
case 2738258 : return LVL_TR1_3B;
|
|
||||||
case 722402 : version = VER_TR1_PSX;
|
|
||||||
case 599840 : return LVL_TR1_CUT_1;
|
|
||||||
case 1621970 : version = VER_TR1_PSX;
|
|
||||||
case 3030550 :
|
|
||||||
case 3030872 : return LVL_TR1_4;
|
|
||||||
case 1585942 : version = VER_TR1_PSX;
|
|
||||||
case 2718218 :
|
|
||||||
case 2718540 : return LVL_TR1_5;
|
|
||||||
case 1708464 : version = VER_TR1_PSX;
|
|
||||||
case 3139590 :
|
|
||||||
case 3074376 : return LVL_TR1_6;
|
|
||||||
case 1696664 : version = VER_TR1_PSX;
|
|
||||||
case 2817290 :
|
|
||||||
case 2817612 : return LVL_TR1_7A;
|
|
||||||
case 1733274 : version = VER_TR1_PSX;
|
|
||||||
case 3388774 :
|
|
||||||
case 3389096 : return LVL_TR1_7B;
|
|
||||||
case 542960 : version = VER_TR1_PSX;
|
|
||||||
case 354320 : return LVL_TR1_CUT_2;
|
|
||||||
case 1563356 : version = VER_TR1_PSX;
|
|
||||||
case 2880242 :
|
|
||||||
case 2880564 : return LVL_TR1_8A;
|
|
||||||
case 1565630 : version = VER_TR1_PSX;
|
|
||||||
case 2886434 :
|
|
||||||
case 2886756 : return LVL_TR1_8B;
|
|
||||||
case 1619360 : version = VER_TR1_PSX;
|
|
||||||
case 3105128 :
|
|
||||||
case 3105450 : return LVL_TR1_8C;
|
|
||||||
case 1678018 : version = VER_TR1_PSX;
|
|
||||||
case 3223816 :
|
|
||||||
case 3224138 : return LVL_TR1_10A;
|
|
||||||
case 636660 : version = VER_TR1_PSX;
|
|
||||||
case 512104 : return LVL_TR1_CUT_3;
|
|
||||||
case 1686748 : version = VER_TR1_PSX;
|
|
||||||
case 3094020 : return LVL_TR1_10B;
|
|
||||||
case 940398 : version = VER_TR1_PSX;
|
|
||||||
case 879582 : return LVL_TR1_CUT_4;
|
|
||||||
case 1814278 : version = VER_TR1_PSX;
|
|
||||||
case 3531702 :
|
|
||||||
case 3532024 : return LVL_TR1_10C;
|
|
||||||
case 3278614 : version = VER_TR1_PSX;
|
|
||||||
case 3279242 : return LVL_TR1_EGYPT;
|
|
||||||
case 3270370 : version = VER_TR1_PSX;
|
|
||||||
case 3270998 : return LVL_TR1_CAT;
|
|
||||||
case 3208018 : return LVL_TR1_END;
|
|
||||||
case 3153300 : return LVL_TR1_END2;
|
|
||||||
// TR2
|
|
||||||
case 148744 : version = VER_TR2_PSX;
|
|
||||||
case 611892 : return LVL_TR2_TITLE;
|
|
||||||
case 1565974 : version = VER_TR2_PSX;
|
|
||||||
case 3471450 : isHomeLevel = true; return LVL_TR2_ASSAULT;
|
|
||||||
case 1661622 : version = VER_TR2_PSX;
|
|
||||||
case 2986356 : return LVL_TR2_WALL;
|
|
||||||
case 2014880 : version = VER_TR2_PSX;
|
|
||||||
case 2010678 : version = VER_TR2_PSX; // PLAYABLE.PSX
|
|
||||||
case 3945738 : return LVL_TR2_BOAT;
|
|
||||||
case 2081402 : version = VER_TR2_PSX;
|
|
||||||
case 4213070 : return LVL_TR2_VENICE;
|
|
||||||
case 2060882 : version = VER_TR2_PSX;
|
|
||||||
case 3996500 : return LVL_TR2_OPERA;
|
|
||||||
case 1950216 : version = VER_TR2_PSX;
|
|
||||||
case 3944472 : return LVL_TR2_RIG;
|
|
||||||
case 1993070 : version = VER_TR2_PSX;
|
|
||||||
case 4101590 : return LVL_TR2_PLATFORM;
|
|
||||||
case 1784200 : version = VER_TR2_PSX;
|
|
||||||
case 3131814 : return LVL_TR2_UNWATER;
|
|
||||||
case 2014110 : version = VER_TR2_PSX;
|
|
||||||
case 3995356 : return LVL_TR2_KEEL;
|
|
||||||
case 1808444 : version = VER_TR2_PSX;
|
|
||||||
case 3501472 : return LVL_TR2_LIVING;
|
|
||||||
case 1968084 : version = VER_TR2_PSX;
|
|
||||||
case 3890042 : return LVL_TR2_DECK;
|
|
||||||
case 1981902 : version = VER_TR2_PSX;
|
|
||||||
case 3521106 : return LVL_TR2_SKIDOO;
|
|
||||||
case 2120772 : version = VER_TR2_PSX;
|
|
||||||
case 4325562 : return LVL_TR2_MONASTRY;
|
|
||||||
case 1877970 : version = VER_TR2_PSX;
|
|
||||||
case 3605052 : return LVL_TR2_CATACOMB;
|
|
||||||
case 1987854 : version = VER_TR2_PSX;
|
|
||||||
case 3803398 : return LVL_TR2_ICECAVE;
|
|
||||||
case 2101594 : version = VER_TR2_PSX;
|
|
||||||
case 4291468 : return LVL_TR2_EMPRTOMB;
|
|
||||||
case 2078690 : version = VER_TR2_PSX;
|
|
||||||
case 4007486 : return LVL_TR2_FLOATING;
|
|
||||||
case 1748838 : version = VER_TR2_PSX;
|
|
||||||
case 3173840 : return LVL_TR2_XIAN;
|
|
||||||
case 1886728 : version = VER_TR2_PSX;
|
|
||||||
case 3693108 : return LVL_TR2_HOUSE;
|
|
||||||
case 952798 : version = VER_TR2_PSX;
|
|
||||||
case 1767052 : return LVL_TR2_CUT_1;
|
|
||||||
case 1098876 : version = VER_TR2_PSX;
|
|
||||||
case 2037544 : return LVL_TR2_CUT_2;
|
|
||||||
case 1288922 : version = VER_TR2_PSX;
|
|
||||||
case 2558286 : return LVL_TR2_CUT_3;
|
|
||||||
case 1116966 : version = VER_TR2_PSX;
|
|
||||||
case 1900230 : return LVL_TR2_CUT_4;
|
|
||||||
// TR3
|
|
||||||
case 1275266 : return LVL_TR3_TITLE;
|
|
||||||
case 3437855 : return LVL_TR3_HOUSE;
|
|
||||||
case 3360001 : return LVL_TR3_JUNGLE;
|
|
||||||
case 3180412 : return LVL_TR3_TEMPLE;
|
|
||||||
case 3131453 : return LVL_TR3_QUADCHAS;
|
|
||||||
case 2618437 : return LVL_TR3_TONYBOSS;
|
|
||||||
case 3365562 : return LVL_TR3_SHORE;
|
|
||||||
case 3331132 : return LVL_TR3_CRASH;
|
|
||||||
case 3148248 : return LVL_TR3_RAPIDS;
|
|
||||||
case 2276838 : return LVL_TR3_TRIBOSS;
|
|
||||||
case 3579476 : return LVL_TR3_ROOFS;
|
|
||||||
case 3670149 : return LVL_TR3_SEWER;
|
|
||||||
case 3523586 : return LVL_TR3_TOWER;
|
|
||||||
case 2504910 : return LVL_TR3_OFFICE;
|
|
||||||
case 3140417 : return LVL_TR3_NEVADA;
|
|
||||||
case 3554880 : return LVL_TR3_COMPOUND;
|
|
||||||
case 3530130 : return LVL_TR3_AREA51;
|
|
||||||
case 3515272 : return LVL_TR3_ANTARC;
|
|
||||||
case 3331087 : return LVL_TR3_MINES;
|
|
||||||
case 3575873 : return LVL_TR3_CITY;
|
|
||||||
case 3190736 : return LVL_TR3_CHAMBER;
|
|
||||||
case 3140028 : return LVL_TR3_STPAUL;
|
|
||||||
case 1547866 : return LVL_TR3_CUT_1;
|
|
||||||
case 1957327 : return LVL_TR3_CUT_2;
|
|
||||||
case 2020225 : return LVL_TR3_CUT_3;
|
|
||||||
case 1048466 : return LVL_TR3_CUT_4;
|
|
||||||
case 1580868 : return LVL_TR3_CUT_5;
|
|
||||||
case 2430940 : return LVL_TR3_CUT_6;
|
|
||||||
case 1253227 : return LVL_TR3_CUT_7;
|
|
||||||
case 944962 : return LVL_TR3_CUT_8;
|
|
||||||
case 1788075 : return LVL_TR3_CUT_9;
|
|
||||||
case 1402003 : return LVL_TR3_CUT_11;
|
|
||||||
case 2321393 : return LVL_TR3_CUT_12;
|
|
||||||
|
|
||||||
}
|
|
||||||
return LVL_CUSTOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 remapTrack(uint8 track) {
|
|
||||||
static const uint8 TR2_TRACK_MAPPING[] = {
|
|
||||||
2, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 18, 19, 20,
|
|
||||||
21, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
||||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
|
|
||||||
};
|
|
||||||
|
|
||||||
if (version & VER_TR2) {
|
|
||||||
ASSERT(track < COUNT(TR2_TRACK_MAPPING));
|
|
||||||
return TR2_TRACK_MAPPING[track];
|
|
||||||
}
|
|
||||||
return track;
|
|
||||||
}
|
|
||||||
|
|
||||||
void readSamples(Stream &stream) {
|
void readSamples(Stream &stream) {
|
||||||
stream.read(soundData, soundDataSize = stream.size);
|
stream.read(soundData, soundDataSize = stream.size);
|
||||||
|
|
||||||
@ -3258,43 +2817,19 @@ namespace TR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LevelID getTitleId() const {
|
LevelID getTitleId() const {
|
||||||
switch (version & VER_VERSION) {
|
return TR::getTitleId(version);
|
||||||
case VER_TR1 : return LVL_TR1_TITLE;
|
|
||||||
case VER_TR2 : return LVL_TR2_TITLE;
|
|
||||||
case VER_TR3 : return LVL_TR3_TITLE;
|
|
||||||
}
|
|
||||||
return LVL_TR1_TITLE;
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelID getHomeId() const {
|
LevelID getHomeId() const {
|
||||||
switch (version & VER_VERSION) {
|
return TR::getHomeId(version);
|
||||||
case VER_TR1 : return LVL_TR1_GYM;
|
|
||||||
case VER_TR2 : return LVL_TR2_ASSAULT;
|
|
||||||
case VER_TR3 : return LVL_TR3_HOUSE;
|
|
||||||
}
|
|
||||||
return LVL_TR1_TITLE;
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelID getStartId() const {
|
LevelID getStartId() const {
|
||||||
switch (version & VER_VERSION) {
|
return TR::getStartId(version);
|
||||||
case VER_TR1 : return LVL_TR1_1;
|
|
||||||
case VER_TR2 : return LVL_TR2_WALL;
|
|
||||||
case VER_TR3 : return LVL_TR3_JUNGLE;
|
|
||||||
}
|
|
||||||
return LVL_MAX;
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelID getEndId() const {
|
LevelID getEndId() const {
|
||||||
switch (version & VER_VERSION) {
|
return TR::getEndId(version);
|
||||||
case VER_TR1 : return LVL_TR1_10C;
|
|
||||||
case VER_TR2 : return LVL_TR2_HOUSE;
|
|
||||||
case VER_TR3 : return LVL_TR3_CHAMBER;
|
|
||||||
}
|
|
||||||
return LVL_MAX;
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTitle() const {
|
bool isTitle() const {
|
||||||
@ -3310,11 +2845,7 @@ namespace TR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isCutsceneLevel() const {
|
bool isCutsceneLevel() const {
|
||||||
return id == LVL_TR1_CUT_1 || id == LVL_TR1_CUT_2 || id == LVL_TR1_CUT_3 || id == LVL_TR1_CUT_4 ||
|
return TR::isCutsceneLevel(id);
|
||||||
id == LVL_TR2_CUT_1 || id == LVL_TR2_CUT_2 || id == LVL_TR2_CUT_3 || id == LVL_TR2_CUT_4 ||
|
|
||||||
id == LVL_TR3_CUT_1 || id == LVL_TR3_CUT_2 || id == LVL_TR3_CUT_3 || id == LVL_TR3_CUT_4 ||
|
|
||||||
id == LVL_TR3_CUT_5 || id == LVL_TR3_CUT_6 || id == LVL_TR3_CUT_7 || id == LVL_TR3_CUT_8 ||
|
|
||||||
id == LVL_TR3_CUT_9 || id == LVL_TR3_CUT_11 || id == LVL_TR3_CUT_12;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void readFace(Stream &stream, Rectangle &v, bool colored = false) {
|
void readFace(Stream &stream, Rectangle &v, bool colored = false) {
|
||||||
@ -3433,7 +2964,7 @@ namespace TR {
|
|||||||
// room sprites
|
// room sprites
|
||||||
if (version == VER_TR2_PSX) { // there is no room sprites
|
if (version == VER_TR2_PSX) { // there is no room sprites
|
||||||
d.sprites = NULL;
|
d.sprites = NULL;
|
||||||
d.sCount = NULL;
|
d.sCount = 0;
|
||||||
} else
|
} else
|
||||||
stream.read(d.sprites, stream.read(d.sCount));
|
stream.read(d.sprites, stream.read(d.sCount));
|
||||||
|
|
||||||
|
11
src/game.h
11
src/game.h
@ -50,7 +50,16 @@ namespace Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init(char *lvlName = NULL, char *sndName = NULL) {
|
void init(char *lvlName = NULL, char *sndName = NULL) {
|
||||||
if (!lvlName) lvlName = (char*)"level/TITLE.PSX";
|
char fileName[255];
|
||||||
|
|
||||||
|
if (!lvlName) {
|
||||||
|
lvlName = fileName;
|
||||||
|
strcpy(lvlName, "level/1/TITLE.PSX");
|
||||||
|
|
||||||
|
TR::Version version = TR::getGameVersion();
|
||||||
|
if (version != TR::VER_UNKNOWN)
|
||||||
|
TR::getGameLevelFile(lvlName, version, TR::getTitleId(version));
|
||||||
|
}
|
||||||
init(new Stream(lvlName));
|
init(new Stream(lvlName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
722
src/gameflow.h
Normal file
722
src/gameflow.h
Normal file
@ -0,0 +1,722 @@
|
|||||||
|
#ifndef H_GAMEFLOW
|
||||||
|
#define H_GAMEFLOW
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
namespace TR {
|
||||||
|
|
||||||
|
bool useEasyStart;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NO_TRACK = 0xFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Version : uint32 {
|
||||||
|
VER_UNKNOWN = 0,
|
||||||
|
|
||||||
|
VER_PC = 256,
|
||||||
|
VER_PSX = 512,
|
||||||
|
VER_SEGA = 1024,
|
||||||
|
|
||||||
|
VER_TR1 = 1,
|
||||||
|
VER_TR2 = 2,
|
||||||
|
VER_TR3 = 4,
|
||||||
|
VER_TR4 = 8,
|
||||||
|
VER_TR5 = 16,
|
||||||
|
|
||||||
|
VER_VERSION = VER_TR1 | VER_TR2 | VER_TR3 | VER_TR4 | VER_TR5,
|
||||||
|
VER_PLATFORM = VER_PC | VER_PSX | VER_SEGA,
|
||||||
|
|
||||||
|
VER_TR1_PC = VER_TR1 | VER_PC,
|
||||||
|
VER_TR1_PSX = VER_TR1 | VER_PSX,
|
||||||
|
VER_TR1_SEGA = VER_TR1 | VER_SEGA,
|
||||||
|
|
||||||
|
VER_TR2_PC = VER_TR2 | VER_PC,
|
||||||
|
VER_TR2_PSX = VER_TR2 | VER_PSX,
|
||||||
|
|
||||||
|
VER_TR3_PC = VER_TR3 | VER_PC,
|
||||||
|
VER_TR3_PSX = VER_TR3 | VER_PSX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LevelID : uint32 {
|
||||||
|
LVL_CUSTOM,
|
||||||
|
// TR1
|
||||||
|
LVL_TR1_TITLE,
|
||||||
|
LVL_TR1_GYM,
|
||||||
|
LVL_TR1_1,
|
||||||
|
LVL_TR1_2,
|
||||||
|
LVL_TR1_3A,
|
||||||
|
LVL_TR1_3B,
|
||||||
|
LVL_TR1_CUT_1,
|
||||||
|
LVL_TR1_4,
|
||||||
|
LVL_TR1_5,
|
||||||
|
LVL_TR1_6,
|
||||||
|
LVL_TR1_7A,
|
||||||
|
LVL_TR1_7B,
|
||||||
|
LVL_TR1_CUT_2,
|
||||||
|
LVL_TR1_8A,
|
||||||
|
LVL_TR1_8B,
|
||||||
|
LVL_TR1_8C,
|
||||||
|
LVL_TR1_10A,
|
||||||
|
LVL_TR1_CUT_3,
|
||||||
|
LVL_TR1_10B,
|
||||||
|
LVL_TR1_CUT_4,
|
||||||
|
LVL_TR1_10C,
|
||||||
|
LVL_TR1_EGYPT,
|
||||||
|
LVL_TR1_CAT,
|
||||||
|
LVL_TR1_END,
|
||||||
|
LVL_TR1_END2,
|
||||||
|
// TR2
|
||||||
|
LVL_TR2_TITLE,
|
||||||
|
LVL_TR2_ASSAULT,
|
||||||
|
LVL_TR2_WALL,
|
||||||
|
LVL_TR2_CUT_1,
|
||||||
|
LVL_TR2_BOAT,
|
||||||
|
LVL_TR2_VENICE,
|
||||||
|
LVL_TR2_OPERA,
|
||||||
|
LVL_TR2_CUT_2,
|
||||||
|
LVL_TR2_RIG,
|
||||||
|
LVL_TR2_PLATFORM,
|
||||||
|
LVL_TR2_CUT_3,
|
||||||
|
LVL_TR2_UNWATER,
|
||||||
|
LVL_TR2_KEEL,
|
||||||
|
LVL_TR2_LIVING,
|
||||||
|
LVL_TR2_DECK,
|
||||||
|
LVL_TR2_SKIDOO,
|
||||||
|
LVL_TR2_MONASTRY,
|
||||||
|
LVL_TR2_CATACOMB,
|
||||||
|
LVL_TR2_ICECAVE,
|
||||||
|
LVL_TR2_EMPRTOMB,
|
||||||
|
LVL_TR2_FLOATING,
|
||||||
|
LVL_TR2_CUT_4,
|
||||||
|
LVL_TR2_XIAN,
|
||||||
|
LVL_TR2_HOUSE,
|
||||||
|
// TR3
|
||||||
|
LVL_TR3_TITLE,
|
||||||
|
LVL_TR3_HOUSE,
|
||||||
|
LVL_TR3_JUNGLE,
|
||||||
|
LVL_TR3_CUT_6,
|
||||||
|
LVL_TR3_TEMPLE,
|
||||||
|
LVL_TR3_CUT_9,
|
||||||
|
LVL_TR3_QUADCHAS,
|
||||||
|
LVL_TR3_TONYBOSS,
|
||||||
|
LVL_TR3_SHORE,
|
||||||
|
LVL_TR3_CUT_1,
|
||||||
|
LVL_TR3_CRASH,
|
||||||
|
LVL_TR3_CUT_4,
|
||||||
|
LVL_TR3_RAPIDS,
|
||||||
|
LVL_TR3_TRIBOSS,
|
||||||
|
LVL_TR3_ROOFS,
|
||||||
|
LVL_TR3_CUT_2,
|
||||||
|
LVL_TR3_SEWER,
|
||||||
|
LVL_TR3_CUT_5,
|
||||||
|
LVL_TR3_TOWER,
|
||||||
|
LVL_TR3_CUT_11,
|
||||||
|
LVL_TR3_OFFICE,
|
||||||
|
LVL_TR3_NEVADA,
|
||||||
|
LVL_TR3_CUT_7,
|
||||||
|
LVL_TR3_COMPOUND,
|
||||||
|
LVL_TR3_CUT_8,
|
||||||
|
LVL_TR3_AREA51,
|
||||||
|
LVL_TR3_ANTARC,
|
||||||
|
LVL_TR3_CUT_3,
|
||||||
|
LVL_TR3_MINES,
|
||||||
|
LVL_TR3_CITY,
|
||||||
|
LVL_TR3_CUT_12,
|
||||||
|
LVL_TR3_CHAMBER,
|
||||||
|
LVL_TR3_STPAUL,
|
||||||
|
|
||||||
|
LVL_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
// TR1
|
||||||
|
TRACK_TR1_TITLE = 2,
|
||||||
|
TRACK_TR1_CAVES = 5,
|
||||||
|
TRACK_TR1_SECRET = 13,
|
||||||
|
TRACK_TR1_CISTERN = 57,
|
||||||
|
TRACK_TR1_EGYPT = 58,
|
||||||
|
TRACK_TR1_MINE = 59,
|
||||||
|
TRACK_TR1_CUT_1 = 23,
|
||||||
|
TRACK_TR1_CUT_2 = 25,
|
||||||
|
TRACK_TR1_CUT_3 = 24,
|
||||||
|
TRACK_TR1_CUT_4 = 22,
|
||||||
|
// TR2
|
||||||
|
TRACK_TR2_TITLE = 64,
|
||||||
|
TRACK_TR2_CHINA_1 = 33,
|
||||||
|
TRACK_TR2_CHINA_2 = 59,
|
||||||
|
TRACK_TR2_ITALY = 31,
|
||||||
|
TRACK_TR2_RIG = 58,
|
||||||
|
TRACK_TR2_UNWATER_1 = 34,
|
||||||
|
TRACK_TR2_UNWATER_2 = 31,
|
||||||
|
TRACK_TR2_TIBET_1 = 33,
|
||||||
|
TRACK_TR2_TIBET_2 = 31,
|
||||||
|
TRACK_TR2_CUT_1 = 3,
|
||||||
|
TRACK_TR2_CUT_2 = 4,
|
||||||
|
TRACK_TR2_CUT_3 = 5,
|
||||||
|
TRACK_TR2_CUT_4 = 30,
|
||||||
|
// TR3
|
||||||
|
TRACK_TR3_TITLE = 5,
|
||||||
|
TRACK_TR3_HOUSE = 2,
|
||||||
|
TRACK_TR3_CAVES = 30,
|
||||||
|
TRACK_TR3_INDIA_1 = 34,
|
||||||
|
TRACK_TR3_INDIA_2 = 30,
|
||||||
|
TRACK_TR3_SOUTH_1 = 32,
|
||||||
|
TRACK_TR3_SOUTH_2 = 33,
|
||||||
|
TRACK_TR3_SOUTH_3 = 36,
|
||||||
|
TRACK_TR3_LONDON_1 = 73,
|
||||||
|
TRACK_TR3_LONDON_2 = 74,
|
||||||
|
TRACK_TR3_LONDON_3 = 31,
|
||||||
|
TRACK_TR3_LONDON_4 = 78,
|
||||||
|
TRACK_TR3_NEVADA_1 = 33,
|
||||||
|
TRACK_TR3_NEVADA_2 = 27,
|
||||||
|
TRACK_TR3_ANTARC_1 = 28,
|
||||||
|
TRACK_TR3_ANTARC_2 = 30,
|
||||||
|
TRACK_TR3_ANTARC_3 = 26,
|
||||||
|
TRACK_TR3_CUT_1 = 68,
|
||||||
|
TRACK_TR3_CUT_2 = 67,
|
||||||
|
TRACK_TR3_CUT_3 = 62,
|
||||||
|
TRACK_TR3_CUT_4 = 65,
|
||||||
|
TRACK_TR3_CUT_5 = 63,
|
||||||
|
TRACK_TR3_CUT_6 = 64,
|
||||||
|
TRACK_TR3_CUT_7 = 72,
|
||||||
|
TRACK_TR3_CUT_8 = 70,
|
||||||
|
TRACK_TR3_CUT_9 = 69,
|
||||||
|
TRACK_TR3_CUT_11 = 71,
|
||||||
|
TRACK_TR3_CUT_12 = 66,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const char *name;
|
||||||
|
const char *title;
|
||||||
|
int ambientTrack;
|
||||||
|
} LEVEL_INFO[LVL_MAX] = {
|
||||||
|
// TR1
|
||||||
|
{ "" , "Custom Level", TRACK_TR1_CAVES },
|
||||||
|
{ "TITLE" , "", TRACK_TR1_TITLE },
|
||||||
|
{ "GYM" , "Lara's Home", NO_TRACK },
|
||||||
|
{ "LEVEL1" , "Caves", TRACK_TR1_CAVES },
|
||||||
|
{ "LEVEL2" , "City of Vilcabamba", TRACK_TR1_CAVES },
|
||||||
|
{ "LEVEL3A" , "Lost Valley", TRACK_TR1_CAVES },
|
||||||
|
{ "LEVEL3B" , "Tomb of Qualopec", TRACK_TR1_CAVES },
|
||||||
|
{ "CUT1" , "", TRACK_TR1_CUT_1 },
|
||||||
|
{ "LEVEL4" , "St. Francis' Folly", TRACK_TR1_CAVES },
|
||||||
|
{ "LEVEL5" , "Colosseum", TRACK_TR1_CAVES },
|
||||||
|
{ "LEVEL6" , "Palace Midas", TRACK_TR1_CAVES },
|
||||||
|
{ "LEVEL7A" , "The Cistern", TRACK_TR1_CISTERN },
|
||||||
|
{ "LEVEL7B" , "Tomb of Tihocan", TRACK_TR1_CISTERN },
|
||||||
|
{ "CUT2" , "", TRACK_TR1_CUT_2 },
|
||||||
|
{ "LEVEL8A" , "City of Khamoon", TRACK_TR1_EGYPT },
|
||||||
|
{ "LEVEL8B" , "Obelisk of Khamoon", TRACK_TR1_EGYPT },
|
||||||
|
{ "LEVEL8C" , "Sanctuary of the Scion", TRACK_TR1_EGYPT },
|
||||||
|
{ "LEVEL10A" , "Natla's Mines", TRACK_TR1_MINE },
|
||||||
|
{ "CUT3" , "", TRACK_TR1_CUT_3 },
|
||||||
|
{ "LEVEL10B" , "Atlantis", TRACK_TR1_MINE },
|
||||||
|
{ "CUT4" , "", TRACK_TR1_CUT_4 },
|
||||||
|
{ "LEVEL10C" , "The Great Pyramid", TRACK_TR1_MINE },
|
||||||
|
{ "EGYPT" , "Return to Egypt", TRACK_TR1_EGYPT },
|
||||||
|
{ "CAT" , "Temple of the Cat", TRACK_TR1_EGYPT },
|
||||||
|
{ "END" , "Atlantean Stronghold", TRACK_TR1_EGYPT },
|
||||||
|
{ "END2" , "The Hive", TRACK_TR1_EGYPT },
|
||||||
|
// TR2
|
||||||
|
{ "TITLE" , "", TRACK_TR2_TITLE },
|
||||||
|
{ "ASSAULT" , "Lara's Home", NO_TRACK },
|
||||||
|
{ "WALL" , "The Great Wall", TRACK_TR2_CHINA_1 },
|
||||||
|
{ "CUT1" , "", TRACK_TR2_CUT_1 },
|
||||||
|
{ "BOAT" , "Venice", NO_TRACK },
|
||||||
|
{ "VENICE" , "Bartoli's Hideout", NO_TRACK },
|
||||||
|
{ "OPERA" , "Opera House", TRACK_TR2_ITALY },
|
||||||
|
{ "CUT2" , "", TRACK_TR2_CUT_2 },
|
||||||
|
{ "RIG" , "Offshore Rig", TRACK_TR2_RIG },
|
||||||
|
{ "PLATFORM" , "Diving Area", TRACK_TR2_RIG },
|
||||||
|
{ "CUT3" , "", TRACK_TR2_CUT_3 },
|
||||||
|
{ "UNWATER" , "40 Fathoms", TRACK_TR2_UNWATER_1 },
|
||||||
|
{ "KEEL" , "Wreck of the Maria Doria", TRACK_TR2_UNWATER_2 },
|
||||||
|
{ "LIVING" , "Living Quarters", TRACK_TR2_UNWATER_1 },
|
||||||
|
{ "DECK" , "The Deck", TRACK_TR2_UNWATER_2 },
|
||||||
|
{ "SKIDOO" , "Tibetan Foothills", TRACK_TR2_TIBET_1 },
|
||||||
|
{ "MONASTRY" , "Barkhang Monastery", NO_TRACK },
|
||||||
|
{ "CATACOMB" , "Catacombs of the Talion", TRACK_TR2_TIBET_2 },
|
||||||
|
{ "ICECAVE" , "Ice Palace", TRACK_TR2_TIBET_2 },
|
||||||
|
{ "EMPRTOMB" , "Temple of Xian", TRACK_TR2_CHINA_2 },
|
||||||
|
{ "FLOATING" , "Floating Islands", TRACK_TR2_CHINA_2 },
|
||||||
|
{ "CUT4" , "", TRACK_TR2_CUT_4 },
|
||||||
|
{ "XIAN" , "The Dragon's Lair", TRACK_TR2_CHINA_2 },
|
||||||
|
{ "HOUSE" , "Home Sweet Home", NO_TRACK },
|
||||||
|
// TR3
|
||||||
|
{ "TITLE", "", TRACK_TR3_TITLE },
|
||||||
|
{ "HOUSE", "Lara's House", NO_TRACK },
|
||||||
|
{ "JUNGLE", "Jungle", TRACK_TR3_INDIA_1 },
|
||||||
|
{ "CUT6", "", TRACK_TR3_CUT_6 },
|
||||||
|
{ "TEMPLE", "Temple Ruins", TRACK_TR3_INDIA_1 },
|
||||||
|
{ "CUT9", "", TRACK_TR3_CUT_9 },
|
||||||
|
{ "QUADCHAS", "The River Ganges", TRACK_TR3_INDIA_1 },
|
||||||
|
{ "TONYBOSS", "Caves Of Kaliya", TRACK_TR3_INDIA_2 },
|
||||||
|
{ "SHORE", "Coastal Village", TRACK_TR3_SOUTH_1 },
|
||||||
|
{ "CUT1", "", TRACK_TR3_CUT_1 },
|
||||||
|
{ "CRASH", "Crash Site", TRACK_TR3_SOUTH_2 },
|
||||||
|
{ "CUT4", "", TRACK_TR3_CUT_4 },
|
||||||
|
{ "RAPIDS", "Madubu Gorge", TRACK_TR3_SOUTH_3 },
|
||||||
|
{ "TRIBOSS", "Temple Of Puna", TRACK_TR3_CAVES },
|
||||||
|
{ "ROOFS", "Thames Wharf", TRACK_TR3_LONDON_1 },
|
||||||
|
{ "CUT2", "", TRACK_TR3_CUT_2 },
|
||||||
|
{ "SEWER", "Aldwych", TRACK_TR3_LONDON_2 },
|
||||||
|
{ "CUT5", "", TRACK_TR3_CUT_5 },
|
||||||
|
{ "TOWER", "Lud's Gate", TRACK_TR3_LONDON_3 },
|
||||||
|
{ "CUT11", "", TRACK_TR3_CUT_11 },
|
||||||
|
{ "OFFICE", "City", TRACK_TR3_LONDON_4 },
|
||||||
|
{ "NEVADA", "Nevada Desert", TRACK_TR3_NEVADA_1 },
|
||||||
|
{ "CUT7", "", TRACK_TR3_CUT_7 },
|
||||||
|
{ "COMPOUND", "High Security Compound", TRACK_TR3_NEVADA_2 },
|
||||||
|
{ "CUT8", "", TRACK_TR3_CUT_8 },
|
||||||
|
{ "AREA51", "Area 51", TRACK_TR3_NEVADA_2 },
|
||||||
|
{ "ANTARC", "Antarctica", TRACK_TR3_ANTARC_1 },
|
||||||
|
{ "CUT3", "", TRACK_TR3_CUT_3 },
|
||||||
|
{ "MINES", "RX-Tech Mines", TRACK_TR3_ANTARC_2 },
|
||||||
|
{ "CITY", "Lost City Of Tinnos", TRACK_TR3_ANTARC_3 },
|
||||||
|
{ "CUT12", "", TRACK_TR3_CUT_12 },
|
||||||
|
{ "CHAMBER", "Meteorite Cavern", TRACK_TR3_ANTARC_3 },
|
||||||
|
{ "STPAUL", "All Hallows", TRACK_TR3_CAVES },
|
||||||
|
};
|
||||||
|
|
||||||
|
LevelID getLevelID(int size, Version &version, bool &isDemoLevel) {
|
||||||
|
isDemoLevel = false;
|
||||||
|
switch (size) {
|
||||||
|
// TR1
|
||||||
|
case 508614 : version = VER_TR1_PSX;
|
||||||
|
case 334874 :
|
||||||
|
case 316138 :
|
||||||
|
case 316460 : return LVL_TR1_TITLE;
|
||||||
|
case 1074234 : version = VER_TR1_PSX;
|
||||||
|
case 3236806 :
|
||||||
|
case 3237128 : return LVL_TR1_GYM;
|
||||||
|
case 1448896 : version = VER_TR1_PSX;
|
||||||
|
case 2533312 :
|
||||||
|
case 2533634 : return LVL_TR1_1;
|
||||||
|
case 2873406 : isDemoLevel = true; return LVL_TR1_2;
|
||||||
|
case 1535734 : version = VER_TR1_PSX;
|
||||||
|
case 2873128 :
|
||||||
|
case 2873450 : return LVL_TR1_2;
|
||||||
|
case 1630560 : version = VER_TR1_PSX;
|
||||||
|
case 2934408 :
|
||||||
|
case 2934730 : return LVL_TR1_3A;
|
||||||
|
case 1506614 : version = VER_TR1_PSX;
|
||||||
|
case 2737936 :
|
||||||
|
case 2738258 : return LVL_TR1_3B;
|
||||||
|
case 722402 : version = VER_TR1_PSX;
|
||||||
|
case 599840 : return LVL_TR1_CUT_1;
|
||||||
|
case 1621970 : version = VER_TR1_PSX;
|
||||||
|
case 3030550 :
|
||||||
|
case 3030872 : return LVL_TR1_4;
|
||||||
|
case 1585942 : version = VER_TR1_PSX;
|
||||||
|
case 2718218 :
|
||||||
|
case 2718540 : return LVL_TR1_5;
|
||||||
|
case 1708464 : version = VER_TR1_PSX;
|
||||||
|
case 3139590 :
|
||||||
|
case 3074376 : return LVL_TR1_6;
|
||||||
|
case 1696664 : version = VER_TR1_PSX;
|
||||||
|
case 2817290 :
|
||||||
|
case 2817612 : return LVL_TR1_7A;
|
||||||
|
case 1733274 : version = VER_TR1_PSX;
|
||||||
|
case 3388774 :
|
||||||
|
case 3389096 : return LVL_TR1_7B;
|
||||||
|
case 542960 : version = VER_TR1_PSX;
|
||||||
|
case 354320 : return LVL_TR1_CUT_2;
|
||||||
|
case 1563356 : version = VER_TR1_PSX;
|
||||||
|
case 2880242 :
|
||||||
|
case 2880564 : return LVL_TR1_8A;
|
||||||
|
case 1565630 : version = VER_TR1_PSX;
|
||||||
|
case 2886434 :
|
||||||
|
case 2886756 : return LVL_TR1_8B;
|
||||||
|
case 1619360 : version = VER_TR1_PSX;
|
||||||
|
case 3105128 :
|
||||||
|
case 3105450 : return LVL_TR1_8C;
|
||||||
|
case 1678018 : version = VER_TR1_PSX;
|
||||||
|
case 3223816 :
|
||||||
|
case 3224138 : return LVL_TR1_10A;
|
||||||
|
case 636660 : version = VER_TR1_PSX;
|
||||||
|
case 512104 : return LVL_TR1_CUT_3;
|
||||||
|
case 1686748 : version = VER_TR1_PSX;
|
||||||
|
case 3094020 : return LVL_TR1_10B;
|
||||||
|
case 940398 : version = VER_TR1_PSX;
|
||||||
|
case 879582 : return LVL_TR1_CUT_4;
|
||||||
|
case 1814278 : version = VER_TR1_PSX;
|
||||||
|
case 3531702 :
|
||||||
|
case 3532024 : return LVL_TR1_10C;
|
||||||
|
case 3278614 : version = VER_TR1_PSX;
|
||||||
|
case 3279242 : return LVL_TR1_EGYPT;
|
||||||
|
case 3270370 : version = VER_TR1_PSX;
|
||||||
|
case 3270998 : return LVL_TR1_CAT;
|
||||||
|
case 3208018 : return LVL_TR1_END;
|
||||||
|
case 3153300 : return LVL_TR1_END2;
|
||||||
|
// TR2
|
||||||
|
case 148744 : version = VER_TR2_PSX;
|
||||||
|
case 611892 : return LVL_TR2_TITLE;
|
||||||
|
case 1565974 : version = VER_TR2_PSX;
|
||||||
|
case 3471450 : return LVL_TR2_ASSAULT;
|
||||||
|
case 1661622 : version = VER_TR2_PSX;
|
||||||
|
case 2986356 : return LVL_TR2_WALL;
|
||||||
|
case 2014880 : version = VER_TR2_PSX;
|
||||||
|
case 2010678 : version = VER_TR2_PSX; // PLAYABLE.PSX
|
||||||
|
case 3945738 : return LVL_TR2_BOAT;
|
||||||
|
case 2081402 : version = VER_TR2_PSX;
|
||||||
|
case 4213070 : return LVL_TR2_VENICE;
|
||||||
|
case 2060882 : version = VER_TR2_PSX;
|
||||||
|
case 3996500 : return LVL_TR2_OPERA;
|
||||||
|
case 1950216 : version = VER_TR2_PSX;
|
||||||
|
case 3944472 : return LVL_TR2_RIG;
|
||||||
|
case 1993070 : version = VER_TR2_PSX;
|
||||||
|
case 4101590 : return LVL_TR2_PLATFORM;
|
||||||
|
case 1784200 : version = VER_TR2_PSX;
|
||||||
|
case 3131814 : return LVL_TR2_UNWATER;
|
||||||
|
case 2014110 : version = VER_TR2_PSX;
|
||||||
|
case 3995356 : return LVL_TR2_KEEL;
|
||||||
|
case 1808444 : version = VER_TR2_PSX;
|
||||||
|
case 3501472 : return LVL_TR2_LIVING;
|
||||||
|
case 1968084 : version = VER_TR2_PSX;
|
||||||
|
case 3890042 : return LVL_TR2_DECK;
|
||||||
|
case 1981902 : version = VER_TR2_PSX;
|
||||||
|
case 3521106 : return LVL_TR2_SKIDOO;
|
||||||
|
case 2120772 : version = VER_TR2_PSX;
|
||||||
|
case 4325562 : return LVL_TR2_MONASTRY;
|
||||||
|
case 1877970 : version = VER_TR2_PSX;
|
||||||
|
case 3605052 : return LVL_TR2_CATACOMB;
|
||||||
|
case 1987854 : version = VER_TR2_PSX;
|
||||||
|
case 3803398 : return LVL_TR2_ICECAVE;
|
||||||
|
case 2101594 : version = VER_TR2_PSX;
|
||||||
|
case 4291468 : return LVL_TR2_EMPRTOMB;
|
||||||
|
case 2078690 : version = VER_TR2_PSX;
|
||||||
|
case 4007486 : return LVL_TR2_FLOATING;
|
||||||
|
case 1748838 : version = VER_TR2_PSX;
|
||||||
|
case 3173840 : return LVL_TR2_XIAN;
|
||||||
|
case 1886728 : version = VER_TR2_PSX;
|
||||||
|
case 3693108 : return LVL_TR2_HOUSE;
|
||||||
|
case 952798 : version = VER_TR2_PSX;
|
||||||
|
case 1767052 : return LVL_TR2_CUT_1;
|
||||||
|
case 1098876 : version = VER_TR2_PSX;
|
||||||
|
case 2037544 : return LVL_TR2_CUT_2;
|
||||||
|
case 1288922 : version = VER_TR2_PSX;
|
||||||
|
case 2558286 : return LVL_TR2_CUT_3;
|
||||||
|
case 1116966 : version = VER_TR2_PSX;
|
||||||
|
case 1900230 : return LVL_TR2_CUT_4;
|
||||||
|
// TR3 (TODO PSX)
|
||||||
|
case 1275266 : return LVL_TR3_TITLE;
|
||||||
|
case 3437855 : return LVL_TR3_HOUSE;
|
||||||
|
case 3360001 : return LVL_TR3_JUNGLE;
|
||||||
|
case 3180412 : return LVL_TR3_TEMPLE;
|
||||||
|
case 3131453 : return LVL_TR3_QUADCHAS;
|
||||||
|
case 2618437 : return LVL_TR3_TONYBOSS;
|
||||||
|
case 3365562 : return LVL_TR3_SHORE;
|
||||||
|
case 3331132 : return LVL_TR3_CRASH;
|
||||||
|
case 3148248 : return LVL_TR3_RAPIDS;
|
||||||
|
case 2276838 : return LVL_TR3_TRIBOSS;
|
||||||
|
case 3579476 : return LVL_TR3_ROOFS;
|
||||||
|
case 3670149 : return LVL_TR3_SEWER;
|
||||||
|
case 3523586 : return LVL_TR3_TOWER;
|
||||||
|
case 2504910 : return LVL_TR3_OFFICE;
|
||||||
|
case 3140417 : return LVL_TR3_NEVADA;
|
||||||
|
case 3554880 : return LVL_TR3_COMPOUND;
|
||||||
|
case 3530130 : return LVL_TR3_AREA51;
|
||||||
|
case 3515272 : return LVL_TR3_ANTARC;
|
||||||
|
case 3331087 : return LVL_TR3_MINES;
|
||||||
|
case 3575873 : return LVL_TR3_CITY;
|
||||||
|
case 3190736 : return LVL_TR3_CHAMBER;
|
||||||
|
case 3140028 : return LVL_TR3_STPAUL;
|
||||||
|
case 1547866 : return LVL_TR3_CUT_1;
|
||||||
|
case 1957327 : return LVL_TR3_CUT_2;
|
||||||
|
case 2020225 : return LVL_TR3_CUT_3;
|
||||||
|
case 1048466 : return LVL_TR3_CUT_4;
|
||||||
|
case 1580868 : return LVL_TR3_CUT_5;
|
||||||
|
case 2430940 : return LVL_TR3_CUT_6;
|
||||||
|
case 1253227 : return LVL_TR3_CUT_7;
|
||||||
|
case 944962 : return LVL_TR3_CUT_8;
|
||||||
|
case 1788075 : return LVL_TR3_CUT_9;
|
||||||
|
case 1402003 : return LVL_TR3_CUT_11;
|
||||||
|
case 2321393 : return LVL_TR3_CUT_12;
|
||||||
|
}
|
||||||
|
return LVL_CUSTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelID getTitleId(Version version) {
|
||||||
|
switch (version & VER_VERSION) {
|
||||||
|
case VER_TR1 : return LVL_TR1_TITLE;
|
||||||
|
case VER_TR2 : return LVL_TR2_TITLE;
|
||||||
|
case VER_TR3 : return LVL_TR3_TITLE;
|
||||||
|
}
|
||||||
|
return LVL_TR1_TITLE;
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelID getHomeId(Version version) {
|
||||||
|
switch (version & VER_VERSION) {
|
||||||
|
case VER_TR1 : return LVL_TR1_GYM;
|
||||||
|
case VER_TR2 : return LVL_TR2_ASSAULT;
|
||||||
|
case VER_TR3 : return LVL_TR3_HOUSE;
|
||||||
|
}
|
||||||
|
return LVL_TR1_TITLE;
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelID getStartId(Version version) {
|
||||||
|
switch (version & VER_VERSION) {
|
||||||
|
case VER_TR1 : return LVL_TR1_1;
|
||||||
|
case VER_TR2 : return LVL_TR2_WALL;
|
||||||
|
case VER_TR3 : return LVL_TR3_JUNGLE;
|
||||||
|
}
|
||||||
|
return LVL_MAX;
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelID getEndId(Version version) {
|
||||||
|
switch (version & VER_VERSION) {
|
||||||
|
case VER_TR1 : return LVL_TR1_10C;
|
||||||
|
case VER_TR2 : return LVL_TR2_HOUSE;
|
||||||
|
case VER_TR3 : return LVL_TR3_CHAMBER;
|
||||||
|
}
|
||||||
|
return LVL_MAX;
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCutsceneLevel(LevelID id) {
|
||||||
|
return id == LVL_TR1_CUT_1 || id == LVL_TR1_CUT_2 || id == LVL_TR1_CUT_3 || id == LVL_TR1_CUT_4 ||
|
||||||
|
id == LVL_TR2_CUT_1 || id == LVL_TR2_CUT_2 || id == LVL_TR2_CUT_3 || id == LVL_TR2_CUT_4 ||
|
||||||
|
id == LVL_TR3_CUT_1 || id == LVL_TR3_CUT_2 || id == LVL_TR3_CUT_3 || id == LVL_TR3_CUT_4 ||
|
||||||
|
id == LVL_TR3_CUT_5 || id == LVL_TR3_CUT_6 || id == LVL_TR3_CUT_7 || id == LVL_TR3_CUT_8 ||
|
||||||
|
id == LVL_TR3_CUT_9 || id == LVL_TR3_CUT_11 || id == LVL_TR3_CUT_12;
|
||||||
|
}
|
||||||
|
|
||||||
|
Version getGameVersion() {
|
||||||
|
useEasyStart = true;
|
||||||
|
if (Stream::existsContent("DATA/GYM.PHD") || Stream::existsContent("GYM.PHD"))
|
||||||
|
return VER_TR1_PC;
|
||||||
|
if (Stream::existsContent("PSXDATA/GYM.PSX"))
|
||||||
|
return VER_TR1_PSX;
|
||||||
|
if (Stream::existsContent("DATA/GYM.SAT"))
|
||||||
|
return VER_TR1_SEGA;
|
||||||
|
|
||||||
|
if (Stream::existsContent("data/ASSAULT.TR2") || Stream::existsContent("data/assault.TR2"))
|
||||||
|
return VER_TR2_PC;
|
||||||
|
if (Stream::existsContent("DATA/ASSAULT.PSX"))
|
||||||
|
return VER_TR2_PSX;
|
||||||
|
|
||||||
|
if (Stream::existsContent("data/JUNGLE.TR2"))
|
||||||
|
return VER_TR3_PC;
|
||||||
|
|
||||||
|
useEasyStart = false;
|
||||||
|
return VER_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getGameLevelFile(char *dst, Version version, LevelID id) {
|
||||||
|
if (useEasyStart) {
|
||||||
|
switch (version) {
|
||||||
|
case VER_TR1_PC :
|
||||||
|
sprintf(dst, "DATA/%s.PHD", LEVEL_INFO[id].name);
|
||||||
|
if (Stream::existsContent(dst)) break;
|
||||||
|
sprintf(dst, "%s.PHD", LEVEL_INFO[id].name);
|
||||||
|
break;
|
||||||
|
case VER_TR1_PSX : sprintf(dst, "PSXDATA/%s.PSX", LEVEL_INFO[id].name); break;
|
||||||
|
case VER_TR1_SEGA : sprintf(dst, "DATA/%s.SAT", LEVEL_INFO[id].name); break;
|
||||||
|
case VER_TR2_PC : { // oh FFFFUUUUUUCKing CaTaComB.Tr2!
|
||||||
|
if (id == LVL_TR2_VENICE || id == LVL_TR2_CUT_2 || id == LVL_TR2_PLATFORM || id == LVL_TR2_CUT_3 || id == LVL_TR2_UNWATER ||
|
||||||
|
id == LVL_TR2_KEEL || id == LVL_TR2_LIVING || id == LVL_TR2_DECK || id == LVL_TR2_CATACOMB || id == LVL_TR2_ICECAVE ||
|
||||||
|
id == LVL_TR2_CUT_4 || id == LVL_TR2_XIAN || id == LVL_TR2_HOUSE) {
|
||||||
|
strcpy(dst, LEVEL_INFO[id].name);
|
||||||
|
String::toLower(dst);
|
||||||
|
sprintf(dst, "DATA/%s.TR2", dst);
|
||||||
|
} else if (id == LVL_TR2_TITLE) {
|
||||||
|
sprintf(dst, "DATA/%s.tr2", LEVEL_INFO[id].name);
|
||||||
|
} else if (id == LVL_TR2_EMPRTOMB) {
|
||||||
|
dst = "DATA/Emprtomb.tr2";
|
||||||
|
} else {
|
||||||
|
sprintf(dst, "DATA/%s.TR2", LEVEL_INFO[id]);
|
||||||
|
}
|
||||||
|
if (Stream::existsContent(dst)) break;
|
||||||
|
strcpy(dst, LEVEL_INFO[id].name);
|
||||||
|
String::toLower(dst);
|
||||||
|
strcat(dst, ".TR2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VER_TR2_PSX : sprintf(dst, "DATA/%s.PSX", LEVEL_INFO[id]); break;
|
||||||
|
case VER_TR3_PC : sprintf(dst, isCutsceneLevel(id) ? "cuts/%s.TR2" : "data/%s.TR2", LEVEL_INFO[id].name); break;
|
||||||
|
default : ASSERT(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strcpy(dst, "level/");
|
||||||
|
if (version & VER_TR1) strcat(dst, "1/");
|
||||||
|
if (version & VER_TR2) strcat(dst, "2/");
|
||||||
|
if (version & VER_TR3) strcat(dst, "3/");
|
||||||
|
strcat(dst, LEVEL_INFO[id].name);
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
strcat(buf, ".PSX");
|
||||||
|
#else
|
||||||
|
switch (version) {
|
||||||
|
case VER_TR1_PC : strcat(dst, ".PHD"); break;
|
||||||
|
case VER_TR2_PC :
|
||||||
|
case VER_TR3_PC : strcat(dst, ".TR2"); break;
|
||||||
|
case VER_TR1_PSX :
|
||||||
|
case VER_TR2_PSX :
|
||||||
|
case VER_TR3_PSX : strcat(dst, ".PSX"); break;
|
||||||
|
default : ASSERT(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* getGameSoundsFile(Version version) {
|
||||||
|
if (!useEasyStart) {
|
||||||
|
if (version == VER_TR2_PC)
|
||||||
|
return "audio/2/MAIN.SFX";
|
||||||
|
if (version == VER_TR3_PC)
|
||||||
|
return "audio/3/MAIN.SFX";
|
||||||
|
} else
|
||||||
|
if (version == VER_TR2_PC || version == VER_TR3_PC)
|
||||||
|
return "data/MAIN.SFX";
|
||||||
|
ASSERT(false);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 remapTrack(Version version, uint8 track) {
|
||||||
|
static const uint8 TR2_TRACK_MAPPING[] = {
|
||||||
|
2, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 18, 19, 20,
|
||||||
|
21, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
|
||||||
|
};
|
||||||
|
|
||||||
|
if (version & VER_TR2) {
|
||||||
|
ASSERT(track < COUNT(TR2_TRACK_MAPPING));
|
||||||
|
return TR2_TRACK_MAPPING[track];
|
||||||
|
}
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkTrack(const char *pre, char *name) {
|
||||||
|
static const char *fmt[] = { ".ogg", ".mp3", ".wav" };
|
||||||
|
static const char *lng[] = { "", "_EN", "_DE", "_FR", "_IT", "_JA", "_RU" };
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
for (int f = 0; f < COUNT(fmt); f++)
|
||||||
|
for (int l = 0; l < COUNT(lng); l++) {
|
||||||
|
strcpy(buf, pre);
|
||||||
|
strcat(buf, name);
|
||||||
|
strcat(buf, lng[l]);
|
||||||
|
strcat(buf, fmt[f]);
|
||||||
|
if (Stream::existsContent(buf)) {
|
||||||
|
strcpy(name, buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getGameTrack(Version version, int track, Stream::Callback callback, void *userData) {
|
||||||
|
track = remapTrack(version, track);
|
||||||
|
|
||||||
|
char title[32];
|
||||||
|
if (useEasyStart) {
|
||||||
|
switch (version) {
|
||||||
|
case VER_TR1_PC :
|
||||||
|
case VER_TR1_PSX :
|
||||||
|
sprintf(title, "track_%02d", track);
|
||||||
|
if (!checkTrack("", title) && !checkTrack("audio/1/", title) && !checkTrack("audio/", title)) {
|
||||||
|
callback(NULL, userData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VER_TR2_PC :
|
||||||
|
case VER_TR2_PSX :
|
||||||
|
if (Stream::existsContent("audio/cdaudio.mp3")) {
|
||||||
|
callback(Sound::openCDAudioMP3("audio/cdaudio.dat", "audio/cdaudio.mp3", track), userData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!checkTrack("", title) && !checkTrack("audio/2/", title) && !checkTrack("audio/", title)) {
|
||||||
|
callback(NULL, userData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VER_TR3_PC :
|
||||||
|
case VER_TR3_PSX :
|
||||||
|
callback(Sound::openCDAudioWAD("audio/cdaudio.wad", track), userData);
|
||||||
|
return;
|
||||||
|
default : return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (version) {
|
||||||
|
case VER_TR1_PC :
|
||||||
|
case VER_TR1_PSX :
|
||||||
|
sprintf(title, "audio/1/track_%02d.ogg", track);
|
||||||
|
break;
|
||||||
|
case VER_TR2_PC :
|
||||||
|
case VER_TR2_PSX :
|
||||||
|
sprintf(title, "audio/2/track_%02d.ogg", track);
|
||||||
|
break;
|
||||||
|
case VER_TR3_PC :
|
||||||
|
case VER_TR3_PSX :
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
callback(Sound::openCDAudioWAD("audio/3/cdaudio.wad", track), userData);
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
sprintf(title, "audio/3/track_%02d.wav", track);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default : return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Stream(title, callback, userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* getGameScreen(Version version, LevelID id) {
|
||||||
|
if (useEasyStart) {
|
||||||
|
|
||||||
|
if (version == VER_TR1_PC)
|
||||||
|
switch (id) {
|
||||||
|
case LVL_TR1_TITLE :
|
||||||
|
if (Stream::existsContent("DATA/TITLEH.PCX")) return "DATA/TITLEH.PCX";
|
||||||
|
break;
|
||||||
|
default : ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == VER_TR2_PC)
|
||||||
|
switch (id) {
|
||||||
|
case LVL_TR2_TITLE :
|
||||||
|
if (Stream::existsContent("data/TITLE.PCX")) return "data/TITLE.PCX";
|
||||||
|
if (Stream::existsContent("pix/title.pcx")) return "pix/title.pcx";
|
||||||
|
break;
|
||||||
|
default : ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == VER_TR3_PC)
|
||||||
|
switch (id) {
|
||||||
|
case LVL_TR3_TITLE :
|
||||||
|
if (Stream::existsContent("pix/TITLEUK.BMP")) return "pix/TITLEUK.BMP";
|
||||||
|
break;
|
||||||
|
default : ;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (version & VER_TR1)
|
||||||
|
switch (id) {
|
||||||
|
case LVL_TR1_TITLE : return "level/1/TITLEH.PCX";
|
||||||
|
default : ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version & VER_TR2)
|
||||||
|
switch (id) {
|
||||||
|
case LVL_TR2_TITLE : return "level/2/TITLE.PCX";
|
||||||
|
default : ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version & VER_TR3)
|
||||||
|
switch (id) {
|
||||||
|
case LVL_TR3_TITLE : return "level/3/TITLEUK.BMP";
|
||||||
|
default : ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -219,12 +219,9 @@ struct Inventory {
|
|||||||
|
|
||||||
memset(background, 0, sizeof(background));
|
memset(background, 0, sizeof(background));
|
||||||
|
|
||||||
if (level->version & TR::VER_TR1)
|
const char *titleBG = TR::getGameScreen(level->version, level->id);
|
||||||
new Stream("level/TITLEH.PCX", loadTitleBG, this);
|
if (titleBG)
|
||||||
if (level->version & TR::VER_TR2)
|
new Stream(titleBG, loadTitleBG, this);
|
||||||
new Stream("level/2/TITLE.PCX", loadTitleBG, this);
|
|
||||||
if (level->version & TR::VER_TR3)
|
|
||||||
new Stream("level/3/TITLEUK.BMP", loadTitleBG, this);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
add(TR::Entity::INV_COMPASS);
|
add(TR::Entity::INV_COMPASS);
|
||||||
|
@ -436,7 +436,7 @@ struct Lara : Character {
|
|||||||
flags.active = 1;
|
flags.active = 1;
|
||||||
initMeshOverrides();
|
initMeshOverrides();
|
||||||
|
|
||||||
if (level->isHomeLevel) {
|
if (level->isHome()) {
|
||||||
if (level->version & TR::VER_TR1)
|
if (level->version & TR::VER_TR1)
|
||||||
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
||||||
} else {
|
} else {
|
||||||
@ -814,7 +814,7 @@ struct Lara : Character {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void wpnChange(Weapon::Type wType) {
|
void wpnChange(Weapon::Type wType) {
|
||||||
if (wpnCurrent == wType || level->isHomeLevel) {
|
if (wpnCurrent == wType || level->isHome()) {
|
||||||
if (emptyHands())
|
if (emptyHands())
|
||||||
wpnDraw();
|
wpnDraw();
|
||||||
return;
|
return;
|
||||||
@ -1703,7 +1703,7 @@ struct Lara : Character {
|
|||||||
if (level->state.tracks[track].once) {
|
if (level->state.tracks[track].once) {
|
||||||
timer += Core::deltaTime;
|
timer += Core::deltaTime;
|
||||||
if (timer > 3.0f)
|
if (timer > 3.0f)
|
||||||
game->loadLevel(level->getTitleId());
|
game->loadNextLevel();
|
||||||
} else {
|
} else {
|
||||||
if (state != STATE_WATER_OUT)
|
if (state != STATE_WATER_OUT)
|
||||||
return 0;
|
return 0;
|
||||||
|
51
src/level.h
51
src/level.h
@ -60,26 +60,9 @@ struct Level : IGame {
|
|||||||
Sound::stopAll();
|
Sound::stopAll();
|
||||||
|
|
||||||
isEnded = true;
|
isEnded = true;
|
||||||
|
|
||||||
char buf[64];
|
char buf[64];
|
||||||
buf[0] = 0;
|
TR::getGameLevelFile(buf, level.version, id);
|
||||||
strcat(buf, "level/");
|
|
||||||
if (level.version & TR::VER_TR2)
|
|
||||||
strcat(buf, "2/");
|
|
||||||
if (level.version & TR::VER_TR3)
|
|
||||||
strcat(buf, "3/");
|
|
||||||
strcat(buf, TR::LEVEL_INFO[id].name);
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
strcat(buf, ".PSX");
|
|
||||||
#else
|
|
||||||
switch (level.version) {
|
|
||||||
case TR::VER_TR1_PC : strcat(buf, ".PHD"); break;
|
|
||||||
case TR::VER_TR2_PC :
|
|
||||||
case TR::VER_TR3_PC : strcat(buf, ".TR2"); break;
|
|
||||||
case TR::VER_TR1_PSX :
|
|
||||||
case TR::VER_TR2_PSX :
|
|
||||||
case TR::VER_TR3_PSX : strcat(buf, ".PSX"); break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
new Stream(buf, loadAsync);
|
new Stream(buf, loadAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +73,7 @@ struct Level : IGame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
loadLevel(level.isEnd() ? level.getTitleId() : TR::LevelID(level.id + 1));
|
loadLevel((level.isEnd() || level.isHome()) ? level.getTitleId() : TR::LevelID(level.id + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void saveGame(int slot) {
|
virtual void saveGame(int slot) {
|
||||||
@ -107,10 +90,6 @@ struct Level : IGame {
|
|||||||
|
|
||||||
// save levels progress
|
// save levels progress
|
||||||
save->progressCount = 0;
|
save->progressCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool saveCurrentState = true;
|
bool saveCurrentState = true;
|
||||||
|
|
||||||
if (saveCurrentState) {
|
if (saveCurrentState) {
|
||||||
@ -559,29 +538,7 @@ struct Level : IGame {
|
|||||||
|
|
||||||
if (track == 0xFF) return;
|
if (track == 0xFF) return;
|
||||||
|
|
||||||
char title[32];
|
getGameTrack(level.version, track, playAsync, this);
|
||||||
switch (level.version) {
|
|
||||||
case TR::VER_TR1_PC :
|
|
||||||
case TR::VER_TR1_PSX :
|
|
||||||
sprintf(title, "audio/track_%02d.ogg", int(track));
|
|
||||||
break;
|
|
||||||
case TR::VER_TR2_PC :
|
|
||||||
case TR::VER_TR2_PSX :
|
|
||||||
sprintf(title, "audio/2/track_%02d.ogg", int(level.remapTrack(track)));
|
|
||||||
break;
|
|
||||||
case TR::VER_TR3_PC :
|
|
||||||
case TR::VER_TR3_PSX :
|
|
||||||
#ifndef __EMSCRIPTEN__
|
|
||||||
playAsync(Sound::openWAD(NULL, track), this);
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
sprintf(title, "audio/3/track_%02d.wav", int(track));
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default : return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new Stream(title, playAsync, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void stopTrack() {
|
virtual void stopTrack() {
|
||||||
|
@ -133,7 +133,7 @@ struct Shader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool linkBinary(const char *fileName) {
|
bool linkBinary(const char *fileName) {
|
||||||
if (!Stream::fileExists(fileName))
|
if (!Stream::exists(fileName))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
GLenum size, format;
|
GLenum size, format;
|
||||||
|
25
src/sound.h
25
src/sound.h
@ -681,8 +681,11 @@ namespace Sound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream *openWAD(const char *name, int index = -1) {
|
Stream *openCDAudioWAD(const char *name, int index = -1) {
|
||||||
Stream *stream = new Stream("audio/3/cdaudio.wad");
|
if (!Stream::existsContent(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Stream *stream = new Stream(name);
|
||||||
if (stream->size) {
|
if (stream->size) {
|
||||||
struct Item {
|
struct Item {
|
||||||
char name[260];
|
char name[260];
|
||||||
@ -690,18 +693,22 @@ namespace Sound {
|
|||||||
int offset;
|
int offset;
|
||||||
} entity;
|
} entity;
|
||||||
|
|
||||||
for (int i = 0; i < 130; i++) {
|
stream->seek(sizeof(entity) * index);
|
||||||
stream->read(entity);
|
stream->read(entity);
|
||||||
if ((name && strcmp(name, entity.name) == 0) || index == i) {
|
stream->setPos(entity.offset);
|
||||||
stream->setPos(entity.offset);
|
return stream;
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
delete stream;
|
delete stream;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream *openCDAudioMP3(const char *dat, const char *name, int index = -1) {
|
||||||
|
if (!Stream::existsContent(dat) || !Stream::existsContent(name))
|
||||||
|
return NULL;
|
||||||
|
// TODO
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Sample* play(Stream *stream, const vec3 &pos, float volume = 1.0f, float pitch = 0.0f, int flags = 0, int id = - 1) {
|
Sample* play(Stream *stream, const vec3 &pos, float volume = 1.0f, float pitch = 0.0f, int flags = 0, int id = - 1) {
|
||||||
ASSERT(pitch >= 0.0f);
|
ASSERT(pitch >= 0.0f);
|
||||||
if (!stream) return NULL;
|
if (!stream) return NULL;
|
||||||
|
29
src/utils.h
29
src/utils.h
@ -1008,11 +1008,10 @@ struct Stream {
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
char *data;
|
char *data;
|
||||||
int size, pos;
|
int size, pos;
|
||||||
char *name;
|
|
||||||
|
|
||||||
Stream(const void *data, int size) : callback(NULL), userData(NULL), f(NULL), data((char*)data), size(size), pos(0), name(NULL) {}
|
Stream(const void *data, int size) : callback(NULL), userData(NULL), f(NULL), data((char*)data), size(size), pos(0) {}
|
||||||
|
|
||||||
Stream(const char *name, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), data(NULL), size(-1), pos(0), name(NULL) {
|
Stream(const char *name, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), data(NULL), size(-1), pos(0) {
|
||||||
if (contentDir[0] && (!cacheDir[0] || !strstr(name, cacheDir))) {
|
if (contentDir[0] && (!cacheDir[0] || !strstr(name, cacheDir))) {
|
||||||
char path[255];
|
char path[255];
|
||||||
path[0] = 0;
|
path[0] = 0;
|
||||||
@ -1051,11 +1050,10 @@ struct Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
~Stream() {
|
~Stream() {
|
||||||
delete[] name;
|
|
||||||
if (f) fclose(f);
|
if (f) fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool fileExists(const char *name) {
|
static bool exists(const char *name) {
|
||||||
FILE *f = fopen(name, "rb");
|
FILE *f = fopen(name, "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return false;
|
return false;
|
||||||
@ -1064,6 +1062,13 @@ struct Stream {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool existsContent(const char *name) {
|
||||||
|
char fileName[1024];
|
||||||
|
strcpy(fileName, Stream::contentDir);
|
||||||
|
strcat(fileName, name);
|
||||||
|
return exists(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
static void write(const char *name, const void *data, int size) {
|
static void write(const char *name, const void *data, int size) {
|
||||||
osSave(name, data, size);
|
osSave(name, data, size);
|
||||||
}
|
}
|
||||||
@ -1105,4 +1110,16 @@ struct Stream {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
namespace String {
|
||||||
|
|
||||||
|
void toLower(char *str) {
|
||||||
|
if (!str) return;
|
||||||
|
while (*str) {
|
||||||
|
*str = tolower(*str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user