diff --git a/src/fixed/common.cpp b/src/fixed/common.cpp index 9f1930a..1d3b020 100644 --- a/src/fixed/common.cpp +++ b/src/fixed/common.cpp @@ -1594,60 +1594,4 @@ void dmaCopy(const void* src, void* dst, uint32 size) #endif } -Stream::Stream(const uint8* data, int32 size) : data(data), size(size), pos(0) -{ - // -} - -const void* Stream::getPtr() -{ - return data + pos; -} - -uint8 Stream::read8u() -{ - return data[pos++]; -} - -uint16 Stream::read16u() -{ - uint32 a = data[pos++]; - uint32 b = data[pos++]; - - if (bigEndian) { - return b | (a << 8); - } else { - return a | (b << 8); - } -} - -uint32 Stream::read32u() -{ - uint32 a = data[pos++]; - uint32 b = data[pos++]; - uint32 c = data[pos++]; - uint32 d = data[pos++]; - - if (bigEndian) { - return d | (c << 8) | (b << 16) | (a << 24); - } else { - return a | (b << 8) | (c << 16) | (d << 24); - } -} - -int8 Stream::read8s() -{ - return (int8)read8u(); -} - -int16 Stream::read16s() -{ - return (int16)read16u(); -} - -int32 Stream::read32s() -{ - return (int32)read32u(); -} - #endif diff --git a/src/fixed/common.h b/src/fixed/common.h index faff226..8a80f51 100644 --- a/src/fixed/common.h +++ b/src/fixed/common.h @@ -2928,24 +2928,4 @@ void updateFading(int32 frames); void dmaFill(void* dst, uint8 value, uint32 count); void dmaCopy(const void* src, void* dst, uint32 size); -struct Stream -{ - const uint8* data; - int32 size; - int32 pos; - bool bigEndian; - - Stream(const uint8* data, int32 size); - - const void* getPtr(); - - uint8 read8u(); - uint16 read16u(); - uint32 read32u(); - - int8 read8s(); - int16 read16s(); - int32 read32s(); -}; - #endif diff --git a/src/fixed/fmt/phd.h b/src/fixed/fmt/phd.h index f487f2b..a5ce3a0 100644 --- a/src/fixed/fmt/phd.h +++ b/src/fixed/fmt/phd.h @@ -2,94 +2,269 @@ #define H_PHD #include "common.h" +#include "stream.h" -struct PHD +bool read_PHD(Stream &f) { - struct RoomVertex - { - int16 x, y, z; - uint16 lighting; - }; + uint8* ptr = gLevelData; - struct RoomQuad - { - uint16 indices[4]; - uint16 flags; - }; - - struct RoomTriangle - { - uint16 indices[3]; - uint16 flags; - }; - - struct RoomSprite - { - uint16 index; - uint16 texture; - }; - - struct RoomPortal - { - int16 roomIndex; - vec3s normal; - vec3s vertices[4]; - }; -}; - -RoomInfo roomsInfo_phd[MAX_ROOMS]; - -bool read_PHD(const uint8* data) -{ -/* TODO - Stream stream(data, 0); - - uint32 magic = stream.read32u(); + uint32 magic = f.read32u(); if (magic != 0x00000020) - { - LOG("Unsupported level format\n"); - return; - } + return false; level.version = VER_TR1_PC; - level.tilesCount = stream.read32u(); - level.tiles = (uint8*)stream.getPtr(); - stream.pos += 4; + level.tilesCount = f.read32u(); + level.tiles = (uint8*)f.getPtr(); - level.roomsCount = stream.read16u(); - level.roomsInfo = phd_roomsInfo; + f.seek(level.tilesCount * 256 * 256 + 4); + + level.roomsCount = f.read16u(); + level.roomsInfo = (RoomInfo*)ptr; + ptr += level.roomsCount * sizeof(RoomInfo); for (uint32 i = 0; i < level.roomsCount; i++) { - RoomInfo* info = phd_roomsInfo + i; + RoomInfo* info = (RoomInfo*)level.roomsInfo + i; - info->x = stream.read32s(); - info->z = stream.read32s(); - info->yBottom = stream.read32s(); - info->yTop = stream.read32s(); + info->x = f.read32s() >> 8; + info->z = f.read32s() >> 8; + f.seek(4 + 4 + 4); - info->verticesCount = stream.read16u(); - info->data.vertices = (RoomVertex*)stream.getPtr(); - stream.pos += sizeof(PHD::RoomVertex) * info->verticesCount; + info->verticesCount = f.read16u(); + info->data.vertices = (RoomVertex*)ptr; - info->quadsCount = stream.read16u(); - info->data.quads = (RoomQuad*)stream.getPtr(); - stream.pos += sizeof(PHD::RoomQuad) * info->quadsCount; + int32 vertDataPos = f.getPos(); - info->trianglesCount = stream.read16u(); - info->data.triangles = (RoomTriangle*)stream.getPtr(); - stream.pos += sizeof(PHD::RoomTriangle) * info->trianglesCount; + int32 yb = -32768; + int32 yt = 32767; - info->spritesCount = stream.read16u(); - info->data.sprites = (RoomSprite*)stream.getPtr(); - stream.pos += sizeof(PHD::RoomSprite) * info->spritesCount; + f.seek(2); // skip x + for (uint32 j = 0; j < info->verticesCount; j++) + { + int32 y = f.read16s(); // read y - info->portalsCount = stream.read16u(); - info->data.portals = (RoomPortal*)stream.getPtr(); - stream.pos += sizeof(PHD::RoomPortal) * info->portalsCount; + if (y < yt) { + yt = y; + } + if (y > yb) { + yb = y; + } + + f.seek(2 + 2 + 2); // skip z, g, x + } + + info->yBottom = yb; + info->yTop = yt; + + f.setPos(vertDataPos); + + for (uint32 j = 0; j < info->verticesCount; j++) + { + RoomVertex *v = (RoomVertex*)ADDR_ALIGN4(ptr); + ptr += sizeof(RoomVertex); + + v->x = f.read16s() >> 8; + v->y = (f.read16s() - yt) >> 8; + v->z = f.read16s() >> 8; + v->g = f.read16u() >> 3; + } + + info->quadsCount = f.read16u(); + info->data.quads = (RoomQuad*)ADDR_ALIGN4(ptr); + for (uint32 j = 0; j < info->quadsCount; j++) + { + RoomQuad *q = (RoomQuad*)ptr; + ptr += sizeof(RoomQuad); + + q->indices[0] = f.read16u(); + q->indices[1] = f.read16u(); + q->indices[2] = f.read16u(); + q->indices[3] = f.read16u(); + q->flags = f.read16u(); + } + + info->trianglesCount = f.read16u(); + info->data.triangles = (RoomTriangle*)ADDR_ALIGN4(ptr); + for (uint32 j = 0; j < info->trianglesCount; j++) + { + RoomTriangle *t = (RoomTriangle*)ptr; + ptr += sizeof(RoomTriangle); + + t->indices[0] = f.read16u(); + t->indices[1] = f.read16u(); + t->indices[2] = f.read16u(); + t->flags = f.read16u(); + } + + info->spritesCount = f.read16u(); + info->data.sprites = (RoomSprite*)ADDR_ALIGN4(ptr); + for (uint32 j = 0; j < info->spritesCount; j++) + { + RoomSprite *s = (RoomSprite*)ptr; + ptr += sizeof(RoomSprite); + + int32 idx = f.read16u(); + s->index = f.read16u() * 0xFF; + + int32 pos = f.getPos(); + f.setPos(vertDataPos + 8 * idx); + + s->pos.x = f.read16u(); + s->pos.y = f.read16u(); + s->pos.z = f.read16u(); + s->g = f.read16u() >> 3; + + f.setPos(pos); + } + + info->portalsCount = uint8(f.read16u()); + info->data.portals = (Portal*)ADDR_ALIGN4(ptr); + for (uint32 j = 0; j < info->portalsCount; j++) + { + Portal *p = (Portal*)ptr; + ptr += sizeof(Portal); + + p->roomIndex = f.read16s(); + p->n.x = f.read16s(); + p->n.y = f.read16s(); + p->n.z = f.read16s(); + for (int32 k = 0; k < 4; k++) + { + p->v[k].x = f.read16s(); + p->v[k].y = f.read16s(); + p->v[k].z = f.read16s(); + } + } + + info->zSectors = uint8(f.read16u()); + info->xSectors = uint8(f.read16u()); + info->data.sectors = (Sector*)ADDR_ALIGN4(ptr); + for (uint32 j = 0; j < uint32(info->zSectors) * uint32(info->xSectors); j++) + { + Sector *s = (Sector*)ptr; + ptr += sizeof(Sector); + + s->floorIndex = f.read16u(); + s->boxIndex = f.read16u(); + s->roomBelow = f.read8u(); + s->floor = f.read8s(); + s->roomAbove = f.read8u(); + s->ceiling = f.read8s(); + } + + info->ambient = f.read16u() >> 5; // TODO 3? + + info->lightsCount = uint8(f.read16u()); + info->data.lights = (Light*)ADDR_ALIGN4(ptr); + for (uint32 j = 0; j < info->lightsCount; j++) + { + Light *l = (Light*)ptr; + ptr += sizeof(Light); + + l->pos.x = f.read32s() - (info->x << 8); + l->pos.y = f.read32s(); + l->pos.z = f.read32s() - (info->z << 8); + l->intensity = f.read16s() >> 5; // TODO 3? + l->radius = f.read32s() >> 8; + } + + info->meshesCount = uint8(f.read16u()); + info->data.meshes = (RoomMesh*)ADDR_ALIGN4(ptr); + for (uint32 j = 0; j < info->meshesCount; j++) + { + RoomMesh *m = (RoomMesh*)ptr; + ptr += sizeof(RoomMesh); + + vec3s pos; + uint8 intensity; + uint8 flags; + + pos.x = f.read32s() - (info->x << 8); + pos.y = f.read32s(); + pos.z = f.read32s() - (info->z << 8); + flags = ((f.read16s() / 0x4000 + 2) << 6); + intensity = f.read16u() >> 5; // TODO 3? + flags |= f.read16u(); + + m->xy = (pos.x << 16) | uint16(pos.y); + m->zf = (pos.z << 16) | (intensity << 8) | flags; + } + + info->alternateRoom = uint8(f.read16s()); + uint16 flags = f.read16u(); + + info->flags = 0; + if (flags & 1) info->flags |= 1; // TODO 1? + if (flags & 256) info->flags |= 2; // TODO 2? } -*/ - return false; + + { // floors data + uint32 floorsCount = f.read32u(); + level.floors = (FloorData*)ADDR_ALIGN4(ptr); + FloorData *fd = (FloorData*)ptr; + for (uint32 i = 0; i < floorsCount; i++) + { + fd[i] = f.read16u(); + } + ptr += sizeof(FloorData) * floorsCount; + } + + { // mesh data + uint32 meshDataSize = f.read32u(); + level.meshes = (const Mesh**)ADDR_ALIGN4(ptr); + + int32 meshDataPos = f.getPos(); + f.seek(meshDataSize * sizeof(uint16)); + + level.meshesCount = f.read32u(); + f.seek(level.meshesCount * sizeof(uint32)); + + // TODO + ptr += meshDataSize * sizeof(uint32); + } + + { // anims + uint32 animsCount = f.read32u(); + level.anims = (Anim*)ADDR_ALIGN4(ptr); + for (uint32 i = 0; i < animsCount; i++) + { + Anim* anim = (Anim*)ptr; + ptr += sizeof(Anim); + + anim->frameOffset = f.read32u(); + anim->frameRate = f.read8u(); + anim->frameSize = f.read8u(); + anim->state = f.read16u(); + anim->speed = f.read32u(); + anim->accel = f.read32u(); + anim->frameBegin = f.read16u(); + anim->frameEnd = f.read16u(); + anim->nextAnimIndex = f.read16u(); + anim->nextFrameIndex = f.read16u(); + anim->statesCount = f.read16u(); + anim->statesStart = f.read16u(); + anim->commandsCount = f.read16u(); + anim->commandsStart = f.read16u(); + } + } + + { // states + uint32 animStatesCount = f.read32u(); + level.animStates = (AnimState*)ADDR_ALIGN4(ptr); + for (uint32 i = 0; i < animStatesCount; i++) + { + AnimState* animState = (AnimState*)ptr; + ptr += sizeof(AnimState); + + animState->state = uint8(f.read16u()); + animState->rangesCount = uint8(f.read16u()); + animState->rangesStart = f.read16u(); + } + } + + // TODO + + return true; } #endif diff --git a/src/fixed/fmt/pkd.h b/src/fixed/fmt/pkd.h index e7ed88a..2271465 100644 --- a/src/fixed/fmt/pkd.h +++ b/src/fixed/fmt/pkd.h @@ -2,9 +2,12 @@ #define H_PKD #include "common.h" +#include "stream.h" -bool read_PKD(const uint8* data) +bool read_PKD(Stream &f) { + const uint8* data = f.getPtr(); + memcpy(&level, data, sizeof(level)); { // fix level data offsets diff --git a/src/fixed/level.h b/src/fixed/level.h index f2cb3b9..aee999e 100644 --- a/src/fixed/level.h +++ b/src/fixed/level.h @@ -2,6 +2,7 @@ #define H_LEVEL #include "common.h" +#include "stream.h" Level level; @@ -58,18 +59,24 @@ void readLevel(const uint8* data) gAnimTexFrame = 0; + Stream f(data, 0); + +#ifdef CPU_BIG_ENDIAN + f.bigEndian = true; +#endif + #if (USE_FMT & LVL_FMT_PKD) - if (read_PKD(data)) + if (read_PKD(f)) return; #endif #if (USE_FMT & LVL_FMT_PHD) - if (read_PHD(data)) + if (read_PHD(f)) return; #endif #if (USE_FMT & LVL_FMT_PSX) - if (read_PSX(data)) + if (read_PSX(f)) return; #endif diff --git a/src/fixed/stream.h b/src/fixed/stream.h new file mode 100644 index 0000000..8128342 --- /dev/null +++ b/src/fixed/stream.h @@ -0,0 +1,89 @@ +#ifndef H_STREAM +#define H_STREAM + +#include "common.h" + +struct Stream +{ + const uint8* data; + int32 size; + int32 pos; + bool bigEndian; + + Stream(const uint8* data, int32 size) : data(data), size(size), pos(0), bigEndian(false) + { + // + } + + const uint8* getPtr() + { + return data + pos; + } + + int32 getPos() + { + return pos; + } + + void setPos(int32 newPos) + { + pos = newPos; + } + + void seek(int32 offset) + { + pos += offset; + } + + X_INLINE uint8 read8u() + { + return data[pos++]; + } + + X_INLINE int8 read8s() + { + return (int8)read8u(); + } + + uint16 read16u() + { + const uint8* ptr = data + pos; + pos += 2; + + uint16 n; + if (intptr_t(ptr) & 1) { + n = ptr[0] | (ptr[1] << 8); + } else { + n = *(uint16*)ptr; + } + + return bigEndian ? swap16(n) : n; + } + + X_INLINE int16 read16s() + { + return (int16)read16u(); + } + + uint32 read32u() + { + const uint8* ptr = data + pos; + pos += 4; + + uint32 n; + if (intptr_t(ptr) & 3) { + n = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); + } else { + n = *(uint32*)ptr; + } + + return bigEndian ? swap32(n) : n; + } + + X_INLINE int32 read32s() + { + return (int32)read32u(); + } +}; + +#endif