示例#1
0
        private bool CompareScripts(Script orig, Script mod)
        {
            bool index = orig.RootExpressionIndex.IsValid && mod.RootExpressionIndex.IsValid;

            int origHash = SequenceHash.GetSequenceHashCode(orig.Parameters);
            int modHash  = SequenceHash.GetSequenceHashCode(mod.Parameters);

            return(index && (orig.Name == mod.Name) && (orig.ExecutionType == mod.ExecutionType) &&
                   (orig.ReturnType == mod.ReturnType) && (origHash == modHash));
        }
示例#2
0
        private void WriteScripts(ScriptData data, IStream stream, StructureValueCollection scnr)
        {
            ScriptLayout layout;

            if (_buildInfo.Name.Contains("Halo: Reach"))
            {
                layout = ScriptLayout.HaloReach;
            }
            else if (_buildInfo.Name.Contains("Halo 3") || _buildInfo.Name.Contains("Halo ODST"))
            {
                layout = ScriptLayout.Halo3;
            }
            else
            {
                throw new NotImplementedException("Saving this game's scripts is not supported yet.");
            }

            Dictionary <int, uint> newParamAddresses = WriteParams(data, stream, scnr);
            StructureLayout        scrlayout         = _buildInfo.Layouts.GetLayout("script element");

            int oldScriptCount = (int)scnr.GetInteger("number of scripts");
            int newScriptCount = data.Scripts.Count;

            uint oldScriptAddress    = (uint)scnr.GetInteger("script table address");
            long expOldScriptAddress = _expander.Expand(oldScriptAddress);
            long newScriptAddress    = 0;

            int oldScriptSize = oldScriptCount * scrlayout.Size;
            int newScriptSize = newScriptCount * scrlayout.Size;

            // get new Script Address
            if (newScriptCount > 0)
            {
                if (oldScriptCount > 0)
                {
                    newScriptAddress = _allocator.Reallocate(expOldScriptAddress, oldScriptSize, newScriptSize, stream);
                }
                else
                {
                    newScriptAddress = _allocator.Allocate(newScriptSize, stream);
                }


                stream.SeekTo(_metaArea.PointerToOffset(newScriptAddress));

                // write scripts
                foreach (var scr in data.Scripts)
                {
                    int paramCount = scr.Parameters.Count;

                    if (paramCount > 0)
                    {
                        int hash = SequenceHash.GetSequenceHashCode(scr.Parameters);

                        if (newParamAddresses.TryGetValue(hash, out uint addr))
                        {
                            scr.Write(stream, _stringIDs, paramCount, addr, layout);
                        }
                        else
                        {
                            throw new KeyNotFoundException("Failed to retrieve the address for a new parameter block.");
                        }
                    }
                    else
                    {
                        scr.Write(stream, _stringIDs, 0, 0, layout);
                    }
                }
            }
            else
            {
                if (oldScriptCount > 0)
                {
                    _allocator.Free(expOldScriptAddress, oldScriptSize);
                }
            }

            scnr.SetInteger("number of scripts", (uint)data.Scripts.Count);
            scnr.SetInteger("script table address", _expander.Contract(newScriptAddress));
        }
示例#3
0
        /// <summary>
        ///     Frees the old Script Parameters and writes new ones to the stream.
        /// </summary>
        /// <param name="data">The new script data</param>
        /// <param name="stream">The stream to write to</param>
        /// <param name="scnr">scnr Meta Data</param>
        /// <returns>A dictionary containing the hashes of parameter groups an their new addresses.</returns>
        private Dictionary <int, uint> WriteParams(ScriptData data, IStream stream, StructureValueCollection scnr)
        {
            StructureLayout scrlayout   = _buildInfo.Layouts.GetLayout("script element");
            StructureLayout paramlayout = _buildInfo.Layouts.GetLayout("script parameter element");

            int  oldScriptCount      = (int)scnr.GetInteger("number of scripts");
            uint oldScriptAddress    = (uint)scnr.GetInteger("script table address");
            long expOldScriptAddress = _expander.Expand(oldScriptAddress);
            int  oldParamSize        = 0;

            StructureValueCollection[] oldScripts = TagBlockReader.ReadTagBlock(stream, oldScriptCount, expOldScriptAddress, scrlayout, _metaArea);

            HashSet <uint> freedParamAddresses = new HashSet <uint>();

            int oldTotalParamCount = 0;

            // loop through old scripts
            for (int i = 0; i < oldScripts.Length; i++)
            {
                int  paramCount = (int)oldScripts[i].GetInteger("number of parameters");
                uint addr       = (uint)oldScripts[i].GetInteger("address of parameter list");

                oldTotalParamCount += paramCount;

                // free params
                if (addr != 0 && !freedParamAddresses.Contains(addr))
                {
                    long exp       = _expander.Expand(addr);
                    int  blockSize = paramCount * paramlayout.Size;
                    _allocator.Free(exp, blockSize);
                    oldParamSize += blockSize;
                    freedParamAddresses.Add(addr);
                }
            }

            int newTotalParamCount = 0;
            int newParamSize       = 0;
            Dictionary <int, uint> newParamAddresses = new Dictionary <int, uint>();

            // loop through new scripts
            foreach (var scr in data.Scripts)
            {
                int count = scr.Parameters.Count;

                if (count > 0)
                {
                    int paramHash = SequenceHash.GetSequenceHashCode(scr.Parameters);
                    if (!newParamAddresses.ContainsKey(paramHash))
                    {
                        long newAddr    = _allocator.Allocate(paramlayout.Size * count, stream);
                        uint conNewAddr = _expander.Contract(newAddr);
                        stream.SeekTo(_metaArea.PointerToOffset(newAddr));
                        // write params to stream
                        foreach (var par in scr.Parameters)
                        {
                            par.Write(stream);
                        }

                        newParamAddresses.Add(paramHash, conNewAddr);
                        newParamSize += scr.Parameters.Count * 36;
                    }
                }
                newTotalParamCount += scr.Parameters.Count;
            }

            return(newParamAddresses);
        }