/// <summary> /// Read a group file. /// </summary> /// <param name="br">The reader.</param> /// <param name="files">List of sound files to make a reference to.</param> public void Read(BinaryDataReader br, List <SoundFile <ISoundFile> > files) { //Open file. FileReader FileReader = new FileReader(); FileReader.OpenFile(br, out writeMode, out Version); //Open info block. FileReader.OpenBlock(br, 0); //Load reference table. FileReader.OpenReferenceTable(br, "FileRefs"); //Load each reference. SoundFiles = new List <SoundFile <ISoundFile> >(); List <SizedReference> sizedReferences = new List <SizedReference>(); for (int i = 0; i < FileReader.ReferenceTableCount("FileRefs"); i++) { //Null reference. if (FileReader.ReferenceTableReferenceIsNull(i, "FileRefs")) { SoundFiles.Add(null); sizedReferences.Add(null); } //Valid reference. else { //Jump to reference. FileReader.ReferenceTableJumpToReference(br, i, "FileRefs"); //Get file id. UInt32 fileId = br.ReadUInt32(); //Add the sized reference. sizedReferences.Add(new SizedReference(ref br)); //If the file references exist. if (files != null) { //If file id is found in the files. if (files.Where(x => x.FileId == (int)fileId).Count() > 0) { //Add sound file. SoundFiles.Add(new SoundFile <ISoundFile>()); files.Where(x => x.FileId == (int)fileId).ToList()[0].ReferencedBy.Add(SoundFiles[SoundFiles.Count - 1]); SoundFiles[SoundFiles.Count - 1].Reference = files.Where(x => x.FileId == (int)fileId).ToList()[0]; } //Independent mode. else { //Add sound file. SoundFiles.Add(new SoundFile <ISoundFile>() { FileId = (int)fileId }); } } //Independent mode. else { //Add sound file. SoundFiles.Add(new SoundFile <ISoundFile>() { FileId = (int)fileId }); } } } //Close table. FileReader.CloseReferenceTable("FileRefs"); //Close info block. FileReader.CloseBlock(br); //Open file block. FileReader.OpenBlock(br, 1); //Read the files. for (int i = 0; i < SoundFiles.Count; i++) { //File exist in first place. if (SoundFiles[i] != null) { //Sound file reference is null, so no embed. if (sizedReferences[i].offset == Reference.NULL_PTR) { SoundFiles[i].Embed = false; } //Sound file reference exist, embed and read it. else { //Embed file. SoundFiles[i].Embed = true; //Jump to file. FileReader.JumpToOffsetManually(br, sizedReferences[i].offset); //Read file. SoundFiles[i].File = SoundArchiveReader.ReadFile(br.ReadBytes((int)sizedReferences[i].size)); } } } //Close file block. FileReader.CloseBlock(br); //New extra info. ExtraInfo = new List <InfoExEntry>(); //Only open EX block if version is bigger than one. if (Version > new FileWriter.Version(1, 0, 0)) { //Open extended info block. FileReader.OpenBlock(br, 2); //Open the table. FileReader.OpenReferenceTable(br, "Ex"); //Reach each extra info entry. for (int i = 0; i < FileReader.ReferenceTableCount("Ex"); i++) { //Entry is null. if (FileReader.ReferenceTableReferenceIsNull(i, "Ex")) { ExtraInfo.Add(null); } //Entry exist. else { //Read data. Id id = new Id(ref br); UInt32 flags = br.ReadUInt32(); //New entry. InfoExEntry e = new InfoExEntry(); e.ItemIndex = (int)id.index; //Type. switch (id.type) { //Sound. case SoundTypes.Sound: e.ItemType = InfoExEntry.EItemType.Sound; break; //Seq sound set or wave data. case SoundTypes.SoundGroup: e.ItemType = InfoExEntry.EItemType.SequenceSetOrWaveData; break; //Bank. case SoundTypes.Bank: e.ItemType = InfoExEntry.EItemType.Bank; break; //Wave archive. case SoundTypes.WaveArchive: e.ItemType = InfoExEntry.EItemType.WaveArchive; break; } //Find flags. bool seq = (flags & 0b1) > 0; bool wsd = (flags & 0b10) > 0; bool bnk = (flags & 0b100) > 0; bool war = (flags & 0b1000) > 0; //Test for flags. if (flags == 0xFFFFFFFF) { e.LoadFlags = InfoExEntry.ELoadFlags.All; } else if (seq && bnk) { e.LoadFlags = InfoExEntry.ELoadFlags.SeqAndBank; } else if (seq && war) { e.LoadFlags = InfoExEntry.ELoadFlags.SeqAndWarc; } else if (bnk && war) { e.LoadFlags = InfoExEntry.ELoadFlags.BankAndWarc; } else if (seq) { e.LoadFlags = InfoExEntry.ELoadFlags.Seq; } else if (bnk) { e.LoadFlags = InfoExEntry.ELoadFlags.Bank; } else if (wsd) { e.LoadFlags = InfoExEntry.ELoadFlags.Wsd; } else if (war) { e.LoadFlags = InfoExEntry.ELoadFlags.Warc; } //Add entry. ExtraInfo.Add(e); } } //Close the table. FileReader.CloseReferenceTable("Ex"); //Close extended info block. FileReader.CloseBlock(br); } //Close file. FileReader.CloseFile(br); }
/// <summary> /// Write the file. /// </summary> /// <param name="writeMode">Write mode.</param> /// <param name="bw">The writer.</param> public void Write(WriteMode writeMode, BinaryDataWriter bw) { //Set write mode. this.writeMode = writeMode; //Init file. FileWriter FileWriter = new FileWriter(); FileWriter.InitFile(bw, writeMode, "GRP", Version > new FileWriter.Version(1, 0, 0) ? 3 : 2, Version); //Info block. FileWriter.InitBlock(bw, ReferenceTypes.GRP_Block_Info, "INFO"); //Reference table to group items. FileWriter.InitReferenceTable(bw, SoundFiles.Count, "FileRefs"); //Write each sound thing. for (int i = 0; i < SoundFiles.Count; i++) { //Null. if (SoundFiles[i] == null) { FileWriter.AddReferenceTableNullReference("FileRefs"); } //Exists. else { //Add reference. FileWriter.AddReferenceTableReference(bw, ReferenceTypes.GRP_Info_Item, "FileRefs"); //Write data. bw.Write((uint)SoundFiles[i].FileId); FileWriter.InitSizedReference(bw, "FileRef" + i); } } //Align. FileWriter.Align(bw, 0x20); //Close reference table. FileWriter.CloseReferenceTable(bw, "FileRefs"); //Close info block. FileWriter.CloseBlock(bw); //File block. FileWriter.InitBlock(bw, ReferenceTypes.GRP_Block_File, "FILE"); //Align to 0x20 bytes. FileWriter.Align(bw, 0x20); //Write each file and align. for (int i = 0; i < SoundFiles.Count; i++) { //Null. if (SoundFiles[i] == null) { FileWriter.CloseSizedNullReference(bw, "FileRef" + i); } //Not null. else { //If the file is embedded. if (SoundFiles[i].Embed) { //Keep track of position. long pos = bw.Position; //Write file. FileWriter.WriteFile(bw, SoundFiles[i].File, 0x20, writeMode); //Close reference. FileWriter.CloseSizedReference(bw, ReferenceTypes.General, (uint)(bw.Position - pos), "FileRef" + i); } //Don't write data. else { FileWriter.CloseSizedNullReference(bw, "FileRef" + i); } } } //Close file block. FileWriter.CloseBlock(bw); //Extra info exists if the version is greater than one. if (Version > new FileWriter.Version(1, 0, 0)) { //Extra info block. FileWriter.InitBlock(bw, ReferenceTypes.GRP_Block_Infx, "INFX"); //Ex table. FileWriter.InitReferenceTable(bw, ExtraInfo.Count, "Ex"); //Write each info entry. for (int i = 0; i < ExtraInfo.Count; i++) { //Null. if (ExtraInfo[i] == null) { FileWriter.AddReferenceTableNullReference("Ex"); } //Not null. else { //Add reference. FileWriter.AddReferenceTableReference(bw, ReferenceTypes.GRP_Infx_Item, "Ex"); //Write the data. InfoExEntry e = ExtraInfo[i]; UInt32 flags = 0; switch (e.LoadFlags) { case InfoExEntry.ELoadFlags.All: flags = 0xFFFFFFFF; break; case InfoExEntry.ELoadFlags.Bank: flags = 0b100; break; case InfoExEntry.ELoadFlags.BankAndWarc: flags = 0b1100; break; case InfoExEntry.ELoadFlags.Seq: flags = 0b1; break; case InfoExEntry.ELoadFlags.SeqAndBank: flags = 0b101; break; case InfoExEntry.ELoadFlags.SeqAndWarc: flags = 0b1100; break; case InfoExEntry.ELoadFlags.Warc: flags = 0b1000; break; case InfoExEntry.ELoadFlags.Wsd: flags = 0b10; break; } //Get type. byte type = 0; switch (e.ItemType) { case InfoExEntry.EItemType.Bank: type = SoundTypes.Bank; break; case InfoExEntry.EItemType.Sound: type = SoundTypes.Sound; break; case InfoExEntry.EItemType.SequenceSetOrWaveData: type = SoundTypes.SoundGroup; break; case InfoExEntry.EItemType.WaveArchive: type = SoundTypes.WaveArchive; break; } //Item id. Id id = new Id(type, (uint)e.ItemIndex); id.Write(ref bw); //Write flags. bw.Write(flags); } } //Close Ex table. FileWriter.CloseReferenceTable(bw, "Ex"); //Close extra info block. FileWriter.CloseBlock(bw); } //Close file. FileWriter.CloseFile(bw); }