/// <summary> /// Selects a race. /// </summary> /// <param name="circuit">The race circuit number to select.</param> /// <param name="race">The race number to select.</param> public void SelectRace(int circuit, int race) { if (initialized) { memoryManager.WriteInt(memoryManager.CalculatePointer(memoryManager.ReadInt(MENU_BASE), SELECTED_CIRCUIT_OFFSETS), memoryManager.ReadInt(memoryManager.CalculatePointer(memoryManager.ReadInt(MENU_BASE), CIRCUIT_BASE_OFFSETS)) + 100 * circuit); memoryManager.WriteInt(memoryManager.CalculatePointer(memoryManager.ReadInt(MENU_BASE), SELECTED_RACE_OFFSETS), race); } }
/// <summary> /// Retrieves the current menu. /// </summary> /// <returns>Returns a Menu containing the current menu.</returns> public Menu GetCurrentMenu() { Menu currentMenu = Menu.MainMenu; currentMenu = (Menu)MemoryManager.ReadByte(MemoryManager.CalculatePointer(MENU_BASEADDRESS, CURRENT_MENU_OFFSET)); return(currentMenu); }
private void UnpauseGame() { MemoryManager.WriteInt(MemoryManager.CalculatePointer(INRACE_BASEADDRESS, PAUSED_SELECTED_INDEX_OFFSET), 0); // select index 0 MemoryManager.WriteInt(MemoryManager.CalculatePointer(INRACE_BASEADDRESS, PAUSED_CURRENT_MENU_OFFSET), 0); // set current menu to 0 int esi = MemoryManager.ReadInt(INRACE_BASEADDRESS) + INRACE_ESI_OFFSET; List <byte> codetoinject = new List <byte>(); codetoinject.Add(0xBE); codetoinject.AddRange(BitConverter.GetBytes(esi)); // mov esi,'esi' codetoinject.AddRange(new byte[] { 0x8B, 0xCE }); // mov ecx,esi codetoinject.Add(0xE8); codetoinject.AddRange(BitConverter.GetBytes(UNPAUSE_FUNCTION_ADDRESS - (int)(MemoryManager.NewMemory + codetoinject.Count + 4))); // call function codetoinject.Add(0xC3); // ret MemoryManager.WriteBytes(MemoryManager.NewMemory, codetoinject.ToArray()); MemoryManager.CreateThread(MemoryManager.NewMemory); // select menu item 0,0 (continue race) }
private void PauseGame() { MemoryManager.WriteInt(MemoryManager.CalculatePointer(INRACE_BASEADDRESS, INRACE_PAUSED_OFFSET), 1); // 1) pause game int esi = MemoryManager.ReadInt(INRACE_BASEADDRESS) + INRACE_ESI_OFFSET; List <byte> codetoinject = new List <byte>(); if (this.GetType() == typeof(Client_2001)) { codetoinject.AddRange(new byte[] { 0x6A, 0x00 }); // push 00 } codetoinject.Add(0xBE); codetoinject.AddRange(BitConverter.GetBytes(esi)); // mov esi,'esi' codetoinject.AddRange(new byte[] { 0x8B, 0xCE }); // mov ecx,esi codetoinject.Add(0xE8); codetoinject.AddRange(BitConverter.GetBytes(PAUSE_FUNCTION_ADDRESS - (int)(MemoryManager.NewMemory + codetoinject.Count + 4))); // call function codetoinject.Add(0xC3); // ret MemoryManager.WriteBytes(MemoryManager.NewMemory, codetoinject.ToArray()); MemoryManager.CreateThread(MemoryManager.NewMemory); // 2) stop music, open menu, etc. }
/// <summary> /// Navigates to a given menu. /// </summary> /// <param name="targetmenu">The menu to navigate to.</param> public void GotoMenu(Menu targetmenu) { if (initialized) { Menu currentMenu = GetCurrentMenu(); Console.WriteLine(currentMenu + " -> " + targetmenu); int offset = 0; int ECXbase = MemoryManager.ReadInt(MemoryManager.CalculatePointer(MENU_BASEADDRESS, TARGETMENU_ECX_OFFSET)); int ESIbase = MemoryManager.ReadInt(MemoryManager.CalculatePointer(MENU_BASEADDRESS, TARGETMENU_ESI_OFFSET)); if (ECXbase != ESIbase) // if a prompt is open { switch (currentMenu) { case Menu.Options: if (targetmenu == Menu.DisplayOptions) { offset = 0x549C; } break; case Menu.Build: // delete racer if (targetmenu == Menu.PromptYes) { offset = 0x5B38; } else if (targetmenu == Menu.PromptNo) { offset = 0x5E28; } break; case Menu.CreateDriver: // cancel if (targetmenu == Menu.PromptYes) { offset = 0x3FD0; } else if (targetmenu == Menu.PromptNo) { offset = 0x42C0; } break; default: return; } } else { switch (currentMenu) { case Menu.MainMenu: if (targetmenu == Menu.Build) { offset = 0x1058; } else if (targetmenu == Menu.SingleRace) { offset = 0x498; } else if (targetmenu == Menu.Options) { offset = 0x1348; } else if (targetmenu == Menu.TimeAttack) { offset = 0xD68; } else if (targetmenu == Menu.Circuit) { offset = 0x788; } else { return; } break; case Menu.Build: if (targetmenu == Menu.MainMenu) { offset = 0x5848; } else if (targetmenu == Menu.CreateDriver) { offset = 0x40C8; } else if (targetmenu == Menu.DeleteRacer) // opens a prompt { offset = 0x4999; } else if (targetmenu == Menu.EditRacer) // Not finished { offset = 0x43B8; } else if (targetmenu == Menu.CopyRacer) { offset = 0x46A8; } else { return; } break; case Menu.Options: if (targetmenu == Menu.MainMenu) { offset = 0x18D8; } else if (targetmenu == Menu.ControlsP1) { offset = 0xA28; } else if (targetmenu == Menu.ControlsP2) { offset = 0xD18; } else if (targetmenu == Menu.GameOptions) { offset = 0x448; } else if (targetmenu == Menu.PromptDisplayOptions) // opens a prompt { offset = 0x51AC; } else if (targetmenu == Menu.Options) // currentmenu==DisplayOptions or GameOptions { offset = 0x18D8; } else { return; } break; case Menu.Controls: if (targetmenu == Menu.Options) { offset = 0x47C; } else { return; } break; case Menu.SingleRace: if (targetmenu == Menu.MainMenu) { offset = 0x1CCC; } else if (targetmenu == Menu.ChooseRacer) { offset = 0x19DC; } else { return; } break; case Menu.TimeAttack: if (targetmenu == Menu.MainMenu) { offset = 0x1CC; } else { return; } break; case Menu.Circuit: if (targetmenu == Menu.MainMenu) { offset = 0x1c34; } else if (targetmenu == Menu.ChooseRacer) { offset = 0x1F24; } else { return; } break; case Menu.CreateDriver: if (targetmenu == Menu.CancelDriver) // opens a prompt { offset = 0x39F0; } else if (targetmenu == Menu.CreateLicense) { offset = 0x3CE0; } else { return; } break; case Menu.CreateLicense: if (targetmenu == Menu.CreateDriver) { offset = 0xA88; } else if (targetmenu == Menu.BuildCar) { offset = 0xD78; } else { return; } break; case Menu.BuildCar: if (targetmenu == Menu.Build) { offset = 0x11E4; } else if (targetmenu == Menu.CreateLicense) { offset = 0x14D4; } else { return; } break; case Menu.ChooseRacer: if (targetmenu == Menu.Circuit || targetmenu == Menu.SingleRace || targetmenu == Menu.TimeAttack) { offset = 0x4998; } else if (targetmenu == Menu.StartRace) { offset = 0x40C8; } else { return; } break; default: return; } } List <byte> codeToInject = new List <byte>(); codeToInject.Add(0xB9); codeToInject.AddRange(BitConverter.GetBytes(ECXbase)); // mov ecx,neededECX codeToInject.Add(0xBE); codeToInject.AddRange(BitConverter.GetBytes(ESIbase + offset)); // mov esi,neededESI codeToInject.AddRange(new byte[] { 0x8B, 0x11, 0x56, 0xFF, 0x52, 0x38, 0xC3 }); // mov edx,[ecx] | push esi | call dword ptr [edx+38] | ret // Write code to the assigned memory and execute it MemoryManager.WriteBytes(MemoryManager.NewMemory, codeToInject.ToArray()); MemoryManager.CreateThread(MemoryManager.NewMemory); } }