IMG

 
IMG
IMG   IMG
  Welcome to GTAForums! Be sure to check out the Grand Theft Auto V Forum.

You are not registered! (If you are, click here to login) Registering is fast, free and easy and allows you to instantly reply to any topic on GTAForums.
Why wait? Click here to register your own unique username and become part of the ever-growing community!


( Log In | Register | Revalidate Validation E-mail )
Quick Log-In:
  IMG
       
>
Forum Rules GTA Modification Forums

Post mod/code requests in the Mod Requests topic

Post mod releases in the Mod Showroom

Read the Modding Rules BEFORE posting!

GTAGarage.com
free mod hosting from GTANet, simply login with your GTAForums account details

GTAModding.com
GTANet's modding wiki

GTA Modding Chatroom
provided by irc.gtanet.com (Don't have an IRC client? Click here)


Pages: (2) 1 [2]   ( Go to first unread post ) Reply to this topicStart new topicStart Poll

 [C++|ASM] Alter damage received

 
FaTony  
Posted: Sunday, Apr 1 2012, 19:02
Quote Post


C++ guy
Group Icon
Group: Members
Joined: Aug 12, 2011

XXXXX



Looks outdated. I've attached debugger to GTAIV.exe and it crashed after a few seconds with callstack inside xlive.dll. I think I'll have dig into the source code of Xliveless...
PM
  Top
 

 
LMS  
Posted: Sunday, Apr 1 2012, 19:54
Quote Post


Punk-ass Bitch
Group Icon
Group: Members
Joined: Jun 30, 2005

gr.gif

XXXXX



I didn't say it allows you to attach a debugger smile.gif You are able to alter the game memory without crashes, but attaching a debugger still requires xliveless.
PM
  Top
 

 
FaTony  
Posted: Sunday, Apr 1 2012, 21:48
Quote Post


C++ guy
Group Icon
Group: Members
Joined: Aug 12, 2011

XXXXX



Oh man, I can't describe how I'm thankful to you. I just did
CODE
void OnPedDamage(void* unknown, void* target)
{
float damage = ReadDamage();
damage *= 0.3f;
SetDamage(damage);
}

and had a best GTA4 cop shootout in my life!

That protection disabler actually works in the end.

Ok, now it's time for some improvements. For example I don't like that that OnPedDamage heavily relies on contents of registers. xmm0 at least. What if I call a function inside OnPedDamage that modifies xmm0 during it's internal workings?

My proposition is to modify Hooked_damagePed as follows:
  • Save all valuable registers into a safe place (stack?).
  • Do a clean call of C++ function. (All relevant pushing and register values).
  • Restore all valuable registers from the safe place and modify xmm0 to the value from C++ function.

I see you already doing this with ecx (does this mean we are hooking __thiscall?).

To help you out with assembly, I've written this small program:
CODE
void OnPedDamage(const void *victim, const void *attacker, float &damage)
{
damage *= 2.0f;
}

int main()
{
void *ptr1 = (void *)1;
void *ptr2 = (void *)2;
float fl3 = 1.0f;
OnPedDamage(ptr1, ptr2, fl3);
fl3 += 42.0f;
return 0;
}


When compiled and disassembled, it gives following code:
CODE
.text:004113C0; int __cdecl main()
.text:004113C0 _main           proc near              ; CODE XREF: j__mainj
.text:004113C0
.text:004113C0 var_E4          = byte ptr -0E4h
.text:004113C0 fl3             = dword ptr -20h
.text:004113C0 ptr2            = dword ptr -14h
.text:004113C0 ptr1            = dword ptr -8
.text:004113C0
.text:004113C0                 push    ebp
.text:004113C1                 mov     ebp, esp
.text:004113C3                 sub     esp, 0E4h
.text:004113C9                 push    ebx
.text:004113CA                 push    esi
.text:004113CB                 push    edi
.text:004113CC                 lea     edi, [ebp+var_E4]
.text:004113D2                 mov     ecx, 39h
.text:004113D7                 mov     eax, 0CCCCCCCCh
.text:004113DC                 rep stosd
.text:004113DE                 mov     [ebp+ptr1], 1
.text:004113E5                 mov     [ebp+ptr2], 2
.text:004113EC                 fld1
.text:004113EE                 fstp    [ebp+fl3]
.text:004113F1                 lea     eax, [ebp+fl3]
.text:004113F4                 push    eax            ; damage
.text:004113F5                 mov     ecx, [ebp+ptr2]
.text:004113F8                 push    ecx            ; attacker
.text:004113F9                 mov     edx, [ebp+ptr1]
.text:004113FC                 push    edx            ; victim
.text:004113FD                 call    j_?OnPedDamage@@YAXPBX0AAM@Z; OnPedDamage(void const *,void const *,float &)
.text:00411402                 add     esp, 0Ch
.text:00411405                 fld     [ebp+fl3]
.text:00411408                 fadd    ds:__real@4045000000000000
.text:0041140E                 fstp    [ebp+fl3]
.text:00411411                 xor     eax, eax
.text:00411413                 push    edx
.text:00411414                 mov     ecx, ebp       ; frame
.text:00411416                 push    eax
.text:00411417                 lea     edx, v         ; v
.text:0041141D                 call    j_@_RTC_CheckStackVars@8; _RTC_CheckStackVars(x,x)
.text:00411422                 pop     eax
.text:00411423                 pop     edx
.text:00411424                 pop     edi
.text:00411425                 pop     esi
.text:00411426                 pop     ebx
.text:00411427                 add     esp, 0E4h
.text:0041142D                 cmp     ebp, esp
.text:0041142F                 call    j___RTC_CheckEsp
.text:00411434                 mov     esp, ebp
.text:00411436                 pop     ebp
.text:00411437                 retn
------------------------------------------------------------------------------------------------------
.text:00411380; void __cdecl OnPedDamage(const void *victim, const void *attacker, float *damage)
.text:00411380 ?OnPedDamage@@YAXPBX0AAM@Z proc near   ; CODE XREF: .text:00411082j
.text:00411380                                        ; .text:004111C2j ...
.text:00411380
.text:00411380 var_C0          = byte ptr -0C0h
.text:00411380 victim          = dword ptr  8
.text:00411380 attacker        = dword ptr  0Ch
.text:00411380 damage          = dword ptr  10h
.text:00411380
.text:00411380                 push    ebp
.text:00411381                 mov     ebp, esp
.text:00411383                 sub     esp, 0C0h
.text:00411389                 push    ebx
.text:0041138A                 push    esi
.text:0041138B                 push    edi
.text:0041138C                 lea     edi, [ebp+var_C0]
.text:00411392                 mov     ecx, 30h
.text:00411397                 mov     eax, 0CCCCCCCCh
.text:0041139C                 rep stosd
.text:0041139E                 mov     eax, [ebp+damage]
.text:004113A1                 fld     dword ptr [eax]
.text:004113A3                 fadd    st, st
.text:004113A5                 mov     ecx, [ebp+damage]
.text:004113A8                 fstp    dword ptr [ecx]
.text:004113AA                 pop     edi
.text:004113AB                 pop     esi
.text:004113AC                 pop     ebx
.text:004113AD                 mov     esp, ebp
.text:004113AF                 pop     ebp
.text:004113B0                 retn
.text:004113B0 ?OnPedDamage@@YAXPBX0AAM@Z endp
PM
  Top
 

 
LMS  
Posted: Sunday, Apr 1 2012, 23:03
Quote Post


Punk-ass Bitch
Group Icon
Group: Members
Joined: Jun 30, 2005

gr.gif

XXXXX



Take a closer look at my code, it only depends on ECX. I only use xmm0 to temporarily store the value to be able to either read it from c++ or to set it from c++, but only [ecx+4h] is changed. Also there's no need to safe the registers, your C++ function will take care of this. Your assembly code is an excellent example for this, notice how it pushes ebx, esi and edi because it needs some registers to work with and later pops them again. So in the end when the function returns all registers will be set to their initial value. I'm glad I could help you smile.gif
PM
  Top
 

 
FaTony  
Posted: Sunday, Apr 1 2012, 23:19
Quote Post


C++ guy
Group Icon
Group: Members
Joined: Aug 12, 2011

XXXXX



Ok, improvising, correct me if I'm wrong:
CODE

__declspec( naked ) int __stdcall PedDamageHook::Hooked_damagePed(void* unknown, void* target)
{
_asm
{
// Save ecx
push ecx
// Save stack
push ebx
push esi
push edi

//Prepare call
push [ecx+4h] //damage
push [ebp+14h] //attacker
push [???] //victim
// Call function
call OnPedDamage
//Pop arguments (assuming _cdecl)
pop ???
...
//Restore stack
pop     edi
pop     esi
pop     ebx
// Restore ecx
pop  ecx
jmp  dwRealFunction
}
}
PM
  Top
 

 
LMS  
Posted: Sunday, Apr 1 2012, 23:25
Quote Post


Punk-ass Bitch
Group Icon
Group: Members
Joined: Jun 30, 2005

gr.gif

XXXXX



There's no need for you to change the code. Your C++ function will save the stack before using it and later pop it again. You don't have to do it! On top of that you don't have to push the arguments for OnPedDamage again, in the naked function there is no stack activity and thus the arguments are still on the top. Also why do you dislike the idea of storing ecx in a global? Trust me, you don't have to touch the code.
PM
  Top
 

 
FaTony  
Posted: Sunday, Apr 1 2012, 23:32
Quote Post


C++ guy
Group Icon
Group: Members
Joined: Aug 12, 2011

XXXXX



I want to change prototype of C++ function from void func(void*, void*) where 1st argument is useless and there needs to be 2 function calls to alter the damage and inline assembly to get the attacker to void func(const void*, const void*, float&) which is const-correct, have 3 valuable arguments and doesn't need any function calls to alter the damage.

EDIT:

If we wrap your functions:
CODE
void OnPedDamage(void *unknown, void *victim)
{
float damage = ReadDamage();
void* attacker = 0;
_asm
{
  push eax
  mov  eax, [ebp+14h]
  mov  attacker, eax
  pop  eax
}
Wrapper2(victim, attacker, damage);
SetDamage(damage);
}


But it's it a bit ugly?

This post has been edited by FaTony on Sunday, Apr 1 2012, 23:46
PM
  Top
 

 
LMS  
Posted: Sunday, Apr 1 2012, 23:47
Quote Post


Punk-ass Bitch
Group Icon
Group: Members
Joined: Jun 30, 2005

gr.gif

XXXXX



Ok I see, but still there no need for you to touch the asm code since you have a C++ function where you don't have to mess around with registers and such. Like:

CODE

void PedDamageHook::OnPedDamage(void* unknown, void* target)
{
// Read damage value
float damage = PedDamageHook::ReadDamage();
// Get damage source
void* source = 0;
_asm
{
 push eax
 mov  eax, [ebp+14h]
 mov  source, eax
 pop  eax
}
PedDamageHook::SetDamage(PedDamageHook::AdjustDamage(target, source, damage));
}

float PedDamageHook::AdjustDamage(void* target, void* source, float damage)
{
void* playerPed = PedDamageHook::GetPlayerPed(0);

if (playerPed == target)
{
 return 1;
}

// If damage is dealt by player, multiply by 10
if (source == playerPed)
{
 return damage * 20;
}
}


Edit: Yeah, just like your wrapper.
PM
  Top
 

 
FaTony  
Posted: Sunday, Apr 1 2012, 23:54
Quote Post


C++ guy
Group Icon
Group: Members
Joined: Aug 12, 2011

XXXXX



But wouldn't it be fun to call AdjustDamage from naked function? Looking at your prototype, I see you don't like references. wink.gif

I'm going to use wrapper, but will try to get rid of it when I'll have more knowledge of asm.
PM
  Top
 

 
LMS  
Posted: Sunday, Apr 1 2012, 23:58
Quote Post


Punk-ass Bitch
Group Icon
Group: Members
Joined: Jun 30, 2005

gr.gif

XXXXX



Sure it would be cleaner, but it would also result in more asm code and more unnecessary work tounge.gif But I think it's a great idea to do this when you have more knowledge of asm. And yeah, thanks to .NET I don't like references and try to avoid them whenever I can. But imho returning the new damage value seems ok when you call the function AdjustDamage.
PM
  Top
 

 
FaTony  
Posted: Monday, Apr 2 2012, 03:49
Quote Post


C++ guy
Group Icon
Group: Members
Joined: Aug 12, 2011

XXXXX



EDIT: Ok. After quite a few assembly related articles I managed to do this:
CODE
const DWORD GetPlayerPedFuncAddress = 0x008788D0;

typedef void *(__cdecl *GetPlayerPedFunc)(int);

GetPlayerPedFunc GetPlayerPed;

void InstallHooks(void)
{
GetPlayerPed = (GetPlayerPedFunc)(GetPlayerPedFuncAddress + dwLoadOffset);
//Other code
}

__declspec(naked) int __stdcall PedDamageHook(void *attacker, void *victim)
{
_asm
{
 // Function prolog
 // Create new stack frame
 push ebp
 mov  ebp, esp

 // Save relevant registers
 // Save ecx
 push ecx

 // Call C++ function
 // Push damage
 lea  eax, [ecx + 4h]
 push eax
 // Push attacker
 push [ebp + 10h]
 // Push victim
 push [ebp + 14h]
 // Call function
 call OnPedDamage
 // Clean stack
 add  esp, 12

 // Restore relevant registers
 // Restore ecx
 pop  ecx

 // Function epilog
 // Restore previous stack frame
 mov  esp, ebp
 pop  ebp

 // Code from '0x00ABB170', 8 ovewritten bytes
 sub  esp, 10h
 push ebp
 mov  ebp, [esp+1Ch]
 jmp  jmpaddress
}
}

void OnPedDamage(const void *victim, const void *attacker, float &damage)
{
void *player = GetPlayerPed(0);
if (victim == player)
{
 damage *= 0.1f;
}
else if (attacker == player)
{
 damage *= 10.0f;
}
}


The problem is, it looks like all peds have 2 ped classes associated with them. One is the "old school ped" that is used during gun fights and another is "Euphoria ped" with is used with physics and ragdolls. Old school peds have addresses in the range of 5xxxxxx. Euphoria peds have addresses in the range of 6xxxxxx. GetPlayerPed returns old school ped. So, for example, when I throw a molotov and get caught by it's fire, attacker will be my old school ped and victim will be my Euphoria ped. As a result, I will get 10x damage. That's no good.

Can you help me find a function that returns Euphoria peds?

This post has been edited by FaTony on Tuesday, Apr 3 2012, 01:57
PM
  Top
 

 

0 User(s) are reading this topic (0 Guests and 0 Anonymous Users)

0 Members:

Pages: (2) 1 [2] 

Topic Options Reply to this topicStart new topicStart Poll
Search topic for posted by (exact match)



 
IMG IMG