Heya,
If you're going to do a patcher via C#, then you can download GRF Editor's sources over here :
http://www.mediafire.com/download/7z6hkdag4ayj8rs
Add a reference to the dlls found in the "Output Libraries" folder to your project and you can use the following code to get you started :
using System;using System.Diagnostics;using System.IO;using System.Windows.Forms;using GRF.Core;using GRF.FileFormats.RgzFormat;using GRF.FileFormats.ThorFormat;using GRF.IO;using Utilities.Extension;namespace TestPatcher { public partial class Form1 : Form { public Form1() { InitializeComponent(); Patch(); } public void Patch() { var patchesPath = @"C

atches"; var patcherExeName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName); var roDirectory = Directory.GetCurrentDirectory(); var serverGrfName = @"server.grf"; var temporaryGrfName = @"temp.grf"; using (var output = new GrfHolder(temporaryGrfName, GrfLoadOptions.New)) { foreach (var patchFile in Directory.GetFiles(patchesPath)) { if (patchFile.IsExtension(".grf", ".gpf")) { using (var grf = new GrfHolder(patchFile)) { output.QuickMerge(grf); } } else if (patchFile.IsExtension(".rgz")) { using (var rgz = new Rgz(patchFile)) { if (rgz.Table.ContainsFile(patcherExeName)) { // Updating on this executable, do something...! throw new NotImplementedException(); } foreach (var entry in rgz.Table) { entry.ExtractFromRelative(roDirectory); } } } else if (patchFile.IsExtension(".thor")) { using (var thor = new Thor(patchFile)) { if (thor.Header.UseGrfMerging) { string targetGrf = thor.Header.UseDefaultTargetGrf ? serverGrfName : thor.Header.TargetGrf; if (string.IsNullOrEmpty(targetGrf)) throw new Exception("THOR extraction failed : no target GRF identified."); if (String.Compare(serverGrfName, targetGrf, StringComparison.OrdinalIgnoreCase) == 0) { output.QuickMerge(thor.ToGrfHolderQuick()); } else { using (var grf = new GrfHolder(targetGrf, GrfLoadOptions.OpenOrNew)) { grf.QuickMerge(thor.ToGrfHolderQuick()); } } } else { if (thor.Table.ContainsFile(patcherExeName)) { // Updating on this executable, do something...! throw new NotImplementedException(); } foreach (var entry in thor.Table) { entry.ExtractFromRelative(roDirectory); } } } } } using (var serverGrf = new GrfHolder(serverGrfName, GrfLoadOptions.OpenOrNew)) { serverGrf.QuickMerge(output); } } GrfPath.Delete(temporaryGrfName); } }}
Obviously this is not optimized and errors are not handled at all, but it yields good results nonetheless. I would definitely not recommend you to start from scratch to make a patcher.