public HeaderFix(string filename) { BaseFile = filename; //Find offsets //Créer buffer avec données du m2 byte[] data = File.ReadAllBytes(filename); //Utilise SearchPattern pour ajouter dans le dictionnaires les offsets de lecture des chunk dans la liste de chunk foreach (var c in ChunkNames) { Offsets.Add(c, SearchPattern(data, Encoding.UTF8.GetBytes(c))); } //Calculate MD20 size //si on lit de 0 à 4 'MD21' alors on lit les offsets de du dictionnaire et on récupère la plus petite valeur //On lui enlève 8 = la taille du header MD21, ainsi on obtient la taille du m2 sans les chunk ni le header if (Encoding.UTF8.GetString(data, 0, 4) == "MD21") { MD20Size = (uint)Offsets.Where(x => x.Value > -1).Min(x => x.Value) - 8; } //sinon on lit la fichier entier en taille, il faut convertir à WoD pour ça, s'il y a les chunk ça va psoer problème. else { MD20Size = (uint)data.Length; } //Si pas de offset dans la liste, on arrête. if (!Offsets.Any(x => x.Value > -1)) { return; } //Read data using (var fs = new FileStream(BaseFile, FileMode.Open, FileAccess.ReadWrite)) using (var br = new BinaryReader(fs)) { foreach (var offset in Offsets) { if (offset.Value == -1) { continue; } //On lit les données du m2 au niveau des chunks. On met la position du reader à l'offset et on ajoute 4 pour passer le nom. br.BaseStream.Position = offset.Value + 4; //Skip chunk name //ReadUint32 pour lire 4 octets, cela placera également le reader après ces 4 octets en position. uint size = br.ReadUInt32(); //Chunk size switch (offset.Key) { //Pour chaque cas il faut divisier la taille par 4 pour le vrai nombre d'élément de référencement dans le chunk. Size lecture = 4 * vraie size. //A chaque lecture la position est modifiée, pas besoin de repositionner (je sais pas pourquoi c'est 8 sur le afid de barn, c'pas de moi c'te méthode. case "SKID": SKID = br.ReadUInt32(); break; case "BFID": for (int i = 0; i < (size / 4); i++) { BFID.Add(new Row <uint>(br.ReadUInt32())); } break; case "AFID": for (int i = 0; i < (size / 8); i++) { AFID.Add(new AFID(br)); } break; case "SFID": for (int i = 0; i < (size / 4); i++) { SFID.Add(new Row <uint>(br.ReadUInt32())); } break; case "PFID": PFID = br.ReadUInt32(); break; } } } }
public void Save() { //Remove incomplete rows SFID.RemoveAll(x => x.FileId <= 0); BFID.RemoveAll(x => x.FileId <= 0); AFID.RemoveAll(x => x.FileId <= 0); using (var fs = new FileStream(BaseFile, FileMode.Open, FileAccess.ReadWrite)) using (var bw = new BinaryWriter(fs)) using (var br = new BinaryReader(fs)) { //PFID if (PFID > 0) { bw.BaseStream.Position = Offsets["PFID"] > -1 ? Offsets["PFID"] : bw.BaseStream.Length; bw.Write(Encoding.UTF8.GetBytes("PFID")); bw.Write(PFID); } //SKID if (SKID > 0) { bw.BaseStream.Position = Offsets["SKID"] > -1 ? Offsets["SKID"] : bw.BaseStream.Length; bw.Write(Encoding.UTF8.GetBytes("SKID")); bw.Write(PFID); } //SFID if (SFID.Count > 0) { bw.BaseStream.Position = Offsets["SFID"] > -1 ? Offsets["SFID"] : bw.BaseStream.Length; bw.Write(Encoding.UTF8.GetBytes("SFID")); bw.Write((uint)(SFID.Count * 4)); SFID.ForEach(x => bw.Write(x.FileId)); } //BFID if (BFID.Count > 0) { bw.BaseStream.Position = Offsets["BFID"] > -1 ? Offsets["BFID"] : bw.BaseStream.Length; bw.Write(Encoding.UTF8.GetBytes("BFID")); bw.Write((uint)(BFID.Count * 4)); BFID.ForEach(x => bw.Write(x.FileId)); } //AFID if (AFID.Count > 0) { bw.BaseStream.Position = Offsets["AFID"] > -1 ? Offsets["AFID"] : bw.BaseStream.Length; bw.Write(Encoding.UTF8.GetBytes("AFID")); bw.Write((uint)(AFID.Count * 8)); AFID.ForEach(x => { bw.Write(x.AnimId); bw.Write(x.SubAnimId); bw.Write(x.FileId); }); } fs.Flush(); FixHeader(bw, br); } }