diff --git a/src/format.h b/src/format.h index 10a71de..0ff79d3 100644 --- a/src/format.h +++ b/src/format.h @@ -2280,8 +2280,6 @@ namespace TR { int32 tilesCount; - uint32 unused; - uint16 roomsCount; Room *rooms; @@ -2548,10 +2546,10 @@ namespace TR { Level(Stream &stream) { memset(this, 0, sizeof(*this)); - version = VER_UNKNOWN; - cutEntity = -1; + version = VER_UNKNOWN; + cutEntity = -1; + meshesCount = 0; - int startPos = stream.pos; uint32 magic; #define MAGIC_TR1_PC 0x00000020 @@ -2562,87 +2560,34 @@ namespace TR { #define MAGIC_TR3_PC2 0xFF180038 #define MAGIC_TR3_PC3 0xFF180034 #define MAGIC_TR3_PSX 0xFFFFFFC8 + #define MAGIC_TR4_PC 0x00345254 id = TR::getLevelID(stream.size, stream.name, version, isDemoLevel); if (version == VER_UNKNOWN || version == VER_TR1_PSX) { stream.read(magic); - if (magic == MAGIC_TR1_SAT) { - version = VER_TR1_SAT; - stream.seek(-4); - // get file name without extension - size_t len = strlen(stream.name); - char *name = new char[len + 1]; - memcpy(name, stream.name, len); - for (int i = int(len) - 1; i >= 0; i--) { - if (name[i] == '/' || name[i] == '\\') - break; - if (name[i] == '.') { - len = i; - break; - } - } - name[len] = 0; - LOG("load Sega Saturn level: %s\n", name); - - strcat(name, ".SAD"); - Stream sad(name); - name[len] = '\0'; - strcat(name, ".SPR"); - Stream spr(name); - name[len] = '\0'; - strcat(name, ".SND"); - Stream snd(name); - name[len] = '\0'; - strcat(name, ".CIN"); - - Stream *cin = NULL; - if (Stream::existsContent(name)) { - cin = new Stream(name); - } else { - len = strlen(name); - for (int i = int(len) - 1; i >= 0; i--) - if (name[i] == '/' || name[i] == '\\') { - char *newName = new char[len + 11 + 1]; - name[i] = 0; - strcpy(newName, name); - strcat(newName, "/../CINDATA/"); - strcat(newName, name + i + 1); - delete[] name; - name = newName; - break; - } - - if (Stream::existsContent(name)) - cin = new Stream(name); - } - - delete[] name; - - readSAT(sad); - readSAT(spr); - readSAT(snd); - if (cin) { - readCIN(*cin); - delete cin; - } - readSAT(stream); // sat - return; - } - - if (magic != MAGIC_TR1_PC && magic != MAGIC_TR2_PC && magic != MAGIC_TR3_PC1 && magic != MAGIC_TR3_PC2 && magic != MAGIC_TR3_PC3 && magic != MAGIC_TR3_PSX) { + if (magic != MAGIC_TR1_PC && + magic != MAGIC_TR1_SAT && + magic != MAGIC_TR2_PC && + magic != MAGIC_TR3_PC1 && + magic != MAGIC_TR3_PC2 && + magic != MAGIC_TR3_PC3 && + magic != MAGIC_TR3_PSX && + magic != MAGIC_TR4_PC) { stream.read(magic); } switch (magic) { case MAGIC_TR1_PC : version = VER_TR1_PC; break; case MAGIC_TR1_PSX : version = VER_TR1_PSX; break; + case MAGIC_TR1_SAT : version = VER_TR1_SAT; break; case MAGIC_TR2_PC : version = VER_TR2_PC; break; case MAGIC_TR3_PC1 : case MAGIC_TR3_PC2 : case MAGIC_TR3_PC3 : version = VER_TR3_PC; break; case MAGIC_TR3_PSX : version = VER_TR3_PSX; break; + //case MAGIC_TR4_PC : version = VER_TR4_PC; break; default : ; } } @@ -2653,291 +2598,20 @@ namespace TR { return; } - if (version == VER_TR2_PSX) { - stream.read(soundOffsets, stream.read(soundOffsetsCount) + 1); - soundSize = new uint32[soundOffsetsCount]; - soundDataSize = 0; - for (int i = 0; i < soundOffsetsCount; i++) { - ASSERT(soundOffsets[i] < soundOffsets[i + 1]); - soundSize[i] = soundOffsets[i + 1] - soundOffsets[i]; - soundOffsets[i] = soundDataSize; - soundDataSize += soundSize[i]; - } - stream.read(soundData, soundDataSize); - } - - if (version == VER_TR3_PSX) { - stream.read(soundOffsets, stream.read(soundOffsetsCount)); - if (soundOffsetsCount) { - stream.read(soundDataSize); - stream.read(soundData, soundDataSize); - soundSize = new uint32[soundOffsetsCount]; - int size = 0; - for (int i = 0; i < soundOffsetsCount - 1; i++) { - ASSERT(soundOffsets[i] < soundOffsets[i + 1]); - size += soundSize[i] = soundOffsets[i + 1] - soundOffsets[i]; - } - - if (soundOffsetsCount) { - soundSize[soundOffsetsCount - 1] = soundDataSize; - if (soundOffsetsCount > 1) - soundSize[soundOffsetsCount - 1] -= soundSize[soundOffsetsCount - 2]; - } - } - - // skip code modules - int size; - for (int i = 0; i < 13; i++) { - stream.read(size); - if (size) { - stream.seek(size); - stream.read(size); - stream.seek(size); - } - } - } - - if (version == VER_TR2_PC || version == VER_TR3_PC) { - stream.read(palette, 256); - stream.read(palette32, 256); - } - - if (version == VER_TR1_PSX && !isCutsceneLevel()) { - uint32 offsetTexTiles; - stream.seek(8); - stream.read(offsetTexTiles); - // sound offsets - uint16 numSounds; - stream.setPos(startPos + 22); - stream.read(numSounds); - stream.setPos(startPos + 2086 + numSounds * 512); - soundOffsetsCount = numSounds; - soundOffsets = new uint32[soundOffsetsCount]; - soundSize = new uint32[soundOffsetsCount]; - soundDataSize = 0; - for (int i = 0; i < soundOffsetsCount; i++) { - soundOffsets[i] = soundDataSize; - uint16 size; - stream.read(size); - soundDataSize += soundSize[i] = size * 8; - } - // sound data - stream.setPos(startPos + 2600 + numSounds * 512); - stream.read(soundData, soundDataSize); - stream.setPos(startPos + offsetTexTiles + 8); - } - - // tiles - if (version & VER_PC) { - stream.read(tiles8, stream.read(tilesCount)); - } - - if (version == VER_TR2_PC || version == VER_TR3_PC) - stream.read(tiles16, tilesCount); - - if (version == VER_TR1_PSX) { - stream.read(tiles4, tilesCount = 13); - stream.read(cluts, clutsCount = 1024); - } - - if (version != VER_TR3_PSX) - stream.read(unused); - - // rooms - rooms = stream.read(roomsCount) ? new Room[roomsCount] : NULL; - for (int i = 0; i < roomsCount; i++) - readRoom(stream, i); - - // floors - stream.read(floors, stream.read(floorsCount)); - - if (version == VER_TR3_PSX) { - // outside room offsets - stream.seek(27 * 27 * 2); - // outside rooms table - int size; - stream.read(size); - stream.seek(size); - // room mesh bbox - stream.read(size); - stream.seek(8 * size); - } - - // meshes - meshesCount = 0; - stream.read(meshData, stream.read(meshDataSize)); - stream.read(meshOffsets, stream.read(meshOffsetsCount)); - // animations - - stream.read(anims, stream.read(animsCount)); - stream.read(states, stream.read(statesCount)); - stream.read(ranges, stream.read(rangesCount)); - stream.read(commands, stream.read(commandsCount)); - stream.read(nodesData, stream.read(nodesDataSize)); - stream.read(frameData, stream.read(frameDataSize)); - // models - models = stream.read(modelsCount) ? new Model[modelsCount] : NULL; - for (int i = 0; i < modelsCount; i++) { - Model &m = models[i]; - uint16 type; - m.type = Entity::Type(stream.read(type)); - stream.seek(sizeof(m.index)); - m.index = i; - stream.read(m.mCount); - stream.read(m.mStart); - stream.read(m.node); - stream.read(m.frame); - stream.read(m.animation); - if (version & VER_PSX) - stream.seek(2); - } - stream.read(staticMeshes, stream.read(staticMeshesCount)); - - if (version == VER_TR2_PSX || version == VER_TR3_PSX) { - stream.read(tiles4, stream.read(tilesCount)); - stream.read(clutsCount); - if (clutsCount > 1024) { // check for japanese version (read kanji CLUT index) - kanjiSprite = clutsCount & 0xFFFF; - stream.seek(-2); - stream.read(clutsCount); - } - if (version == VER_TR3_PSX) - clutsCount *= 2; // read underwater cluts too - stream.read(cluts, clutsCount); - if (version != VER_TR3_PSX) - stream.seek(4); - } - - // textures & UV - if (version != VER_TR3_PC) - readObjectTex(stream); - readSpriteTex(stream); - // palette for demo levels - if (version == VER_TR1_PC && isDemoLevel) stream.read(palette, 256); - // cameras - stream.read(cameras, stream.read(camerasCount)); - // sound sources - stream.read(soundSources, stream.read(soundSourcesCount)); - // AI - boxes = stream.read(boxesCount) ? new Box[boxesCount] : NULL; - for (int i = 0; i < boxesCount; i++) { - Box &b = boxes[i]; - if (version & VER_TR1) { - stream.read(b.minZ); - stream.read(b.maxZ); - stream.read(b.minX); - stream.read(b.maxX); - } - - if (version & (VER_TR2 | VER_TR3)) { - uint8 value; - b.minZ = stream.read(value) * 1024; - b.maxZ = stream.read(value) * 1024; - b.minX = stream.read(value) * 1024; - b.maxX = stream.read(value) * 1024; - } - - stream.read(b.floor); - stream.read(b.overlap.value); - } - - stream.read(overlaps, stream.read(overlapsCount)); - for (int i = 0; i < 2; i++) { - stream.read(zones[i].ground1, boxesCount); - stream.read(zones[i].ground2, boxesCount); - if (!(version & VER_TR1)) { - stream.read(zones[i].ground3, boxesCount); - stream.read(zones[i].ground4, boxesCount); - } else { - zones[i].ground3 = NULL; - zones[i].ground4 = NULL; - } - stream.read(zones[i].fly, boxesCount); - } - - // animated textures - readAnimTex(stream); - - if (version == VER_TR3_PC) - readObjectTex(stream); - - // entities (enemies, items, lara etc.) - readEntities(stream); - - if (version & VER_PC) { - stream.seek(32 * 256); - // palette for release levels - if ((version == VER_TR1_PC) && !isDemoLevel) - stream.read(palette, 256); - // cinematic frames for cameras (PC) - stream.read(cameraFrames, stream.read(cameraFramesCount)); - // demo data - stream.read(demoData, stream.read(demoDataSize)); - } - - if (version == VER_TR2_PSX) - stream.seek(4); - - if (version == VER_TR3_PSX) { - stream.read(skyColor); - - roomTexturesCount = stream.readLE32(); - - if (roomTexturesCount) { - roomTextures = new TextureInfo[roomTexturesCount]; - - // load room textures - for (int i = 0; i < roomTexturesCount; i++) { - readObjectTex(stream, roomTextures[i], TEX_TYPE_ROOM); - stream.seek(2 * 16); // skip 2 mipmap levels - } - } - } - - // sounds - stream.read(soundsMap, (version & VER_TR1) ? 256 : 370); - soundsInfo = stream.read(soundsInfoCount) ? new SoundInfo[soundsInfoCount] : NULL; - for (int i = 0; i < soundsInfoCount; i++) { - SoundInfo &s = soundsInfo[i]; - - stream.read(s.index); - if (version & (VER_TR1 | VER_TR2)) { - uint16 v; - stream.read(v); s.volume = float(v) / 0x7FFF; - stream.read(v); s.chance = float(v) / 0xFFFF; - s.range = 8 * 1024; - s.pitch = 0.2f; - } else { - uint8 v; - stream.read(v); s.volume = float(v) / 0xFF; - stream.read(v); s.range = float(v) * 1024; - stream.read(v); s.chance = float(v) / 0xFF; - stream.read(v); s.pitch = float(v) / 0xFF; - } - - stream.read(s.flags.value); - - ASSERT(s.volume <= 1.0f); - } - - if (version == VER_TR3_PSX) - stream.seek(4); - - if (version == VER_TR1_PC) { - stream.read(soundData, stream.read(soundDataSize)); - stream.read(soundOffsets, stream.read(soundOffsetsCount)); - } - - if (version == VER_TR2_PC || version == VER_TR3_PC) { - stream.read(soundOffsets, stream.read(soundOffsetsCount)); - new Stream(getGameSoundsFile(version), sfxLoadAsync, this); - } - - // cinematic frames for cameras (PSX) - if (version & VER_PSX) { - if (version != VER_TR3_PSX) - stream.seek(4); - stream.read(cameraFrames, stream.read(cameraFramesCount)); + switch (version) { + case VER_TR1_PC : loadTR1_PC (stream); break; + case VER_TR1_PSX : loadTR1_PSX (stream); break; + case VER_TR1_SAT : loadTR1_SAT (stream); break; + case VER_TR2_PC : loadTR2_PC (stream); break; + case VER_TR2_PSX : loadTR2_PSX (stream); break; + case VER_TR3_PC : loadTR3_PC (stream); break; + case VER_TR3_PSX : loadTR3_PSX (stream); break; + case VER_TR4_PC : loadTR4_PC (stream); break; + case VER_TR4_PSX : loadTR4_PSX (stream); break; + case VER_TR4_SDC : loadTR4_SDC (stream); break; + case VER_TR5_PC : loadTR5_PC (stream); break; + case VER_TR5_PSX : loadTR5_PSX (stream); break; + case VER_TR5_SDC : loadTR5_SDC (stream); break; } prepare(); @@ -3007,6 +2681,481 @@ namespace TR { delete[] tsub; } + void loadTR1_PC (Stream &stream) { + stream.read(tiles8, stream.read(tilesCount)); + + readDataArrays(stream); + readObjectTex(stream); + readSpriteTex(stream); + + if (isDemoLevel) { + stream.read(palette, 256); + } + + readCameras(stream); + readSoundSources(stream); + readBoxes(stream); + readOverlaps(stream); + readZones(stream); + readAnimTex(stream); + readEntities(stream); + readLightMap(stream); + + if (!isDemoLevel) { + stream.read(palette, 256); + } + + readCameraFrames(stream); + readDemoData(stream); + readSoundMap(stream); + readSoundData(stream); + readSoundOffsets(stream); + } + + void loadTR1_PSX (Stream &stream) { + if (!isCutsceneLevel()) { + uint32 offsetTexTiles; + stream.seek(8); + stream.read(offsetTexTiles); + // sound offsets + uint16 numSounds; + stream.setPos(22); + stream.read(numSounds); + stream.setPos(2086 + numSounds * 512); + soundOffsetsCount = numSounds; + soundOffsets = new uint32[soundOffsetsCount]; + soundSize = new uint32[soundOffsetsCount]; + soundDataSize = 0; + for (int i = 0; i < soundOffsetsCount; i++) { + soundOffsets[i] = soundDataSize; + uint16 size; + stream.read(size); + soundDataSize += soundSize[i] = size * 8; + } + // sound data + stream.setPos(2600 + numSounds * 512); + stream.read(soundData, soundDataSize); + stream.setPos(offsetTexTiles + 8); + } + + stream.read(tiles4, tilesCount = 13); + stream.read(cluts, clutsCount = 1024); + + readDataArrays(stream); + readObjectTex(stream); + readSpriteTex(stream); + readCameras(stream); + readSoundSources(stream); + readBoxes(stream); + readOverlaps(stream); + readZones(stream); + readAnimTex(stream); + readEntities(stream); + readSoundMap(stream); + stream.seek(4); + readCameraFrames(stream); + } + + void loadTR1_SAT (Stream &stream) { + stream.seek(-4); // no magic header + + // get file name without extension + size_t len = strlen(stream.name); + char *name = new char[len + 1]; + memcpy(name, stream.name, len); + for (int i = int(len) - 1; i >= 0; i--) { + if (name[i] == '/' || name[i] == '\\') + break; + if (name[i] == '.') { + len = i; + break; + } + } + name[len] = 0; + + LOG("load Sega Saturn level: %s\n", name); + + strcat(name, ".SAD"); + Stream sad(name); + name[len] = '\0'; + strcat(name, ".SPR"); + Stream spr(name); + name[len] = '\0'; + strcat(name, ".SND"); + Stream snd(name); + name[len] = '\0'; + strcat(name, ".CIN"); + + Stream *cin = NULL; + if (Stream::existsContent(name)) { + cin = new Stream(name); + } else { + len = strlen(name); + for (int i = int(len) - 1; i >= 0; i--) + if (name[i] == '/' || name[i] == '\\') { + char *newName = new char[len + 11 + 1]; + name[i] = 0; + strcpy(newName, name); + strcat(newName, "/../CINDATA/"); + strcat(newName, name + i + 1); + delete[] name; + name = newName; + break; + } + + if (Stream::existsContent(name)) + cin = new Stream(name); + } + + delete[] name; + + readSAT(sad); + readSAT(spr); + readSAT(snd); + if (cin) { + readCIN(*cin); + delete cin; + } + readSAT(stream); // sat + } + + void loadTR2_PC (Stream &stream) { + stream.read(palette, 256); + stream.read(palette32, 256); + stream.read(tiles8, stream.read(tilesCount)); + stream.read(tiles16, tilesCount); + + readDataArrays(stream); + readObjectTex(stream); + readSpriteTex(stream); + readCameras(stream); + readSoundSources(stream); + readBoxes(stream); + readOverlaps(stream); + readZones(stream); + readAnimTex(stream); + readEntities(stream); + readLightMap(stream); + readCameraFrames(stream); + readDemoData(stream); + readSoundMap(stream); + readSoundOffsets(stream); + + new Stream(getGameSoundsFile(version), sfxLoadAsync, this); + } + + void loadTR2_PSX (Stream &stream) { + stream.read(soundOffsets, stream.read(soundOffsetsCount) + 1); + soundSize = new uint32[soundOffsetsCount]; + soundDataSize = 0; + for (int i = 0; i < soundOffsetsCount; i++) { + ASSERT(soundOffsets[i] < soundOffsets[i + 1]); + soundSize[i] = soundOffsets[i + 1] - soundOffsets[i]; + soundOffsets[i] = soundDataSize; + soundDataSize += soundSize[i]; + } + stream.read(soundData, soundDataSize); + + readDataArrays(stream); + + stream.read(tiles4, stream.read(tilesCount)); + stream.read(clutsCount); + if (clutsCount > 1024) { // check for japanese version (read kanji CLUT index) + kanjiSprite = clutsCount & 0xFFFF; + stream.seek(-2); + stream.read(clutsCount); + } + stream.read(cluts, clutsCount); + stream.seek(4); + readObjectTex(stream); + readSpriteTex(stream); + readCameras(stream); + readSoundSources(stream); + readBoxes(stream); + readOverlaps(stream); + readZones(stream); + readAnimTex(stream); + readEntities(stream); + stream.seek(4); + readSoundMap(stream); + stream.seek(4); + readCameraFrames(stream); + } + + void loadTR3_PC (Stream &stream) { + stream.read(palette, 256); + stream.read(palette32, 256); + stream.read(tiles8, stream.read(tilesCount)); + stream.read(tiles16, tilesCount); + + readDataArrays(stream); + readSpriteTex(stream); + readCameras(stream); + readSoundSources(stream); + readBoxes(stream); + readOverlaps(stream); + readZones(stream); + readAnimTex(stream); + readObjectTex(stream); + readEntities(stream); + readLightMap(stream); + readCameraFrames(stream); + readDemoData(stream); + readSoundMap(stream); + readSoundOffsets(stream); + new Stream(getGameSoundsFile(version), sfxLoadAsync, this); + } + + void loadTR3_PSX (Stream &stream) { + readSoundOffsets(stream); + if (soundOffsetsCount) { + readSoundData(stream); + soundSize = new uint32[soundOffsetsCount]; + int size = 0; + for (int i = 0; i < soundOffsetsCount - 1; i++) { + ASSERT(soundOffsets[i] < soundOffsets[i + 1]); + size += soundSize[i] = soundOffsets[i + 1] - soundOffsets[i]; + } + + if (soundOffsetsCount) { + soundSize[soundOffsetsCount - 1] = soundDataSize; + if (soundOffsetsCount > 1) { + soundSize[soundOffsetsCount - 1] -= soundSize[soundOffsetsCount - 2]; + } + } + } + + // skip code modules + int size; + for (int i = 0; i < 13; i++) { + stream.read(size); + if (size) { + stream.seek(size); + stream.read(size); + stream.seek(size); + } + } + + readDataArrays(stream); + + stream.read(tiles4, stream.read(tilesCount)); + stream.read(clutsCount); + if (clutsCount > 1024) { // check for japanese version (read kanji CLUT index) + kanjiSprite = clutsCount & 0xFFFF; + stream.seek(-2); + stream.read(clutsCount); + } + clutsCount *= 2; // read underwater cluts too + stream.read(cluts, clutsCount); + + readObjectTex(stream); + readSpriteTex(stream); + readCameras(stream); + readSoundSources(stream); + readBoxes(stream); + readOverlaps(stream); + readZones(stream); + readAnimTex(stream); + readEntities(stream); + + stream.read(skyColor); + + roomTexturesCount = stream.readLE32(); + + if (roomTexturesCount) { + roomTextures = new TextureInfo[roomTexturesCount]; + + // load room textures + for (int i = 0; i < roomTexturesCount; i++) { + readObjectTex(stream, roomTextures[i], TEX_TYPE_ROOM); + stream.seek(2 * 16); // skip 2 mipmap levels + } + } + + readSoundMap(stream); + stream.seek(4); + readCameraFrames(stream); + } + + void loadTR4_PC (Stream &stream) { + + } + + void loadTR4_PSX (Stream &stream) { + + } + + void loadTR4_SDC (Stream &stream) { + + } + + void loadTR5_PC (Stream &stream) { + + } + + void loadTR5_PSX (Stream &stream) { + + } + + void loadTR5_SDC (Stream &stream) { + + } + + void readDataArrays(Stream &stream) { + if (version != VER_TR3_PSX) { + stream.seek(4); + } + + rooms = stream.read(roomsCount) ? new Room[roomsCount] : NULL; + for (int i = 0; i < roomsCount; i++) { + readRoom(stream, i); + } + + stream.read(floors, stream.read(floorsCount)); + + if (version == VER_TR3_PSX) { + // outside room offsets + stream.seek(27 * 27 * 2); + // outside rooms table + int size; + stream.read(size); + stream.seek(size); + // room mesh bbox + stream.read(size); + stream.seek(8 * size); + } + + stream.read(meshData, stream.read(meshDataSize)); + stream.read(meshOffsets, stream.read(meshOffsetsCount)); + stream.read(anims, stream.read(animsCount)); + stream.read(states, stream.read(statesCount)); + stream.read(ranges, stream.read(rangesCount)); + stream.read(commands, stream.read(commandsCount)); + stream.read(nodesData, stream.read(nodesDataSize)); + stream.read(frameData, stream.read(frameDataSize)); + + readModels(stream); + + stream.read(staticMeshes, stream.read(staticMeshesCount)); + } + + void readModels(Stream &stream) { + models = stream.read(modelsCount) ? new Model[modelsCount] : NULL; + for (int i = 0; i < modelsCount; i++) { + Model &m = models[i]; + uint16 type; + m.type = Entity::Type(stream.read(type)); + stream.seek(sizeof(m.index)); + m.index = i; + stream.read(m.mCount); + stream.read(m.mStart); + stream.read(m.node); + stream.read(m.frame); + stream.read(m.animation); + if (version & VER_PSX) { + stream.seek(2); + } + } + } + + void readCameras(Stream &stream) { + stream.read(cameras, stream.read(camerasCount)); + } + + void readSoundSources(Stream &stream) { + stream.read(soundSources, stream.read(soundSourcesCount)); + } + + void readBoxes(Stream &stream) { + boxes = stream.read(boxesCount) ? new Box[boxesCount] : NULL; + for (int i = 0; i < boxesCount; i++) { + Box &b = boxes[i]; + if (version & VER_TR1) { + stream.read(b.minZ); + stream.read(b.maxZ); + stream.read(b.minX); + stream.read(b.maxX); + } + + if (version & (VER_TR2 | VER_TR3)) { + uint8 value; + b.minZ = stream.read(value) * 1024; + b.maxZ = stream.read(value) * 1024; + b.minX = stream.read(value) * 1024; + b.maxX = stream.read(value) * 1024; + } + + stream.read(b.floor); + stream.read(b.overlap.value); + } + } + + void readOverlaps(Stream &stream) { + stream.read(overlaps, stream.read(overlapsCount)); + } + + void readZones(Stream &stream) { + for (int i = 0; i < 2; i++) { + stream.read(zones[i].ground1, boxesCount); + stream.read(zones[i].ground2, boxesCount); + if (!(version & VER_TR1)) { + stream.read(zones[i].ground3, boxesCount); + stream.read(zones[i].ground4, boxesCount); + } else { + zones[i].ground3 = NULL; + zones[i].ground4 = NULL; + } + stream.read(zones[i].fly, boxesCount); + } + } + + void readLightMap(Stream &stream) { + stream.seek(32 * 256); // unused + } + + void readCameraFrames(Stream &stream) { + stream.read(cameraFrames, stream.read(cameraFramesCount)); + } + + void readDemoData(Stream &stream) { + stream.read(demoData, stream.read(demoDataSize)); + } + + void readSoundMap(Stream &stream) { + stream.read(soundsMap, (version & VER_TR1) ? 256 : 370); + soundsInfo = stream.read(soundsInfoCount) ? new SoundInfo[soundsInfoCount] : NULL; + for (int i = 0; i < soundsInfoCount; i++) { + SoundInfo &s = soundsInfo[i]; + + stream.read(s.index); + if (version & (VER_TR1 | VER_TR2)) { + uint16 v; + stream.read(v); s.volume = float(v) / 0x7FFF; + stream.read(v); s.chance = float(v) / 0xFFFF; + s.range = 8 * 1024; + s.pitch = 0.2f; + } else { + uint8 v; + stream.read(v); s.volume = float(v) / 0xFF; + stream.read(v); s.range = float(v) * 1024; + stream.read(v); s.chance = float(v) / 0xFF; + stream.read(v); s.pitch = float(v) / 0xFF; + } + + stream.read(s.flags.value); + + ASSERT(s.volume <= 1.0f); + } + } + + void readSoundData(Stream &stream) { + stream.read(soundData, stream.read(soundDataSize)); + } + + void readSoundOffsets(Stream &stream) { + stream.read(soundOffsets, stream.read(soundOffsetsCount)); + } + #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) | \ ((uint64)((const char*)(str))[4] << 32) | ((uint64)((const char*)(str))[5] << 40) | ((uint64)((const char*)(str))[6] << 48) | ((uint64)((const char*)(str))[7] << 56)) @@ -3439,7 +3588,6 @@ namespace TR { case CHUNK("ROOMEND ") : ASSERTV(stream.readBE32() == 0x00000000); ASSERTV(stream.readBE32() == 0x00000000); - prepare(); break; // SAD case CHUNK("OBJFILE ") : @@ -4044,7 +4192,7 @@ namespace TR { TextureInfo &t = objectTextures[f.flags.texture]; if (t.type != TEX_TYPE_OBJECT) { if (!dupObjTex) { - dupObjTex = new TextureInfo[128]; + dupObjTex = new TextureInfo[256]; } int index = 0; @@ -4056,7 +4204,7 @@ namespace TR { } if (index == dupObjTexCount) { - ASSERT(index <= 128); + ASSERT(index <= 256); dupObjTex[dupObjTexCount] = t; dupObjTex[dupObjTexCount].type = TEX_TYPE_OBJECT; dupObjTexCount++; diff --git a/src/gameflow.h b/src/gameflow.h index f24b1ba..0adce99 100644 --- a/src/gameflow.h +++ b/src/gameflow.h @@ -18,15 +18,16 @@ namespace TR { enum Version { VER_UNKNOWN = 0, - VER_PC = 256, - VER_PSX = 512, - VER_SAT = 1024, + VER_PC = 0x1000, + VER_PSX = 0x2000, + VER_SAT = 0x4000, + VER_SDC = 0x8000, - VER_TR1 = 1, - VER_TR2 = 2, - VER_TR3 = 4, - VER_TR4 = 8, - VER_TR5 = 16, + VER_TR1 = 0x01, + VER_TR2 = 0x02, + VER_TR3 = 0x04, + VER_TR4 = 0x08, + VER_TR5 = 0x10, VER_VERSION = VER_TR1 | VER_TR2 | VER_TR3 | VER_TR4 | VER_TR5, VER_PLATFORM = VER_PC | VER_PSX | VER_SAT, @@ -41,6 +42,14 @@ namespace TR { VER_TR3_PC = VER_TR3 | VER_PC, VER_TR3_PSX = VER_TR3 | VER_PSX, + VER_TR4_PC = VER_TR4 | VER_PC, + VER_TR4_PSX = VER_TR4 | VER_PSX, + VER_TR4_SDC = VER_TR4 | VER_SDC, + + VER_TR5_PC = VER_TR5 | VER_PC, + VER_TR5_PSX = VER_TR5 | VER_PSX, + VER_TR5_SDC = VER_TR5 | VER_SDC, + VER_MAX = 0xFFFFFFFF, }; diff --git a/src/gapi/c3d.h b/src/gapi/c3d.h index eea06b9..2be7147 100644 --- a/src/gapi/c3d.h +++ b/src/gapi/c3d.h @@ -466,13 +466,13 @@ namespace GAPI { C3D_AttrInfo vertexAttribs; void init() { + gfxInitDefault(); + consoleInit(GFX_BOTTOM, NULL); + LOG("Vendor : %s\n", "Nintendo"); LOG("Renderer : %s\n", "PICA200 citro3D"); LOG("Version : %s\n", "1.0"); - gfxInitDefault(); - consoleInit(GFX_BOTTOM, NULL); - C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); defTarget[0] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); defTarget[1] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);