private static bool IsFileSizeCorrect(string fn, long expectedSize) { if (new FileInfo(fn).Length == expectedSize) return true; UserFeedback.Trace("'{0}' is not the expected size", fn); return false; }
private static void ShowUsage() { UserFeedback.Warning("Usage: aoe2wide.exe [width height]"); UserFeedback.Info("If the new width and height are omitted, the current screen resolution(s) will be used."); UserFeedback.Trace("Alternatively, use: aoe2wide.exe createpatches"); UserFeedback.Trace(" to try to create fresh patch files for all your age2_x1 executables, from the RootPatch file"); }
private static bool IsFileHashCorrect(string fn, string expectedHash) { var actualHash = GetChecksum(fn); if (actualHash.Equals(expectedHash, StringComparison.InvariantCultureIgnoreCase)) return true; UserFeedback.Trace(string.Format(@"'{0}' doesn't meet the expected hashcode '{1}' instead of '{2}'", fn, actualHash, expectedHash)); return false; }
private static void FindResAndPatchExecutable(int newWidth, int newHeight, string exe) { try { UserFeedback.Trace(@""); _orgExePath = exe; var patch = FindPatchForExe(_orgExePath); if (patch == null) { UserFeedback.Trace("No patches found for executable '{0}'", _orgExePath); return; } UserFeedback.Info(string.Format("Patching Exe '{0}' (version {1}) with patch file '{2}'", _orgExePath, patch.Version, patch.PatchFilepath)); if (patch.InterfaceX1DrsPosition > 0 && !File.Exists(_orgX1DrsPath)) throw new FatalError(string.Format(@"Cannot find X1 drs file '{0}' in the game folder", _orgX1DrsPath)); if (patch.InterfaceX1DrsPosition == 0 && File.Exists(_orgX1DrsPath)) UserFeedback.Warning(string.Format(@"Found X1 drs file '{0}' in the game folder, but no x1drspos=??? in patch file. X1 drs won't be patched!", _orgX1DrsPath)); if (newWidth == 0 && newHeight == 0) { UserFeedback.Info( @"Auto patching for all current screen sizes. Note that the game will always use the primary screen!"); var doneList = new HashSet<int>(); foreach (var screen in System.Windows.Forms.Screen.AllScreens) { try { newWidth = screen.Bounds.Width; newHeight = screen.Bounds.Height; var key = newWidth + (newHeight * 65536); if (doneList.Add(key)) PatchExecutable(newWidth, newHeight, patch); } catch (Exception e) { UserFeedback.Error(e); } } } else { PatchExecutable(newWidth, newHeight, patch); } } catch (Exception e) { UserFeedback.Error(e); } return; }
private static string FindGameDirectory() { UserFeedback.Trace(@"Locating game main folder..."); var iter = new DirectoryInfo(Directory.GetCurrentDirectory()); while (iter.GetFiles(@"language_x1.dll").Length == 0) { iter = iter.Parent; if (iter == null) throw new FatalError(@"Cannot locate the game directory (where I expect language_x1.dll). Please run AoE2Wide from the game folder or a subfolder of it."); } UserFeedback.Trace(@"Located @'{0}'", iter.FullName); return iter.FullName; }
static void Main(string[] args) { try { Go(args); } catch (Exception e) { UserFeedback.Error(e); } UserFeedback.Close(); }
private static int FindComparablePos(byte[] correctExe, byte[] otherExe, int pos) { for (var windowSize = 4; windowSize < 25; windowSize += 4) { var window = new byte[windowSize]; var startOffset = 0; if (startOffset + pos < 0) { startOffset = -pos; } if ((startOffset + windowSize) >= correctExe.Length) { startOffset = correctExe.Length - (pos + windowSize); } for (var i = 0; i < windowSize; i++) { window[i] = correctExe[i + pos + startOffset]; } var positions = FindWindow(otherExe, window).ToArray(); if (positions.Length == 1) { return(positions[0] - startOffset); } if (positions.Length == 0) { if (windowSize == 8 && startOffset == 0) { startOffset = -4; for (var i = 0; i < windowSize; i++) { window[i] = correctExe[i + pos + startOffset]; } positions = FindWindow(otherExe, window).ToArray(); if (positions.Length == 1) { return(positions[0] - startOffset); } } UserFeedback.Warning(string.Format(@"Found no matches for block {0:X8} {1}", pos, windowSize)); return(-pos); } } UserFeedback.Warning("Found too many matches for block {0:X8}", pos); return(-pos); }
private static void ConvertPatchFile(string otherExe) { UserFeedback.Info(@"Converting RootPatch file to a patch file for '{0}'", otherExe); var rootPatchFilePath = FindRootPatchFile(); UserFeedback.Trace(@"Reading the root patch file"); var patch = Patcher.ReadPatch(rootPatchFilePath, true); UserFeedback.Trace(@"Locating the root executable file"); var rootExePath = FindExeFile(patch.FileSize, patch.Md5); UserFeedback.Trace(@"Reading the target executable"); var exe2 = File.ReadAllBytes(otherExe); UserFeedback.Trace(@"Reading root executable"); var exe1 = File.ReadAllBytes(rootExePath); var md5 = GetChecksum(exe2); UserFeedback.Trace(@"Detecting version from filename and/or md5"); string version = GetVersion(otherExe, md5); UserFeedback.Trace(@"Version: '{0}'", version); var rootMd5 = GetChecksum(exe1); Patch newPatch; if (rootMd5.Equals(md5)) { UserFeedback.Trace(@"Executable is equal; leaving patch file as-is"); newPatch = new Patch { FileSize = patch.FileSize, InterfaceDrsPosition = patch.InterfaceDrsPosition, Items = patch.Items, Md5 = patch.Md5 }; } else { UserFeedback.Trace(@"Locating comparable locations, this may take a while"); newPatch = Patcher.ConvertPatch(exe1, exe2, patch); newPatch.FileSize = exe2.Length; newPatch.Md5 = md5; } newPatch.Version = version; var patchFileName = @"AoE2Wide_" + version + @".patch"; var patchOutput = Path.Combine(Path.GetDirectoryName(otherExe), patchFileName); UserFeedback.Trace("Writing the patch file '{0}'", patchOutput); Patcher.WritePatch(newPatch, patchOutput); }
private static string FindFile(string whatFile, string fileName, Int64? expectedSize, string expectedHash) { var files = FindFiles(whatFile, fileName, expectedSize, expectedHash); if (files.Length > 1) { UserFeedback.Warning( @"Multiple correct {0} instances found in current directory and subdirectories:", whatFile); foreach (var file in files) UserFeedback.Trace(file); } UserFeedback.Info(@"Using '{0}'", files[0]); return files[0]; }
private static string[] FindFiles(string whatFile, string fileName, Int64? expectedSize, string expectedHash) { UserFeedback.Trace(string.Format(@"Locating {0} file '{1}'", whatFile, fileName)); var files = Directory.GetFiles(_gameDirectory, fileName, SearchOption.AllDirectories); if (expectedSize.HasValue) files = files.Where(fn => IsFileSizeCorrect(fn, expectedSize.Value)).ToArray(); if (expectedHash != null) files = files.Where(fn => IsFileHashCorrect(fn, expectedHash)).ToArray(); if (files.Length == 0) throw new FatalError(string.Format(@"No correct {0} found in current directory or subdirectories", whatFile)); return files; }
public static Patch TryReadPatch(string patchFile, bool activeOnly) { try { UserFeedback.Info(@"Reading the patch file '{0}'", patchFile); return(ReadPatch(patchFile, activeOnly)); } catch (Exception e) { UserFeedback.Error(e); return(new Patch() { PatchFilepath = patchFile }); } }
static void PatchADrs(string _orgDrsPath, string newDrsName, int oldWidth, int oldHeight, int newWidth, int newHeight) { UserFeedback.Trace(@"Opening original {0}", System.IO.Path.GetFileName(_orgDrsPath)); using ( var interfaceDrs = new FileStream(_orgDrsPath, FileMode.Open, FileSystemRights.ReadData, FileShare.Read, 1024 * 1024, FileOptions.SequentialScan)) { UserFeedback.Trace(@"Creating patched drs file '{0}'", newDrsName); using ( var newDrs = new FileStream(newDrsName, FileMode.Create, FileSystemRights.Write, FileShare.None, 1024 * 1024, FileOptions.SequentialScan)) { UserFeedback.Trace(@"Patching DRS '{0}'", System.IO.Path.GetFileName(_orgDrsPath)); DrsPatcher.Patch(interfaceDrs, newDrs, oldWidth, oldHeight, newWidth, newHeight); } } }
static void PatchAllDrs() { var doneList = new HashSet<int>(); foreach (var screen in System.Windows.Forms.Screen.AllScreens) { try { var newWidth = screen.Bounds.Width; var newHeight = screen.Bounds.Height; var key = newWidth + (newHeight * 65536); if (doneList.Add(key)) PatchAllDrs(newWidth, newHeight); } catch (Exception e) { UserFeedback.Error(e); } } }
private static Patch FindPatchForExe(int exeFileSize, string exeMd5, string exeFilenameForFeedback) { if (patchFiles == null) patchFiles = FindPatchFiles(); if (allPatches == null) allPatches = patchFiles.Select(patchFile => Patcher.TryReadPatch(patchFile, true)).ToArray(); var matchingPatches = allPatches.Where(patch => patch.FileSize == exeFileSize && patch.Md5.Equals(exeMd5)).ToArray(); if (matchingPatches.Length == 0) return null; if (matchingPatches.Length == 1) return matchingPatches[0]; UserFeedback.Warning("Multiple matching patches found for executable '{0}', using first:", exeFilenameForFeedback); foreach (var mp in matchingPatches) UserFeedback.Trace("* {0}", mp.PatchFilepath); return matchingPatches[0]; }
private static void AddAsmToRootPatchFile() { UserFeedback.Info(@"Locating listing file"); var lstFile = FindFile("listing file", "age2_x1*.lst", null, null); UserFeedback.Info(@"Locating RootPatch file"); var rootPatchFilePath = FindRootPatchFile(); UserFeedback.Trace(@"Reading the root patch file"); var patch = Patcher.ReadPatch(rootPatchFilePath, false); UserFeedback.Trace(@"Reading the listing file"); var asmMap = Patcher.ReadAsmMap(lstFile); UserFeedback.Trace(@"Adding Asm to the patch data"); Patcher.AddAsm(patch, asmMap); var outputRootPatchFilePath = rootPatchFilePath + "2"; UserFeedback.Trace("Writing the patch file '{0}'", outputRootPatchFilePath); Patcher.WritePatch(patch, outputRootPatchFilePath); }
public static byte[] Enlarge(uint id, byte[] data, int oldWidth, int oldHeight, int newWidth, int newHeight) { var reader = new BinaryReader(new MemoryStream(data, false)); var version = reader.ReadUInt32(); if (version != 0x4e302e32) { return(data); } var framecount = reader.ReadUInt32(); if (framecount != 1) { return(data); } var comment = reader.ReadBytes(24); /*var linesOffset = */ reader.ReadUInt32(); var maskOffset = reader.ReadUInt32(); var paletteOffset = reader.ReadUInt32(); var properties = reader.ReadUInt32(); var width = reader.ReadInt32(); if (width != oldWidth) { return(data); } var height = reader.ReadInt32(); var centerX = reader.ReadInt32(); var centerY = reader.ReadInt32(); if (height - centerY != oldHeight) { return(data); } if (centerY != 0) { int higher = newHeight - oldHeight; centerY -= higher; newHeight = oldHeight = height; } var newMaskSize = (uint)(newHeight * 4); var newLinesOffset = maskOffset + newMaskSize; var newLinesSize = (uint)(newHeight * 4); var newLineDataStart = newLinesOffset + newLinesSize; var outStream = new MemoryStream(); var writer = new BinaryWriter(outStream); UserFeedback.Info(string.Format("Resizing image #{0} for {1}x{2} to {3}x{4}", id, oldWidth, oldHeight, newWidth, newHeight)); writer.Write(version); writer.Write(framecount); writer.Write(comment); writer.Write(newLinesOffset); writer.Write(maskOffset); writer.Write(paletteOffset); writer.Write(properties); writer.Write(newWidth); writer.Write(newHeight); writer.Write(centerX); writer.Write(centerY); var osp = outStream.Position; Trace.Assert(osp == maskOffset); var orgLineMasks = new UInt32[oldHeight]; for (var inLine = 0; inLine < oldHeight; inLine++) { orgLineMasks[inLine] = reader.ReadUInt32(); } var orgLineStarts = new UInt32[oldHeight + 1]; for (var inLine = 0; inLine < oldHeight; inLine++) { orgLineStarts[inLine] = reader.ReadUInt32(); } orgLineStarts[oldHeight] = (uint)data.Length; var orgLines = new List <byte[]>(oldHeight); for (var inLine = 0; inLine < oldHeight; inLine++) { var orgLineSize = orgLineStarts[inLine + 1] - orgLineStarts[inLine]; orgLines.Add(reader.ReadBytes((int)orgLineSize)); } var newLineMasks = new UInt32[newHeight]; var newLines = new List <byte[]>(newHeight); var extraLines = newHeight - oldHeight; var shrinking = extraLines < 0; var expanding = extraLines > 0; var centreLine = oldHeight / 2; var shrinkSkipStart = centreLine + extraLines; var shrinkSkipEnd = centreLine; // duplication is the amount of times every duplicated line, is duplicated var duplication = 1 + (extraLines + 1) / (oldHeight / 2); // the duplication block size is the block that is being duplicated // the last line of which MIGHT not be duplicated 'duplication' times // eg if duplication is 2, extralines = 501, dbs = 251, the last of which is // duped just once. var duplicationBlockSize = (extraLines + duplication - 1) / duplication; var dupStart = centreLine - duplicationBlockSize / 2; var dupEnd = dupStart + duplicationBlockSize; var dupedLines = 0; //'UNIT'TEST for (var inLine = 0; inLine < oldHeight; inLine++) { // If shrinking skip 'extralines' lines on the centerline and above if (shrinking && inLine >= shrinkSkipStart && inLine < shrinkSkipEnd) { dupedLines--; continue; } newLineMasks[newLines.Count] = orgLineMasks[inLine]; var newLine = StretchLine(orgLines[inLine], oldWidth, newWidth); newLines.Add(newLine); // If expanding, duplicate the right amount of lines before centreLine if (!expanding || inLine < dupStart || inLine >= dupEnd) { continue; } for (var rep = 0; rep < duplication && dupedLines < extraLines; rep++) { newLineMasks[newLines.Count] = orgLineMasks[inLine]; newLines.Add(newLine); dupedLines++; } } Trace.Assert(newLines.Count == newHeight); Trace.Assert(dupedLines == extraLines); var nextLineStart = newLineDataStart; foreach (var newLineMask in newLineMasks) { writer.Write(newLineMask); } osp = outStream.Position; Trace.Assert(newLinesOffset == osp); foreach (var newLine in newLines) { writer.Write(nextLineStart); nextLineStart += (uint)newLine.Length; } osp = outStream.Position; Trace.Assert(newLineDataStart == osp); foreach (var newLine in newLines) { writer.Write(newLine); } Trace.Assert(outStream.Position == nextLineStart); writer.Close(); var newSlp = outStream.ToArray(); // For debugging: //File.WriteAllBytes(string.Format(@"slp\{0}org.slp", id), data); //File.WriteAllBytes(string.Format(@"slp\{0}new.slp", id), newSlp); return(newSlp); }
static public void PatchResolutions(byte[] exe, int oldWidth, int oldHeight, int newWidth, int newHeight, Patch patch) { // Create the map so, that originally larger resolutions stay larger even after patching. They _may_ become invalid though. // This is necessary to keep the internal (in AoE) if > else if > else if > code working. var hmap = new Dictionary <int, int>(); var existingWidths = new[] { 800, 1024, 1280, 1600 }; var wshift = newWidth; foreach (var w in existingWidths) { if (w == oldWidth) { hmap[w] = newWidth; } else if (w > oldWidth) { hmap[w] = ++wshift; } } var vmap = new Dictionary <int, int>(); var existingHeights = new[] { 600, 768, 1024, 1200 }; var hshift = newHeight; foreach (var h in existingHeights) { if (h == oldHeight) { vmap[h] = newHeight; } else if (h > oldHeight) { vmap[h] = ++hshift; } } foreach (var pair in hmap) { UserFeedback.Trace(string.Format(@"Horizontal {0} => {1}", pair.Key, pair.Value)); } foreach (var pair in vmap) { UserFeedback.Trace(string.Format(@"Vertical {0} => {1}", pair.Key, pair.Value)); } foreach (var item in patch.Items) { if (item.Pos >= exe.Length) { UserFeedback.Warning(@"Error in input: Invalid location {0:X8}. [NOT PATCHED]", item.Pos); continue; } var oldValue = item.ReferenceValue; int newValue; var hor = item.Type.Contains("H"); var ver = item.Type.Contains("V"); // If a number is used for both horizontal and vertical // prefer the one that we are patching. if (hor && ver) { if (oldWidth == oldValue) // so if we have 1024 HV, and are patching 1024x768, we'd ignore the V, and use the H { ver = false; } else { hor = false; } } Trace.Assert(hor || ver); var map = ver ? vmap : hmap; if (!map.TryGetValue(oldValue, out newValue)) { newValue = oldValue; } if (item.Type.Contains("H") && item.Type.Contains("V")) { UserFeedback.Trace(string.Format(@"{0} HV: Mapping to {1}", oldValue, newValue)); } var ob0 = (int)exe[item.Pos]; var ob1 = (int)exe[item.Pos + 1]; var ob2 = (int)exe[item.Pos + 2]; var ob3 = (int)exe[item.Pos + 3]; var orgValue = ob0 | ob1 << 8 | ob2 << 16 | ob3 << 24; if (item.Type.Equals("dV") || item.Type.Equals("dH")) { var expectedOrgValue = item.Parameter; if (expectedOrgValue == 0) { UserFeedback.Warning( string.Format( "{0} action is safer if you mention the expected orgValue. Encountered {1} @ {2:X8}", item.Type, orgValue, item.Pos)); } else { if (expectedOrgValue != orgValue) { UserFeedback.Warning(string.Format( @"{0} action expected value mismatch: {1} expected, {2} encountered @ {3:X8} [NOT PATCHED]", item.Type, expectedOrgValue, orgValue, item.Pos)); continue; } } var offset = newValue - oldValue; newValue = orgValue + offset; } else { if (orgValue != oldValue) { UserFeedback.Warning(string.Format( @"{0} action expected value mismatch: {1} expected, {2} encountered @ {3:X8} [NOT PATCHED]", item.Type, oldValue, orgValue, item.Pos)); continue; } } var b0 = (byte)(newValue & 0xFF); var b1 = (byte)((newValue >> 8) & 0xFF); var b2 = (byte)((newValue >> 16) & 0xFF); var b3 = (byte)((newValue >> 24) & 0xFF); exe[item.Pos] = b0; exe[item.Pos + 1] = b1; exe[item.Pos + 2] = b2; exe[item.Pos + 3] = b3; } }
private static void PatchExecutable(int newWidth, int newHeight, Patch patch) { try { int oldWidth, oldHeight; GetOldWidthHeight(newWidth, newHeight, out oldWidth, out oldHeight); UserFeedback.Info(string.Format(@"Changing {0}x{1} to {2}x{3}", oldWidth, oldHeight, newWidth, newHeight)); UserFeedback.Trace(@"Reading original executable"); var exe = File.ReadAllBytes(_orgExePath); var versionString = patch.Version.Length == 0 ? "" : patch.Version + "_"; var newDrsName = Path.Combine(Path.Combine(_gameDirectory, @"Data"), string.Format(@"{0:D4}{1:D4}.drs", newWidth, newHeight)); var newX1DrsName = Path.Combine(Path.Combine(_gameDirectory, @"Data"), string.Format(@"{0:D4}{1:D4}_x1.drs", newWidth, newHeight)); var newExeName = Path.Combine(_gameDirectory, string.Format(@"age2_x1_{2}{0}x{1}.exe", newWidth, newHeight, versionString)); var batchName = Path.Combine(_gameDirectory, string.Format(@"AoC{2} {0}x{1}.bat", newWidth, newHeight, patch.Version)); var desktopBatchName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), string.Format(@"AoC{2} {0}x{1}.bat", newWidth, newHeight, patch.Version)); //Trace(@"Writing file with all occurrences of resolutions"); //Patcher.ListEm(bytes); UserFeedback.Trace("Patching the executable: DRS reference"); Patcher.PatchDrsRefInExe(exe, Path.GetFileName(newDrsName), patch); if (patch.InterfaceX1DrsPosition > 0) { UserFeedback.Trace("Patching the executable: X1 DRS reference"); Patcher.PatchX1DrsRefInExe(exe, Path.GetFileName(newX1DrsName), patch); } UserFeedback.Trace("Patching the executable: resolutions"); Patcher.PatchResolutions(exe, oldWidth, oldHeight, newWidth, newHeight, patch); UserFeedback.Trace(string.Format(@"Writing the patched executable '{0}'", newExeName)); File.WriteAllBytes(newExeName, exe); if (skipExistingFiles && File.Exists(batchName)) { UserFeedback.Trace(@"Skipping existing convenience batch file '{0}'", batchName); } else { UserFeedback.Trace(@"Writing convenience batch file '{0}'", batchName); var batContent = new List<string> {@"@echo off"}; var processExe = IsVistaOrHigher ? FindProcessExe() : null; if (processExe != null) { batContent.Add( @"ECHO Using process.exe to suspend explorer.exe (win7, vista palette fix)"); batContent.Add(string.Format("\"{0}\" -s explorer.exe", processExe)); } batContent.Add(@"ECHO Starting Age of Empires II - The Conquerers in the correct screen mode"); batContent.Add(string.Format("\"{0}\" {1}", Path.GetFileName(newExeName), oldWidth)); if (processExe != null) { batContent.Add(@"ECHO Resuming explorer (was suspended before)"); batContent.Add(string.Format("\"{0}\" -r explorer.exe", processExe)); } File.WriteAllLines(batchName, batContent.ToArray()); } if (skipExistingFiles && File.Exists(desktopBatchName)) { UserFeedback.Trace(@"Skipping existing convenience desktop batch file '{0}'", desktopBatchName); } else { var driveLetter = Path.GetPathRoot(_gameDirectory); driveLetter = driveLetter.Replace(Path.DirectorySeparatorChar, ' '); UserFeedback.Trace(@"Writing convenience desktop batch file '{0}'", desktopBatchName); var batContent = new List<string> { @"@echo off", driveLetter, string.Format("cd \"{0}\"", _gameDirectory) }; var processExe = IsVistaOrHigher ? FindProcessExe() : null; if (processExe != null) { batContent.Add( @"ECHO Using process.exe to suspend explorer.exe (win7, vista palette fix)"); batContent.Add(string.Format("\"{0}\" -s explorer.exe", processExe)); } batContent.Add(@"ECHO Starting Age of Empires II - The Conquerers in the correct screen mode"); batContent.Add(string.Format("\"{0}\" {1}", Path.GetFileName(newExeName), oldWidth)); if (processExe != null) { batContent.Add(@"ECHO Resuming explorer (was suspended before)"); batContent.Add(string.Format("\"{0}\" -r explorer.exe", processExe)); } File.WriteAllLines(desktopBatchName, batContent.ToArray()); } if (skipExistingFiles && File.Exists(newDrsName)) { UserFeedback.Info(@"Patched drs file '{0}' exists already, skipping.", newDrsName); } else { PatchADrs(_orgDrsPath, newDrsName, oldWidth, oldHeight, newWidth, newHeight); } if (patch.InterfaceX1DrsPosition > 0) { if (skipExistingFiles && File.Exists(newX1DrsName)) { UserFeedback.Info(@"Patched X1 drs file '{0}' exists already, skipping.", newX1DrsName); } else { PatchADrs(_orgX1DrsPath, newX1DrsName, oldWidth, oldHeight, newWidth, newHeight); } } try { var pubDir = Path.Combine(_gameDirectory, @"donePatches"); if (Directory.Exists(pubDir)) { var specificPubDir = Path.Combine(pubDir, string.Format(@"{0}x{1}", newWidth, newHeight)); if (!Directory.Exists(specificPubDir)) Directory.CreateDirectory(specificPubDir); var specificPubDataDir = Path.Combine(specificPubDir, @"Data"); if (!Directory.Exists(specificPubDataDir)) Directory.CreateDirectory(specificPubDataDir); var pubExePath = Path.Combine(specificPubDir, Path.GetFileName(newExeName)); var pubDrsPath = Path.Combine(specificPubDataDir, Path.GetFileName(newDrsName)); File.Copy(newExeName, pubExePath, true); File.Copy(newDrsName, pubDrsPath, true); } } catch (Exception e) { UserFeedback.Warning("Couldn't publish: {0}", e.ToString()); } UserFeedback.Trace("Done"); } catch (Exception e) { UserFeedback.Error(e); } }
static void Go(string[] args) { _gameDirectory = FindGameDirectory(); if (args.Length == 1) { if (args[0].Equals(@"addasm")) { AddAsmToRootPatchFile(); return; } /* if (args[0].Equals(@"test")) { PatchAllDrs(); return; }*/ if (args[0].Equals("createpatches")) { var allExes = FindFiles(@"AoK-TC executables", @"age2_x1*.exe", null, null); var allPatchedExes = new List<string>(); try { allPatchedExes = new List<string>(FindFiles(@"Patched executables", @"age2_x1*_???*x???*.exe", null, null)); } catch (FatalError) { // Happens if no patched exes are found. No problem! } foreach (var exe in allExes) { if (allPatchedExes.Contains(exe)) { UserFeedback.Trace(@"Skipping patched exe '{0}'", exe); continue; } ConvertPatchFile(exe); } } else { ShowUsage(); } return; } int newWidth = 0, newHeight = 0; switch (args.Length) { case 0: break; case 2: { if (!int.TryParse(args[0], out newWidth) || !int.TryParse(args[1], out newHeight)) { ShowUsage(); return; } } break; default: ShowUsage(); break; } _orgDrsPath = Path.Combine(Path.Combine(_gameDirectory, @"Data"), @"interfac.drs"); _orgX1DrsPath = Path.Combine(Path.Combine(_gameDirectory, @"Data"), @"interfac_x1.drs"); if (!File.Exists(_orgDrsPath)) throw new FatalError(string.Format(@"Cannot find drs file '{0}' in the game folder", _orgDrsPath)); UserFeedback.Info("Trying to find a patch file for all executables > 2MiB in size"); var allExecutables = FindFiles("executables", "*.exe", null, null); var allLargeExes = allExecutables.Where(exe => new FileInfo(exe).Length > 2000000); foreach (var exe in allLargeExes) FindResAndPatchExecutable(newWidth, newHeight, exe); }
public static byte[] UpdateGuiTable(byte[] data, uint id, int oldWidth, int oldHeight, int newWidth, int newHeight) { int Xcol, Ycol, Wcol, Hcol; switch (oldWidth) { case 800: Xcol = (int)Columns.X800; Ycol = (int)Columns.Y800; Wcol = (int)Columns.W800; Hcol = (int)Columns.H800; break; case 1024: Xcol = (int)Columns.X1024; Ycol = (int)Columns.Y1024; Wcol = (int)Columns.W1024; Hcol = (int)Columns.H1024; break; case 1280: Xcol = (int)Columns.X1280; Ycol = (int)Columns.Y1280; Wcol = (int)Columns.W1280; Hcol = (int)Columns.H1280; break; default: return(data); } int higher = newHeight - oldHeight; int wider = newWidth - oldWidth; if (data.Length < 10) { return(data); } try { var test = System.Text.Encoding.ASCII.GetString(data, 0, 10); if (test == null || !test.Equals("Item Name\t")) { return(data); } } catch { return(data); } try { var file = System.Text.Encoding.ASCII.GetString(data); var lines = file.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var table = lines.Select(line => line.Split(new char[] { '\t' })).ToArray(); foreach (var tableRow in table) { if (tableRow.Length < 13) { continue; } if (string.IsNullOrEmpty(tableRow[(int)Columns.Name])) { continue; } if (string.IsNullOrEmpty(tableRow[(int)Columns.H1280])) { continue; } var x = int.Parse(tableRow[Xcol]); var y = int.Parse(tableRow[Ycol]); var w = int.Parse(tableRow[Wcol]); var h = int.Parse(tableRow[Hcol]); // Stuff that overlaps the centerline, stretches if (y < oldHeight / 2 && (y + h) > oldHeight / 2) { h += higher; } // Stuff that is below the old centerline, moves down else if (y > oldHeight / 2) { y += higher; } /* * // Only stuff that sticks to the right side: * if ((x + w) == oldWidth) * { * // Stuff on the right half, moves right * if (x > oldWidth / 2) * { * x += wider; * } * else if (x == oldWidth / 2) * { * // stuff in the center, stays in the center * x = newWidth / 2; * w = newWidth / 2; * } * else * { * // Stuff that stretches over the center, stretches (including full-width stuff) * w += wider; * } * } */ if (w == oldWidth) { w = newWidth; } tableRow[Xcol] = x.ToString(); tableRow[Ycol] = y.ToString(); tableRow[Wcol] = w.ToString(); tableRow[Hcol] = h.ToString(); } var newLines = table.Select(tableRow => tableRow.Aggregate((output, col) => output + "\t" + col)); var newText = newLines.Aggregate((output, line) => output + "\r\n" + line); var newBytes = System.Text.Encoding.ASCII.GetBytes(newText); UserFeedback.Info("Patched Gui Table #{0}", id); return(newBytes); } catch (Exception e) { UserFeedback.Warning("Failed to patch Gui Table #{0}; leaving it unchanged.", id); UserFeedback.Error(e); return(data); } }