internal static int CalculateSize(RSAREntryList entries) { //Header int len = 0x40; //SYMB, INFO, FILE Headers int symbLen = 0x20, infoLen = 0, fileLen = 0; //Calculate SYMB //String offsets symbLen += entries._strings.Count * 4; //Strings are packed tightly with no trailing pad symbLen += entries._stringLength; //Mask entries symbLen += 32; //Headers symbLen += (entries._count * 2 - 4) * 20; //Entries //Align symbLen = symbLen.Align(0x20); //Calculate INFO //Calculate FILE return(len + symbLen); }
internal int EncodeSYMBBlock(SYMBHeader *header, RSAREntryList entries, RSARNode node) { int len = 0; int count = entries._strings.Count; VoidPtr baseAddr = (VoidPtr)header + 8, dataAddr; bint * strEntry = (bint *)(baseAddr + 0x18); PString pStr = (byte *)strEntry + (count << 2); //Strings header->_stringOffset = 0x14; strEntry[-1] = entries._strings.Count; foreach (string s in entries._strings) { *strEntry++ = (int)(pStr - baseAddr); pStr.Write(s, 0, s.Length + 1); pStr += s.Length + 1; } dataAddr = pStr; //Sounds header->_maskOffset1 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup(header, (SYMBMaskHeader *)dataAddr, entries._sounds, node, 0); //Player Info header->_maskOffset2 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup(header, (SYMBMaskHeader *)dataAddr, entries._playerInfo, node, 1); //Groups header->_maskOffset3 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup(header, (SYMBMaskHeader *)dataAddr, entries._groups, node, 2); //Banks header->_maskOffset4 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup(header, (SYMBMaskHeader *)dataAddr, entries._banks, node, 3); int temp = (int)dataAddr - (int)header; len = temp.Align(0x20); //Fill padding byte *p = (byte *)dataAddr; for (int i = temp; i < len; i++) { *p++ = 0; } //Set header header->_header._tag = SYMBHeader.Tag; header->_header._length = len; return(len); }
internal int EncodeFILEBlock(FILEHeader *header, VoidPtr baseAddress, RSAREntryList entries, RSARNode node) { int len = 0; VoidPtr baseAddr = (VoidPtr)header + 0x20; VoidPtr addr = baseAddr; //Build files - order by groups foreach (RSARGroupNode g in entries._groups) { int headerLen = 0, audioLen = 0, i = 0; INFOGroupEntry *e = (INFOGroupEntry *)((VoidPtr)g._headerAddr + INFOGroupHeader.Size + 4 + g._files.Count * 8); g._headerAddr->_headerOffset = addr - baseAddress; foreach (RSARFileNode f in g._files) { e[i]._headerLength = f._headerLen; e[i]._headerOffset = headerLen; headerLen += f._headerLen; ++i; } i = 0; VoidPtr wave = addr + headerLen; g._headerAddr->_waveDataOffset = wave - baseAddress; foreach (RSARFileNode f in g._files) { f._rebuildAudioAddr = wave + audioLen; f.Rebuild(addr, f._headerLen, true); e[i]._dataOffset = f._audioLen == 0 ? 0 : audioLen; e[i]._dataLength = f._audioLen; addr += f._headerLen; audioLen += f._audioLen; ++i; } addr += audioLen; g._headerAddr->_headerLength = headerLen; g._headerAddr->_waveDataLength = audioLen; } len = ((int)addr - (int)(VoidPtr)header).Align(0x20); //Set header header->_header._tag = FILEHeader.Tag; header->_header._length = len; return(len); }
internal static int EncodeSYMBBlock(SYMBHeader *header, RSAREntryList entries) { int count = entries._count; VoidPtr baseAddr = (VoidPtr)header + 8, dataAddr; int len; bint * strEntry = (bint *)(baseAddr + 0x18); PString pStr = (byte *)strEntry + (count << 2); //Strings header->_stringOffset = 0x14; strEntry[-1] = entries._strings.Count; foreach (string s in entries._strings) { *strEntry++ = (int)(pStr - baseAddr); pStr.Write(s, 0, s.Length + 1); pStr += s.Length + 1; } dataAddr = pStr; //Sounds header->_maskOffset1 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup((SYMBMaskHeader *)dataAddr, entries._sounds); //Types header->_maskOffset2 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup((SYMBMaskHeader *)dataAddr, entries._types); //Groups header->_maskOffset3 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup((SYMBMaskHeader *)dataAddr, entries._groups); //Banks header->_maskOffset4 = (int)(dataAddr - baseAddr); dataAddr += EncodeMaskGroup((SYMBMaskHeader *)dataAddr, entries._banks); len = ((int)baseAddr).Align(0x20); //Fill padding byte *p = (byte *)dataAddr; for (int i = dataAddr - header; i < len; i++) { *p++ = 0; } //Set header header->_tag = SYMBHeader.Tag; header->_length = len; return(len); }
internal int EncodeFILEBlock(FILEHeader *header, RSAREntryList entries, RSARNode node) { int len = 0; VoidPtr baseAddr = (VoidPtr)header + 0x20; VoidPtr addr = baseAddr; //Build files - order by groups for (int x = 0; x <= entries._groups.Count; x++) { RSARGroupNode g = x == entries._groups.Count ? node._nullGroup : ((RSAREntryState)entries._groups[x])._node as RSARGroupNode; int headerLen = 0, audioLen = 0; int i = 0; INFOGroupEntry *e = (INFOGroupEntry *)((VoidPtr)g._rebuildAddr + INFOGroupHeader.Size + 4 + g._files.Count * 8); g._rebuildAddr->_headerOffset = (int)(addr - node._rebuildBase); foreach (RSARFileNode f in g.Files) { e[i]._headerLength = f._headerLen; e[i++]._headerOffset = headerLen; headerLen += f._headerLen; } i = 0; VoidPtr wave = addr + headerLen; g._rebuildAddr->_waveDataOffset = (int)(wave - node._rebuildBase); foreach (RSARFileNode f in g.Files) { f._rebuildAudioAddr = wave + audioLen; f.Rebuild(addr, f._headerLen, true); addr += f._headerLen; e[i]._dataLength = f._audioLen; e[i++]._dataOffset = f._audioLen == 0 ? 0 : audioLen; audioLen += f._audioLen; } addr += audioLen; g._rebuildAddr->_headerLength = headerLen; g._rebuildAddr->_waveDataLength = audioLen; } len = ((int)addr - (int)(VoidPtr)header).Align(0x20); //Set header header->_header._tag = FILEHeader.Tag; header->_header._length = len; return(len); }
internal static int CalculateSize(RSAREntryList entries) { int len = 0x40; //SYMB int symbLen = 0x20; //Header //String offsets symbLen += entries._strings.Count * 4; //Strings are packed tightly with no trailing pad symbLen += entries._stringLength; //Mask entries symbLen += 32; //Headers symbLen += (entries._count * 2 - 4) * 20; //Entries //Align symbLen = symbLen.Align(0x20); return(len + symbLen); }
internal int EncodeINFOBlock(INFOHeader *header, RSAREntryList entries, RSARNode node) { int len = 0; VoidPtr baseAddr = header->_collection.Address; ruint * values = (ruint *)baseAddr; VoidPtr dataAddr = baseAddr + 0x30; RuintList *entryList; int index = 0; //Set up sound ruint list values[0] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList *)dataAddr; entryList->_numEntries = entries._sounds.Count; dataAddr += entries._sounds.Count * 8 + 4; //Write sound entries foreach (RSAREntryNode r in entries._sounds) { r._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r.Rebuild(dataAddr, r._calcSize, true); dataAddr += r._calcSize; } index = 0; //Set up bank ruint list values[1] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList *)dataAddr; entryList->_numEntries = entries._banks.Count; dataAddr += entries._banks.Count * 8 + 4; //Write bank entries foreach (RSAREntryNode r in entries._banks) { r._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r.Rebuild(dataAddr, r._calcSize, true); dataAddr += r._calcSize; } index = 0; //Set up playerInfo ruint list values[2] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList *)dataAddr; entryList->_numEntries = entries._playerInfo.Count; dataAddr += entries._playerInfo.Count * 8 + 4; //Write playerInfo entries foreach (RSAREntryNode r in entries._playerInfo) { r._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r.Rebuild(dataAddr, r._calcSize, true); dataAddr += r._calcSize; } index = 0; //Set up file ruint list values[3] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList *)dataAddr; entryList->_numEntries = entries._files.Count; dataAddr += entries._files.Count * 8 + 4; //Write file entries foreach (RSARFileNode file in entries._files) { //if (file._groupRefs.Count == 0 && !(file is RSARExtFileNode)) // continue; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; INFOFileHeader *fileHdr = (INFOFileHeader *)dataAddr; dataAddr += INFOFileHeader.Size; RuintList *list = (RuintList *)dataAddr; fileHdr->_entryNumber = -1; if (file is RSARExtFileNode) { uint extFileSize = 0; //Make an attempt to get current file size if (file.ExternalFileInfo.Exists) { extFileSize = (uint)file.ExternalFileInfo.Length; } if (file._extFileSize != extFileSize && extFileSize != 0) { file._extFileSize = extFileSize; } //Shouldn't matter if 0 fileHdr->_headerLen = file._extFileSize; fileHdr->_dataLen = 0; fileHdr->_stringOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr); sbyte *dPtr = (sbyte *)list; file._extPath.Write(ref dPtr); dataAddr += ((int)((VoidPtr)dPtr - (VoidPtr)dataAddr)).Align(4); fileHdr->_listOffset = (uint)((VoidPtr)dataAddr - (VoidPtr)baseAddr); dataAddr += 4; //Empty list } else { fileHdr->_headerLen = (uint)file._headerLen; fileHdr->_dataLen = (uint)file._audioLen; //fileHdr->_stringOffset = 0; fileHdr->_listOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr); list->_numEntries = file._groupRefs.Count; INFOFileEntry *fileEntries = (INFOFileEntry *)((VoidPtr)list + 4 + file._groupRefs.Count * 8); int z = 0; List <int> used = new List <int>(); foreach (RSARGroupNode g in file._groupRefs) { list->Entries[z] = (uint)((VoidPtr)(&fileEntries[z]) - baseAddr); fileEntries[z]._groupId = g._rebuildIndex; int[] all = g._files.FindAllOccurences(file); bool done = false; foreach (int i in all) { if (!used.Contains(i)) { fileEntries[z]._index = i; used.Add(i); done = true; break; } } if (!done) { fileEntries[z]._index = g._files.IndexOf(file); } z++; } dataAddr = (VoidPtr)fileEntries + file._groupRefs.Count * INFOFileEntry.Size; } } index = 0; //Set up group ruint list values[4] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList *)dataAddr; entryList->_numEntries = entries._groups.Count; dataAddr += entries._groups.Count * 8 + 4; //Write group entries foreach (RSAREntryNode r in entries._groups) { r._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r.Rebuild(dataAddr, r._calcSize, true); dataAddr += r._calcSize; } //Write footer values[5] = (uint)dataAddr - (uint)baseAddr; *(INFOFooter *)dataAddr = node._ftr; //Set header header->_header._tag = INFOHeader.Tag; header->_header._length = len = ((int)((dataAddr + INFOFooter.Size) - (baseAddr - 8))).Align(0x20); return(len); }
internal int CalculateSize(RSAREntryList entries, RSARNode node) { //Header _headerLen = 0x40; //SYMB, INFO, FILE Headers _symbLen = 0x20; _infoLen = 0x8; _fileLen = 0x20; #region SYMB //String offsets _symbLen += entries._strings.Count * 4; //Strings are packed tightly with no trailing pad _symbLen += entries._stringLength; //Mask entries _symbLen += 32; //Headers _symbLen += (entries._strings.Count * 2 - 4) * 20; //Entries //Align _symbLen = _symbLen.Align(0x20); #endregion #region Info //Info ruint collection and ruint list counts _infoLen += 0x30; int sounds = 4, playerInfo = 4, banks = 4, groups = 4, files = 4; //ruint sizes sounds += entries._sounds.Count * 8; playerInfo += entries._playerInfo.Count * 8; groups += entries._groups.Count * 8; banks += entries._banks.Count * 8 + 8; files += entries._files.Count * 8; //Evaluate entries with child offsets foreach (RSAREntryNode s in entries._sounds) { sounds += s.CalculateSize(true); } foreach (RSAREntryNode s in entries._playerInfo) { playerInfo += s.CalculateSize(true); } foreach (RSAREntryNode s in entries._banks) { banks += s.CalculateSize(true); } foreach (RSAREntryNode s in entries._groups) { groups += s.CalculateSize(true); } foreach (RSARFileNode s in entries._files) { if (s._groupRefs.Count == 0 && !(s is RSARExtFileNode)) { Console.WriteLine(s.Name); } files += INFOFileHeader.Size + 4 + (!(s is RSARExtFileNode) ? (s._groupRefs.Count * (8 + INFOFileEntry.Size)) : (s._extPath.Length + 1).Align(4)); } //Footer and Align _infoLen = ((_infoLen += (sounds + banks + playerInfo + files + groups)) + 0x10).Align(0x20); #endregion #region File foreach (RSARGroupNode g in entries._groups) { foreach (RSARFileNode f in g._files) { _fileLen += f.CalculateSize(true); } } //Align _fileLen = _fileLen.Align(0x20); #endregion return(_headerLen + _symbLen + _infoLen + _fileLen); }
internal static int EncodeINFOBlock(INFOHeader *header, RSAREntryList entries) { return(0); }
internal static int EncodeFILEBlock(FILEHeader *header, RSAREntryList entries) { return(0); }
internal int EncodeINFOBlock(INFOHeader* header, RSAREntryList entries, RSARNode node) { int len = 0; VoidPtr baseAddr = header->_collection.Address; ruint* values = (ruint*)baseAddr; VoidPtr dataAddr = baseAddr + 0x30; RuintList* entryList; int index = 0; //Set up sound ruint list values[0] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList*)dataAddr; entryList->_numEntries = entries._sounds.Count; dataAddr += entries._sounds.Count * 8 + 4; //Write sound entries foreach (RSAREntryState r in entries._sounds) { r._node._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r._node.Rebuild(dataAddr, r._node._calcSize, true); dataAddr += r._node._calcSize; } index = 0; //Set up bank ruint list values[1] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList*)dataAddr; entryList->_numEntries = entries._banks.Count; dataAddr += entries._banks.Count * 8 + 4; //Write bank entries foreach (RSAREntryState r in entries._banks) { r._node._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r._node.Rebuild(dataAddr, r._node._calcSize, true); dataAddr += r._node._calcSize; } index = 0; //Set up playerInfo ruint list values[2] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList*)dataAddr; entryList->_numEntries = entries._playerInfo.Count; dataAddr += entries._playerInfo.Count * 8 + 4; //Write playerInfo entries foreach (RSAREntryState r in entries._playerInfo) { r._node._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r._node.Rebuild(dataAddr, r._node._calcSize, true); dataAddr += r._node._calcSize; } index = 0; //Set up file ruint list values[3] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList*)dataAddr; entryList->_numEntries = entries._files.Count; dataAddr += entries._files.Count * 8 + 4; //Write file entries foreach (RSARFileNode file in entries._files) { entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; INFOFileHeader* fileHdr = (INFOFileHeader*)dataAddr; dataAddr += INFOFileHeader.Size; RuintList* list = (RuintList*)dataAddr; fileHdr->_entryNumber = -1; if (file is RSARExtFileNode) { //Make an attempt to get current file size uint s = 0; if (file.ExternalFileInfo.Exists) s = (uint)file.ExternalFileInfo.Length; if (file._extFileSize != s && s != 0) file._extFileSize = s; //Shouldn't matter if 0 fileHdr->_headerLen = file._extFileSize; fileHdr->_dataLen = 0; fileHdr->_stringOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr); sbyte* dPtr = (sbyte*)list; file._extPath.Write(ref dPtr); dataAddr += ((int)((VoidPtr)dPtr - (VoidPtr)dataAddr)).Align(4); fileHdr->_listOffset = (uint)((VoidPtr)dataAddr - (VoidPtr)baseAddr); dataAddr += 4; //Empty list } else { fileHdr->_headerLen = (uint)file._headerLen; fileHdr->_dataLen = (uint)file._audioLen; //fileHdr->_stringOffset = 0; fileHdr->_listOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr); list->_numEntries = file._groups.Count; INFOFileEntry* fileEntries = (INFOFileEntry*)((VoidPtr)list + 4 + file._groups.Count * 8); int z = 0; List<int> used = new List<int>(); foreach (RSARGroupNode g in file._groups) { list->Entries[z] = (uint)((VoidPtr)(&fileEntries[z]) - baseAddr); fileEntries[z]._groupId = g._rebuildIndex; int[] all = g._files.FindAllOccurences(file); bool done = false; foreach (int i in all) if (!used.Contains(i)) { fileEntries[z]._index = i; used.Add(i); done = true; break; } if (!done) fileEntries[z]._index = g._files.IndexOf(file); z++; } dataAddr = (VoidPtr)fileEntries + file._groups.Count * INFOFileEntry.Size; } } index = 0; //Set up group ruint list values[4] = (uint)dataAddr - (uint)baseAddr; entryList = (RuintList*)dataAddr; entryList->_numEntries = entries._groups.Count + 1; dataAddr += (entries._groups.Count + 1) * 8 + 4; //Write group entries foreach (RSAREntryState r in entries._groups) { r._node._rebuildBase = baseAddr; entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr; r._node.Rebuild(dataAddr, r._node._calcSize, true); dataAddr += r._node._calcSize; } //Null group at the end entryList->Entries[entries._groups.Count] = (uint)dataAddr - (uint)baseAddr; INFOGroupHeader* grp = (INFOGroupHeader*)dataAddr; node._nullGroup._rebuildAddr = grp; node._nullGroup._rebuildBase = baseAddr; *(bint*)(dataAddr + INFOGroupHeader.Size) = 0; grp->_entryNum = -1; grp->_stringId = -1; //grp->_extFilePathRef = 0; //grp->_extFilePathRef._dataType = 0; grp->_headerLength = 0; grp->_waveDataLength = 0; grp->_headerOffset = grp->_waveDataOffset = _headerLen + _symbLen + _infoLen + _fileLen; grp->_listOffset = (uint)((VoidPtr)(dataAddr + INFOGroupHeader.Size) - baseAddr); dataAddr += INFOGroupHeader.Size; RuintList* l = (RuintList*)dataAddr; INFOGroupEntry* e = (INFOGroupEntry*)((VoidPtr)l + 4 + node._nullGroup.Files.Count * 8); l->_numEntries = node._nullGroup.Files.Count; int y = 0; foreach (RSARFileNode file in node._nullGroup.Files) { l->Entries[y] = (uint)((VoidPtr)(&e[y]) - baseAddr); e[y++]._fileId = file._fileIndex; //entries[i]._dataLength = 0; //entries[i]._dataOffset = 0; //entries[i]._headerLength = 0; //entries[i]._headerOffset = 0; } dataAddr = (VoidPtr)e + node._nullGroup.Files.Count * 0x18; //Write footer values[5] = (uint)dataAddr - (uint)baseAddr; *(INFOFooter*)dataAddr = node.ftr; //Set header header->_header._tag = INFOHeader.Tag; header->_header._length = len = ((int)((dataAddr + INFOFooter.Size) - (baseAddr - 8))).Align(0x20); return len; }
internal int CalculateSize(RSAREntryList entries, RSARNode node) { //Header _headerLen = 0x40; //SYMB, INFO, FILE Headers _symbLen = 0x20; _infoLen = 0x8; _fileLen = 0x20; #region SYMB //String offsets _symbLen += entries._strings.Count * 4; //Strings are packed tightly with no trailing pad _symbLen += entries._stringLength; //Mask entries _symbLen += 32; //Headers _symbLen += (entries._strings.Count * 2 - 4) * 20; //Entries //Align _symbLen = _symbLen.Align(0x20); #endregion #region Info //Info ruint collection and ruint list counts _infoLen += 0x30; int sounds = 4, playerInfo = 4, banks = 4, groups = 4, files = 4; //ruint sizes sounds += entries._sounds.Count * 8; playerInfo += entries._playerInfo.Count * 8; groups += entries._groups.Count * 8; banks += entries._banks.Count * 8 + 8; files += entries._files.Count * 8; //Evaluate entries with child offsets foreach (RSAREntryState s in entries._sounds) sounds += s._node.CalculateSize(true); foreach (RSAREntryState s in entries._playerInfo) playerInfo += s._node.CalculateSize(true); foreach (RSAREntryState s in entries._banks) banks += s._node.CalculateSize(true); foreach (RSAREntryState s in entries._groups) groups += s._node.CalculateSize(true); groups += INFOGroupHeader.Size + 4; //Null group at the end groups += node._nullGroup.Files.Count * 32; foreach (RSARFileNode s in entries._files) { files += INFOFileHeader.Size + 4; if (!(s is RSARExtFileNode)) files += s._groups.Count * (8 + INFOFileEntry.Size); else files += (s._extPath.Length + 1).Align(4); } //Footer and Align _infoLen = ((_infoLen += (sounds + banks + playerInfo + files + groups)) + 0x10).Align(0x20); #endregion #region File foreach (RSAREntryState r in entries._groups) { RSARGroupNode g = r._node as RSARGroupNode; foreach (RSARFileNode f in g.Files) _fileLen += f.CalculateSize(true); } foreach (RSARFileNode f in node._nullGroup.Files) _fileLen += f.CalculateSize(true); //Align _fileLen = _fileLen.Align(0x20); #endregion return _headerLen + _symbLen + _infoLen + _fileLen; }