diff --git a/common/array.cpp b/common/array.cpp index 43711a2b..6b22e6a2 100755 --- a/common/array.cpp +++ b/common/array.cpp @@ -208,7 +208,7 @@ void ObjArray::Expand(int Grow) { if ((m_Length + Grow) > m_Alloc) { - int NewSize = ((m_Length + Grow) / m_Grow + 1) * m_Grow; + int NewSize = ((m_Length + Grow + m_Grow - 1) / m_Grow) * m_Grow; T* NewData = new T[NewSize]; @@ -252,6 +252,13 @@ void ObjArray::Add(const T& Obj) m_Data[m_Length++] = Obj; } +template +T& ObjArray::Add() +{ + Expand(1); + return m_Data[m_Length++]; +} + template void ObjArray::AddSorted (const T& Obj, LC_OBJARRAY_COMPARE_FUNC Func, void* SortData) { diff --git a/common/array.h b/common/array.h index c2ad6bb0..27656ab3 100755 --- a/common/array.h +++ b/common/array.h @@ -13,6 +13,7 @@ public: int GetSize() const { return m_nLength; } void SetSize(int Size); + void Expand(int nGrow); T* RemoveIndex(int nIndex); T* RemovePointer(T* pObj); @@ -30,8 +31,6 @@ public: { return m_pData[nIndex]; } protected: - void Expand(int nGrow); - T** m_pData; int m_nLength; int m_nAlloc; @@ -52,7 +51,9 @@ public: void RemoveIndex(int Index); void RemoveAll(); void SetSize(int NewSize); + void Expand(int Grow); void Add(const T& Obj); + T& Add(); void AddSorted(const T& Obj, LC_OBJARRAY_COMPARE_FUNC Func, void* SortData); void InsertAt(int Index, const T& Obj); @@ -60,8 +61,6 @@ public: { return m_Data[Index]; } protected: - void Expand(int Grow); - T* m_Data; int m_Length; int m_Alloc; diff --git a/common/lc_library.cpp b/common/lc_library.cpp index fca810bb..c61b7cb1 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -1,15 +1,581 @@ #include "lc_global.h" #include "lc_library.h" +#include "lc_zipfile.h" +#include "lc_file.h" +#include "pieceinf.h" +#include "lc_colors.h" lcPiecesLibrary::lcPiecesLibrary() { + mZipFile = NULL; } lcPiecesLibrary::~lcPiecesLibrary() { + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + delete mPieces[PieceIdx]; + + delete mZipFile; } -bool lcPiecesLibrary::OpenArchive(const char* LibPath) +bool lcPiecesLibrary::OpenArchive(const char* FileName) { + mZipFile = new lcZipFile(); + + if (!mZipFile->Open(FileName)) + { + delete mZipFile; + mZipFile = NULL; + return false; + } + + for (int FileIdx = 0; FileIdx < mZipFile->mFiles.GetSize(); FileIdx++) + { + lcZipFileInfo& FileInfo = mZipFile->mFiles[FileIdx]; + char Name[LC_PIECE_NAME_LEN]; + + const char* Src = FileInfo.file_name; + char* Dst = Name; + + while (*Src && Dst - Name < LC_PIECE_NAME_LEN) + { + if (*Src >= 'a' && *Src <= 'z') + *Dst = *Src + 'A' - 'a'; + else if (*Src == '\\') + *Dst = '/'; + else + *Dst = *Src; + + Src++; + Dst++; + } + + if (Dst - Name <= 4) + continue; + + Dst -= 4; + if (memcmp(Dst, ".DAT", 4)) + continue; + *Dst = 0; + + if (memcmp(Name, "LDRAW/", 6)) + continue; + + if (!memcmp(Name + 6, "PARTS/", 6)) + { + if (memcmp(Name + 12, "S/", 2)) + { + PieceInfo* Info = new PieceInfo(); + mPieces.Add(Info); + + strncpy(Info->m_strName, Name + 12, sizeof(Info->m_strName)); + Info->m_strName[sizeof(Info->m_strName) - 1] = 0; + + Info->m_nFlags = 0; + Info->m_nOffset = FileIdx; + } + else + { + lcLibraryPrimitive* Prim = new lcLibraryPrimitive(); + mPrimitives.Add(Prim); + strncpy(Prim->mName, Name + 12, sizeof(Prim->mName)); + Prim->mName[sizeof(Prim->mName) - 1] = 0; + Prim->mZipFileIndex = FileIdx; + Prim->mLoaded = false; + Prim->mStud = false; + Prim->mSubFile = true; + } + } + else if (!memcmp(Name + 6, "P/", 2)) + { + lcLibraryPrimitive* Prim = new lcLibraryPrimitive(); + mPrimitives.Add(Prim); + strncpy(Prim->mName, Name + 8, sizeof(Prim->mName)); + Prim->mName[sizeof(Prim->mName) - 1] = 0; + Prim->mZipFileIndex = FileIdx; + Prim->mLoaded = false; + Prim->mStud = (memcmp(Prim->mName, "STU", 3) == 0); + Prim->mSubFile = false; + } + } + + lcMemFile PieceFile; + + for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++) + { + PieceInfo* Info = mPieces[PieceInfoIndex]; + + mZipFile->ExtractFile(Info->m_nOffset, PieceFile, 256); + PieceFile.Seek(0, SEEK_END); + PieceFile.WriteU8(0); + + char* Src = (char*)PieceFile.mBuffer + 2; + char* Dst = Info->m_strDescription; + + for (;;) + { + if (*Src != '\r' && *Src != '\n' && *Src && Dst - Info->m_strDescription < sizeof(Info->m_strDescription) - 1) + { + *Dst++ = *Src++; + continue; + } + + *Dst = 0; + break; + } + } + return true; } + +bool lcPiecesLibrary::LoadPiece(const char* PieceName) +{ + for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++) + { + PieceInfo* Info = mPieces[PieceInfoIndex]; + + if (!strcmp(Info->m_strName, PieceName)) + return LoadPiece(PieceInfoIndex); + } + + return false; +} + +bool lcPiecesLibrary::LoadPiece(int PieceIndex) +{ + PieceInfo* Info = mPieces[PieceIndex]; + lcMemFile PieceFile; + lcLibraryMeshData MeshData; + + if (!mZipFile->ExtractFile(Info->m_nOffset, PieceFile)) + return false; + + if (!ReadMeshData(PieceFile, lcMatrix44Identity(), 16, MeshData)) + return false; + + lcMesh* Mesh = new lcMesh(); + + int NumIndices = 0; + + for (int SectionIdx = 0; SectionIdx < MeshData.mSections.GetSize(); SectionIdx++) + NumIndices += MeshData.mSections[SectionIdx]->mIndices.GetSize(); + + Mesh->Create(MeshData.mSections.GetSize(), MeshData.mVertices.GetSize(), NumIndices); + + lcVector3* DstVerts = (lcVector3*)Mesh->mVertexBuffer.mData; + lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX), Max(-FLT_MAX, -FLT_MAX, -FLT_MAX); + + for (int VertexIdx = 0; VertexIdx < MeshData.mVertices.GetSize(); VertexIdx++) + { + const lcVector3& SrcVertex = MeshData.mVertices[VertexIdx]; + lcVector3& Vertex = *DstVerts++; + Vertex = lcVector3(SrcVertex.x / 25.0f, SrcVertex.z / 25.0f, -SrcVertex.y / 25.0f); + + Min.x = lcMin(Min.x, Vertex.x); + Min.y = lcMin(Min.y, Vertex.y); + Min.z = lcMin(Min.z, Vertex.z); + Max.x = lcMax(Max.x, Vertex.x); + Max.y = lcMax(Max.y, Vertex.y); + Max.z = lcMax(Max.z, Vertex.z); + } + + Info->m_fDimensions[0] = Max.x; + Info->m_fDimensions[1] = Max.y; + Info->m_fDimensions[2] = Max.z; + Info->m_fDimensions[3] = Min.x; + Info->m_fDimensions[4] = Min.y; + Info->m_fDimensions[5] = Min.z; + + NumIndices = 0; + + for (int SectionIdx = 0; SectionIdx < MeshData.mSections.GetSize(); SectionIdx++) + { + lcMeshSection& DstSection = Mesh->mSections[SectionIdx]; + lcLibraryMeshSection* SrcSection = MeshData.mSections[SectionIdx]; + + DstSection.ColorIndex = lcGetColorIndex(SrcSection->mColorCode); + DstSection.PrimitiveType = SrcSection->mTriangles ? GL_TRIANGLES : GL_LINES; + DstSection.NumIndices = SrcSection->mIndices.GetSize(); + + if (Mesh->mNumVertices < 0x10000) + { + DstSection.IndexOffset = NumIndices * 2; + + lcuint16* Index = (lcuint16*)Mesh->mIndexBuffer.mData + NumIndices; + + for (int IndexIdx = 0; IndexIdx < DstSection.NumIndices; IndexIdx++) + *Index++ = SrcSection->mIndices[IndexIdx]; + } + else + { + DstSection.IndexOffset = NumIndices * 4; + + lcuint32* Index = (lcuint32*)Mesh->mIndexBuffer.mData + NumIndices; + + for (int IndexIdx = 0; IndexIdx < DstSection.NumIndices; IndexIdx++) + *Index++ = SrcSection->mIndices[IndexIdx]; + } + + if (SrcSection->mTriangles) + { + if (SrcSection->mColorCode == 16) + Info->m_nFlags |= LC_PIECE_HAS_DEFAULT; + else + { + if (lcIsColorTranslucent(DstSection.ColorIndex)) + Info->m_nFlags |= LC_PIECE_HAS_TRANSLUCENT; + else + Info->m_nFlags |= LC_PIECE_HAS_SOLID; + } + } + else + Info->m_nFlags |= LC_PIECE_HAS_LINES; + + NumIndices += DstSection.NumIndices; + } + + Mesh->UpdateBuffers(); + Info->mMesh = Mesh; + + return true; +} + +int lcPiecesLibrary::FindPrimitiveIndex(const char* Name) +{ + for (int PrimitiveIndex = 0; PrimitiveIndex < mPrimitives.GetSize(); PrimitiveIndex++) + if (!strcmp(mPrimitives[PrimitiveIndex]->mName, Name)) + return PrimitiveIndex; + + return -1; +} + +bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) +{ + lcLibraryPrimitive* Primitive = mPrimitives[PrimitiveIndex]; + lcMemFile File; + + if (!mZipFile->ExtractFile(Primitive->mZipFileIndex, File)) + return false; + + if (!ReadMeshData(File, lcMatrix44Identity(), 16, Primitive->mMeshData)) + return false; + + Primitive->mLoaded = true; + + return true; +} + +bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcLibraryMeshData& MeshData) +{ + char Line[1024]; + + while (File.ReadLine(Line, sizeof(Line))) + { + lcuint32 ColorCode, ColorCodeHex; + int LineType; + + if (sscanf(Line, "%d", &LineType) != 1) + continue; + + if (LineType < 1 || LineType > 4) + continue; + + if (sscanf(Line, "%d %d", &LineType, &ColorCode) != 2) + continue; + + if (ColorCode == 0) + { + sscanf(Line, "%d %i", &LineType, &ColorCodeHex); + + if (ColorCode != ColorCodeHex) + ColorCode = ColorCodeHex | LC_COLOR_DIRECT; + } + + if (ColorCode == 16) + ColorCode = CurrentColorCode; + + int Dummy; + lcVector3 Points[4]; + + switch (LineType) + { + case 1: + { + char FileName[LC_MAXPATH]; + float fm[12]; + + sscanf(Line, "%d %i %f %f %f %f %f %f %f %f %f %f %f %f %s", &LineType, &Dummy, &fm[0], &fm[1], &fm[2], &fm[3], &fm[4], &fm[5], &fm[6], &fm[7], &fm[8], &fm[9], &fm[10], &fm[11], FileName); + + char* Ch; + for (Ch = FileName; *Ch; Ch++) + { + if (*Ch >= 'a' && *Ch <= 'z') + *Ch = *Ch + 'A' - 'a'; + else if (*Ch == '\\') + *Ch = '/'; + } + + if (Ch - FileName > 4) + { + Ch -= 4; + if (!memcmp(Ch, ".DAT", 4)) + *Ch = 0; + } + + int PrimitiveIndex = FindPrimitiveIndex(FileName); + lcMatrix44 IncludeTransform(lcVector4(fm[3], fm[6], fm[9], 0.0f), lcVector4(fm[4], fm[7], fm[10], 0.0f), lcVector4(fm[5], fm[8], fm[11], 0.0f), lcVector4(fm[0], fm[1], fm[2], 1.0f)); + IncludeTransform = lcMul(IncludeTransform, CurrentTransform); + + if (PrimitiveIndex != -1) + { + lcLibraryPrimitive* Primitive = mPrimitives[PrimitiveIndex]; + + if (!Primitive->mLoaded && !LoadPrimitive(PrimitiveIndex)) + continue; + + if (Primitive->mStud) + MeshData.AddMeshDataNoDuplicateCheck(Primitive->mMeshData, IncludeTransform, ColorCode); + else if (!Primitive->mSubFile) + MeshData.AddMeshData(Primitive->mMeshData, IncludeTransform, ColorCode); + else + { + lcMemFile IncludeFile; + + if (!mZipFile->ExtractFile(Primitive->mZipFileIndex, IncludeFile)) + continue; + + if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData)) + continue; + } + } + else + { + for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++) + { + PieceInfo* Info = mPieces[PieceInfoIndex]; + + if (strcmp(Info->m_strName, FileName)) + continue; + + lcMemFile IncludeFile; + + if (!mZipFile->ExtractFile(Info->m_nOffset, IncludeFile)) + break; + + if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData)) + break; + + break; + } + } + } break; + + case 2: + { + sscanf(Line, "%d %i %f %f %f %f %f %f", &LineType, &Dummy, &Points[0].x, &Points[0].y, &Points[0].z, &Points[1].x, &Points[1].y, &Points[1].z); + + Points[0] = lcMul31(Points[0], CurrentTransform); + Points[1] = lcMul31(Points[1], CurrentTransform); + + MeshData.AddLine(LineType, ColorCode, Points); + } break; + + case 3: + { + sscanf(Line, "%d %i %f %f %f %f %f %f %f %f %f", &LineType, &Dummy, &Points[0].x, &Points[0].y, &Points[0].z, + &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z); + + Points[0] = lcMul31(Points[0], CurrentTransform); + Points[1] = lcMul31(Points[1], CurrentTransform); + Points[2] = lcMul31(Points[2], CurrentTransform); + + MeshData.AddLine(LineType, ColorCode, Points); + } break; + + case 4: + { + sscanf(Line, "%d %i %f %f %f %f %f %f %f %f %f %f %f %f", &LineType, &Dummy, &Points[0].x, &Points[0].y, &Points[0].z, + &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z, &Points[3].x, &Points[3].y, &Points[3].z); + + Points[0] = lcMul31(Points[0], CurrentTransform); + Points[1] = lcMul31(Points[1], CurrentTransform); + Points[2] = lcMul31(Points[2], CurrentTransform); + Points[3] = lcMul31(Points[3], CurrentTransform); + + MeshData.AddLine(LineType, ColorCode, Points); + } break; + } + } + + return true; +} + +void lcLibraryMeshData::AddLine(int LineType, lcuint32 ColorCode, const lcVector3* Vertices) +{ + lcLibraryMeshSection* Section; + int SectionIdx; + bool Triangles = (LineType != 2); + + for (SectionIdx = 0; SectionIdx < mSections.GetSize(); SectionIdx++) + { + Section = mSections[SectionIdx]; + + if (Section->mColorCode == ColorCode && Section->mTriangles == Triangles) + break; + } + + if (SectionIdx == mSections.GetSize()) + { + Section = new lcLibraryMeshSection; + + Section->mColorCode = ColorCode; + Section->mTriangles = Triangles; + + mSections.Add(Section); + } + + int Indices[4] = { -1, -1, -1, -1 }; + + for (int IndexIdx = 0; IndexIdx < LineType; IndexIdx++) + { + const lcVector3& Vertex = Vertices[IndexIdx]; + + for (int VertexIdx = mVertices.GetSize() - 1; VertexIdx >= 0; VertexIdx--) + { + if (Vertex == mVertices[VertexIdx]) + { + Indices[IndexIdx] = VertexIdx; + break; + } + } + + if (Indices[IndexIdx] == -1) + { + Indices[IndexIdx] = mVertices.GetSize(); + mVertices.Add(Vertex); + } + } + + switch (LineType) + { + case 4: + Section->mIndices.Add(Indices[2]); + Section->mIndices.Add(Indices[3]); + Section->mIndices.Add(Indices[0]); + case 3: + Section->mIndices.Add(Indices[0]); + Section->mIndices.Add(Indices[1]); + Section->mIndices.Add(Indices[2]); + break; + case 2: + Section->mIndices.Add(Indices[0]); + Section->mIndices.Add(Indices[1]); + break; + } +} + +void lcLibraryMeshData::AddMeshData(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode) +{ + int VertexCount = Data.mVertices.GetSize(); + ObjArray IndexRemap(VertexCount); + + mVertices.Expand(Data.mVertices.GetSize()); + + for (int SrcVertexIdx = 0; SrcVertexIdx < VertexCount; SrcVertexIdx++) + { + lcVector3 Vertex = lcMul31(Data.mVertices[SrcVertexIdx], Transform); + int Index = -1; + + for (int DstVertexIdx = mVertices.GetSize() - 1; DstVertexIdx >= 0; DstVertexIdx--) + { +// if (Vertex == mVertices[DstVertexIdx]) + if (fabsf(Vertex.x - mVertices[DstVertexIdx].x) < 0.25 && fabsf(Vertex.y - mVertices[DstVertexIdx].y) < 0.25 && fabsf(Vertex.z - mVertices[DstVertexIdx].z) < 0.25) + { + Index = DstVertexIdx; + break; + } + } + + if (Index == -1) + { + Index = mVertices.GetSize(); + mVertices.Add(Vertex); + } + + IndexRemap.Add(Index); + } + + for (int SrcSectionIdx = 0; SrcSectionIdx < Data.mSections.GetSize(); SrcSectionIdx++) + { + lcLibraryMeshSection* SrcSection = Data.mSections[SrcSectionIdx]; + lcLibraryMeshSection* DstSection = NULL; + lcuint32 ColorCode = SrcSection->mColorCode == 16 ? CurrentColorCode : SrcSection->mColorCode; + + for (int DstSectionIdx = 0; DstSectionIdx < mSections.GetSize(); DstSectionIdx++) + { + lcLibraryMeshSection* Section = mSections[DstSectionIdx]; + + if (Section->mColorCode == ColorCode && Section->mTriangles == SrcSection->mTriangles) + { + DstSection = Section; + break; + } + } + + if (!DstSection) + { + DstSection = new lcLibraryMeshSection; + + DstSection->mColorCode = ColorCode; + DstSection->mTriangles = SrcSection->mTriangles; + + mSections.Add(DstSection); + } + + DstSection->mIndices.Expand(SrcSection->mIndices.GetSize()); + for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++) + DstSection->mIndices.Add(IndexRemap[SrcSection->mIndices[IndexIdx]]); + } +} + +void lcLibraryMeshData::AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode) +{ + lcuint32 BaseIndex = mVertices.GetSize(); + + mVertices.Expand(Data.mVertices.GetSize()); + + for (int SrcVertexIdx = 0; SrcVertexIdx < Data.mVertices.GetSize(); SrcVertexIdx++) + mVertices.Add(lcMul31(Data.mVertices[SrcVertexIdx], Transform)); + + for (int SrcSectionIdx = 0; SrcSectionIdx < Data.mSections.GetSize(); SrcSectionIdx++) + { + lcLibraryMeshSection* SrcSection = Data.mSections[SrcSectionIdx]; + lcLibraryMeshSection* DstSection = NULL; + lcuint32 ColorCode = SrcSection->mColorCode == 16 ? CurrentColorCode : SrcSection->mColorCode; + + for (int DstSectionIdx = 0; DstSectionIdx < mSections.GetSize(); DstSectionIdx++) + { + lcLibraryMeshSection* Section = mSections[DstSectionIdx]; + + if (Section->mColorCode == ColorCode && Section->mTriangles == SrcSection->mTriangles) + { + DstSection = Section; + break; + } + } + + if (!DstSection) + { + DstSection = new lcLibraryMeshSection; + + DstSection->mColorCode = ColorCode; + DstSection->mTriangles = SrcSection->mTriangles; + + mSections.Add(DstSection); + } + + DstSection->mIndices.Expand(SrcSection->mIndices.GetSize()); + for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++) + DstSection->mIndices.Add(BaseIndex + SrcSection->mIndices[IndexIdx]); + } +} diff --git a/common/lc_library.h b/common/lc_library.h index 05961309..a400c522 100644 --- a/common/lc_library.h +++ b/common/lc_library.h @@ -1,13 +1,82 @@ #ifndef _LC_LIBRARY_H_ #define _LC_LIBRARY_H_ +#include "lc_mesh.h" +#include "array.h" + +class PieceInfo; +class lcZipFile; + +class lcLibraryMeshSection +{ +public: + lcLibraryMeshSection() + : mIndices(1024, 1024) + { + } + + ~lcLibraryMeshSection() + { + } + + lcuint32 mColorCode; + bool mTriangles; + ObjArray mIndices; +}; + +class lcLibraryMeshData +{ +public: + lcLibraryMeshData() + : mVertices(1024, 1024) + { + } + + ~lcLibraryMeshData() + { + for (int SectionIdx = 0; SectionIdx < mSections.GetSize(); SectionIdx++) + delete mSections[SectionIdx]; + } + + void AddLine(int LineType, lcuint32 ColorCode, const lcVector3* Vertices); + void AddMeshData(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode); + void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode); + + PtrArray mSections; + ObjArray mVertices; +}; + +class lcLibraryPrimitive +{ +public: + char mName[LC_MAXPATH]; + lcuint32 mZipFileIndex; + bool mLoaded; + bool mStud; + bool mSubFile; + lcLibraryMeshData mMeshData; +}; + class lcPiecesLibrary { public: lcPiecesLibrary(); ~lcPiecesLibrary(); - bool OpenArchive(const char* LibPath); + bool OpenArchive(const char* FileName); + + + bool LoadPiece(const char* PieceName); + bool LoadPiece(int PieceIndex); + int FindPrimitiveIndex(const char* Name); + bool LoadPrimitive(int PrimitiveIndex); + bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcLibraryMeshData& MeshData); + + PtrArray mPieces; + PtrArray mPrimitives; + +protected: + lcZipFile* mZipFile; }; #endif // _LC_LIBRARY_H_ diff --git a/common/lc_math.h b/common/lc_math.h index 3b3f5839..f5e479a2 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -258,6 +258,11 @@ inline lcVector3& operator/=(lcVector3& a, float b) return a; } +inline bool operator==(const lcVector3& a, const lcVector3& b) +{ + return a.x == b.x && a.y == b.y && a.z == b.z; +} + inline void lcVector3::Normalize() { float InvLength = 1.0f / Length(); diff --git a/common/lc_zipfile.cpp b/common/lc_zipfile.cpp index 139f2296..7f6daa59 100644 --- a/common/lc_zipfile.cpp +++ b/common/lc_zipfile.cpp @@ -155,62 +155,62 @@ lcuint64 lcZipFile::SearchCentralDir64() return RelativeOffset; } -bool lcZipFile::CheckFileCoherencyHeader(int FileIndex, lcuint32* SizeVar, lcuint64* OffsetLocalExtraField, lcuint32* SizeLocalExtraField) -{ - lcuint16 Number16, Flags; - lcuint32 Number32, Magic; - lcuint16 SizeFilename, SizeExtraField; - const lcZipFileInfo& FileInfo = mFiles[FileIndex]; - - *SizeVar = 0; - *OffsetLocalExtraField = 0; - *SizeLocalExtraField = 0; - - mFile->Seek((long)(FileInfo.offset_curfile + mBytesBeforeZipFile), SEEK_SET); - +bool lcZipFile::CheckFileCoherencyHeader(int FileIndex, lcuint32* SizeVar, lcuint64* OffsetLocalExtraField, lcuint32* SizeLocalExtraField) +{ + lcuint16 Number16, Flags; + lcuint32 Number32, Magic; + lcuint16 SizeFilename, SizeExtraField; + const lcZipFileInfo& FileInfo = mFiles[FileIndex]; + + *SizeVar = 0; + *OffsetLocalExtraField = 0; + *SizeLocalExtraField = 0; + + mFile->Seek((long)(FileInfo.offset_curfile + mBytesBeforeZipFile), SEEK_SET); + if (mFile->ReadU32(&Magic, 1) != 1 || Magic != 0x04034b50) return false; - - if (mFile->ReadU16(&Number16, 1) != 1) - return false; - - if (mFile->ReadU16(&Flags, 1) != 1) - return false; - - if (mFile->ReadU16(&Number16, 1) != 1 || Number16 != FileInfo.compression_method) - return false; - - if (FileInfo.compression_method != 0 && FileInfo.compression_method != Z_DEFLATED) - return false; - - if (mFile->ReadU32(&Number32, 1) != 1) - return false; - - if (mFile->ReadU32(&Number32, 1) != 1 || ((Number32 != FileInfo.crc) && ((Flags & 8)==0))) - return false; - - if (mFile->ReadU32(&Number32, 1) != 1 || (Number32 != 0xFFFFFFFF && (Number32 != FileInfo.compressed_size) && ((Flags & 8)==0))) - return false; - - if (mFile->ReadU32(&Number32, 1) != 1 || (Number32 != 0xFFFFFFFF && (Number32 != FileInfo.uncompressed_size) && ((Flags & 8)==0))) - return false; - - if (mFile->ReadU16(&SizeFilename, 1) != 1 || SizeFilename != FileInfo.size_filename) - return false; - - *SizeVar += SizeFilename; - - if (mFile->ReadU16(&SizeExtraField, 1) != 1) - return false; - - *OffsetLocalExtraField= FileInfo.offset_curfile + 0x1e + SizeFilename; - *SizeLocalExtraField = SizeExtraField; - - *SizeVar += SizeExtraField; - - return true; -} - + + if (mFile->ReadU16(&Number16, 1) != 1) + return false; + + if (mFile->ReadU16(&Flags, 1) != 1) + return false; + + if (mFile->ReadU16(&Number16, 1) != 1 || Number16 != FileInfo.compression_method) + return false; + + if (FileInfo.compression_method != 0 && FileInfo.compression_method != Z_DEFLATED) + return false; + + if (mFile->ReadU32(&Number32, 1) != 1) + return false; + + if (mFile->ReadU32(&Number32, 1) != 1 || ((Number32 != FileInfo.crc) && ((Flags & 8)==0))) + return false; + + if (mFile->ReadU32(&Number32, 1) != 1 || (Number32 != 0xFFFFFFFF && (Number32 != FileInfo.compressed_size) && ((Flags & 8)==0))) + return false; + + if (mFile->ReadU32(&Number32, 1) != 1 || (Number32 != 0xFFFFFFFF && (Number32 != FileInfo.uncompressed_size) && ((Flags & 8)==0))) + return false; + + if (mFile->ReadU16(&SizeFilename, 1) != 1 || SizeFilename != FileInfo.size_filename) + return false; + + *SizeVar += SizeFilename; + + if (mFile->ReadU16(&SizeExtraField, 1) != 1) + return false; + + *OffsetLocalExtraField= FileInfo.offset_curfile + 0x1e + SizeFilename; + *SizeLocalExtraField = SizeExtraField; + + *SizeVar += SizeExtraField; + + return true; +} + bool lcZipFile::Open() { lcuint64 NumberEntriesCD, CentralPos; @@ -312,9 +312,6 @@ bool lcZipFile::Open() mBytesBeforeZipFile = CentralPos - (mCentralDirOffset + mCentralDirSize); mCentralPos = CentralPos; -// us.pfile_in_zip_read = NULL; -// us.encrypted = 0; - return ReadCentralDir(); } @@ -538,193 +535,144 @@ bool lcZipFile::ReadCentralDir() return true; } -bool lcZipFile::ExtractFile(int FileIndex, lcMemFile& File) +bool lcZipFile::ExtractFile(int FileIndex, lcMemFile& File, lcuint32 MaxLength) { - lcuint32 SizeVar; - lcuint64 OffsetLocalExtraField; - lcuint32 SizeLocalExtraField; - const lcZipFileInfo& FileInfo = mFiles[FileIndex]; - const int BufferSize = 16384; - - if (!CheckFileCoherencyHeader(FileIndex, &SizeVar, &OffsetLocalExtraField, &SizeLocalExtraField)) - return false; - - // file_in_zip_read_info_s contain internal information about a file in zipfile, when reading and decompress it - struct file_in_zip64_read_info - { - char read_buffer[BufferSize]; // internal buffer for compressed data - z_stream stream; // zLib stream structure for inflate - - lcuint64 pos_in_zipfile; // position in byte on the zipfile, for fseek - lcuint32 stream_initialised; // flag set if stream structure is initialised - - lcuint64 offset_local_extrafield; // offset of the local extra field - lcuint32 size_local_extrafield; // size of the local extra field - lcuint64 pos_local_extrafield; // position in the local extra field in read - lcuint64 total_out_64; - - lcuint32 crc32; // crc32 of all data uncompressed - lcuint32 crc32_wait; // crc32 we must obtain after decompress all - lcuint64 rest_read_compressed; // number of byte to be decompressed - lcuint64 rest_read_uncompressed; //number of byte to be obtained after decomp -// zlib_filefunc64_32_def z_filefunc; -// voidpf filestream; // io structore of the zipfile - lcuint32 compression_method; // compression method (0==store) - lcuint64 byte_before_the_zipfile; // byte before the zipfile, (>0 for sfx) - int raw; - }; + lcuint32 SizeVar; + lcuint64 OffsetLocalExtraField; + lcuint32 SizeLocalExtraField; + const lcZipFileInfo& FileInfo = mFiles[FileIndex]; - file_in_zip64_read_info ReadInfo; + if (!CheckFileCoherencyHeader(FileIndex, &SizeVar, &OffsetLocalExtraField, &SizeLocalExtraField)) + return false; + + const int BufferSize = 16384; + char ReadBuffer[BufferSize]; + z_stream Stream; + lcuint32 Crc32; + lcuint64 PosInZipfile; + lcuint64 RestReadCompressed; + lcuint64 RestReadUncompressed; + + Crc32 = 0; + Stream.total_out = 0; + + if (FileInfo.compression_method == Z_DEFLATED) + { + Stream.zalloc = (alloc_func)0; + Stream.zfree = (free_func)0; + Stream.opaque = (voidpf)0; + Stream.next_in = 0; + Stream.avail_in = 0; + + int err = inflateInit2(&Stream, -MAX_WBITS); + if (err != Z_OK) + return false; + } + + RestReadCompressed = FileInfo.compressed_size; + RestReadUncompressed = FileInfo.uncompressed_size; + PosInZipfile = FileInfo.offset_curfile + 0x1e + SizeVar; + + Stream.avail_in = (uInt)0; + + lcuint32 Length = lcMin((lcuint32)FileInfo.uncompressed_size, MaxLength); + File.SetLength(Length); + File.Seek(0, SEEK_SET); + + Stream.next_out = (Bytef*)File.mBuffer; + Stream.avail_out = Length; + + lcuint32 Read = 0; + + while (Stream.avail_out > 0) + { + if ((Stream.avail_in == 0) && (RestReadCompressed > 0)) + { + lcuint32 ReadThis = BufferSize; + + if (RestReadCompressed < ReadThis) + ReadThis = (lcuint32)RestReadCompressed; + + if (ReadThis == 0) + return false; + + mFile->Seek((long)(PosInZipfile + mBytesBeforeZipFile), SEEK_SET); + if (mFile->ReadBuffer(ReadBuffer, ReadThis) != ReadThis) + return false; + + PosInZipfile += ReadThis; + + RestReadCompressed -= ReadThis; + + Stream.next_in = (Bytef*)ReadBuffer; + Stream.avail_in = (uInt)ReadThis; + } + + if (FileInfo.compression_method == 0) + { + lcuint32 DoCopy, i; + + if ((Stream.avail_in == 0) && (RestReadCompressed == 0)) + return (Read == 0) ? false : true; + + if (Stream.avail_out < Stream.avail_in) + DoCopy = Stream.avail_out; + else + DoCopy = Stream.avail_in; + + for (i = 0; i < DoCopy; i++) + *(Stream.next_out+i) = *(Stream.next_in+i); + + Crc32 = crc32(Crc32, Stream.next_out, DoCopy); + RestReadUncompressed -= DoCopy; + Stream.avail_in -= DoCopy; + Stream.avail_out -= DoCopy; + Stream.next_out += DoCopy; + Stream.next_in += DoCopy; + Stream.total_out += DoCopy; + Read += DoCopy; + } + else + { + lcuint64 TotalOutBefore, TotalOutAfter; + const Bytef *bufBefore; + lcuint64 OutThis; + int flush = Z_SYNC_FLUSH; + + TotalOutBefore = Stream.total_out; + bufBefore = Stream.next_out; + + int err = inflate(&Stream,flush); + + if ((err >= 0) && (Stream.msg != NULL)) + err = Z_DATA_ERROR; + + TotalOutAfter = Stream.total_out; + OutThis = TotalOutAfter - TotalOutBefore; + + Crc32 = crc32(Crc32, bufBefore, (uInt)(OutThis)); + + RestReadUncompressed -= OutThis; + + Read += (uInt)(TotalOutAfter - TotalOutBefore); + + if (err != Z_OK) + { + inflateEnd(&Stream); + + if (RestReadUncompressed == 0) + { + if (Crc32 != FileInfo.crc) + return false; + } + + if (err == Z_STREAM_END) + return (Read == 0) ? false : true; + + return false; + } + } + } - ReadInfo.offset_local_extrafield = OffsetLocalExtraField; - ReadInfo.size_local_extrafield = SizeLocalExtraField; - ReadInfo.pos_local_extrafield = 0; - ReadInfo.raw = 0; - - ReadInfo.stream_initialised=0; - - ReadInfo.crc32_wait = FileInfo.crc; - ReadInfo.crc32 = 0; - ReadInfo.total_out_64 = 0; - ReadInfo.compression_method = FileInfo.compression_method; -// ReadInfo.filestream = s->filestream; -// ReadInfo.z_filefunc = s->z_filefunc; - ReadInfo.byte_before_the_zipfile = mBytesBeforeZipFile; - - ReadInfo.stream.total_out = 0; - - if (FileInfo.compression_method == Z_DEFLATED) - { - ReadInfo.stream.zalloc = (alloc_func)0; - ReadInfo.stream.zfree = (free_func)0; - ReadInfo.stream.opaque = (voidpf)0; - ReadInfo.stream.next_in = 0; - ReadInfo.stream.avail_in = 0; - - int err=inflateInit2(&ReadInfo.stream, -MAX_WBITS); - if (err == Z_OK) - ReadInfo.stream_initialised = Z_DEFLATED; - else - return false; - } - - ReadInfo.rest_read_compressed = FileInfo.compressed_size; - ReadInfo.rest_read_uncompressed = FileInfo.uncompressed_size; - ReadInfo.pos_in_zipfile = FileInfo.offset_curfile + 0x1e + SizeVar; - - ReadInfo.stream.avail_in = (uInt)0; - -// s->pfile_in_zip_read = pfile_in_zip_read_info; -// s->encrypted = 0; - - File.SetLength((long)FileInfo.uncompressed_size); - File.Seek(0, SEEK_SET); - - ReadInfo.stream.next_out = (Bytef*)File.mBuffer; - ReadInfo.stream.avail_out = File.mBufferSize; - -// if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && (!(pfile_in_zip_read_info->raw))) -// pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - -// if ((len>pfile_in_zip_read_info->rest_read_compressed+pfile_in_zip_read_info->stream.avail_in) && (pfile_in_zip_read_info->raw)) -// pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_compressed+pfile_in_zip_read_info->stream.avail_in; - - lcuint32 Read = 0; - - while (ReadInfo.stream.avail_out > 0) - { - if ((ReadInfo.stream.avail_in == 0) && (ReadInfo.rest_read_compressed > 0)) - { - lcuint32 ReadThis = BufferSize; - - if (ReadInfo.rest_read_compressed < ReadThis) - ReadThis = (lcuint32)ReadInfo.rest_read_compressed; - - if (ReadThis == 0) - return false; - - mFile->Seek((long)(ReadInfo.pos_in_zipfile + ReadInfo.byte_before_the_zipfile), SEEK_SET); - if (mFile->ReadBuffer(ReadInfo.read_buffer, ReadThis) != ReadThis) - return false; - - ReadInfo.pos_in_zipfile += ReadThis; - - ReadInfo.rest_read_compressed -= ReadThis; - - ReadInfo.stream.next_in = (Bytef*)ReadInfo.read_buffer; - ReadInfo.stream.avail_in = (uInt)ReadThis; - } - - if (ReadInfo.compression_method == 0) - { - lcuint32 DoCopy, i; - - if ((ReadInfo.stream.avail_in == 0) && (ReadInfo.rest_read_compressed == 0)) - return (Read == 0) ? false : true; - - if (ReadInfo.stream.avail_out < - ReadInfo.stream.avail_in) - DoCopy = ReadInfo.stream.avail_out; - else - DoCopy = ReadInfo.stream.avail_in; - - for (i = 0; i < DoCopy; i++) - *(ReadInfo.stream.next_out+i) = *(ReadInfo.stream.next_in+i); - - ReadInfo.total_out_64 = ReadInfo.total_out_64 + DoCopy; - - ReadInfo.crc32 = crc32(ReadInfo.crc32, ReadInfo.stream.next_out, DoCopy); - ReadInfo.rest_read_uncompressed -= DoCopy; - ReadInfo.stream.avail_in -= DoCopy; - ReadInfo.stream.avail_out -= DoCopy; - ReadInfo.stream.next_out += DoCopy; - ReadInfo.stream.next_in += DoCopy; - ReadInfo.stream.total_out += DoCopy; - Read += DoCopy; - } - else - { - lcuint64 TotalOutBefore, TotalOutAfter; - const Bytef *bufBefore; - lcuint64 OutThis; - int flush = Z_SYNC_FLUSH; - - TotalOutBefore = ReadInfo.stream.total_out; - bufBefore = ReadInfo.stream.next_out; - - int err = inflate(&ReadInfo.stream,flush); - - if ((err >= 0) && (ReadInfo.stream.msg != NULL)) - err = Z_DATA_ERROR; - - TotalOutAfter = ReadInfo.stream.total_out; - OutThis = TotalOutAfter - TotalOutBefore; - - ReadInfo.total_out_64 = ReadInfo.total_out_64 + OutThis; - - ReadInfo.crc32 = crc32(ReadInfo.crc32,bufBefore, (uInt)(OutThis)); - - ReadInfo.rest_read_uncompressed -= OutThis; - - Read += (uInt)(TotalOutAfter - TotalOutBefore); - - if (err != Z_OK) - { - inflateEnd(&ReadInfo.stream); - - if (ReadInfo.rest_read_uncompressed == 0) - { - if (ReadInfo.crc32 != ReadInfo.crc32_wait) - return false; - } - - if (err == Z_STREAM_END) - return (Read == 0) ? false : true; - - return false; - } - } - } - return true; } diff --git a/common/lc_zipfile.h b/common/lc_zipfile.h index ab201aab..5c01b39e 100644 --- a/common/lc_zipfile.h +++ b/common/lc_zipfile.h @@ -47,7 +47,7 @@ public: ~lcZipFile(); bool Open(const char* FilePath); - bool ExtractFile(int FileIndex, lcMemFile& File); + bool ExtractFile(int FileIndex, lcMemFile& File, lcuint32 MaxLength = 0xffffffff); ObjArray mFiles; @@ -56,7 +56,7 @@ protected: bool ReadCentralDir(); lcuint64 SearchCentralDir(); lcuint64 SearchCentralDir64(); - bool CheckFileCoherencyHeader(int FileIndex, lcuint32* SizeVar, lcuint64* OffsetLocalExtraField, lcuint32* SizeLocalExtraField); + bool CheckFileCoherencyHeader(int FileIndex, lcuint32* SizeVar, lcuint64* OffsetLocalExtraField, lcuint32* SizeLocalExtraField); lcFile* mFile; diff --git a/common/pieceinf.cpp b/common/pieceinf.cpp index 45b7a565..ca6a6211 100644 --- a/common/pieceinf.cpp +++ b/common/pieceinf.cpp @@ -40,6 +40,8 @@ static float costbl[SIDES]; PieceInfo::PieceInfo() { + m_nRef = 0; + m_nBoxList = 0; mMesh = NULL; } @@ -68,10 +70,6 @@ void PieceInfo::LoadIndex(lcFile& file) init = true; } - // TODO: don't change ref. if we're reloading ? - m_nRef = 0; - m_nBoxList = 0; - file.ReadBuffer(m_strName, LC_PIECE_NAME_LEN); file.ReadBuffer(m_strDescription, 64); m_strDescription[64] = '\0'; @@ -100,9 +98,6 @@ void PieceInfo::LoadIndex(lcFile& file) void PieceInfo::CreatePlaceholder(const char* Name) { - m_nRef = 0; - m_nBoxList = 0; - strncpy(m_strName, Name, sizeof(m_strName)); m_strName[sizeof(m_strName)-1] = 0; strncpy(m_strDescription, Name, sizeof(m_strDescription)); diff --git a/common/pieceinf.h b/common/pieceinf.h index edebbde4..edeac50f 100644 --- a/common/pieceinf.h +++ b/common/pieceinf.h @@ -80,7 +80,7 @@ public: // Attributes char m_strName[LC_PIECE_NAME_LEN]; - char m_strDescription[65]; + char m_strDescription[128]; float m_fDimensions[6]; lcuint32 m_nOffset; lcuint32 m_nSize;