public byte[] vocaloid; // uncompressed // From known item and packpath public BBPRecord(JbMgrFormat.JbMgrItem item, string path, int slot) { Slot = slot; FullPath = path; mgrItem = item; if (item.Flags.OnSD) { var buffer = File.ReadAllBytes(path); var bytes = buffer; var nums = Enumerable.Range(0, 17).Select(i => BitConverter.ToInt32(bytes, i * 4)).ToList(); var unc1 = Decompress(bytes, nums[3], nums[4]); bbp = unc1.ToStruct<BBPFormat>(); if (nums[5] == 1) vocaloid = Decompress(bytes, nums[7], nums[8]); } else { bbp = new BBPFormat { title = item.Title.StringToArray(250), channelInfo = new BBPFormat.ChannelInfo[0] }; } }
public JbManager(string path) { FilePath = path; if (new FileInfo(path).Length != binSize) { throw new InvalidDataException($"{path} has an incorrect filesize!"); } using (var ms = new MemoryStream()) { using (var gz = new GZipStream(File.OpenRead(path), CompressionMode.Decompress)) { gz.CopyTo(ms); } // Convert file contents into our struct if (ms.Length != Marshal.SizeOf<JbMgrFormat>()) { throw new InvalidDataException($"{path} has an incorrect buffer length!"); } mgr = ms.ToArray().ToStruct<JbMgrFormat>(); } }
public static void Convert(string path, out JbMgrFormat.JbMgrItem mgrItem, out BBPFormat bbp, out byte[] vocaloid) { mgrItem = JbMgrFormat.JbMgrItem.Empty; vocaloid = null; using (var br = new BinReader(path)) { // Obtain ID2 and go look for all records in memory br.Goto(0xC16C68); mgrItem.OtherID = br.ReadUInt32(); br.Goto(0xC16E90); br.Goto(br.ReadUInt32() + 4); br.Goto(br.ReadUInt32()); br.Goto(br.ReadUInt32() + 56); br.Goto(br.ReadUInt32() + 24); br.Goto(br.ReadUInt32() + 12); // Go through records in memory to find the matching one uint recordCount = br.ReadUInt32(); br.BaseStream.Position += 4; uint recordAddr = br.ReadUInt32(); if (recordCount == 100) { br.BaseStream.Position += 8; recordCount = br.ReadUInt32(); } br.Goto(recordAddr); while (br.ReadUInt32() != mgrItem.OtherID) { if (--recordCount == 0) throw new InvalidDataException($"{path} has incorrect data -- could not find matching record"); br.BaseStream.Position += 48; } // Read mgrItem metadata from memory mgrItem.ID = br.ReadUInt32(); mgrItem.Title = br.ReadStringPointer(); if (mgrItem.Title.Length == 50 && mgrItem.Title[49] == '…') { mgrItem.Title = mgrItem.Title.Substring(0, 49); } mgrItem.TitleSimple = br.ReadStringPointer().Simplify(); br.BaseStream.Position += 8; mgrItem.Author = br.ReadStringPointer(); br.BaseStream.Position += 12; var code = br.ReadStringPointer(); // Finally, obtain pack data br.Goto(0xC16CF4); var packaddr = br.ReadUInt32(); var packsize = br.ReadInt32(); if (packsize >= 16777216) throw new InvalidDataException($"{path} has incorrect header error #5 {mgrItem.Title}:{mgrItem.Author}"); br.Goto(packaddr); var bytes = br.ReadBytes(packsize); if (!gzipHeaderBytes.SequenceEqual(bytes.Take(16))) throw new InvalidDataException($"{path} has incorrect data error #7 {mgrItem.Title}:{mgrItem.Author}"); var nums = Enumerable.Range(0, 17).Select(i => BitConverter.ToInt32(bytes, i * 4)).ToList(); //overwrite bbp's ID and title bbp = Decompress(bytes, nums[3], nums[4]).ToStruct<BBPFormat>(); bbp.titleID = (int)mgrItem.ID; bbp.title = mgrItem.Title.StringToArray(bbp.title.Length); bbp.test0 = 1; bbp.test2 = (byte)(char.IsNumber(code[1]) ? 0 : 1); vocaloid = null; if (nums[5] == 1) vocaloid = Decompress(bytes, nums[7], nums[8]); //File.WriteAllBytes($"{path}.dat", bbp.StructToArray()); //if (vocaloid != null) File.WriteAllBytes($"{path}.voc", vocaloid); // metadata stuff temporarily here var instrTypes = bbp.channelInfo.Select(c => c.playType); var hasPiano = instrTypes.Contains(PlayType.Piano); var hasGuitar = instrTypes.Contains(PlayType.Guitar); var hasDrum = instrTypes.Contains(PlayType.Drum); //mgr.Flags var instrx = bbp.timeSignature == 3; var lyrics = bbp.karaokeTimer[0] != 0x3FFF; var melody = bbp.test3 != -1; var isclassic = bbp.test2 == 1; mgrItem.Flags = new JbMgrFormat.JbMgrItem.JbFlags { HasDrum = hasDrum, HasGuitar = hasGuitar, HasPiano = hasPiano, HasLyrics = lyrics, HasMelody = melody, IsValid = true, OnSD = true, HasVocals = vocaloid != null, IsSingable = vocaloid != null, Parts = bbp.channelInfo.Count(c => c.instrument != 0), IsReceived = true, HasInstrX = instrx, IsClassic = isclassic }; } }
public static BBPFormat Convert(BDXFormat bdx, out JbMgrFormat.JbMgrItem mgr) { var converted = new BDX2BBP(bdx); mgr = converted.mgr; return converted.bbp; }