public void LoadFromLinker(Linker linker) { if (_codeBlob != null) throw new InvalidOperationException("this KamekFile already has stuff in it"); // Extract _just_ the code/data sections _codeBlob = new byte[linker.OutputEnd - linker.OutputStart]; Array.Copy(linker.Memory, linker.OutputStart - linker.BaseAddress, _codeBlob, 0, _codeBlob.Length); _baseAddress = linker.BaseAddress; _bssSize = linker.BssSize; _hooks = new List<Hooks.Hook>(); _commands = new Dictionary<Word, Commands.Command>(); AddRelocsAsCommands(linker.Fixups); foreach (var cmd in linker.Hooks) ApplyHook(cmd); ApplyStaticCommands(); }
static void Main(string[] args) { Console.WriteLine("Kamek 2.0 by Ninji/Ash Wolf - https://github.com/Treeki/Kamek"); Console.WriteLine(); // Parse the command line arguments and do cool things! var modules = new List <Elf>(); uint? baseAddress = null; string outputKamekPath = null, outputRiivPath = null, outputGeckoPath = null, outputCodePath = null; string inputDolPath = null, outputDolPath = null; var externals = new Dictionary <string, uint>(); VersionInfo versions = null; var selectedVersions = new List <String>(); foreach (var arg in args) { if (arg.StartsWith("-")) { if (arg == "-h" || arg == "-help" || arg == "--help") { ShowHelp(); return; } if (arg == "-dynamic") { baseAddress = null; } else if (arg.StartsWith("-static=0x")) { baseAddress = uint.Parse(arg.Substring(10), System.Globalization.NumberStyles.HexNumber); } else if (arg.StartsWith("-output-kamek=")) { outputKamekPath = arg.Substring(14); } else if (arg.StartsWith("-output-riiv=")) { outputRiivPath = arg.Substring(13); } else if (arg.StartsWith("-output-gecko=")) { outputGeckoPath = arg.Substring(14); } else if (arg.StartsWith("-output-code=")) { outputCodePath = arg.Substring(13); } else if (arg.StartsWith("-input-dol=")) { inputDolPath = arg.Substring(11); } else if (arg.StartsWith("-output-dol=")) { outputDolPath = arg.Substring(12); } else if (arg.StartsWith("-externals=")) { ReadExternals(externals, arg.Substring(11)); } else if (arg.StartsWith("-versions=")) { versions = new VersionInfo(arg.Substring(10)); } else if (arg.StartsWith("-select-version=")) { selectedVersions.Add(arg.Substring(16)); } else { Console.WriteLine("warning: unrecognised argument: {0}", arg); } } else { Console.WriteLine("adding {0} as object..", arg); using (var stream = new FileStream(arg, FileMode.Open)) { modules.Add(new Elf(stream)); } } } // We need a default VersionList for the loop later if (versions == null) { versions = new VersionInfo(); } // Can we build a thing? if (modules.Count == 0) { Console.WriteLine("no input files specified"); return; } if (outputKamekPath == null && outputRiivPath == null && outputGeckoPath == null && outputCodePath == null && outputDolPath == null) { Console.WriteLine("no output path(s) specified"); return; } if (outputDolPath != null && inputDolPath == null) { Console.WriteLine("input dol path not specified"); return; } // Do safety checks if (versions.Mappers.Count > 1 && selectedVersions.Count != 1) { bool ambiguousOutputPath = false; ambiguousOutputPath |= (outputKamekPath != null && !outputKamekPath.Contains("$KV$")); ambiguousOutputPath |= (outputRiivPath != null && !outputRiivPath.Contains("$KV$")); ambiguousOutputPath |= (outputGeckoPath != null && !outputGeckoPath.Contains("$KV$")); ambiguousOutputPath |= (outputCodePath != null && !outputCodePath.Contains("$KV$")); ambiguousOutputPath |= (outputDolPath != null && !outputDolPath.Contains("$KV$")); if (ambiguousOutputPath) { Console.WriteLine("ERROR: this configuration builds for multiple game versions, and some of the outputs will be overwritten"); Console.WriteLine("add the $KV$ placeholder to your output paths, or use -select-version=.. to only build one version"); return; } } foreach (var version in versions.Mappers) { if (selectedVersions.Count > 0 && !selectedVersions.Contains(version.Key)) { Console.WriteLine("(skipping version {0} as it's not selected)", version.Key); continue; } Console.WriteLine("linking version {0}...", version.Key); var linker = new Linker(version.Value); foreach (var module in modules) { linker.AddModule(module); } if (baseAddress.HasValue) { linker.LinkStatic(baseAddress.Value, externals); } else { linker.LinkDynamic(externals); } var kf = new KamekFile(); kf.LoadFromLinker(linker); if (outputKamekPath != null) { File.WriteAllBytes(outputKamekPath.Replace("$KV$", version.Key), kf.Pack()); } if (outputRiivPath != null) { File.WriteAllText(outputRiivPath.Replace("$KV$", version.Key), kf.PackRiivolution()); } if (outputGeckoPath != null) { File.WriteAllText(outputGeckoPath.Replace("$KV$", version.Key), kf.PackGeckoCodes()); } if (outputCodePath != null) { File.WriteAllBytes(outputCodePath.Replace("$KV$", version.Key), kf.CodeBlob); } if (outputDolPath != null) { var dol = new Dol(new FileStream(inputDolPath.Replace("$KV$", version.Key), FileMode.Open)); kf.InjectIntoDol(dol); var outpath = outputDolPath.Replace("$KV$", version.Key); using (var outStream = new FileStream(outpath, FileMode.Create)) { dol.Write(outStream); } } } }
static void Main(string[] args) { Console.WriteLine("Kamek 2.0 by Treeki"); Console.WriteLine(); // Parse the command line arguments and do cool things! var modules = new List <Elf>(); uint? baseAddress = null; string outputKamekPath = null, outputRiivPath = null, outputGeckoPath = null, outputCodePath = null; string inputDolPath = null, outputDolPath = null; var externals = new Dictionary <string, uint>(); VersionInfo versions = null; foreach (var arg in args) { if (arg.StartsWith("-")) { if (arg == "-dynamic") { baseAddress = null; } else if (arg.StartsWith("-static=0x")) { baseAddress = uint.Parse(arg.Substring(10), System.Globalization.NumberStyles.HexNumber); } else if (arg.StartsWith("-output-kamek=")) { outputKamekPath = arg.Substring(14); } else if (arg.StartsWith("-output-riiv=")) { outputRiivPath = arg.Substring(13); } else if (arg.StartsWith("-output-gecko=")) { outputGeckoPath = arg.Substring(14); } else if (arg.StartsWith("-output-code=")) { outputCodePath = arg.Substring(13); } else if (arg.StartsWith("-input-dol=")) { inputDolPath = arg.Substring(11); } else if (arg.StartsWith("-output-dol=")) { outputDolPath = arg.Substring(12); } else if (arg.StartsWith("-externals=")) { ReadExternals(externals, arg.Substring(11)); } else if (arg.StartsWith("-versions=")) { versions = new VersionInfo(arg.Substring(10)); } else { Console.WriteLine("warning: unrecognised argument: {0}", arg); } } else { Console.WriteLine("adding {0} as object..", arg); using (var stream = new FileStream(arg, FileMode.Open)) { modules.Add(new Elf(stream)); } } } // We need a default VersionList for the loop later if (versions == null) { versions = new VersionInfo(); } // Can we build a thing? if (modules.Count == 0) { Console.WriteLine("no input files specified"); return; } if (outputKamekPath == null && outputRiivPath == null && outputGeckoPath == null && outputCodePath == null && outputDolPath == null) { Console.WriteLine("no output path(s) specified"); return; } if (outputDolPath != null && inputDolPath == null) { Console.WriteLine("input dol path not specified"); return; } foreach (var version in versions.Mappers) { Console.WriteLine("linking version {0}...", version.Key); var linker = new Linker(version.Value); foreach (var module in modules) { linker.AddModule(module); } if (baseAddress.HasValue) { linker.LinkStatic(baseAddress.Value, externals); } else { linker.LinkDynamic(externals); } var kf = new KamekFile(); kf.LoadFromLinker(linker); if (outputKamekPath != null) { File.WriteAllBytes(outputKamekPath.Replace("$KV$", version.Key), kf.Pack()); } if (outputRiivPath != null) { File.WriteAllText(outputRiivPath.Replace("$KV$", version.Key), kf.PackRiivolution()); } if (outputGeckoPath != null) { File.WriteAllText(outputGeckoPath.Replace("$KV$", version.Key), kf.PackGeckoCodes()); } if (outputCodePath != null) { File.WriteAllBytes(outputCodePath.Replace("$KV$", version.Key), kf.CodeBlob); } if (outputDolPath != null) { var dol = new Dol(new FileStream(inputDolPath, FileMode.Open)); kf.InjectIntoDol(dol); var outpath = outputDolPath.Replace("$KV$", version.Key); using (var outStream = new FileStream(outpath, FileMode.Create)) { dol.Write(outStream); } } } }
static void Main(string[] args) { Console.WriteLine("Kamek 2.0 by Treeki"); Console.WriteLine(); // Parse the command line arguments and do cool things! var modules = new List<Elf>(); uint? baseAddress = null; string outputKamekPath = null, outputRiivPath = null, outputGeckoPath = null; var externals = new Dictionary<string, uint>(); foreach (var arg in args) { if (arg.StartsWith("-")) { if (arg == "-dynamic") baseAddress = null; else if (arg.StartsWith("-static=0x")) baseAddress = uint.Parse(arg.Substring(10), System.Globalization.NumberStyles.HexNumber); else if (arg.StartsWith("-output-kamek=")) outputKamekPath = arg.Substring(14); else if (arg.StartsWith("-output-riiv=")) outputRiivPath = arg.Substring(13); else if (arg.StartsWith("-output-gecko=")) outputGeckoPath = arg.Substring(14); else if (arg.StartsWith("-externals=")) ReadExternals(externals, arg.Substring(11)); else Console.WriteLine("warning: unrecognised argument: {0}", arg); } else { Console.WriteLine("adding {0} as object..", arg); using (var stream = new FileStream(arg, FileMode.Open)) { modules.Add(new Elf(stream)); } } } // Can we build a thing? if (modules.Count == 0) { Console.WriteLine("no input files specified"); return; } if (outputKamekPath == null && outputRiivPath == null && outputGeckoPath == null) { Console.WriteLine("no output path(s) specified"); return; } var linker = new Linker(); foreach (var module in modules) linker.AddModule(module); if (baseAddress.HasValue) linker.LinkStatic(baseAddress.Value, externals); else linker.LinkDynamic(externals); var kf = new KamekFile(); kf.LoadFromLinker(linker); if (outputKamekPath != null) File.WriteAllBytes(outputKamekPath, kf.Pack()); if (outputRiivPath != null) File.WriteAllText(outputRiivPath, kf.PackRiivolution()); if (outputGeckoPath != null) File.WriteAllText(outputGeckoPath, kf.PackGeckoCodes()); }
public static byte[] PackFrom(Linker linker) { var kf = new KamekFile(); kf.LoadFromLinker(linker); return kf.Pack(); }
private void ApplyHook(Linker.HookData hookData) { var hook = Hooks.Hook.Create(hookData); foreach (var cmd in hook.Commands) { if (_commands.ContainsKey(cmd.Address)) throw new InvalidOperationException(string.Format("duplicate commands for address {0}", cmd.Address)); _commands[cmd.Address] = cmd; } _hooks.Add(hook); }