Exemple #1
0
        /// <summary>
        /// This writes changed data without rewriting the entire file
        /// </summary>
        public unsafe void QuickWrite()
        {
            VoidPtr origAddr          = _rootNode.WorkingUncompressed.Address;
            SakuraiArchiveHeader *hdr = (SakuraiArchiveHeader *)origAddr;
            VoidPtr origBase          = hdr->BaseAddress;

            var changed = _rootNode.RebuildEntries;

            if (changed.Count != 0)
            {
                foreach (var entry in changed)
                {
                    int   eOffset       = entry._offset;
                    bint *lookup        = hdr->LookupEntries;
                    int   currentOffset = *(bint *)(origBase + *lookup++);
                    for (int i = 0; i < hdr->_lookupEntryCount - 1; i++, lookup++)
                    {
                        int nextOffset = *(bint *)(origBase + *lookup);
                        if (eOffset >= currentOffset && eOffset < nextOffset)
                        {
                            int newSize = entry._calcSize;
                            int oldSize = entry._initSize;
                            int diff    = newSize - oldSize;

                            for (int x = i; x < hdr->_lookupEntryCount; x++)
                            {
                                lookup[x] += diff;
                            }
                        }
                        currentOffset = nextOffset;
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Creates a table of offsets with a corresponding data size at each offset.
        /// </summary>
        private void GetLookupSizes(SakuraiArchiveHeader *hdr)
        {
            //Read lookup offsets first and use them to get entry sizes at each offset.
            bint *lookup = hdr->LookupEntries;

            //First add each offset to the dictionary with size of 0.
            //The dictionary will sort the offsets automatically, in case they aren't already.
            for (int i = 0; i < hdr->_lookupEntryCount; i++)
            {
                int w = *(bint *)Address(lookup[i]);
                if (!_lookupSizes.ContainsKey(w))
                {
                    _lookupSizes.Add(w, 0);
                }
            }
            //Now go through each offset and calculate the size with the offset difference.
            int prev = 0; bool first = true;

            int[] t = _lookupSizes.Keys.ToArray();
            for (int i = 0; i < t.Length; i++)
            {
                int off = t[i];
                if (first)
                {
                    first = false;
                }
                else
                {
                    _lookupSizes[prev] = off - prev;
                }
                prev = off;
            }
            //The last entry in the moveset file goes right up to the lookup offsets.
            _lookupSizes[prev] = Offset(lookup) - prev;
        }
Exemple #3
0
        /// <summary>
        /// Initializes all variables.
        /// </summary>
        protected virtual void InitData(SakuraiArchiveHeader *hdr)
        {
            //Get header values
            _dataSize = hdr->_fileSize;

#if DEBUG
            for (int i = 0; i < 3; i++)
            {
                int value = (&hdr->_pad1)[i];
                if (value != 0)
                {
                    Console.WriteLine("MovesetNode InitData " + i);
                }
            }
#endif

            //Create lists
            _changedEntries   = new BindingList <SakuraiEntryNode>();
            _rebuildEntries   = new BindingList <SakuraiEntryNode>();
            _referenceList    = new BindingList <TableEntryNode>();
            _sectionList      = new BindingList <TableEntryNode>();
            _lookupSizes      = new SortedList <int, int>();
            _entryCache       = new SortedDictionary <int, SakuraiEntryNode>();
            _postParseEntries = new List <SakuraiEntryNode>();
        }
Exemple #4
0
        protected virtual void ParseInternals(SakuraiArchiveHeader *hdr)
        {
            sStringTable *stringTable = hdr->StringTable;

            _sectionList = new BindingList <TableEntryNode>();

            //Parse sections
            int numSections = hdr->_sectionCount;

            if (numSections > 0)
            {
                sStringEntry *entries = (sStringEntry *)hdr->Sections;

                List <TableEntryNode> _specialSections = new List <TableEntryNode>();
                for (int i = 0; i < numSections; i++)
                {
                    int    offset = entries[i]._dataOffset;
                    string name   = stringTable->GetString(entries[i]._stringOffset);

                    TableEntryNode section = TableEntryNode.GetRaw(name);

                    //If null, this type of section doesn't have a dedicated class
                    if (section == null)
                    {
                        //Have the inheriting class handle it.
                        //Initialize the node with Parse() in here!!!
                        section = GetTableEntryNode(name, i);

                        //Still unhandled, so initialize as raw
                        if (section == null)
                        {
                            section = Parse <RawDataNode>(offset);
                        }
                    }
                    else
                    {
                        _specialSections.Add(section);
                    }

                    section._name  = name;
                    section._index = i;
                    section.DataOffsets.Add(offset);

                    _sectionList.Add(section);
                }

                //Now parse any dedicated-class nodes that may reference other sections.
                foreach (TableEntryNode section in _specialSections)
                {
                    section.ParseSelf(this, null, section.DataOffsets[0]);
                }

                HandleSpecialSections(_specialSections);
            }
        }
Exemple #5
0
        public override bool OnInitialize()
        {
            //Start initializing.
            //This enables some functions for use.
            _initializing = true;

            SakuraiArchiveHeader *hdr = (SakuraiArchiveHeader *)WorkingUncompressed.Address;

            InitData(hdr);
            GetLookupSizes(hdr);
            ParseExternals(hdr);
            ParseInternals(hdr);
            PostParse();

            return(_initializing = false);
        }
        protected override void InitData(SakuraiArchiveHeader *hdr)
        {
            base.InitData(hdr);

            _subRoutines       = new BindingList <Script>();
            _commonSubRoutines = new BindingList <Script>();
            _actions           = new BindingList <ActionEntry>();
            _scriptOffsets     = new List <List <int> > [5];
            for (int i = 0; i < 5; i++)
            {
                _scriptOffsets[i] = new List <List <int> >();
                for (int x = 0; x < (i == 0 ? 2 : i == 1 ? 4 : 1); x++)
                {
                    _scriptOffsets[i].Add(new List <int>());
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Reads external subroutine references
        /// </summary>
        private void ParseExternals(SakuraiArchiveHeader *hdr)
        {
            sStringTable *stringTable = hdr->StringTable;

            //Parse references
            int numRefs = hdr->_externalSubRoutineCount;

            if (numRefs > 0)
            {
                sStringEntry *entries = (sStringEntry *)hdr->ExternalSubRoutines;
                for (int i = 0; i < numRefs; i++)
                {
                    TableEntryNode e = Parse <TableEntryNode>(entries[i]._dataOffset);
                    e._name = stringTable->GetString(entries[i]._stringOffset);
                    _referenceList.Add(e);
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// This gets the size using entries that need to be rebuilt
        /// and the original lookup entries to inject the edited data
        /// into the original file
        /// </summary>
        /// <returns></returns>
        public unsafe int QuickGetSize()
        {
            _calculatingSize = true;

            VoidPtr origAddr          = _rootNode.WorkingUncompressed.Address;
            SakuraiArchiveHeader *hdr = (SakuraiArchiveHeader *)origAddr;
            VoidPtr origBase          = hdr->BaseAddress;

            _size = _rootNode.WorkingUncompressed.Length;
            foreach (var entry in _rootNode.RebuildEntries)
            {
                int newSize = entry.GetSize();
                int oldSize = entry._initSize;
                int diff    = newSize - oldSize;

                int lookupCount     = entry.GetLookupCount();
                int prevLookupCount = 0;

                int minOffset = entry._offset;
                int maxOffset = minOffset + oldSize;

                bint *lookup        = hdr->LookupEntries;
                int   currentOffset = *(bint *)(origBase + *lookup++);
                for (int i = 0; i < hdr->_lookupEntryCount - 1; i++, lookup++)
                {
                    int nextOffset = *(bint *)(origBase + *lookup);
                    if (minOffset >= currentOffset && minOffset < nextOffset)
                    {
                        for (int x = i; x < hdr->_lookupEntryCount; x++)
                        {
                            int insideOffset = *(bint *)(origBase + lookup[x]);
                        }
                    }
                }

                _size += diff;
            }

            _calculatingSize = false;

            return(_size);
        }
Exemple #9
0
        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;
        }