public static void ReadInstrumentSetList() { // traverse the whole audiobank index and grab details about every bank // use those details to generate a list from the vanilla game that we can modify as needed List <InstrumentSetInfo> InstrumentSets = new List <InstrumentSetInfo>(); for (int inst_set_num = 0; inst_set_num <= 0x28; ++inst_set_num) { // each bank has one 16 byte sentence of data, first word is address, second length, last 8 bytes metadata int table_pointer_addr = Addresses.AudiobankTable + (16 * inst_set_num); int bank_location = (ReadWriteUtils.ReadU16(table_pointer_addr) << 16) + ReadWriteUtils.ReadU16(table_pointer_addr + 2); int bank_length = (ReadWriteUtils.ReadU16(table_pointer_addr + 4) << 16) + ReadWriteUtils.ReadU16(table_pointer_addr + 6); byte[] metadata = new byte[8]; for (int b = 0; b < 8; ++b) { metadata[b] = ReadWriteUtils.Read(table_pointer_addr + 8 + b); } byte[] bank_data = new byte[bank_length]; for (int b = 0; b < bank_length; ++b) { bank_data[b] = ReadWriteUtils.Read(Addresses.Audiobank + bank_location + b); } InstrumentSetInfo new_bank = new InstrumentSetInfo { BankSlot = inst_set_num, BankMetaData = metadata, BankBinary = bank_data }; InstrumentSets.Add(new_bank); } RomData.InstrumentSetList = InstrumentSets; }
public static void ReadInstrumentSetList() { /// traverse the whole audiobank index and grab details about every bank /// use those details to generate a list from the vanilla game that we can modify as needed RomData.InstrumentSetList = new List <InstrumentSetInfo>(); for (int audiobankIndex = 0; audiobankIndex <= 0x28; ++audiobankIndex) { // each bank has one 16 byte sentence of data, first word is address, second is length, last 2 words metadata int audiobankIndexAddr = Addresses.AudiobankTable + (audiobankIndex * 0x10); int audiobankBankOffset = (ReadWriteUtils.ReadU16(audiobankIndexAddr) << 16) + ReadWriteUtils.ReadU16(audiobankIndexAddr + 2); int bankLength = (ReadWriteUtils.ReadU16(audiobankIndexAddr + 4) << 16) + ReadWriteUtils.ReadU16(audiobankIndexAddr + 6); byte[] bankMetadata = new byte[8]; for (int b = 0; b < 8; ++b) { bankMetadata[b] = ReadWriteUtils.Read(audiobankIndexAddr + 8 + b); } byte[] bankData = new byte[bankLength]; for (int b = 0; b < bankLength; ++b) { bankData[b] = ReadWriteUtils.Read(Addresses.Audiobank + audiobankBankOffset + b); } var newInstrumentSet = new InstrumentSetInfo { BankSlot = audiobankIndex, BankMetaData = bankMetadata, BankBinary = bankData }; RomData.InstrumentSetList.Add(newInstrumentSet); } }
public static void RebuildAudioBank(List <InstrumentSetInfo> InstrumentSetList) { // get index for the old audiobank, we're putting it back int the same spot but letting it expand into audioseq's spot, because the later is no longer there int f = RomUtils.GetFileIndexForWriting(Addresses.AudiobankTable); // the DMA table doesn't point directly to the table on the rom, its part of a larger yaz0 file, we have to use an offset to get the address in the file int audiobank_table_adjusted_addr = Addresses.AudiobankTable - RomData.MMFileList[RomUtils.GetFileIndexForWriting(Addresses.AudiobankTable)].Addr; int current_audiobank_addr = 0; byte[] new_audiobank = new byte[0]; // for each bank, concat onto the new bank byte object, update the table to match the new instrument sets for (int inst_set_num = 0; inst_set_num <= 0x28; ++inst_set_num) { InstrumentSetInfo current_bank = InstrumentSetList[inst_set_num]; // not sure lists are sequential in C# int bank_len = current_bank.BankBinary.Length; new_audiobank = new_audiobank.Concat(current_bank.BankBinary).ToArray(); // update address of the bank in the table RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16] = (byte)((current_audiobank_addr & 0xFF000000) >> 24); RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 1] = (byte)((current_audiobank_addr & 0xFF0000) >> 16); RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 2] = (byte)((current_audiobank_addr & 0xFF00) >> 8); RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 3] = (byte)(current_audiobank_addr & 0xFF); // adjust the address for the next sequence to use current_audiobank_addr += bank_len; int remainder = bank_len % 16; if (remainder > 0) // in the event the user made an audiobank instrument set that isn't padded { new_audiobank = new_audiobank.Concat(new byte[remainder + 0x10]).ToArray(); // padding with a spare 16 byte line sounds cheap enough to try Debug.WriteLine("Bank " + inst_set_num + " wasn't padded to 16 bytes:" + bank_len.ToString("X")); current_audiobank_addr += remainder; } // update length of the bank in the table RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 4] = (byte)((bank_len & 0xFF000000) >> 24); RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 5] = (byte)((bank_len & 0xFF0000) >> 16); RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 6] = (byte)((bank_len & 0xFF00) >> 8); RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 7] = (byte)(bank_len & 0xFF); // update metadata of the bank in the table for (int meta_iter = 0; meta_iter < 8; ++meta_iter) { RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + (inst_set_num * 16) + 8 + meta_iter] = current_bank.BankMetaData[meta_iter]; } } // write audioseq as a new file f = RomUtils.GetFileIndexForWriting(Addresses.Audiobank); RomData.MMFileList[f].Data = new_audiobank; }
public static void ScanZSEQUENCE(string directory) // TODO make this folder identifiable, add directory and list of banks from scanned directory to this { // check if files were added by user to directory // we're not going to check for non-zseq here until I find an easy way to do that // Just going to trust users aren't stupid enough to think renaming a mp3 to zseq will work // format: FILENAME_InstrumentSet_Categories-separated-by-commas.zseq // where the filename, instrumentset, and categories are separated by single underscore foreach (String filePath in Directory.GetFiles(directory, "*.zseq")) { String filename = Path.GetFileName(filePath); // test if file has enough delimiters to separate data into name_bank_formats String[] pieces = filename.Split('_'); if (pieces.Length != 3) { continue; } byte[] input_seq_data = null; using (BinaryReader bank_reader = new BinaryReader(File.Open(Path.Combine(directory, filename), FileMode.Open))) { input_seq_data = new byte[((int)bank_reader.BaseStream.Length)]; bank_reader.Read(input_seq_data, 0, (int)bank_reader.BaseStream.Length); } SequenceBinaryData sequence_data = null; InstrumentSetInfo instrumnet_info = null; if (pieces[1].Contains("x")) //temporary, we can remove this now that we have MMRS, but maybe don't remove just yet { // load the custom bank for this file byte[] input_bank_data = null; String bank_name = filename.Substring(0, filename.LastIndexOf(".zseq")) + ".zbank"; using (BinaryReader bank_reader = new BinaryReader(File.Open(Path.Combine(directory, bank_name), FileMode.Open))) { input_bank_data = new byte[((int)bank_reader.BaseStream.Length)]; bank_reader.Read(input_bank_data, 0, (int)bank_reader.BaseStream.Length); } byte[] meta_data = new byte[8]; using (BinaryReader meta_reader = new BinaryReader(File.Open(Path.Combine(directory, bank_name.Substring(0, bank_name.LastIndexOf(".zbank")) + ".bankmeta"), FileMode.Open))) meta_reader.Read(meta_data, 0, meta_data.Length); pieces[1] = pieces[1].Replace("x", ""); instrumnet_info = new InstrumentSetInfo() { BankBinary = input_bank_data, BankMetaData = meta_data, BankSlot = Convert.ToInt32(pieces[1], 16), Modified = true }; } sequence_data = new SequenceBinaryData { SequenceBinary = input_seq_data, InstrumentSet = instrumnet_info }; var sourceName = filename; var sourceTypeString = pieces[2].Substring(0, pieces[2].Length - 5); var sourceInstrument = Convert.ToInt32(pieces[1], 16); //var sourceType = Array.ConvertAll(sourceTypeString.Split('-'), int.Parse).ToList(); List <int> sourceType = new List <int>(); foreach (String part in sourceTypeString.Split('-')) { sourceType.Add(Convert.ToInt32(part, 16)); } SequenceInfo sourceSequence = new SequenceInfo { Name = sourceName, Type = sourceType, Instrument = sourceInstrument, SequenceBinaryList = new List <SequenceBinaryData>() { sequence_data } }; RomData.SequenceList.Add(sourceSequence); } }