/// <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.ReadInt(MENU_BASE) + TARGETMENU_ECX_OFFSET); int ESIbase = memoryManager.ReadInt(memoryManager.ReadInt(MENU_BASE) + 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((int)memoryManager.NewMemory, codeToInject.ToArray()); memoryManager.Execute(memoryManager.NewMemory); } }
/// <summary> /// Uses a Power-up from the driver. This does not trigger the PowerUpUsed event. /// </summary> /// <param name="brick">The Brick type to use.</param> /// <param name="whiteBricks">Amount of White bricks to use.</param> public void UsePowerUp(Brick brick, int whiteBricks) { if (driverNumber >= 0 && driverNumber <= 5 && brick != Brick.White && brick != Brick.None) { int function = 0; switch (brick) { case Brick.Red: // Red Power-up function = powerUpRed; break; case Brick.Blue: // Blue Power-up function = powerUpBlue; break; case Brick.Green: // Green Power-up function = powerUpGreen; break; case Brick.Yellow: // Yellow Power-up function = powerUpYellow; break; default: return; } int raceraddress; if (driverNumber == 0) { raceraddress = memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(0x004C67BC) + 0x60) + 0xA8) + 0x114) + 0x40) - 0x121C; } else { raceraddress = memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(0x004C67BC) + 0x60) + 0xA8) + 0x110 + (int)driverNumber * 4) + 0x40) - 0x3e8; } int ecx = memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(memoryManager.ReadInt(0x004C67BC) + 0x60) + 0xA8) + 0x114) + 0x40) - 0x121C + 0x8); int ebx = 0; int edx = 0; switch (driverNumber) { case 0: // Local player ebx = ecx - 0x498; edx = ecx - 0x444; break; case 1: // Opponent 1 edx = 0xD1; break; case 2: // Opponent 2 edx = 0xA4; break; case 3: // Opponent 3 edx = 0xBA; break; case 4: // Opponent 4 edx = 0x49; break; case 5: // Opponent 5 edx = 0x8D; break; default: return; } List <byte> codeToInject = new List <byte>(); codeToInject.Add(0xBB); codeToInject.AddRange(BitConverter.GetBytes(ebx)); // mov ebx,neededEBX codeToInject.Add(0xB9); codeToInject.AddRange(BitConverter.GetBytes(ecx)); // mov ecx,neededECX codeToInject.Add(0xBA); codeToInject.AddRange(BitConverter.GetBytes(edx)); // mov edx,neededEDX codeToInject.Add(0x6A); codeToInject.Add((byte)whiteBricks); // push whitebricks codeToInject.Add(0x68); codeToInject.AddRange(BitConverter.GetBytes(raceraddress)); // push raceraddress codeToInject.Add(0xE8); codeToInject.AddRange(BitConverter.GetBytes((int)(-(memoryManager.NewMemory + codeToInject.Count + 4) + function))); // call function codeToInject.Add(0xC3); // ret // Write code to the assigned memory and execute it memoryManager.WriteBytes((int)memoryManager.NewMemory, codeToInject.ToArray()); memoryManager.Execute(memoryManager.NewMemory); /*int raceraddress; * * int ecx = memoryManager.ReadInt(memoryManager.CalculatePointer(DRIVER_BASE, ENEMY_1_BASE_OFFSETS) + 0x8); * int ebx = 0; * int edx = 0; * * switch (driverNumber) * { * case 0: // Player * raceraddress = memoryManager.ReadInt(memoryManager.CalculatePointer(DRIVER_BASE, PLAYER_BASE_OFFSETS)); * ebx = ecx - 0x498; * edx = ecx - 0x444; * break; * case 1: // AI 1 * raceraddress = memoryManager.ReadInt(memoryManager.CalculatePointer(DRIVER_BASE, ENEMY_1_BASE_OFFSETS)); * edx = 0xD1; * break; * case 2: // AI 2 * raceraddress = memoryManager.ReadInt(memoryManager.CalculatePointer(DRIVER_BASE, ENEMY_2_BASE_OFFSETS)); * edx = 0xA4; * break; * case 3: // AI 3 * raceraddress = memoryManager.ReadInt(memoryManager.CalculatePointer(DRIVER_BASE, ENEMY_3_BASE_OFFSETS)); * edx = 0xBA; * break; * case 4: // AI 4 * raceraddress = memoryManager.ReadInt(memoryManager.CalculatePointer(DRIVER_BASE, ENEMY_4_BASE_OFFSETS)); * edx = 0x49; * break; * case 5: // AI 5 * raceraddress = memoryManager.ReadInt(memoryManager.CalculatePointer(DRIVER_BASE, ENEMY_5_BASE_OFFSETS)); * edx = 0x8D; * break; * } * * List<byte> codeToInject = new List<byte>(); * * codeToInject.Add(0xBB); * codeToInject.AddRange(BitConverter.GetBytes(ebx)); // mov ebx,neededEBX * codeToInject.Add(0xB9); * codeToInject.AddRange(BitConverter.GetBytes(ecx)); // mov ecx,neededECX * codeToInject.Add(0xBA); * codeToInject.AddRange(BitConverter.GetBytes(edx)); // mov edx,neededEDX * codeToInject.Add(0x6A); * codeToInject.Add((byte)whiteBricks); // push whitebricks * codeToInject.Add(0x68); * codeToInject.AddRange(BitConverter.GetBytes(raceraddress)); // push raceraddress * codeToInject.Add(0xE8); * codeToInject.AddRange(BitConverter.GetBytes(function - (int)(MemoryManager.NewMemory + codeToInject.Count + 4))); // call function * codeToInject.Add(0xC3); // ret * memoryManager.WriteBytes((int)memoryManager.NewMemory, codeToInject.ToArray()); * memoryManager.Execute(MemoryManager.NewMemory);*/ } }