Example #1
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));
        }