Example #1
0
        public ChunkReader(byte[] expectedMagicNumber, Stream stream, HashSet <ChunkId> knownChunkList = null)
        {
            _knownChunkList = knownChunkList;

            // Check file type
            byte[] magicNumber = new byte[expectedMagicNumber.Length];
            stream.Read(magicNumber, 0, expectedMagicNumber.Length);
            if (!magicNumber.SequenceEqual(expectedMagicNumber))
            {
                throw new NotSupportedException("The header of the file was unrecognizable. Most likely it is not a valid file.");
            }

            // Check chunk type
            uint chunkVersion = new BinaryReader(stream).ReadUInt32();

            if ((chunkVersion & 0x7fffffffu) != 0)
            {
                throw new NotSupportedException("Chunk version " + chunkVersion + " is not supported");
            }

            if ((chunkVersion & 0x80000000u) != 0)
            {
                int    compressedSize   = new BinaryReader(stream).ReadInt32();
                byte[] compressedBuffer = new byte[compressedSize];
                stream.Read(compressedBuffer, 0, compressedSize);
                byte[] decompressedBuffer = ZLib.DecompressData(compressedBuffer);

                _reader = new BinaryReaderEx(new MemoryStream(decompressedBuffer));
            }
            else
            {
                _reader = new BinaryReaderEx(stream);
            }
        }
Example #2
0
        public static byte[] GetDecompressedData(string pakFilePath)
        {
            using (FileStream stream = new FileStream(pakFilePath, FileMode.Open, FileAccess.Read))
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, (int)stream.Length);
                bytes = bytes.Skip(4).ToArray();

                return(ZLib.DecompressData(bytes));
            }
        }
Example #3
0
        /// <summary>
        /// Initializes a new instance of PayloadReader using the specified payload data. If the payload is compressed, it is automatically decompressed.
        /// </summary>
        /// <param name="payload">The payload data to be read.</param>
        /// <remarks>
        /// The null bytes padding is ignored by the reader.
        /// </remarks>
        public PayloadReader(byte[] payload)
        {
            Data = payload;

            if (CompressionFlag)
            {
                byte[] firstPart           = Sequence.ReadBlock(Data, 0, 11);
                byte[] decompressedContent = ZLib.DecompressData(Sequence.ReadBlock(Data, 11, Size - 4));
                byte[] nullBytesPadding    = new byte[3];

                Data = Sequence.Concat(firstPart, decompressedContent, nullBytesPadding);
            }
        }
Example #4
0
        /// <summary>
        /// Initializes a new instance of PayloadReader using the specified payload data. If the
        /// payload is compressed, it is automatically decompressed.
        /// </summary>
        /// <param name="payload">The payload data to be read.</param>
        /// <remarks>The null bytes padding is ignored by the reader.</remarks>
        public PayloadReader(byte[] payload)
        {
            _payloadData = payload;

            if (CompressionFlag)
            {
                byte[] firstPart           = Sequence.ReadBlock(_payloadData, 0, 11);
                byte[] decompressedContent = ZLib.DecompressData(Sequence.ReadBlock(_payloadData, 11, ContentLength - sizeof(int)));
                byte[] zeroesPadding       = new byte[4];

                _payloadData = Sequence.Concat(firstPart, decompressedContent, zeroesPadding);
            }
        }
Example #5
0
        public void Read(IAsyncResult read)
        {
            try
            {
                if (this.active == true)
                {
                    byte[] sizer = new byte[2];
                    sizer[0] = this.buffer[0];
                    sizer[1] = this.buffer[1];
                    Array.Reverse(sizer);
                    short Resize = BitConverter.ToInt16(this.buffer, 0);
                    if (Resize > 0)
                    {
                        Array.Resize(ref this.buffer, Resize);
                        Array.Resize(ref this.readers.req, Resize);
                        this.readers.req = this.buffer;
                        this.buffer      = initialize.decrypt(this.buffer, this.IV, this.Hmac);
                        byte[] getOp = new byte[2];
                        getOp[0] = this.buffer[0];
                        getOp[1] = this.buffer[1];
                        Array.Reverse(getOp);
                        short opcode = BitConverter.ToInt16(getOp, 0);
                        if ((byte)this.buffer[6] == 1)
                        {
                            byte[] temp        = new byte[0];
                            byte[] lenCompress = new byte[2];
                            lenCompress[0] = this.buffer[4];
                            lenCompress[1] = this.buffer[5];
                            Array.Reverse(lenCompress);
                            short len = BitConverter.ToInt16(lenCompress, 0);
                            Array.Resize(ref temp, len - 4);
                            Array.Copy(this.buffer, 11, temp, 0, len - 4);
                            byte[] temp1            = ZLib.DecompressData(temp);
                            byte[] bufferDecompress = new byte[0];
                            Array.Resize(ref bufferDecompress, temp1.Length + 7);
                            Array.Copy(temp1, 0, bufferDecompress, 7, temp1.Length);
                            Array.Copy(this.buffer, 0, bufferDecompress, 0, 7);

                            Array.Resize(ref this.buffer, bufferDecompress.Length);
                            Array.Resize(ref this.readers.req, bufferDecompress.Length);

                            this.readers.req = bufferDecompress;
                            this.buffer      = bufferDecompress;
                            Packets packets = new Packets(opcode, readers, this, bufferDecompress);
                            log.Hex("Recebido, OpCode {" + opcode + "} Payload: ", buffer, 0);
                        }
                        else
                        {
                            Packets packets = new Packets(opcode, readers, this, this.buffer);
                            log.Hex("Recebido, OpCode {" + opcode + "} Payload: ", buffer, 0);
                        }
                    }
                    else
                    {
                        this.close();
                    }
                }
            }
            catch (Exception e)
            {
                log.Error("{1} \n {0}", e.Message, e.StackTrace);
            }
            finally
            {
                if (this.active)
                {
                    this.buffer      = new byte[1024];
                    this.readers.req = new byte[1024];
                    this.socket.BeginReceive(this.buffer, 0, this.buffer.Length, SocketFlags.None, this.Read, null);
                }
            }
        }
Example #6
0
        public TestLevel(string fileName, string outFileName = "")
        {
            this.fileName = fileName;

            FileStream     fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReaderEx reader     = new BinaryReaderEx(fileStream);

            byte[] buffer;

            reader.ReadBlock(out Version);
            reader.ReadBlock(out NumRoomTextureTiles);
            reader.ReadBlock(out NumObjectTextureTiles);
            reader.ReadBlock(out NumBumpTextureTiles);

            reader.ReadBlock(out Texture32UncompressedSize);
            reader.ReadBlock(out Texture32CompressedSize);

            Texture32 = new byte[Texture32CompressedSize];
            reader.ReadBlockArray(out Texture32, Texture32CompressedSize);
            Texture32 = ZLib.DecompressData(Texture32);

            ImageC img = ImageC.FromByteArray(Texture32, 256, (int)Texture32UncompressedSize / 262144 * 256);
            //img.Save("H:\\karnak.png");

            BinaryWriterEx wrttext = new BinaryWriterEx(new FileStream("textures.raw", FileMode.Create, FileAccess.Write, FileShare.None));

            wrttext.WriteBlockArray(Texture32);
            wrttext.Flush();
            wrttext.Close();

            reader.ReadBlock(out Texture16UncompressedSize);
            reader.ReadBlock(out Texture16CompressedSize);
            Texture16 = new byte[Texture16CompressedSize];
            reader.ReadBlockArray(out Texture16, Texture16CompressedSize);
            Texture16 = ZLib.DecompressData(Texture16);

            reader.ReadBlock(out MiscTextureUncompressedSize);
            reader.ReadBlock(out MiscTextureCompressedSize);
            MiscTexture = new byte[MiscTextureCompressedSize];
            reader.ReadBlockArray(out MiscTexture, MiscTextureCompressedSize);
            MiscTexture = ZLib.DecompressData(MiscTexture);

            reader.ReadBlock(out LevelUncompressedSize);
            reader.ReadBlock(out LevelCompressedSize);
            buffer = new byte[LevelCompressedSize];
            reader.ReadBlockArray(out buffer, LevelCompressedSize);
            buffer = ZLib.DecompressData(buffer);

            var stream = new MemoryStream();

            stream.Write(buffer, 0, (int)LevelUncompressedSize);
            stream.Seek(0, SeekOrigin.Begin);

            BinaryWriterEx wrt = new BinaryWriterEx(new FileStream("coastal.bin", FileMode.Create, FileAccess.Write, FileShare.None));

            wrt.Write(buffer, 0, (int)LevelUncompressedSize);
            wrt.Flush();
            wrt.Close();

            BinaryWriterEx wrs = new BinaryWriterEx(new FileStream("samples." + outFileName + ".bin", FileMode.Create, FileAccess.Write, FileShare.None));

            byte[] samples = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
            wrs.Write(samples);
            wrs.Flush();
            wrs.Close();

            reader.Close();

            reader = new BinaryReaderEx(stream);
            reader.ReadBlock(out Unused);
            reader.ReadBlock(out NumRooms);

            int max = 0;

            StreamWriter wp = new StreamWriter(new FileStream("portals" + outFileName + ".txt", FileMode.Create, FileAccess.Write, FileShare.None));

            Rooms = new tr_room[NumRooms];
            for (int i = 0; i < NumRooms; i++)
            {
                wp.WriteLine("=====================================================================");
                wp.WriteLine("ROOM #" + i);
                wp.WriteLine("=====================================================================");

                reader.ReadBlock(out Rooms[i].Info);
                reader.ReadBlock(out Rooms[i].NumDataWords);
                reader.ReadBlock(out Rooms[i].NumVertices);
                //  Rooms[i].Vertices = new tr_room_vertex[Rooms[i].NumVertices];
                reader.ReadBlockArray(out Rooms[i].Vertices, Rooms[i].NumVertices);
                if (Rooms[i].NumVertices > max)
                {
                    max = Rooms[i].NumVertices;
                }
                reader.ReadBlock(out Rooms[i].NumRectangles);
                Rooms[i].Rectangles = new tr_face4[Rooms[i].NumRectangles];
                for (int j = 0; j < Rooms[i].NumRectangles; j++)
                {
                    // Rooms[i].Rectangles[j].Vertices = new ushort[4];
                    reader.ReadBlockArray(out Rooms[i].Rectangles[j].Vertices, 4);
                    reader.ReadBlock(out Rooms[i].Rectangles[j].Texture);
                }

                reader.ReadBlock(out Rooms[i].NumTriangles);
                Rooms[i].Triangles = new tr_face3[Rooms[i].NumTriangles];
                for (int j = 0; j < Rooms[i].NumTriangles; j++)
                {
                    // Rooms[i].Triangles[j].Vertices = new ushort[3];
                    reader.ReadBlockArray(out Rooms[i].Triangles[j].Vertices, 3);
                    reader.ReadBlock(out Rooms[i].Triangles[j].Texture);
                }

                reader.ReadBlock(out Rooms[i].NumSprites);

                reader.ReadBlock(out Rooms[i].NumPortals);
                //Rooms[i].Portals = new tr_room_portal[Rooms[i].NumPortals];
                reader.ReadBlockArray(out Rooms[i].Portals, Rooms[i].NumPortals);

                for (int nn = 0; nn < Rooms[i].Portals.Length; nn++)
                {
                    tr_room_portal pt = Rooms[i].Portals[nn];
                    wp.WriteLine(nn + ": ");
                    wp.WriteLine("Room: " + pt.AdjoiningRoom);
                    for (int vv = 0; vv < 4; vv++)
                    {
                        wp.Write("V" + vv + " = " + pt.Vertices[vv].X + ", " + pt.Vertices[vv].Y + ", " + pt.Vertices[vv].Z);
                        wp.WriteLine("");
                    }
                    wp.WriteLine("");
                }

                reader.ReadBlock(out Rooms[i].NumZSectors);
                reader.ReadBlock(out Rooms[i].NumXSectors);
                //Rooms[i].Sectors = new tr_room_sector[Rooms[i].NumZSectors * Rooms[i].NumXSectors];
                reader.ReadBlockArray(out Rooms[i].Sectors, (uint)Rooms[i].NumZSectors * Rooms[i].NumXSectors);

                reader.ReadBlock(out Rooms[i].AmbientIntensity1);
                reader.ReadBlock(out Rooms[i].AmbientIntensity2);

                reader.ReadBlock(out Rooms[i].NumLights);
                reader.ReadBlockArray(out Rooms[i].Lights, Rooms[i].NumLights);

                reader.ReadBlock(out Rooms[i].NumStaticMeshes);
                reader.ReadBlockArray(out Rooms[i].StaticMeshes, Rooms[i].NumStaticMeshes);

                reader.ReadBlock(out Rooms[i].AlternateRoom);
                reader.ReadBlock(out Rooms[i].Flags);
                reader.ReadBlock(out Rooms[i].Param1);
                reader.ReadBlock(out Rooms[i].Unknown1);
                reader.ReadBlock(out Rooms[i].Unknown2);
            }

            wp.Flush();
            wp.Close();
            //return;

            reader.ReadBlock(out NumFloorData);
            reader.ReadBlockArray(out FloorData, NumFloorData);

            reader.ReadBlock(out NumMeshData);

            /*for (int i = 0; i < NumFloorData; i++)
             *  Console.WriteLine(FloorData[i].ToString("X2"));*/

            int   numBytes   = 0;
            int   totalBytes = 0;
            int   l          = 0;
            short temp       = 0;

            Meshes = new tr_mesh[2048];
            while (totalBytes < NumMeshData * 2)
            {
                long offset1 = reader.BaseStream.Position;

                reader.ReadBlock(out Meshes[l].Center);
                reader.ReadBlock(out Meshes[l].Radius);
                numBytes += 10;

                reader.ReadBlock(out Meshes[l].NumVertices);
                reader.ReadBlockArray(out Meshes[l].Vertices, Meshes[l].NumVertices);
                numBytes += 2 + 6 * Meshes[l].NumVertices;

                reader.ReadBlock(out Meshes[l].NumNormals);
                if (Meshes[l].NumNormals > 0)
                {
                    reader.ReadBlockArray(out Meshes[l].Normals, Meshes[l].NumNormals);
                    numBytes += 2 + 6 * Meshes[l].NumNormals;
                }
                else
                {
                    reader.ReadBlockArray(out Meshes[l].Lights, -Meshes[l].NumNormals);
                    numBytes += 2 - 2 * Meshes[l].NumNormals;
                }

                reader.ReadBlock(out Meshes[l].NumTexturedRectangles);
                reader.ReadBlockArray(out Meshes[l].TexturedRectangles, Meshes[l].NumTexturedRectangles);
                numBytes += 2 + 12 * Meshes[l].NumTexturedRectangles;

                reader.ReadBlock(out Meshes[l].NumTexturedTriangles);
                reader.ReadBlockArray(out Meshes[l].TexturedTriangles, Meshes[l].NumTexturedTriangles);
                numBytes += 2 + 10 * Meshes[l].NumTexturedTriangles;

                long offset2 = reader.BaseStream.Position;
                int  diff    = (int)(offset2 - offset1);
                if (diff % 4 != 0)
                {
                    reader.ReadBlock(out temp); diff += 2;
                }
                Meshes[l].MeshSize    = numBytes;
                Meshes[l].MeshPointer = totalBytes;

                if (l == 209)
                {
                    BinaryWriterEx tmpwriter = new BinaryWriterEx(new FileStream("cleopal.msh", FileMode.Create, FileAccess.Write, FileShare.None));
                    tmpwriter.WriteBlock(Meshes[l].Center);
                    tmpwriter.WriteBlock(Meshes[l].Radius);
                    tmpwriter.WriteBlock(Meshes[l].NumVertices);
                    tmpwriter.WriteBlockArray(Meshes[l].Vertices);
                    tmpwriter.WriteBlock(Meshes[l].NumNormals);
                    if (Meshes[l].NumNormals > 0)
                    {
                        tmpwriter.WriteBlockArray(Meshes[l].Normals);
                    }
                    else
                    {
                        tmpwriter.WriteBlockArray(Meshes[l].Lights);
                    }
                    tmpwriter.WriteBlock(Meshes[l].NumTexturedRectangles);
                    tmpwriter.WriteBlockArray(Meshes[l].TexturedRectangles);
                    tmpwriter.WriteBlock(Meshes[l].NumTexturedTriangles);
                    tmpwriter.WriteBlockArray(Meshes[l].TexturedTriangles);

                    tmpwriter.Flush();
                    tmpwriter.Close();
                }

                totalBytes += diff;// numBytes;
                numBytes    = 0;
                l++;
            }

            Array.Resize(ref Meshes, l);

            NumMeshes = (uint)Meshes.Length;

            reader.ReadBlock(out NumMeshPointers);
            reader.ReadBlockArray(out MeshPointers, NumMeshPointers);

            reader.ReadBlock(out NumAnimations);
            reader.ReadBlockArray(out Animations, NumAnimations);

            reader.ReadBlock(out NumStateChanges);
            reader.ReadBlockArray(out StateChanges, NumStateChanges);

            reader.ReadBlock(out NumAnimDispatches);
            reader.ReadBlockArray(out AnimDispatches, NumAnimDispatches);

            reader.ReadBlock(out NumAnimCommands);
            reader.ReadBlockArray(out AnimCommands, NumAnimCommands);

            reader.ReadBlock(out NumMeshTrees);
            reader.ReadBlockArray(out MeshTrees, NumMeshTrees);

            logger.Debug(reader.BaseStream.Position.ToString());
            reader.ReadBlock(out NumFrames);
            reader.ReadBlockArray(out Frames, NumFrames);

            reader.ReadBlock(out NumMoveables);
            reader.ReadBlockArray(out Moveables, NumMoveables);

            reader.ReadBlock(out NumStaticMeshes);
            reader.ReadBlockArray(out StaticMeshes, NumStaticMeshes);

            reader.ReadBlockArray(out SPR, 3);

            reader.ReadBlock(out NumSpriteTextures);
            reader.ReadBlockArray(out SpriteTextures, NumSpriteTextures);

            reader.ReadBlock(out NumSpriteSequences);
            reader.ReadBlockArray(out SpriteSequences, NumSpriteSequences);

            reader.ReadBlock(out NumCameras);
            reader.ReadBlockArray(out Cameras, NumCameras);

            reader.ReadBlock(out NumFlyByCameras);
            reader.ReadBlockArray(out FlyByCameras, NumFlyByCameras * 40);

            reader.ReadBlock(out NumSoundSources);
            reader.ReadBlockArray(out SoundSources, NumSoundSources);

            reader.ReadBlock(out NumBoxes);
            reader.ReadBlockArray(out Boxes, NumBoxes);

            reader.ReadBlock(out NumOverlaps);
            reader.ReadBlockArray(out Overlaps, NumOverlaps);

            // reader.ReadBlockArray(out Zones, NumBoxes * 10);
            Zones = new short[NumBoxes * 10];
            for (int n = 0; n < NumBoxes * 10; n++)
            {
                Zones[n] = reader.ReadInt16();
            }

            reader.ReadBlock(out NumAnimatedTextures);
            short[] animTextures;
            reader.ReadBlockArray(out animTextures, NumAnimatedTextures);

            string fn = Path.GetFileNameWithoutExtension(fileName);

            if (File.Exists("pathfinding." + fn + "." + outFileName + ".txt"))
            {
                File.Delete("pathfinding." + fn + "." + outFileName + ".txt");
            }
            StreamWriter writer = new StreamWriter(new FileStream("pathfinding." + fn + "." + outFileName + ".txt", FileMode.Create, FileAccess.Write, FileShare.None));

            writer.WriteLine("BOXES");

            for (int n = 0; n < Boxes.Length; n++)
            {
                writer.WriteLine("[" + n + "] " + "Xmin: " + Boxes[n].Xmin + ", " + "Xmax: " + Boxes[n].Xmax + ", " +
                                 "Zmin: " + Boxes[n].Zmin + ", " + "Zmax: " + Boxes[n].Zmax + ", " +
                                 "Floor: " + Boxes[n].TrueFloor + ", Overlap Index: " + Boxes[n].OverlapIndex);
            }

            writer.WriteLine(" ");
            writer.WriteLine("OVERLAPS");

            for (int n = 0; n < Overlaps.Length; n++)
            {
                writer.WriteLine("[" + n + "] " + (Overlaps[n] & 0x7fff));
                if ((Overlaps[n] & 0x8000) != 0)
                {
                    writer.WriteLine("--- END OF LIST ---");
                }
            }

            writer.WriteLine(" ");
            writer.WriteLine("ZONES");

            for (int n = 0; n < Boxes.Length; n++)
            {
                /*writer.WriteLine("[" + n + "] " + "Ground1: " + Zones[n * 10 + 0] + ", " + "Ground2: " + Zones[n * 10 + 1] + ", " +
                 *               "Ground3: " + Zones[n * 10 + 2] + ", " + "Ground4: " + Zones[n * 10 + 3] + ", " +
                 *               "Fly: " + Zones[n * 10 + 4] + ", A_Ground1: " + Zones[n * 10 + 5] + ", " + "A_Ground2: " + Zones[n * 10 + 6] + ", " +
                 *               "A_Ground3: " + Zones[n * 10 + 7] + ", " + "A_Ground4: " + Zones[n * 10 + 8] + ", " +
                 *               "A_Fly: " + Zones[n * 10 + 9]);*/
                writer.WriteLine("[" + n + "] " + "Ground1: " + Zones[n] + ", " + "Ground2: " + Zones[1 * NumBoxes + n] + ", " +
                                 "Ground3: " + Zones[2 * NumBoxes + n] + ", " + "Ground4: " + Zones[3 * NumBoxes + n] + ", " +
                                 "Fly: " + Zones[4 * NumBoxes + n] + ", A_Ground1: " + Zones[5 * NumBoxes + n] + ", " + "A_Ground2: " + Zones[6 * NumBoxes + n] + ", " +
                                 "A_Ground3: " + Zones[7 * NumBoxes + n] + ", " + "A_Ground4: " + Zones[8 * NumBoxes + n] + ", " +
                                 "A_Fly: " + Zones[9 * NumBoxes + n]);
            }

            writer.Flush();
            writer.Close();

            reader.ReadBlockArray(out TEX, 4);

            reader.ReadBlock(out NumObjectTextures);
            reader.ReadBlockArray(out ObjectTextures, NumObjectTextures);

            if (File.Exists("textures." + fn + "." + outFileName + ".txt"))
            {
                File.Delete("textures." + fn + "." + outFileName + ".txt");
            }
            writer = new StreamWriter(new FileStream("textures." + fn + "." + outFileName + ".txt", FileMode.Create, FileAccess.Write, FileShare.None));

            for (int ii = 0; ii < NumObjectTextures; ii++)
            {
                writer.WriteLine("TEXTURE #" + ii);
                writer.WriteLine("    TileAndFlags: " + (ObjectTextures[ii].Tile).ToString());
                writer.WriteLine("    NewFlags: " + (ObjectTextures[ii].Flags).ToString());
                writer.WriteLine("    Tile: " + (ObjectTextures[ii].Tile & 0xFF).ToString());
                for (int jj = 0; jj < 4; jj++)
                {
                    writer.WriteLine("    " + jj + " X: " +
                                     ((ushort)(ObjectTextures[ii].Vertices[jj].Xpixel << 8 + ObjectTextures[ii].Vertices[jj].Xcoordinate)).ToString() +
                                     " Y: " +
                                     ((ushort)(ObjectTextures[ii].Vertices[jj].Ypixel << 8 + ObjectTextures[ii].Vertices[jj].Ycoordinate)).ToString() +
                                     " (" + ObjectTextures[ii].Vertices[jj].Xpixel + ", " + ObjectTextures[ii].Vertices[jj].Ypixel + ")");
                }

                /* BinaryWriterEx tmpwriter2 = new BinaryWriterEx(new FileStream("test\\cleopal_" + ii + ".text", FileMode.Create, FileAccess.Write, FileShare.None));
                 * tmpwriter2.WriteBlock(ObjectTextures[ii]);
                 * tmpwriter2.Flush();
                 * tmpwriter2.Close();*/
            }

            writer.Flush();
            writer.Close();

            reader.ReadBlock(out NumItems);
            reader.ReadBlockArray(out Items, NumItems);

            reader.ReadBlock(out NumAiItems);
            reader.ReadBlockArray(out AiItems, NumAiItems);

            StreamWriter aiw = new StreamWriter(new FileStream("AI" + outFileName + ".txt", FileMode.Create, FileAccess.Write, FileShare.None));

            for (int n = 0; n < NumAiItems; n++)
            {
                aiw.WriteLine("[" + n + "]");
                aiw.WriteLine("    ObjectID: " + AiItems[n].ObjectID);
                aiw.WriteLine("    X: " + AiItems[n].X);
                aiw.WriteLine("    Y: " + AiItems[n].Y);
                aiw.WriteLine("    Z: " + AiItems[n].Z);
                aiw.WriteLine("    Room: " + AiItems[n].Room);
                aiw.WriteLine("    Angle: " + AiItems[n].Angle);
            }

            aiw.Flush();
            aiw.Close();

            BinaryWriterEx bwex = new BinaryWriterEx(new FileStream("sounds" + outFileName + ".sfx", FileMode.Create, FileAccess.Write, FileShare.None));

            var numDemo = reader.ReadInt16();

            byte[] soundmap        = reader.ReadBytes((numDemo != 0 ? numDemo * 2 : 740));
            int    numSoundDetails = reader.ReadInt32();

            byte[] details    = reader.ReadBytes(8 * numSoundDetails);
            int    numIndices = reader.ReadInt32();

            byte[] indices = reader.ReadBytes(4 * numIndices);

            bwex.Write(soundmap);
            bwex.Write(numSoundDetails);
            bwex.Write(details);
            bwex.Write(numIndices);
            bwex.Write(indices);

            bwex.Flush();
            bwex.Close();

            List <byte> bytes = new List <byte>();

            while (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                bytes.Add(reader.ReadByte());
            }
        }