Пример #1
0
        /// <summary>
        /// Modify a chosen command in a code block
        /// <para>If the new command has more params than the old command (or the old command did not have params in the first place), the params location space may need to be expanded/relocated</para>
        /// </summary>
        /// <param name="commandLocation">The location of the command in the code block</param>
        /// <param name="oldPsaCommand">The old psa command (the one that is being modified)</param>
        /// <param name="newPsaCommand">The new psa command (the one that is replcaing the old psa command)</param>
        public void ModifyCommand(int commandLocation, PsaCommand oldPsaCommand, PsaCommand newPsaCommand)
        {
            if (PsaFile.DataSection[commandLocation + 1] >= 0 && PsaFile.DataSection[commandLocation + 1] < PsaFile.DataSectionSize)
            {
                // if there were no command params on the previous command
                if (oldPsaCommand.GetCommandParamsSize() == 0)
                {
                    // if there are no command params on new command, it's simply a swap out of command instructions with nothing else needed
                    if (newPsaCommand.GetCommandParamsSize() == 0)
                    {
                        PsaFile.DataSection[commandLocation] = newPsaCommand.Instruction;
                    }

                    // if there are command params on new command, create space for this new params location
                    else
                    {
                        CreateNewCommandParametersLocation(commandLocation, newPsaCommand);
                        PsaFileHelperMethods.ApplyHeaderUpdatesToAccountForPsaCommandChanges();
                    }
                }

                // if there are existing command params, they need to be overwritten, or the entire action may need to be relocated if not enough room for all the params
                else
                {
                    ModifyExistingCommandParametersLocation(commandLocation, oldPsaCommand, newPsaCommand);
                    PsaFileHelperMethods.ApplyHeaderUpdatesToAccountForPsaCommandChanges();
                }
            }
            else
            {
                throw new ApplicationException("Cannot modify command because it is not located within the data section");
            }
        }
Пример #2
0
        /// <summary>
        /// This will expand (usually includes relocating) the command's parameters location if the new psa command has more parameters than the old psa command
        /// <para>If possible, it will not relocate the params section if enough free space can be found</para>
        /// <para>If it can't find enough free space in the data section, it resorts to expanding the data section</para>
        /// </summary>
        /// <param name="oldPsaCommand">The psa command being modified</param>
        /// <param name="newPsaCommand">The psa command replacing the old psa command</param>
        /// <returns>The new location of the command parameters section (if section does not end up getting relocated, it will return the original param section location of the old psa command)</returns>
        private int ExpandCommandParametersSection(PsaCommand oldPsaCommand, PsaCommand newPsaCommand)
        {
            int oldCommandParamsSize = oldPsaCommand.GetCommandParamsSize();
            int newCommandParamsSize = newPsaCommand.GetCommandParamsSize();

            // determine how much space is currently available for params
            // to start, there is the original amount of space that the old psa command had
            int currentCommandParamSize = oldCommandParamsSize;

            // if adding one command to the current parameters location would cause it to go over the data section limit, expand the data section by the amount needed
            if (oldPsaCommand.CommandParametersValuesLocation + oldCommandParamsSize + 5 > PsaFile.DataSection.Count)
            {
                if (oldPsaCommand.CommandParametersValuesLocation + oldCommandParamsSize + 3 > PsaFile.DataSection.Count)
                {
                    // difference between the new size needed and the old size
                    currentCommandParamSize = newCommandParamsSize;
                }
            }

            // add 1 additional block of space for each free space (FADEF00D) that comes afterwards
            while (currentCommandParamSize < newCommandParamsSize &&
                   PsaFile.DataSection[oldPsaCommand.CommandParametersValuesLocation + currentCommandParamSize] == Constants.FADEF00D)
            {
                currentCommandParamSize++;
            }

            // if expanding the data section was applicable or enough free space was found from the above loop
            // the original location of the old psa command now has enough room to hold all necessary parameters for the new command
            if (currentCommandParamSize >= newCommandParamsSize)
            {
                return(oldPsaCommand.CommandParametersValuesLocation);
            }

            // if the amount of space available at the current moment is STILL not enough for all of the new params
            // the parameter location is going to need to be relocated to a place in the file with enough free space
            else
            {
                // find a location in the file with enough free space
                int newCommandParametersValuesLocation = PsaFileHelperMethods.FindLocationWithAmountOfFreeSpace(CodeBlockDataStartLocation, newCommandParamsSize);

                // if new location goes over data section limit, expand data sectoin
                if (newCommandParametersValuesLocation >= PsaFile.DataSection.Count)
                {
                    newCommandParametersValuesLocation = PsaFile.DataSection.Count;
                }
                return(newCommandParametersValuesLocation);
            }
        }
Пример #3
0
        /// <summary>
        /// Creates a new parameters section for a command
        /// <para>This is called if the old psa command does not have any parameters, but the new command does -- that means a parameters section for the command needs to be created and pointed to</para>
        /// </summary>
        /// <param name="commandLocation"></param>
        /// <param name="newPsaCommand"></param>
        private void CreateNewCommandParametersLocation(int commandLocation, PsaCommand newPsaCommand)
        {
            int newCommandParamsValuesSize = newPsaCommand.GetCommandParamsSize();

            // determine where the new parameters values location will be by finding enough free space to fit it
            int newCommandParametersValuesLocation = PsaFileHelperMethods.FindLocationWithAmountOfFreeSpace(CodeBlockDataStartLocation, newCommandParamsValuesSize);

            // if the only place with free space found is after the limits of the data section, expand the data section to make room
            if (newCommandParametersValuesLocation >= PsaFile.DataSection.Count)
            {
                newCommandParametersValuesLocation = PsaFile.DataSection.Count;
            }

            // go through each parameter in the new command one at a time and place it in the newly created parameters values location (type, value)
            for (int paramIndex = 0; paramIndex < newPsaCommand.NumberOfParams; paramIndex++)
            {
                int paramTypeLocation  = paramIndex * 2;
                int paramValueLocation = paramIndex * 2 + 1;

                // if command param type is "Pointer" and the param value is greater than 0 (meaning it points to something)
                if (newPsaCommand.Parameters[paramIndex].Type == 2 && newPsaCommand.Parameters[paramIndex].Value > 0)
                {
                    int commandParameterPointerLocation = (newCommandParametersValuesLocation + paramTypeLocation) * 4 + 4;
                    PsaFile.OffsetSection.Add(commandParameterPointerLocation);
                }
                PsaFileHelperMethods.SetDataSectionValue(newCommandParametersValuesLocation + paramTypeLocation, newPsaCommand.Parameters[paramIndex].Type);
                PsaFileHelperMethods.SetDataSectionValue(newCommandParametersValuesLocation + paramValueLocation, newPsaCommand.Parameters[paramIndex].Value);
            }

            // place new command instruction at command location
            PsaFile.DataSection[commandLocation] = newPsaCommand.Instruction;

            // set pointer to command parameters location
            int newCommandParametersLocation = newCommandParametersValuesLocation * 4;

            PsaFile.DataSection[commandLocation + 1] = newCommandParametersLocation;

            // set pointer to command parameters pointer location in the offset interlock tracker
            int newCommandParametersPointerLocation = commandLocation * 4 + 4;

            PsaFile.OffsetSection.Add(newCommandParametersPointerLocation);
        }