mirror of
https://github.com/aimrebirth/tools.git
synced 2026-04-14 17:33:25 +00:00
Improve mod library and example mod.
This commit is contained in:
parent
091dd3cbe9
commit
3d76460d56
7 changed files with 2833 additions and 144 deletions
381
examples/mods/aim1_community_fix/aim.exe.fixes.h
Normal file
381
examples/mods/aim1_community_fix/aim.exe.fixes.h
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
/*struct char20 {
|
||||
char string[20];
|
||||
};*/
|
||||
|
||||
#define _BYTE uint8_t
|
||||
#define this
|
||||
#define __unaligned
|
||||
#include "aim.exe.h"
|
||||
#undef this
|
||||
#undef __unaligned
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
constexpr auto call_command_length = 5;
|
||||
|
||||
enum aim1_fix : uint32_t {
|
||||
script_function__ISGLIDER = 0x0043A1F6,
|
||||
trade_actions_weapon_checks = 0x004072FA,
|
||||
setup_proper_weapon_slots_for_a_glider = 0x004D62E4,
|
||||
put_weapon_into_the_right_slot_after_purchase = 0x00417A6D,
|
||||
sell_correct_weapon = 0x004176BC,
|
||||
empty_light_weapon_message = 0x004067C4,
|
||||
empty_heavy_weapon_message = 0x0040688B,
|
||||
};
|
||||
uint32_t known_caller;
|
||||
auto player_ptr = (Player **)0x005B7B38;
|
||||
auto get_player_ptr() {
|
||||
auto player_ptr2 = (Player *)0x00678FEC;
|
||||
return player_ptr2;
|
||||
}
|
||||
|
||||
enum class glider_id : uint32_t {
|
||||
nargoon = 0x7,
|
||||
eyedstone = 0xe,
|
||||
finder1 = 0x19,
|
||||
finder2 = 0x1A,
|
||||
};
|
||||
|
||||
#define NOP1 __asm { nop }
|
||||
#define NOP2 NOP1 NOP1
|
||||
#define NOP4 NOP2 NOP2
|
||||
#define NOP8 NOP4 NOP4
|
||||
#define NOP16 NOP8 NOP8
|
||||
#define NOP32 NOP16 NOP16
|
||||
#define NOP64 NOP32 NOP32
|
||||
#define NOP128 NOP64 NOP64
|
||||
#define NOP256 NOP128 NOP128
|
||||
#define NOP512 NOP256 NOP256
|
||||
#define NOP1024 NOP512 NOP512
|
||||
#define NOP4K NOP1024 NOP1024 NOP1024 NOP1024
|
||||
|
||||
bool __stdcall strequ(const char *s1, const char *s2) {
|
||||
do {
|
||||
if (*s1 != *s2) {
|
||||
return false;
|
||||
}
|
||||
} while (*s1++ && *s2++);
|
||||
return true;
|
||||
}
|
||||
|
||||
__declspec(naked) void fix_script_function__ISGLIDER() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
mov edi, eax ; my glider
|
||||
mov esi, [esp+20h+4+8*4] ; arg
|
||||
|
||||
label_cmp:
|
||||
mov al, [edi]
|
||||
mov cl, [esi]
|
||||
cmp al, cl
|
||||
jne bad
|
||||
cmp al, 0
|
||||
je end
|
||||
inc edi
|
||||
inc esi
|
||||
jmp label_cmp
|
||||
end:
|
||||
cmp al, cl
|
||||
jne bad
|
||||
popad
|
||||
; push some regs as required by success branch
|
||||
push ebx
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
push 0x0043A2DA
|
||||
ret
|
||||
|
||||
bad:
|
||||
popad
|
||||
; original thunk
|
||||
copy:
|
||||
mov cl, [eax]; injection point
|
||||
inc eax
|
||||
mov[edx], cl
|
||||
inc edx
|
||||
test cl, cl
|
||||
jnz copy
|
||||
|
||||
; epilogue
|
||||
push known_caller
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
bool is_double_light_weapons_glider() {
|
||||
return false
|
||||
|| get_player_ptr()->glider_name.idx == (int)glider_id::nargoon
|
||||
|| get_player_ptr()->glider_name.idx == (int)glider_id::finder1
|
||||
;
|
||||
}
|
||||
bool is_double_heavy_weapons_glider() {
|
||||
return false
|
||||
|| get_player_ptr()->glider_name.idx == (int)glider_id::eyedstone
|
||||
|| get_player_ptr()->glider_name.idx == (int)glider_id::finder2
|
||||
;
|
||||
}
|
||||
bool is_special_glider() {
|
||||
return is_double_light_weapons_glider() || is_double_heavy_weapons_glider();
|
||||
}
|
||||
|
||||
bool is_double_light_weapons_glider(glider_id id) {
|
||||
return false
|
||||
|| id == glider_id::nargoon
|
||||
|| id == glider_id::finder1
|
||||
;
|
||||
}
|
||||
bool is_double_heavy_weapons_glider(glider_id id) {
|
||||
return false
|
||||
|| id == glider_id::eyedstone
|
||||
|| id == glider_id::finder2
|
||||
;
|
||||
}
|
||||
bool is_special_glider(glider_id id) {
|
||||
return is_double_light_weapons_glider(id) || is_double_heavy_weapons_glider(id);
|
||||
}
|
||||
|
||||
bool __stdcall can_buy_weapon(int selected_weapon_type, int *canbuy) {
|
||||
if (is_special_glider()) {
|
||||
if (selected_weapon_type == light && is_double_heavy_weapons_glider()) {
|
||||
*(uint8_t*)canbuy = 0;
|
||||
}
|
||||
if (selected_weapon_type == heavy && is_double_light_weapons_glider()) {
|
||||
*(uint8_t *)canbuy = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
__declspec(naked) void fix_trade_actions_weapon_checks() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
; ebx = selected weapon type in the store
|
||||
; esi = gun_desc
|
||||
; [esp + 102h] bool is_buy_change
|
||||
; [esp + 103h] bool can_buy
|
||||
|
||||
mov edx, esp
|
||||
add edx, 123h
|
||||
lea edx, [edx]
|
||||
push edx
|
||||
|
||||
push ebx
|
||||
call can_buy_weapon
|
||||
test al, 1
|
||||
jz epi
|
||||
popad
|
||||
push 0x00407308
|
||||
ret
|
||||
|
||||
epi:
|
||||
; epilogue
|
||||
popad
|
||||
mov eax, ebx
|
||||
sub eax, 0
|
||||
push known_caller
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
bool can_have_light_weapon_slot(glider *obj, glider_id id, int special) {
|
||||
if (is_special_glider(id)) {
|
||||
return true;
|
||||
}
|
||||
return ((special >> 1) & 0x1) == 0;
|
||||
}
|
||||
bool can_have_heavy_weapon_slot(glider *obj, glider_id id, int special) {
|
||||
if (is_special_glider(id)) {
|
||||
return true;
|
||||
}
|
||||
return obj->standard > 2 && (special & 0x1) == 0;
|
||||
}
|
||||
void __stdcall can_have_weapon_slots(glider *gliders, glider *obj, int special) {
|
||||
auto id = obj - gliders;
|
||||
obj->can_have_light_weap = can_have_light_weapon_slot(obj, (glider_id)id, special);
|
||||
obj->can_have_heavy_weap = can_have_heavy_weapon_slot(obj, (glider_id)id, special);
|
||||
}
|
||||
__declspec(naked) void fix_can_have_weapon_slots_for_a_glider() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
push eax; SPECIAL field value
|
||||
mov ecx, edx;
|
||||
add ecx, ebx;
|
||||
push ecx ; glider*
|
||||
push edx ; glider**
|
||||
call can_have_weapon_slots
|
||||
|
||||
popad
|
||||
push 0x004D6351
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
bool __stdcall put_purchased_weapon_into_light_slot(int purchased_weapon_type) {
|
||||
if (is_special_glider()) {
|
||||
return get_player_ptr()->glider_object->light_gun_id == -1;
|
||||
}
|
||||
return purchased_weapon_type == 0;
|
||||
}
|
||||
__declspec(naked) void fix_put_weapon_into_the_right_slot_after_purchase() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
push eax ; purchased weapon type
|
||||
|
||||
call put_purchased_weapon_into_light_slot
|
||||
cmp al, 1
|
||||
jne heavy_exit
|
||||
popad
|
||||
push 0x00417AA1
|
||||
ret
|
||||
|
||||
heavy_exit:
|
||||
popad
|
||||
push 0x00417A75
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
bool __stdcall sell_light_weapon(int sold_weapon_type) {
|
||||
if (is_special_glider()) {
|
||||
return get_player_ptr()->glider_object->light_gun_id != -1;
|
||||
}
|
||||
return sold_weapon_type == 0;
|
||||
}
|
||||
__declspec(naked) void fix_sell_correct_weapon() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
push eax; purchased weapon type
|
||||
|
||||
call sell_light_weapon
|
||||
cmp al, 1
|
||||
jne heavy_exit
|
||||
popad
|
||||
push 0x004176F1
|
||||
ret
|
||||
|
||||
heavy_exit:
|
||||
popad
|
||||
push 0x004176C4
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t empty_weapon_message;
|
||||
void __stdcall fix_empty_weapon_message(int light_slot) {
|
||||
constexpr auto INT_EMPTY_LIGHT_GUN = 0x00521AA8;
|
||||
constexpr auto INT_EMPTY_HEAVY_GUN = 0x00521A94;
|
||||
if (is_double_light_weapons_glider()) {
|
||||
empty_weapon_message = INT_EMPTY_LIGHT_GUN;
|
||||
} else if (is_double_heavy_weapons_glider()) {
|
||||
empty_weapon_message = INT_EMPTY_HEAVY_GUN;
|
||||
} else {
|
||||
empty_weapon_message = light_slot ? INT_EMPTY_LIGHT_GUN : INT_EMPTY_HEAVY_GUN;
|
||||
}
|
||||
}
|
||||
__declspec(naked) void fix_empty_light_weapon_message() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
mov eax, 1
|
||||
push eax
|
||||
call fix_empty_weapon_message
|
||||
|
||||
popad
|
||||
push empty_weapon_message
|
||||
push known_caller
|
||||
ret
|
||||
}
|
||||
}
|
||||
__declspec(naked) void fix_empty_heavy_weapon_message() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
mov eax, 0
|
||||
push eax
|
||||
call fix_empty_weapon_message
|
||||
|
||||
popad
|
||||
push empty_weapon_message
|
||||
push known_caller
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) __declspec(naked) void dispatcher() {
|
||||
__asm {
|
||||
pop known_caller
|
||||
pushad
|
||||
}
|
||||
switch (known_caller - call_command_length) {
|
||||
case aim1_fix::script_function__ISGLIDER:
|
||||
known_caller += 0xA - call_command_length; // make normal ret
|
||||
__asm jmp fix_script_function__ISGLIDER
|
||||
break;
|
||||
case aim1_fix::trade_actions_weapon_checks:
|
||||
__asm jmp fix_trade_actions_weapon_checks
|
||||
break;
|
||||
case aim1_fix::setup_proper_weapon_slots_for_a_glider:
|
||||
__asm jmp fix_can_have_weapon_slots_for_a_glider
|
||||
break;
|
||||
case aim1_fix::put_weapon_into_the_right_slot_after_purchase:
|
||||
__asm jmp fix_put_weapon_into_the_right_slot_after_purchase
|
||||
break;
|
||||
case aim1_fix::sell_correct_weapon:
|
||||
__asm jmp fix_sell_correct_weapon
|
||||
break;
|
||||
case aim1_fix::empty_light_weapon_message:
|
||||
__asm jmp fix_empty_light_weapon_message
|
||||
break;
|
||||
case aim1_fix::empty_heavy_weapon_message:
|
||||
__asm jmp fix_empty_heavy_weapon_message
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// just return
|
||||
__asm {
|
||||
popad
|
||||
push known_caller
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
//constexpr uint32_t free_data_base = 0x006929C0;
|
||||
constexpr uint32_t free_data_base = 0x00692FF0;
|
||||
auto mem = (uint8_t *)free_data_base;
|
||||
mem[0] = 0xE9;
|
||||
*(uint32_t*)&mem[1] = (uint32_t)&dispatcher - free_data_base - call_command_length;
|
||||
}
|
||||
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) {
|
||||
if (fdwReason == DLL_PROCESS_ATTACH) {
|
||||
setup();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
2323
examples/mods/aim1_community_fix/aim.exe.h
Normal file
2323
examples/mods/aim1_community_fix/aim.exe.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -12,6 +12,9 @@ deps: pub.lzwdgc.Polygon4.Tools.aim1_mod_maker-master
|
|||
* You can also distribute mod archive (requires 7z program).
|
||||
**/
|
||||
|
||||
#define AIM_TYPES_FILE_NAME "aim.exe.h"
|
||||
#define INJECTIONS_FILE_NAME "aim.exe.fixes.h"
|
||||
|
||||
#ifndef INJECTED_DLL
|
||||
#include "aim1_mod_maker.h"
|
||||
|
||||
|
|
@ -19,7 +22,7 @@ deps: pub.lzwdgc.Polygon4.Tools.aim1_mod_maker-master
|
|||
// patch note: lz, Solant, Streef
|
||||
// patch note:
|
||||
// patch note: Description
|
||||
// patch note: This mod fixes some issues with the original AIM v1.04 game.
|
||||
// patch note: This mod fixes some issues with the original AIM v1.06 (DRM-free) (1.0.6.3) game.
|
||||
// patch note:
|
||||
// patch note: Installation
|
||||
// patch note: Unpack and drop all files near original aim.exe. Replace files if necessary.
|
||||
|
|
@ -27,6 +30,16 @@ deps: pub.lzwdgc.Polygon4.Tools.aim1_mod_maker-master
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
mod_maker mod;
|
||||
mod.files_to_distribute.insert(INJECTIONS_FILE_NAME);
|
||||
mod.files_to_distribute.insert(AIM_TYPES_FILE_NAME);
|
||||
|
||||
// patch note: enable double weap gliders (still have many bugs related)
|
||||
mod.make_injection(0x004072FA); // can trade for buy purposes
|
||||
mod.make_injection(0x004D62E4); // setup proper weapon slots for a glider
|
||||
mod.make_injection(0x00417A6D); // put weapon into the right slot after purchase
|
||||
mod.make_injection(0x004176BC); // sell correct weapon
|
||||
mod.make_injection(0x004067C4); // empty light weap
|
||||
mod.make_injection(0x0040688B); // empty heavy weap
|
||||
|
||||
// patch note: CHANGES
|
||||
// patch note:
|
||||
|
|
@ -65,7 +78,6 @@ int main(int argc, char *argv[]) {
|
|||
// patch note:
|
||||
|
||||
// patch note: Script Changes
|
||||
// patch note: _ISGLIDER() function can check exact glider name now, for example _ISGLIDER(GL_M3_A_FIRST1) (lz)
|
||||
// patch note: fix joining First Ones having one of four required gliders (lz, Streef)
|
||||
mod.replace("ORG_FIRST.scr",
|
||||
"IF(_PLAYERHAS(GL_M3_A_FIRST1)||_PLAYERHAS(GL_M3_A_FIRST1))",
|
||||
|
|
@ -77,24 +89,30 @@ int main(int argc, char *argv[]) {
|
|||
mod.replace("ORG_SINIGR.scr",
|
||||
"IF(_PLAYERHAS(GL_S2_PA_SINYGR)|_PLAYERHAS(GL_S4_S_SINYGR))",
|
||||
"IF(_ISGLIDER(GL_S2_PA_SINYGR)|_ISGLIDER(GL_S4_S_SINYGR))");
|
||||
|
||||
// patch note: _ISGLIDER() function can check exact glider name now, for example _ISGLIDER(GL_M3_A_FIRST1) (lz)
|
||||
mod.make_injection(0x0043A1F6, 10);
|
||||
//
|
||||
|
||||
// end of scripts section
|
||||
// patch note:
|
||||
|
||||
/*mod.replace("Script/bin/B_L1_BASE1.scr", "_ADDBALANCE(300)", R"(
|
||||
mod.replace("Script/bin/B_L1_BASE1.scr", "_ADDBALANCE(300)", R"(
|
||||
_ADDBALANCE(300 )
|
||||
|
||||
_ADDOBJECT(GL_M3_PA_EYEDSTONE)
|
||||
_ADDOBJECT(GL_S3_PS_FINDER1)
|
||||
_ADDOBJECT(EQP_VACUUM_DRIVE_S3)
|
||||
_ADDOBJECT(EQP_ZERO_ARMOR_S3)
|
||||
_ADDOBJECT(EQP_SHIELD_GENERATOR4_S3)
|
||||
|
||||
_ADDOBJECT(GL_M4_S_FIRST2)
|
||||
_ADDOBJECT(EQP_VACUUM_DRIVE_S4)
|
||||
//_ADDOBJECT(GL_M4_S_FIRST2)
|
||||
//_ADDOBJECT(EQP_VACUUM_DRIVE_S4)
|
||||
//_ADDOBJECT(EQP_MEZON_REACTOR_S4)
|
||||
//_ADDOBJECT(EQP_GLUON_REACTOR_S1)
|
||||
_ADDOBJECT(EQP_ZERO_ARMOR_S4)
|
||||
_ADDOBJECT(EQP_SHIELD_GENERATOR4_S4)
|
||||
_ADDOBJECT(GUN_MICROWAVE_OSCILLATOR)
|
||||
_ADDOBJECT(GUN_RAILGUN)
|
||||
//_ADDOBJECT(EQP_ZERO_ARMOR_S4)
|
||||
//_ADDOBJECT(EQP_SHIELD_GENERATOR4_S4)
|
||||
//_ADDOBJECT(GUN_MICROWAVE_OSCILLATOR)
|
||||
//_ADDOBJECT(GUN_RAILGUN)
|
||||
|
||||
_ADDRATING(300000000)
|
||||
_ADDBALANCE(30000000)
|
||||
|
|
@ -115,7 +133,7 @@ int main(int argc, char *argv[]) {
|
|||
_SETEVENT(SECTOR7.ACCESS)
|
||||
//_SETEVENT(SECTOR8.VISIT)
|
||||
_SETEVENT(SECTOR8.ACCESS)
|
||||
)");*/
|
||||
)");
|
||||
|
||||
// patch note: Release Manager
|
||||
// patch note: lz
|
||||
|
|
@ -144,100 +162,5 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
#else // INJECTED_DLL
|
||||
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
constexpr auto call_command_length = 5;
|
||||
|
||||
enum aim1_fix : uint32_t {
|
||||
script_function__ISGLIDER = 0x0043A1F6,
|
||||
};
|
||||
uint32_t known_caller;
|
||||
|
||||
__declspec(naked) void fix_script_function__ISGLIDER() {
|
||||
__asm {
|
||||
; restore values
|
||||
popad
|
||||
pushad
|
||||
|
||||
mov edi, eax; my glider
|
||||
mov esi, [esp + 20h + 4 + 8 * 4]; arg
|
||||
|
||||
label_cmp :
|
||||
mov al, [edi]
|
||||
mov cl, [esi]
|
||||
cmp al, cl
|
||||
jne bad
|
||||
cmp al, 0
|
||||
je end
|
||||
cmp cl, 0
|
||||
je end
|
||||
inc edi
|
||||
inc esi
|
||||
jmp label_cmp
|
||||
end :
|
||||
cmp al, cl
|
||||
jne bad
|
||||
popad
|
||||
; push some regs as required by success branch
|
||||
push ebx
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
push 0x0043A2DA
|
||||
ret
|
||||
|
||||
bad :
|
||||
popad
|
||||
; popf
|
||||
; original thunk
|
||||
copy :
|
||||
mov cl, [eax]; injection point
|
||||
inc eax
|
||||
mov[edx], cl
|
||||
inc edx
|
||||
test cl, cl
|
||||
jnz copy
|
||||
|
||||
; epilogue
|
||||
push known_caller
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) __declspec(naked) void dispatcher() {
|
||||
__asm {
|
||||
pop known_caller
|
||||
pushad
|
||||
}
|
||||
switch (known_caller - call_command_length) {
|
||||
case aim1_fix::script_function__ISGLIDER:
|
||||
known_caller += 0xA - call_command_length; // make normal ret
|
||||
__asm jmp fix_script_function__ISGLIDER
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// just return
|
||||
__asm {
|
||||
popa
|
||||
push known_caller
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
constexpr uint32_t free_data_base = 0x006929C0;
|
||||
auto mem = (uint8_t *)free_data_base;
|
||||
mem[0] = 0xE9;
|
||||
*(uint32_t *)&mem[1] = (uint32_t)&dispatcher - free_data_base - call_command_length;
|
||||
}
|
||||
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) {
|
||||
if (fdwReason == DLL_PROCESS_ATTACH) {
|
||||
setup();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#include INJECTIONS_FILE_NAME
|
||||
#endif
|
||||
|
|
@ -51,6 +51,18 @@ auto operator""_bin(const char *ptr, uint64_t len) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct aim_exe_v1_06_constants {
|
||||
enum : uint32_t {
|
||||
trampoline_base_real = 0x00025100,
|
||||
trampoline_target_real = 0x001207f0,
|
||||
//code_base = 0x00401000,
|
||||
//data_base = 0x00540000,
|
||||
//free_data_base_virtual = 0x006929C0,
|
||||
free_data_base_virtual = 0x00692FF0,
|
||||
our_code_start_virtual = 0x005207F0, // place to put out dll load
|
||||
};
|
||||
};
|
||||
|
||||
struct mod_maker {
|
||||
enum class file_type {
|
||||
unknown,
|
||||
|
|
@ -164,6 +176,24 @@ struct mod_maker {
|
|||
return patch_raw(fn, offset, oldval, val);
|
||||
}
|
||||
|
||||
// all you need is to provide injection address (virtual) with size
|
||||
// handle the call instruction in 'dispatcher' symbol (naked) of your dll
|
||||
constexpr static inline auto call_command_length = 5;
|
||||
void make_injection(uint32_t virtual_address, uint32_t size = call_command_length) {
|
||||
uint32_t len = size;
|
||||
if (len < call_command_length) {
|
||||
throw std::runtime_error{"jumppad must be 5 bytes atleast"};
|
||||
}
|
||||
primitives::templates2::mmap_file<uint8_t> f{find_real_filename(aim_exe),
|
||||
primitives::templates2::mmap_file<uint8_t>::rw{}};
|
||||
auto ptr = f.p + virtual_address - aim_exe_v1_06_constants::our_code_start_virtual + aim_exe_v1_06_constants::trampoline_target_real;
|
||||
memcpy(ptr, make_insn_with_address("e8"_bin, aim_exe_v1_06_constants::free_data_base_virtual -
|
||||
(virtual_address + call_command_length)));
|
||||
memcpy(ptr, make_nops(len - call_command_length));
|
||||
std::println("making injection on the virtual address 0x{:0X} (real address 0x{:0X}), size {}", virtual_address, ptr - f.p,
|
||||
size);
|
||||
}
|
||||
|
||||
#define ENABLE_DISABLE_FUNC(name, enable, disable) \
|
||||
void enable_##name() { name(enable); } \
|
||||
void disable_##name() { name(disable); }
|
||||
|
|
@ -226,7 +256,7 @@ private:
|
|||
*(uint32_t *)(&arr[insn.size()]) = addr;
|
||||
return arr;
|
||||
}
|
||||
static auto make_nops(uint32_t len) {
|
||||
static byte_array make_nops(uint32_t len) {
|
||||
byte_array arr(len, 0x90);
|
||||
return arr;
|
||||
}
|
||||
|
|
@ -279,28 +309,26 @@ private:
|
|||
make_injected_dll();
|
||||
files_to_distribute.insert(aim_exe);
|
||||
primitives::templates2::mmap_file<uint8_t> f{find_real_filename(aim_exe), primitives::templates2::mmap_file<uint8_t>::rw{}};
|
||||
constexpr uint32_t trampoline_base = 0x00025100;
|
||||
constexpr uint32_t trampoline_target = 0x001207f0;
|
||||
constexpr uint32_t code_base = 0x00401000;
|
||||
constexpr uint32_t data_base = 0x00540000;
|
||||
constexpr uint32_t free_data_base = 0x006929C0;
|
||||
//constexpr uint32_t our_data = 0x00550FD0;
|
||||
const uint32_t our_data_start = 0x005207F0;
|
||||
uint32_t our_data = 0x005207F0;
|
||||
//constexpr uint32_t free_data_base_real = 0x140000 + our_data - 0x00540000;
|
||||
uint32_t our_data = aim_exe_v1_06_constants::our_code_start_virtual;
|
||||
|
||||
auto ptr = f.p + trampoline_target;
|
||||
//strcpy((char *)f.p + free_data_base_real, get_dll_name().c_str());
|
||||
strcpy((char *)ptr, get_dll_name().c_str());
|
||||
auto ptr = f.p + aim_exe_v1_06_constants::trampoline_target_real;
|
||||
#ifdef NDEBUG
|
||||
auto dllnamelen = get_sw_dll_name().size() + 1;
|
||||
strcpy((char *)ptr, get_sw_dll_name().c_str());
|
||||
#else
|
||||
auto dllname = "h:\\Games\\AIM\\1\\.sw\\out\\d\\aim_fixes-0.0.1.dll"s;
|
||||
auto dllnamelen = dllname.size() + 1;
|
||||
strcpy((char *)ptr, dllname.c_str());
|
||||
#endif
|
||||
ptr += dllnamelen;
|
||||
auto push_dll_name = make_insn_with_address("68"_bin, our_data); // push
|
||||
ptr += 0x20;
|
||||
our_data += 0x20;
|
||||
strcpy((char *)ptr, "dispatcher");
|
||||
auto dispatcher_func_name = make_insn_with_address("68"_bin, our_data); // push
|
||||
ptr += 0x20;
|
||||
our_data += 0x20;
|
||||
const auto jumppad = "68 30 B8 51 00"_bin; // push offset SEH_425100
|
||||
uint32_t jump_offset = ptr - f.p - trampoline_base - jumppad.size() * 2;
|
||||
uint32_t jump_offset = ptr - f.p - aim_exe_v1_06_constants::trampoline_base_real - jumppad.size() * 2;
|
||||
memreplace(f.p, f.sz, jumppad, make_insn_with_address("e9"_bin, jump_offset));
|
||||
memcpy(ptr, jumppad); // put our removed insn
|
||||
memcpy(ptr, R"(
|
||||
|
|
@ -331,15 +359,7 @@ FF D7 ; call edi
|
|||
memcpy(ptr, R"(
|
||||
61 ; popa
|
||||
)"_bin);
|
||||
memcpy(ptr, make_insn_with_address("e9"_bin, -(ptr - f.p - trampoline_base - jumppad.size())));
|
||||
|
||||
// E8 C5 87 25 00
|
||||
constexpr auto call_command_length = 5;
|
||||
uint32_t start_addr = 0x0043A1F6;
|
||||
uint32_t len = 10;
|
||||
ptr = f.p + start_addr - our_data_start + trampoline_target;
|
||||
memcpy(ptr, make_insn_with_address("e8"_bin, free_data_base - (start_addr + call_command_length)));
|
||||
memcpy(ptr, make_nops(len - call_command_length));
|
||||
memcpy(ptr, make_insn_with_address("e9"_bin, -(ptr - f.p - aim_exe_v1_06_constants::trampoline_base_real - jumppad.size())));
|
||||
}
|
||||
path find_real_filename(path fn) const {
|
||||
auto s = fn.wstring();
|
||||
|
|
|
|||
|
|
@ -22,4 +22,43 @@
|
|||
</DisplayString>
|
||||
</Type>
|
||||
|
||||
<Type Name="db2::tab">
|
||||
<Expand>
|
||||
<Item Name="[number of tables]" ExcludeView="simple">n_tables</Item>
|
||||
<Item Name="[number of fields]" ExcludeView="simple">n_fields</Item>
|
||||
<ArrayItems>
|
||||
<Size>n_tables</Size>
|
||||
<ValuePointer>(db2::tab::table*)(&n_fields+1)</ValuePointer>
|
||||
</ArrayItems>
|
||||
<ArrayItems>
|
||||
<Size>n_fields</Size>
|
||||
<ValuePointer>(db2::tab::field*)((db2::tab::table*)(&n_fields+1)+n_tables)</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="db2::tab::table">
|
||||
<DisplayString>
|
||||
{id},{name,s}
|
||||
</DisplayString>
|
||||
</Type>
|
||||
<Type Name="db2::tab::field">
|
||||
<DisplayString>
|
||||
{table_id},{id},{name,s},{type}
|
||||
</DisplayString>
|
||||
</Type>
|
||||
<Type Name="db2::ind">
|
||||
<Expand>
|
||||
<Item Name="[number of values]" ExcludeView="simple">n_values</Item>
|
||||
<ArrayItems>
|
||||
<Size>n_values</Size>
|
||||
<ValuePointer>(db2::value*)(&n_values+1)</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="db2::value">
|
||||
<DisplayString>
|
||||
{table_id},{name,s}
|
||||
</DisplayString>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ struct Good
|
|||
};
|
||||
|
||||
std::string name;
|
||||
char unk1[0x40];
|
||||
char condition_variable[0x40]; // when this var is set, we can access the good
|
||||
float unk1_2 = 0;
|
||||
float price = 0; // unk, quantity?
|
||||
float unk2[10];
|
||||
|
|
@ -199,7 +199,7 @@ struct Good
|
|||
{
|
||||
READ_STRING(b, name);
|
||||
if (gameType == GameType::Aim1)
|
||||
READ(b, unk1);
|
||||
READ(b, condition_variable);
|
||||
else
|
||||
READ(b, unk1_2);
|
||||
READ(b, price);
|
||||
|
|
|
|||
17
sw.cpp
17
sw.cpp
|
|
@ -8,10 +8,13 @@ void build(Solution &s)
|
|||
auto cppstd = cpp23;
|
||||
|
||||
auto &common = tools.addStaticLibrary("common");
|
||||
{
|
||||
common += cppstd;
|
||||
common.setRootDirectory("src/common");
|
||||
common += ".*"_rr;
|
||||
common.Public += "pub.egorpugin.primitives.filesystem"_dep;
|
||||
common.Public += "pub.egorpugin.primitives.templates2"_dep;
|
||||
}
|
||||
|
||||
auto add_exe_base = [&](const String &name) -> decltype(auto)
|
||||
{
|
||||
|
|
@ -73,16 +76,16 @@ void build(Solution &s)
|
|||
;
|
||||
}
|
||||
|
||||
auto &aim1_mod_maker = tools.addStaticLibrary("aim1_mod_maker");
|
||||
auto &aim1_mod_maker = add_exe_with_common("aim1_mod_maker"); // actually a library
|
||||
aim1_mod_maker.Public += "pub.egorpugin.primitives.command"_dep;
|
||||
|
||||
auto &aim1_community_fix = tools.addExecutable("examples.mods.aim1_community_fix");
|
||||
{
|
||||
auto &t = aim1_mod_maker;
|
||||
auto name = "aim1_mod_maker";
|
||||
auto &t = aim1_community_fix;
|
||||
t.PackageDefinitions = true;
|
||||
t += cppstd;
|
||||
t.setRootDirectory("src/"s + name);
|
||||
//t.Public += "pub.egorpugin.primitives.sw.main"_dep;
|
||||
t.Public += "pub.egorpugin.primitives.command"_dep;
|
||||
t.Public += common;
|
||||
t += "examples/mods/aim1_community_fix/.*"_rr;
|
||||
t += aim1_mod_maker;
|
||||
}
|
||||
|
||||
add_exe("mod_reader") += model;
|
||||
|
|
|
|||
Loading…
Reference in a new issue