Example #1
0
        private void variableSpinner_ValueChanged(object sender, EventArgs e)
        {
            AsmPatch patch = (clb_Patches.SelectedItem as AsmPatch);

            if (!ignoreChanges)
            {
                UInt32       newValue = (UInt32)variableSpinner.Value;
                VariableType variable = patch.VariableMap[(string)variableComboBox.SelectedItem];
                UpdateVariable(variable, newValue);

                /*
                 * if (variable.PresetValues.Count > 0)
                 * {
                 *  VariableType.VariablePreset preset = FindSelectedPreset(variable);
                 *  if (preset == null)
                 *  {
                 *      cmb_Variable_Preset.SelectedIndex = -1;
                 *  }
                 *  else
                 *  {
                 *      cmb_Variable_Preset.SelectedIndex = variablePresetIndexMap[preset];
                 *  }
                 * }
                 */
            }
        }
Example #2
0
        private void clb_Patches_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if ((skipCheckEventHandler) || (lsb_FilesList.SelectedItem == null))
            {
                return;
            }

            int      selectedIndex = lsb_FilesList.SelectedIndex;
            AsmPatch asmPatch      = clb_Patches.Items[e.Index] as AsmPatch;

            if ((e.CurrentValue == CheckState.Unchecked) && (e.NewValue == CheckState.Checked) && (!asmPatch.ValidatePatch()))
            {
                e.NewValue = CheckState.Unchecked;
            }

            if (e.NewValue == CheckState.Checked)
            {
                patchData.SelectedPatches.Add(asmPatch);
            }
            else if (e.NewValue == CheckState.Unchecked)
            {
                if (patchData.SelectedPatches.Contains(asmPatch))
                {
                    patchData.SelectedPatches.Remove(asmPatch);
                }
            }

            patchData.CurrentSelectedPatches = GetCurrentFileSelectedPatches();
            bool enablePatchButtons = (patchData.CurrentSelectedPatches.Count > 0);

            btnPatch.Enabled          = enablePatchButtons;
            btnPatchSaveState.Enabled = enablePatchButtons;
        }
Example #3
0
        private void UpdateReferenceVariableValue(VariableType variable)
        {
            if (variable.isReference)
            {
                byte[] referenceBytes = VariableMap[variable.reference.name].byteArray;
                uint   value          = AsmPatch.GetUnsignedByteArrayValue_LittleEndian(referenceBytes);

                switch (variable.reference.operatorSymbol)
                {
                case "+":
                    value += variable.reference.operand;
                    break;

                case "-":
                    value -= variable.reference.operand;
                    break;

                case "*":
                    value *= variable.reference.operand;
                    break;

                case "/":
                    value /= variable.reference.operand;
                    break;
                }

                UpdateVariable(variable, value);
            }
        }
Example #4
0
        private void btnMove_Click(object sender, EventArgs e)
        {
            long newOffset = 0U;

            if (long.TryParse(txtAddress.Text, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out newOffset))
            {
                DataGridViewSelectedRowCollection selectedRows = dgv_FreeSpace.SelectedRows;
                if (selectedRows.Count > 0)
                {
                    DataGridViewRow row    = selectedRows[0];
                    long            offset = (long)(row.Cells[1].Value);

                    if (offset != newOffset)
                    {
                        PatchedByteArray patchedByteArray = rowPatchMap[row];
                        AsmPatch         asmPatch         = freeSpaceMaps.InnerPatchMap[patchedByteArray];
                        long             moveOffset       = newOffset - offset;

                        MovePatchRange movePatchRange = new MovePatchRange(new PatchRange(patchedByteArray), moveOffset);
                        asmPatch.MoveBlock(asmUtility, movePatchRange);
                        asmPatch.Update(asmUtility);

                        txtAddress.BackColor = Color.White;
                        Reload();
                    }
                }
            }
            else
            {
                txtAddress.BackColor = Color.FromArgb(225, 125, 125);
            }
        }
Example #5
0
        public AsmPatch Copy()
        {
            AsmPatch result = new AsmPatch(Name, Filename, Description, CopyableEntry.CopyList <PatchedByteArray>(innerList), HideInDefault, IsHidden, CopyableEntry.CopyArray <VariableType>(Variables));

            result.ErrorText = ErrorText;
            return(result);
        }
Example #6
0
        void clb_Patches_SelectedIndexChanged(object sender, EventArgs e)
        {
            AsmPatch p = clb_Patches.SelectedItem as AsmPatch;

            if (p != null)
            {
                textBox1.Text = p.Description;

                int index = clb_Patches.SelectedIndex;
                txt_Messages.Text = (index >= 0) ? patchMessages[index] : "";

                if (p.Variables.Count > 0)
                {
                    ignoreChanges = true;
                    variableComboBox.Items.Clear();
                    p.Variables.ForEach(varType => variableComboBox.Items.Add(varType.content.Key));
                    variableComboBox.SelectedIndex = 0;

                    //variableSpinner.Value = p.Variables[0].content.Value.GetBytes()[0];
                    Byte[] byteArray = p.Variables[0].content.Value.GetBytes();
                    variableSpinner.Maximum = (decimal)Math.Pow(256, p.Variables[0].bytes) - 1;
                    variableSpinner.Value   = p.GetUnsignedByteArrayValue_LittleEndian(byteArray);

                    variableSpinner.Visible  = true;
                    ignoreChanges            = false;
                    variableComboBox.Visible = true;
                }
                else
                {
                    variableSpinner.Visible  = false;
                    ignoreChanges            = true;
                    variableComboBox.Visible = false;
                }
            }
        }
Example #7
0
 public PatchRangeConflict(PatchRange range, AsmPatch conflictPatch, PatchRange conflictRange, bool isInFreeSpace)
 {
     this.Range         = range;
     this.ConflictPatch = conflictPatch;
     this.ConflictRange = conflictRange;
     this.IsInFreeSpace = isInFreeSpace;
 }
Example #8
0
        private void ShowConflicts(AsmPatch patch)
        {
            List <PatchRangeConflict> conflictList = conflictPatchData.ConflictMap[patch];

            foreach (PatchRangeConflict conflict in conflictList)
            {
                //PsxIso.Sectors sector = (PsxIso.Sectors)(conflict.ConflictRange.Sector);
                //string strSector = Enum.GetName(typeof(PsxIso.Sectors), sector);
                //string strSector = PatcherLib.Iso.PsxIso.GetSectorName(sector);

                /*
                 * Type sectorType = (mode == FreeSpaceMode.PSP) ? typeof(PspIso.Sectors) : typeof(PsxIso.Sectors);
                 * Enum sector = (Enum)Enum.ToObject(sectorType, conflict.ConflictRange.Sector);
                 * string strSector = (mode == FreeSpaceMode.PSP) ? PspIso.GetSectorName((PspIso.Sectors)sector) : PsxIso.GetSectorName((PsxIso.Sectors)sector);
                 */

                string strSector = ISOHelper.GetSectorName(conflict.ConflictRange.Sector, FreeSpace.GetContext(mode));

                // Patch #, Sector, Location, Conflict Location
                ListViewItem item = new ListViewItem();
                item.Text = conflict.ConflictPatchNumber.ToString();
                item.SubItems.Add(strSector);
                item.SubItems.Add(conflict.Range.StartOffset.ToString("X"));
                item.SubItems.Add(conflict.ConflictRange.StartOffset.ToString("X"));
                item.BackColor = conflict.IsInFreeSpace ? backColor_Conflict_FreeSpace : backColor_Conflict_NonFreeSpace;
                lv_Conflicts.Items.Add(item);
            }
        }
Example #9
0
        private void variableSpinner_ValueChanged(object sender, EventArgs e)
        {
            AsmPatch patch = (clb_Patches.SelectedItem as AsmPatch);

            if (!ignoreChanges)
            {
                UInt32       newValue = (UInt32)variableSpinner.Value;
                VariableType variable = patch.VariableMap[(string)variableComboBox.SelectedItem];
                UpdateVariable(variable, newValue);
            }
        }
Example #10
0
        private void LoadItems(int freeSpacePositionIndex)
        {
            lbl_NumberOfPatches.Text = "0";
            lbl_NumberOfWrites.Text  = "0";

            if (freeSpacePositionIndex < 0)
            {
                return;
            }

            dgv_FreeSpace.Rows.Clear();
            txtAddress.Clear();

            rowPatchMap = new Dictionary <DataGridViewRow, PatchedByteArray>();

            PatchRange range = FreeSpace.GetRanges(mode)[freeSpacePositionIndex];

            if (!freeSpaceMaps.PatchRangeMap.ContainsKey(range))
            {
                return;
            }

            //long positionEndOffset = position.StartLocation + position.Length - 1;
            List <PatchedByteArray> patchedByteArrayList = freeSpaceMaps.PatchRangeMap[range];
            HashSet <AsmPatch>      asmPatchSet          = freeSpaceMaps.OuterPatchRangeMap[range];

            for (int index = 0; index < patchedByteArrayList.Count; index++)
            {
                PatchedByteArray patchedByteArray = patchedByteArrayList[index];
                AsmPatch         asmPatch         = freeSpaceMaps.InnerPatchMap[patchedByteArray];

                // Column order: Number, Address, Length, Next Address, Space to Next Patch, File, Name
                int  length                     = patchedByteArray.GetBytes().Length;
                long nextAddress                = patchedByteArray.Offset + length;
                long nextPatchLocation          = (index < (patchedByteArrayList.Count - 1)) ? patchedByteArrayList[index + 1].Offset : range.EndOffset;
                long spaceToNextPatch           = nextPatchLocation - nextAddress;
                bool isSpaceToNextPatchNegative = (spaceToNextPatch < 0);
                //string strSpaceToNextPatch = isSpaceToNextPatchNegative ? ("-" + (-spaceToNextPatch).ToString("X")) : spaceToNextPatch.ToString("X");

                //dgv_FreeSpace.Rows.Add(index, patchedByteArray.Offset.ToString("X"), length.ToString("X"), nextAddress.ToString("X"), strSpaceToNextPatch, asmPatch.Filename, asmPatch.Name);
                dgv_FreeSpace.Rows.Add(index, patchedByteArray.Offset, length, nextAddress, spaceToNextPatch, asmPatch.Filename, asmPatch.Name);

                if (isSpaceToNextPatchNegative)
                {
                    dgv_FreeSpace.Rows[index].Cells[4].Style.BackColor = Color.FromArgb(225, 125, 125);
                }

                rowPatchMap.Add(dgv_FreeSpace.Rows[index], patchedByteArray);
            }

            lbl_NumberOfPatches.Text = asmPatchSet.Count.ToString();
            lbl_NumberOfWrites.Text  = patchedByteArrayList.Count.ToString();
        }
Example #11
0
        void variableSpinner_ValueChanged(object sender, EventArgs e)
        {
            AsmPatch patch = (clb_Patches.SelectedItem as AsmPatch);

            if (!ignoreChanges)
            {
                UInt32 def = (UInt32)variableSpinner.Value;
                for (int i = 0; i < patch.Variables[variableComboBox.SelectedIndex].bytes; i++)
                {
                    patch.Variables[variableComboBox.SelectedIndex].content.Value.GetBytes()[i] = (Byte)((def >> (i * 8)) & 0xff);
                }
            }
        }
Example #12
0
        private void clb_Patches_SelectedIndexChanged(object sender, EventArgs e)
        {
            AsmPatch p = clb_Patches.SelectedItem as AsmPatch;

            if (p != null)
            {
                textBox1.Text = p.Description;

                int index = clb_Patches.SelectedIndex;
                txt_Messages.Text = p.ErrorText;

                //if (p.Variables.Count > 0)
                if (p.CountNonReferenceVariables() > 0)
                {
                    ignoreChanges = true;
                    variableComboBox.Items.Clear();

                    bool         foundFirst = false;
                    VariableType firstNonReferenceVariable = p.Variables[0];
                    foreach (VariableType variable in p.Variables)
                    {
                        if (!variable.isReference)
                        {
                            variableComboBox.Items.Add(variable.name);
                            if (!foundFirst)
                            {
                                firstNonReferenceVariable = variable;
                                foundFirst = true;
                            }
                        }
                    }
                    variableComboBox.SelectedIndex = 0;

                    byte[] byteArray = firstNonReferenceVariable.byteArray;
                    variableSpinner.Maximum = (decimal)Math.Pow(256, firstNonReferenceVariable.numBytes) - 1;
                    variableSpinner.Value   = AsmPatch.GetUnsignedByteArrayValue_LittleEndian(byteArray);

                    variableSpinner.Visible  = true;
                    ignoreChanges            = false;
                    variableComboBox.Visible = true;
                }
                else
                {
                    variableSpinner.Visible  = false;
                    ignoreChanges            = true;
                    variableComboBox.Visible = false;
                }
            }
        }
Example #13
0
        private void cmb_Variable_Preset_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!ignoreChanges)
            {
                AsmPatch     patch                 = (clb_Patches.SelectedItem as AsmPatch);
                VariableType selectedVariable      = patch.VariableMap[(string)variableComboBox.SelectedItem];
                VariableType.VariablePreset preset = (VariableType.VariablePreset)cmb_Variable_Preset.SelectedItem;
                variableSpinner.Visible = preset.IsModifiable;

                if (!preset.IsModifiable)
                {
                    variableSpinner.Value = preset.Value;
                }
            }
        }
Example #14
0
        void variableComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!ignoreChanges)
            {
                AsmPatch patch     = (clb_Patches.SelectedItem as AsmPatch);
                Byte[]   byteArray = patch.Variables[variableComboBox.SelectedIndex].content.Value.GetBytes();

                // Setting Maximum can trigger the variableSpinner_ValueChanged event, but we don't want to change the variable value here, so set ignoreChanges = true before setting Maximum.
                ignoreChanges           = true;
                variableSpinner.Maximum = (decimal)Math.Pow(256, patch.Variables[variableComboBox.SelectedIndex].bytes) - 1;
                ignoreChanges           = false;

                variableSpinner.Value = patch.GetUnsignedByteArrayValue_LittleEndian(byteArray);
            }
        }
Example #15
0
        private void variableComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!ignoreChanges)
            {
                AsmPatch     patch            = (clb_Patches.SelectedItem as AsmPatch);
                VariableType selectedVariable = patch.VariableMap[(string)variableComboBox.SelectedItem];

                byte[] byteArray = selectedVariable.byteArray;

                // Setting Maximum can trigger the variableSpinner_ValueChanged event, but we don't want to change the variable value here, so set ignoreChanges = true before setting Maximum.
                ignoreChanges           = true;
                variableSpinner.Maximum = (decimal)Math.Pow(256, selectedVariable.numBytes) - 1;
                ignoreChanges           = false;

                variableSpinner.Value = AsmPatch.GetUnsignedByteArrayValue_LittleEndian(byteArray);
            }
        }
Example #16
0
        private void ShowPatches(ConflictCheckResult conflictPatchData)
        {
            lv_Patches.Items.Clear();
            for (int patchIndex = 0; patchIndex < conflictPatchData.PatchList.Count; patchIndex++)
            {
                AsmPatch patch = conflictPatchData.PatchList[patchIndex];
                int      leastConflictPatchIndex = GetLeastConflictPatchIndex(patchIndex, conflictPatchData.ConflictMap[patch]);

                // Patch #, File, Name
                ListViewItem listViewItem = new ListViewItem();
                listViewItem.Text = patchIndex.ToString();
                listViewItem.SubItems.Add(patch.Filename);
                listViewItem.SubItems.Add(patch.Name);
                listViewItem.BackColor = patchColors[leastConflictPatchIndex];
                lv_Patches.Items.Add(listViewItem);
            }

            lv_Patches_columnHeader_Name.AutoResize(System.Windows.Forms.ColumnHeaderAutoResizeStyle.ColumnContent);
        }
Example #17
0
        public void Update(ASMEncoding.ASMEncodingUtility asmUtility)
        {
            UpdateReferenceVariableValues();

            List <PatchedByteArray> allPatches = GetAllPatches();

            foreach (PatchedByteArray patchedByteArray in allPatches)
            {
                if (patchedByteArray.IsAsm)
                {
                    string encodeContent = patchedByteArray.AsmText;
                    //string strPrefix = "";
                    //IList<VariableType> variables = Variables;

                    System.Text.StringBuilder sbPrefix = new System.Text.StringBuilder();
                    foreach (PatchedByteArray currentPatchedByteArray in allPatches)
                    {
                        if (!string.IsNullOrEmpty(currentPatchedByteArray.Label))
                        {
                            sbPrefix.AppendFormat(".label @{0}, {1}{2}", currentPatchedByteArray.Label, currentPatchedByteArray.RamOffset, Environment.NewLine);
                        }
                    }
                    foreach (VariableType variable in Variables)
                    {
                        sbPrefix.AppendFormat(".eqv %{0}, {1}{2}", ASMEncoding.Helpers.ASMStringHelper.RemoveSpaces(variable.name).Replace(",", ""),
                                              AsmPatch.GetUnsignedByteArrayValue_LittleEndian(variable.byteArray), Environment.NewLine);
                    }

                    encodeContent = sbPrefix.ToString() + patchedByteArray.AsmText;
                    //patchedByteArray.SetBytes(asmUtility.EncodeASM(encodeContent, (uint)patchedByteArray.RamOffset).EncodedBytes);

                    byte[] bytes = asmUtility.EncodeASM(encodeContent, (uint)patchedByteArray.RamOffset).EncodedBytes;

                    if ((!patchedByteArray.IsMoveSimple) && (blockMoveList.Count > 0))
                    {
                        bytes = asmUtility.UpdateBlockReferences(bytes, (uint)patchedByteArray.RamOffset, true, blockMoveList);
                    }

                    patchedByteArray.SetBytes(bytes);
                }
            }
        }
Example #18
0
        private void ShowConflicts(AsmPatch patch)
        {
            List <PatchRangeConflict> conflictList = conflictPatchData.ConflictMap[patch];

            foreach (PatchRangeConflict conflict in conflictList)
            {
                PsxIso.Sectors sector = (PsxIso.Sectors)(conflict.ConflictRange.Sector);
                //string strSector = Enum.GetName(typeof(PsxIso.Sectors), sector);
                string strSector = PatcherLib.Iso.PsxIso.GetSectorName(sector);

                // Patch #, Sector, Location, Conflict Location
                ListViewItem item = new ListViewItem();
                item.Text = conflict.ConflictPatchNumber.ToString();
                item.SubItems.Add(strSector);
                item.SubItems.Add(conflict.Range.StartOffset.ToString("X"));
                item.SubItems.Add(conflict.ConflictRange.StartOffset.ToString("X"));
                item.BackColor = conflict.IsInFreeSpace ? backColor_Conflict_FreeSpace : backColor_Conflict_NonFreeSpace;
                lv_Conflicts.Items.Add(item);
            }
        }
Example #19
0
        void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            AsmPatch p = checkedListBox1.SelectedItem as AsmPatch;

            textBox1.Text = p.Description;
            if (p.Variables.Count > 0)
            {
                ignoreChanges = true;
                variableComboBox.Items.Clear();
                p.Variables.ForEach(kvp => variableComboBox.Items.Add(kvp.Key));
                variableComboBox.SelectedIndex = 0;
                variableSpinner.Value          = p.Variables[0].Value.Bytes[0];
                ignoreChanges            = false;
                variableSpinner.Visible  = true;
                variableComboBox.Visible = true;
            }
            else
            {
                ignoreChanges            = true;
                variableComboBox.Visible = false;
                variableSpinner.Visible  = false;
            }
        }
Example #20
0
        private void LoadFilePatches(int selectedIndex)
        {
            ClearCurrentPatch();

            if (selectedIndex == 0)
            {
                LoadPatches(patchData.AllShownPatches);
                clb_Patches.BackColors = patchData.BackgroundColors[selectedIndex];
            }
            else if (!patchData.LoadedCorrectly[selectedIndex - 1])
            {
                clb_Patches.Items.Clear();
                PatcherLib.MyMessageBox.Show(this, lsb_FilesList.SelectedItem + " did not load correctly!", "Error", MessageBoxButtons.OK);
            }
            else
            {
                LoadPatches(patchData.FilePatches[selectedIndex - 1].Patches);
                clb_Patches.BackColors = patchData.BackgroundColors[selectedIndex];
            }

            //patchData.CurrentSelectedPatches = GetCurrentFileSelectedPatches();

            skipCheckEventHandler = true;
            for (int index = 0; index < clb_Patches.Items.Count; index++)
            {
                AsmPatch asmPatch = (AsmPatch)(clb_Patches.Items[index]);
                clb_Patches.ForceSetItemChecked(index, patchData.SelectedPatches.Contains(asmPatch));
            }

            skipCheckEventHandler = false;

            //bool enablePatchButtons = (patchData.CurrentSelectedPatches.Count > 0);
            bool enablePatchButtons = (patchData.SelectedPatches.Count > 0);

            btnPatch.Enabled = enablePatchButtons;
            //btnPatchSaveState.Enabled = enablePatchButtons;
        }
Example #21
0
 public AsmPatchEnumerator(AsmPatch owner)
 {
     this.owner = owner;
 }
Example #22
0
        public static ConflictResolveResult ResolveConflicts(IList <AsmPatch> patchList, ASMEncoding.ASMEncodingUtility asmUtility, int maxConflictResolveAttempts = MaxConflictResolveAttempts)
        {
            List <AsmPatch>            resultPatchList = new List <AsmPatch>();
            Dictionary <AsmPatch, int> patchIndexMap   = new Dictionary <AsmPatch, int>();
            StringBuilder sbMessage    = new StringBuilder();
            bool          hasConflicts = false;

            for (int index = 0; index < patchList.Count; index++)
            {
                resultPatchList.Add(patchList[index]);
                patchIndexMap.Add(patchList[index], index);
            }

            Context       context       = (asmUtility.EncodingMode == ASMEncoding.ASMEncodingMode.PSP) ? Context.US_PSP : Context.US_PSX;
            FreeSpaceMode mode          = FreeSpace.GetMode(context);
            FreeSpaceMaps freeSpaceMaps = FreeSpace.GetFreeSpaceMaps(resultPatchList, mode);

            foreach (PatchRange freeSpaceRange in freeSpaceMaps.PatchRangeMap.Keys)
            {
                List <PatchedByteArray> innerPatches  = freeSpaceMaps.PatchRangeMap[freeSpaceRange];
                FreeSpaceAnalyzeResult  analyzeResult = FreeSpace.Analyze(innerPatches, freeSpaceRange, true);
                int conflictResolveAttempts           = 0;

                /*
                 * Type sectorType = ISOHelper.GetSectorType(context);
                 * Enum sector = (Enum)Enum.ToObject(sectorType, freeSpaceRange.Sector);
                 * string strSector = (mode == FreeSpaceMode.PSP) ? PspIso.GetSectorName((PspIso.Sectors)sector) : PsxIso.GetSectorName((PsxIso.Sectors)sector);
                 */

                string strSector = ISOHelper.GetSectorName(freeSpaceRange.Sector, context);

                while ((analyzeResult.HasConflicts) && (conflictResolveAttempts < maxConflictResolveAttempts))
                {
                    bool isStatic   = false;
                    bool stayStatic = false;

                    int endIndex = innerPatches.Count - 1;
                    for (int index = 0; index < endIndex; index++)
                    {
                        PatchedByteArray innerPatch = innerPatches[index];
                        isStatic   = innerPatch.IsStatic || stayStatic;
                        stayStatic = (innerPatch.IsStatic) && (innerPatch.IsPatchEqual(innerPatches[index + 1]));

                        if ((analyzeResult.ConflictIndexes.Contains(index)) && (!isStatic))
                        {
                            long           moveOffset     = analyzeResult.LargestGapOffset - innerPatch.Offset;
                            MovePatchRange movePatchRange = new MovePatchRange(new PatchRange(innerPatch), moveOffset);

                            AsmPatch asmPatch         = freeSpaceMaps.InnerPatchMap[innerPatch];
                            int      resultPatchIndex = patchIndexMap[asmPatch];
                            patchIndexMap.Remove(asmPatch);

                            asmPatch = asmPatch.Copy();
                            resultPatchList[resultPatchIndex] = asmPatch;
                            patchIndexMap.Add(asmPatch, resultPatchIndex);
                            asmPatch.MoveBlock(asmUtility, movePatchRange);
                            asmPatch.Update(asmUtility);

                            sbMessage.AppendLine("Conflict resolved by moving segment of patch \"" + asmPatch.Name + "\" in sector " + strSector + " from offset "
                                                 + innerPatch.Offset.ToString("X") + " to " + analyzeResult.LargestGapOffset.ToString("X") + ".");

                            freeSpaceMaps = FreeSpace.GetFreeSpaceMaps(resultPatchList, mode);
                            innerPatches  = freeSpaceMaps.PatchRangeMap[freeSpaceRange];
                            analyzeResult = FreeSpace.Analyze(innerPatches, freeSpaceRange, false);
                            conflictResolveAttempts++;
                            break;
                        }
                    }
                }

                if (analyzeResult.HasConflicts)
                {
                    hasConflicts = true;
                    int endIndex = innerPatches.Count - 1;
                    for (int index = 0; index < endIndex; index++)
                    {
                        if (analyzeResult.ConflictIndexes.Contains(index))
                        {
                            sbMessage.Length = 0;
                            sbMessage.AppendLine("Conflict in sector " + strSector + " at offset " + innerPatches[index].Offset.ToString("X") + "!");
                            break;
                        }
                    }
                }
            }

            return(new ConflictResolveResult(resultPatchList, hasConflicts, sbMessage.ToString()));
        }
Example #23
0
        private void clb_Patches_SelectedIndexChanged(object sender, EventArgs e)
        {
            AsmPatch p = clb_Patches.SelectedItem as AsmPatch;

            if (p != null)
            {
                string description = "";
                if (!string.IsNullOrEmpty(p.Description))
                {
                    StringBuilder sb    = new StringBuilder();
                    string[]      lines = p.Description.Split('\n');

                    for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++)
                    {
                        string line    = lines[lineIndex];
                        string newLine = line.Trim().Replace("\r", "");
                        if (((lineIndex != 0) && (lineIndex < (lines.Length - 1))) || (!string.IsNullOrEmpty(newLine)))
                        {
                            sb.AppendLine(newLine);
                        }
                    }
                    description = sb.ToString();
                    description = description.Substring(0, description.LastIndexOf(Environment.NewLine));
                }

                textBox1.Text = description;

                int index = clb_Patches.SelectedIndex;
                txt_Messages.Text = p.ErrorText;

                //if (p.Variables.Count > 0)
                if (p.CountNonReferenceVariables() > 0)
                {
                    ignoreChanges = true;
                    variableComboBox.Items.Clear();

                    bool         foundFirst = false;
                    VariableType firstNonReferenceVariable = p.Variables[0];
                    foreach (VariableType variable in p.Variables)
                    {
                        if (!variable.IsReference)
                        {
                            variableComboBox.Items.Add(variable.Name);
                            if (!foundFirst)
                            {
                                firstNonReferenceVariable = variable;
                                foundFirst = true;
                            }
                        }
                    }
                    variableComboBox.SelectedIndex = 0;

                    byte[] byteArray = firstNonReferenceVariable.ByteArray;
                    variableSpinner.Maximum = (decimal)Math.Pow(256, firstNonReferenceVariable.NumBytes) - 1;
                    variableSpinner.Value   = Utilities.GetUnsignedByteArrayValue_LittleEndian(byteArray);

                    variableSpinner.Visible  = true;
                    ignoreChanges            = false;
                    variableComboBox.Visible = true;

                    HandleVariablePresets(firstNonReferenceVariable);
                }
                else
                {
                    variableSpinner.Visible     = false;
                    ignoreChanges               = true;
                    variableComboBox.Visible    = false;
                    cmb_Variable_Preset.Visible = false;
                }
            }
        }
Example #24
0
 private void UpdateVariable(VariableType variable, UInt32 newValue)
 {
     AsmPatch.UpdateVariable(variable, newValue);
 }
Example #25
0
        private ConflictCheckResult CheckConflicts(List <AsmPatch> patchList)
        {
            List <AsmPatch> resultPatchList = new List <AsmPatch>();
            Dictionary <AsmPatch, List <PatchRangeConflict> > conflictMap          = new Dictionary <AsmPatch, List <PatchRangeConflict> >();
            Dictionary <AsmPatch, List <PatchedByteArray> >   combinedPatchListMap = new Dictionary <AsmPatch, List <PatchedByteArray> >();

            foreach (AsmPatch patch in patchList)
            {
                combinedPatchListMap[patch] = patch.GetCombinedPatchList();
            }

            for (int patchIndex = 0; patchIndex < patchList.Count; patchIndex++)
            {
                AsmPatch patch = patchList[patchIndex];

                List <PatchedByteArray> combinedPatchList = combinedPatchListMap[patch];
                foreach (PatchedByteArray patchedByteArray in combinedPatchList)
                {
                    if (patchedByteArray is InputFilePatch)
                    {
                        continue;
                    }

                    PatchRange range = new PatchRange(patchedByteArray);
                    for (int conflictPatchIndex = patchIndex + 1; conflictPatchIndex < patchList.Count; conflictPatchIndex++)
                    {
                        AsmPatch conflictPatch = patchList[conflictPatchIndex];

                        List <PatchedByteArray> conflictCombinedPatchList = combinedPatchListMap[conflictPatch];
                        foreach (PatchedByteArray conflictPatchedByteArray in conflictCombinedPatchList)
                        {
                            if (conflictPatchedByteArray is InputFilePatch)
                            {
                                continue;
                            }

                            //if (patchedByteArray.IsPatchEqual(conflictPatchedByteArray))
                            if (!patchedByteArray.HasConflict(conflictPatchedByteArray))
                            {
                                continue;
                            }

                            PatchRange conflictRange = new PatchRange(conflictPatchedByteArray);
                            if (range.HasOverlap(conflictRange))
                            {
                                bool isInFreeSpace = FreeSpace.IsContainedWithinPsxFreeSpace(range);

                                PatchRangeConflict patchConflict        = new PatchRangeConflict(range, conflictPatch, conflictRange, isInFreeSpace);
                                PatchRangeConflict reversePatchConflict = new PatchRangeConflict(conflictRange, patch, range, isInFreeSpace);

                                if (conflictMap.ContainsKey(patch))
                                {
                                    conflictMap[patch].Add(patchConflict);
                                }
                                else
                                {
                                    conflictMap.Add(patch, new List <PatchRangeConflict> {
                                        patchConflict
                                    });
                                }

                                if (conflictMap.ContainsKey(conflictPatch))
                                {
                                    conflictMap[conflictPatch].Add(reversePatchConflict);
                                }
                                else
                                {
                                    conflictMap.Add(conflictPatch, new List <PatchRangeConflict> {
                                        reversePatchConflict
                                    });
                                }
                            }
                        }
                    }
                }

                if (conflictMap.ContainsKey(patch))
                {
                    resultPatchList.Add(patch);
                }
            }

            return(new ConflictCheckResult(resultPatchList, conflictMap));
        }
Example #26
0
        private void CheckPatches()
        {
            List <Color>  bgColors = new List <Color>();
            List <string> messages = new List <string>();

            for (int index = 0; index < clb_Patches.Items.Count; index++)
            {
                Color         color     = clb_Patches.BackColor;
                StringBuilder sbMessage = new StringBuilder();

                object objPatch = clb_Patches.Items[index];
                if (objPatch != null)
                {
                    AsmPatch asmPatch       = (AsmPatch)objPatch;
                    int      byteArrayIndex = 0;
                    foreach (PatchedByteArray patchedByteArray in asmPatch)
                    {
                        if (byteArrayIndex >= (asmPatch.Count - asmPatch.Variables.Count))
                        {
                            break;
                        }

                        bool   canLoadBytes = true;
                        byte[] bytes        = null;
                        try
                        {
                            bytes = patchedByteArray.GetBytes();
                        }
                        catch (Exception)
                        {
                            canLoadBytes = false;
                        }

                        if (canLoadBytes)
                        {
                            UInt32 ramOffset = 0;
                            try
                            {
                                PsxIso.FileToRamOffsets ftrOffset = (PsxIso.FileToRamOffsets)Enum.Parse(typeof(PsxIso.FileToRamOffsets), "OFFSET_"
                                                                                                        + Enum.GetName(typeof(PsxIso.Sectors), patchedByteArray.Sector));
                                ramOffset = (UInt32)patchedByteArray.Offset + (UInt32)ftrOffset;
                            }
                            catch (Exception) { }

                            ramOffset = ramOffset | 0x80000000;     // KSEG0

                            bool markedAsData = asmPatch.isDataSectionList[byteArrayIndex];
                            if (!markedAsData)
                            {
                                ASMCheckResult result = asmUtility.CheckASMFromBytes(bytes, ramOffset, true, false, asmCheckConditions);
                                if (result.IsASM)
                                {
                                    if (!string.IsNullOrEmpty(result.ErrorText))
                                    {
                                        color = Color.FromArgb(225, 125, 125);
                                        sbMessage.Append(result.ErrorText);
                                    }
                                }
                            }
                        }

                        byteArrayIndex++;
                    }
                }

                bgColors.Add(color);
                messages.Add(sbMessage.ToString());
            }

            clb_Patches.BackColors = bgColors.ToArray();
            patchMessages          = messages.ToArray();
        }
Example #27
0
        public static IList <AsmPatch> GetPatches(XmlNode rootNode, string xmlFilename, ASMEncodingUtility asmUtility)
        {
            bool         rootHideInDefault = false;
            XmlAttribute attrHideInDefault = rootNode.Attributes["hideInDefault"];

            if (attrHideInDefault != null)
            {
                rootHideInDefault = (attrHideInDefault.InnerText.ToLower().Trim() == "true");
            }

            bool         rootIsHidden = false;
            XmlAttribute attrIsHidden = rootNode.Attributes["hidden"];

            if (attrIsHidden != null)
            {
                rootIsHidden = (attrIsHidden.InnerText.ToLower().Trim() == "true");
            }

            string shortXmlFilename = xmlFilename.Substring(xmlFilename.LastIndexOf("\\") + 1);

            XmlNodeList     patchNodes = rootNode.SelectNodes("Patch");
            List <AsmPatch> result     = new List <AsmPatch>(patchNodes.Count);

            Context context       = (asmUtility.EncodingMode == ASMEncodingMode.PSP) ? Context.US_PSP : Context.US_PSX;
            Type    sectorType    = ISOHelper.GetSectorType(context);
            Enum    defaultSector = ISOHelper.GetSector(0, context);

            foreach (XmlNode node in patchNodes)
            {
                XmlAttribute ignoreNode = node.Attributes["ignore"];
                if (ignoreNode != null && Boolean.Parse(ignoreNode.InnerText))
                {
                    continue;
                }

                bool hasDefaultSector = false;

                //PsxIso.Sectors defaultSector = (PsxIso.Sectors)0;
                //Enum defaultSector = (Enum)Enum.ToObject(sectorType, 0);
                XmlAttribute attrDefaultFile   = node.Attributes["file"];
                XmlAttribute attrDefaultSector = node.Attributes["sector"];

                if (attrDefaultFile != null)
                {
                    //defaultSector = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), attrDefaultFile.InnerText);
                    //defaultSector = (Enum)Enum.Parse(sectorType, attrDefaultFile.InnerText);
                    defaultSector    = ISOHelper.GetSector(attrDefaultFile.InnerText, context);
                    hasDefaultSector = true;
                }
                else if (attrDefaultSector != null)
                {
                    //defaultSector = (PsxIso.Sectors)Int32.Parse(attrDefaultSector.InnerText, System.Globalization.NumberStyles.HexNumber);
                    //defaultSector = (Enum)Enum.ToObject(sectorType, Int32.Parse(attrDefaultSector.InnerText, System.Globalization.NumberStyles.HexNumber));
                    defaultSector    = ISOHelper.GetSectorHex(attrDefaultSector.InnerText, context);
                    hasDefaultSector = true;
                }

                StringBuilder sbPatchErrorText = new StringBuilder();

                List <VariableType>     variables      = new List <VariableType>();
                List <PatchedByteArray> includePatches = new List <PatchedByteArray>();

                XmlNodeList includeNodes = node.SelectNodes("Include");
                foreach (XmlNode includeNode in includeNodes)
                {
                    XmlAttribute attrPatch = includeNode.Attributes["patch"];
                    if (attrPatch != null)
                    {
                        string patchName       = attrPatch.InnerText.ToLower().Trim();
                        int    foundPatchCount = 0;

                        foreach (AsmPatch currentAsmPatch in result)
                        {
                            if (currentAsmPatch.Name.ToLower().Trim().Equals(patchName))
                            {
                                foreach (VariableType variable in currentAsmPatch.Variables)
                                {
                                    variables.Add(variable.Copy());
                                }
                                for (int index = 0; index < currentAsmPatch.NonVariableCount; index++)
                                {
                                    includePatches.Add(currentAsmPatch[index].Copy());
                                }
                                foundPatchCount++;
                            }
                        }

                        if (foundPatchCount == 0)
                        {
                            sbPatchErrorText.AppendLine("Error in patch XML: Missing dependent patch \"" + attrPatch.InnerText + "\"!");
                        }
                    }
                }

                foreach (XmlNode varNode in node.SelectNodes("Variable"))
                {
                    XmlAttribute numBytesAttr = varNode.Attributes["bytes"];
                    string       strNumBytes  = (numBytesAttr == null) ? "1" : numBytesAttr.InnerText;
                    byte         numBytes     = (byte)(UInt32.Parse(strNumBytes) & 0xff);

                    string varName = varNode.Attributes["name"].InnerText;

                    XmlAttribute fileAttribute   = varNode.Attributes["file"];
                    XmlAttribute sectorAttribute = varNode.Attributes["sector"];
                    XmlAttribute attrSpecific    = varNode.Attributes["specific"];
                    XmlAttribute attrAlign       = varNode.Attributes["align"];

                    //PsxIso.Sectors varSec = (PsxIso.Sectors)Enum.Parse( typeof( PsxIso.Sectors ), varNode.Attributes["file"].InnerText );
                    //UInt32 varOffset = UInt32.Parse( varNode.Attributes["offset"].InnerText, System.Globalization.NumberStyles.HexNumber );
                    //string strOffsetAttr = varNode.Attributes["offset"].InnerText;
                    XmlAttribute offsetAttribute  = varNode.Attributes["offset"];
                    string       strOffsetAttr    = (offsetAttribute != null) ? offsetAttribute.InnerText : "";
                    string[]     strOffsets       = strOffsetAttr.Replace(" ", "").Split(',');
                    bool         ignoreOffsetMode = false;
                    bool         isSpecific       = false;

                    List <SpecificLocation> specifics = FillSpecificAttributeData(attrSpecific, defaultSector);

                    int align = 0;
                    if (attrAlign != null)
                    {
                        Int32.TryParse(sectorAttribute.InnerText, out align);

                        if (align < 0)
                        {
                            align = 0;
                        }
                    }

                    XmlAttribute symbolAttribute = varNode.Attributes["symbol"];
                    bool         isSymbol        = (symbolAttribute != null) && PatcherLib.Utilities.Utilities.ParseBool(symbolAttribute.InnerText);

                    if (isSymbol)
                    {
                        strOffsets = new string[0];
                    }
                    else if (specifics.Count > 0)
                    {
                        isSpecific = true;
                        List <string> newStrOffsets = new List <string>(specifics.Count);
                        foreach (SpecificLocation specific in specifics)
                        {
                            newStrOffsets.Add(specific.OffsetString);
                        }
                        strOffsets = newStrOffsets.ToArray();
                    }
                    else if ((string.IsNullOrEmpty(strOffsetAttr)) && (variables.Count > 0) && (variables[variables.Count - 1].Content.Count > 0))
                    {
                        // No offset defined -- offset is (last patch offset) + (last patch size)
                        int lastIndex = variables[variables.Count - 1].Content.Count - 1;
                        PatchedByteArray lastPatchedByteArray = variables[variables.Count - 1].Content[lastIndex];
                        long             offset    = lastPatchedByteArray.Offset + lastPatchedByteArray.GetBytes().Length;
                        string           strOffset = offset.ToString("X");
                        strOffsets = new string[1] {
                            strOffset
                        };
                        ignoreOffsetMode = true;

                        // Advance offset to match up with alignment, if necessary
                        if (align > 0)
                        {
                            int offsetAlign = (int)(offset % align);
                            if (offsetAlign > 0)
                            {
                                offset += (align - offsetAlign);
                            }
                        }
                    }

                    //PsxIso.Sectors sector = (PsxIso.Sectors)0;
                    Enum sector = ISOHelper.GetSector(0, context); // (Enum)Enum.ToObject(sectorType, 0);
                    if (isSpecific)
                    {
                        sector = specifics[0].Sector;
                    }
                    else if (fileAttribute != null)
                    {
                        //sector = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), fileAttribute.InnerText);
                        //sector = (Enum)Enum.Parse(sectorType, fileAttribute.InnerText);
                        sector = ISOHelper.GetSector(fileAttribute.InnerText, context);
                    }
                    else if (sectorAttribute != null)
                    {
                        //sector = (PsxIso.Sectors)Int32.Parse(sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber);
                        //sector = (Enum)Enum.ToObject(sectorType, Int32.Parse(sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber));
                        sector = ISOHelper.GetSectorHex(sectorAttribute.InnerText, context);
                    }
                    else if (hasDefaultSector)
                    {
                        sector = defaultSector;
                    }
                    else if ((variables.Count > 0) && (variables[variables.Count - 1].Content.Count > 0))
                    {
                        int lastIndex = variables[variables.Count - 1].Content.Count - 1;
                        //sector = (PsxIso.Sectors)(variables[variables.Count - 1].Content[lastIndex].Sector);
                        //sector = (Enum)Enum.ToObject(sectorType, variables[variables.Count - 1].Content[lastIndex].Sector);
                        sector = variables[variables.Count - 1].Content[lastIndex].SectorEnum;
                    }
                    else if (!isSymbol)
                    {
                        sbPatchErrorText.AppendLine("Error in patch XML: Invalid file/sector!");
                    }

                    XmlAttribute offsetModeAttribute = varNode.Attributes["offsetMode"];
                    bool         isRamOffset         = false;
                    if ((!ignoreOffsetMode) && (offsetModeAttribute != null))
                    {
                        if (offsetModeAttribute.InnerText.ToLower().Trim() == "ram")
                        {
                            isRamOffset = true;
                        }
                    }

                    int ftrOffset = ISOHelper.GetFileToRamOffset(sector, context);

                    XmlAttribute defaultAttr = varNode.Attributes["default"];
                    Byte[]       byteArray   = new Byte[numBytes];
                    UInt32       def         = 0;
                    if (defaultAttr != null)
                    {
                        def = UInt32.Parse(defaultAttr.InnerText, System.Globalization.NumberStyles.HexNumber);
                        for (int i = 0; i < numBytes; i++)
                        {
                            byteArray[i] = (Byte)((def >> (i * 8)) & 0xff);
                        }
                    }

                    List <PatchedByteArray> patchedByteArrayList = new List <PatchedByteArray>();
                    int offsetIndex = 0;

                    foreach (string strOffset in strOffsets)
                    {
                        UInt32 offset = UInt32.Parse(strOffset, System.Globalization.NumberStyles.HexNumber);
                        //UInt32 ramOffset = offset;
                        UInt32 fileOffset = offset;

                        if (ftrOffset >= 0)
                        {
                            try
                            {
                                if (isRamOffset)
                                {
                                    fileOffset -= (UInt32)ftrOffset;
                                }
                                //else
                                //    ramOffset += (UInt32)ftrOffset;
                            }
                            catch (Exception) { }
                        }

                        //ramOffset = ramOffset | PsxIso.KSeg0Mask;     // KSEG0

                        patchedByteArrayList.Add(new PatchedByteArray(sector, fileOffset, byteArray));

                        offsetIndex++;
                        if (offsetIndex < strOffsets.Length)
                        {
                            if (isSpecific)
                            {
                                sector    = specifics[offsetIndex].Sector;
                                ftrOffset = ISOHelper.GetFileToRamOffset(sector, context);
                            }
                        }
                    }

                    bool   isReference             = false;
                    string referenceName           = "";
                    string referenceOperatorSymbol = "";
                    uint   referenceOperand        = 0;

                    XmlAttribute attrReference = varNode.Attributes["reference"];
                    XmlAttribute attrOperator  = varNode.Attributes["operator"];
                    XmlAttribute attrOperand   = varNode.Attributes["operand"];

                    if (attrReference != null)
                    {
                        isReference             = true;
                        referenceName           = attrReference.InnerText;
                        referenceOperatorSymbol = (attrOperator != null) ? attrOperator.InnerText : "";
                        if (attrOperand != null)
                        {
                            //UInt32.Parse(defaultAttr.InnerText, System.Globalization.NumberStyles.HexNumber);
                            uint.TryParse(attrOperand.InnerText, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out referenceOperand);
                        }
                    }

                    List <VariableType.VariablePreset> presetValueList = new List <VariableType.VariablePreset>();
                    XmlNodeList presetNodeList = varNode.SelectNodes("Preset");

                    string       presetKey  = null;
                    XmlAttribute attrPreset = varNode.Attributes["preset"];
                    if (attrPreset != null)
                    {
                        presetKey = attrPreset.InnerText;
                        if (!string.IsNullOrEmpty(presetKey))
                        {
                            presetValueList = VariableType.VariablePreset.TypeMap[presetKey];
                        }
                    }
                    else if (presetNodeList != null)
                    {
                        foreach (XmlNode presetNode in presetNodeList)
                        {
                            XmlAttribute attrName   = presetNode.Attributes["name"];
                            XmlAttribute attrValue  = presetNode.Attributes["value"];
                            XmlAttribute attrModify = presetNode.Attributes["modify"];
                            UInt32       value      = 0;

                            byte[] valueBytes = new Byte[numBytes];
                            if (attrValue != null)
                            {
                                UInt32.TryParse(attrValue.InnerText, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out value);
                                for (int i = 0; i < numBytes; i++)
                                {
                                    valueBytes[i] = (byte)((value >> (i * 8)) & 0xff);
                                }
                            }

                            bool isModifiable = false;
                            if (attrModify != null)
                            {
                                bool.TryParse(attrModify.InnerText, out isModifiable);
                            }

                            presetValueList.Add(new VariableType.VariablePreset(attrName.InnerText, value, valueBytes, isModifiable));
                        }
                    }

                    VariableType vType = new VariableType();
                    vType.NumBytes                 = numBytes;
                    vType.ByteArray                = byteArray;
                    vType.Name                     = varName;
                    vType.Content                  = patchedByteArrayList;
                    vType.IsReference              = isReference;
                    vType.Reference                = new VariableReference();
                    vType.Reference.Name           = referenceName;
                    vType.Reference.OperatorSymbol = referenceOperatorSymbol;
                    vType.Reference.Operand        = referenceOperand;
                    vType.PresetValues             = presetValueList;

                    variables.Add(vType);
                }

                GetPatchResult getPatchResult = GetPatch(node, xmlFilename, asmUtility, variables);

                List <PatchedByteArray> patches = new List <PatchedByteArray>(includePatches.Count + getPatchResult.StaticPatches.Count);
                patches.AddRange(includePatches);
                patches.AddRange(getPatchResult.StaticPatches);

                AsmPatch asmPatch = new AsmPatch(getPatchResult.Name, shortXmlFilename, getPatchResult.Description, patches,
                                                 (getPatchResult.HideInDefault | rootHideInDefault), (getPatchResult.IsHidden | rootIsHidden), variables);

                asmPatch.ErrorText = sbPatchErrorText.ToString() + getPatchResult.ErrorText;
                //asmPatch.Update(asmUtility);

                result.Add(asmPatch);
            }

            patchNodes = rootNode.SelectNodes("ImportFilePatch");
            foreach (XmlNode node in patchNodes)
            {
                KeyValuePair <string, string> nameDesc = GetPatchNameAndDescription(node);

                string name        = nameDesc.Key;
                string description = nameDesc.Value;

                XmlNodeList fileNodes = node.SelectNodes("ImportFile");
                if (fileNodes.Count != 1)
                {
                    continue;
                }

                XmlNode theRealNode = fileNodes[0];

                //PsxIso.Sectors sector = (PsxIso.Sectors)Enum.Parse( typeof( PsxIso.Sectors ), theRealNode.Attributes["file"].InnerText );
                Enum   sector         = (Enum)Enum.Parse(sectorType, theRealNode.Attributes["file"].InnerText);
                UInt32 offset         = UInt32.Parse(theRealNode.Attributes["offset"].InnerText, System.Globalization.NumberStyles.HexNumber);
                UInt32 expectedLength = UInt32.Parse(theRealNode.Attributes["expectedLength"].InnerText, System.Globalization.NumberStyles.HexNumber);

                result.Add(new FileAsmPatch(name, shortXmlFilename, description, new InputFilePatch(sector, offset, expectedLength)));
            }

            return(result.AsReadOnly());
        }
Example #28
0
        private static GetPatchResult GetPatch(XmlNode node, string xmlFileName, ASMEncodingUtility asmUtility, List <VariableType> variables)
        {
            KeyValuePair <string, string> nameDesc = GetPatchNameAndDescription(node);

            bool         hideInDefault     = false;
            XmlAttribute attrHideInDefault = node.Attributes["hideInDefault"];

            if (attrHideInDefault != null)
            {
                if (attrHideInDefault.InnerText.ToLower().Trim() == "true")
                {
                    hideInDefault = true;
                }
            }

            bool         isHidden     = false;
            XmlAttribute attrIsHidden = node.Attributes["hidden"];

            if (attrIsHidden != null)
            {
                if (attrIsHidden.InnerText.ToLower().Trim() == "true")
                {
                    isHidden = true;
                }
            }

            bool hasDefaultSector = false;
            //PsxIso.Sectors defaultSector = (PsxIso.Sectors)0;
            Context context    = (asmUtility.EncodingMode == ASMEncodingMode.PSP) ? Context.US_PSP : Context.US_PSX;
            Type    sectorType = ISOHelper.GetSectorType(context);

            Enum         defaultSector     = ISOHelper.GetSector(0, context); // (Enum)Enum.ToObject(sectorType, 0);
            XmlAttribute attrDefaultFile   = node.Attributes["file"];
            XmlAttribute attrDefaultSector = node.Attributes["sector"];

            if (attrDefaultFile != null)
            {
                //defaultSector = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), attrDefaultFile.InnerText);
                //defaultSector = (Enum)Enum.Parse(sectorType, attrDefaultFile.InnerText);
                defaultSector    = ISOHelper.GetSector(attrDefaultFile.InnerText, context);
                hasDefaultSector = true;
            }
            else if (attrDefaultSector != null)
            {
                //defaultSector = (PsxIso.Sectors)Int32.Parse(attrDefaultSector.InnerText, System.Globalization.NumberStyles.HexNumber);
                defaultSector    = ISOHelper.GetSectorHex(attrDefaultSector.InnerText, context);
                hasDefaultSector = true;
            }

            XmlNodeList             currentLocs      = node.SelectNodes("Location");
            List <PatchedByteArray> patches          = new List <PatchedByteArray>(currentLocs.Count);
            StringBuilder           sbOuterErrorText = new StringBuilder();

            Dictionary <PatchedByteArray, string> replaceLabelsContentMap = new Dictionary <PatchedByteArray, string>();

            foreach (XmlNode location in currentLocs)
            {
                //UInt32 offset = UInt32.Parse( location.Attributes["offset"].InnerText, System.Globalization.NumberStyles.HexNumber );
                XmlAttribute offsetAttribute        = location.Attributes["offset"];
                XmlAttribute fileAttribute          = location.Attributes["file"];
                XmlAttribute sectorAttribute        = location.Attributes["sector"];
                XmlAttribute modeAttribute          = location.Attributes["mode"];
                XmlAttribute offsetModeAttribute    = location.Attributes["offsetMode"];
                XmlAttribute inputFileAttribute     = location.Attributes["inputFile"];
                XmlAttribute replaceLabelsAttribute = location.Attributes["replaceLabels"];
                XmlAttribute attrLabel    = location.Attributes["label"];
                XmlAttribute attrSpecific = location.Attributes["specific"];
                XmlAttribute attrMovable  = location.Attributes["movable"];
                XmlAttribute attrAlign    = location.Attributes["align"];
                XmlAttribute attrStatic   = location.Attributes["static"];

                string   strOffsetAttr      = (offsetAttribute != null) ? offsetAttribute.InnerText : "";
                string[] strOffsets         = strOffsetAttr.Replace(" ", "").Split(',');
                bool     ignoreOffsetMode   = false;
                bool     isSpecific         = false;
                bool     isSequentialOffset = false;

                List <SpecificLocation> specifics = FillSpecificAttributeData(attrSpecific, defaultSector);

                bool isAsmMode    = false;
                bool markedAsData = false;
                if (modeAttribute != null)
                {
                    string modeAttributeText = modeAttribute.InnerText.ToLower().Trim();
                    if (modeAttributeText == "asm")
                    {
                        isAsmMode = true;
                    }
                    else if (modeAttributeText == "data")
                    {
                        markedAsData = true;
                    }
                }

                int align = 0;
                if (attrAlign != null)
                {
                    Int32.TryParse(sectorAttribute.InnerText, out align);

                    if (align < 0)
                    {
                        align = 0;
                    }
                }
                else if (isAsmMode)
                {
                    align = 4;
                }

                if (specifics.Count > 0)
                {
                    isSpecific = true;
                    List <string> newStrOffsets = new List <string>(specifics.Count);
                    foreach (SpecificLocation specific in specifics)
                    {
                        newStrOffsets.Add(specific.OffsetString);
                    }
                    strOffsets = newStrOffsets.ToArray();
                }
                else if ((string.IsNullOrEmpty(strOffsetAttr)) && (patches.Count > 0))
                {
                    // No offset defined -- offset is (last patch offset) + (last patch size)
                    PatchedByteArray lastPatchedByteArray = patches[patches.Count - 1];
                    long             offset = lastPatchedByteArray.Offset + lastPatchedByteArray.GetBytes().Length;
                    ignoreOffsetMode   = true;
                    isSequentialOffset = true;

                    // Advance offset to match up with alignment, if necessary
                    if (align > 0)
                    {
                        int offsetAlign = (int)(offset % align);
                        if (offsetAlign > 0)
                        {
                            offset            += (align - offsetAlign);
                            isSequentialOffset = false;
                        }
                    }

                    string strOffset = offset.ToString("X");
                    strOffsets = new string[1] {
                        strOffset
                    };
                }

                //PsxIso.Sectors sector = (PsxIso.Sectors)0;
                Enum sector = ISOHelper.GetSector(0, context); // (Enum)Enum.ToObject(sectorType, 0);
                if (isSpecific)
                {
                    sector = specifics[0].Sector;
                }
                else if (fileAttribute != null)
                {
                    //sector = (PsxIso.Sectors)Enum.Parse( typeof( PsxIso.Sectors ), fileAttribute.InnerText );
                    //sector = (Enum)Enum.Parse( sectorType, fileAttribute.InnerText );
                    sector = ISOHelper.GetSector(fileAttribute.InnerText, context);
                }
                else if (sectorAttribute != null)
                {
                    //sector = (PsxIso.Sectors)Int32.Parse( sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber );
                    //sector = (Enum)Enum.ToObject(sectorType, Int32.Parse(sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber));
                    sector = ISOHelper.GetSectorHex(sectorAttribute.InnerText, context);
                }
                else if (hasDefaultSector)
                {
                    sector = defaultSector;
                }
                else if (patches.Count > 0)
                {
                    //sector = (PsxIso.Sectors)(patches[patches.Count - 1].Sector);
                    //sector = (Enum)Enum.ToObject(sectorType, patches[patches.Count - 1].Sector);
                    sector = patches[patches.Count - 1].SectorEnum;
                }
                else
                {
                    sbOuterErrorText.AppendLine("Error in patch XML: Invalid file/sector!");
                }

                bool isRamOffset = false;
                if ((!ignoreOffsetMode) && (offsetModeAttribute != null))
                {
                    if (offsetModeAttribute.InnerText.ToLower().Trim() == "ram")
                    {
                        isRamOffset = true;
                    }
                }

                string content = location.InnerText;
                if (inputFileAttribute != null)
                {
                    try
                    {
                        string   strMode  = Enum.GetName(typeof(ASMEncodingMode), asmUtility.EncodingMode);
                        string   readPath = Path.Combine("Include", inputFileAttribute.InnerText);
                        FileInfo fileInfo = new FileInfo(xmlFileName);
                        readPath = Path.Combine(fileInfo.DirectoryName, readPath);
                        using (StreamReader streamReader = new StreamReader(readPath, Encoding.UTF8))
                        {
                            content = streamReader.ReadToEnd();
                        }
                    }
                    catch (Exception)
                    {
                        string readPath = inputFileAttribute.InnerText;
                        using (StreamReader streamReader = new StreamReader(readPath, Encoding.UTF8))
                        {
                            content = streamReader.ReadToEnd();
                        }
                    }
                }

                bool replaceLabels = false;
                if (replaceLabelsAttribute != null)
                {
                    if (replaceLabelsAttribute.InnerText.ToLower().Trim() == "true")
                    {
                        replaceLabels = true;
                    }
                }
                if (replaceLabels)
                {
                    StringBuilder sbLabels = new StringBuilder();
                    foreach (PatchedByteArray currentPatchedByteArray in patches)
                    {
                        if (!string.IsNullOrEmpty(currentPatchedByteArray.Label))
                        {
                            sbLabels.Append(String.Format(".label @{0}, {1}{2}", currentPatchedByteArray.Label, currentPatchedByteArray.RamOffset, Environment.NewLine));
                        }
                    }
                    asmUtility.EncodeASM(sbLabels.ToString(), 0);
                    content = asmUtility.ReplaceLabelsInHex(content, true, true);
                }

                string label = "";
                if (attrLabel != null)
                {
                    label = attrLabel.InnerText.Replace(" ", "");
                }

                bool isMoveSimple = isAsmMode;
                if (attrMovable != null)
                {
                    bool.TryParse(attrMovable.InnerText, out isMoveSimple);
                }

                bool isStatic = false;
                if (attrStatic != null)
                {
                    bool.TryParse(attrStatic.InnerText, out isStatic);
                }

                int ftrOffset = ISOHelper.GetFileToRamOffset(sector, context);

                int offsetIndex = 0;
                foreach (string strOffset in strOffsets)
                {
                    UInt32 offset = UInt32.Parse(strOffset, System.Globalization.NumberStyles.HexNumber);

                    UInt32 ramOffset  = offset;
                    UInt32 fileOffset = offset;

                    if (ftrOffset >= 0)
                    {
                        try
                        {
                            if (isRamOffset)
                            {
                                fileOffset -= (UInt32)ftrOffset;
                            }
                            else
                            {
                                ramOffset += (UInt32)ftrOffset;
                            }
                        }
                        catch (Exception) { }
                    }

                    if (context == Context.US_PSX)
                    {
                        ramOffset = ramOffset | PsxIso.KSeg0Mask;
                    }

                    byte[] bytes;
                    string errorText = "";
                    if (isAsmMode)
                    {
                        string encodeContent = content;

                        StringBuilder sbPrefix = new StringBuilder();
                        foreach (PatchedByteArray currentPatchedByteArray in patches)
                        {
                            if (!string.IsNullOrEmpty(currentPatchedByteArray.Label))
                            {
                                sbPrefix.Append(String.Format(".label @{0}, {1}{2}", currentPatchedByteArray.Label, currentPatchedByteArray.RamOffset, Environment.NewLine));
                            }
                        }
                        foreach (VariableType variable in variables)
                        {
                            sbPrefix.Append(String.Format(".eqv %{0}, {1}{2}", ASMStringHelper.RemoveSpaces(variable.Name).Replace(",", ""),
                                                          PatcherLib.Utilities.Utilities.GetUnsignedByteArrayValue_LittleEndian(variable.ByteArray), Environment.NewLine));
                        }

                        encodeContent = sbPrefix.ToString() + content;

                        ASMEncoderResult result = asmUtility.EncodeASM(encodeContent, ramOffset, true);
                        bytes     = result.EncodedBytes;
                        errorText = result.ErrorText;
                    }
                    else
                    {
                        AsmPatch.GetBytesResult result = AsmPatch.GetBytes(content, ramOffset, variables);
                        bytes     = result.Bytes;
                        errorText = result.ErrorMessage;
                    }

                    /*
                     * bool isCheckedAsm = false;
                     * if (!markedAsData)
                     * {
                     *  ASMCheckResult checkResult = asmUtility.CheckASMFromBytes(bytes, ramOffset, true, false, new HashSet<ASMCheckCondition>() {
                     *      ASMCheckCondition.LoadDelay,
                     *      ASMCheckCondition.UnalignedOffset,
                     *      ASMCheckCondition.MultCountdown,
                     *      ASMCheckCondition.StackPointerOffset4,
                     *      ASMCheckCondition.BranchInBranchDelaySlot
                     *  });
                     *
                     *  if (checkResult.IsASM)
                     *  {
                     *      isCheckedAsm = true;
                     *      if (!string.IsNullOrEmpty(checkResult.ErrorText))
                     *      {
                     *          errorText += checkResult.ErrorText;
                     *      }
                     *  }
                     * }
                     */

                    //if (!string.IsNullOrEmpty(errorText))
                    //    sbOuterErrorText.Append(errorText);

                    PatchedByteArray patchedByteArray = new PatchedByteArray(sector, fileOffset, bytes);
                    patchedByteArray.IsAsm              = isAsmMode;
                    patchedByteArray.MarkedAsData       = markedAsData;
                    patchedByteArray.IsCheckedAsm       = false; // isCheckedAsm;
                    patchedByteArray.IsSequentialOffset = isSequentialOffset;
                    patchedByteArray.IsMoveSimple       = isMoveSimple;
                    //patchedByteArray.AsmText = isAsmMode ? content : "";
                    patchedByteArray.Text      = content;
                    patchedByteArray.RamOffset = ramOffset;
                    patchedByteArray.ErrorText = errorText;
                    patchedByteArray.Label     = label;
                    patchedByteArray.IsStatic  = isStatic;

                    if (replaceLabels)
                    {
                        replaceLabelsContentMap.Add(patchedByteArray, content);
                    }

                    patches.Add(patchedByteArray);

                    offsetIndex++;
                    if (offsetIndex < strOffsets.Length)
                    {
                        if (isSpecific)
                        {
                            sector    = specifics[offsetIndex].Sector;
                            ftrOffset = ISOHelper.GetFileToRamOffset(sector, context);
                        }
                    }
                }
            }

            StringBuilder sbEncodePrefix = new StringBuilder();

            foreach (PatchedByteArray currentPatchedByteArray in patches)
            {
                if (!string.IsNullOrEmpty(currentPatchedByteArray.Label))
                {
                    sbEncodePrefix.Append(String.Format(".label @{0}, {1}{2}", currentPatchedByteArray.Label, currentPatchedByteArray.RamOffset, Environment.NewLine));
                }
            }
            foreach (VariableType variable in variables)
            {
                sbEncodePrefix.Append(String.Format(".eqv %{0}, {1}{2}", ASMStringHelper.RemoveSpaces(variable.Name).Replace(",", ""),
                                                    PatcherLib.Utilities.Utilities.GetUnsignedByteArrayValue_LittleEndian(variable.ByteArray), Environment.NewLine));
            }
            string strEncodePrefix = sbEncodePrefix.ToString();

            asmUtility.EncodeASM(strEncodePrefix, 0);

            foreach (PatchedByteArray patchedByteArray in patches)
            {
                string errorText = string.Empty;

                string replaceLabelsContent;
                if (replaceLabelsContentMap.TryGetValue(patchedByteArray, out replaceLabelsContent))
                {
                    if (!string.IsNullOrEmpty(replaceLabelsContent))
                    {
                        AsmPatch.GetBytesResult result = AsmPatch.GetBytes(asmUtility.ReplaceLabelsInHex(replaceLabelsContent, true, false), (uint)patchedByteArray.RamOffset, variables);
                        patchedByteArray.SetBytes(result.Bytes);
                        errorText += result.ErrorMessage;
                    }
                }

                if (patchedByteArray.IsAsm)
                {
                    string           encodeContent = strEncodePrefix + patchedByteArray.Text;
                    ASMEncoderResult result        = asmUtility.EncodeASM(encodeContent, (uint)patchedByteArray.RamOffset);
                    patchedByteArray.SetBytes(result.EncodedBytes);
                    errorText += result.ErrorText;
                }

                if (!patchedByteArray.MarkedAsData)
                {
                    HashSet <ASMCheckCondition> checkConditions = new HashSet <ASMCheckCondition>()
                    {
                        ASMCheckCondition.LoadDelay,
                        ASMCheckCondition.UnalignedOffset,
                        ASMCheckCondition.MultCountdown,
                        ASMCheckCondition.StackPointerOffset4,
                        ASMCheckCondition.BranchInBranchDelaySlot
                    };

                    if (asmUtility.EncodingMode == ASMEncodingMode.PSP)
                    {
                        checkConditions.Remove(ASMCheckCondition.LoadDelay);
                    }

                    ASMCheckResult checkResult = asmUtility.CheckASMFromBytes(patchedByteArray.GetBytes(), (uint)patchedByteArray.RamOffset, true, false, checkConditions);

                    if (checkResult.IsASM)
                    {
                        patchedByteArray.IsCheckedAsm = true;
                        if (!string.IsNullOrEmpty(checkResult.ErrorText))
                        {
                            errorText += checkResult.ErrorText;
                        }
                    }
                }

                if (!string.IsNullOrEmpty(errorText))
                {
                    sbOuterErrorText.Append(errorText);
                }
            }

            currentLocs = node.SelectNodes("STRLocation");
            foreach (XmlNode location in currentLocs)
            {
                XmlAttribute fileAttribute   = location.Attributes["file"];
                XmlAttribute sectorAttribute = location.Attributes["sector"];

                //PsxIso.Sectors sector = (PsxIso.Sectors)0;
                Enum sector = ISOHelper.GetSector(0, context); // (Enum)Enum.ToObject(sectorType, 0);

                if (fileAttribute != null)
                {
                    //sector = (PsxIso.Sectors)Enum.Parse( typeof( PsxIso.Sectors ), fileAttribute.InnerText );
                    //sector = (Enum)Enum.Parse(sectorType, fileAttribute.InnerText);
                    sector = ISOHelper.GetSector(fileAttribute.InnerText, context);
                }
                else if (sectorAttribute != null)
                {
                    //sector = (PsxIso.Sectors)Int32.Parse( sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber );
                    //sector = (Enum)Enum.ToObject(sectorType, Int32.Parse(sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber));
                    sector = ISOHelper.GetSectorHex(sectorAttribute.InnerText, context);
                }
                else
                {
                    throw new Exception();
                }

                string filename = location.Attributes["input"].InnerText;
                filename = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(xmlFileName), filename);

                patches.Add(new STRPatchedByteArray(sector, filename));
            }

            return(new GetPatchResult(nameDesc.Key, nameDesc.Value, patches.AsReadOnly(), hideInDefault, isHidden, sbOuterErrorText.ToString()));
        }
        public static IList <AsmPatch> GetPatches(XmlNode rootNode, string xmlFilename, ASMEncodingUtility asmUtility)
        {
            bool         rootHideInDefault = false;
            XmlAttribute attrHideInDefault = rootNode.Attributes["hideInDefault"];

            if (attrHideInDefault != null)
            {
                rootHideInDefault = (attrHideInDefault.InnerText.ToLower().Trim() == "true");
            }

            string shortXmlFilename = xmlFilename.Substring(xmlFilename.LastIndexOf("\\") + 1);

            XmlNodeList     patchNodes = rootNode.SelectNodes("Patch");
            List <AsmPatch> result     = new List <AsmPatch>(patchNodes.Count);

            foreach (XmlNode node in patchNodes)
            {
                XmlAttribute ignoreNode = node.Attributes["ignore"];
                if (ignoreNode != null && Boolean.Parse(ignoreNode.InnerText))
                {
                    continue;
                }

                bool           hasDefaultSector  = false;
                PsxIso.Sectors defaultSector     = (PsxIso.Sectors) 0;
                XmlAttribute   attrDefaultFile   = node.Attributes["file"];
                XmlAttribute   attrDefaultSector = node.Attributes["sector"];

                if (attrDefaultFile != null)
                {
                    defaultSector    = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), attrDefaultFile.InnerText);
                    hasDefaultSector = true;
                }
                else if (attrDefaultSector != null)
                {
                    defaultSector    = (PsxIso.Sectors)Int32.Parse(attrDefaultSector.InnerText, System.Globalization.NumberStyles.HexNumber);
                    hasDefaultSector = true;
                }

                List <VariableType>     variables      = new List <VariableType>();
                List <PatchedByteArray> includePatches = new List <PatchedByteArray>();

                XmlNodeList includeNodes = node.SelectNodes("Include");
                foreach (XmlNode includeNode in includeNodes)
                {
                    XmlAttribute attrPatch = includeNode.Attributes["patch"];
                    if (attrPatch != null)
                    {
                        string patchName = attrPatch.InnerText.ToLower().Trim();
                        foreach (AsmPatch currentAsmPatch in result)
                        {
                            if (currentAsmPatch.Name.ToLower().Trim().Equals(patchName))
                            {
                                foreach (VariableType variable in currentAsmPatch.Variables)
                                {
                                    variables.Add(AsmPatch.CopyVariable(variable));
                                }
                                for (int index = 0; index < currentAsmPatch.NonVariableCount; index++)
                                {
                                    includePatches.Add(currentAsmPatch[index].Copy());
                                }
                            }
                        }
                    }
                }

                foreach (XmlNode varNode in node.SelectNodes("Variable"))
                {
                    XmlAttribute numBytesAttr = varNode.Attributes["bytes"];
                    string       strNumBytes  = (numBytesAttr == null) ? "1" : numBytesAttr.InnerText;
                    byte         numBytes     = (byte)(UInt32.Parse(strNumBytes) & 0xff);

                    string varName = varNode.Attributes["name"].InnerText;

                    XmlAttribute fileAttribute   = varNode.Attributes["file"];
                    XmlAttribute sectorAttribute = varNode.Attributes["sector"];
                    XmlAttribute attrSpecific    = varNode.Attributes["specific"];

                    //PsxIso.Sectors varSec = (PsxIso.Sectors)Enum.Parse( typeof( PsxIso.Sectors ), varNode.Attributes["file"].InnerText );
                    //UInt32 varOffset = UInt32.Parse( varNode.Attributes["offset"].InnerText, System.Globalization.NumberStyles.HexNumber );
                    //string strOffsetAttr = varNode.Attributes["offset"].InnerText;
                    XmlAttribute offsetAttribute  = varNode.Attributes["offset"];
                    string       strOffsetAttr    = (offsetAttribute != null) ? offsetAttribute.InnerText : "";
                    string[]     strOffsets       = strOffsetAttr.Replace(" ", "").Split(',');
                    bool         ignoreOffsetMode = false;
                    bool         isSpecific       = false;

                    List <SpecificLocation> specifics = FillSpecificAttributeData(attrSpecific, defaultSector);

                    if (specifics.Count > 0)
                    {
                        isSpecific = true;
                        List <string> newStrOffsets = new List <string>(specifics.Count);
                        foreach (SpecificLocation specific in specifics)
                        {
                            newStrOffsets.Add(specific.OffsetString);
                        }
                        strOffsets = newStrOffsets.ToArray();
                    }
                    else if ((string.IsNullOrEmpty(strOffsetAttr)) && (variables.Count > 0) && (variables[variables.Count - 1].content.Count > 0))
                    {
                        // No offset defined -- offset is (last patch offset) + (last patch size)
                        int lastIndex = variables[variables.Count - 1].content.Count - 1;
                        PatchedByteArray lastPatchedByteArray = variables[variables.Count - 1].content[lastIndex];
                        long             offset    = lastPatchedByteArray.Offset + lastPatchedByteArray.GetBytes().Length;
                        string           strOffset = offset.ToString("X");
                        strOffsets = new string[1] {
                            strOffset
                        };
                        ignoreOffsetMode = true;
                    }

                    PsxIso.Sectors sector = (PsxIso.Sectors) 0;
                    if (isSpecific)
                    {
                        sector = specifics[0].Sector;
                    }
                    else if (fileAttribute != null)
                    {
                        sector = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), fileAttribute.InnerText);
                    }
                    else if (sectorAttribute != null)
                    {
                        sector = (PsxIso.Sectors)Int32.Parse(sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber);
                    }
                    else if (hasDefaultSector)
                    {
                        sector = defaultSector;
                    }
                    else if ((variables.Count > 0) && (variables[variables.Count - 1].content.Count > 0))
                    {
                        int lastIndex = variables[variables.Count - 1].content.Count - 1;
                        sector = (PsxIso.Sectors)(variables[variables.Count - 1].content[lastIndex].Sector);
                    }
                    else
                    {
                        throw new Exception("Error in patch XML: Invalid file/sector!");
                    }

                    XmlAttribute offsetModeAttribute = varNode.Attributes["offsetMode"];
                    bool         isRamOffset         = false;
                    if ((!ignoreOffsetMode) && (offsetModeAttribute != null))
                    {
                        if (offsetModeAttribute.InnerText.ToLower().Trim() == "ram")
                        {
                            isRamOffset = true;
                        }
                    }

                    Nullable <PsxIso.FileToRamOffsets> ftrOffset = null;
                    try
                    {
                        ftrOffset = (PsxIso.FileToRamOffsets)Enum.Parse(typeof(PsxIso.FileToRamOffsets), "OFFSET_" + Enum.GetName(typeof(PsxIso.Sectors), sector));
                        //ftrOffset = (PsxIso.FileToRamOffsets)Enum.Parse(typeof(PsxIso.FileToRamOffsets), "OFFSET_" + fileAttribute.InnerText);
                    }
                    catch (Exception)
                    {
                        ftrOffset = null;
                    }

                    XmlAttribute defaultAttr = varNode.Attributes["default"];
                    Byte[]       byteArray   = new Byte[numBytes];
                    UInt32       def         = 0;
                    if (defaultAttr != null)
                    {
                        def = UInt32.Parse(defaultAttr.InnerText, System.Globalization.NumberStyles.HexNumber);
                        for (int i = 0; i < numBytes; i++)
                        {
                            byteArray[i] = (Byte)((def >> (i * 8)) & 0xff);
                        }
                    }

                    List <PatchedByteArray> patchedByteArrayList = new List <PatchedByteArray>();
                    int offsetIndex = 0;

                    foreach (string strOffset in strOffsets)
                    {
                        UInt32 offset = UInt32.Parse(strOffset, System.Globalization.NumberStyles.HexNumber);
                        //UInt32 ramOffset = offset;
                        UInt32 fileOffset = offset;

                        if (ftrOffset.HasValue)
                        {
                            try
                            {
                                if (isRamOffset)
                                {
                                    fileOffset -= (UInt32)ftrOffset;
                                }
                                //else
                                //    ramOffset += (UInt32)ftrOffset;
                            }
                            catch (Exception) { }
                        }

                        //ramOffset = ramOffset | 0x80000000;     // KSEG0

                        patchedByteArrayList.Add(new PatchedByteArray(sector, fileOffset, byteArray));

                        offsetIndex++;
                        if (offsetIndex < strOffsets.Length)
                        {
                            if (isSpecific)
                            {
                                sector = specifics[offsetIndex].Sector;

                                try
                                {
                                    ftrOffset = (PsxIso.FileToRamOffsets)Enum.Parse(typeof(PsxIso.FileToRamOffsets), "OFFSET_" + Enum.GetName(typeof(PsxIso.Sectors), sector));
                                }
                                catch (Exception)
                                {
                                    ftrOffset = null;
                                }
                            }
                        }
                    }

                    bool   isReference             = false;
                    string referenceName           = "";
                    string referenceOperatorSymbol = "";
                    uint   referenceOperand        = 0;

                    XmlAttribute attrReference = varNode.Attributes["reference"];
                    XmlAttribute attrOperator  = varNode.Attributes["operator"];
                    XmlAttribute attrOperand   = varNode.Attributes["operand"];

                    if (attrReference != null)
                    {
                        isReference             = true;
                        referenceName           = attrReference.InnerText;
                        referenceOperatorSymbol = (attrOperator != null) ? attrOperator.InnerText : "";
                        if (attrOperand != null)
                        {
                            //UInt32.Parse(defaultAttr.InnerText, System.Globalization.NumberStyles.HexNumber);
                            uint.TryParse(attrOperand.InnerText, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out referenceOperand);
                        }
                    }

                    VariableType vType = new VariableType();
                    vType.numBytes                 = numBytes;
                    vType.byteArray                = byteArray;
                    vType.name                     = varName;
                    vType.content                  = patchedByteArrayList;
                    vType.isReference              = isReference;
                    vType.reference                = new VariableReference();
                    vType.reference.name           = referenceName;
                    vType.reference.operatorSymbol = referenceOperatorSymbol;
                    vType.reference.operand        = referenceOperand;

                    variables.Add(vType);
                }

                GetPatchResult getPatchResult = GetPatch(node, xmlFilename, asmUtility, variables);

                List <PatchedByteArray> patches = new List <PatchedByteArray>(includePatches.Count + getPatchResult.StaticPatches.Count);
                patches.AddRange(includePatches);
                patches.AddRange(getPatchResult.StaticPatches);

                AsmPatch asmPatch = new AsmPatch(getPatchResult.Name, shortXmlFilename, getPatchResult.Description, patches,
                                                 (getPatchResult.HideInDefault | rootHideInDefault), variables);

                asmPatch.ErrorText = getPatchResult.ErrorText;
                result.Add(asmPatch);
            }

            patchNodes = rootNode.SelectNodes("ImportFilePatch");
            foreach (XmlNode node in patchNodes)
            {
                KeyValuePair <string, string> nameDesc = GetPatchNameAndDescription(node);

                string name        = nameDesc.Key;
                string description = nameDesc.Value;

                XmlNodeList fileNodes = node.SelectNodes("ImportFile");
                if (fileNodes.Count != 1)
                {
                    continue;
                }

                XmlNode theRealNode = fileNodes[0];

                PsxIso.Sectors sector         = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), theRealNode.Attributes["file"].InnerText);
                UInt32         offset         = UInt32.Parse(theRealNode.Attributes["offset"].InnerText, System.Globalization.NumberStyles.HexNumber);
                UInt32         expectedLength = UInt32.Parse(theRealNode.Attributes["expectedLength"].InnerText, System.Globalization.NumberStyles.HexNumber);

                result.Add(new FileAsmPatch(name, shortXmlFilename, description, new InputFilePatch(sector, offset, expectedLength)));
            }

            return(result.AsReadOnly());
        }
        private static GetPatchResult GetPatch(XmlNode node, string xmlFileName, ASMEncodingUtility asmUtility, List <VariableType> variables)
        {
            KeyValuePair <string, string> nameDesc = GetPatchNameAndDescription(node);

            bool         hideInDefault     = false;
            XmlAttribute attrHideInDefault = node.Attributes["hideInDefault"];

            if (attrHideInDefault != null)
            {
                if (attrHideInDefault.InnerText.ToLower().Trim() == "true")
                {
                    hideInDefault = true;
                }
            }

            bool hasDefaultSector = false;

            PsxIso.Sectors defaultSector     = (PsxIso.Sectors) 0;
            XmlAttribute   attrDefaultFile   = node.Attributes["file"];
            XmlAttribute   attrDefaultSector = node.Attributes["sector"];

            if (attrDefaultFile != null)
            {
                defaultSector    = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), attrDefaultFile.InnerText);
                hasDefaultSector = true;
            }
            else if (attrDefaultSector != null)
            {
                defaultSector    = (PsxIso.Sectors)Int32.Parse(attrDefaultSector.InnerText, System.Globalization.NumberStyles.HexNumber);
                hasDefaultSector = true;
            }

            XmlNodeList             currentLocs      = node.SelectNodes("Location");
            List <PatchedByteArray> patches          = new List <PatchedByteArray>(currentLocs.Count);
            StringBuilder           sbOuterErrorText = new StringBuilder();

            foreach (XmlNode location in currentLocs)
            {
                //UInt32 offset = UInt32.Parse( location.Attributes["offset"].InnerText, System.Globalization.NumberStyles.HexNumber );
                XmlAttribute offsetAttribute        = location.Attributes["offset"];
                XmlAttribute fileAttribute          = location.Attributes["file"];
                XmlAttribute sectorAttribute        = location.Attributes["sector"];
                XmlAttribute modeAttribute          = location.Attributes["mode"];
                XmlAttribute offsetModeAttribute    = location.Attributes["offsetMode"];
                XmlAttribute inputFileAttribute     = location.Attributes["inputFile"];
                XmlAttribute replaceLabelsAttribute = location.Attributes["replaceLabels"];
                XmlAttribute attrLabel    = location.Attributes["label"];
                XmlAttribute attrSpecific = location.Attributes["specific"];
                XmlAttribute attrMovable  = location.Attributes["movable"];

                string   strOffsetAttr      = (offsetAttribute != null) ? offsetAttribute.InnerText : "";
                string[] strOffsets         = strOffsetAttr.Replace(" ", "").Split(',');
                bool     ignoreOffsetMode   = false;
                bool     isSpecific         = false;
                bool     isSequentialOffset = false;

                List <SpecificLocation> specifics = FillSpecificAttributeData(attrSpecific, defaultSector);

                if (specifics.Count > 0)
                {
                    isSpecific = true;
                    List <string> newStrOffsets = new List <string>(specifics.Count);
                    foreach (SpecificLocation specific in specifics)
                    {
                        newStrOffsets.Add(specific.OffsetString);
                    }
                    strOffsets = newStrOffsets.ToArray();
                }
                else if ((string.IsNullOrEmpty(strOffsetAttr)) && (patches.Count > 0))
                {
                    // No offset defined -- offset is (last patch offset) + (last patch size)
                    PatchedByteArray lastPatchedByteArray = patches[patches.Count - 1];
                    long             offset    = lastPatchedByteArray.Offset + lastPatchedByteArray.GetBytes().Length;
                    string           strOffset = offset.ToString("X");
                    strOffsets = new string[1] {
                        strOffset
                    };
                    ignoreOffsetMode   = true;
                    isSequentialOffset = true;
                }

                PsxIso.Sectors sector = (PsxIso.Sectors) 0;
                if (isSpecific)
                {
                    sector = specifics[0].Sector;
                }
                else if (fileAttribute != null)
                {
                    sector = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), fileAttribute.InnerText);
                }
                else if (sectorAttribute != null)
                {
                    sector = (PsxIso.Sectors)Int32.Parse(sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber);
                }
                else if (hasDefaultSector)
                {
                    sector = defaultSector;
                }
                else if (patches.Count > 0)
                {
                    sector = (PsxIso.Sectors)(patches[patches.Count - 1].Sector);
                }
                else
                {
                    throw new Exception("Error in patch XML: Invalid file/sector!");
                }

                bool asmMode      = false;
                bool markedAsData = false;
                if (modeAttribute != null)
                {
                    string modeAttributeText = modeAttribute.InnerText.ToLower().Trim();
                    if (modeAttributeText == "asm")
                    {
                        asmMode = true;
                    }
                    else if (modeAttributeText == "data")
                    {
                        markedAsData = true;
                    }
                }

                bool isRamOffset = false;
                if ((!ignoreOffsetMode) && (offsetModeAttribute != null))
                {
                    if (offsetModeAttribute.InnerText.ToLower().Trim() == "ram")
                    {
                        isRamOffset = true;
                    }
                }

                string content = location.InnerText;
                if (inputFileAttribute != null)
                {
                    using (StreamReader streamReader = new StreamReader(inputFileAttribute.InnerText, Encoding.UTF8))
                    {
                        content = streamReader.ReadToEnd();
                    }
                }

                bool replaceLabels = false;
                if (replaceLabelsAttribute != null)
                {
                    if (replaceLabelsAttribute.InnerText.ToLower().Trim() == "true")
                    {
                        replaceLabels = true;
                    }
                }
                if (replaceLabels)
                {
                    foreach (PatchedByteArray currentPatchedByteArray in patches)
                    {
                        StringBuilder sbLabels = new StringBuilder();
                        if (!string.IsNullOrEmpty(currentPatchedByteArray.Label))
                        {
                            sbLabels.Append(String.Format(".label @{0}, {1}{2}", currentPatchedByteArray.Label, currentPatchedByteArray.RamOffset, Environment.NewLine));
                        }
                        asmUtility.EncodeASM(sbLabels.ToString(), 0);
                    }
                    content = asmUtility.ReplaceLabelsInHex(content, true);
                }

                string label = "";
                if (attrLabel != null)
                {
                    label = attrLabel.InnerText.Replace(" ", "");
                }

                bool isMoveSimple = asmMode;
                if (attrMovable != null)
                {
                    bool.TryParse(attrMovable.InnerText, out isMoveSimple);
                }

                Nullable <PsxIso.FileToRamOffsets> ftrOffset = null;
                try
                {
                    ftrOffset = (PsxIso.FileToRamOffsets)Enum.Parse(typeof(PsxIso.FileToRamOffsets), "OFFSET_" + Enum.GetName(typeof(PsxIso.Sectors), sector));
                }
                catch (Exception)
                {
                    ftrOffset = null;
                }

                int offsetIndex = 0;
                foreach (string strOffset in strOffsets)
                {
                    UInt32 offset = UInt32.Parse(strOffset, System.Globalization.NumberStyles.HexNumber);

                    UInt32 ramOffset  = offset;
                    UInt32 fileOffset = offset;

                    if (ftrOffset.HasValue)
                    {
                        try
                        {
                            if (isRamOffset)
                            {
                                fileOffset -= (UInt32)ftrOffset;
                            }
                            else
                            {
                                ramOffset += (UInt32)ftrOffset;
                            }
                        }
                        catch (Exception) { }
                    }

                    ramOffset = ramOffset | 0x80000000;     // KSEG0

                    byte[] bytes;
                    string errorText = "";
                    if (asmMode)
                    {
                        string encodeContent = content;

                        StringBuilder sbPrefix = new StringBuilder();
                        foreach (PatchedByteArray currentPatchedByteArray in patches)
                        {
                            if (!string.IsNullOrEmpty(currentPatchedByteArray.Label))
                            {
                                sbPrefix.Append(String.Format(".label @{0}, {1}{2}", currentPatchedByteArray.Label, currentPatchedByteArray.RamOffset, Environment.NewLine));
                            }
                        }
                        foreach (VariableType variable in variables)
                        {
                            sbPrefix.Append(String.Format(".eqv %{0}, {1}{2}", ASMStringHelper.RemoveSpaces(variable.name).Replace(",", ""),
                                                          AsmPatch.GetUnsignedByteArrayValue_LittleEndian(variable.byteArray), Environment.NewLine));
                        }

                        encodeContent = sbPrefix.ToString() + content;

                        ASMEncoderResult result = asmUtility.EncodeASM(encodeContent, ramOffset);
                        bytes     = result.EncodedBytes;
                        errorText = result.ErrorText;
                    }
                    else
                    {
                        bytes = GetBytes(content);
                    }

                    bool isCheckedAsm = false;
                    if (!markedAsData)
                    {
                        ASMCheckResult checkResult = asmUtility.CheckASMFromBytes(bytes, ramOffset, true, false, new HashSet <ASMCheckCondition>()
                        {
                            ASMCheckCondition.LoadDelay,
                            ASMCheckCondition.UnalignedOffset,
                            ASMCheckCondition.MultCountdown,
                            ASMCheckCondition.StackPointerOffset4,
                            ASMCheckCondition.BranchInBranchDelaySlot
                        });

                        if (checkResult.IsASM)
                        {
                            isCheckedAsm = true;
                            if (!string.IsNullOrEmpty(checkResult.ErrorText))
                            {
                                errorText += checkResult.ErrorText;
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(errorText))
                    {
                        sbOuterErrorText.Append(errorText);
                    }

                    PatchedByteArray patchedByteArray = new PatchedByteArray(sector, fileOffset, bytes);
                    patchedByteArray.IsAsm              = asmMode;
                    patchedByteArray.MarkedAsData       = markedAsData;
                    patchedByteArray.IsCheckedAsm       = isCheckedAsm;
                    patchedByteArray.IsSequentialOffset = isSequentialOffset;
                    patchedByteArray.IsMoveSimple       = isMoveSimple;
                    patchedByteArray.AsmText            = asmMode ? content : "";
                    patchedByteArray.RamOffset          = ramOffset;
                    patchedByteArray.ErrorText          = errorText;
                    patchedByteArray.Label              = label;

                    patches.Add(patchedByteArray);

                    offsetIndex++;
                    if (offsetIndex < strOffsets.Length)
                    {
                        if (isSpecific)
                        {
                            sector = specifics[offsetIndex].Sector;

                            try
                            {
                                ftrOffset = (PsxIso.FileToRamOffsets)Enum.Parse(typeof(PsxIso.FileToRamOffsets), "OFFSET_" + Enum.GetName(typeof(PsxIso.Sectors), sector));
                            }
                            catch (Exception)
                            {
                                ftrOffset = null;
                            }
                        }
                    }
                }
            }

            currentLocs = node.SelectNodes("STRLocation");
            foreach (XmlNode location in currentLocs)
            {
                XmlAttribute   fileAttribute   = location.Attributes["file"];
                XmlAttribute   sectorAttribute = location.Attributes["sector"];
                PsxIso.Sectors sector          = (PsxIso.Sectors) 0;
                if (fileAttribute != null)
                {
                    sector = (PsxIso.Sectors)Enum.Parse(typeof(PsxIso.Sectors), fileAttribute.InnerText);
                }
                else if (sectorAttribute != null)
                {
                    sector = (PsxIso.Sectors)Int32.Parse(sectorAttribute.InnerText, System.Globalization.NumberStyles.HexNumber);
                }
                else
                {
                    throw new Exception();
                }

                string filename = location.Attributes["input"].InnerText;
                filename = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(xmlFileName), filename);

                patches.Add(new STRPatchedByteArray(sector, filename));
            }

            return(new GetPatchResult(nameDesc.Key, nameDesc.Value, patches.AsReadOnly(), hideInDefault, sbOuterErrorText.ToString()));
        }