public static void StartGame(Session session, Action OnExit) { if (Process.GetProcessesByName("RomeTW").Length > 0) { Debug.ShowWarning("Rome is already running!"); return; } if (session == null || OnExit == null || session.Installation == null) { return; } FactionInfo currentFaction = session.GetCurrentFaction(); if (currentFaction == null) { return; } if (currentFaction != session.GetPlayerFaction()) { Debug.ShowWarning("It's not the player's turn!"); return; } CodeVersion version = session.Version; Process.Start(new ProcessStartInfo(version.ProcessStartPath ?? session.Installation.FilePath)); Process proc; long startTicks = DateTime.UtcNow.Ticks; while (true) { var arr = Process.GetProcessesByName("RomeTW"); if (arr.Length > 0) { proc = arr[0]; break; } if (DateTime.UtcNow.Ticks - startTicks > 10 * TimeSpan.TicksPerSecond) { Debug.ShowWarning("Failed to start Rome!"); return; } System.Threading.Thread.Sleep(10); } SuspendProcess(proc); proc.Exited += (s, e) => Application.Current.Dispatcher.Invoke(OnExit); proc.EnableRaisingEvents = true; EditSettings(proc, version, session); EditFactionTurnStart(proc, version, session); if (session.GetLastPlayedFaction() == null) // new campaign { EditPlayableFactions(proc, version, session); EditStartNewCampaign(proc, version, session); } else { EditLoadGame(proc, version, session); EditFinishedLoading(proc, version, session); } //System.Windows.MessageBox.Show(""); ResumeProcess(proc); }
static void EditFactionTurnStart(Process proc, CodeVersion version, Session session) { proc.Write(version.ControlFactionSelfCheckAddress, 0xEB); // make control faction ignore whether we're officially already that faction using (ProcessStream ps = new ProcessStream(proc)) { // check current faction id ps.Write(0x51); // push ecx ps.Write(0x8B, 0x0D); // mov ecx, [018CD818] ps.WriteInt(0x018CD818); ps.Write(0x8B, 0x81); // mov eax, [ecx+230] ps.WriteInt(0x230); // current faction id int nextIndex = session.SwitchIndex(session.GetCurrentFaction().Index) - 1; if (session.GetLastPlayedFaction() == null) { ps.Write(0x83, 0xF8, (byte)nextIndex); // cmp eax, nextIndex ps.Write(0x74); // je to hook exit ps.WriteByteDistance("hookexit"); } else { int lastIndex = session.SwitchIndex(session.GetLastPlayedFaction().Index) - 1; if (lastIndex == nextIndex) { nextIndex += 2; if (session.GetModFolder().GetFaction((byte)nextIndex) == null) { nextIndex = 1; } //if (currentIndex == nextIndex) do nothing; ps.Write(0x83, 0xF8, (byte)(nextIndex - 1)); // cmp eax, nextIndex ps.Write(0x75); // jne to hook exit ps.WriteByteDistance("hookexit"); } else if (lastIndex < nextIndex) { //if (currentIndex <= nextIndex && currentIndex > lastIndex) do nothing; ps.Write(0x83, 0xF8, (byte)nextIndex); // cmp eax, nextIndex ps.Write(0x77); // ja to save & quit ps.WriteByteDistance("savequit"); ps.Write(0x83, 0xF8, (byte)lastIndex); // cmp eax, lastIndex ps.Write(0x77); // ja to hook exit ps.WriteByteDistance("hookexit"); } else if (lastIndex > nextIndex) { //if (currentIndex <= nextIndex || currentIndex > lastIndex) do nothing; ps.Write(0x83, 0xF8, (byte)nextIndex); // cmp eax, nextIndex ps.Write(0x76); // jna to hookexit ps.WriteByteDistance("hookexit"); ps.Write(0x83, 0xF8, (byte)lastIndex); // cmp eax, lastIndex ps.Write(0x77); // ja to hook exit ps.WriteByteDistance("hookexit"); } ps.AddByteDistance("savequit"); } // save game ps.Write(0x6A, 0x00); // push 0 ps.Write(0x68); // push file path string ps.WriteInt(ps.AllocString(session.OutputSaveGamePath, true, 2)); ps.Write(0x8B, 0x0D, 0x28, 0xD8, 0x8C, 0x01); // mov ecx, [018CD828] ps.Write(0xE8); // call save ps.WriteRelativeAddress(0x420FB9); // close game //ps.Write(0xC6, 0x05); // mov [12CB8EC], 1 // quit, does not exit reliable between turns ???? //ps.WriteInt(0x12CB8EC); //ps.Write(0x01); ps.Write(0x6A, 0x00); // push 0 ps.Write(0xE8); // call exit, simply kills the process // bad ps.WriteRelativeAddress(0xFC5603); // hook exit ps.AddByteDistance("hookexit"); ps.Write(0x59); // pop ecx //ps.Write(0x5F, 0x5E, 0x5B, 0xC9, 0xC3); // ori code ps.Write(0xE8); ps.WriteRelativeAddress(0x8AAE20); ps.Write(0xE9); // jmp back ps.WriteRelativeAddress(version.BetweenFactionTurnsAddress + 5); int hookAddr = ps.AllocInject(); // // Jmp to factionstarthook // ps.Reset(); ps.Write(0xE9); ps.WriteRelativeAddress(hookAddr); ps.Inject(version.BetweenFactionTurnsAddress); } }
public void Read(out CodeVersion version) { int id = stream.ReadByte(); version = CodeVersion.Versions.FirstOrDefault(v => v.ID == id); }
private Installation(string filePath, CodeVersion version, IEnumerable <ModFolder> mods) { this.filePath = filePath; this.version = version; this.mods = new List <ModFolder>(mods); }
public void Write(CodeVersion version) { stream.WriteByte(version.ID); }