/// <summary> /// Reads Sounds and def /// </summary> public void Initialize(Verdata verdata) { m_Cache = new UOSound[0xFFF]; m_Removed = new bool[0xFFF]; m_FileIndex = new FileIndex("soundidx.mul", "sound.mul", "soundLegacyMUL.uop", 0xFFF, 8, ".dat", -1, false, verdata, _Files); var reg = new Regex(@"(\d{1,3}) \x7B(\d{1,3})\x7D (\d{1,3})", RegexOptions.Compiled); m_Translations = new Dictionary <int, int>(); string line; string path = _Files.GetFilePath("Sound.def"); if (path == null) { return; } using (var reader = new StreamReader(path)) { while ((line = reader.ReadLine()) != null) { if (((line = line.Trim()).Length != 0) && !line.StartsWith("#")) { Match match = reg.Match(line); if (match.Success) { m_Translations.Add(int.Parse(match.Groups[1].Value), int.Parse(match.Groups[2].Value)); } } } } }
/// <summary> /// Inizializza una nuova istanza della classe <see cref="T:System.Object"/>. /// </summary> public Light(Verdata verdata, Files files) { _files = files; m_FileIndex = new FileIndex("lightidx.mul", "light.mul", 100, -1, verdata, files); m_Cache = new Bitmap[100]; m_Removed = new bool[100]; }
/// <summary> /// Inizializza una nuova istanza della classe <see cref="T:System.Object"/>. /// </summary> public AnimationEdit(Verdata verdata, Animations animations, Files files) { this._Animations = animations; _files = files; m_FileIndex = new FileIndex("Anim.idx", "Anim.mul", 6, verdata, _files); m_FileIndex2 = new FileIndex("Anim2.idx", "Anim2.mul", -1, verdata, _files); m_FileIndex3 = new FileIndex("Anim3.idx", "Anim3.mul", -1, verdata, _files); m_FileIndex4 = new FileIndex("Anim4.idx", "Anim4.mul", -1, verdata, _files); m_FileIndex5 = new FileIndex("Anim5.idx", "Anim5.mul", -1, verdata, _files); if (m_FileIndex.IdxLength > 0) { animcache = new AnimIdx[m_FileIndex.IdxLength / 12]; } if (m_FileIndex2.IdxLength > 0) { animcache = new AnimIdx[m_FileIndex2.IdxLength / 12]; } if (m_FileIndex3.IdxLength > 0) { animcache = new AnimIdx[m_FileIndex3.IdxLength / 12]; } if (m_FileIndex4.IdxLength > 0) { animcache = new AnimIdx[m_FileIndex4.IdxLength / 12]; } if (m_FileIndex5.IdxLength > 0) { animcache = new AnimIdx[m_FileIndex5.IdxLength / 12]; } }
public void Init() { Verdata = new Verdata(this); RadarCol = new RadarCol(this); Hues = new Hues(this); Gumps = new Gumps(this); Art = new Art(this); TileData = new TileData(this); Skills = new Skills(this); Light = new Light(this); Sound = new Sounds(this); Textures = new Textures(this); Multis = new Multis(this); AnimationEdit = new AnimationEdit(this); ASCIIText = new ASCIIText(this); Maps = new Dictionary <MapNames, Map> { { MapNames.Felucca, Map.Felucca(this) }, { MapNames.Ilshenar, Map.Ilshenar(this) }, { MapNames.Malas, Map.Malas(this) }, { MapNames.Trammel, Map.Trammel(this) }, { MapNames.Tokuno, Map.Tokuno(this) }, { MapNames.TerMur, Map.TerMur(this) } }; MultiMap = new Ultima.MultiMap(this); Animations = new Animations(this); }
public Gumps(Verdata verdata, Files files) { _Files = files; if (m_FileIndex != null) { m_Cache = new Bitmap[m_FileIndex.Index.Length]; m_Removed = new bool[m_FileIndex.Index.Length]; } else { m_Cache = new Bitmap[0xFFFF]; m_Removed = new bool[0xFFFF]; } try { m_FileIndex = new FileIndex("Gumpidx.mul", "Gumpart.mul", "gumpartLegacyMUL.uop", 12, -1, ".tga", -1, true, verdata, _Files); m_Cache = new Bitmap[m_FileIndex.Index.Length]; m_Removed = new bool[m_FileIndex.Index.Length]; } catch { m_FileIndex = null; m_Cache = new Bitmap[0xFFFF]; m_Removed = new bool[0xFFFF]; } m_PixelBuffer = null; m_StreamBuffer = null; m_ColorTable = null; m_patched.Clear(); }
public Stream Seek(int index, out int length, out int extra, out bool patched) { if (index < 0 || index >= Index.Length) { length = extra = 0; patched = false; return(null); } Entry3D e = Index[index]; if (e.Lookup < 0) { length = extra = 0; patched = false; return(null); } length = e.Length & 0x7FFFFFFF; extra = e.Extra; if ((e.Length & (1 << 31)) != 0) { patched = true; Verdata.Seek(e.Lookup); return(Verdata.Stream); } if (e.Length < 0) { length = extra = 0; patched = false; return(null); } if ((_stream?.CanRead != true) || (!_stream.CanSeek)) { _stream = _mulPath == null ? null : new FileStream(_mulPath, FileMode.Open, FileAccess.Read, FileShare.Read); } if (_stream == null) { length = extra = 0; patched = false; return(null); } if (_stream.Length < e.Lookup) { length = extra = 0; patched = false; return(null); } patched = false; _stream.Seek(e.Lookup, SeekOrigin.Begin); return(_stream); }
public Textures(Verdata verdata, Files files) { this._Files = files; m_FileIndex = new FileIndex("Texidx.mul", "Texmaps.mul", 0x4000, 10, verdata, _Files); m_Cache = new Bitmap[0x4000]; m_Removed = new bool[0x4000]; m_patched.Clear(); }
/// <summary> /// Inizializza una nuova istanza della classe <see cref="T:System.Object"/>. /// </summary> public Art(Verdata verdata, Files files) { _Files = files; m_Cache = new Bitmap[0xFFFF]; m_Removed = new bool[0xFFFF]; m_FileIndex = new FileIndex("Artidx.mul", "Art.mul", "artLegacyMUL.uop", 0x10000 /*0x13FDC*/, 4, ".tga", 0x13FDC, false, verdata, files); m_patched.Clear(); Modified = false; }
/// <summary> /// Inizializza una nuova istanza della classe <see cref="T:System.Object"/>. /// </summary> public Animations(Verdata verdata, Hues hues, Files files) { _files = files; m_FileIndex = new FileIndex("Anim.idx", "Anim.mul", 0x40000, 6, verdata, _files); m_FileIndex2 = new FileIndex("Anim2.idx", "Anim2.mul", 0x10000, -1, verdata, files); m_FileIndex3 = new FileIndex("Anim3.idx", "Anim3.mul", 0x20000, -1, verdata, files); m_FileIndex4 = new FileIndex("Anim4.idx", "Anim4.mul", 0x20000, -1, verdata, files); m_FileIndex5 = new FileIndex("Anim5.idx", "Anim5.mul", 0x20000, -1, verdata, files); _BodyConverter = new BodyConverter(_files); BodyTable = new BodyTable(_files); _hues = hues; LoadTable(); }
/// <summary> /// Inizializza una nuova istanza della classe <see cref="T:System.Object"/>. /// </summary> /// public Skills(Verdata verdata, Files files) { _files = files; m_FileIndex = new FileIndex("skills.idx", "skills.mul", 16, verdata, _files); m_SkillEntries = new List <SkillInfo>(); for (int i = 0; i < m_FileIndex.Index.Length; ++i) { SkillInfo info = GetSkill(i); if (info == null) { break; } m_SkillEntries.Add(info); } }
public Stream Seek(int index, out int length, out int extra, out bool patched) { if (index < 0 || index >= Index.Length) { length = extra = 0; patched = false; return(null); } Entry3D e = Index[index]; if (e.lookup < 0) { length = extra = 0; patched = false; return(null); } length = e.length & 0x7FFFFFFF; extra = e.extra; if ((e.length & (1 << 31)) != 0) { patched = true; Verdata.Seek(e.lookup); return(Verdata.Stream); } if (e.length < 0) { length = extra = 0; patched = false; return(null); } if ((Stream == null) || (!Stream.CanRead) || (!Stream.CanSeek)) { if (MulPath == null) { Stream = null; } else { Stream = new FileStream(MulPath, FileMode.Open, FileAccess.Read, FileShare.Read); } } if (Stream == null) { length = extra = 0; patched = false; return(null); } else if (Stream.Length < e.lookup) { length = extra = 0; patched = false; return(null); } patched = false; Stream.Seek(e.lookup, SeekOrigin.Begin); return(Stream); }
public Sounds(Verdata verdata, Files files) { _Files = files; Initialize(verdata); }
public FileIndex(string idxFile, string mulFile, int file, Verdata verdata, Files files) { _files = files; this._Verdata = verdata; string idxPath = null; MulPath = null; if (_files.MulPath == null) { _files.LoadMulPath(); } if (_files.MulPath.Count > 0) { idxPath = _files.MulPath[idxFile.ToLower()]; MulPath = _files.MulPath[mulFile.ToLower()]; if (String.IsNullOrEmpty(idxPath)) { idxPath = null; } else { if (String.IsNullOrEmpty(Path.GetDirectoryName(idxPath))) { idxPath = Path.Combine(_files.RootDir, idxPath); } if (!File.Exists(idxPath)) { idxPath = null; } } if (String.IsNullOrEmpty(MulPath)) { MulPath = null; } else { if (String.IsNullOrEmpty(Path.GetDirectoryName(MulPath))) { MulPath = Path.Combine(_files.RootDir, MulPath); } if (!File.Exists(MulPath)) { MulPath = null; } } } if ((idxPath != null) && (MulPath != null)) { using (var index = new FileStream(idxPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)) { Stream = new FileStream(MulPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); var count = (int)(index.Length / 12); IdxLength = index.Length; Index = new Entry3D[count]; GCHandle gc = GCHandle.Alloc(Index, GCHandleType.Pinned); var buffer = new byte[index.Length]; index.Read(buffer, 0, (int)index.Length); Marshal.Copy(buffer, 0, gc.AddrOfPinnedObject(), (int)index.Length); gc.Free(); } } else { Stream = null; Index = new Entry3D[1]; return; } Entry5D[] patches = _Verdata.Patches; if (file > -1) { for (int i = 0; i < patches.Length; ++i) { Entry5D patch = patches[i]; if (patch.file == file && patch.index >= 0 && patch.index < Index.Length) { Index[patch.index].lookup = patch.lookup; Index[patch.index].length = patch.length | (1 << 31); Index[patch.index].extra = patch.extra; } } } }
public FileIndex( string idxFile, string mulFile, string uopFile, int length, int file, string uopEntryExtension, int idxLength, bool hasExtra, Verdata verdata, Files files) { _files = files; this._Verdata = verdata; Index = new Entry3D[length]; string idxPath = null; MulPath = null; string uopPath = null; if (_files.MulPath == null) { _files.LoadMulPath(); } if (_files.MulPath.Count > 0) { idxPath = _files.MulPath[idxFile.ToLower()]; MulPath = _files.MulPath[mulFile.ToLower()]; if (!String.IsNullOrEmpty(uopFile) && _files.MulPath.ContainsKey(uopFile.ToLower())) { uopPath = _files.MulPath[uopFile.ToLower()]; } if (String.IsNullOrEmpty(idxPath)) { idxPath = null; } else { if (String.IsNullOrEmpty(Path.GetDirectoryName(idxPath))) { idxPath = Path.Combine(_files.RootDir, idxPath); } if (!File.Exists(idxPath)) { idxPath = null; } } if (String.IsNullOrEmpty(MulPath)) { MulPath = null; } else { if (String.IsNullOrEmpty(Path.GetDirectoryName(MulPath))) { MulPath = Path.Combine(_files.RootDir, MulPath); } if (!File.Exists(MulPath)) { MulPath = null; } } if (String.IsNullOrEmpty(uopPath)) { uopPath = null; } else { if (String.IsNullOrEmpty(Path.GetDirectoryName(uopPath))) { uopPath = Path.Combine(_files.RootDir, uopPath); } if (!File.Exists(uopPath)) { uopPath = null; } else { MulPath = uopPath; } } } /* UOP files support code, written by Wyatt (c) www.ruosi.org * idxLength variable was added for compatibility with legacy code for art (see art.cs) * At the moment the only UOP file having entries with extra field is gumpartlegacy.uop, * and it's two dwords in the beginning of the entry. * It's possible that UOP can include some entries with unknown hash: not really unknown for me, but * not useful for reading legacy entries. That's why i removed unknown hash exception throwing from this code */ if (MulPath != null && MulPath.EndsWith(".uop")) { using (var index = new FileStream(MulPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)) { Stream = new FileStream(MulPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); var fi = new FileInfo(MulPath); string uopPattern = fi.Name.Replace(fi.Extension, "").ToLowerInvariant(); using (var br = new BinaryReader(Stream)) { br.BaseStream.Seek(0, SeekOrigin.Begin); if (br.ReadInt32() != 0x50594D) { throw new ArgumentException("Bad UOP file."); } br.ReadInt64(); // version + signature long nextBlock = br.ReadInt64(); br.ReadInt32(); // block capacity int count = br.ReadInt32(); if (idxLength > 0) { IdxLength = idxLength * 12; } var hashes = new Dictionary <ulong, int>(); for (int i = 0; i < length; i++) { string entryName = string.Format("build/{0}/{1:D8}{2}", uopPattern, i, uopEntryExtension); ulong hash = HashFileName(entryName); if (!hashes.ContainsKey(hash)) { hashes.Add(hash, i); } } br.BaseStream.Seek(nextBlock, SeekOrigin.Begin); do { int filesCount = br.ReadInt32(); nextBlock = br.ReadInt64(); for (int i = 0; i < filesCount; i++) { long offset = br.ReadInt64(); int headerLength = br.ReadInt32(); int compressedLength = br.ReadInt32(); int decompressedLength = br.ReadInt32(); ulong hash = br.ReadUInt64(); br.ReadUInt32(); // Adler32 short flag = br.ReadInt16(); int entryLength = flag == 1 ? compressedLength : decompressedLength; if (offset == 0) { continue; } int idx; if (hashes.TryGetValue(hash, out idx)) { if (idx < 0 || idx > Index.Length) { throw new IndexOutOfRangeException("hashes dictionary and files collection have different count of entries!"); } Index[idx].lookup = (int)(offset + headerLength); Index[idx].length = entryLength; if (hasExtra) { long curPos = br.BaseStream.Position; br.BaseStream.Seek(offset + headerLength, SeekOrigin.Begin); byte[] extra = br.ReadBytes(8); var extra1 = (ushort)((extra[3] << 24) | (extra[2] << 16) | (extra[1] << 8) | extra[0]); var extra2 = (ushort)((extra[7] << 24) | (extra[6] << 16) | (extra[5] << 8) | extra[4]); Index[idx].lookup += 8; Index[idx].extra = extra1 << 16 | extra2; br.BaseStream.Seek(curPos, SeekOrigin.Begin); } } } }while (br.BaseStream.Seek(nextBlock, SeekOrigin.Begin) != 0); } } } else if ((idxPath != null) && (MulPath != null)) { using (var index = new FileStream(idxPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)) { Stream = new FileStream(MulPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); var count = (int)(index.Length / 12); IdxLength = index.Length; GCHandle gc = GCHandle.Alloc(Index, GCHandleType.Pinned); var buffer = new byte[index.Length]; index.Read(buffer, 0, (int)index.Length); Marshal.Copy(buffer, 0, gc.AddrOfPinnedObject(), (int)Math.Min(IdxLength, length * 12)); gc.Free(); for (int i = count; i < length; ++i) { Index[i].lookup = -1; Index[i].length = -1; Index[i].extra = -1; } } } else { Stream = null; return; } Entry5D[] patches = _Verdata.Patches; if (file > -1) { for (int i = 0; i < patches.Length; ++i) { Entry5D patch = patches[i]; if (patch.file == file && patch.index >= 0 && patch.index < length) { Index[patch.index].lookup = patch.lookup; Index[patch.index].length = patch.length | (1 << 31); Index[patch.index].extra = patch.extra; } } } }
public FileIndex(string idxFile, string mulFile, int length, int file, Verdata verdata, Files files) : this(idxFile, mulFile, null, length, file, ".dat", -1, false, verdata, files) { }