Skip to content

Instantly share code, notes, and snippets.

@CherryDT
Created December 3, 2021 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CherryDT/19bf4d95b1cc7f5872c095870decf483 to your computer and use it in GitHub Desktop.
Save CherryDT/19bf4d95b1cc7f5872c095870decf483 to your computer and use it in GitHub Desktop.
Source code of XEvasionAgiDecouple DynRPG plugin
#define _WIN32_WINNT _WIN32_WINNT_WIN7
#include <DynRPG/DynRPG.h>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <wincon.h>
#include <stdlib.h>
#include <stdint.h>
#include <windows.h>
bool debugMode = false;
int actorAgiVarStart = 0;
int monsterAgiVarStart = 0;
std::string pluginName = "";
void fail (std::string error) {
if (debugMode) std::cout << "ERROR: " << error << std::endl;
MessageBox(NULL, error.c_str(), pluginName.c_str(), MB_OK | MB_ICONERROR);
ExitProcess(1);
}
void initConsole () {
AllocConsole();
AttachConsole(GetCurrentProcessId());
freopen("CON", "w", stdout);
std::cout << "XEvasionAgiDecouple Debug Console" << std::endl;
}
int __stdcall getAgiForEvasion (RPG::Battler* battler) {
if (debugMode) std::cout << "getAgiForEvasion called for " << (battler->isMonster() ? "monster" : "actor") << " " << battler->id << std::endl;
int varId = (battler->isMonster() ? monsterAgiVarStart : actorAgiVarStart) - 1 + battler->id;
int val = RPG::variables[varId];
if (debugMode) std::cout << std::dec << "Returning V[" << varId << "] which is " << val << std::endl;
return val;
}
// Replaces a mov eax, X instruction by nop and push X and replaces the target of the following call instruction.
void replaceCall (uint8_t* addr, void* target) {
uint16_t movInstr = *(uint16_t*)addr;
if ((movInstr & 0xF0FF) != 0xC08B) {
std::stringstream s;
s << std::hex << "Unexpected instruction 0x" << movInstr << " at 0x" << std::hex << (uint32_t)addr << std::endl;
fail(s.str());
}
uint16_t nopAndPushInstr = 0x5090 | (movInstr & 0x0F00);
*(uint16_t*)addr = nopAndPushInstr;
*(uint32_t*)(addr + 3) = (uint32_t)target - ((uint32_t)addr + 7);
}
bool onStartup(char *pluginName) {
::pluginName = pluginName;
std::map<std::string, std::string> configuration = RPG::loadConfiguration(pluginName);
debugMode = atoi(configuration["DebugMode"].c_str()) == 1;
if (debugMode) initConsole();
actorAgiVarStart = atoi(configuration["ActorAgiVarStart"].c_str());
monsterAgiVarStart = atoi(configuration["MonsterAgiVarStart"].c_str());
if (!actorAgiVarStart) fail("ActorAgiVarStart is not set in plugin configuration!");
if (!monsterAgiVarStart) fail("MonsterAgiVarStart is not set in plugin configuration!");
replaceCall((uint8_t*)0x49B0CB, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49B0F0, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49B104, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49B48F, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49B499, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49B4BE, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49B4D2, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49C6E5, (void*)getAgiForEvasion);
replaceCall((uint8_t*)0x49C6F9, (void*)getAgiForEvasion);
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment