public override bool OnInitialize() { ModuleSectionNode section = Location; if (section == null || !Header) { return(false); } //Don't make a copy buffer here. //Use the original buffer to save memory buint * sPtr = (buint *)Header; VoidPtr ceil = section.Header + section._dataSize; while (!(PowerPC.Disassemble(*sPtr++) is PPCblr) && (int)sPtr < (int)ceil) { ; } _codeStart = (int)Header - (int)section.Header; _codeLen = (int)sPtr - (int)Header; _manager = new RelocationManager(null); _manager.UseReference(section, _codeStart); if (_codeLen > 0) { _manager.AddTag(0, FullName + " Start"); _manager.AddTag(_codeLen / 4 - 1, FullName + " End"); } return(false); }
public override void OnRebuild(VoidPtr address, int length, bool force) { WAVEHeader *header = (WAVEHeader *)address; header->_tag = WAVEHeader.Tag; header->_numEntries = Children.Count; header->_length = length; buint * table = (buint *)header + 3; VoidPtr addr = table + Children.Count; VoidPtr baseAddr = _audioAddr; foreach (WAVESoundNode r in Children) { table[r.Index] = (uint)(addr - address); r.MoveRawUncompressed(addr, r.WorkingUncompressed.Length); WaveInfo *wave = (WaveInfo *)addr; wave->_dataLocation = (uint)(_audioAddr - baseAddr); Memory.Move(_audioAddr, r._streamBuffer.Address, (uint)r._streamBuffer.Length); _audioAddr += (uint)r._streamBuffer.Length; addr += r.WorkingUncompressed.Length; } }
private AttributeInterpretation GenerateDefaultInterpretation() { AttributeInfo[] arr = new AttributeInfo[NumEntries]; buint * pIn = (buint *)AttributeAddress; int index = 0x10; for (int i = 0; i < arr.Length; i++) { arr[i] = new AttributeInfo() { _name = "0x" + index.ToString("X3") }; //Guess if the value is a an integer or float uint u = (uint)*((buint *)pIn); float f = (float)*((bfloat *)pIn); if (*pIn == 0) { arr[i]._type = 0; arr[i]._description = "Default: 0 (could be int or float - be careful)"; } else if (((u >> 24) & 0xFF) != 0 && *((bint *)pIn) != -1 && !float.IsNaN(f)) { float abs = Math.Abs(f); if (abs > 0.0000001 && abs < 10000000) { arr[i]._type = 0; arr[i]._description = "Default (float): " + f + " (" + u.ToString("X8") + ")"; } else { arr[i]._type = 1; arr[i]._description = "Default (unknown type): " + u + " (" + u.ToString("X8") + ")"; arr[i]._name = "~" + arr[i]._name; } } else { arr[i]._type = 1; arr[i]._description = "Default (int): " + u + " (" + u.ToString("X8") + ")"; arr[i]._name = "*" + arr[i]._name; } index += 4; pIn++; } ResourceNode root = this; while (root.Parent != null) { root = root.Parent; } string filename = "TBLV/" + root.Name.Replace("STG", "") + ".txt"; return(new AttributeInterpretation(arr, filename)); }
public uint GetSize() { buint *offsets = TextOffset; buint *sizes = TextSize; uint maxLen = 0; for (int i = 0; i < 18; ++i) { maxLen = Math.Max(offsets[i] + sizes[i], maxLen); } return(maxLen + 0x100); }
public unsafe void ExportInitialized(string outPath) { using (FileStream stream = new FileStream(outPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, 8, FileOptions.RandomAccess)) { stream.SetLength(_dataBuffer.Length); using (FileMap map = FileMap.FromStream(stream)) { buint *addr = (buint *)map.Address; foreach (Relocation loc in Relocations) { *addr++ = loc.SectionOffset; } } } }
public override void OnRebuild(VoidPtr address, int length, bool force) { buint *addr = (buint *)address; ((bushort *)addr)[0] = ptcl; ((bushort *)addr)[1] = _ptclInitTrackCount; addr += ptcl + 1; foreach (REFFAnimationNode e in Children) { if (e._isPtcl) { *addr++ = (uint)e._calcSize; } } ((bushort *)addr)[0] = emit; ((bushort *)addr)[1] = _emitInitTrackCount; addr += emit + 1; foreach (REFFAnimationNode e in Children) { if (!e._isPtcl) { *addr++ = (uint)e._calcSize; } } VoidPtr ptr = addr; foreach (REFFAnimationNode e in Children) { if (e._isPtcl) { e.Rebuild(ptr, e._calcSize, true); ptr += e._calcSize; } } foreach (REFFAnimationNode e in Children) { if (!e._isPtcl) { e.Rebuild(ptr, e._calcSize, true); ptr += e._calcSize; } } }
public override bool OnInitialize() { ModuleSectionNode section = Location; if ((TargetSection == 1 || TargetModule.Equals("main.dol")) && ModuleMapLoader.MapFiles.ContainsKey(TargetModule)) { if (ModuleMapLoader.MapFiles[TargetModule].ContainsKey(TargetOffset)) { _name = ModuleMapLoader.MapFiles[TargetModule][TargetOffset]; } } if (section == null || !Header) { return(false); } //Don't make a copy buffer here. //Use the original buffer to save memory buint * sPtr = (buint *)Header; VoidPtr ceil = section.Header + section._dataSize; while (!(PowerPC.Disassemble(*sPtr++) is PPCblr) && (int)sPtr < (int)ceil) { ; } _codeStart = (int)Header - (int)section.Header; _codeLen = (int)sPtr - (int)Header; _manager = new RelocationManager(null); _manager.UseReference(section, _codeStart); if (_codeLen > 0) { _manager.AddTag(0, FullName + " Start"); _manager.AddTag(_codeLen / 4 - 1, FullName + " End"); } return(false); }
public override void OnPopulate() { int offset = 0; buint *addr = _ptclTrackAddr; addr += PtclTrackCount; //skip nulled pointers to size list for (int i = 0; i < PtclTrackCount; i++) { new REFFAnimationNode() { _isPtcl = true }.Initialize(this, First + offset, (int)*addr); offset += (int)*addr++; } addr = _emitTrackAddr; addr += EmitTrackCount; //skip nulled pointers to size list for (int i = 0; i < EmitTrackCount; i++) { new REFFAnimationNode().Initialize(this, First + offset, (int)*addr); offset += (int)*addr++; } }
public override void OnPopulate() { //Enumerate entries, attaching them to the files. RSARHeader *rsar = Header; SYMBHeader *symb = rsar->SYMBBlock; sbyte * offset = (sbyte *)symb + 8; buint * stringOffsets = symb->StringOffsets; VoidPtr baseAddr = (VoidPtr)rsar->INFOBlock + 8; ruint * typeList = (ruint *)baseAddr; //Iterate through group types for (int i = 0; i < 5; i++) { _infoCache[i] = new List <RSAREntryNode>(); Type t = null; RuintList *list = (RuintList *)((uint)baseAddr + typeList[i]); sbyte * str, end; switch (i) { case 0: t = typeof(RSARSoundNode); break; case 1: t = typeof(RSARBankNode); break; case 2: t = typeof(RSARPlayerInfoNode); break; case 3: continue; //Files case 4: t = typeof(RSARGroupNode); break; //Last group entry is null } for (int x = 0; x < list->_numEntries; x++) { VoidPtr addr = list->Get(baseAddr, x); ResourceNode parent = this; RSAREntryNode n = Activator.CreateInstance(t) as RSAREntryNode; n._origSource = n._uncompSource = new DataSource(addr, 0); n._infoIndex = x; if (i == 4 && x == list->_numEntries - 1) { n._name = "<null>"; n._parent = this; _nullGroup = n as RSARGroupNode; } else { str = offset + stringOffsets[n.StringId]; for (end = str; *end != 0; end++) { ; } while ((--end > str) && (*end != '_')) { ; } if (end > str) { parent = CreatePath(parent, str, (int)end - (int)str); n._name = new String(end + 1); } else { n._name = new String(str); } } n.Initialize(parent, addr, 0); _infoCache[i].Add(n); } } ftr = *(INFOFooter *)((uint)baseAddr + typeList[5]); foreach (RSARFileNode n in Files) { if (!(n is RSARExtFileNode)) { n.GetName(); } } _rootIds = new int[4]; _symbCache = new List <SYMBMaskEntry> [4]; bint *offsets = (bint *)((VoidPtr)symb + 12); for (int i = 0; i < 4; i++) { _symbCache[i] = new List <SYMBMaskEntry>(); SYMBMaskHeader *hdr = (SYMBMaskHeader *)((VoidPtr)symb + 8 + offsets[i]); //Console.WriteLine("Root Index = " + hdr->_rootId); _rootIds[i] = hdr->_rootId; for (int x = 0; x < hdr->_numEntries; x++) { SYMBMaskEntry *e = &hdr->Entries[x]; _symbCache[i].Add(*e); //Console.WriteLine(String.Format("[{5}] {0}, {1}, {2} - {4}", e->_bit != -1 ? e->_bit.ToString().PadLeft(3) : " ", e->_leftId != -1 ? e->_leftId.ToString().PadLeft(3) : " ", e->_rightId != -1 ? e->_rightId.ToString().PadLeft(3) : " ", e->_index != -1 ? e->_index.ToString().PadLeft(3) : " ", new string(offset + stringOffsets[e->_stringId]), x.ToString().PadLeft(3))); } } //Sort(true); }
public static unsafe FileMap Encode(IAudioStream stream, IProgressTracker progress) { int tmp; bool looped = stream.IsLooping; int channels = stream.Channels; int samples; int blocks; int sampleRate = stream.Frequency; int lbSamples, lbSize, lbTotal; int /*loopPadding, */ loopStart, totalSamples; short *tPtr; int blockLen, samplesPerBlock; if (looped) { loopStart = stream.LoopStartSample; samples = stream.LoopEndSample; //Set sample size to end sample. That way the audio gets cut off when encoding. blockLen = (samples.Align(14) / 14 * 8); samplesPerBlock = blockLen / 8 * 14; //If loop point doesn't land on a block, pad the stream so that it does. //if ((tmp = loopStart % samplesPerBlock) != 0) //{ // loopPadding = samplesPerBlock - tmp; // loopStart += loopPadding; //} //else // loopPadding = 0; totalSamples = /*loopPadding + */ samples; } else { //loopPadding = 0; loopStart = 0; totalSamples = samples = stream.Samples; blockLen = (samples.Align(14) / 14 * 8); samplesPerBlock = blockLen / 8 * 14; } if (progress != null) { progress.Begin(0, totalSamples * channels * 3, 0); } blocks = (totalSamples + (samplesPerBlock - 1)) / samplesPerBlock; //Initialize stream info if ((tmp = totalSamples % samplesPerBlock) != 0) { lbSamples = tmp; lbSize = (lbSamples + 13) / 14 * 8; lbTotal = lbSize.Align(0x20); } else { lbSamples = samplesPerBlock; lbTotal = lbSize = blockLen; } //Get section sizes int headerSize = RWAV.Size, infoSize = 8, waveSize = 0x1C, tableSize = channels * 4, channelSize = channels * 0x1C, adpcmInfoSize = channels * 0x30, entrySize = (infoSize + waveSize + tableSize + channelSize + adpcmInfoSize).Align(0x20) - 8, dataSize = (((blocks - 1) * blockLen + lbTotal) * channels) + 8; //Create file map FileMap map = FileMap.FromTempFile(headerSize + entrySize + 8 + dataSize); //Get section pointers RWAV *header = (RWAV *)map.Address; header->_header._tag = RWAV.Tag; header->_header.Endian = Endian.Big; header->_header._version = 0x102; header->_header._length = map.Length; header->_header._firstOffset = 0x20; header->_header._numEntries = 2; header->_infoOffset = 0x20; header->_infoLength = entrySize + 8; header->_dataOffset = 0x20 + entrySize + 8; header->_dataLength = dataSize; RWAVInfo *infoBlock = header->Info; infoBlock->_header._tag = RWAVInfo.Tag; infoBlock->_header._length = entrySize + 8; WaveInfo *wave = &infoBlock->_info; wave->_format = new AudioFormatInfo(2, (byte)(looped ? 1 : 0), (byte)channels, 0); wave->_sampleRate = (ushort)sampleRate; wave->_channelInfoTableOffset = 0x1C; wave->_dataLocation = (uint)(header->Data->Data - map.Address); wave->LoopSample = loopStart; wave->NumSamples = totalSamples; RWAVData *dataBlock = header->Data; dataBlock->_header._tag = RWAVData.Tag; dataBlock->_header._length = dataSize; //Create one ChannelInfo for each channel buint * table = (buint *)((VoidPtr)wave + 0x1C); ChannelInfo *channelInfo = (ChannelInfo *)((VoidPtr)wave + waveSize + tableSize); for (int i = 0; i < channels; i++) { table[i] = (uint)&channelInfo[i] - (uint)wave; channelInfo[i] = new ChannelInfo() { _volBackLeft = 1, _volBackRight = 1, _volFrontLeft = 1, _volFrontRight = 1, _adpcmInfoOffset = waveSize + tableSize + channelSize + i * 0x30 }; } //Create one ADPCMInfo for each channel int * adpcData = stackalloc int[channels]; ADPCMInfo **pAdpcm = (ADPCMInfo **)adpcData; for (int i = 0; i < channels; i++) { *(pAdpcm[i] = wave->GetADPCMInfo(i)) = new ADPCMInfo(); } //Create buffer for each channel int * bufferData = stackalloc int[channels]; short **channelBuffers = (short **)bufferData; int bufferSamples = totalSamples + 2; //Add two samples for initial yn values for (int i = 0; i < channels; i++) { channelBuffers[i] = tPtr = (short *)Marshal.AllocHGlobal(bufferSamples * 2); //Two bytes per sample //Zero padding samples and initial yn values //for (int x = 0; x < (loopPadding + 2); x++) // *tPtr++ = 0; } //Fill buffers stream.SamplePosition = 0; short *sampleBuffer = stackalloc short[channels]; for (int i = 2; i < bufferSamples; i++) { //if (stream.SamplePosition == stream.LoopEndSample && looped) // stream.SamplePosition = stream.LoopStartSample; stream.ReadSamples(sampleBuffer, 1); for (int x = 0; x < channels; x++) { channelBuffers[x][i] = sampleBuffer[x]; } } //Calculate coefs for (int i = 0; i < channels; i++) { AudioConverter.CalcCoefs(channelBuffers[i] + 2, totalSamples, (short *)pAdpcm[i], progress); } //Encode blocks byte *dPtr = (byte *)dataBlock->Data; for (int sIndex = 0, bIndex = 1; sIndex < totalSamples; sIndex += samplesPerBlock, bIndex++) { int blockSamples = Math.Min(totalSamples - sIndex, samplesPerBlock); for (int x = 0; x < channels; x++) { channelInfo[x]._channelDataOffset = (int)(dPtr - (byte *)dataBlock->Data); short *sPtr = channelBuffers[x] + sIndex; //Set block yn values if (bIndex != blocks) { pAdpcm[x]->_yn1 = sPtr[samplesPerBlock + 1]; pAdpcm[x]->_yn2 = sPtr[samplesPerBlock]; } //Encode block (include yn in sPtr) AudioConverter.EncodeBlock(sPtr, blockSamples, dPtr, (short *)pAdpcm[x]); //Set initial ps if (bIndex == 1) { pAdpcm[x]->_ps = *dPtr; } //Advance output pointer if (bIndex == blocks) { //Fill remaining dPtr += lbSize; for (int i = lbSize; i < lbTotal; i++) { *dPtr++ = 0; } } else { dPtr += blockLen; } } if (progress != null && (sIndex % samplesPerBlock) == 0) { progress.Update(progress.CurrentValue + (samplesPerBlock * 2 * channels)); } } //Reverse coefs for (int i = 0; i < channels; i++) { short *p = pAdpcm[i]->_coefs; for (int x = 0; x < 16; x++, p++) { *p = p->Reverse(); } } //Write loop states if (looped) { //Can't we just use block states? int loopBlock = loopStart / samplesPerBlock; int loopChunk = (loopStart - (loopBlock * samplesPerBlock)) / 14; dPtr = (byte *)dataBlock->Data + (loopBlock * blockLen * channels) + (loopChunk * 8); tmp = (loopBlock == blocks - 1) ? lbTotal : blockLen; for (int i = 0; i < channels; i++, dPtr += tmp) { //Use adjusted samples for yn values tPtr = channelBuffers[i] + loopStart; pAdpcm[i]->_lps = *dPtr; pAdpcm[i]->_lyn2 = *tPtr++; pAdpcm[i]->_lyn1 = *tPtr; } } //Free memory for (int i = 0; i < channels; i++) { Marshal.FreeHGlobal((IntPtr)channelBuffers[i]); } if (progress != null) { progress.Finish(); } return(map); }
protected override void OnPopulate() { RSARFolderNode g = new RSARFolderNode(); g.Name = "Info"; g.Parent = this; g = new RSARFolderNode(); g.Name = "Files"; g.Parent = this; //Retrieve all files to attach to entries GetFiles(); //Enumerate entries, attaching them to the files. RSARHeader *rsar = Header; SYMBHeader *symb = rsar->SYMBBlock; sbyte * offset = (sbyte *)symb + 8; buint * stringOffsets = symb->StringOffsets; VoidPtr types = (VoidPtr)rsar->INFOBlock + 8; ruint * typeList = (ruint *)types; //Iterate through group types for (int i = 0; i < 5; i++) { Type t = null; ruint *entryList = (ruint *)((uint)types + typeList[i] + 4); int entryCount = *((bint *)entryList - 1); sbyte *str, end; switch (i) { case 0: t = typeof(RSARSoundNode); break; case 1: t = typeof(RSARBankNode); break; case 2: t = typeof(RSARTypeNode); break; case 3: continue; case 4: t = typeof(RSARGroupNode); break; } for (int x = 0; x < entryCount; x++) { ResourceNode parent = Children[0]; RSAREntryNode n = Activator.CreateInstance(t) as RSAREntryNode; n._origSource = n._uncompSource = new DataSource(types + entryList[x], 0); str = offset + stringOffsets[n.StringId]; for (end = str; *end != 0; end++) { ; } while ((--end > str) && (*end != '_')) { ; } if (end > str) { parent = CreatePath(parent, str, (int)end - (int)str); n._name = new String(end + 1); } else { n._name = new String(str); } n.Initialize(parent, types + entryList[x], 0); //n.Populate(); } } //Sort(true); }
public override void OnRebuild(VoidPtr address, int length, bool force) { ItmFreqHeader *header = (ItmFreqHeader *)address; *header = new ItmFreqHeader(); header->_Length = length; int offCount = 0; // save for later; //header->_OffCount; header->_DataTable = 1; header->_pad0 = 0; header->_pad1 = 0; header->_pad2 = 0; header->_pad3 = 0; List <uint> groupOffsets = new List <uint>(); List <uint> tableOffsets = new List <uint>(); uint offset = ItmFreqHeader.Size; // First, rebuild the items themselves, updating the group offset to the proper value (also reset both sets of offsets) foreach (ItmTableNode table in Children) { table._offset = 0; table._dataSize = 0; if (table.HasChildren) { offCount++; foreach (ItmTableGroupNode group in table.Children) { group._offset = 0; if (group.HasChildren) { offCount++; group._offset = offset - ItmFreqHeader.Size; foreach (ResourceNode item in group.Children) { int size = item.OnCalculateSize(true); item.OnRebuild(address + offset, size, true); offset += (uint)size; table._dataSize += (uint)size; } } } // Rebuild the table's groups table._offset = offset - ItmFreqHeader.Size; foreach (ResourceNode group in table.Children) { int size = group.OnCalculateSize(true); group.OnRebuild(address + offset, size, true); if (group.HasChildren) { groupOffsets.Add(offset - 0x14); } offset += (uint)size; table._dataSize += (uint)size; } } // Add padding to match vBrawl if (table.HasChildren && (table.NextSibling()?.HasChildren ?? true)) { buint *ptr = (buint *)(address + offset); ptr[0] = 0; offset += 4; } } header->_OffCount = offCount; header->_DataLength = length - (ItmFreqHeader.Size + (offCount + 2) * 0x04 + "genParamSet".UTF8Length() + 1); // Finally, rebuild tables foreach (ResourceNode table in Children) { int size = table.OnCalculateSize(true); table.OnRebuild(address + offset, size, true); if (table.HasChildren) { tableOffsets.Add(offset - 0x14 - 0x0C); } offset += (uint)size; } foreach (uint i in groupOffsets) { buint *ptr = (buint *)(address + offset); ptr[0] = i; offset += 4; } foreach (uint i in tableOffsets) { buint *ptr = (buint *)(address + offset); ptr[0] = i; offset += 4; } if (tableOffsets.Count > 0) { buint *ptr = (buint *)(address + offset); ptr[0] = tableOffsets[0]; offset += 4; } buint *clear = (buint *)(address + offset); clear[0] = 0; offset += 4; (address + offset).WriteUTF8String("genParamSet", true); }
public override void OnPopulate() { _sections = new ModuleSectionNode[_numSections]; int prevOffset = RELHeader.Size + RELSectionEntry.Size * (int)_numSections; for (int i = 0; i < _numSections; i++) { RELSectionEntry entry = Header->SectionInfo[i]; ModuleSectionNode section = _sections[i] = new ModuleSectionNode(); int dataOffset = entry.Offset, dataSize = (int)(uint)entry._size; section._isCodeSection = entry.IsCodeSection; section._dataOffset = dataOffset; section._dataSize = entry._size; section.Initialize(this, WorkingUncompressed.Address + dataOffset, dataSize); if (dataOffset > 0) { section._dataAlign = dataOffset - prevOffset; prevOffset = dataOffset + dataSize; } } //Larger modules may take slightly longer to relocate //Use a background worker so the UI thread isn't suspended Action <object, DoWorkEventArgs> work = (object sender, DoWorkEventArgs e) => { Stopwatch watch = Stopwatch.StartNew(); ApplyRelocations(); //Scan for branches, add extra tags foreach (ModuleSectionNode s in Sections) { if (s.HasCode) { PPCOpCode code; buint * opPtr = s.BufferAddress; for (int i = 0; i < s._dataBuffer.Length / 4; i++) { if ((code = (uint)*opPtr++) is PPCBranch && !(code is PPCblr || code is PPCbctr)) { s._manager.LinkBranch(i, true); } } var cmds = s._manager.GetCommands(); foreach (var x in cmds) { RelocationTarget target = x.Value.GetTargetRelocation(); string value = null; if (target.Section != null && target._sectionID == 5 && !String.IsNullOrEmpty(value = target.Section._manager.GetString(target._index))) { s._manager.AddTag(x.Key, value); } } } } Sections[5].Populate(); watch.Stop(); Console.WriteLine("Took {0} seconds to relocate {1} module", (double)watch.ElapsedMilliseconds / 1000d, Name); }; using (BackgroundWorker b = new BackgroundWorker()) { b.DoWork += new DoWorkEventHandler(work); b.RunWorkerAsync(); } // Stage module conversion byte *bptr = (byte *)WorkingUncompressed.Address; int offset = findStageIDOffset(); _stageID = offset < 0 ? (byte?)null : bptr[offset]; if (nodeContainsString("stOnlineTrainning")) { // File must be online training room .rel file _itemIDs = new byte[OTrainItemOffsets.Length]; for (int i = 0; i < OTrainItemOffsets.Length; i++) { _itemIDs[i] = bptr[OTrainItemOffsets[i]]; } } }
//public RSARGroupNode _nullGroup; public override void OnPopulate() { //Enumerate entries, attaching them to the files. RSARHeader *rsar = Header; SYMBHeader *symb = rsar->SYMBBlock; sbyte * offset = (sbyte *)symb + 8; buint * stringOffsets = symb->StringOffsets; VoidPtr baseAddr = (VoidPtr)rsar->INFOBlock + 8; ruint * typeList = (ruint *)baseAddr; //Iterate through group types for (int i = 0; i < 5; i++) { Type t = null; switch (i) { case 0: t = typeof(RSARSoundNode); break; case 1: t = typeof(RSARBankNode); break; case 2: t = typeof(RSARPlayerInfoNode); break; case 3: continue; //Files case 4: t = typeof(RSARGroupNode); break; //Last group entry has no name } _infoCache[i] = new List <RSAREntryNode>(); RuintList *list = (RuintList *)((uint)baseAddr + typeList[i]); sbyte * str, end; for (int x = 0; x < list->_numEntries; x++) { VoidPtr addr = list->Get(baseAddr, x); ResourceNode parent = this; RSAREntryNode n = Activator.CreateInstance(t) as RSAREntryNode; n._origSource = n._uncompSource = new DataSource(addr, 0); if (n.StringId >= 0) { str = offset + stringOffsets[n.StringId]; for (end = str; *end != 0; end++) { ; } while ((--end > str) && (*end != '_')) { ; } if (end > str) { parent = CreatePath(parent, str, (int)end - (int)str); n._name = new String(end + 1); } else { n._name = new String(str); } } else { n._name = null; } n._infoIndex = x; n.Initialize(parent, addr, 0); _infoCache[i].Add(n); } _ftr = *(INFOFooter *)((uint)baseAddr + typeList[5]); foreach (RSARFileNode n in Files) { if (!(n is RSARExtFileNode)) { n.GetName(); } } } }
protected override void OnPopulate() { //Get files GetFiles(); //Enumerate entries, attaching them to the files. RSARHeader *rsar = Header; SYMBHeader *symb = rsar->SYMBBlock; sbyte * offset = (sbyte *)symb + 8; buint * stringOffsets = symb->StringOffsets; VoidPtr gOffset = (VoidPtr)rsar->INFOBlock + 8; ruint * groups = (ruint *)gOffset; for (int i = 0; i < 5; i++) { Type t = null; ruint *list = (ruint *)((uint)groups + groups[i] + 4); int count = *((bint *)list - 1); sbyte *str, end; switch (i) { case 0: t = typeof(RSARSoundNode); break; case 1: t = typeof(RSARBankNode); break; case 2: t = typeof(RSARTypeNode); break; case 3: { //Get files //INFOFileHeader* fileHeader; //INFOFileEntry* fileEntry; //RuintList* entryList; //INFOGroupHeader* group; //INFOGroupEntry* gEntry; //RuintList* groupList = rsar->INFOBlock->Groups; //RSARFileNode n; //DataSource source; //for (int x = 0; x < count; x++) //{ // fileHeader = (INFOFileHeader*)(gOffset + list[x]); // entryList = fileHeader->GetList(gOffset); // if (entryList->_numEntries == 0) // { // //Must be external file. // n = new RSARExtFileNode(); // source = new DataSource(fileHeader, 0); // } // else // { // //use first entry // fileEntry = (INFOFileEntry*)entryList->Get(gOffset, 0); // //Find group with matching ID // group = (INFOGroupHeader*)groupList->Get(gOffset, fileEntry->_groupId); // //Find group entry with matching index // gEntry = (INFOGroupEntry*)group->GetCollection(gOffset)->Get(gOffset, fileEntry->_index); // //Create node and parse // source = new DataSource((int)rsar + group->_headerOffset + gEntry->_headerOffset, gEntry->_headerLength); // if ((n = NodeFactory.GetRaw(source) as RSARFileNode) == null) // n = new RSARFileNode(); // n._audioSource = new DataSource((int)rsar + group->_dataOffset + gEntry->_dataOffset, gEntry->_dataLength); // } // n._fileIndex = x; // n._parent = this; //This is so that the node won't add itself to the child list. // n.Initialize(this, source); // _files.Add(n); //} continue; } case 4: t = typeof(RSARGroupNode); break; } for (int x = 0; x < count; x++) { ResourceNode parent = this; RSAREntryNode n = Activator.CreateInstance(t) as RSAREntryNode; n._origSource = n._uncompSource = new DataSource(gOffset + list[x], 0); str = offset + stringOffsets[n.StringId]; for (end = str; *end != 0; end++) { ; } while ((--end > str) && (*end != '_')) { ; } if (end > str) { parent = CreatePath(parent, str, (int)end - (int)str); n._name = new String(end + 1); } else { n._name = new String(str); } n.Initialize(parent, gOffset + list[x], 0); } } Sort(true); }