From ed05cfcf08770db220dbba69b094e8fb7124c103 Mon Sep 17 00:00:00 2001 From: Damon Murdoch Date: Fri, 22 Apr 2022 10:45:52 +1000 Subject: [PATCH 1/8] MT5DX+ Story saving, MT5 force full tune --- OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp | 454 +++----- .../src/Functions/Games/ES3X/WMMT5DXPlus.cpp | 1007 ++++++----------- 2 files changed, 506 insertions(+), 955 deletions(-) diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp index aab95a6..fc31144 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp @@ -1,10 +1,14 @@ #include #include "Utility/InitFunction.h" #include "Functions/Global.h" +#include +#include +#include #include "MinHook.h" #include #include #ifdef _M_AMD64 + #pragma optimize("", off) #pragma comment(lib, "Ws2_32.lib") @@ -425,79 +429,72 @@ unsigned int WINAPI Hook_bind(SOCKET s, const sockaddr *addr, int namelen) { unsigned char saveData[0x2000]; -// BASE: 0x24E0 -// Campaing honor data: 2998, save 0xB8 -// Story Mode Honor data: 25F0, save 0x98 -// StoryModeNoLoseHonorData: 2C80, Copy 0,0x10, Copy 0x18,0x28 maybe 8 bytes more -// OtherHonorData: 2A90, Copy 0x60 -// CampaignHonorData: 2698, Copy 0x48 -//static int SaveCampaingHonorData2() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2698; -// FILE* file = fopen(V("CampaignHonorData.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x48); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveOtherHonorData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2A90; -// FILE* file = fopen(V("OtherHonorData.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x60); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveStoryModeNoLoseHonorData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2C80; -// FILE* file = fopen(V("StoryModeNoLoseHonorData.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x10); -// value += 0x18; -// memcpy(saveData, (void *)value, 0x28); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveCampaingHonorData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2998; -// FILE* file = fopen(V("campaing.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0xB8); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveStoryData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x25F0; -// FILE* file = fopen(V("story.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x98); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} +// forceFullTune(pArguments: void*): DWORD WINAPI +// Function which runs in a secondary thread if the forceFullTune +// option is selected in the compiler. If the player's car is not fully +// tuned, it is forcibly set to max tune. If the player's car is already +// fully tuned, it is left alone. +static DWORD WINAPI forceFullTune(void* pArguments) +{ + // Loops while the program is running + while (true) { + + // Only runs every 16th frame + Sleep(16); + + // Car save hex address + auto carSaveBase = (uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); + auto powerAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase) + 0x98); + auto handleAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase) + 0x9C); + + // Dereference the power value from the memory address + auto powerValue = injector::ReadMemory(powerAddress, true); + auto handleValue = injector::ReadMemory(handleAddress, true); + + // If the power and handling values do not add up to fully tuned + if (powerValue + handleValue < 0x20) + { + // Car is not fully tuned, force it to the default full tune + injector::WriteMemory(powerAddress, 0x10, true); + injector::WriteMemory(handleAddress, 0x10, true); + } + + // Otherwise, don't do anything :) + } +} + +// ******************************************** // +// ************ Debug Data Logging ************ // +// ******************************************** // + +// ************* Global Variables ************* // + +// **** String Variables + +// Debugging event log file +std::string logfile = "wmmt5_errors.txt"; + +// writeLog(filename: String, message: String): Int +// Given a filename string and a message string, appends +// the message to the given file. +static int writeLog(std::string filename, std::string message) +{ + // Log file to write to + std::ofstream eventLog; + + // Open the filename provided (append mode) + eventLog.open(filename, std::ios_base::app); + + // Write the message to the file + eventLog << message; + + // Close the log file handle + eventLog.close(); + + // Success + return 0; +} static bool saveOk = false; unsigned char carData[0xFF]; @@ -516,10 +513,14 @@ static int SaveGameData() if (!saveOk) return 1; + // Zero out save data binary memset(saveData, 0, 0x2000); + + // Get the hex address for the start of the save data block uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); value = *(uintptr_t*)(value + 0x108); memcpy(saveData, (void *)value, 0x340); + FILE* file = fopen("openprogress.sav", "wb"); fwrite(saveData, 1, 0x2000, file); fclose(file); @@ -527,6 +528,7 @@ static int SaveGameData() // Car Profile saving memset(carData, 0, 0xFF); memset(carFileName, 0, 0xFF); + memcpy(carData, (void *)*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18), 0xE0); CreateDirectoryA("OpenParrot_Cars", nullptr); if(customCar) @@ -551,118 +553,6 @@ static int SaveGameData() uintptr_t saveGameOffset; -//static int LoadCampaingHonorData2() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("CampaignHonorData.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2698; -// memcpy((void *)value, saveData, 0x48); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadOtherHonorData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("OtherHonorData.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2A90; -// memcpy((void *)value, saveData, 0x60); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadStoryModeNoLoseHonorData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("StoryModeNoLoseHonorData.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2C80; -// //memcpy((void *)value, saveData, 0x10); -// value += 0x18; -// memcpy((void *)value, saveData, 0x28); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadCampaingHonorData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("campaing.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x24E0; -// memcpy((void *)value, saveData, 0xB8); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadStoryData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("story.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x25F0; -// memcpy((void *)value, saveData, 0x98); -// } -// fclose(file); -// } -// return 1; -//} - static int LoadGameData() { saveOk = false; @@ -710,95 +600,10 @@ static int LoadGameData() value -= 0x2B8; loadOk = true; - - //+ 0x80 - - //+ [0x340] - - // [[[[0000000005CE5850] + 108] + 340] + 50] + 50 - // [[[[0000000005CE5850] + 108] + 340] + 50] + 54 - // wmn5r.exe + 1948BF8 - //TA stuff - - //[[[[magic_rva]+108]+340]+50] - - //value += 0x24E0; - // First chunk - //memcpy((void *)(value + 0x16), saveData + 0x16, 0x28); - //// - //memcpy((void *)(value + 0x40), saveData + 0x40, 0x18); - //// - //memcpy((void *)(value + 0x60), saveData + 0x60, 0x20); - //// - //memcpy((void *)(value + 0x90), saveData + 0x90, 0x28); - //// - //memcpy((void *)(value + 0xC0), saveData + 0xC0, 0x10); - //// - //memcpy((void *)(value + 0xD8), saveData + 0xD8, 0x28); // OK - //// - //memcpy((void *)(value + 0x110), saveData + 0x110, 0x98); - //// - //memcpy((void *)(value + 0x1B8), saveData + 0x1B8, 0x48); - //// - //memcpy((void *)(value + 0x208), saveData + 0x208, 0x28); - //// - //memcpy((void *)(value + 0x240), saveData + 0x240, 0x68); - //// - //memcpy((void *)(value + 0x2B8), saveData + 0x2B8, 0x88); - // - //memcpy((void *)(value + 0x370), saveData + 0x370, 0x10); - //// - //memcpy((void *)(value + 0x388), saveData + 0x388, 0x90); - //// - //memcpy((void *)(value + 0x420), saveData + 0x420, 0x18); - //// - //memcpy((void *)(value + 0x440), saveData + 0x440, 0x18); - //// - //memcpy((void *)(value + 0x460), saveData + 0x460, 0x48); - //// - //memcpy((void *)(value + 0x4B8), saveData + 0x4B8, 0xB8); - //// - //memcpy((void *)(value + 0x578), saveData + 0x578, 0x08); - //// - //memcpy((void *)(value + 0x5A8), saveData + 0x5A8, 0x68); - //// - //memcpy((void *)(value + 0x628), saveData + 0x628, 0x48); - //// - //memcpy((void *)(value + 0x688), saveData + 0x688, 0x48); - //// - //memcpy((void *)(value + 0x6E8), saveData + 0x6E8, 0xA8); - //// - //memcpy((void *)(value + 0x7A0), saveData + 0x7A0, 0x10); - //// - //memcpy((void *)(value + 0x7B8), saveData + 0x7B8, 0x28); - //// - //memcpy((void *)(value + 0x7E8), saveData + 0x7E8, 0x10); - //// - ////memcpy((void *)(value + 0x800), saveData + 0x800, 0x48); // Problem - ////// - //memcpy((void *)(value + 0x850), saveData + 0x850, 0x08); - // - //memcpy((void *)(value + 0x860), saveData + 0x860, 0x08); - ////// - //memcpy((void *)(value + 0x870), saveData + 0x870, 0x18); - //// - //memcpy((void *)(value + 0x890), saveData + 0x890, 0x40); - //// - //memcpy((void *)(value + 0x8E0), saveData + 0x8E0, 0x10); - //// - //memcpy((void *)(value + 0x8F8), saveData + 0x8F8, 0x28); - //// - //memcpy((void *)(value + 0x928), saveData + 0x928, 0x10); - //// - //memcpy((void *)(value + 0x940), saveData + 0x940, 0x48); // Problem } fclose(file); } - //LoadStoryData(); - //LoadCampaingHonorData(); - //LoadStoryModeNoLoseHonorData(); - //LoadOtherHonorData(); - //LoadCampaingHonorData2(); + return 1; } @@ -825,27 +630,36 @@ static void LoadWmmt5CarData() fseek(file, 0, SEEK_SET); fread(carData, fsize, 1, file); uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); - memcpy((void *)(carSaveLocation + 0x08), carData + 0x08, 8); - memcpy((void *)(carSaveLocation + 0x10), carData + 0x10, 8); - memcpy((void *)(carSaveLocation + 0x20), carData + 0x20, 8); - memcpy((void *)(carSaveLocation + 0x28), carData + 0x28, 8); - memcpy((void *)(carSaveLocation + 0x30), carData + 0x30, 8); - memcpy((void *)(carSaveLocation + 0x38), carData + 0x38, 8); - memcpy((void *)(carSaveLocation + 0x40), carData + 0x40, 8); - memcpy((void *)(carSaveLocation + 0x50), carData + 0x50, 8); - memcpy((void *)(carSaveLocation + 0x58), carData + 0x58, 8); - memcpy((void *)(carSaveLocation + 0x68), carData + 0x68, 8); - memcpy((void *)(carSaveLocation + 0x7C), carData + 0x7C, 1); //should add neons - memcpy((void *)(carSaveLocation + 0x80), carData + 0x80, 8); - memcpy((void *)(carSaveLocation + 0x88), carData + 0x88, 8); - memcpy((void *)(carSaveLocation + 0x90), carData + 0x90, 8); - memcpy((void *)(carSaveLocation + 0x98), carData + 0x98, 8); - memcpy((void *)(carSaveLocation + 0xA0), carData + 0xA0, 8); - memcpy((void *)(carSaveLocation + 0xA8), carData + 0xA8, 8); - memcpy((void *)(carSaveLocation + 0xB8), carData + 0xB8, 8); - memcpy((void *)(carSaveLocation + 0xC8), carData + 0xC8, 8); - memcpy((void *)(carSaveLocation + 0xD8), carData + 0xD8, 8); + + // memcpy((void *)(carSaveLocation + 0x08), carData + 0x08, 8); + // memcpy((void *)(carSaveLocation + 0x10), carData + 0x10, 8); + // memcpy((void *)(carSaveLocation + 0x20), carData + 0x20, 8); + // memcpy((void *)(carSaveLocation + 0x28), carData + 0x28, 8); + memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 1); // Stock Colour + memcpy((void*)(carSaveLocation + 0x34), carData + 0x34, 1); // Custom Colour + memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 1); // Rims Type + memcpy((void*)(carSaveLocation + 0x3C), carData + 0x3C, 1); // Rims Colour + memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 1); // Aero Type + memcpy((void*)(carSaveLocation + 0x44), carData + 0x44, 1); // Hood Type + memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 1); // Wing Type + memcpy((void*)(carSaveLocation + 0x54), carData + 0x54, 1); // Mirror Type + memcpy((void*)(carSaveLocation + 0x58), carData + 0x58, 1); // Body Sticker Type + memcpy((void*)(carSaveLocation + 0x5C), carData + 0x5C, 1); // Body Sticker Variant + // memcpy((void *)(carSaveLocation + 0x68), carData + 0x68, 8); + memcpy((void*)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neons + memcpy((void*)(carSaveLocation + 0x80), carData + 0x80, 1); // Trunk + memcpy((void*)(carSaveLocation + 0x84), carData + 0x80, 1); // Plate Frame + memcpy((void*)(carSaveLocation + 0x8A), carData + 0x8A, 1); // Plate Frame Colour + // memcpy((void *)(carSaveLocation + 0x90), carData + 0x90, 8); + memcpy((void*)(carSaveLocation + 0x98), carData + 0x98, 1); // Power + memcpy((void*)(carSaveLocation + 0x9C), carData + 0x9C, 1); // Handling + memcpy((void*)(carSaveLocation + 0xA4), carData + 0xA4, 1); // Rank + // memcpy((void *)(carSaveLocation + 0xA8), carData + 0xA8, 8); + // memcpy((void *)(carSaveLocation + 0xB8), carData + 0xB8, 8); + // memcpy((void *)(carSaveLocation + 0xC8), carData + 0xC8, 8); + // memcpy((void *)(carSaveLocation + 0xD8), carData + 0xD8, 8); //memcpy((void *)(carSaveLocation + 0xE0), carData + 0xE0, 8); + customCar = true; } loadOk = false; @@ -854,6 +668,13 @@ static void LoadWmmt5CarData() } } + // If the force full tune switch is set + if (ToBool(config["Tune"]["Force Full Tune"])) + { + // Create the force full tune thread + CreateThread(0, 0, forceFullTune, 0, 0, 0); + } + memset(carFileName, 0, 0xFF); // Load actual car if available sprintf(carFileName, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); @@ -869,26 +690,34 @@ static void LoadWmmt5CarData() fseek(file, 0, SEEK_SET); fread(carData, fsize, 1, file); uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); - memcpy((void *)(carSaveLocation + 0x08), carData + 0x08, 8); - memcpy((void *)(carSaveLocation + 0x10), carData + 0x10, 8); - memcpy((void *)(carSaveLocation + 0x20), carData + 0x20, 8); - memcpy((void *)(carSaveLocation + 0x28), carData + 0x28, 8); - memcpy((void *)(carSaveLocation + 0x30), carData + 0x30, 8); - memcpy((void *)(carSaveLocation + 0x38), carData + 0x38, 8); - memcpy((void *)(carSaveLocation + 0x40), carData + 0x40, 8); - memcpy((void *)(carSaveLocation + 0x50), carData + 0x50, 8); - memcpy((void *)(carSaveLocation + 0x58), carData + 0x58, 8); - memcpy((void *)(carSaveLocation + 0x68), carData + 0x68, 8); - memcpy((void *)(carSaveLocation + 0x7C), carData + 0x7C, 1); //should add neons - memcpy((void *)(carSaveLocation + 0x80), carData + 0x80, 8); - memcpy((void *)(carSaveLocation + 0x88), carData + 0x88, 8); - memcpy((void *)(carSaveLocation + 0x90), carData + 0x90, 8); - memcpy((void *)(carSaveLocation + 0x98), carData + 0x98, 8); - memcpy((void *)(carSaveLocation + 0xA0), carData + 0xA0, 8); - memcpy((void *)(carSaveLocation + 0xA8), carData + 0xA8, 8); - memcpy((void *)(carSaveLocation + 0xB8), carData + 0xB8, 8); - memcpy((void *)(carSaveLocation + 0xC8), carData + 0xC8, 8); - memcpy((void *)(carSaveLocation + 0xD8), carData + 0xD8, 8); + + // memcpy((void *)(carSaveLocation + 0x08), carData + 0x08, 8); + // memcpy((void *)(carSaveLocation + 0x10), carData + 0x10, 8); + // memcpy((void *)(carSaveLocation + 0x20), carData + 0x20, 8); + // memcpy((void *)(carSaveLocation + 0x28), carData + 0x28, 8); + memcpy((void *)(carSaveLocation + 0x30), carData + 0x30, 1); // Stock Colour + memcpy((void *)(carSaveLocation + 0x34), carData + 0x34, 1); // Custom Colour + memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 1); // Rims Type + memcpy((void *)(carSaveLocation + 0x3C), carData + 0x3C, 1); // Rims Colour + memcpy((void *)(carSaveLocation + 0x40), carData + 0x40, 1); // Aero Type + memcpy((void *)(carSaveLocation + 0x44), carData + 0x44, 1); // Hood Type + memcpy((void *)(carSaveLocation + 0x50), carData + 0x50, 1); // Wing Type + memcpy((void *)(carSaveLocation + 0x54), carData + 0x54, 1); // Mirror Type + memcpy((void *)(carSaveLocation + 0x58), carData + 0x58, 1); // Body Sticker Type + memcpy((void *)(carSaveLocation + 0x5C), carData + 0x5C, 1); // Body Sticker Variant + // memcpy((void *)(carSaveLocation + 0x68), carData + 0x68, 8); + memcpy((void *)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neons + memcpy((void *)(carSaveLocation + 0x80), carData + 0x80, 1); // Trunk + memcpy((void *)(carSaveLocation + 0x84), carData + 0x80, 1); // Plate Frame + memcpy((void *)(carSaveLocation + 0x8A), carData + 0x8A, 1); // Plate Frame Colour + // memcpy((void *)(carSaveLocation + 0x90), carData + 0x90, 8); + memcpy((void *)(carSaveLocation + 0x98), carData + 0x98, 1); // Power + memcpy((void *)(carSaveLocation + 0x9C), carData + 0x9C, 1); // Handling + memcpy((void *)(carSaveLocation + 0xA4), carData + 0xA4, 1); // Rank + // memcpy((void *)(carSaveLocation + 0xA8), carData + 0xA8, 8); + // memcpy((void *)(carSaveLocation + 0xB8), carData + 0xB8, 8); + // memcpy((void *)(carSaveLocation + 0xC8), carData + 0xC8, 8); + // memcpy((void *)(carSaveLocation + 0xD8), carData + 0xD8, 8); //memcpy((void *)(carSaveLocation + 0xE0), carData + 0xE0, 8); } fclose(file); @@ -1150,6 +979,7 @@ static InitFunction Wmmt5Func([]() hookPort = "COM3"; imageBase = (uintptr_t)GetModuleHandleA(0); + MH_Initialize(); // Hook dongle funcs @@ -1162,8 +992,6 @@ static InitFunction Wmmt5Func([]() MH_CreateHookApi(L"hasp_windows_x64_109906.dll", "hasp_login", Hook_hasp_login, NULL); MH_CreateHookApi(L"WS2_32", "bind", Hook_bind, reinterpret_cast(&pbind)); - - GenerateDongleData(isTerminal); // Patch some check @@ -1330,7 +1158,7 @@ static InitFunction Wmmt5Func([]() safeJMP(imageBase + 0x561290, ReturnTrue); safeJMP(imageBase + 0x5A0AE8, LoadWmmt5CarData); - + // crash fix //safeJMP(imageBase + 0xAD6F28, WmmtOperatorDelete); //safeJMP(imageBase + 0xAD6F4C, WmmtMemset); diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp index 9a82c40..ecc2b69 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp @@ -19,45 +19,9 @@ static bool isFreePlay; static bool isEventMode2P; static bool isEventMode4P; const char *ipaddrdxplus; -/* -// Data for IC card, Force Feedback etc OFF. -unsigned char settingData[408] = { - 0x1F, 0x8B, 0x08, 0x08, 0x53, 0x6A, 0x8B, 0x5A, 0x00, 0x03, 0x46, 0x73, - 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x2E, 0x6C, 0x75, 0x61, 0x00, 0x85, - 0x93, 0x5B, 0x6F, 0x82, 0x30, 0x14, 0xC7, 0xDF, 0xF9, 0x14, 0x7E, 0x01, - 0x17, 0x11, 0xE7, 0xDC, 0xC3, 0x1E, 0x14, 0x65, 0x9A, 0x48, 0x66, 0x94, - 0x68, 0xB2, 0xB7, 0x5A, 0x8E, 0xD2, 0xD8, 0x8B, 0x29, 0xED, 0x16, 0xBF, - 0xFD, 0x5A, 0xA8, 0x50, 0xB2, 0x65, 0xF2, 0x40, 0xF8, 0xFF, 0xCE, 0x85, - 0x73, 0x69, 0xFB, 0xFD, 0xFF, 0x9F, 0xC0, 0xBE, 0x7A, 0x25, 0x28, 0x45, - 0xF8, 0xF9, 0x89, 0x6A, 0x14, 0x3C, 0x08, 0xE8, 0x07, 0x01, 0x8B, 0x11, - 0x25, 0xC7, 0x25, 0xE2, 0x39, 0x85, 0x18, 0xB8, 0x02, 0xD9, 0x7B, 0xEB, - 0x45, 0xC3, 0x97, 0xF1, 0xC4, 0x99, 0xA6, 0x18, 0x03, 0x6D, 0x2C, 0x03, - 0x47, 0x67, 0x12, 0x5D, 0xE0, 0x17, 0x4D, 0x85, 0x12, 0xB2, 0xA1, 0xCF, - 0x61, 0xE8, 0x78, 0x26, 0x34, 0x2E, 0xD6, 0x70, 0x52, 0x86, 0x0E, 0x07, - 0xA3, 0x89, 0x8F, 0xB7, 0xE4, 0x5C, 0x58, 0x1E, 0x8E, 0xA2, 0x68, 0xEC, - 0x1B, 0x32, 0x71, 0xFD, 0x0B, 0xCF, 0x84, 0x52, 0x82, 0xB5, 0x89, 0x04, - 0xE1, 0x71, 0xA1, 0x15, 0x58, 0xDF, 0x80, 0xCD, 0xF4, 0x2D, 0x46, 0x32, - 0x8F, 0x45, 0x69, 0x73, 0x46, 0x01, 0x7B, 0x47, 0x0C, 0x9C, 0x1A, 0x5A, - 0x6F, 0x6E, 0x66, 0xA3, 0x3D, 0x92, 0x68, 0x4A, 0x63, 0xA1, 0x65, 0x79, - 0x67, 0x23, 0xC3, 0x24, 0xC0, 0x86, 0xA2, 0x5B, 0x9D, 0x72, 0x83, 0x8F, - 0xAB, 0xBC, 0x6E, 0x72, 0x85, 0x6D, 0xF2, 0xED, 0xB7, 0xAF, 0xF6, 0xC0, - 0xF3, 0xFB, 0x10, 0xD2, 0xB3, 0x6F, 0x4F, 0x84, 0xC4, 0x90, 0x00, 0xE4, - 0x47, 0x84, 0x2F, 0x35, 0x3A, 0x10, 0x5E, 0x4E, 0x79, 0xBE, 0x05, 0x86, - 0xCC, 0x57, 0x9D, 0x7F, 0xF1, 0x65, 0x06, 0x96, 0x8A, 0x1C, 0x6A, 0x97, - 0x46, 0xCE, 0x49, 0x55, 0x8F, 0x8F, 0x4C, 0xA1, 0xDC, 0xD5, 0x18, 0x53, - 0x51, 0x42, 0x76, 0xBB, 0x82, 0x6B, 0xCC, 0xCA, 0x9D, 0xE6, 0x46, 0xBD, - 0x8E, 0x9D, 0x4C, 0x45, 0x47, 0x66, 0x1A, 0x7C, 0x79, 0x80, 0xBC, 0x63, - 0x2D, 0xB4, 0x2F, 0x13, 0x49, 0x7C, 0xB9, 0x43, 0xCA, 0x97, 0xF3, 0x6A, - 0x36, 0x56, 0x56, 0x2B, 0xD9, 0x20, 0x0E, 0xB4, 0x2E, 0xD5, 0x8E, 0x7B, - 0x2F, 0xAC, 0x08, 0x8D, 0x9A, 0x2A, 0x25, 0x11, 0x56, 0x2D, 0xF8, 0x38, - 0x9D, 0x28, 0xE1, 0xD0, 0x76, 0x6B, 0xD2, 0xE1, 0x8B, 0xA1, 0xE6, 0xD0, - 0xD6, 0x20, 0x23, 0x0C, 0x3E, 0x05, 0xBF, 0xB7, 0x66, 0x77, 0x6F, 0x91, - 0xF9, 0xE3, 0xDA, 0x1D, 0x14, 0xCF, 0x69, 0x69, 0x16, 0xD7, 0x04, 0x4F, - 0x5A, 0x9E, 0x12, 0xEE, 0xE7, 0xDC, 0x69, 0xC6, 0x40, 0x5A, 0x63, 0x27, - 0xA0, 0x63, 0xE9, 0x86, 0x3C, 0xBC, 0x37, 0xD5, 0x4D, 0x5B, 0x7C, 0x24, - 0x8F, 0x3D, 0x7F, 0x00, 0x10, 0x1E, 0x34, 0xD9, 0xB5, 0x03, 0x00, 0x00 -}; -*/ + +// MUST DISABLE IC CARD, FFB MANUALLY N MT5DX+ + // FOR FREEPLAY unsigned char dxpterminalPackage1_Free[79] = { 0x01, 0x04, 0x4B, 0x00, 0x12, 0x14, 0x0A, 0x00, 0x10, 0x04, 0x18, 0x00, @@ -210,7 +174,6 @@ unsigned char dxpterminalPackage6_Coin[139] = { 0x00, 0x28, 0x00, 0xBD, 0x07, 0xCF, 0xDC }; - //Event mode 2P unsigned char dxpterminalPackage1_Event4P[79] = { 0x01, 0x04, 0x44, 0x00, 0x12, 0x0e, 0x0a, 0x00, 0x10, 0x04, 0x18, 0x00, @@ -411,80 +374,6 @@ unsigned int dxpHook_hasp_write(int hasp_handle, int hasp_fileid, unsigned int o unsigned char saveDatadxp[0x2000]; unsigned char mileDatadxp[0x08]; -// BASE: 0x24E0 -// Campaing honor data: 2998, save 0xB8 -// Story Mode Honor data: 25F0, save 0x98 -// StoryModeNoLoseHonorData: 2C80, Copy 0,0x10, Copy 0x18,0x28 maybe 8 bytes more -// OtherHonorData: 2A90, Copy 0x60 -// CampaignHonorData: 2698, Copy 0x48 - -//static int SaveCampaingHonorData2() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2698; -// FILE* file = fopen(V("CampaignHonorData.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x48); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveOtherHonorData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2A90; -// FILE* file = fopen(V("OtherHonorData.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x60); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveStoryModeNoLoseHonorData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2C80; -// FILE* file = fopen(V("StoryModeNoLoseHonorData.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x10); -// value += 0x18; -// memcpy(saveData, (void *)value, 0x28); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveCampaingHonorData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2998; -// FILE* file = fopen(V("campaing.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0xB8); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} -// -//static int SaveStoryData() -//{ -// memset(saveData, 0, 0x1000); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x25F0; -// FILE* file = fopen(V("story.sav"), V("wb")); -// memcpy(saveData, (void *)value, 0x98); -// fwrite(saveData, 1, 0x100, file); -// fclose(file); -// return 1; -//} - //set system date patch by pockywitch typedef bool (WINAPI* SETSYSTEMTIME)(SYSTEMTIME* in); SETSYSTEMTIME pSetSystemTime = NULL; @@ -494,53 +383,128 @@ bool WINAPI Hook_SetSystemTime(SYSTEMTIME* in) return TRUE; } -static DWORD WINAPI forceFT(void* pArguments) +// forceFullTune(pArguments: void*): DWORD WINAPI +// Function which runs in a secondary thread if the forceFullTune +// option is selected in the menu. If the player's car is not fully +// tuned, it is forcibly set to max tune. If the player's car is already +// fully tuned, it is left alone. +static DWORD WINAPI forceFullTune(void* pArguments) { + // Loops while the program is running while (true) { + + // Only runs every 16th frame Sleep(16); + + // Get the memory addresses for the car base save, power and handling values auto carSaveBase = (uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x01F7D578) + 0x268); auto powerAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0xAC); auto handleAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0xB8); - injector::WriteMemory(powerAddress, 0x10, true); - injector::WriteMemory(handleAddress, 0x10, true); + + // Dereference the power value from the memory address + auto powerValue = injector::ReadMemory(powerAddress, true); + auto handleValue = injector::ReadMemory(handleAddress, true); + + // If the power and handling values do not add up to fully tuned + if (powerValue + handleValue < 0x20) + { + // Car is not fully tuned, force it to the default full tune + injector::WriteMemory(powerAddress, 0x10, true); + injector::WriteMemory(handleAddress, 0x10, true); + } + + // Otherwise, don't do anything :) + } +} + +// ******************************************** // +// ************ Debug Data Logging ************ // +// ******************************************** // + +// ************* Global Variables ************* // + +// **** String Variables + +// Debugging event log file +std::string logfileDxp = "wmmt5dxp_errors.txt"; + +// writeLog(filename: String, message: String): Int +// Given a filename string and a message string, appends +// the message to the given file. +static int writeLog(std::string filename, std::string message) +{ + // Log file to write to + std::ofstream eventLog; + + // Open the filename provided (append mode) + eventLog.open(filename, std::ios_base::app); + + // File open success + if (eventLog.is_open()) + { + // Write the message to the file + eventLog << message; + + // Close the log file handle + eventLog.close(); + + // Success + return 0; + } + else // File open failed + { + // Failure + return 1; + } +} + +// writeDump(filename: Char*, data: unsigned char *, size: size_t): Int +static int writeDump(char * filename, unsigned char * data, size_t size) +{ + // Open the file with the provided filename + FILE* file = fopen(filename, "wb"); + + // File opened successfully + if (file) + { + // Write the data to the file + fwrite((void*)data, 1, size, file); + + // Close the file + fclose(file); + + // Return success status + return 0; + } + else // Failed to open + { + // Return failure status + return 1; } - //debug - /* - std::ofstream myfile("debug.txt"); - myfile << "Base: "; - myfile << carSaveBase; - myfile << " Power: "; - myfile << powerAddress; - myfile << " Handling: "; - myfile << handleAddress; - myfile.close(); - */ } static bool saveOk = false; -unsigned char carDatadxp[0xFF]; +unsigned char carDataDxp[0xFF]; static int SaveOk() { saveOk = true; return 1; } -char carFileNamedxp[0xFF]; -bool loadOkdxp = false; -bool customCardxp = false; +char carFileNameDxp[0xFF]; +bool loadOkDxp = false; +bool customCarDxp = false; -static void saveMileagedxp() +static void saveMileage() { - - //Mileage Write to "GAME/mileage.dat" auto mileageLocation = (uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x280); - //try this maybe, casting to int probably not right/not gonna work + FILE* tempFile = fopen("mileage.dat", "wb"); fwrite(mileageLocation, 1, sizeof(mileageLocation), tempFile); fclose(tempFile); } -static void LoadMileagedxp() +static void LoadMileage() { memset(mileDatadxp, 0, 0x08); @@ -560,352 +524,214 @@ static void LoadMileagedxp() } } - static int SaveGameData() { if (!saveOk) return 1; + writeLog(logfileDxp, "[DEBUG] Saving game data ...\n"); + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + + // Save story data + + // Zero out save data binary + memset(saveDatadxp, 0, 0x2000); + + // Address where the player story data starts + uintptr_t storySaveBase = *(uintptr_t*)(saveDataBase + 0x108); + + // Copy 340 nibbles to saveDatadxp from the story save data index + memcpy(saveDatadxp, (void*)storySaveBase, 0x340); + + // Dump the save data to openprogress.sav + writeDump("openprogress.sav", saveDatadxp, 0x2000); + // Car Profile saving - memset(carDatadxp, 0, 0xFF); - memset(carFileNamedxp, 0, 0xFF); + memset(carDataDxp, 0, 0xFF); + memset(carFileNameDxp, 0, 0xFF); //new multilevel - uintptr_t carSaveBase = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x268); + uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x268); - //memcpy(carData + 0x00, (void*)(carSaveBase + 0xAC), 0x1); - //memcpy(carData + 0x01, (void*)(carSaveBase + 0xB8), 0x1); //successfully dumped power and handling! - memcpy(carDatadxp + 0x00, (void*)(carSaveBase + 0x0), 0xFF); //dumps whole region + memcpy(carDataDxp + 0x00, (void*)(carSaveBase + 0x0), 0xFF); //dumps whole region CreateDirectoryA("OpenParrot_Cars", nullptr); - if (customCardxp) + if (customCarDxp) { - sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\custom.car"); + sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\custom.car"); } else { - sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); + sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); } - FILE* file = fopen(carFileNamedxp, "wb"); - fwrite(carDatadxp, 1, 0xFF, file); - fclose(file); + FILE* carFile = fopen(carFileNameDxp, "wb"); + fwrite(carDataDxp, 1, 0xFF, carFile); + fclose(carFile); - saveMileagedxp(); + saveMileage(); saveOk = false; return 1; - - /* - memset(saveData, 0, 0x2000); - uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); - value = *(uintptr_t*)(value + 0x108); - memcpy(saveData, (void *)value, 0x340); - FILE* file = fopen("openprogress.sav", "wb"); - fwrite(saveData, 1, 0x2000, file); - fclose(file); - - // Car Profile saving - memset(carData, 0, 0xFF); - memset(carFileNamedxp, 0, 0xFF); - memcpy(carData, (void *)*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18), 0xE0); - CreateDirectoryA("OpenParrot_Cars", nullptr); - if(customCardxp) - { - sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\custom.car"); - } - else - { - sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); - } - FILE *carSave = fopen(carFileNamedxp, "wb"); - fwrite(carData, 1, 0xE0, file); - fclose(carSave); - //SaveStoryData(); - //SaveCampaingHonorData(); - //SaveStoryModeNoLoseHonorData(); - //SaveOtherHonorData(); - //SaveCampaingHonorData2(); - saveOk = false; - return 1; - */ } uintptr_t saveGameOffsetdxp; -//static int LoadCampaingHonorData2() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("CampaignHonorData.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2698; -// memcpy((void *)value, saveData, 0x48); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadOtherHonorData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("OtherHonorData.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2A90; -// memcpy((void *)value, saveData, 0x60); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadStoryModeNoLoseHonorData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("StoryModeNoLoseHonorData.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x2C80; -// //memcpy((void *)value, saveData, 0x10); -// value += 0x18; -// memcpy((void *)value, saveData, 0x28); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadCampaingHonorData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("campaing.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x24E0; -// memcpy((void *)value, saveData, 0xB8); -// } -// fclose(file); -// } -// return 1; -//} -// -//static int LoadStoryData() -//{ -// memset(saveData, 0x0, 0x1000); -// FILE* file = fopen(V("story.sav"), V("rb")); -// if (file) -// { -// fseek(file, 0, SEEK_END); -// int fsize = ftell(file); -// if (fsize == 0x100) -// { -// fseek(file, 0, SEEK_SET); -// fread(saveData, fsize, 1, file); -// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); -// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); -// value += 0x25F0; -// memcpy((void *)value, saveData, 0x98); -// } -// fclose(file); -// } -// return 1; -//} - static int LoadGameData() { saveOk = false; + + // Zero out the save data array memset(saveDatadxp, 0x0, 0x2000); + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + + // Open the openprogress file with read privileges FILE* file = fopen("openprogress.sav", "rb"); + + // If the file exists if (file) { + // Get all of the contents from the file fseek(file, 0, SEEK_END); + + // Get the size of the file int fsize = ftell(file); + + // If the file has 2000 nibbles (correct size) if (fsize == 0x2000) { + // Reset seek index to start fseek(file, 0, SEEK_SET); + + // Read all of the contents of the file into saveDatadxp fread(saveDatadxp, fsize, 1, file); - uintptr_t value = *(uintptr_t*)(imageBasedxplus + 0x1948F10); - value = *(uintptr_t*)(value + 0x108); + + // Story save data offset + uintptr_t storyOffset = *(uintptr_t*)(saveDataBase + 0x108); + + // Try copying everything??? lmfao + + // Backup for storing the data BEFORE I write to memory + unsigned char saveDataPre[0x340]; + + writeLog(logfileDxp, "Backup for storing the data BEFORE I write to memory OK"); + + // Flash the pre-backup to all zeros + memset(saveDataPre, 0, 0x340); + + writeLog(logfileDxp, "Flash the pre-backup to all zeros OK"); + + // Copy the existing data in the game to the array + memcpy(saveDataPre, (void*)(storyOffset), 0x340); + + writeLog(logfileDxp, "Copy the existing data in the game to the array OK"); + + // Dump the existing memory to disk + writeDump("memory_before.bin", saveDataPre, 0x340); + + writeLog(logfileDxp, "Dump the existing memory to disk OK"); + + // Dump the data that is being copied to a file + // writeDump("openprogress_test.sav", saveDatadxp + 0x70, 0x100); + // memcpy((void*)(storyOffset + 0x70), saveDatadxp + 0x70, 0x100); + + // memcpy((void*)(storyOffset + 0x7C), saveDatadxp + 0x7C, 0x1); // Not sure + // memcpy((void*)(storyOffset + 0xE0), saveDatadxp + 0xE0, 0x1); // Not sure + // memcpy((void*)(storyOffset + 0xE4), saveDatadxp + 0xE4, 0x1); // Not sure + // memcpy((void*)(storyOffset + 0xEC), saveDatadxp + 0xEC, 0x1); // Not sure + // memcpy((void*)(storyOffset + 0xEC), saveDatadxp + 0xEC, 0x1); // Not sure + // memcpy((void*)(storyOffset + 0x10C), saveDatadxp + 0x10C, 0x1); // Not sure + + // Not sure why, but story doesn't load unless I add this + memcpy((void*)(storyOffset + 0x48), saveDatadxp + 0x48, 0x1); + + // Pretty sure this is the whole save file region, but need to test more :) + memcpy((void*)(storyOffset + 0xE0), saveDatadxp + 0xE0, 0x80); + + writeLog(logfileDxp, "Dump the data that is being copied to a file OK"); + + // Backup for storing the data AFTER I write to memory + unsigned char saveDataPost[0x340]; + + writeLog(logfileDxp, "Backup for storing the data AFTER I write to memory OK"); + + // Flash the post-backup to all zeros + memset(saveDataPost, 0, 0x340); + + writeLog(logfileDxp, "Flash the post-backup to all zeros OK"); + + // Copy the existing data in the game to the array + memcpy(saveDataPost, (void*)(storyOffset), 0x340); + + writeLog(logfileDxp, "Copy the existing data in the game to the array OK"); + + // Dump the existing memory to disk + writeDump("memory_after.bin", saveDataPost, 0x340); + + writeLog(logfileDxp, "Dump the existing memory to disk OK"); // First page - //memcpy((void *)(value), saveData, 0x48); - memcpy((void *)(value + 0x10), saveDatadxp + 0x10, 0x20); - memcpy((void *)(value + 0x40), saveDatadxp + 0x40, 0x08); - //memcpy((void *)(value + 0x48 + 8), saveData + 0x48 + 8, 0x20); - memcpy((void *)(value + 0x48 + 8), saveDatadxp + 0x48 + 8, 0x08); - memcpy((void *)(value + 0x48 + 24), saveDatadxp + 0x48 + 24, 0x08); - memcpy((void *)(value + 0x48 + 32), saveDatadxp + 0x48 + 32, 0x08); + //memcpy((void *)(storyOffset), saveDatadxp, 0x08); + // memcpy((void *)(storyOffset + 0x40), saveDatadxp + 0x40, 0x08); + // memcpy((void *)(storyOffset + 0x48 + 8), saveDatadxp + 0x48 + 8, 0x08); + // memcpy((void *)(storyOffset + 0x48 + 24), saveDatadxp + 0x48 + 24, 0x08); + // memcpy((void *)(storyOffset + 0x48 + 32), saveDatadxp + 0x48 + 32, 0x08); // Second page - value += 0x110; - memcpy((void *)(value), saveDatadxp + 0x110, 0x90); - value -= 0x110; + // storyOffset += 0x110; + // memcpy((void *)(storyOffset), saveDatadxp + 0x110, 0x90); + // storyOffset -= 0x110; // Third Page - value += 0x1B8; - memcpy((void *)(value), saveDatadxp + 0x1B8, 0x48); - memcpy((void *)(value + 0x48 + 8), saveDatadxp + 0x1B8 + 0x48 + 8, 0x28); - value -= 0x1B8; + // storyOffset += 0x1B8; + // memcpy((void *)(storyOffset), saveDatadxp + 0x1B8, 0x48); + // memcpy((void *)(storyOffset + 0x48 + 8), saveDatadxp + 0x1B8 + 0x48 + 8, 0x28); + // storyOffset -= 0x1B8; // Fourth page - value += 0x240; - memcpy((void *)(value), saveDatadxp + 0x240, 0x68); - value -= 0x240; + // storyOffset += 0x240; + // memcpy((void *)(storyOffset), saveDatadxp + 0x240, 0x68); + // storyOffset -= 0x240; // Fifth page - value += 0x2B8; - memcpy((void *)(value), saveDatadxp + 0x2B8, 0x88); - value -= 0x2B8; + // storyOffset += 0x2B8; + // memcpy((void *)(storyOffset), saveDatadxp + 0x2B8, 0x88); + // storyOffset -= 0x2B8; - loadOkdxp = true; - - //+ 0x80 - - //+ [0x340] - - // [[[[0000000005CE5850] + 108] + 340] + 50] + 50 - // [[[[0000000005CE5850] + 108] + 340] + 50] + 54 - // wmn5r.exe + 1948BF8 - //TA stuff - - //[[[[magic_rva]+108]+340]+50] - - //value += 0x24E0; - // First chunk - //memcpy((void *)(value + 0x16), saveData + 0x16, 0x28); - //// - //memcpy((void *)(value + 0x40), saveData + 0x40, 0x18); - //// - //memcpy((void *)(value + 0x60), saveData + 0x60, 0x20); - //// - //memcpy((void *)(value + 0x90), saveData + 0x90, 0x28); - //// - //memcpy((void *)(value + 0xC0), saveData + 0xC0, 0x10); - //// - //memcpy((void *)(value + 0xD8), saveData + 0xD8, 0x28); // OK - //// - //memcpy((void *)(value + 0x110), saveData + 0x110, 0x98); - //// - //memcpy((void *)(value + 0x1B8), saveData + 0x1B8, 0x48); - //// - //memcpy((void *)(value + 0x208), saveData + 0x208, 0x28); - //// - //memcpy((void *)(value + 0x240), saveData + 0x240, 0x68); - //// - //memcpy((void *)(value + 0x2B8), saveData + 0x2B8, 0x88); - // - //memcpy((void *)(value + 0x370), saveData + 0x370, 0x10); - //// - //memcpy((void *)(value + 0x388), saveData + 0x388, 0x90); - //// - //memcpy((void *)(value + 0x420), saveData + 0x420, 0x18); - //// - //memcpy((void *)(value + 0x440), saveData + 0x440, 0x18); - //// - //memcpy((void *)(value + 0x460), saveData + 0x460, 0x48); - //// - //memcpy((void *)(value + 0x4B8), saveData + 0x4B8, 0xB8); - //// - //memcpy((void *)(value + 0x578), saveData + 0x578, 0x08); - //// - //memcpy((void *)(value + 0x5A8), saveData + 0x5A8, 0x68); - //// - //memcpy((void *)(value + 0x628), saveData + 0x628, 0x48); - //// - //memcpy((void *)(value + 0x688), saveData + 0x688, 0x48); - //// - //memcpy((void *)(value + 0x6E8), saveData + 0x6E8, 0xA8); - //// - //memcpy((void *)(value + 0x7A0), saveData + 0x7A0, 0x10); - //// - //memcpy((void *)(value + 0x7B8), saveData + 0x7B8, 0x28); - //// - //memcpy((void *)(value + 0x7E8), saveData + 0x7E8, 0x10); - //// - ////memcpy((void *)(value + 0x800), saveData + 0x800, 0x48); // Problem - ////// - //memcpy((void *)(value + 0x850), saveData + 0x850, 0x08); - // - //memcpy((void *)(value + 0x860), saveData + 0x860, 0x08); - ////// - //memcpy((void *)(value + 0x870), saveData + 0x870, 0x18); - //// - //memcpy((void *)(value + 0x890), saveData + 0x890, 0x40); - //// - //memcpy((void *)(value + 0x8E0), saveData + 0x8E0, 0x10); - //// - //memcpy((void *)(value + 0x8F8), saveData + 0x8F8, 0x28); - //// - //memcpy((void *)(value + 0x928), saveData + 0x928, 0x10); - //// - //memcpy((void *)(value + 0x940), saveData + 0x940, 0x48); // Problem + loadOkDxp = true; } fclose(file); } - //LoadStoryData(); - //LoadCampaingHonorData(); - //LoadStoryModeNoLoseHonorData(); - //LoadOtherHonorData(); - //LoadCampaingHonorData2(); + return 1; } -static void LoadWmmt5CarData() +static void LoadWmmt5carDataDxp() { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); -// if (!loadOkdxp) +// if (!loadOkDxp) // return; - customCardxp = false; - memset(carDatadxp, 0, 0xFF); - memset(carFileNamedxp, 0, 0xFF); + customCarDxp = false; + memset(carDataDxp, 0, 0xFF); + memset(carFileNameDxp, 0, 0xFF); CreateDirectoryA("OpenParrot_Cars", nullptr); - LoadMileagedxp(); + LoadMileage(); // check for custom car - sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\custom.car"); - if (FileExists(carFileNamedxp)) + sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\custom.car"); + if (FileExists(carFileNameDxp)) { - FILE* file = fopen(carFileNamedxp, "rb"); + FILE* file = fopen(carFileNameDxp, "rb"); if (file) { fseek(file, 0, SEEK_END); @@ -913,51 +739,54 @@ static void LoadWmmt5CarData() if (fsize == 0xFF) { fseek(file, 0, SEEK_SET); - fread(carDatadxp, fsize, 1, file); + fread(carDataDxp, fsize, 1, file); uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x268); - memcpy((void*)(carSaveLocation + 0xAC), carDatadxp + 0xAC, 0x1); //power - memcpy((void*)(carSaveLocation + 0xB8), carDatadxp + 0xB8, 0x1); //handling - memcpy((void*)(carSaveLocation + 0x28), carDatadxp + 0x28, 0x1); //region - memcpy((void*)(carSaveLocation + 0x34), carDatadxp + 0x34, 0x1); //carID - memcpy((void*)(carSaveLocation + 0x38), carDatadxp + 0x38, 0x1); //defaultColor - memcpy((void*)(carSaveLocation + 0x3C), carDatadxp + 0x3C, 0x1); //customColor - memcpy((void*)(carSaveLocation + 0x40), carDatadxp + 0x40, 0x1); //rims - memcpy((void*)(carSaveLocation + 0x44), carDatadxp + 0x44, 0x1); //rimColor - memcpy((void*)(carSaveLocation + 0x48), carDatadxp + 0x48, 0x1); //aero - memcpy((void*)(carSaveLocation + 0x4C), carDatadxp + 0x4C, 0x1); //hood - memcpy((void*)(carSaveLocation + 0x58), carDatadxp + 0x58, 0x1); //wang - memcpy((void*)(carSaveLocation + 0x5C), carDatadxp + 0x5C, 0x1); //mirror - memcpy((void*)(carSaveLocation + 0x60), carDatadxp + 0x60, 0x1); //sticker - memcpy((void*)(carSaveLocation + 0x64), carDatadxp + 0x64, 0x1); //stickerVariant - memcpy((void*)(carSaveLocation + 0x88), carDatadxp + 0x88, 0x1); //roofSticker - memcpy((void*)(carSaveLocation + 0x8C), carDatadxp + 0x8C, 0x1); //roofStickerVariant - memcpy((void*)(carSaveLocation + 0x90), carDatadxp + 0x90, 0x1); //neon - memcpy((void*)(carSaveLocation + 0x94), carDatadxp + 0x94, 0x1); //trunk - memcpy((void*)(carSaveLocation + 0x98), carDatadxp + 0x98, 0x1); //plateFrame - memcpy((void*)(carSaveLocation + 0xA0), carDatadxp + 0xA0, 0x4); //plateNumber - memcpy((void*)(carSaveLocation + 0xA4), carDatadxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 - memcpy((void*)(carSaveLocation + 0xA8), carDatadxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture - memcpy((void*)(carSaveLocation + 0xBC), carDatadxp + 0xBC, 0x1); //rank - memcpy((void*)(carSaveLocation + 0xF0), carDatadxp + 0xF0, 0x1); //title?? + memcpy((void*)(carSaveLocation + 0xAC), carDataDxp + 0xAC, 0x1); //power + memcpy((void*)(carSaveLocation + 0xB8), carDataDxp + 0xB8, 0x1); //handling + memcpy((void*)(carSaveLocation + 0x28), carDataDxp + 0x28, 0x1); //region + memcpy((void*)(carSaveLocation + 0x34), carDataDxp + 0x34, 0x1); //carID + memcpy((void*)(carSaveLocation + 0x38), carDataDxp + 0x38, 0x1); //defaultColor + memcpy((void*)(carSaveLocation + 0x3C), carDataDxp + 0x3C, 0x1); //customColor + memcpy((void*)(carSaveLocation + 0x40), carDataDxp + 0x40, 0x1); //rims + memcpy((void*)(carSaveLocation + 0x44), carDataDxp + 0x44, 0x1); //rimColor + memcpy((void*)(carSaveLocation + 0x48), carDataDxp + 0x48, 0x1); //aero + memcpy((void*)(carSaveLocation + 0x4C), carDataDxp + 0x4C, 0x1); //hood + memcpy((void*)(carSaveLocation + 0x58), carDataDxp + 0x58, 0x1); //wang + memcpy((void*)(carSaveLocation + 0x5C), carDataDxp + 0x5C, 0x1); //mirror + memcpy((void*)(carSaveLocation + 0x60), carDataDxp + 0x60, 0x1); //sticker + memcpy((void*)(carSaveLocation + 0x64), carDataDxp + 0x64, 0x1); //stickerVariant + memcpy((void*)(carSaveLocation + 0x88), carDataDxp + 0x88, 0x1); //roofSticker + memcpy((void*)(carSaveLocation + 0x8C), carDataDxp + 0x8C, 0x1); //roofStickerVariant + memcpy((void*)(carSaveLocation + 0x90), carDataDxp + 0x90, 0x1); //neon + memcpy((void*)(carSaveLocation + 0x94), carDataDxp + 0x94, 0x1); //trunk + memcpy((void*)(carSaveLocation + 0x98), carDataDxp + 0x98, 0x1); //plateFrame + memcpy((void*)(carSaveLocation + 0xA0), carDataDxp + 0xA0, 0x4); //plateNumber + memcpy((void*)(carSaveLocation + 0xA4), carDataDxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 + memcpy((void*)(carSaveLocation + 0xA8), carDataDxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture + memcpy((void*)(carSaveLocation + 0xBC), carDataDxp + 0xBC, 0x1); //rank + memcpy((void*)(carSaveLocation + 0xF0), carDataDxp + 0xF0, 0x1); //title?? - customCardxp = true; + customCarDxp = true; } - loadOkdxp = false; + loadOkDxp = false; fclose(file); return; } } + + // If the force full tune switch is set if (ToBool(config["Tune"]["Force Full Tune"])) { - CreateThread(0, 0, forceFT, 0, 0, 0); + // Create the force full tune thread + CreateThread(0, 0, forceFullTune, 0, 0, 0); } - memset(carFileNamedxp, 0, 0xFF); + memset(carFileNameDxp, 0, 0xFF); // Load actual car if available - sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); - if(FileExists(carFileNamedxp)) + sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); + if(FileExists(carFileNameDxp)) { - FILE* file = fopen(carFileNamedxp, "rb"); + FILE* file = fopen(carFileNameDxp, "rb"); if (file) { fseek(file, 0, SEEK_END); @@ -965,44 +794,63 @@ static void LoadWmmt5CarData() if (fsize == 0xFF) { fseek(file, 0, SEEK_SET); - fread(carDatadxp, fsize, 1, file); + fread(carDataDxp, fsize, 1, file); uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x268); - memcpy((void*)(carSaveLocation + 0xAC), carDatadxp + 0xAC, 0x1); //power - memcpy((void*)(carSaveLocation + 0xB8), carDatadxp + 0xB8, 0x1); //handling - memcpy((void*)(carSaveLocation + 0x28), carDatadxp + 0x28, 0x1); //region - memcpy((void*)(carSaveLocation + 0x34), carDatadxp + 0x34, 0x1); //carID - memcpy((void*)(carSaveLocation + 0x38), carDatadxp + 0x38, 0x1); //defaultColor - memcpy((void*)(carSaveLocation + 0x3C), carDatadxp + 0x3C, 0x1); //customColor - memcpy((void*)(carSaveLocation + 0x40), carDatadxp + 0x40, 0x1); //rims - memcpy((void*)(carSaveLocation + 0x44), carDatadxp + 0x44, 0x1); //rimColor - memcpy((void*)(carSaveLocation + 0x48), carDatadxp + 0x48, 0x1); //aero - memcpy((void*)(carSaveLocation + 0x4C), carDatadxp + 0x4C, 0x1); //hood - memcpy((void*)(carSaveLocation + 0x58), carDatadxp + 0x58, 0x1); //wang - memcpy((void*)(carSaveLocation + 0x5C), carDatadxp + 0x5C, 0x1); //mirror - memcpy((void*)(carSaveLocation + 0x60), carDatadxp + 0x60, 0x1); //sticker - memcpy((void*)(carSaveLocation + 0x64), carDatadxp + 0x64, 0x1); //stickerVariant - memcpy((void*)(carSaveLocation + 0x88), carDatadxp + 0x88, 0x1); //roofSticker - memcpy((void*)(carSaveLocation + 0x8C), carDatadxp + 0x8C, 0x1); //roofStickerVariant - memcpy((void*)(carSaveLocation + 0x90), carDatadxp + 0x90, 0x1); //neon - memcpy((void*)(carSaveLocation + 0x94), carDatadxp + 0x94, 0x1); //trunk - memcpy((void*)(carSaveLocation + 0x98), carDatadxp + 0x98, 0x1); //plateFrame - memcpy((void*)(carSaveLocation + 0xA0), carDatadxp + 0xA0, 0x4); //plateNumber - memcpy((void*)(carSaveLocation + 0xA4), carDatadxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 - memcpy((void*)(carSaveLocation + 0xA8), carDatadxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture - memcpy((void*)(carSaveLocation + 0xBC), carDatadxp + 0xBC, 0x1); //rank - memcpy((void*)(carSaveLocation + 0xF0), carDatadxp + 0xF0, 0x1); //title?? + memcpy((void*)(carSaveLocation + 0xAC), carDataDxp + 0xAC, 0x1); //power + memcpy((void*)(carSaveLocation + 0xB8), carDataDxp + 0xB8, 0x1); //handling + memcpy((void*)(carSaveLocation + 0x28), carDataDxp + 0x28, 0x1); //region + memcpy((void*)(carSaveLocation + 0x34), carDataDxp + 0x34, 0x1); //carID + memcpy((void*)(carSaveLocation + 0x38), carDataDxp + 0x38, 0x1); //defaultColor + memcpy((void*)(carSaveLocation + 0x3C), carDataDxp + 0x3C, 0x1); //customColor + memcpy((void*)(carSaveLocation + 0x40), carDataDxp + 0x40, 0x1); //rims + memcpy((void*)(carSaveLocation + 0x44), carDataDxp + 0x44, 0x1); //rimColor + memcpy((void*)(carSaveLocation + 0x48), carDataDxp + 0x48, 0x1); //aero + memcpy((void*)(carSaveLocation + 0x4C), carDataDxp + 0x4C, 0x1); //hood + memcpy((void*)(carSaveLocation + 0x58), carDataDxp + 0x58, 0x1); //wang + memcpy((void*)(carSaveLocation + 0x5C), carDataDxp + 0x5C, 0x1); //mirror + memcpy((void*)(carSaveLocation + 0x60), carDataDxp + 0x60, 0x1); //sticker + memcpy((void*)(carSaveLocation + 0x64), carDataDxp + 0x64, 0x1); //stickerVariant + memcpy((void*)(carSaveLocation + 0x88), carDataDxp + 0x88, 0x1); //roofSticker + memcpy((void*)(carSaveLocation + 0x8C), carDataDxp + 0x8C, 0x1); //roofStickerVariant + memcpy((void*)(carSaveLocation + 0x90), carDataDxp + 0x90, 0x1); //neon + memcpy((void*)(carSaveLocation + 0x94), carDataDxp + 0x94, 0x1); //trunk + memcpy((void*)(carSaveLocation + 0x98), carDataDxp + 0x98, 0x1); //plateFrame + memcpy((void*)(carSaveLocation + 0xA0), carDataDxp + 0xA0, 0x4); //plateNumber + memcpy((void*)(carSaveLocation + 0xA4), carDataDxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 + memcpy((void*)(carSaveLocation + 0xA8), carDataDxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture + memcpy((void*)(carSaveLocation + 0xBC), carDataDxp + 0xBC, 0x1); //rank + memcpy((void*)(carSaveLocation + 0xF0), carDataDxp + 0xF0, 0x1); //title?? } fclose(file); } } - loadOkdxp = false; + loadOkDxp = false; +} + +static void loadGame() +{ + // Runs after car data is loaded + + // Load story data thread + std::thread t1(LoadGameData); + t1.detach(); + + // Load car data thread + std::thread t2(LoadWmmt5carDataDxp); + t2.detach(); +} + +/* +static void loadStory() +{ + } static void loadCar() { - std::thread t1(LoadWmmt5CarData); - t1.detach(); + } +*/ static int ReturnTrue() { @@ -1202,67 +1050,37 @@ static DWORD WINAPI SpamMulticast(LPVOID) } } -/* -extern int* ffbOffset; -extern int* ffbOffset2; -extern int* ffbOffset3; -extern int* ffbOffset4; - -DWORD WINAPI Wmmt5FfbCollector(void* ctx) -{ - uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); - while (true) - { - *ffbOffset = *(DWORD *)(imageBase + 0x196F188); - *ffbOffset2 = *(DWORD *)(imageBase + 0x196F18c); - *ffbOffset3 = *(DWORD *)(imageBase + 0x196F190); - *ffbOffset4 = *(DWORD *)(imageBase + 0x196F194); - Sleep(10); - } -}*/ - +// Wmmt5Func([]()): InitFunction +// Performs the initial startup tasks for +// maximum tune 5, including the starting +// of required subprocesses. static InitFunction Wmmt5Func([]() -{/* - FILE* fileF = _wfopen(L"Fsetting.lua.gz", L"r"); - if (fileF == NULL) - { - FILE* settingsF = _wfopen(L"Fsetting.lua.gz", L"wb"); - fwrite(settingData, 1, sizeof(settingData), settingsF); - fclose(settingsF); - } - else - { - fclose(fileF); - } - - FILE* fileG = _wfopen(L"Gsetting.lua.gz", L"r"); - if (fileG == NULL) - { - FILE* settingsG = _wfopen(L"Gsetting.lua.gz", L"wb"); - fwrite(settingData, 1, sizeof(settingData), settingsG); - fclose(settingsG); - } - else - { - fclose(fileG); - }*/ - +{ + writeLog(logfileDxp, "[DEBUG] Starting emulation ...\n"); + // Records if terminal mode is enabled bool isTerminal = false; + + // If terminal mode is set in the general settings if (ToBool(config["General"]["TerminalMode"])) { + // Terminal mode is set isTerminal = true; } + // Get the network adapter ip address from the general settings std::string networkip = config["General"]["NetworkAdapterIP"]; + + // If the ip address is not blank if (!networkip.empty()) { - //strcpy(ipaddr, networkip.c_str()); + // Overwrite the default ip address ipaddrdxplus = networkip.c_str(); } hookPort = "COM3"; imageBasedxplus = (uintptr_t)GetModuleHandleA(0); + MH_Initialize(); // Hook dongle funcs @@ -1274,12 +1092,9 @@ static InitFunction Wmmt5Func([]() MH_CreateHookApi(L"hasp_windows_x64_106482.dll", "hasp_logout", dxpHook_hasp_logout, NULL); MH_CreateHookApi(L"hasp_windows_x64_106482.dll", "hasp_login", dxpHook_hasp_login, NULL); - - GenerateDongleDataDxp(isTerminal); - - //prevents game from setting time, thanks pockywitch! + // Prevents game from setting time, thanks pockywitch! MH_CreateHookApi(L"KERNEL32", "SetSystemTime", Hook_SetSystemTime, reinterpret_cast(&pSetSystemTime)); // Patch some check TEMP DISABLE AS WELL OVER HERE @@ -1317,81 +1132,35 @@ static InitFunction Wmmt5Func([]() // Patch some call // 45 33 C0 BA 65 09 00 00 48 8D 4D B0 E8 ?? ?? ?? ?? 48 8B 08 // FOUND ON 21, 10, 1 - //injector::MakeNOP(imageBase + 0x7DADED, 5); - //THIS injector::MakeNOP(hook::get_pattern("45 33 C0 BA 65 09 00 00 48 8D 4D B0 E8 ? ? ? ? 48 8B 08", 12), 5); { // 199AE18 TIME OFFSET RVA temp disable ALL JNZ PATCH auto location = hook::get_pattern("41 3B C7 74 0E 48 8D 8F B8 00 00 00 BA F6 01 00 00 EB 6E 48 8D 8F A0 00 00 00"); + // Patch some jnz // 41 3B C7 74 0E 48 8D 8F B8 00 00 00 BA F6 01 00 00 EB 6E 48 8D 8F A0 00 00 00 // FOUND ON 21, 10, 1 - //injector::WriteMemory(imageBase + 0x943F52, 0xEB, true); injector::WriteMemory(location + 3, 0xEB, true); //patches content router (doomer) // Skip some jnz - //injector::MakeNOP(imageBase + 0x943F71, 2); injector::MakeNOP(location + 0x22, 2); //patches ip addr error again (doomer) // Skip some jnz - //injector::MakeNOP(imageBase + 0x943F82, 2); injector::MakeNOP(location + 0x33, 2); //patches ip aaddr error(doomer) } - // Skip DebugBreak on MFStartup fail - // 48 83 EC 28 33 D2 B9 70 00 02 00 E8 ?? ?? ?? ?? 85 C0 79 06 - // FOUND on 21, 1 + // Terminal mode is off + if (!isTerminal) { - /* - auto location = hook::get_pattern("48 83 EC 28 33 D2 B9 70 00 02 00 E8 ? ? ? ? 85 C0 79 06"); - injector::WriteMemory(location + 0x12, 0xEB, true); - */ - } - //safeJMP(hook::get_pattern(V("48 83 EC 28 33 D2 B9 70 00 02 00 E8 ? ? ? ? 85 C0 79 06")), ReturnTrue); + // I don't know what this is for sorry + injector::MakeNOP(imageBasedxplus + 0x9F2BB3, 2); - if (isTerminal) - { - // Patch some func to 1 - // - // FOUND ON 21, 10, 1 - // NOT FOUND: - //safeJMP(imageBase + 0x7BE440, ReturnTrue); - //safeJMP(hook::get_pattern("0F B6 41 05 2C 30 3C 09 77 04 0F BE C0 C3 83 C8 FF C3"), ReturnTrue); - //safeJMP(imageBase + 0x89D420, ReturnTrue); - - // Patch some func to 1 - // 40 53 48 83 EC 20 48 83 39 00 48 8B D9 75 28 48 8D ?? ?? ?? ?? 00 48 8D ?? ?? ?? ?? 00 41 B8 ?? ?? 00 00 FF 15 ?? ?? ?? ?? 4C 8B 1B 41 0F B6 43 78 - // FOUND ON 21, 10, 1 - //safeJMP(imageBase + 0x7CF8D0, ReturnTrue); - //safeJMP(hook::get_pattern("40 53 48 83 EC 20 48 83 39 00 48 8B D9 75 11 48 8B 0D C2"), ReturnTrue); - //safeJMP(imageBase + 0x8B5190, ReturnTrue); - } - else - { - // Disregard terminal scanner stuff. - // 48 8B 18 48 3B D8 0F 84 88 00 00 00 39 7B 1C 74 60 80 7B 31 00 75 4F 48 8B 43 10 80 78 31 00 - // FOUND ON 21, 10, 1 - //injector::MakeNOP(imageBase + 0x91E1AE, 6); - //injector::MakeNOP(imageBase + 0x91E1B7, 2); - //injector::MakeNOP(imageBase + 0x91E1BD, 2); - - { - - /* - auto location = hook::get_pattern("48 8B 18 48 3B D8 0F 84 8B 00 00 00 0F 1F 80 00 00 00 00 39 73 1C 74 5C 80 7B 31 00"); - //injector::MakeNOP(location + 6, 6); // 6 - injector::MakeNOP(location + 0xF, 2); // 0xF - //injector::MakeNOP(location + 0x15, 2); // 0x15 - */ - injector::MakeNOP(imageBasedxplus + 0x9F2BB3, 2); - } - - - // spam thread + // If terminal emulator is enabled if (ToBool(config["General"]["TerminalEmulator"])) { - CreateThread(0, 0, SpamMulticast, 0, 0, 0); + // Start the multicast spam thread + CreateThread(0, 0, SpamMulticast, 0, 0, 0); } } @@ -1418,93 +1187,47 @@ static InitFunction Wmmt5Func([]() } } - if (ToBool(config["General"]["SkipMovies"])) - { - // Skip movies fuck you wmmt5 - //safeJMP(imageBase + 0x806020, ReturnTrue); - } - + // Get the custom name specified in the config file std::string value = config["General"]["CustomName"]; + + // If a custom name is set if (!value.empty()) { - + // Zero out the custom name variable memset(customNamedxp, 0, 256); + + // Copy the custom name to the custom name block strcpy(customNamedxp, value.c_str()); + + // Create the spam custom name thread CreateThread(0, 0, SpamcustomNamedxp, 0, 0, 0); - } // Save story stuff (only 05) { - - // skip erasing of temp card data - //injector::WriteMemory(imageBase + 0xA35CA3, 0xEB, true); - /* - // Skip erasing of temp card - safeJMP(imageBase + 0x54DCE1, LoadGameData); - safeJMP(imageBase + 0x5612F0, ReturnTrue); - safeJMP(imageBase + 0x5753C0, ReturnTrue); - safeJMP(imageBase + 0x57DF10, ReturnTrue); - - safeJMP(imageBase + 0x92DB20, ReturnTrue); - safeJMP(imageBase + 0x5628C0, ReturnTrue); - safeJMP(imageBase + 0x579090, ReturnTrue); - - // Skip more - safeJMP(imageBase + 0x54B0F0, ReturnTrue); - safeJMP(imageBase + 0x909DB0, ReturnTrue); - safeJMP(imageBase + 0x59FD90, ReturnTrue); - safeJMP(imageBase + 0x5A0030, ReturnTrue); - safeJMP(imageBase + 0x915370, ReturnTrue); - safeJMP(imageBase + 0x5507A0, ReturnTrue); - safeJMP(imageBase + 0x561290, ReturnTrue); - - safeJMP(imageBase + 0x5A0AE8, LoadWmmt5CarData); - - // crash fix - //safeJMP(imageBase + 0xAD6F28, WmmtOperatorDelete); - //safeJMP(imageBase + 0xAD6F4C, WmmtMemset); - - // Save progress trigger - injector::WriteMemory(imageBase + 0x556CE3, 0xB848, true); - injector::WriteMemory(imageBase + 0x556CE3 + 2, (uintptr_t)SaveOk, true); - injector::WriteMemory(imageBase + 0x556CED, 0x9090D0FF, true); - - // Try save later! - injector::MakeNOP(imageBase + 0x308546, 0x12); - injector::WriteMemory(imageBase + 0x308546, 0xB848, true); - injector::WriteMemory(imageBase + 0x308546 + 2, (uintptr_t)SaveGameData, true); - injector::WriteMemory(imageBase + 0x308550, 0x3348D0FF, true); - injector::WriteMemory(imageBase + 0x308550 + 4, 0x90C0, true); - - CreateThread(0, 0, Wmmt5FfbCollector, 0, 0, 0); - */ - // Enable all print injector::MakeNOP(imageBasedxplus + 0x898BD3, 6); - //load car trigger - safeJMP(imageBasedxplus + 0x72AB90, loadCar); - - //save car trigger - //injector::WriteMemory(imageBase + 0x376F80 + 2, (uintptr_t)SaveGameData, true); - //safeJMP(imageBase + 0x376F76, SaveGameData); - + // Load car trigger + // safeJMP(imageBasedxplus + 0x72AB90, loadCar); + // Load car and story data at once + safeJMP(imageBasedxplus + 0x72AB90, loadGame); + + // Attempting to piggyback story load off load car + // safeJMP(imageBasedxplus + 0x72AB90, loadStory); + + // Save car trigger injector::MakeNOP(imageBasedxplus + 0x376F76, 0x12); injector::WriteMemory(imageBasedxplus + 0x376F76, 0xB848, true); injector::WriteMemory(imageBasedxplus + 0x376F76 + 2, (uintptr_t)SaveGameData, true); injector::WriteMemory(imageBasedxplus + 0x376F80, 0x3348D0FF, true); injector::WriteMemory(imageBasedxplus + 0x376F80 + 4, 0x90C0, true); - //prevents startup saving - //injector::MakeNOP(imageBase + 0x6B908C, 0x0D); - //safeJMP(imageBase + 0x6B908C, SaveOk); + // Prevents startup saving injector::WriteMemory(imageBasedxplus + 0x6B909A, 0xB848, true); injector::WriteMemory(imageBasedxplus + 0x6B909A + 2, (uintptr_t)SaveOk, true); injector::WriteMemory(imageBasedxplus + 0x6B90A4, 0x9090D0FF, true); - - } MH_EnableHook(MH_ALL_HOOKS); From 781dc449af8dceb269ed32f0c2c9c8960686ebd5 Mon Sep 17 00:00:00 2001 From: Damon Murdoch Date: Fri, 22 Apr 2022 10:58:33 +1000 Subject: [PATCH 2/8] Added support for seperate story / miles saving for different cars, custom names for MT5DX+ --- .gitignore | 1 + OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp | 96 +-- .../src/Functions/Games/ES3X/WMMT5DXPlus.cpp | 687 +++++++++++------- 3 files changed, 472 insertions(+), 312 deletions(-) diff --git a/.gitignore b/.gitignore index b62cbf3..1a2f8c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.sln *.vcxproj *.vcxproj.filters +*.commit-and-copy.ps1 .vs/ build/ Debug/ diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp index fc31144..d16660c 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp @@ -631,34 +631,26 @@ static void LoadWmmt5CarData() fread(carData, fsize, 1, file); uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); - // memcpy((void *)(carSaveLocation + 0x08), carData + 0x08, 8); - // memcpy((void *)(carSaveLocation + 0x10), carData + 0x10, 8); - // memcpy((void *)(carSaveLocation + 0x20), carData + 0x20, 8); - // memcpy((void *)(carSaveLocation + 0x28), carData + 0x28, 8); - memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 1); // Stock Colour - memcpy((void*)(carSaveLocation + 0x34), carData + 0x34, 1); // Custom Colour - memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 1); // Rims Type - memcpy((void*)(carSaveLocation + 0x3C), carData + 0x3C, 1); // Rims Colour - memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 1); // Aero Type - memcpy((void*)(carSaveLocation + 0x44), carData + 0x44, 1); // Hood Type - memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 1); // Wing Type - memcpy((void*)(carSaveLocation + 0x54), carData + 0x54, 1); // Mirror Type - memcpy((void*)(carSaveLocation + 0x58), carData + 0x58, 1); // Body Sticker Type - memcpy((void*)(carSaveLocation + 0x5C), carData + 0x5C, 1); // Body Sticker Variant - // memcpy((void *)(carSaveLocation + 0x68), carData + 0x68, 8); - memcpy((void*)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neons - memcpy((void*)(carSaveLocation + 0x80), carData + 0x80, 1); // Trunk - memcpy((void*)(carSaveLocation + 0x84), carData + 0x80, 1); // Plate Frame - memcpy((void*)(carSaveLocation + 0x8A), carData + 0x8A, 1); // Plate Frame Colour - // memcpy((void *)(carSaveLocation + 0x90), carData + 0x90, 8); - memcpy((void*)(carSaveLocation + 0x98), carData + 0x98, 1); // Power - memcpy((void*)(carSaveLocation + 0x9C), carData + 0x9C, 1); // Handling - memcpy((void*)(carSaveLocation + 0xA4), carData + 0xA4, 1); // Rank - // memcpy((void *)(carSaveLocation + 0xA8), carData + 0xA8, 8); - // memcpy((void *)(carSaveLocation + 0xB8), carData + 0xB8, 8); - // memcpy((void *)(carSaveLocation + 0xC8), carData + 0xC8, 8); - // memcpy((void *)(carSaveLocation + 0xD8), carData + 0xD8, 8); - //memcpy((void *)(carSaveLocation + 0xE0), carData + 0xE0, 8); + memcpy((void*)(carSaveLocation + 0x08), carData + 0x08, 8); // ?? + memcpy((void*)(carSaveLocation + 0x10), carData + 0x10, 8); // ?? + memcpy((void*)(carSaveLocation + 0x20), carData + 0x20, 8); // ?? + memcpy((void*)(carSaveLocation + 0x28), carData + 0x28, 8); // ?? + memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 8); // Stock Colour (0x30), Custom Colour (0x34) + memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 8); // Rims Type (0x38), Rims Colour (0x3C) + memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 8); // Aero Type (0x40), Hood Type (0x44) + memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 8); // Wing Type (0x50), Mirror Type (0x54) + memcpy((void*)(carSaveLocation + 0x58), carData + 0x58, 8); // Body Sticker Type (0x58), Variant (0x5C) + memcpy((void*)(carSaveLocation + 0x68), carData + 0x68, 8); // ?? + memcpy((void*)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neon Type + memcpy((void*)(carSaveLocation + 0x80), carData + 0x80, 8); // Trunk Colour (0x80), Plate Frame (0x84) + memcpy((void*)(carSaveLocation + 0x88), carData + 0x88, 8); // Plate Frame Colour (0x8A) + memcpy((void*)(carSaveLocation + 0x90), carData + 0x90, 8); // ?? + memcpy((void*)(carSaveLocation + 0x98), carData + 0x98, 8); // Power (0x98), Handling (0x9C) + memcpy((void*)(carSaveLocation + 0xA0), carData + 0xA0, 8); // Rank (0xA4) + memcpy((void*)(carSaveLocation + 0xA8), carData + 0xA8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xB8), carData + 0xB8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xC8), carData + 0xC8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xD8), carData + 0xD8, 8); // ?? customCar = true; } @@ -691,34 +683,26 @@ static void LoadWmmt5CarData() fread(carData, fsize, 1, file); uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); - // memcpy((void *)(carSaveLocation + 0x08), carData + 0x08, 8); - // memcpy((void *)(carSaveLocation + 0x10), carData + 0x10, 8); - // memcpy((void *)(carSaveLocation + 0x20), carData + 0x20, 8); - // memcpy((void *)(carSaveLocation + 0x28), carData + 0x28, 8); - memcpy((void *)(carSaveLocation + 0x30), carData + 0x30, 1); // Stock Colour - memcpy((void *)(carSaveLocation + 0x34), carData + 0x34, 1); // Custom Colour - memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 1); // Rims Type - memcpy((void *)(carSaveLocation + 0x3C), carData + 0x3C, 1); // Rims Colour - memcpy((void *)(carSaveLocation + 0x40), carData + 0x40, 1); // Aero Type - memcpy((void *)(carSaveLocation + 0x44), carData + 0x44, 1); // Hood Type - memcpy((void *)(carSaveLocation + 0x50), carData + 0x50, 1); // Wing Type - memcpy((void *)(carSaveLocation + 0x54), carData + 0x54, 1); // Mirror Type - memcpy((void *)(carSaveLocation + 0x58), carData + 0x58, 1); // Body Sticker Type - memcpy((void *)(carSaveLocation + 0x5C), carData + 0x5C, 1); // Body Sticker Variant - // memcpy((void *)(carSaveLocation + 0x68), carData + 0x68, 8); - memcpy((void *)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neons - memcpy((void *)(carSaveLocation + 0x80), carData + 0x80, 1); // Trunk - memcpy((void *)(carSaveLocation + 0x84), carData + 0x80, 1); // Plate Frame - memcpy((void *)(carSaveLocation + 0x8A), carData + 0x8A, 1); // Plate Frame Colour - // memcpy((void *)(carSaveLocation + 0x90), carData + 0x90, 8); - memcpy((void *)(carSaveLocation + 0x98), carData + 0x98, 1); // Power - memcpy((void *)(carSaveLocation + 0x9C), carData + 0x9C, 1); // Handling - memcpy((void *)(carSaveLocation + 0xA4), carData + 0xA4, 1); // Rank - // memcpy((void *)(carSaveLocation + 0xA8), carData + 0xA8, 8); - // memcpy((void *)(carSaveLocation + 0xB8), carData + 0xB8, 8); - // memcpy((void *)(carSaveLocation + 0xC8), carData + 0xC8, 8); - // memcpy((void *)(carSaveLocation + 0xD8), carData + 0xD8, 8); - //memcpy((void *)(carSaveLocation + 0xE0), carData + 0xE0, 8); + memcpy((void*)(carSaveLocation + 0x08), carData + 0x08, 8); // ?? + memcpy((void*)(carSaveLocation + 0x10), carData + 0x10, 8); // ?? + memcpy((void*)(carSaveLocation + 0x20), carData + 0x20, 8); // ?? + memcpy((void*)(carSaveLocation + 0x28), carData + 0x28, 8); // ?? + memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 8); // Stock Colour (0x30), Custom Colour (0x34) + memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 8); // Rims Type (0x38), Rims Colour (0x3C) + memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 8); // Aero Type (0x40), Hood Type (0x44) + memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 8); // Wing Type (0x50), Mirror Type (0x54) + memcpy((void*)(carSaveLocation + 0x58), carData + 0x58, 8); // Body Sticker Type (0x58), Variant (0x5C) + memcpy((void*)(carSaveLocation + 0x68), carData + 0x68, 8); // ?? + memcpy((void*)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neon Type + memcpy((void*)(carSaveLocation + 0x80), carData + 0x80, 8); // Trunk Colour (0x80), Plate Frame (0x84) + memcpy((void*)(carSaveLocation + 0x88), carData + 0x88, 8); // Plate Frame Colour (0x8A) + memcpy((void*)(carSaveLocation + 0x90), carData + 0x90, 8); // ?? + memcpy((void*)(carSaveLocation + 0x98), carData + 0x98, 8); // Power (0x98), Handling (0x9C) + memcpy((void*)(carSaveLocation + 0xA0), carData + 0xA0, 8); // Rank (0xA4) + memcpy((void*)(carSaveLocation + 0xA8), carData + 0xA8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xB8), carData + 0xB8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xC8), carData + 0xC8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xD8), carData + 0xD8, 8); // ?? } fclose(file); } diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp index ecc2b69..111610e 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp @@ -1,6 +1,7 @@ #include #include "Utility/InitFunction.h" #include "Functions/Global.h" +#include #include #include #include @@ -369,9 +370,10 @@ unsigned int dxpHook_hasp_write(int hasp_handle, int hasp_fileid, unsigned int o return HASP_STATUS_OK; } - - +// Save data dump memory block unsigned char saveDatadxp[0x2000]; + +// Mile data dump memory block unsigned char mileDatadxp[0x08]; //set system date patch by pockywitch @@ -495,104 +497,218 @@ char carFileNameDxp[0xFF]; bool loadOkDxp = false; bool customCarDxp = false; -static void saveMileage() -{ - auto mileageLocation = (uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x280); +uintptr_t saveGameOffsetdxp; - FILE* tempFile = fopen("mileage.dat", "wb"); - fwrite(mileageLocation, 1, sizeof(mileageLocation), tempFile); - fclose(tempFile); -} - -static void LoadMileage() +// loadCarFile(filename: char*): Int +// Given a filename, loads the data from +// the car file into memory. +static int loadCarFile(char* filename) { - - memset(mileDatadxp, 0, 0x08); - FILE* miles = fopen("mileage.dat", "rb"); - if (miles) + // Open the file with the filename + FILE* file = fopen(filename, "rb"); + + // File open OK + if (file) { - fseek(miles, 0, SEEK_END); - int mileSize = ftell(miles); - if (mileSize == 0x08) + // Get the length of the file + fseek(file, 0, SEEK_END); + int fsize = ftell(file); + + // If the file has the right size + if (fsize == 0xFF) { - fseek(miles, 0, SEEK_SET); - fread(mileDatadxp, mileSize, 1, miles); - uintptr_t mileMemory = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); - memcpy((void*)(mileMemory + 0x280), mileDatadxp + 0x00, 0x04); - fclose(miles); + // Reset to start of the file and read it into the car data variable + fseek(file, 0, SEEK_SET); + fread(carDataDxp, fsize, 1, file); + + // Dereference the memory location for the car save data + uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x268); + + memcpy((void*)(carSaveLocation + 0xAC), carDataDxp + 0xAC, 0x1); //power + memcpy((void*)(carSaveLocation + 0xB8), carDataDxp + 0xB8, 0x1); //handling + memcpy((void*)(carSaveLocation + 0x28), carDataDxp + 0x28, 0x1); //region + memcpy((void*)(carSaveLocation + 0x34), carDataDxp + 0x34, 0x1); //carID + memcpy((void*)(carSaveLocation + 0x38), carDataDxp + 0x38, 0x1); //defaultColor + memcpy((void*)(carSaveLocation + 0x3C), carDataDxp + 0x3C, 0x1); //customColor + memcpy((void*)(carSaveLocation + 0x40), carDataDxp + 0x40, 0x1); //rims + memcpy((void*)(carSaveLocation + 0x44), carDataDxp + 0x44, 0x1); //rimColor + memcpy((void*)(carSaveLocation + 0x48), carDataDxp + 0x48, 0x1); //aero + memcpy((void*)(carSaveLocation + 0x4C), carDataDxp + 0x4C, 0x1); //hood + memcpy((void*)(carSaveLocation + 0x58), carDataDxp + 0x58, 0x1); //wang + memcpy((void*)(carSaveLocation + 0x5C), carDataDxp + 0x5C, 0x1); //mirror + memcpy((void*)(carSaveLocation + 0x60), carDataDxp + 0x60, 0x1); //sticker + memcpy((void*)(carSaveLocation + 0x64), carDataDxp + 0x64, 0x1); //stickerVariant + memcpy((void*)(carSaveLocation + 0x88), carDataDxp + 0x88, 0x1); //roofSticker + memcpy((void*)(carSaveLocation + 0x8C), carDataDxp + 0x8C, 0x1); //roofStickerVariant + memcpy((void*)(carSaveLocation + 0x90), carDataDxp + 0x90, 0x1); //neon + memcpy((void*)(carSaveLocation + 0x94), carDataDxp + 0x94, 0x1); //trunk + memcpy((void*)(carSaveLocation + 0x98), carDataDxp + 0x98, 0x1); //plateFrame + memcpy((void*)(carSaveLocation + 0xA0), carDataDxp + 0xA0, 0x4); //plateNumber + memcpy((void*)(carSaveLocation + 0xA4), carDataDxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 + memcpy((void*)(carSaveLocation + 0xA8), carDataDxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture + memcpy((void*)(carSaveLocation + 0xBC), carDataDxp + 0xBC, 0x1); //rank + memcpy((void*)(carSaveLocation + 0xF0), carDataDxp + 0xF0, 0x1); //title?? } + + // Disable loading + loadOkDxp = false; + + // Close the file + fclose(file); + + // Success + return 1; } + + // Failed + return 0; } -static int SaveGameData() +// loadCarData(filepath: char*): Void +// Given a filepath, attempts to load a +// car file (either custom.car or specific +// car file) from that folder. +static int loadCarData(char * filepath) { - if (!saveOk) - return 1; + // Sleep for 1 second + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - writeLog(logfileDxp, "[DEBUG] Saving game data ...\n"); + // Custom car disabled by default + customCarDxp = false; - // Address where player save data starts - uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + // Miles path string + char carpath[0xFF]; - // Save story data + // Set the milepath memory to zero + memset(carpath, 0, 0xFF); - // Zero out save data binary - memset(saveDatadxp, 0, 0x2000); + // Copy the file path to the miles path + strcpy(carpath, filepath); - // Address where the player story data starts - uintptr_t storySaveBase = *(uintptr_t*)(saveDataBase + 0x108); + // Append the mileage filename to the string + strcat(carpath, "\\OpenParrot_Cars"); - // Copy 340 nibbles to saveDatadxp from the story save data index - memcpy(saveDatadxp, (void*)storySaveBase, 0x340); + // Create the OpenParrot_cars directory at the given filepath + std::filesystem::create_directories(carpath); - // Dump the save data to openprogress.sav - writeDump("openprogress.sav", saveDatadxp, 0x2000); + // Get the path to the custom car file + sprintf(carFileNameDxp, "%s\\custom.car", carpath); + // If the custom car file exists + if (FileExists(carFileNameDxp)) + { + // Load the custom car file + loadCarFile(carFileNameDxp); + + // Enable custom car switch + customCarDxp = true; + } + + // Empty the car filename string + memset(carFileNameDxp, 0, 0xFF); + + // Get the path to the specific car file + sprintf(carFileNameDxp, "%s\\%08X.car", carpath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); + + // If the specific car file exists + if (FileExists(carFileNameDxp)) + { + // Load the car file + loadCarFile(carFileNameDxp); + } + + // If the force full tune switch is set + if (ToBool(config["Tune"]["Force Full Tune"])) + { + // Create the force full tune thread + CreateThread(0, 0, forceFullTune, 0, 0, 0); + } + + // Success + return 1; +} + +static int saveCarData(char* filepath) +{ // Car Profile saving memset(carDataDxp, 0, 0xFF); memset(carFileNameDxp, 0, 0xFF); + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + //new multilevel uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x268); - memcpy(carDataDxp + 0x00, (void*)(carSaveBase + 0x0), 0xFF); //dumps whole region + // Miles path string + char carpath[0xFF]; + // Set the milepath memory to zero + memset(carpath, 0, 0xFF); - CreateDirectoryA("OpenParrot_Cars", nullptr); + // Copy the file path to the miles path + strcpy(carpath, filepath); + // Append the mileage filename to the string + strcat(carpath, "\\OpenParrot_Cars"); + + // CreateDirectoryA(carpath, nullptr); + + // Create the cars path folder + std::filesystem::create_directories(carpath); + + // Copy the 0xFF bytes from memory to the car data array + memcpy(carDataDxp + 0x00, (void*)(carSaveBase + 0x0), 0xFF); + + // If custom car is set if (customCarDxp) { - sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\custom.car"); + // Save the file to custom.car + sprintf(carpath, "%s\\custom.car", carpath); } - else + else // Custom car is not set { - sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); + // Save the file to the specific car filename + sprintf(carpath, "%s\\%08X.car", carpath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); } - FILE* carFile = fopen(carFileNameDxp, "wb"); + // Open the file at the given car path + FILE* carFile = fopen(carpath, "wb"); + + // Write the data from the array to the file fwrite(carDataDxp, 1, 0xFF, carFile); + fclose(carFile); - saveMileage(); - - saveOk = false; + // Success return 1; } -uintptr_t saveGameOffsetdxp; - -static int LoadGameData() +// loadStoryData(filepath: char *): Void +// Given a filepath, loads the story data +// from the file into memory. +static int loadStoryData(char* filepath) { - saveOk = false; - // Zero out the save data array memset(saveDatadxp, 0x0, 0x2000); + // Miles path string + char storyPath[0xFF]; + + // Set the milepath memory to zero + memset(storyPath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(storyPath, filepath); + + // Append the mileage filename to the string + strcat(storyPath, "\\openprogress.sav"); + // Address where player save data starts uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); // Open the openprogress file with read privileges - FILE* file = fopen("openprogress.sav", "rb"); + FILE* file = fopen(storyPath, "rb"); // If the file exists if (file) @@ -615,216 +731,293 @@ static int LoadGameData() // Story save data offset uintptr_t storyOffset = *(uintptr_t*)(saveDataBase + 0x108); - // Try copying everything??? lmfao - - // Backup for storing the data BEFORE I write to memory - unsigned char saveDataPre[0x340]; - - writeLog(logfileDxp, "Backup for storing the data BEFORE I write to memory OK"); - - // Flash the pre-backup to all zeros - memset(saveDataPre, 0, 0x340); - - writeLog(logfileDxp, "Flash the pre-backup to all zeros OK"); - - // Copy the existing data in the game to the array - memcpy(saveDataPre, (void*)(storyOffset), 0x340); - - writeLog(logfileDxp, "Copy the existing data in the game to the array OK"); - - // Dump the existing memory to disk - writeDump("memory_before.bin", saveDataPre, 0x340); - - writeLog(logfileDxp, "Dump the existing memory to disk OK"); - - // Dump the data that is being copied to a file - // writeDump("openprogress_test.sav", saveDatadxp + 0x70, 0x100); - // memcpy((void*)(storyOffset + 0x70), saveDatadxp + 0x70, 0x100); - - // memcpy((void*)(storyOffset + 0x7C), saveDatadxp + 0x7C, 0x1); // Not sure - // memcpy((void*)(storyOffset + 0xE0), saveDatadxp + 0xE0, 0x1); // Not sure - // memcpy((void*)(storyOffset + 0xE4), saveDatadxp + 0xE4, 0x1); // Not sure - // memcpy((void*)(storyOffset + 0xEC), saveDatadxp + 0xEC, 0x1); // Not sure - // memcpy((void*)(storyOffset + 0xEC), saveDatadxp + 0xEC, 0x1); // Not sure - // memcpy((void*)(storyOffset + 0x10C), saveDatadxp + 0x10C, 0x1); // Not sure - // Not sure why, but story doesn't load unless I add this memcpy((void*)(storyOffset + 0x48), saveDatadxp + 0x48, 0x1); // Pretty sure this is the whole save file region, but need to test more :) memcpy((void*)(storyOffset + 0xE0), saveDatadxp + 0xE0, 0x80); - writeLog(logfileDxp, "Dump the data that is being copied to a file OK"); - - // Backup for storing the data AFTER I write to memory - unsigned char saveDataPost[0x340]; - - writeLog(logfileDxp, "Backup for storing the data AFTER I write to memory OK"); - - // Flash the post-backup to all zeros - memset(saveDataPost, 0, 0x340); - - writeLog(logfileDxp, "Flash the post-backup to all zeros OK"); - - // Copy the existing data in the game to the array - memcpy(saveDataPost, (void*)(storyOffset), 0x340); - - writeLog(logfileDxp, "Copy the existing data in the game to the array OK"); - - // Dump the existing memory to disk - writeDump("memory_after.bin", saveDataPost, 0x340); - - writeLog(logfileDxp, "Dump the existing memory to disk OK"); - - // First page - //memcpy((void *)(storyOffset), saveDatadxp, 0x08); - // memcpy((void *)(storyOffset + 0x40), saveDatadxp + 0x40, 0x08); - // memcpy((void *)(storyOffset + 0x48 + 8), saveDatadxp + 0x48 + 8, 0x08); - // memcpy((void *)(storyOffset + 0x48 + 24), saveDatadxp + 0x48 + 24, 0x08); - // memcpy((void *)(storyOffset + 0x48 + 32), saveDatadxp + 0x48 + 32, 0x08); - - // Second page - // storyOffset += 0x110; - // memcpy((void *)(storyOffset), saveDatadxp + 0x110, 0x90); - // storyOffset -= 0x110; - - // Third Page - // storyOffset += 0x1B8; - // memcpy((void *)(storyOffset), saveDatadxp + 0x1B8, 0x48); - // memcpy((void *)(storyOffset + 0x48 + 8), saveDatadxp + 0x1B8 + 0x48 + 8, 0x28); - // storyOffset -= 0x1B8; - - // Fourth page - // storyOffset += 0x240; - // memcpy((void *)(storyOffset), saveDatadxp + 0x240, 0x68); - // storyOffset -= 0x240; - - // Fifth page - // storyOffset += 0x2B8; - // memcpy((void *)(storyOffset), saveDatadxp + 0x2B8, 0x88); - // storyOffset -= 0x2B8; - + // Save data loaded successfully loadOkDxp = true; } + + // Close the save file fclose(file); } + // Success status + return 1; +} + +static int saveStoryData(char* filepath) +{ + // Miles path string + char storyPath[0xFF]; + + // Set the milepath memory to zero + memset(storyPath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(storyPath, filepath); + + // Append the mileage filename to the string + strcat(storyPath, "\\openprogress.sav"); + + // Save story data + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + + // Zero out save data binary + memset(saveDatadxp, 0, 0x2000); + + // Address where the player story data starts + uintptr_t storySaveBase = *(uintptr_t*)(saveDataBase + 0x108); + + // Copy 340 nibbles to saveDatadxp from the story save data index + memcpy(saveDatadxp, (void*)storySaveBase, 0x340); + + // Dump the save data to openprogress.sav + writeDump(storyPath, saveDatadxp, 0x2000); + + // Success + return 1; +} + +static int loadMileData(char* filepath) +{ + // Zero out the mile data memory + memset(mileDatadxp, 0, 0x08); + + // Miles path string + char milepath[0xFF]; + + // Set the milepath memory to zero + memset(milepath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(milepath, filepath); + + // Append the mileage filename to the string + strcat(milepath, "\\mileage.dat"); + + // Path to the miles file + FILE* miles = fopen(milepath, "rb"); + + // File loaded OK + if (miles) + { + // Get the size of the file + fseek(miles, 0, SEEK_END); + int mileSize = ftell(miles); + + // If the file size is correct + if (mileSize == 0x08) + { + // Load the content from the file into mileDatadxp + fseek(miles, 0, SEEK_SET); + fread(mileDatadxp, mileSize, 1, miles); + + // Get the pointer to the memory location storing the miles + uintptr_t mileMemory = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + + // Copy the mile data from the file into the memory location + memcpy((void*)(mileMemory + 0x280), mileDatadxp + 0x00, 0x04); + + fclose(miles); + } + } + + // Success + return 1; +} + +static int saveMileData(char* filepath) +{ + // Get the pointer to the memory location storing the miles + auto mileageLocation = (uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x280); + + // Miles path string + char milepath[0xFF]; + + // Set the milepath memory to zero + memset(milepath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(milepath, filepath); + + // Append the mileage filename to the string + strcat(milepath, "\\mileage.dat"); + + // Load the miles file + FILE* tempFile = fopen(milepath, "wb"); + + // Write the miles data from memory to the miles file + fwrite(mileageLocation, 1, sizeof(mileageLocation), tempFile); + + fclose(tempFile); + + // Success + return 1; +} + +static int loadGameData() +{ + // Disable saving + saveOk = false; + + // Miles path string + char loadPath[0xFF]; + + // Set the milepath memory to zero + memset(loadPath, 0, 0xFF); + + // Wirte the '.' into the load path + sprintf(loadPath, "."); + + // Seperate save file / cars per user profile + if (ToBool(config["Save"]["Save Per Custom Name"])) + { + // Get the profile name from the + std::string name = config["General"]["CustomName"]; + + // Add the c string version of the profile name to the path + sprintf(loadPath, "%s\\%s", loadPath, name.c_str()); + } + + // Seperate miles / story per car + if (ToBool(config["Save"]["Save Per Car"])) + { + // Need to get the hex code for the selected car + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + + // Address where the car save data starts + uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x268); + + // If custom car is set + if (customCarDxp) + { + // Add the car id to the save path + sprintf(loadPath, "%s\\custom", loadPath); + } + else // Custom car is not set + { + // Add the custom folder to the save path + sprintf(loadPath, "%s\\%08X", loadPath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); + } + } + + writeLog(logfileDxp, "creating directories ...\n"); + writeLog(logfileDxp, "path:" + std::string(loadPath) + "\n"); + + // Ensure the directory exists + std::filesystem::create_directories(loadPath); + + writeLog(logfileDxp, "loading story ...\n"); + + // Load the openprogress.sav file + loadStoryData(loadPath); + + writeLog(logfileDxp, "loading car ...\n"); + + // Load the car save file + loadCarData(loadPath); + + writeLog(logfileDxp, "loading miles ...\n"); + + // Load the miles save file + loadMileData(loadPath); + + writeLog(logfileDxp, "success.\n"); + + // Success return 1; } -static void LoadWmmt5carDataDxp() +// SaveGameData(void): Int +// If saving is enabled, loads the +// player story data +static int SaveGameData() { - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + // Saving is disabled + if (!saveOk) + return 1; -// if (!loadOkDxp) -// return; - customCarDxp = false; - memset(carDataDxp, 0, 0xFF); - memset(carFileNameDxp, 0, 0xFF); - CreateDirectoryA("OpenParrot_Cars", nullptr); + // Miles path string + char savePath[0xFF]; - LoadMileage(); + // Set the milepath memory to zero + memset(savePath, 0, 0xFF); - // check for custom car - sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\custom.car"); - if (FileExists(carFileNameDxp)) + // Wirte the '.' into the load path + sprintf(savePath, "."); + + // Seperate save file / cars per user profile + if (ToBool(config["Save"]["Save Per Custom Name"])) { - FILE* file = fopen(carFileNameDxp, "rb"); - if (file) - { - fseek(file, 0, SEEK_END); - int fsize = ftell(file); - if (fsize == 0xFF) - { - fseek(file, 0, SEEK_SET); - fread(carDataDxp, fsize, 1, file); - uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x268); - memcpy((void*)(carSaveLocation + 0xAC), carDataDxp + 0xAC, 0x1); //power - memcpy((void*)(carSaveLocation + 0xB8), carDataDxp + 0xB8, 0x1); //handling - memcpy((void*)(carSaveLocation + 0x28), carDataDxp + 0x28, 0x1); //region - memcpy((void*)(carSaveLocation + 0x34), carDataDxp + 0x34, 0x1); //carID - memcpy((void*)(carSaveLocation + 0x38), carDataDxp + 0x38, 0x1); //defaultColor - memcpy((void*)(carSaveLocation + 0x3C), carDataDxp + 0x3C, 0x1); //customColor - memcpy((void*)(carSaveLocation + 0x40), carDataDxp + 0x40, 0x1); //rims - memcpy((void*)(carSaveLocation + 0x44), carDataDxp + 0x44, 0x1); //rimColor - memcpy((void*)(carSaveLocation + 0x48), carDataDxp + 0x48, 0x1); //aero - memcpy((void*)(carSaveLocation + 0x4C), carDataDxp + 0x4C, 0x1); //hood - memcpy((void*)(carSaveLocation + 0x58), carDataDxp + 0x58, 0x1); //wang - memcpy((void*)(carSaveLocation + 0x5C), carDataDxp + 0x5C, 0x1); //mirror - memcpy((void*)(carSaveLocation + 0x60), carDataDxp + 0x60, 0x1); //sticker - memcpy((void*)(carSaveLocation + 0x64), carDataDxp + 0x64, 0x1); //stickerVariant - memcpy((void*)(carSaveLocation + 0x88), carDataDxp + 0x88, 0x1); //roofSticker - memcpy((void*)(carSaveLocation + 0x8C), carDataDxp + 0x8C, 0x1); //roofStickerVariant - memcpy((void*)(carSaveLocation + 0x90), carDataDxp + 0x90, 0x1); //neon - memcpy((void*)(carSaveLocation + 0x94), carDataDxp + 0x94, 0x1); //trunk - memcpy((void*)(carSaveLocation + 0x98), carDataDxp + 0x98, 0x1); //plateFrame - memcpy((void*)(carSaveLocation + 0xA0), carDataDxp + 0xA0, 0x4); //plateNumber - memcpy((void*)(carSaveLocation + 0xA4), carDataDxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 - memcpy((void*)(carSaveLocation + 0xA8), carDataDxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture - memcpy((void*)(carSaveLocation + 0xBC), carDataDxp + 0xBC, 0x1); //rank - memcpy((void*)(carSaveLocation + 0xF0), carDataDxp + 0xF0, 0x1); //title?? + // Get the profile name from the + std::string name = config["General"]["CustomName"]; - customCarDxp = true; - } - loadOkDxp = false; - fclose(file); - return; + // Add the c string version of the profile name to the path + sprintf(savePath, "%s\\%s", savePath, name.c_str()); + } + + // Seperate miles / story per car + if (ToBool(config["Save"]["Save Per Car"])) + { + // Need to get the hex code for the selected car + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); + + // Address where the car save data starts + uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x268); + + // If custom car is set + if (customCarDxp) + { + // Add the car id to the save path + sprintf(savePath, "%s\\custom", savePath); + } + else // Custom car is not set + { + // Add the custom folder to the save path + sprintf(savePath, "%s\\%08X", savePath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); } } - // If the force full tune switch is set - if (ToBool(config["Tune"]["Force Full Tune"])) - { - // Create the force full tune thread - CreateThread(0, 0, forceFullTune, 0, 0, 0); - } + writeLog(logfileDxp, "creating directories ...\n"); + writeLog(logfileDxp, "path:" + std::string(savePath) + "\n"); - memset(carFileNameDxp, 0, 0xFF); - // Load actual car if available - sprintf(carFileNameDxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x1F7D578) + 0x268) + 0x34)); - if(FileExists(carFileNameDxp)) - { - FILE* file = fopen(carFileNameDxp, "rb"); - if (file) - { - fseek(file, 0, SEEK_END); - int fsize = ftell(file); - if (fsize == 0xFF) - { - fseek(file, 0, SEEK_SET); - fread(carDataDxp, fsize, 1, file); - uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x268); - memcpy((void*)(carSaveLocation + 0xAC), carDataDxp + 0xAC, 0x1); //power - memcpy((void*)(carSaveLocation + 0xB8), carDataDxp + 0xB8, 0x1); //handling - memcpy((void*)(carSaveLocation + 0x28), carDataDxp + 0x28, 0x1); //region - memcpy((void*)(carSaveLocation + 0x34), carDataDxp + 0x34, 0x1); //carID - memcpy((void*)(carSaveLocation + 0x38), carDataDxp + 0x38, 0x1); //defaultColor - memcpy((void*)(carSaveLocation + 0x3C), carDataDxp + 0x3C, 0x1); //customColor - memcpy((void*)(carSaveLocation + 0x40), carDataDxp + 0x40, 0x1); //rims - memcpy((void*)(carSaveLocation + 0x44), carDataDxp + 0x44, 0x1); //rimColor - memcpy((void*)(carSaveLocation + 0x48), carDataDxp + 0x48, 0x1); //aero - memcpy((void*)(carSaveLocation + 0x4C), carDataDxp + 0x4C, 0x1); //hood - memcpy((void*)(carSaveLocation + 0x58), carDataDxp + 0x58, 0x1); //wang - memcpy((void*)(carSaveLocation + 0x5C), carDataDxp + 0x5C, 0x1); //mirror - memcpy((void*)(carSaveLocation + 0x60), carDataDxp + 0x60, 0x1); //sticker - memcpy((void*)(carSaveLocation + 0x64), carDataDxp + 0x64, 0x1); //stickerVariant - memcpy((void*)(carSaveLocation + 0x88), carDataDxp + 0x88, 0x1); //roofSticker - memcpy((void*)(carSaveLocation + 0x8C), carDataDxp + 0x8C, 0x1); //roofStickerVariant - memcpy((void*)(carSaveLocation + 0x90), carDataDxp + 0x90, 0x1); //neon - memcpy((void*)(carSaveLocation + 0x94), carDataDxp + 0x94, 0x1); //trunk - memcpy((void*)(carSaveLocation + 0x98), carDataDxp + 0x98, 0x1); //plateFrame - memcpy((void*)(carSaveLocation + 0xA0), carDataDxp + 0xA0, 0x4); //plateNumber - memcpy((void*)(carSaveLocation + 0xA4), carDataDxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 - memcpy((void*)(carSaveLocation + 0xA8), carDataDxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture - memcpy((void*)(carSaveLocation + 0xBC), carDataDxp + 0xBC, 0x1); //rank - memcpy((void*)(carSaveLocation + 0xF0), carDataDxp + 0xF0, 0x1); //title?? - } - fclose(file); - } - } - loadOkDxp = false; + // Ensure the directory exists + std::filesystem::create_directories(savePath); + + writeLog(logfileDxp, "saving story ...\n"); + + // Load the openprogress.sav file + saveStoryData(savePath); + + writeLog(logfileDxp, "saving car ...\n"); + + // Load the car save file + saveCarData(savePath); + + writeLog(logfileDxp, "saving miles ...\n"); + + // Load the miles save file + saveMileData(savePath); + + writeLog(logfileDxp, "success.\n"); + + // Disable saving + saveOk = false; + + // Success + return 1; } static void loadGame() @@ -832,26 +1025,10 @@ static void loadGame() // Runs after car data is loaded // Load story data thread - std::thread t1(LoadGameData); + std::thread t1(loadGameData); t1.detach(); - - // Load car data thread - std::thread t2(LoadWmmt5carDataDxp); - t2.detach(); } -/* -static void loadStory() -{ - -} - -static void loadCar() -{ - -} -*/ - static int ReturnTrue() { return 1; @@ -1056,8 +1233,6 @@ static DWORD WINAPI SpamMulticast(LPVOID) // of required subprocesses. static InitFunction Wmmt5Func([]() { - writeLog(logfileDxp, "[DEBUG] Starting emulation ...\n"); - // Records if terminal mode is enabled bool isTerminal = false; From a2d78bdc0844c53f5276aac86f256e159a66f2e5 Mon Sep 17 00:00:00 2001 From: Scrubbs Date: Thu, 28 Apr 2022 00:06:02 +1000 Subject: [PATCH 3/8] MT5/5DX+ Seperate Story/Mile Saving per car and / or per profile (optional) --- OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp | 793 +++++++++++++----- .../src/Functions/Games/ES3X/WMMT5DXPlus.cpp | 614 ++++++++++++-- 2 files changed, 1121 insertions(+), 286 deletions(-) diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp index d16660c..68565d5 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp @@ -1,6 +1,7 @@ #include #include "Utility/InitFunction.h" #include "Functions/Global.h" +#include #include #include #include @@ -427,9 +428,114 @@ unsigned int WINAPI Hook_bind(SOCKET s, const sockaddr *addr, int namelen) { } } - +// Save data dump memory block unsigned char saveData[0x2000]; +// BASE: 0x24E0 +// Campaing honor data: 2998, save 0xB8 +// Story Mode Honor data: 25F0, save 0x98 +// StoryModeNoLoseHonorData: 2C80, Copy 0,0x10, Copy 0x18,0x28 maybe 8 bytes more +// OtherHonorData: 2A90, Copy 0x60 +// CampaignHonorData: 2698, Copy 0x48 + +//static int SaveCampaingHonorData2() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2698; +// FILE* file = fopen(V("CampaignHonorData.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x48); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveOtherHonorData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2A90; +// FILE* file = fopen(V("OtherHonorData.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x60); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveStoryModeNoLoseHonorData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2C80; +// FILE* file = fopen(V("StoryModeNoLoseHonorData.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x10); +// value += 0x18; +// memcpy(saveData, (void *)value, 0x28); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveCampaingHonorData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2998; +// FILE* file = fopen(V("campaing.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0xB8); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveStoryData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x25F0; +// FILE* file = fopen(V("story.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x98); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} + +// setFullTune(void): Int +// If the currently loaded car is NOT fully tuned, +// updates the power and handling values to be fully +// tuned (16 for each). If they are already fully tuned, +// does not change any values. +static int setFullTune() +{ + // Car save hex address + auto carSaveBase = (uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); + auto powerAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0x98); + auto handleAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0x9C); + + // Dereference the power value from the memory address + auto powerValue = injector::ReadMemory(powerAddress, true); + auto handleValue = injector::ReadMemory(handleAddress, true); + + // If the power and handling values do not add up to fully tuned + if (powerValue + handleValue < 0x20) + { + // Car is not fully tuned, force it to the default full tune + injector::WriteMemory(powerAddress, 0x10, true); + injector::WriteMemory(handleAddress, 0x10, true); + + // Updated + return 1; + } + + // Not updated + return 0; +} + // forceFullTune(pArguments: void*): DWORD WINAPI // Function which runs in a secondary thread if the forceFullTune // option is selected in the compiler. If the player's car is not fully @@ -443,24 +549,8 @@ static DWORD WINAPI forceFullTune(void* pArguments) // Only runs every 16th frame Sleep(16); - // Car save hex address - auto carSaveBase = (uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); - auto powerAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase) + 0x98); - auto handleAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase) + 0x9C); - - // Dereference the power value from the memory address - auto powerValue = injector::ReadMemory(powerAddress, true); - auto handleValue = injector::ReadMemory(handleAddress, true); - - // If the power and handling values do not add up to fully tuned - if (powerValue + handleValue < 0x20) - { - // Car is not fully tuned, force it to the default full tune - injector::WriteMemory(powerAddress, 0x10, true); - injector::WriteMemory(handleAddress, 0x10, true); - } - - // Otherwise, don't do anything :) + // Run the set full tune process + setFullTune(); } } @@ -486,228 +576,529 @@ static int writeLog(std::string filename, std::string message) // Open the filename provided (append mode) eventLog.open(filename, std::ios_base::app); - // Write the message to the file - eventLog << message; + // File open success + if (eventLog.is_open()) + { + // Write the message to the file + eventLog << message; - // Close the log file handle - eventLog.close(); + // Close the log file handle + eventLog.close(); - // Success - return 0; + // Success + return 0; + } + else // File open failed + { + // Failure + return 1; + } } +// writeDump(filename: Char*, data: unsigned char *, size: size_t): Int +static int writeDump(char* filename, unsigned char* data, size_t size) +{ + // Open the file with the provided filename + FILE* file = fopen(filename, "wb"); + + // File opened successfully + if (file) + { + // Write the data to the file + fwrite((void*)data, 1, size, file); + + // Close the file + fclose(file); + + // Return success status + return 0; + } + else // Failed to open + { + // Return failure status + return 1; + } +} + +// Sets if saving is allowed or not static bool saveOk = false; + +// If custom car is used +bool customCar = false; + +// Sets if loading is allowed +bool loadOk = false; + +// Car save data reserved memory unsigned char carData[0xFF]; + +// Car filename string +char carFileName[0xFF]; + +// SaveOk(void): Void +// Enables saving static int SaveOk() { saveOk = true; return 1; } -char carFileName[0xFF]; -bool loadOk = false; -bool customCar = false; - -static int SaveGameData() +// loadCarFile(filename: char*): Int +// Given a filename, loads the data from +// the car file into memory. +static int loadCarFile(char* filename) { - if (!saveOk) - return 1; + // Open the file with the filename + FILE* file = fopen(filename, "rb"); - // Zero out save data binary - memset(saveData, 0, 0x2000); - - // Get the hex address for the start of the save data block - uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); - value = *(uintptr_t*)(value + 0x108); - memcpy(saveData, (void *)value, 0x340); - - FILE* file = fopen("openprogress.sav", "wb"); - fwrite(saveData, 1, 0x2000, file); - fclose(file); - - // Car Profile saving - memset(carData, 0, 0xFF); - memset(carFileName, 0, 0xFF); - - memcpy(carData, (void *)*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18), 0xE0); - CreateDirectoryA("OpenParrot_Cars", nullptr); - if(customCar) - { - sprintf(carFileName, ".\\OpenParrot_Cars\\custom.car"); - } - else - { - sprintf(carFileName, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); - } - FILE *carSave = fopen(carFileName, "wb"); - fwrite(carData, 1, 0xE0, file); - fclose(carSave); - //SaveStoryData(); - //SaveCampaingHonorData(); - //SaveStoryModeNoLoseHonorData(); - //SaveOtherHonorData(); - //SaveCampaingHonorData2(); - saveOk = false; - return 1; -} - -uintptr_t saveGameOffset; - -static int LoadGameData() -{ - saveOk = false; - memset(saveData, 0x0, 0x2000); - FILE* file = fopen("openprogress.sav", "rb"); + // File open OK if (file) { + // Get the length of the file fseek(file, 0, SEEK_END); int fsize = ftell(file); - if (fsize == 0x2000) + + // If the file has the right size + if (fsize == 0xE0) { + // Reset to start of the file and read it into the car data variable fseek(file, 0, SEEK_SET); - fread(saveData, fsize, 1, file); - uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); - value = *(uintptr_t*)(value + 0x108); + fread(carData, fsize, 1, file); - // First page - //memcpy((void *)(value), saveData, 0x48); - memcpy((void *)(value + 0x10), saveData + 0x10, 0x20); - memcpy((void *)(value + 0x40), saveData + 0x40, 0x08); - //memcpy((void *)(value + 0x48 + 8), saveData + 0x48 + 8, 0x20); - memcpy((void *)(value + 0x48 + 8), saveData + 0x48 + 8, 0x08); - memcpy((void *)(value + 0x48 + 24), saveData + 0x48 + 24, 0x08); - memcpy((void *)(value + 0x48 + 32), saveData + 0x48 + 32, 0x08); + // Dereference the memory location for the car save data + uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); - // Second page - value += 0x110; - memcpy((void *)(value), saveData + 0x110, 0x90); - value -= 0x110; - - // Third Page - value += 0x1B8; - memcpy((void *)(value), saveData + 0x1B8, 0x48); - memcpy((void *)(value + 0x48 + 8), saveData + 0x1B8 + 0x48 + 8, 0x28); - value -= 0x1B8; - - // Fourth page - value += 0x240; - memcpy((void *)(value), saveData + 0x240, 0x68); - value -= 0x240; - - // Fifth page - value += 0x2B8; - memcpy((void *)(value), saveData + 0x2B8, 0x88); - value -= 0x2B8; - - loadOk = true; + memcpy((void*)(carSaveLocation + 0x08), carData + 0x08, 8); // ?? + memcpy((void*)(carSaveLocation + 0x10), carData + 0x10, 8); // ?? + memcpy((void*)(carSaveLocation + 0x20), carData + 0x20, 8); // ?? + memcpy((void*)(carSaveLocation + 0x28), carData + 0x28, 8); // ?? + memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 8); // Stock Colour (0x30), Custom Colour (0x34) + memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 8); // Rims Type (0x38), Rims Colour (0x3C) + memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 8); // Aero Type (0x40), Hood Type (0x44) + memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 8); // Wing Type (0x50), Mirror Type (0x54) + memcpy((void*)(carSaveLocation + 0x58), carData + 0x58, 8); // Body Sticker Type (0x58), Variant (0x5C) + memcpy((void*)(carSaveLocation + 0x68), carData + 0x68, 8); // ?? + memcpy((void*)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neon Type + memcpy((void*)(carSaveLocation + 0x80), carData + 0x80, 8); // Trunk Colour (0x80), Plate Frame (0x84) + memcpy((void*)(carSaveLocation + 0x88), carData + 0x88, 8); // Plate Frame Colour (0x8A) + memcpy((void*)(carSaveLocation + 0x90), carData + 0x90, 8); // ?? + memcpy((void*)(carSaveLocation + 0x98), carData + 0x98, 8); // Power (0x98), Handling (0x9C) + memcpy((void*)(carSaveLocation + 0xA0), carData + 0xA0, 8); // Rank (0xA4) + memcpy((void*)(carSaveLocation + 0xA8), carData + 0xA8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xB8), carData + 0xB8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xC8), carData + 0xC8, 8); // ?? + memcpy((void*)(carSaveLocation + 0xD8), carData + 0xD8, 8); // ?? } + + // Disable loading + loadOk = false; + + // Close the file fclose(file); + + // Success + return 1; } - return 1; + // Failed + return 0; } -static void LoadWmmt5CarData() +// loadCarData(filepath: char*): Void +// Given a filepath, attempts to load a +// car file (either custom.car or specific +// car file) from that folder. +static int loadCarData(char* filepath) { - if (!loadOk) - return; - customCar = false; - memset(carData, 0, 0xFF); - memset(carFileName, 0, 0xFF); - CreateDirectoryA("OpenParrot_Cars", nullptr); + // Sleep for 1 second + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - // check for custom car - sprintf(carFileName, ".\\OpenParrot_Cars\\custom.car"); + // Custom car disabled by default + customCar = false; + + // Miles path string + char carPath[0xFF]; + + // Set the milepath memory to zero + memset(carPath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(carPath, filepath); + + // Append the mileage filename to the string + strcat(carPath, "\\OpenParrot_Cars"); + + // Create the OpenParrot_cars directory at the given filepath + std::filesystem::create_directories(carPath); + + // Get the path to the custom car file + sprintf(carFileName, "%s\\custom.car", carPath); + + // If the custom car file exists if (FileExists(carFileName)) { - FILE* file = fopen(carFileName, "rb"); - if (file) - { - fseek(file, 0, SEEK_END); - int fsize = ftell(file); - if (fsize == 0xE0) - { - fseek(file, 0, SEEK_SET); - fread(carData, fsize, 1, file); - uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); + // Load the custom car file + loadCarFile(carFileName); - memcpy((void*)(carSaveLocation + 0x08), carData + 0x08, 8); // ?? - memcpy((void*)(carSaveLocation + 0x10), carData + 0x10, 8); // ?? - memcpy((void*)(carSaveLocation + 0x20), carData + 0x20, 8); // ?? - memcpy((void*)(carSaveLocation + 0x28), carData + 0x28, 8); // ?? - memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 8); // Stock Colour (0x30), Custom Colour (0x34) - memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 8); // Rims Type (0x38), Rims Colour (0x3C) - memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 8); // Aero Type (0x40), Hood Type (0x44) - memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 8); // Wing Type (0x50), Mirror Type (0x54) - memcpy((void*)(carSaveLocation + 0x58), carData + 0x58, 8); // Body Sticker Type (0x58), Variant (0x5C) - memcpy((void*)(carSaveLocation + 0x68), carData + 0x68, 8); // ?? - memcpy((void*)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neon Type - memcpy((void*)(carSaveLocation + 0x80), carData + 0x80, 8); // Trunk Colour (0x80), Plate Frame (0x84) - memcpy((void*)(carSaveLocation + 0x88), carData + 0x88, 8); // Plate Frame Colour (0x8A) - memcpy((void*)(carSaveLocation + 0x90), carData + 0x90, 8); // ?? - memcpy((void*)(carSaveLocation + 0x98), carData + 0x98, 8); // Power (0x98), Handling (0x9C) - memcpy((void*)(carSaveLocation + 0xA0), carData + 0xA0, 8); // Rank (0xA4) - memcpy((void*)(carSaveLocation + 0xA8), carData + 0xA8, 8); // ?? - memcpy((void*)(carSaveLocation + 0xB8), carData + 0xB8, 8); // ?? - memcpy((void*)(carSaveLocation + 0xC8), carData + 0xC8, 8); // ?? - memcpy((void*)(carSaveLocation + 0xD8), carData + 0xD8, 8); // ?? + // Enable custom car switch + customCar = true; + } - customCar = true; - } - loadOk = false; - fclose(file); - return; - } + // Empty the car filename string + memset(carFileName, 0, 0xFF); + + // Get the path to the specific car file + sprintf(carFileName, "%s\\%08X.car", carPath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); + + // If the specific car file exists + if (FileExists(carFileName)) + { + // Load the car file + loadCarFile(carFileName); } // If the force full tune switch is set if (ToBool(config["Tune"]["Force Full Tune"])) { // Create the force full tune thread - CreateThread(0, 0, forceFullTune, 0, 0, 0); + // CreateThread(0, 0, forceFullTune, 0, 0, 0); + + // Set the car to be fully tuned + setFullTune(); } - memset(carFileName, 0, 0xFF); - // Load actual car if available - sprintf(carFileName, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); - if(FileExists(carFileName)) - { - FILE* file = fopen(carFileName, "rb"); - if (file) - { - fseek(file, 0, SEEK_END); - int fsize = ftell(file); - if (fsize == 0xE0) - { - fseek(file, 0, SEEK_SET); - fread(carData, fsize, 1, file); - uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBase + 0x1948F10)) + 0x180 + 0xa8 + 0x18); + // Success + return 1; +} - memcpy((void*)(carSaveLocation + 0x08), carData + 0x08, 8); // ?? - memcpy((void*)(carSaveLocation + 0x10), carData + 0x10, 8); // ?? - memcpy((void*)(carSaveLocation + 0x20), carData + 0x20, 8); // ?? - memcpy((void*)(carSaveLocation + 0x28), carData + 0x28, 8); // ?? - memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 8); // Stock Colour (0x30), Custom Colour (0x34) - memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 8); // Rims Type (0x38), Rims Colour (0x3C) - memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 8); // Aero Type (0x40), Hood Type (0x44) - memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 8); // Wing Type (0x50), Mirror Type (0x54) - memcpy((void*)(carSaveLocation + 0x58), carData + 0x58, 8); // Body Sticker Type (0x58), Variant (0x5C) - memcpy((void*)(carSaveLocation + 0x68), carData + 0x68, 8); // ?? - memcpy((void*)(carSaveLocation + 0x7C), carData + 0x7C, 1); // Neon Type - memcpy((void*)(carSaveLocation + 0x80), carData + 0x80, 8); // Trunk Colour (0x80), Plate Frame (0x84) - memcpy((void*)(carSaveLocation + 0x88), carData + 0x88, 8); // Plate Frame Colour (0x8A) - memcpy((void*)(carSaveLocation + 0x90), carData + 0x90, 8); // ?? - memcpy((void*)(carSaveLocation + 0x98), carData + 0x98, 8); // Power (0x98), Handling (0x9C) - memcpy((void*)(carSaveLocation + 0xA0), carData + 0xA0, 8); // Rank (0xA4) - memcpy((void*)(carSaveLocation + 0xA8), carData + 0xA8, 8); // ?? - memcpy((void*)(carSaveLocation + 0xB8), carData + 0xB8, 8); // ?? - memcpy((void*)(carSaveLocation + 0xC8), carData + 0xC8, 8); // ?? - memcpy((void*)(carSaveLocation + 0xD8), carData + 0xD8, 8); // ?? - } - fclose(file); +static int saveCarData(char* filepath) +{ + // Car Profile saving + memset(carData, 0, 0xFF); + memset(carFileName, 0, 0xFF); + + // Get the hex address for the start of the save data block + uintptr_t saveDataBase = *(uintptr_t*)(imageBase + 0x1948F10); + + // Address where car save data starts + uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x108); + + // Miles path string + char carPath[0xFF]; + + // Set the milepath memory to zero + memset(carPath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(carPath, filepath); + + // Append the mileage filename to the string + strcat(carPath, "\\OpenParrot_Cars"); + + // CreateDirectoryA(carPath, nullptr); + + // Create the cars path folder + std::filesystem::create_directories(carPath); + + // Copy the 0xE0 bytes from memory to the car data array + memcpy(carData, (void*)*(uintptr_t*)(saveDataBase + 0x180 + 0xa8 + 0x18), 0xE0); + + // If custom car is set + if (customCar) + { + // Save the file to custom.car + sprintf(carPath, "%s\\custom.car", carPath); + } + else // Custom car is not set + { + // Save the file to the specific car filename + sprintf(carPath, "%s\\%08X.car", carPath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); + } + + // Open the file at the given car path + FILE* carFile = fopen(carPath, "wb"); + + // Write the data from the array to the file + fwrite(carData, 1, 0xE0, carFile); + fclose(carFile); + + // Success + return 1; +} + +static int saveStoryData(char* filepath) +{ + // Miles path string + char storyPath[0xFF]; + + // Set the milepath memory to zero + memset(storyPath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(storyPath, filepath); + + // Append the mileage filename to the string + strcat(storyPath, "\\openprogress.sav"); + + // Save story data + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBase + 0x1948F10); + + // Zero out save data binary + memset(saveData, 0, 0x2000); + + // Address where the story save data starts + uintptr_t storySaveBase = *(uintptr_t*)(saveDataBase + 0x108); + + // Copy to saveData from the story save data index + memcpy(saveData, (void*)storySaveBase, 0x340); + + // Dump the save data to openprogress.sav + writeDump(storyPath, saveData, 0x2000); + + //SaveStoryData(); + //SaveCampaingHonorData(); + //SaveStoryModeNoLoseHonorData(); + //SaveOtherHonorData(); + //SaveCampaingHonorData2(); + + // Success + return 1; +} + +static int loadStoryData(char* filepath) +{ + // Zero out the save data array + memset(saveData, 0x0, 0x2000); + + // Miles path string + char storyPath[0xFF]; + + // Set the milepath memory to zero + memset(storyPath, 0, 0xFF); + + // Copy the file path to the miles path + strcpy(storyPath, filepath); + + // Append the mileage filename to the string + strcat(storyPath, "\\openprogress.sav"); + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBase + 0x1948F10); + + // Open the openprogress file with read privileges + FILE* file = fopen(storyPath, "rb"); + + // If the file exists + if (file) + { + // Get all of the contents from the file + fseek(file, 0, SEEK_END); + + // Get the size of the file + int fsize = ftell(file); + + // Check file is correct size + if (fsize == 0x2000) + { + // Reset seek index to start + fseek(file, 0, SEEK_SET); + + // Read all of the contents of the file into saveDatadxp + fread(saveData, fsize, 1, file); + + // Story save data offset + uintptr_t saveStoryBase = *(uintptr_t*)(saveDataBase + 0x108); + + // Not sure why, but story doesn't load unless I add this + memcpy((void*)(saveStoryBase + 0x48), saveData + 0x48, 0x1); + + // Pretty sure this is the whole save file region, but need to test more :) + memcpy((void*)(saveStoryBase + 0xE0), saveData + 0xE0, 0x80); + + /* + // First page + //memcpy((void *)(value), saveData, 0x48); + memcpy((void*)(value + 0x10), saveData + 0x10, 0x20); + memcpy((void*)(value + 0x40), saveData + 0x40, 0x08); + //memcpy((void *)(value + 0x48 + 8), saveData + 0x48 + 8, 0x20); + memcpy((void*)(value + 0x48 + 8), saveData + 0x48 + 8, 0x08); + memcpy((void*)(value + 0x48 + 24), saveData + 0x48 + 24, 0x08); + memcpy((void*)(value + 0x48 + 32), saveData + 0x48 + 32, 0x08); + + // Second page + value += 0x110; + memcpy((void*)(value), saveData + 0x110, 0x90); + value -= 0x110; + + // Third Page + value += 0x1B8; + memcpy((void*)(value), saveData + 0x1B8, 0x48); + memcpy((void*)(value + 0x48 + 8), saveData + 0x1B8 + 0x48 + 8, 0x28); + value -= 0x1B8; + + // Fourth page + value += 0x240; + memcpy((void*)(value), saveData + 0x240, 0x68); + value -= 0x240; + + // Fifth page + value += 0x2B8; + memcpy((void*)(value), saveData + 0x2B8, 0x88); + value -= 0x2B8; + */ + + + // Save data loaded successfully + loadOk = true; + } + fclose(file); + } + + //LoadStoryData(); + //LoadCampaingHonorData(); + //LoadStoryModeNoLoseHonorData(); + //LoadOtherHonorData(); + //LoadCampaingHonorData2(); + + // Success status + return 1; +} + +static int SaveGameData() +{ + // Saving is disabled + if (!saveOk) + return 1; + + // Miles path string + char savePath[0xFF]; + + // Set the milepath memory to zero + memset(savePath, 0, 0xFF); + + // Wirte the '.' into the load path + sprintf(savePath, "."); + + // Seperate save file / cars per user profile + if (ToBool(config["Save"]["Save Per Custom Name"])) + { + // Get the profile name from the + std::string name = config["General"]["CustomName"]; + + // Add the c string version of the profile name to the path + sprintf(savePath, "%s\\%s", savePath, name.c_str()); + } + + // Seperate miles / story per car + if (ToBool(config["Save"]["Save Per Car"])) + { + // Need to get the hex code for the selected car + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBase + 0x1948F10); + + // Address where the car save data starts + uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x108); + + // If custom car is set + if (customCar) + { + // Add the car id to the save path + sprintf(savePath, "%s\\custom", savePath); + } + else // Custom car is not set + { + // Add the custom folder to the save path + sprintf(savePath, "%s\\%08X", savePath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); } } - loadOk = false; + + // Ensure the directory exists + std::filesystem::create_directories(savePath); + + // Save the openprogress.sav file + saveStoryData(savePath); + + // Save the car save file + saveCarData(savePath); + + // Disable saving + saveOk = false; + + // Success + return 1; +} + +static int loadGameData() +{ + // Disable saving + saveOk = false; + + // Miles path string + char loadPath[0xFF]; + + // Set the milepath memory to zero + memset(loadPath, 0, 0xFF); + + // Wirte the '.' into the load path + sprintf(loadPath, "."); + + // Seperate save file / cars per user profile + if (ToBool(config["Save"]["Save Per Custom Name"])) + { + // Get the profile name from the + std::string name = config["General"]["CustomName"]; + + // Add the c string version of the profile name to the path + sprintf(loadPath, "%s\\%s", loadPath, name.c_str()); + } + + // Seperate miles / story per car + if (ToBool(config["Save"]["Save Per Car"])) + { + // Need to get the hex code for the selected car + + // Address where player save data starts + uintptr_t saveDataBase = *(uintptr_t*)(imageBase + 0x1948F10); + + // Address where the car save data starts + uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x108); + + // If custom car is set + if (customCar) + { + // Add the car id to the save path + sprintf(loadPath, "%s\\custom", loadPath); + } + else // Custom car is not set + { + // Add the custom folder to the save path + sprintf(loadPath, "%s\\%08X", loadPath, *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); + } + } + + // Ensure the directory exists + std::filesystem::create_directories(loadPath); + + // Load the openprogress.sav file + loadStoryData(loadPath); + + // Load the car save file + loadCarData(loadPath); + + // Success + return 1; +} + +static void loadGame() +{ + // Runs after car data is loaded + + // Load story data thread + std::thread t1(loadGameData); + t1.detach(); } static int ReturnTrue() @@ -1123,7 +1514,9 @@ static InitFunction Wmmt5Func([]() // skip erasing of temp card data injector::WriteMemory(imageBase + 0x8DEBC3, 0xEB, true); // Skip erasing of temp card - safeJMP(imageBase + 0x54DCE1, LoadGameData); + + // Old story load func + // safeJMP(imageBase + 0x54DCE1, LoadGameData); safeJMP(imageBase + 0x5612F0, ReturnTrue); safeJMP(imageBase + 0x5753C0, ReturnTrue); safeJMP(imageBase + 0x57DF10, ReturnTrue); @@ -1141,7 +1534,11 @@ static InitFunction Wmmt5Func([]() safeJMP(imageBase + 0x5507A0, ReturnTrue); safeJMP(imageBase + 0x561290, ReturnTrue); - safeJMP(imageBase + 0x5A0AE8, LoadWmmt5CarData); + + // safeJMP(imageBase + 0x5A0AE8, LoadWmmt5CarData); + + // Load story and car data + safeJMP(imageBase + 0x5A0AE8, loadGame); // crash fix //safeJMP(imageBase + 0xAD6F28, WmmtOperatorDelete); diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp index 111610e..ca24a5e 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp @@ -385,6 +385,111 @@ bool WINAPI Hook_SetSystemTime(SYSTEMTIME* in) return TRUE; } +// BASE: 0x24E0 +// Campaing honor data: 2998, save 0xB8 +// Story Mode Honor data: 25F0, save 0x98 +// StoryModeNoLoseHonorData: 2C80, Copy 0,0x10, Copy 0x18,0x28 maybe 8 bytes more +// OtherHonorData: 2A90, Copy 0x60 +// CampaignHonorData: 2698, Copy 0x48 + +//static int SaveCampaingHonorData2() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2698; +// FILE* file = fopen(V("CampaignHonorData.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x48); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveOtherHonorData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2A90; +// FILE* file = fopen(V("OtherHonorData.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x60); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveStoryModeNoLoseHonorData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2C80; +// FILE* file = fopen(V("StoryModeNoLoseHonorData.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x10); +// value += 0x18; +// memcpy(saveData, (void *)value, 0x28); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveCampaingHonorData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2998; +// FILE* file = fopen(V("campaing.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0xB8); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} +// +//static int SaveStoryData() +//{ +// memset(saveData, 0, 0x1000); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x25F0; +// FILE* file = fopen(V("story.sav"), V("wb")); +// memcpy(saveData, (void *)value, 0x98); +// fwrite(saveData, 1, 0x100, file); +// fclose(file); +// return 1; +//} + +// setFullTune(void): Int +// If the currently loaded car is NOT fully tuned, +// updates the power and handling values to be fully +// tuned (16 for each). If they are already fully tuned, +// does not change any values. +static int setFullTune() +{ + // Get the memory addresses for the car base save, power and handling values + auto carSaveBase = (uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x01F7D578) + 0x268); + auto powerAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0xAC); + auto handleAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0xB8); + + // Dereference the power value from the memory address + auto powerValue = injector::ReadMemory(powerAddress, true); + auto handleValue = injector::ReadMemory(handleAddress, true); + + // If the power and handling values do not add up to fully tuned + if (powerValue + handleValue < 0x20) + { + // Car is not fully tuned, force it to the default full tune + injector::WriteMemory(powerAddress, 0x10, true); + injector::WriteMemory(handleAddress, 0x10, true); + + // Updated + return 1; + } + + // Not updated + return 0; +} + // forceFullTune(pArguments: void*): DWORD WINAPI // Function which runs in a secondary thread if the forceFullTune // option is selected in the menu. If the player's car is not fully @@ -398,24 +503,8 @@ static DWORD WINAPI forceFullTune(void* pArguments) // Only runs every 16th frame Sleep(16); - // Get the memory addresses for the car base save, power and handling values - auto carSaveBase = (uintptr_t*)(*(uintptr_t*)(imageBasedxplus + 0x01F7D578) + 0x268); - auto powerAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0xAC); - auto handleAddress = (uintptr_t*)(*(uintptr_t*)(carSaveBase)+0xB8); - - // Dereference the power value from the memory address - auto powerValue = injector::ReadMemory(powerAddress, true); - auto handleValue = injector::ReadMemory(handleAddress, true); - - // If the power and handling values do not add up to fully tuned - if (powerValue + handleValue < 0x20) - { - // Car is not fully tuned, force it to the default full tune - injector::WriteMemory(powerAddress, 0x10, true); - injector::WriteMemory(handleAddress, 0x10, true); - } - - // Otherwise, don't do anything :) + // Run the set full tune process + setFullTune(); } } @@ -485,20 +574,29 @@ static int writeDump(char * filename, unsigned char * data, size_t size) } } +// Sets if saving is allowed or not static bool saveOk = false; + +// If custom car is used +bool customCarDxp = false; + +// Sets if loading is allowed +bool loadOkDxp = false; + +// Car save data reserved memory unsigned char carDataDxp[0xFF]; + +// Car filename string +char carFileNameDxp[0xFF]; + +// SaveOk(void): Void +// Enables saving static int SaveOk() { saveOk = true; return 1; } -char carFileNameDxp[0xFF]; -bool loadOkDxp = false; -bool customCarDxp = false; - -uintptr_t saveGameOffsetdxp; - // loadCarFile(filename: char*): Int // Given a filename, loads the data from // the car file into memory. @@ -524,30 +622,35 @@ static int loadCarFile(char* filename) // Dereference the memory location for the car save data uintptr_t carSaveLocation = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x268); - memcpy((void*)(carSaveLocation + 0xAC), carDataDxp + 0xAC, 0x1); //power - memcpy((void*)(carSaveLocation + 0xB8), carDataDxp + 0xB8, 0x1); //handling - memcpy((void*)(carSaveLocation + 0x28), carDataDxp + 0x28, 0x1); //region - memcpy((void*)(carSaveLocation + 0x34), carDataDxp + 0x34, 0x1); //carID - memcpy((void*)(carSaveLocation + 0x38), carDataDxp + 0x38, 0x1); //defaultColor - memcpy((void*)(carSaveLocation + 0x3C), carDataDxp + 0x3C, 0x1); //customColor - memcpy((void*)(carSaveLocation + 0x40), carDataDxp + 0x40, 0x1); //rims - memcpy((void*)(carSaveLocation + 0x44), carDataDxp + 0x44, 0x1); //rimColor - memcpy((void*)(carSaveLocation + 0x48), carDataDxp + 0x48, 0x1); //aero - memcpy((void*)(carSaveLocation + 0x4C), carDataDxp + 0x4C, 0x1); //hood - memcpy((void*)(carSaveLocation + 0x58), carDataDxp + 0x58, 0x1); //wang - memcpy((void*)(carSaveLocation + 0x5C), carDataDxp + 0x5C, 0x1); //mirror - memcpy((void*)(carSaveLocation + 0x60), carDataDxp + 0x60, 0x1); //sticker - memcpy((void*)(carSaveLocation + 0x64), carDataDxp + 0x64, 0x1); //stickerVariant - memcpy((void*)(carSaveLocation + 0x88), carDataDxp + 0x88, 0x1); //roofSticker - memcpy((void*)(carSaveLocation + 0x8C), carDataDxp + 0x8C, 0x1); //roofStickerVariant - memcpy((void*)(carSaveLocation + 0x90), carDataDxp + 0x90, 0x1); //neon - memcpy((void*)(carSaveLocation + 0x94), carDataDxp + 0x94, 0x1); //trunk - memcpy((void*)(carSaveLocation + 0x98), carDataDxp + 0x98, 0x1); //plateFrame - memcpy((void*)(carSaveLocation + 0xA0), carDataDxp + 0xA0, 0x4); //plateNumber - memcpy((void*)(carSaveLocation + 0xA4), carDataDxp + 0xA4, 0x1); //vinyl_body_challenge_prefecture_1~15 - memcpy((void*)(carSaveLocation + 0xA8), carDataDxp + 0xA8, 0x1); //vinyl_body_challenge_prefecture - memcpy((void*)(carSaveLocation + 0xBC), carDataDxp + 0xBC, 0x1); //rank - memcpy((void*)(carSaveLocation + 0xF0), carDataDxp + 0xF0, 0x1); //title?? + // memcpy((void*)(carSaveLocation + 0x00), carDataDxp + 0x00, 8); // ?? + // memcpy((void*)(carSaveLocation + 0x08), carDataDxp + 0x08, 8); // ?? + // memcpy((void*)(carSaveLocation + 0x10), carDataDxp + 0x10, 8); // ?? + // memcpy((void*)(carSaveLocation + 0x18), carDataDxp + 0x18, 8); // ?? + // memcpy((void*)(carSaveLocation + 0x20), carDataDxp + 0x20, 8); // Crash + memcpy((void*)(carSaveLocation + 0x28), carDataDxp + 0x28, 8); // Region (0x28) + memcpy((void*)(carSaveLocation + 0x30), carDataDxp + 0x30, 8); // CarID (0x34) + // memcpy((void*)(carSaveLocation + 0x38), carDataDxp + 0x38, 4); // defaultColor + memcpy((void*)(carSaveLocation + 0x3C), carDataDxp + 0x3C, 4); // CustomColor (0x3C) + memcpy((void*)(carSaveLocation + 0x40), carDataDxp + 0x40, 8); // Rims (0x40), Rims Colour (0x44) + memcpy((void*)(carSaveLocation + 0x48), carDataDxp + 0x48, 8); // Aero (0x48), Hood (0x4C) + // memcpy((void*)(carSaveLocation + 0x50), carDataDxp + 0x50, 8); // Crash + memcpy((void*)(carSaveLocation + 0x58), carDataDxp + 0x58, 8); // Wing (0x58), Mirror (0x5C) + memcpy((void*)(carSaveLocation + 0x60), carDataDxp + 0x60, 8); // Sticker (0x60), Sticker Type (0x64) + // memcpy((void*)(carSaveLocation + 0x68), carDataDxp + 0x60, 8); // Crash + memcpy((void*)(carSaveLocation + 0x88), carDataDxp + 0x88, 8); // Roof Sticker (0x88), Roof Sticker Type (0x8C) + memcpy((void*)(carSaveLocation + 0x90), carDataDxp + 0x90, 8); // Neon (0x90), Trunk (0x94) + memcpy((void*)(carSaveLocation + 0x98), carDataDxp + 0x98, 8); // Plate Frame (0x98) + memcpy((void*)(carSaveLocation + 0xA0), carDataDxp + 0xA0, 8); // Plate Number (0xA0), vinyl_body_challenge_prefecture_1~15 (0xA4) + memcpy((void*)(carSaveLocation + 0xA8), carDataDxp + 0xA8, 8); // vinyl_body_challenge_prefecture (0xA8), Power (0xAC) + memcpy((void*)(carSaveLocation + 0xB8), carDataDxp + 0xB8, 8); // Handling (0xB8), Rank (0xBC) + // memcpy((void*)(carSaveLocation + 0xC0), carDataDxp + 0xC0, 8); // ?? + // memcpy((void*)(carSaveLocation + 0xC8), carDataDxp + 0xC8, 8); // ?? + // memcpy((void*)(carSaveLocation + 0xD0), carDataDxp + 0xD0, 8); // Crash + // memcpy((void*)(carSaveLocation + 0xD8), carDataDxp + 0xD8, 8); // ?? + // memcpy((void*)(carSaveLocation + 0xE0), carDataDxp + 0xE0, 8); // ?? + // memcpy((void*)(carSaveLocation + 0xE8), carDataDxp + 0xE8, 8); // ?? + // memcpy((void*)(carSaveLocation + 0xF0), carDataDxp + 0xF0, 8); // ?? + // memcpy((void*)(carSaveLocation + 0xF8), carDataDxp + 0xF8, 8); // ?? } // Disable loading @@ -562,7 +665,7 @@ static int loadCarFile(char* filename) // Failed return 0; -} +} // loadCarData(filepath: char*): Void // Given a filepath, attempts to load a @@ -621,7 +724,10 @@ static int loadCarData(char * filepath) if (ToBool(config["Tune"]["Force Full Tune"])) { // Create the force full tune thread - CreateThread(0, 0, forceFullTune, 0, 0, 0); + // CreateThread(0, 0, forceFullTune, 0, 0, 0); + + // Set the car to be fully tuned + setFullTune(); } // Success @@ -637,7 +743,7 @@ static int saveCarData(char* filepath) // Address where player save data starts uintptr_t saveDataBase = *(uintptr_t*)(imageBasedxplus + 0x1F7D578); - //new multilevel + // Address where car save data starts uintptr_t carSaveBase = *(uintptr_t*)(saveDataBase + 0x268); // Miles path string @@ -677,11 +783,51 @@ static int saveCarData(char* filepath) // Write the data from the array to the file fwrite(carDataDxp, 1, 0xFF, carFile); - fclose(carFile); // Success return 1; + + /* + + // Legacy MT5 car saving code reference + + memset(saveData, 0, 0x2000); + uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); + value = *(uintptr_t*)(value + 0x108); + memcpy(saveData, (void *)value, 0x340); + FILE* file = fopen("openprogress.sav", "wb"); + fwrite(saveData, 1, 0x2000, file); + fclose(file); + + // Car Profile saving + memset(carData, 0, 0xFF); + memset(carFileNamedxp, 0, 0xFF); + memcpy(carData, (void *)*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18), 0xE0); + CreateDirectoryA("OpenParrot_Cars", nullptr); + + if(customCardxp) + { + sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\custom.car"); + } + else + { + sprintf(carFileNamedxp, ".\\OpenParrot_Cars\\%08X.car", *(DWORD*)(*(uintptr_t*)(*(uintptr_t*)(imageBase + 0x1948F10) + 0x180 + 0xa8 + 0x18) + 0x2C)); + } + + FILE *carSave = fopen(carFileNamedxp, "wb"); + fwrite(carData, 1, 0xE0, file); + fclose(carSave); + + //SaveStoryData(); + //SaveCampaingHonorData(); + //SaveStoryModeNoLoseHonorData(); + //SaveOtherHonorData(); + //SaveCampaingHonorData2(); + + saveOk = false; + return 1; + */ } // loadStoryData(filepath: char *): Void @@ -719,7 +865,7 @@ static int loadStoryData(char* filepath) // Get the size of the file int fsize = ftell(file); - // If the file has 2000 nibbles (correct size) + // Check file is correct size if (fsize == 0x2000) { // Reset seek index to start @@ -729,26 +875,223 @@ static int loadStoryData(char* filepath) fread(saveDatadxp, fsize, 1, file); // Story save data offset - uintptr_t storyOffset = *(uintptr_t*)(saveDataBase + 0x108); + uintptr_t saveStoryBase = *(uintptr_t*)(saveDataBase + 0x108); // Not sure why, but story doesn't load unless I add this - memcpy((void*)(storyOffset + 0x48), saveDatadxp + 0x48, 0x1); + memcpy((void*)(saveStoryBase + 0x48), saveDatadxp + 0x48, 0x1); // Pretty sure this is the whole save file region, but need to test more :) - memcpy((void*)(storyOffset + 0xE0), saveDatadxp + 0xE0, 0x80); + memcpy((void*)(saveStoryBase + 0xE0), saveDatadxp + 0xE0, 0x80); // Save data loaded successfully loadOkDxp = true; - } - // Close the save file + //+ 0x80 + + //+ [0x340] + + // [[[[0000000005CE5850] + 108] + 340] + 50] + 50 + // [[[[0000000005CE5850] + 108] + 340] + 50] + 54 + // wmn5r.exe + 1948BF8 + //TA stuff + + //[[[[magic_rva]+108]+340]+50] + + //value += 0x24E0; + // First chunk + //memcpy((void *)(value + 0x16), saveData + 0x16, 0x28); + //// + //memcpy((void *)(value + 0x40), saveData + 0x40, 0x18); + //// + //memcpy((void *)(value + 0x60), saveData + 0x60, 0x20); + //// + //memcpy((void *)(value + 0x90), saveData + 0x90, 0x28); + //// + //memcpy((void *)(value + 0xC0), saveData + 0xC0, 0x10); + //// + //memcpy((void *)(value + 0xD8), saveData + 0xD8, 0x28); // OK + //// + //memcpy((void *)(value + 0x110), saveData + 0x110, 0x98); + //// + //memcpy((void *)(value + 0x1B8), saveData + 0x1B8, 0x48); + //// + //memcpy((void *)(value + 0x208), saveData + 0x208, 0x28); + //// + //memcpy((void *)(value + 0x240), saveData + 0x240, 0x68); + //// + //memcpy((void *)(value + 0x2B8), saveData + 0x2B8, 0x88); + // + //memcpy((void *)(value + 0x370), saveData + 0x370, 0x10); + //// + //memcpy((void *)(value + 0x388), saveData + 0x388, 0x90); + //// + //memcpy((void *)(value + 0x420), saveData + 0x420, 0x18); + //// + //memcpy((void *)(value + 0x440), saveData + 0x440, 0x18); + //// + //memcpy((void *)(value + 0x460), saveData + 0x460, 0x48); + //// + //memcpy((void *)(value + 0x4B8), saveData + 0x4B8, 0xB8); + //// + //memcpy((void *)(value + 0x578), saveData + 0x578, 0x08); + //// + //memcpy((void *)(value + 0x5A8), saveData + 0x5A8, 0x68); + //// + //memcpy((void *)(value + 0x628), saveData + 0x628, 0x48); + //// + //memcpy((void *)(value + 0x688), saveData + 0x688, 0x48); + //// + //memcpy((void *)(value + 0x6E8), saveData + 0x6E8, 0xA8); + //// + //memcpy((void *)(value + 0x7A0), saveData + 0x7A0, 0x10); + //// + //memcpy((void *)(value + 0x7B8), saveData + 0x7B8, 0x28); + //// + //memcpy((void *)(value + 0x7E8), saveData + 0x7E8, 0x10); + //// + ////memcpy((void *)(value + 0x800), saveData + 0x800, 0x48); // Problem + ////// + //memcpy((void *)(value + 0x850), saveData + 0x850, 0x08); + // + //memcpy((void *)(value + 0x860), saveData + 0x860, 0x08); + ////// + //memcpy((void *)(value + 0x870), saveData + 0x870, 0x18); + //// + //memcpy((void *)(value + 0x890), saveData + 0x890, 0x40); + //// + //memcpy((void *)(value + 0x8E0), saveData + 0x8E0, 0x10); + //// + //memcpy((void *)(value + 0x8F8), saveData + 0x8F8, 0x28); + //// + //memcpy((void *)(value + 0x928), saveData + 0x928, 0x10); + //// + //memcpy((void *)(value + 0x940), saveData + 0x940, 0x48); // Problem + } fclose(file); } + //LoadStoryData(); + //LoadCampaingHonorData(); + //LoadStoryModeNoLoseHonorData(); + //LoadOtherHonorData(); + //LoadCampaingHonorData2(); + // Success status return 1; } +//static int LoadCampaingHonorData2() +//{ +// memset(saveData, 0x0, 0x1000); +// FILE* file = fopen(V("CampaignHonorData.sav"), V("rb")); +// if (file) +// { +// fseek(file, 0, SEEK_END); +// int fsize = ftell(file); +// if (fsize == 0x100) +// { +// fseek(file, 0, SEEK_SET); +// fread(saveData, fsize, 1, file); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2698; +// memcpy((void *)value, saveData, 0x48); +// } +// fclose(file); +// } +// return 1; +//} +// +//static int LoadOtherHonorData() +//{ +// memset(saveData, 0x0, 0x1000); +// FILE* file = fopen(V("OtherHonorData.sav"), V("rb")); +// if (file) +// { +// fseek(file, 0, SEEK_END); +// int fsize = ftell(file); +// if (fsize == 0x100) +// { +// fseek(file, 0, SEEK_SET); +// fread(saveData, fsize, 1, file); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2A90; +// memcpy((void *)value, saveData, 0x60); +// } +// fclose(file); +// } +// return 1; +//} +// +//static int LoadStoryModeNoLoseHonorData() +//{ +// memset(saveData, 0x0, 0x1000); +// FILE* file = fopen(V("StoryModeNoLoseHonorData.sav"), V("rb")); +// if (file) +// { +// fseek(file, 0, SEEK_END); +// int fsize = ftell(file); +// if (fsize == 0x100) +// { +// fseek(file, 0, SEEK_SET); +// fread(saveData, fsize, 1, file); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x2C80; +// //memcpy((void *)value, saveData, 0x10); +// value += 0x18; +// memcpy((void *)value, saveData, 0x28); +// } +// fclose(file); +// } +// return 1; +//} +// +//static int LoadCampaingHonorData() +//{ +// memset(saveData, 0x0, 0x1000); +// FILE* file = fopen(V("campaing.sav"), V("rb")); +// if (file) +// { +// fseek(file, 0, SEEK_END); +// int fsize = ftell(file); +// if (fsize == 0x100) +// { +// fseek(file, 0, SEEK_SET); +// fread(saveData, fsize, 1, file); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x24E0; +// memcpy((void *)value, saveData, 0xB8); +// } +// fclose(file); +// } +// return 1; +//} +// +//static int LoadStoryData() +//{ +// memset(saveData, 0x0, 0x1000); +// FILE* file = fopen(V("story.sav"), V("rb")); +// if (file) +// { +// fseek(file, 0, SEEK_END); +// int fsize = ftell(file); +// if (fsize == 0x100) +// { +// fseek(file, 0, SEEK_SET); +// fread(saveData, fsize, 1, file); +// uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); +// uintptr_t value = *(uintptr_t*)(imageBase + 0x1948F10); +// value += 0x25F0; +// memcpy((void *)value, saveData, 0x98); +// } +// fclose(file); +// } +// return 1; +//} + static int saveStoryData(char* filepath) { // Miles path string @@ -774,7 +1117,7 @@ static int saveStoryData(char* filepath) // Address where the player story data starts uintptr_t storySaveBase = *(uintptr_t*)(saveDataBase + 0x108); - // Copy 340 nibbles to saveDatadxp from the story save data index + // Copy to saveDatadxp from the story save data index memcpy(saveDatadxp, (void*)storySaveBase, 0x340); // Dump the save data to openprogress.sav @@ -909,29 +1252,18 @@ static int loadGameData() } } - writeLog(logfileDxp, "creating directories ...\n"); - writeLog(logfileDxp, "path:" + std::string(loadPath) + "\n"); - // Ensure the directory exists std::filesystem::create_directories(loadPath); - writeLog(logfileDxp, "loading story ...\n"); - // Load the openprogress.sav file loadStoryData(loadPath); - writeLog(logfileDxp, "loading car ...\n"); - // Load the car save file loadCarData(loadPath); - writeLog(logfileDxp, "loading miles ...\n"); - // Load the miles save file loadMileData(loadPath); - writeLog(logfileDxp, "success.\n"); - // Success return 1; } @@ -990,29 +1322,18 @@ static int SaveGameData() } } - writeLog(logfileDxp, "creating directories ...\n"); - writeLog(logfileDxp, "path:" + std::string(savePath) + "\n"); - // Ensure the directory exists std::filesystem::create_directories(savePath); - writeLog(logfileDxp, "saving story ...\n"); - // Load the openprogress.sav file saveStoryData(savePath); - writeLog(logfileDxp, "saving car ...\n"); - // Load the car save file saveCarData(savePath); - writeLog(logfileDxp, "saving miles ...\n"); - // Load the miles save file saveMileData(savePath); - writeLog(logfileDxp, "success.\n"); - // Disable saving saveOk = false; @@ -1227,12 +1548,56 @@ static DWORD WINAPI SpamMulticast(LPVOID) } } +/* +extern int* ffbOffset; +extern int* ffbOffset2; +extern int* ffbOffset3; +extern int* ffbOffset4; +DWORD WINAPI Wmmt5FfbCollector(void* ctx) +{ + uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0); + while (true) + { + *ffbOffset = *(DWORD *)(imageBase + 0x196F188); + *ffbOffset2 = *(DWORD *)(imageBase + 0x196F18c); + *ffbOffset3 = *(DWORD *)(imageBase + 0x196F190); + *ffbOffset4 = *(DWORD *)(imageBase + 0x196F194); + Sleep(10); + } +}*/ + + // Wmmt5Func([]()): InitFunction // Performs the initial startup tasks for // maximum tune 5, including the starting // of required subprocesses. static InitFunction Wmmt5Func([]() { + /* + FILE* fileF = _wfopen(L"Fsetting.lua.gz", L"r"); + if (fileF == NULL) + { + FILE* settingsF = _wfopen(L"Fsetting.lua.gz", L"wb"); + fwrite(settingData, 1, sizeof(settingData), settingsF); + fclose(settingsF); + } + else + { + fclose(fileF); + } + FILE* fileG = _wfopen(L"Gsetting.lua.gz", L"r"); + if (fileG == NULL) + { + FILE* settingsG = _wfopen(L"Gsetting.lua.gz", L"wb"); + fwrite(settingData, 1, sizeof(settingData), settingsG); + fclose(settingsG); + } + else + { + fclose(fileG); + } + */ + // Records if terminal mode is enabled bool isTerminal = false; @@ -1328,7 +1693,20 @@ static InitFunction Wmmt5Func([]() // Terminal mode is off if (!isTerminal) { - // I don't know what this is for sorry + // Disregard terminal scanner stuff. + // 48 8B 18 48 3B D8 0F 84 88 00 00 00 39 7B 1C 74 60 80 7B 31 00 75 4F 48 8B 43 10 80 78 31 00 + // FOUND ON 21, 10, 1 + //injector::MakeNOP(imageBase + 0x91E1AE, 6); + //injector::MakeNOP(imageBase + 0x91E1B7, 2); + //injector::MakeNOP(imageBase + 0x91E1BD, 2); + + /* + auto location = hook::get_pattern("48 8B 18 48 3B D8 0F 84 8B 00 00 00 0F 1F 80 00 00 00 00 39 73 1C 74 5C 80 7B 31 00"); + // injector::MakeNOP(location + 6, 6); // 6 + injector::MakeNOP(location + 0xF, 2); // 0xF + // injector::MakeNOP(location + 0x15, 2); // 0x15 + */ + injector::MakeNOP(imageBasedxplus + 0x9F2BB3, 2); // If terminal emulator is enabled @@ -1338,6 +1716,25 @@ static InitFunction Wmmt5Func([]() CreateThread(0, 0, SpamMulticast, 0, 0, 0); } } + /* + else + { + // Patch some func to 1 + // + // FOUND ON 21, 10, 1 + // NOT FOUND: + //safeJMP(imageBase + 0x7BE440, ReturnTrue); + //safeJMP(hook::get_pattern("0F B6 41 05 2C 30 3C 09 77 04 0F BE C0 C3 83 C8 FF C3"), ReturnTrue); + //safeJMP(imageBase + 0x89D420, ReturnTrue); + + // Patch some func to 1 + // 40 53 48 83 EC 20 48 83 39 00 48 8B D9 75 28 48 8D ?? ?? ?? ?? 00 48 8D ?? ?? ?? ?? 00 41 B8 ?? ?? 00 00 FF 15 ?? ?? ?? ?? 4C 8B 1B 41 0F B6 43 78 + // FOUND ON 21, 10, 1 + //safeJMP(imageBase + 0x7CF8D0, ReturnTrue); + //safeJMP(hook::get_pattern("40 53 48 83 EC 20 48 83 39 00 48 8B D9 75 11 48 8B 0D C2"), ReturnTrue); + //safeJMP(imageBase + 0x8B5190, ReturnTrue); + } + */ auto chars = { 'F', 'G' }; @@ -1380,17 +1777,56 @@ static InitFunction Wmmt5Func([]() // Save story stuff (only 05) { + // Skip erasing of temp card data + // injector::WriteMemory(imageBase + 0xA35CA3, 0xEB, true); + + /* + // Skip erasing of temp card + safeJMP(imageBase + 0x54DCE1, LoadGameData); + safeJMP(imageBase + 0x5612F0, ReturnTrue); + safeJMP(imageBase + 0x5753C0, ReturnTrue); + safeJMP(imageBase + 0x57DF10, ReturnTrue); + safeJMP(imageBase + 0x92DB20, ReturnTrue); + safeJMP(imageBase + 0x5628C0, ReturnTrue); + safeJMP(imageBase + 0x579090, ReturnTrue); + + // Skip more + safeJMP(imageBase + 0x54B0F0, ReturnTrue); + safeJMP(imageBase + 0x909DB0, ReturnTrue); + safeJMP(imageBase + 0x59FD90, ReturnTrue); + safeJMP(imageBase + 0x5A0030, ReturnTrue); + safeJMP(imageBase + 0x915370, ReturnTrue); + safeJMP(imageBase + 0x5507A0, ReturnTrue); + safeJMP(imageBase + 0x561290, ReturnTrue); + safeJMP(imageBase + 0x5A0AE8, LoadWmmt5CarData); + + // crash fix + //safeJMP(imageBase + 0xAD6F28, WmmtOperatorDelete); + //safeJMP(imageBase + 0xAD6F4C, WmmtMemset); + + // Save progress trigger + injector::WriteMemory(imageBase + 0x556CE3, 0xB848, true); + injector::WriteMemory(imageBase + 0x556CE3 + 2, (uintptr_t)SaveOk, true); + injector::WriteMemory(imageBase + 0x556CED, 0x9090D0FF, true); + + // Try save later! + injector::MakeNOP(imageBase + 0x308546, 0x12); + injector::WriteMemory(imageBase + 0x308546, 0xB848, true); + injector::WriteMemory(imageBase + 0x308546 + 2, (uintptr_t)SaveGameData, true); + injector::WriteMemory(imageBase + 0x308550, 0x3348D0FF, true); + injector::WriteMemory(imageBase + 0x308550 + 4, 0x90C0, true); + CreateThread(0, 0, Wmmt5FfbCollector, 0, 0, 0); + */ + // Enable all print injector::MakeNOP(imageBasedxplus + 0x898BD3, 6); - // Load car trigger - // safeJMP(imageBasedxplus + 0x72AB90, loadCar); - // Load car and story data at once safeJMP(imageBasedxplus + 0x72AB90, loadGame); - - // Attempting to piggyback story load off load car - // safeJMP(imageBasedxplus + 0x72AB90, loadStory); + + // Save car trigger + // injector::WriteMemory(imageBase + 0x376F80 + 2, (uintptr_t)SaveGameData, true); + // safeJMP(imageBase + 0x376F76, SaveGameData); // Save car trigger injector::MakeNOP(imageBasedxplus + 0x376F76, 0x12); @@ -1400,6 +1836,8 @@ static InitFunction Wmmt5Func([]() injector::WriteMemory(imageBasedxplus + 0x376F80 + 4, 0x90C0, true); // Prevents startup saving + // injector::MakeNOP(imageBase + 0x6B908C, 0x0D); + // safeJMP(imageBase + 0x6B908C, SaveOk); injector::WriteMemory(imageBasedxplus + 0x6B909A, 0xB848, true); injector::WriteMemory(imageBasedxplus + 0x6B909A + 2, (uintptr_t)SaveOk, true); injector::WriteMemory(imageBasedxplus + 0x6B90A4, 0x9090D0FF, true); From 6686a3db96be412807a4ee8f15b19147471c2682 Mon Sep 17 00:00:00 2001 From: Damon Murdoch Date: Thu, 5 May 2022 11:30:22 +1000 Subject: [PATCH 4/8] Fixed bug which broke multiplayer in 5dx+, moved story loading to after car loading. Thanks Leadbman! --- OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp | 4 ++- .../src/Functions/Games/ES3X/WMMT5DXPlus.cpp | 30 ++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp index 68565d5..2daf809 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp @@ -7,7 +7,9 @@ #include #include "MinHook.h" #include +#include #include + #ifdef _M_AMD64 #pragma optimize("", off) @@ -546,7 +548,7 @@ static DWORD WINAPI forceFullTune(void* pArguments) // Loops while the program is running while (true) { - // Only runs every 16th frame + // Sleep for 16ms Sleep(16); // Run the set full tune process diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp index ca24a5e..f9b87eb 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp @@ -878,10 +878,26 @@ static int loadStoryData(char* filepath) uintptr_t saveStoryBase = *(uintptr_t*)(saveDataBase + 0x108); // Not sure why, but story doesn't load unless I add this - memcpy((void*)(saveStoryBase + 0x48), saveDatadxp + 0x48, 0x1); + memcpy((void*)(saveStoryBase + 0x48), saveDatadxp + 0x48, 0x8); + // Pretty sure this is the whole save file region, but need to test more :) - memcpy((void*)(saveStoryBase + 0xE0), saveDatadxp + 0xE0, 0x80); + memcpy((void*)(saveStoryBase + 0xE0), saveDatadxp + 0xE0, 0x8); + memcpy((void*)(saveStoryBase + 0xE8), saveDatadxp + 0xE8, 0x8); + memcpy((void*)(saveStoryBase + 0xF0), saveDatadxp + 0xF0, 0x8); + memcpy((void*)(saveStoryBase + 0xF8), saveDatadxp + 0xF8, 0x8); + memcpy((void*)(saveStoryBase + 0x100), saveDatadxp + 0x100, 0x8); + memcpy((void*)(saveStoryBase + 0x108), saveDatadxp + 0x108, 0x8); + memcpy((void*)(saveStoryBase + 0x110), saveDatadxp + 0x110, 0x8); + memcpy((void*)(saveStoryBase + 0x118), saveDatadxp + 0x118, 0x8); + memcpy((void*)(saveStoryBase + 0x120), saveDatadxp + 0x120, 0x8); + memcpy((void*)(saveStoryBase + 0x128), saveDatadxp + 0x128, 0x8); + memcpy((void*)(saveStoryBase + 0x130), saveDatadxp + 0x130, 0x8); + memcpy((void*)(saveStoryBase + 0x138), saveDatadxp + 0x138, 0x8); + memcpy((void*)(saveStoryBase + 0x140), saveDatadxp + 0x140, 0x8); + memcpy((void*)(saveStoryBase + 0x148), saveDatadxp + 0x148, 0x8); + memcpy((void*)(saveStoryBase + 0x150), saveDatadxp + 0x150, 0x8); + memcpy((void*)(saveStoryBase + 0x158), saveDatadxp + 0x158, 0x8); // Save data loaded successfully loadOkDxp = true; @@ -1216,7 +1232,7 @@ static int loadGameData() memset(loadPath, 0, 0xFF); // Wirte the '.' into the load path - sprintf(loadPath, "."); + sprintf(loadPath, ".\\SaveData"); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) @@ -1255,12 +1271,12 @@ static int loadGameData() // Ensure the directory exists std::filesystem::create_directories(loadPath); - // Load the openprogress.sav file - loadStoryData(loadPath); - // Load the car save file loadCarData(loadPath); + // Load the openprogress.sav file + loadStoryData(loadPath); + // Load the miles save file loadMileData(loadPath); @@ -1286,7 +1302,7 @@ static int SaveGameData() memset(savePath, 0, 0xFF); // Wirte the '.' into the load path - sprintf(savePath, "."); + sprintf(savePath, ".\\SaveData"); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) From 0115af8eef54bd8e5509258134374887fa9d0cc2 Mon Sep 17 00:00:00 2001 From: Scrubbs Date: Sun, 8 May 2022 21:24:40 +1000 Subject: [PATCH 5/8] Added SaveData folder for MT5 saves, removed stock colour loading from MT5 (Uses selected colour at menu) --- OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp | 68 ++++++------------- .../src/Functions/Games/ES3X/WMMT5DXPlus.cpp | 49 +++++++------ 2 files changed, 49 insertions(+), 68 deletions(-) diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp index 2daf809..0a6d9de 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp @@ -674,7 +674,8 @@ static int loadCarFile(char* filename) memcpy((void*)(carSaveLocation + 0x10), carData + 0x10, 8); // ?? memcpy((void*)(carSaveLocation + 0x20), carData + 0x20, 8); // ?? memcpy((void*)(carSaveLocation + 0x28), carData + 0x28, 8); // ?? - memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 8); // Stock Colour (0x30), Custom Colour (0x34) + // memcpy((void*)(carSaveLocation + 0x30), carData + 0x30, 8); // Stock Colour (0x30), Custom Colour (0x34) + memcpy((void*)(carSaveLocation + 0x34), carData + 0x34, 4); // Custom Colour (0x34) memcpy((void*)(carSaveLocation + 0x38), carData + 0x38, 8); // Rims Type (0x38), Rims Colour (0x3C) memcpy((void*)(carSaveLocation + 0x40), carData + 0x40, 8); // Aero Type (0x40), Hood Type (0x44) memcpy((void*)(carSaveLocation + 0x50), carData + 0x50, 8); // Wing Type (0x50), Mirror Type (0x54) @@ -907,50 +908,25 @@ static int loadStoryData(char* filepath) // Reset seek index to start fseek(file, 0, SEEK_SET); - // Read all of the contents of the file into saveDatadxp + // Read all of the contents of the file into saveData fread(saveData, fsize, 1, file); // Story save data offset uintptr_t saveStoryBase = *(uintptr_t*)(saveDataBase + 0x108); - // Not sure why, but story doesn't load unless I add this - memcpy((void*)(saveStoryBase + 0x48), saveData + 0x48, 0x1); + // 0x00 - 70 23 - Should be able to use this to figure out what game a save is from - // Pretty sure this is the whole save file region, but need to test more :) - memcpy((void*)(saveStoryBase + 0xE0), saveData + 0xE0, 0x80); - - /* - // First page - //memcpy((void *)(value), saveData, 0x48); - memcpy((void*)(value + 0x10), saveData + 0x10, 0x20); - memcpy((void*)(value + 0x40), saveData + 0x40, 0x08); - //memcpy((void *)(value + 0x48 + 8), saveData + 0x48 + 8, 0x20); - memcpy((void*)(value + 0x48 + 8), saveData + 0x48 + 8, 0x08); - memcpy((void*)(value + 0x48 + 24), saveData + 0x48 + 24, 0x08); - memcpy((void*)(value + 0x48 + 32), saveData + 0x48 + 32, 0x08); - - // Second page - value += 0x110; - memcpy((void*)(value), saveData + 0x110, 0x90); - value -= 0x110; - - // Third Page - value += 0x1B8; - memcpy((void*)(value), saveData + 0x1B8, 0x48); - memcpy((void*)(value + 0x48 + 8), saveData + 0x1B8 + 0x48 + 8, 0x28); - value -= 0x1B8; - - // Fourth page - value += 0x240; - memcpy((void*)(value), saveData + 0x240, 0x68); - value -= 0x240; - - // Fifth page - value += 0x2B8; - memcpy((void*)(value), saveData + 0x2B8, 0x88); - value -= 0x2B8; - */ + // (Mostly) discovered story data + memcpy((void*)(saveStoryBase + 0x118), saveData + 0x118, 0x8); // Total Wins (0x118) + memcpy((void*)(saveStoryBase + 0x120), saveData + 0x120, 0x8); // Chapter Progress (0x120) (Bitmask), Current Chapter (0x124) + memcpy((void*)(saveStoryBase + 0x128), saveData + 0x128, 0x8); // ?? + memcpy((void*)(saveStoryBase + 0x130), saveData + 0x130, 0x8); // ?? + memcpy((void*)(saveStoryBase + 0x138), saveData + 0x138, 0x8); // Win Streak (0x138) + memcpy((void*)(saveStoryBase + 0x140), saveData + 0x140, 0x8); // ?? + memcpy((void*)(saveStoryBase + 0x148), saveData + 0x148, 0x8); // ?? + memcpy((void*)(saveStoryBase + 0x150), saveData + 0x150, 0x8); // Locked Chapters (0x150) (Bitmask) + memcpy((void*)(saveStoryBase + 0x158), saveData + 0x158, 0x8); // ?? // Save data loaded successfully loadOk = true; @@ -981,7 +957,7 @@ static int SaveGameData() memset(savePath, 0, 0xFF); // Wirte the '.' into the load path - sprintf(savePath, "."); + sprintf(savePath, ".\\SaveData"); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) @@ -1020,12 +996,12 @@ static int SaveGameData() // Ensure the directory exists std::filesystem::create_directories(savePath); - // Save the openprogress.sav file - saveStoryData(savePath); - // Save the car save file saveCarData(savePath); + // Save the openprogress.sav file + saveStoryData(savePath); + // Disable saving saveOk = false; @@ -1045,7 +1021,7 @@ static int loadGameData() memset(loadPath, 0, 0xFF); // Wirte the '.' into the load path - sprintf(loadPath, "."); + sprintf(loadPath, ".\\SaveData"); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) @@ -1084,12 +1060,12 @@ static int loadGameData() // Ensure the directory exists std::filesystem::create_directories(loadPath); - // Load the openprogress.sav file - loadStoryData(loadPath); - // Load the car save file loadCarData(loadPath); + // Load the openprogress.sav file + loadStoryData(loadPath); + // Success return 1; } diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp index f9b87eb..be85519 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp @@ -877,27 +877,30 @@ static int loadStoryData(char* filepath) // Story save data offset uintptr_t saveStoryBase = *(uintptr_t*)(saveDataBase + 0x108); - // Not sure why, but story doesn't load unless I add this - memcpy((void*)(saveStoryBase + 0x48), saveDatadxp + 0x48, 0x8); + // 0x00 - 08 4C - Should be able to use this to figure out what game a save is from + // (Mostly) discovered story data - // Pretty sure this is the whole save file region, but need to test more :) - memcpy((void*)(saveStoryBase + 0xE0), saveDatadxp + 0xE0, 0x8); - memcpy((void*)(saveStoryBase + 0xE8), saveDatadxp + 0xE8, 0x8); - memcpy((void*)(saveStoryBase + 0xF0), saveDatadxp + 0xF0, 0x8); - memcpy((void*)(saveStoryBase + 0xF8), saveDatadxp + 0xF8, 0x8); - memcpy((void*)(saveStoryBase + 0x100), saveDatadxp + 0x100, 0x8); - memcpy((void*)(saveStoryBase + 0x108), saveDatadxp + 0x108, 0x8); - memcpy((void*)(saveStoryBase + 0x110), saveDatadxp + 0x110, 0x8); - memcpy((void*)(saveStoryBase + 0x118), saveDatadxp + 0x118, 0x8); - memcpy((void*)(saveStoryBase + 0x120), saveDatadxp + 0x120, 0x8); - memcpy((void*)(saveStoryBase + 0x128), saveDatadxp + 0x128, 0x8); - memcpy((void*)(saveStoryBase + 0x130), saveDatadxp + 0x130, 0x8); - memcpy((void*)(saveStoryBase + 0x138), saveDatadxp + 0x138, 0x8); - memcpy((void*)(saveStoryBase + 0x140), saveDatadxp + 0x140, 0x8); - memcpy((void*)(saveStoryBase + 0x148), saveDatadxp + 0x148, 0x8); - memcpy((void*)(saveStoryBase + 0x150), saveDatadxp + 0x150, 0x8); - memcpy((void*)(saveStoryBase + 0x158), saveDatadxp + 0x158, 0x8); + memcpy((void*)(saveStoryBase + 0x48), saveDatadxp + 0x48, 0x8); // Story Bit + memcpy((void*)(saveStoryBase + 0xE0), saveDatadxp + 0xE0, 0x8); // ?? + memcpy((void*)(saveStoryBase + 0xE8), saveDatadxp + 0xE8, 0x8); // Chapter Progress (0xE8) (Bitmask) + memcpy((void*)(saveStoryBase + 0xF0), saveDatadxp + 0xF0, 0x8); // Current Chapter (0xF0), Total Wins (0xF4) + memcpy((void*)(saveStoryBase + 0xF8), saveDatadxp + 0xF8, 0x8); // ?? + memcpy((void*)(saveStoryBase + 0x100), saveDatadxp + 0x100, 0x8); // Win Streak (0x104) + memcpy((void*)(saveStoryBase + 0x108), saveDatadxp + 0x108, 0x8); // ?? + memcpy((void*)(saveStoryBase + 0x110), saveDatadxp + 0x110, 0x8); // Locked Chapters (0x110) (Bitmask) + + // Can't tell if the data past this point does anything + + // memcpy((void*)(saveStoryBase + 0x118), saveDatadxp + 0x118, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x120), saveDatadxp + 0x120, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x128), saveDatadxp + 0x128, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x130), saveDatadxp + 0x130, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x138), saveDatadxp + 0x138, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x140), saveDatadxp + 0x140, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x148), saveDatadxp + 0x148, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x150), saveDatadxp + 0x150, 0x8); // ?? + // memcpy((void*)(saveStoryBase + 0x158), saveDatadxp + 0x158, 0x8); // ?? // Save data loaded successfully loadOkDxp = true; @@ -913,6 +916,8 @@ static int loadStoryData(char* filepath) //[[[[magic_rva]+108]+340]+50] + // memcpy((void*)(saveStoryBase + 0x24E0 + 0x16), saveDatadxp + 0x16, 0x1000); + //value += 0x24E0; // First chunk //memcpy((void *)(value + 0x16), saveData + 0x16, 0x28); @@ -1341,12 +1346,12 @@ static int SaveGameData() // Ensure the directory exists std::filesystem::create_directories(savePath); - // Load the openprogress.sav file - saveStoryData(savePath); - // Load the car save file saveCarData(savePath); + // Load the openprogress.sav file + saveStoryData(savePath); + // Load the miles save file saveMileData(savePath); From a26ad13b55c5e8d0a79e1310f3e4023b50426559 Mon Sep 17 00:00:00 2001 From: Damon Murdoch Date: Tue, 10 May 2022 14:25:35 +1000 Subject: [PATCH 6/8] Removed SaveData folder, MT5/5DX+ saves will be stored in root --- OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp | 10 ++++++---- OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp index 0a6d9de..9ccbc16 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5.cpp @@ -956,8 +956,9 @@ static int SaveGameData() // Set the milepath memory to zero memset(savePath, 0, 0xFF); - // Wirte the '.' into the load path - sprintf(savePath, ".\\SaveData"); + // Write the '.' into the load path + // sprintf(savePath, ".\\SaveData"); + sprintf(savePath, "."); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) @@ -1020,8 +1021,9 @@ static int loadGameData() // Set the milepath memory to zero memset(loadPath, 0, 0xFF); - // Wirte the '.' into the load path - sprintf(loadPath, ".\\SaveData"); + // Write the '.' into the load path + // sprintf(loadPath, ".\\SaveData"); + sprintf(loadPath, "."); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp index be85519..0190dfc 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp @@ -1237,7 +1237,8 @@ static int loadGameData() memset(loadPath, 0, 0xFF); // Wirte the '.' into the load path - sprintf(loadPath, ".\\SaveData"); + // sprintf(loadPath, ".\\SaveData"); + sprintf(loadPath, "."); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) @@ -1307,7 +1308,8 @@ static int SaveGameData() memset(savePath, 0, 0xFF); // Wirte the '.' into the load path - sprintf(savePath, ".\\SaveData"); + // sprintf(savePath, ".\\SaveData"); + sprintf(savePath, "."); // Seperate save file / cars per user profile if (ToBool(config["Save"]["Save Per Custom Name"])) From b0c7eedb7b01e724841cc86e503447b736a226db Mon Sep 17 00:00:00 2001 From: Damon Murdoch Date: Tue, 10 May 2022 15:15:20 +1000 Subject: [PATCH 7/8] Update .gitignore Removed old script from gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1a2f8c9..983a00b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *.sln *.vcxproj *.vcxproj.filters -*.commit-and-copy.ps1 + .vs/ build/ Debug/ From 2085bbc55096f0dcceb9e0aba89a54a5ab6bfa4f Mon Sep 17 00:00:00 2001 From: Damon Murdoch Date: Fri, 13 May 2022 16:06:36 +1000 Subject: [PATCH 8/8] Working star loading / saving, credit to @doomertheboomer for figuring this out! --- .../src/Functions/Games/ES3X/WMMT5DXPlus.cpp | 119 +++++++++++++++++- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp index 0190dfc..519ba00 100644 --- a/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp +++ b/OpenParrot/src/Functions/Games/ES3X/WMMT5DXPlus.cpp @@ -376,6 +376,9 @@ unsigned char saveDatadxp[0x2000]; // Mile data dump memory block unsigned char mileDatadxp[0x08]; +// Star data dump memory block +unsigned char starDataDxp[0x40]; + //set system date patch by pockywitch typedef bool (WINAPI* SETSYSTEMTIME)(SYSTEMTIME* in); SETSYSTEMTIME pSetSystemTime = NULL; @@ -673,9 +676,6 @@ static int loadCarFile(char* filename) // car file) from that folder. static int loadCarData(char * filepath) { - // Sleep for 1 second - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - // Custom car disabled by default customCarDxp = false; @@ -1225,6 +1225,107 @@ static int saveMileData(char* filepath) return 1; } +// Credits to chery vtec tuning club for figuring out star loading / saving +static int saveStarData(char* filepath) +{ + // Star path saving + char starPath[0xFF]; + + // Set the storyPath memory to zero + memset(starPath, 0, 0xFF); + + // Copy the file path to the stars path + strcpy(starPath, filepath); + + // Append the mileage filename to the string + strcat(starPath, "\\stars.bin"); + + // Clear star data memory + memset(starDataDxp, 0, 0x40); + + // Save Star Data + + // Dereference the star pointer + uintptr_t starBase = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x110); + + // Dumps first 2 bytes from star pointer + memcpy(starDataDxp + 0x00, (void*)(starBase + 0x248), 0x2); + + // Dumps medal offsets from star pointer, 16 bytes + memcpy(starDataDxp + 0x04, (void*)(starBase + 0x254), 0x10); + + // Dump the contents of the star data array to the file + writeDump(starPath, starDataDxp, sizeof(starDataDxp)); + + // Success + return 1; +} + +static int loadStarData(char* filepath) +{ + // Star path loading + char starPath[0xFF]; + + // Set the storyPath memory to zero + memset(starPath, 0, 0xFF); + + // Copy the file path to the stars path + strcpy(starPath, filepath); + + // Append the mileage filename to the string + strcat(starPath, "\\stars.bin"); + + // Clear star data memory + memset(starDataDxp, 0, 0x40); + + // Open the star binary file + FILE* starFile = fopen(starPath, "rb"); + + // saveStarData(".\\preloadstars"); + writeLog(logfileDxp, "Loading stars ...\n"); + + // If the file opened successfully + if (starFile) + { + // saveStarData(".\\preloadstars"); + writeLog(logfileDxp, "success.\n"); + + // If the file size is correct + fseek(starFile, 0, SEEK_END); + int starSize = ftell(starFile); + if (starSize == 0x40) + { + // Reset the file pointer to the start + fseek(starFile, 0, SEEK_SET); + + // Read all of the contents into the array + fread(starDataDxp, starSize, 1, starFile); + + // Dereference the star pointer in the game memory + uintptr_t starBase = *(uintptr_t*)((*(uintptr_t*)(imageBasedxplus + 0x1F7D578)) + 0x110); + + // Dumps first 2 bytes from star pointer + memcpy((void*)(starBase + 0x248), starDataDxp + 0x00, 0x2); + + // Dumps medal offsets from star pointer, 16 bytes + memcpy((void*)(starBase + 0x254), starDataDxp + 0x04, 0x10); + + // Close the stars file + fclose(starFile); + } + } + + // saveStarData(".\\postloadstars"); + + // Delay another ten seconds + // std::this_thread::sleep_for(std::chrono::seconds(10)); + + // saveStarData(".\\delayloadstars"); + + // Success + return 1; +} + static int loadGameData() { // Disable saving @@ -1277,6 +1378,9 @@ static int loadGameData() // Ensure the directory exists std::filesystem::create_directories(loadPath); + // Sleep for 1 second + std::this_thread::sleep_for(std::chrono::seconds(1)); + // Load the car save file loadCarData(loadPath); @@ -1286,6 +1390,12 @@ static int loadGameData() // Load the miles save file loadMileData(loadPath); + // Sleep for 14 seconds + std::this_thread::sleep_for(std::chrono::seconds(14)); + + // Load the stars save file + loadStarData(loadPath); + // Success return 1; } @@ -1357,6 +1467,9 @@ static int SaveGameData() // Load the miles save file saveMileData(savePath); + // Load the miles save file + saveStarData(savePath); + // Disable saving saveOk = false;