public void OpenFile(string file,bool getObjects=false,bool useNewTextures=true)
        {
            if (File.Exists(file))
            {
                Task.Factory.StartNew(() =>
                    {
                        S3D s3d = null;
                        int status = 0;

                        status += 5;
                        DoStatusUpdate(status, "Loading " + file);

                        try
                        {
                            s3d = S3D.Load(file);
                        }
                        catch (Exception e)
                        {
                            DoStatusUpdate(0, "Failed loading s3d: " + e.Message, false);
                            return;
                        }

                        _archive = s3d;

                        var filename = System.IO.Path.GetFileName(file);
                        int period = filename.IndexOf('.', 0);
                        var zone = filename.Substring(0, period);
                        string dir = Path.GetDirectoryName(file);

                        //var archiveFile = s3d.Files.FirstOrDefault(x => x.Name.Contains(zone + ".wld"));
                        //if (archiveFile == null) return;

                        _wld = null;
                        _objectLocations = null;
                        List<WLD> wlds = new List<WLD>();

                        foreach (var archive in s3d.Files.Where(x => x.Name.Contains(".wld")))
                        {
                            bool isObjects = archive.Name.Contains("objects.wld");
                            if (isObjects && !getObjects) continue;

                            status += 20;
                            DoStatusUpdate(status, "Loading " + archive.Name);

                            using (var ms = new MemoryStream(archive.Bytes))
                            {
                                WLD wld = null;
                                try
                                {
                                    wld = WLD.Load(ms,archive.Name);
                                    if (useNewTextures) wld.TexturingFormat = WLD.TextureFormat.HighResolution;
                                    else wld.TexturingFormat = WLD.TextureFormat.Original;
                                }
                                catch (Exception e)
                                {
                                    DoStatusUpdate(0, "Failed loading: " + archive.Name + " " + e.Message, false);
                                    return;
                                }
                                wlds.Add(wld);
                                if (archive.Name.Contains(zone + ".wld"))
                                {
                                    _wld = wld;
                                    if (archive.Name.Contains("_obj") || archive.Name.Contains("_chr"))
                                    {
                                        _wld.ResolveMeshNames();
                                    }
                                }
                                else if (isObjects)
                                {
                                    _objectLocations = wld;
                                    if (_objectLocations != null)
                                    {
                                        _objectLocations.ResolveObjectLocationNames();
                                    }
                                }
                            }
                        }
                        _wlds = wlds;

                        //load up the _obj.s3d WLD
                        string objFile = dir + "\\" + zone + "_obj.s3d";

                        if (getObjects && File.Exists(objFile))
                        {
                            status += 10;
                            DoStatusUpdate(status, "Loading " + zone + "_obj.s3d");
                            var objS3d = S3D.Load(objFile);
                            var archive = objS3d.Files.FirstOrDefault(x => x.Name.Contains(".wld"));
                            if (archive != null)
                            {
                                using (var ms = new MemoryStream(archive.Bytes))
                                {
                                    WLD wld = null;
                                    try
                                    {
                                        wld = WLD.Load(ms,archive.Name);
                                    }
                                    catch (Exception e)
                                    {
                                        DoStatusUpdate(0, "Failed loading: " + archive.Name + " " + e.Message, false);
                                        return;
                                    }
                                    wlds.Add(wld);
                                    _objects = wld;
                                    _objects.Files = objS3d;
                                }
                                if (_objects != null)
                                {
                                    _objects.ResolveMeshNames();
                                }
                            }
                        }

                        if (wlds.Count > 0)
                        {
                            status = 90;
                            DoStatusUpdate(status, "Generating Geometry", false);
                            _wld = _wld == null ? wlds.ElementAt(0) : _wld;
                        }

                        _dispatcher.BeginInvoke((Action)(() =>
                        {
                            if (_wld != null)
                            {
                                _wld.Files = s3d;
                                WLDObject = _wld;
                                _wlds = wlds;
                            }

                            Status = new LoadStatus()
                            {
                                PercentDone = 100,
                                OperationDescription = "Done"
                            };
                        }));
                    });
            }
        }
Beispiel #2
0
        public static S3D Load(string file)
        {
            S3D s3d = null;

            //var fileInfo = new FileInfo(file);
            //var s3dFile = new byte[fileInfo.Length];

            using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                int size = Marshal.SizeOf(typeof(PFSHeader));
                var barray = new byte[size];

                fs.Read(barray, 0, size);
                PFSHeader header = Functions.ByteArrayToStructure<PFSHeader>(barray);

                unsafe
                {
                    if (header.MagicCookie[0] != 'P' && header.MagicCookie[1] != 'F' && header.MagicCookie[2] != 'S' && header.MagicCookie[3] != ' ')
                    {
                        throw new ArgumentException();
                    }
                }

                int uint32size = Marshal.SizeOf(typeof(UInt32));

                //determine the file count
                fs.Seek(header.Offset, SeekOrigin.Begin);
                barray = new byte[uint32size];
                fs.Read(barray, 0, uint32size);

                int filecount = BitConverter.ToInt32(barray, 0);
                //var files = new ArchiveFile[filecount];
                var files = new List<ArchiveFile>();
                size = Marshal.SizeOf(typeof(PFSMeta));

                ArchiveFile directory = new ArchiveFile();

                for (int i = 0; i < filecount; i++)
                {
                    barray = new byte[size];
                    fs.Read(barray, 0, size);
                    var block = Functions.ByteArrayToStructure<PFSMeta>(barray);

                    var f = new ArchiveFile();
                    f.Meta = block;

                    if (block.CRC == 0x61580AC9)
                    {
                        directory = f;
                    }
                    else
                    {
                        files.Add(f);
                    }
                }

                if (directory.Meta.Offset == 0 || directory.Meta.Size == 0) throw new Exception("Could not find directory in archive");

                fs.Seek(directory.Meta.Offset, SeekOrigin.Begin);
                size = Marshal.SizeOf(typeof(PFSData));
                barray = new byte[size];

                var tempBuffer = new ArrayList( (int)directory.Meta.Size);
                int inflatedSize = 0;
                while( inflatedSize < directory.Meta.Size )
                {
                    fs.Read(barray, 0, size);

                    var data = Functions.ByteArrayToStructure<PFSData>(barray);

                    var deflatedBuffer = new byte[data.DeflatedLength];
                    var inflatedBuffer = new byte[data.InflatedLength];

                    fs.Read(deflatedBuffer, 0, (int)data.DeflatedLength);

                    s3d = new S3D();
                    s3d.Decompress(deflatedBuffer, (int)data.DeflatedLength, inflatedBuffer, (int)data.InflatedLength);
                    tempBuffer.AddRange(inflatedBuffer);
                    inflatedSize += (int)data.InflatedLength;
                }

                if (directory.Meta.Size != tempBuffer.Count)
                {
                    throw new Exception("Directory size mismatch");
                }

                List<string> fileNames = new List<string>();
                using (var ms = new MemoryStream(tempBuffer.Cast<byte>().ToArray()))
                {
                    ms.Seek(8, SeekOrigin.Begin);
                    var encoding = new ASCIIEncoding();
                    for (int i = 0; i < filecount - 1; i++)
                    {
                        int val = -1;
                        List<byte> namechars = new List<byte>();

                        while (val != 0)
                        {
                            val = ms.ReadByte();

                            if (val != 0)
                            {
                                namechars.Add((byte)val);
                            }
                            else
                            {
                                fileNames.Add(encoding.GetString(namechars.ToArray()));
                                ms.Seek(4, SeekOrigin.Current);
                                break;
                            }
                        }
                    }
                }

                s3d._files = files.OrderBy(x => x.Meta.Offset);
                for (int i = 0; i < s3d._files.Count(); i++)
                {
                    s3d._files.ElementAt(i).Name = fileNames.ElementAt(i).ToLower();
                    s3d.DecompressFile(s3d._files.ElementAt(i), fs);
                }
            }
            return s3d;
        }