An asset that contains other assets.
Наследование: Asset
Пример #1
0
        /// <summary>
        /// Create <see cref="FolderAsset"/>s as necessary to store this asset within a path and set the name of this asset to the last name in the path.
        /// </summary>
        /// <param name="path"></param>
        protected void MoveIntoPath(params string[] path)
        {
            int index = 0;

            if (path[0].Length == 0)
            {
                index = 1;
            }

            Asset target = Parent;

            for (; index < path.Length - 1; index++)
            {
                string name  = path[index];
                bool   found = false;

                foreach (Asset child in target.Children)
                {
                    if (child is FolderAsset && child.Name == name)
                    {
                        target = child;
                        found  = true;
                    }
                }

                if (!found)
                {
                    target = new FolderAsset((FolderAsset)target, name);
                }
            }

            Parent = target;
            Name   = path[index];
        }
Пример #2
0
 /// <summary>Initialise the asset.</summary>
 /// <param name="folder"></param>
 /// <param name="name"></param>
 /// <param name="colors"></param>
 public PaletteAsset(FolderAsset folder, string name, IEnumerable <Color> colors)
     : base(folder, name)
 {
     if (colors != null)
     {
         ColorsMutable.AddRange(colors);
     }
 }
Пример #3
0
        internal ModelBoneUnknown(FolderAsset bonesFolder, int index, AssetLoader loader)
            : base(bonesFolder, index, loader)
        {
            var reader = loader.Reader;

            Unknowns.ReadSingles(reader, 3);
            reader.Require(IsDS1 ? 0xFFFFFFFFu : 0xFF000000u);
            Unknowns.ReadSingles(reader, 3);
            Unknowns.ReadInt16s(reader, 2);
            Unknowns.ReadSingles(reader, 3);
            Unknowns.ReadInt16s(reader, 2);
            reader.RequireZeroes(4 * 4);
        }
Пример #4
0
        internal ModelBone(FolderAsset folder, int index, AssetLoader loader)
            : base(folder, index, loader)
        {
            var reader = loader.Reader;

            Position = reader.ReadVector3f();
            Name = reader.ReadStringzAtUInt32(Encoding);
            Angle = Angle3.Radians(reader.ReadVector3f());
            parentIndex = reader.ReadInt16();
            firstChildIndex = reader.ReadInt16();
            Scale = reader.ReadVector3f();
            nextSiblingIndex = reader.ReadInt16();
            previousSiblingIndex = reader.ReadInt16();
            var min = reader.ReadVector3f();
            Unknowns.ReadInt32s(reader, 1); // 0 or 1
            var max = reader.ReadVector3f();
            Bounds = new Box3f(min, max);
            reader.RequireZeroes(4 * 13);
        }
Пример #5
0
        internal ModelMesh(FolderAsset folder, int index, AssetLoader loader)
            : base(folder, index, loader)
        {
            var reader = loader.Reader;

            Unknowns.ReadInt32s(reader, 1); // 1?
            MaterialIndex = reader.ReadInt32();
            reader.RequireZeroes(4 * 2);
            Unknowns.ReadInt32s(reader, 1); // 0 or 1, seems to be material-related but is not transparency; second seems bones-related
            int boneCount = reader.ReadInt32();
            reader.RequireZeroes(4 * 1);
            int boneIndicesOffset = reader.ReadInt32();
            PartCount = reader.ReadInt32();
            int partIndicesOffset = reader.ReadInt32();
            reader.Require(1);
            int indexOffset = reader.ReadInt32();

            long reset = reader.BaseStream.Position;

            reader.BaseStream.Position = boneIndicesOffset;
            var bones = new Codex<ModelBone>();
            Bones = bones;
            for (int i = 0; i < boneCount; i++)
                bones.Add(Model.Bones[reader.ReadInt32()]);

            // Read the part indices.
            reader.BaseStream.Position = partIndicesOffset;
            int partStart = PartStartIndex;
            for (int i = 0; i < PartCount; i++)
                reader.Require(i + partStart);

            reader.BaseStream.Position = indexOffset;
            reader.Require(Index);

            reader.BaseStream.Position = reset;
        }
        internal ModelVertexDeclaration(FolderAsset folder, int index, AssetLoader loader)
            : base(folder, index, loader)
        {
            var reader = loader.Reader;

            int count = reader.ReadInt32();
            reader.RequireZeroes(4 * 2);
            int offset = reader.ReadInt32();
            long reset = reader.BaseStream.Position;

            reader.BaseStream.Position = offset;
            var blocks = new Codex<ModelVertexAttribute>();
            Attributes = blocks;
            for (int blockIndex = 0; blockIndex < count; blockIndex++)
                blocks.Add(new ModelVertexAttribute(this, loader, blockIndex));

            reader.BaseStream.Position = reset;
        }
Пример #7
0
 /// <summary>Initialise the asset.</summary>
 /// <param name="folder"></param>
 /// <param name="name"></param>
 /// <param name="colors"></param>
 public PaletteAsset(FolderAsset folder, string name, params Color[] colors) : this(folder, name, (IEnumerable <Color>)colors)
 {
 }
Пример #8
0
        internal Model(AssetLoader loader)
            : base(loader)
        {
            Asset context = loader.Context;
            string name = loader.Name;
            BinaryReader reader = loader.Reader;

            FolderAsset textureArchive = null;

            FolderAsset bonesFolder = new FolderAsset(this, "Bones");
            FolderAsset materialsFolder = new FolderAsset(this, "Materials");
            FolderAsset meshesFolder = new FolderAsset(this, "Meshes");
            FolderAsset vertexDeclarationsFolder = new FolderAsset(this, "Vertex declarations");

            ArrayBackedList<byte> bufferData = new ArrayBackedList<byte>();

            if (context != null && context.Parent is FolderAsset) {
                // @"/map/m##_##_##_##/m*.flver.dcx" for DS1; textures are in the @"/map/m##/" folder.
                if (name.StartsWith(@"map/m")) {
                    string folderName = name.Substring(4, 3);
                    FolderAsset maps = (FolderAsset)context.Parent.Parent;
                    foreach (FolderAsset child in maps.Children) {
                        if (child.Name == folderName) {
                            textureArchive = child;
                            break;
                        }
                    }
                } else
                    textureArchive = (FolderAsset)context.Parent;
            }

            #if Marking
            MarkingStream markingStream = loader.StartMarking(out reader);
            #endif

            loader.ExpectMagic(Magic);
            char endian = (char)reader.ReadByte();

            switch (endian) {
                case 'L':
                    ByteOrder = ByteOrder.LittleEndian;
                    break;

                case 'B':
                    reader = loader.MakeBigEndian();
                    ByteOrder = ByteOrder.BigEndian;
                    break;

                default:
                    throw new Exception();
            }

            using (reader) {
                // Read header.
                loader.Expect((byte)0);
                Version = (ModelVersion)reader.ReadInt32();
                if (Version != ModelVersion.DarkSouls && Version != ModelVersion.DarkSouls2)
                    loader.AddError(loader.Position - 4, "Unknown model version " + VersionString + "; will try to load it anyway.");
                int dataOffset = reader.ReadInt32();
                int dataSize = reader.ReadInt32();
                if (((dataOffset + dataSize + 31) & ~31) != reader.BaseStream.Length)
                    loader.AddError(loader.Position - 4, "Data size and offset aren't correct.");

                int boneUnknownCount = reader.ReadInt32();
                int materialCount = reader.ReadInt32();
                int boneCount = reader.ReadInt32();

                int meshCount = reader.ReadInt32();
                int meshCount2 = reader.ReadInt32();
                if (meshCount != meshCount2)
                    loader.AddError(loader.Position - 4, "Mesh count 1 and 2 aren't the same.");

                Bounds = new Box3f(reader.ReadVector3f(), reader.ReadVector3f());
                Unknowns.ReadInt32s(reader, 1); // Possible the non-degenerate triangle count. Seems related.
                int triangleCount = reader.ReadInt32();

                loader.Expect(IsDS1 ? 272 : 0x10010100);
                loader.Expect(IsDS1 ? 0 : 0xFFFF);

                int partCount = reader.ReadInt32();
                int vertexDeclarationCount = reader.ReadInt32();
                int materialParameterCount = reader.ReadInt32();
                loader.Expect(IsDS1 ? 0 : 0x1000000);
                loader.ExpectZeroes(4, 8);

                // Calculate offsets.
                long boneUnknownsOffset = HeaderSize;
                long materialsOffset = boneUnknownsOffset + boneUnknownCount * ModelBoneUnknown.DataSize;
                long bonesOffset = materialsOffset + materialCount * ModelMaterial.DataSize;
                long meshesOffset = bonesOffset + boneCount * ModelBone.DataSize;
                long detailLevelsOffset = meshesOffset + meshCount * ModelMesh.DataSize;
                long meshVerticesOffset = detailLevelsOffset + partCount * ModelDetailLevel.DataSize;
                long vertexDeclarationsOffset = meshVerticesOffset + meshCount * ModelMesh.DataSizeVertexHeader;
                long materialParametersOffset = vertexDeclarationsOffset + vertexDeclarationCount * ModelVertexDeclaration.DataSize;
                long postHeaderOffset = materialParametersOffset + materialParameterCount * ModelMaterialParameter.DataSize;

                // BoneUnknowns
                ExpectedOffset(loader, boneUnknownsOffset, typeof(ModelBoneUnknown).Name);
                for (int index = 0; index < boneUnknownCount; index++)
                    boneUnknowns.Add(new ModelBoneUnknown(bonesFolder, index, loader));

                // Materials
                ExpectedOffset(loader, materialsOffset, typeof(ModelMaterial).Name);
                for (int index = 0; index < materialCount; index++)
                    materials.Add(new ModelMaterial(materialsFolder, index, loader));
                int expectedMaterialParameterCount = materialCount > 0 ? materials[materialCount - 1].ParameterEndIndex : 0;
                if (expectedMaterialParameterCount != materialParameterCount)
                    loader.AddError(null, "Expected material parameter count {0} doesn't match actual count {1}.", expectedMaterialParameterCount, materialParameterCount);

                // Bones
                ExpectedOffset(loader, bonesOffset, typeof(ModelBone).Name);
                for (int index = 0; index < boneCount; index++)
                    bones.Add(new ModelBone(bonesFolder, index, loader));

                // Meshes
                ExpectedOffset(loader, meshesOffset, typeof(ModelMesh).Name);
                for (int index = 0; index < meshCount; index++)
                    meshes.Add(new ModelMesh(meshesFolder, index, loader));
                int expectedPartCount = meshCount > 0 ? meshes[meshCount - 1].PartEndIndex : 0;
                if (expectedPartCount != partCount)
                    throw new InvalidDataException("Expected part count doesn't match actual count.");

                // Detail levels
                ExpectedOffset(loader, detailLevelsOffset, typeof(ModelDetailLevel).Name);
                foreach (ModelMesh mesh in meshes) {
                    mesh.ReadDetailLevels(loader, dataOffset, bufferData);
                    detailLevels.AddRange(mesh.DetailLevels);
                }

                // Mesh vertices
                ExpectedOffset(loader, meshVerticesOffset, typeof(ModelMesh).Name + " vertex header");
                foreach (ModelMesh mesh in meshes)
                    mesh.ReadVertexHeaders(reader, dataOffset, bufferData);

                // Vertex declarations
                ExpectedOffset(loader, vertexDeclarationsOffset, typeof(ModelVertexDeclaration).Name);
                for (int index = 0; index < vertexDeclarationCount; index++)
                    vertexDeclarations.Add(new ModelVertexDeclaration(vertexDeclarationsFolder, index, loader));

                // Material parameters
                ExpectedOffset(loader, materialParametersOffset, typeof(ModelMaterialParameter).Name);
                foreach (ModelMaterial material in materials) {
                    material.ReadParameters(loader, textureArchive);
                    materialParameters.AddRange(material.Parameters);
                }

                ExpectedOffset(loader, postHeaderOffset, "Post-header");

            #if Marking
                if (markingStream != null) {
                    markingStream.Report(loader);
                }
            #endif // Marking

            #if SkippedChecks
                /*int vertexDataSize = 0, indexCount = 0, indexSize = 0, vertexCount = 0, expectedTriangleCount = 0, nondegenerateTriangleCount = 0;
                foreach (var mesh in Meshes) {
                    vertexDataSize += mesh.VertexCount * mesh.VertexSize;
                    vertexCount += mesh.VertexCount;
                    foreach (var part in mesh.Parts) {
                        indexCount += part.Indices.Length;
                        indexSize += part.Indices.Length * 2;
                        expectedTriangleCount += part.Indices.Length - 2;
                        for (int index = 0; index < part.Indices.Length - 2; index++) {
                            if (part.Indices[index] != part.Indices[index + 1] && part.Indices[index + 1] != part.Indices[index + 2] && part.Indices[index] != part.Indices[index + 2])
                                nondegenerateTriangleCount++;
                        }
                    }
                }
                if (Math.Abs(expectedTriangleCount - triangleCount) > partCount)
                    throw new InvalidDataException("Expected triangle count doesn't match the read value.");*/
            #endif
            }

            Buffer = new GraphicsBuffer(bufferData.Count == 0 ? 1 : bufferData.Count);
            Buffer.Write(0, bufferData.Array, 0, bufferData.Count);
        }
Пример #9
0
        internal void Sort(FolderAsset parent, string name, int fileNameBaseOffset, byte[] fileNames)
        {
            int fileNameOffset = FileNameOffset - fileNameBaseOffset;
            int fileIndex = FileIndex;

            if (Used)
                throw new InvalidDataException();

            Used = true;
            Parent = parent;
            Name = name;

            while (true) {
                byte nameCode = fileNames[fileNameOffset++];
                if (nameCode == 0)
                    break;
                byte nameLength = (byte)(nameCode & 0x7F);
                bool isFolder = (nameCode & 0x80) != 0;

                string childName = Encoding.ASCII.GetString(fileNames, fileNameOffset, nameLength);
                fileNameOffset += nameLength;

                if (isFolder) {
                    int folderIndex = fileNames[fileNameOffset++] + (fileNames[fileNameOffset++] << 8);
                    RomFolder folder = Rom.Folders[folderIndex & 0xFFF];
                    folder.Unknown2 = (byte)(folderIndex >> 12);
                    if (folder.Unknown2 != 15) {
                    }
                    folder.Sort(this, childName, fileNameBaseOffset, fileNames);
                } else {
                    RomFile file = Rom.Files[fileIndex++];
                    file.Sort(this, childName);
                }
            }
        }
Пример #10
0
        internal Rom(AssetLoader loader)
            : base(loader)
        {
            BinaryReader reader = Reader = loader.Reader;

            Codex<RomFile> files = new Codex<RomFile>();
            Codex<RomFolder> folders = new Codex<RomFolder>();
            Files = files;
            Folders = folders;

            GameTitle = Reader.ReadStringz(12, Encoding.ASCII);
            GameCode = Reader.ReadStringz(4, Encoding.ASCII);

            // Offset 0x10
            MakerCode = Reader.ReadStringz(2, Encoding.ASCII);
            UnitCode = reader.ReadByte();
            DeviceCode = reader.ReadByte();
            CardSizeBase = reader.ReadByte();
            loader.ExpectZeroes(1, 7);
            Unknowns.ReadInt32s(reader, 1); // Usually 0, Alice in Wonderland: 3

            // Offset 0x20
            PageSize = reader.ReadInt32(); // Usually (always?) 0x4000
            Unknowns.ReadInt16s(reader, 2); // The Dark Spire: 0x800; Trauma Center: 0xF780 (-2176)
            loader.Expect(0x2000000);
            Unknowns.ReadInt32s(reader, 1); // The Dark Spire: 0x9BEF8; Trauma Center: 0x1DC518

            // Offset 0x30
            Unknowns.ReadInt32s(reader, 1); // Entry points? The Dark Spire: 0x152200; Trauma Center: 0x1E0600
            loader.Expect(0x2380000);
            loader.Expect(0x2380000);
            Unknowns.ReadInt16s(reader, 1); // The Dark Spire: 0x6F28; Trauma Center: 0x6F24
            loader.Expect((short)0x2);

            // Offset 0x40
            int fileNameTableOffset = reader.ReadInt32();
            int fileNameTableSize = reader.ReadInt32();
            int fileSizeTableOffset = reader.ReadInt32();
            int fileSizeTableSize = reader.ReadInt32();

            // Offset 0x50
            Unknowns.ReadInt32s(reader, 2, "Offset and size"); // Used in The Dark Spire, zeroes in Trauma Center.
            loader.ExpectZeroes(4, 2);

            // Offset 0x60
            Unknowns.ReadInt32s(reader, 2);
            int iconAndTitleOffset = reader.ReadInt32();
            Unknowns.ReadInt32s(reader, 1);

            // Offset 0x70
            Unknowns.ReadInt32s(reader, 2);
            loader.ExpectZeroes(4, 2);

            // Offset 0x80
            DataLength = reader.ReadInt32();
            loader.Expect(PageSize);
            Unknowns.ReadInt32s(reader, 2); // The Dark Spire: 0x4B68; 0 in Trauma Center.

            ReadIconAndTitle(iconAndTitleOffset);

            if (fileNameTableOffset > 0) {
                int folderNamesOffset = reader.ReadInt32At(fileNameTableOffset);
                reader.BaseStream.Position = fileNameTableOffset;
                int folderCount = folderNamesOffset / 8;
                for (int index = 0; index < folderCount; index++)
                    folders.Add(new RomFolder(this, index, reader));
                byte[] folderNames = reader.ReadBytes(fileNameTableSize - folderNamesOffset);

                reader.BaseStream.Position = fileSizeTableOffset;
                int fileCount = fileSizeTableSize / 8;
                for (int index = 0; index < fileCount; index++)
                    files.Add(new RomFile(this, index, reader));

                folders[0].Sort(this, "Root", folderNamesOffset, folderNames);

                FolderAsset orphanedFolders = null, orphanedFiles = null;

                foreach (RomFolder folder in folders) {
                    if (folder.Used)
                        continue;
                    if (orphanedFolders == null)
                        orphanedFolders = new FolderAsset(this, "Orphaned folder[s]");
                    folder.Sort(this, folder.Name, folderNamesOffset, folderNames);
                }

                foreach (RomFile file in files) {
                    if (file.Used)
                        continue;
                    if (orphanedFiles == null)
                        orphanedFiles = new FolderAsset(this, "Orphaned file[s]");
                    file.Sort(orphanedFiles, file.Name);
                }
            }
        }
Пример #11
0
 /// <summary>Initialise the asset.</summary>
 /// <param name="folder"></param>
 /// <param name="name"></param>
 /// <param name="colors"></param>
 public PaletteAsset(FolderAsset folder, string name, IEnumerable<Color> colors)
     : base(folder, name)
 {
     if (colors != null)
         ColorsMutable.AddRange(colors);
 }
Пример #12
0
 /// <summary>
 /// Initialise the asset.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="name"></param>
 /// <param name="description"></param>
 public Asset(FolderAsset parent, string name, string description = null)
     : this(parent.Manager, name, description)
 {
     Parent = parent;
 }
Пример #13
0
 /// <summary>
 /// Initialise the folder asset.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="loader"></param>
 public FolderAsset(FolderAsset parent, AssetLoader loader)
     : base(parent, loader)
 {
 }
Пример #14
0
 /// <summary>Initialise the table asset.</summary>
 /// <param name="parent"></param>
 /// <param name="loader"></param>
 public TableAsset(FolderAsset parent, AssetLoader loader) : base(parent, loader)
 {
 }
        internal static void LoadFileTable(FolderAsset parent, BinaryReader reader, NintendoOpticalDiscSystem system)
        {
            reader.BaseStream.Position = 0x424;
            long fileTableOffset = LoadOffset(reader, system);

            reader.BaseStream.Position = fileTableOffset + 8;
            int count = reader.ReadInt32();
            for (int index = 1; index < count; )
                LoadFile(parent, reader, ref index, system);

            foreach (Asset asset in parent.Children)
                LoadFileName(asset, reader, fileTableOffset + count * 12);
        }
 internal NintendoOpticalDiscPartitionFile(FolderAsset parent, int index, int nameOffset, BinaryReader reader, NintendoOpticalDiscSystem system)
     : base(parent, "")
 {
     Index = index;
     NameOffset = nameOffset;
     DataOffset = NintendoOpticalDiscPartition.LoadOffset(reader, system);
     Size = reader.ReadUInt32();
 }
        internal static Asset LoadFile(FolderAsset parent, BinaryReader reader, ref int index, NintendoOpticalDiscSystem system)
        {
            int nameOffset = reader.ReadInt32();
            bool isDirectory = (nameOffset & 0xFF000000) != 0;
            nameOffset &= 0xFFFFFF;

            if (isDirectory)
                return new NintendoOpticalDiscPartitionFolder(parent, ref index, nameOffset, reader, system);
            else
                return new NintendoOpticalDiscPartitionFile(parent, index++, nameOffset, reader, system);
        }
 /// <summary>Initialise the texture.</summary>
 /// <param name="parent"></param>
 /// <param name="loader"></param>
 protected IndexedTextureAsset(FolderAsset parent, AssetLoader loader)
     : base(parent, loader, null)
 {
 }
Пример #19
0
 /// <summary>
 /// Initialise the asset.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="loader"></param>
 public Asset(FolderAsset parent, AssetLoader loader)
     : this(loader) {
     Parent = parent;
 }
Пример #20
0
 /// <summary>Initialise the texture.</summary>
 /// <param name="parent"></param>
 /// <param name="loader"></param>
 protected IndexedTextureAsset(FolderAsset parent, AssetLoader loader) : base(parent, loader, null)
 {
 }
Пример #21
0
 /// <summary>
 /// Initialise the object.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="index"></param>
 /// <param name="loader"></param>
 public ModelAsset(FolderAsset parent, int index, AssetLoader loader)
     : base(parent, "")
 {
     Name = GetType().Name + " " + index;
     Index = index;
 }
Пример #22
0
 /// <summary>Initialise the asset.</summary>
 /// <param name="folder"></param>
 /// <param name="name"></param>
 /// <param name="colors"></param>
 public PaletteAsset(FolderAsset folder, string name, params Color[] colors)
     : this(folder, name, (IEnumerable<Color>)colors)
 {
 }
Пример #23
0
 internal void Sort(FolderAsset parent, string name)
 {
     if (Used)
         throw new InvalidDataException();
     Parent = parent;
     Name = name;
     Used = true;
 }
 internal NintendoOpticalDiscPartitionFolder(FolderAsset parent, ref int index, int nameOffset, BinaryReader reader, NintendoOpticalDiscSystem system)
     : base(parent, "")
 {
     Index = index;
     NameOffset = nameOffset;
     int firstIndex = reader.ReadInt32();
     /*if (firstIndex != index + 1)
         throw new InvalidDataException();*/
     int endIndex = reader.ReadInt32();
     index++;
     while (index < endIndex)
         NintendoOpticalDiscPartition.LoadFile(this, reader, ref index, system);
 }
Пример #25
0
 /// <summary>
 /// Initialise the folder asset.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="name"></param>
 /// <param name="description"></param>
 public FolderAsset(FolderAsset parent, string name, string description = null) : base(parent, name, description)
 {
 }
Пример #26
0
 /// <summary>Initialise the asset.</summary>
 /// <param name="parent"></param>
 /// <param name="loader"></param>
 /// <param name="texture"></param>
 public TextureAsset(FolderAsset parent, AssetLoader loader, Glare.Graphics.Texture texture) : base(parent, loader)
 {
 }
Пример #27
0
 /// <summary>Initialise the asset.</summary>
 /// <param name="parent"></param>
 /// <param name="loader"></param>
 /// <param name="texture"></param>
 public TextureAsset(FolderAsset parent, AssetLoader loader, Glare.Graphics.Texture texture)
     : base(parent, loader)
 {
 }
Пример #28
0
 /// <summary>
 /// Initialise the data asset.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="name"></param>
 /// <param name="description"></param>
 public DataAsset(FolderAsset parent, string name, string description = null)
     : base(parent, name, description)
 {
 }
Пример #29
0
 /// <summary>
 /// Initialise the resource.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="map"></param>
 /// <param name="id"></param>
 public Resource(FolderAsset parent, ResourceMap map, ResourceId id)
     : base(parent, id.ToString())
 {
     Map = map;
     Id = id;
 }