private void Setup(SakuraiArchiveNode node, SakuraiEntryNode parent, int offset, string name) { _name = name; _root = node; _offset = offset; _parent = parent; if (_initSize <= 0) { _initSize = _root.GetSize(_offset); } _root.EntryCache[_offset] = this; if ((_externalEntry = _root.TryGetExternal(offset)) != null) { _externalEntry.References.Add(this); } }
public unsafe void Write(SakuraiArchiveNode node, VoidPtr address, int length) { _baseAddress = address + 0x20; _currentAddress = _baseAddress; //Write header SakuraiArchiveHeader *hdr = (SakuraiArchiveHeader *)address; hdr->_sectionCount = _sectionCount; hdr->_externalSubRoutineCount = _referenceCount; hdr->_lookupEntryCount = _lookupManager.Count; hdr->_fileSize = length; hdr->_pad1 = hdr->_pad2 = hdr->_pad3 = 0; List <int> _sectionOffsets = new List <int>(); //Write section data foreach (TableEntryNode section in node.SectionList) { SakuraiEntryNode entry = section; //If this section is referenced from an entry, //write that entry instead if (section.References.Count > 0) { entry = section.References[0]; } _sectionOffsets.Add(entry.Write(_currentAddress)); _currentAddress += entry.TotalSize; } //Write lookup values hdr->_lookupOffset = (int)_currentAddress - (int)_baseAddress; _lookupManager.Write(ref _currentAddress); //These can only be accessed after the lookup offset and count //have been written to the header. sStringEntry *sectionAddr = hdr->Sections; sStringEntry *refAddr = hdr->ExternalSubRoutines; }
/// <summary> /// Don't call this outside of the Parse functions. /// This is here to eliminate redundant code. /// </summary> private static T CommonInit <T>(SakuraiArchiveNode root, SakuraiEntryNode parent, VoidPtr addr, params object[] parameters) where T : SakuraiEntryNode { int offset = root.Offset(addr); bool attributes = parameters.Contains("Attributes"); if (offset <= 0 && !attributes) { return(null); } if (attributes) { parameters = new object[0]; } T n = Activator.CreateInstance(typeof(T), parameters) as T; n.Setup(root, parent, offset); n.OnParse(addr); return(n); }
public int GetSize() { _calculatingSize = true; //Reset variables _lookupCount = _lookupLen = 0; _lookupManager = new LookupManager(); _postProcessNodes = new List <SakuraiEntryNode>(); _referenceStringTable = new CompactStringTable(); //Add header size _size = SakuraiArchiveHeader.Size; //Calculate the size of each section and add names to string table foreach (TableEntryNode section in _rootNode.SectionList) { SakuraiEntryNode entry = section; //Sections *usually* have only one reference in data or dataCommon //An example of an exception to this is the 'AnimCmd' section //If a reference exists, calculate the size of that reference instead if (section.References.Count > 0) { entry = section.References[0]; } //Add the size of the entry's data, and the entry itself _size += entry.GetSize() + 8; //Add the lookup count _lookupCount += entry.GetLookupCount(); //Add the section's name to the string table _referenceStringTable.Add(entry.Name); } //Calculate reference table size and add names to string table foreach (TableEntryNode reference in _rootNode.ReferenceList) { if (reference.References.Count > 0 || AddUnreferencedReferences) { //Add entry name to string table _referenceStringTable.Add(reference.Name); //Add entry size (reference don't have any actual 'data' size) _size += 8; } //TODO: Does each reference offset throughout the file //have a lookup offset? //Also, subtract 1 because the initial offset has no lookup entry //lookupCount += e.References.Count - 1; } _calculatingSize = false; //Add the lookup size and reference table size _size += (_lookupLen = _lookupCount * 4) + _referenceStringTable.TotalSize; return(_size); }
/// <summary> /// Returns a node of the given type at an address in the moveset file. /// </summary> public T Parse <T>(VoidPtr address) where T : SakuraiEntryNode { return(SakuraiEntryNode.Parse <T>(this, null, address)); }
/// <summary> /// Returns a node of the given type at an offset in the moveset file. /// </summary> public T Parse <T>(int offset) where T : SakuraiEntryNode { return(SakuraiEntryNode.Parse <T>(this, null, Address(offset))); }
private void Setup(SakuraiArchiveNode node, SakuraiEntryNode parent, int offset) { Setup(node, parent, offset, null); }
public void ParseSelf(SakuraiArchiveNode root, SakuraiEntryNode parent, VoidPtr address) { Setup(root, parent, Offset(address)); OnParse(address); }
public void ParseSelf(SakuraiArchiveNode root, SakuraiEntryNode parent, int offset) { Setup(root, parent, offset); OnParse(Address(offset)); }
/// <summary> /// Use this to parse a node of a specific type at the given address. /// This will automatically add the node to the entry cache, get its size, /// set its offset value, and attach its external entry if it has one. /// Be sure to send the proper constructor parameters for the given type /// as well, or an error will be thrown. /// </summary> public static T Parse <T>(SakuraiArchiveNode root, SakuraiEntryNode parent, VoidPtr address, params object[] parameters) where T : SakuraiEntryNode { return(CommonInit <T>(root, parent, address, parameters)); }