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" }; })); }); } }
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; }