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()); }
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()); }