Skip to content

Commit

Permalink
[+] Tested (and fixed) LunaHook Wrappers
Browse files Browse the repository at this point in the history
[+] Added more Lawn functions (Autogen)
[+] Added more Zombie functions (Autogen)
  • Loading branch information
0xVB committed Sep 6, 2024
1 parent 293f6f8 commit 7b71cbb
Show file tree
Hide file tree
Showing 8 changed files with 2,136 additions and 27 deletions.
3 changes: 3 additions & 0 deletions include/Luna/Hook/LunaHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class LunaHookThread
static void DetourHeader(LunaHookThread*);
static void DetourFooter(LunaHookThread*);
class CodeBuffer;

public:
typedef unsigned int (__cdecl* LunaWrapper)(...);

Expand All @@ -58,6 +59,7 @@ class LunaHookThread
size_t GetCodeSize();
unsigned char AddToBuffer(unsigned char* BufferStart, unsigned short StackOffset);
void Encode(CodeBuffer*, char StackOffset = 0);
char EncodeIn(CodeBuffer*, char StackOffset);
Parameter(u8 StackOffset = 0);
Parameter(Register32);
};
Expand Down Expand Up @@ -88,6 +90,7 @@ class LunaHookThread

void Finalize(void* DetourTo);
LunaWrapper AllocateWrapper();
LunaWrapper FinalizeAndWrap(void* DetourTo);
static FunctionSignature* New(LunaHookThread*, DWORD Address);
};

Expand Down
18 changes: 16 additions & 2 deletions include/Lunacy/Lawn.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,20 +281,25 @@ class Lawn : Sexy::UIElement, Sexy::ButtonListener
bool IsPoolCell(int Col, int Row);
bool IsIceCell(int Col, int Row);

void PlantHitTest(int MouseX, int MouseY, HitResult*);
void MouseHitTest(int, int, HitResult*);

GridItem* GridItemHitTest(int MouseX, int MouseY);
Zombie* ZombieHitTest(int MouseX, int MouseY);
Plant* PlantHitTest(int MouseX, int MouseY);
Plant* SpecialPlantHitTest(int MouseX, int MouseY);

bool MouseHitTest(int X, int Y, HitResult* Out);
void PickUpTool(GameObjectType);
bool CanInteractWithButtons();
void SetPause(bool);
void ClearCursor();
void HighlightPlantsForMouse(int X, int Y);
void PickSpecialGraveStone();

void UpdateMousePosition();
void UpdateToolTip();
void MouseDownWithPlant(int X, int Y, ClickCode);
void MouseDownCobcannonFire(int X, int Y, ClickCode);
void MouseDownWithTool(int X, int Y, ClickCode, CursorType);

void ShowTutorialArrow(int X, int Y);
Expand All @@ -309,6 +314,9 @@ class Lawn : Sexy::UIElement, Sexy::ButtonListener
void __inline ZombiesWon() { ZombiesWon(NewZombie(ZOMBIE_NORMAL, 0)); }

bool IsFinalSurvivalStage();
bool IsFinalScaryPotterStage();
bool IsSurvivalStageWithRepick();
bool IsLastStandStageWithRepick();
bool LevelAwardDropped();
void UpdateSunSkyfall();
void UpdateZombieSpawning();
Expand All @@ -321,7 +329,8 @@ class Lawn : Sexy::UIElement, Sexy::ButtonListener
void ClearFogAroundPlant(Plant*, int Size);
void UpdateFog();

void DrawIce(Sexy::Graphics*);
void DrawZenWheelBarrowButton(Sexy::Graphics*, int YOffset);
void DrawIce(Sexy::Graphics*, int Lane);
void DrawBackground(Sexy::Graphics*);
void DrawProgressMeter(Sexy::Graphics*);
void DrawHouseDoorBottom(Sexy::Graphics*);
Expand Down Expand Up @@ -350,6 +359,8 @@ class Lawn : Sexy::UIElement, Sexy::ButtonListener
int GetSunBeingCollected();
int GetCoinsBeingCollected();
int GetNumSeedsInBank();
int GetNumWavesPerSurvivalStage();
void RemoveParticleSystemByType(ParticleEffect);

bool IsConveyorBeltLevel();
bool StageHasGraves();
Expand All @@ -361,6 +372,7 @@ class Lawn : Sexy::UIElement, Sexy::ButtonListener
bool StageHasZombiesWalkInFromRight();
int GetSeedPacketXPosition(int PacketIndex);
int GetSeedBankExtraWidth();
Plant* FindUmbrellaPlant(int Col, int Row);

bool SeedNotRecommendedForLevel(SeedType);
bool CanDropLoot();
Expand All @@ -369,6 +381,8 @@ class Lawn : Sexy::UIElement, Sexy::ButtonListener
void DoFwoosh(int Row);
void UpdateFwoosh();
bool PlantingRequirementsMet(SeedType);
bool PlantUsesAcceleratedPricing(SeedType);
int GetCurrentPlantCost(SeedType Type, SeedType ImitaterType = SeedType::SEED_NONE);

#pragma endregion

Expand Down
6 changes: 2 additions & 4 deletions include/Lunacy/Rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ class Sexy::Rect

Rect(N X = 0, N Y = 0, N W = 0, N H = 0)
{
mX = X;
mY = Y;
mW = W;
mH = H;
mPosition = Vector2<N>(0, 0);
mSize = Vector2<N>(0, 0);
}

Rect(Vector2<N> Position, Vector2<N> Size)
Expand Down
18 changes: 14 additions & 4 deletions include/Lunacy/Zombie.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ class Zombie : public GameObject
GetTrackPosition(TrackName, out.mX, out.mY);
return out;
}
int GetBobsledPosition();

void DropLoot();
void Die(bool DropLoot = true);
Expand Down Expand Up @@ -196,6 +197,9 @@ class Zombie : public GameObject
void ReanimIgnoreClipRect(const char* TrackName, bool DoIgnore = true);
void EnableClipping();
void LoadPlainZombieReanim();
void TrySpawnLevelAward();
void RemoveIceTrap();
void HitIceTrap();

void PickBungeeZombieTarget(int Column = -1);
void BungeeDropZombie(Zombie*, int Col, int Row);
Expand Down Expand Up @@ -258,6 +262,11 @@ class Zombie : public GameObject
void UpdateZombiePosition();
void UpdateZombieInChimney();
void UpdateZombieHighGround();
void UpdateZombieChimney();
void BossPlayIdle();
void DrawBossFireBall(Sexy::Graphics*);
void UpdateDamageStates(DamageFlag);
void UpdateActions();

bool IsTangleKelpTarget();
bool IsWalkingBackwards();
Expand All @@ -268,13 +277,14 @@ class Zombie : public GameObject
bool IsOnBoard();
bool IsFlying();

void DropShield();
void DropShield(DamageFlag);
void DropHelm(DamageFlag);
void DropHead(DamageFlag);
void DropArm(DamageFlag);
void DropFlag();
void DropPole();
void DropHead();
void DropArm();

bool CanTargetPlant(ZombieAttackType, Plant*);
bool CanTargetPlant(Plant*, ZombieAttackType = ZombieAttackType::ATTACKTYPE_CHEW);
Plant* FindPlantTarget(ZombieAttackType);
Zombie* FindZombieTarget();
void StartWalking(int BlendTime);
Expand Down
69 changes: 55 additions & 14 deletions src/Luna/Hook/LunaHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ class LunaHookThread::CodeBuffer
iPtr++;
}

void EncodeByte(char Value)
{
*cPtr = Value;
cPtr++;
}

void EncodePop(LunaHookThread::Register32 Reg)
{
*cPtr = (0x58 + Reg);
Expand Down Expand Up @@ -233,6 +239,26 @@ void LunaHookThread::Parameter::Encode(CodeBuffer* Buffer, char StackOffset)
Buffer->EncodeStackPush(mStackOffset + StackOffset);
}

char LunaHookThread::Parameter::EncodeIn(CodeBuffer* Buffer, char StackOffset)
{
if (isRegister)
{
Buffer->EncodeByte(0x8B);
Buffer->EncodeByte(0x44 + 0x8 * mRegister);
Buffer->EncodeByte(0x24);
Buffer->EncodeByte(StackOffset);
return 0x00;
}
else
{
Buffer->EncodeByte(0xFF);
Buffer->EncodeByte(0x74);
Buffer->EncodeByte(0x24);
Buffer->EncodeByte(StackOffset);
return 0x04;
}
}

void LunaHookThread::SetReturn(DWORD Value)
{
_registers[EAX] = Value;
Expand Down Expand Up @@ -443,20 +469,19 @@ void LunaHookThread::FunctionSignature::Finalize(void* DetourTo)
LunaHookThread::LunaWrapper LunaHookThread::FunctionSignature::AllocateWrapper()
{
/* Base Wrapper:
* push non-volatile registers (ebx, ebp, esi, edi) // Preserving non-volatile registers
* push non-volatile registers (ebx, ebp, esi, edi) // Preserving non-volatile registers (0x04)
*
* mov & push params in correct order // Moving and pushing function parameters
* push L0 // Pushing return address for cleanup (L0)
* mov & push params in correct order // Moving and pushing function parameters (_paramCodeSize)
* push L0 // Pushing return address for cleanup (L0) (0x05)
*
* original hook code // Executing the code that was overwritten
* original hook code // Executing the code that was overwritten (_origCodeSize)
*
* push funcaddr + hook code size // Pushing the address to return to after the original function call
* ret // Returning from the function
* push funcaddr + hook code size // Pushing the address to return to after the original function call (0x05)
* ret // Returning from the function (0x01)
*
* L0:
* pop non-volatile registers // Restoring the saved registers
* add esp PopBytes // Cleaning up the stack if necessary (for __stdcall convention)
* ret // Returning from the wrapper
* pop non-volatile registers // Restoring the saved registers (0x04)
* ret // Returning from the wrapper (0x01)
*/

// Unlock bytes near hook for execution
Expand All @@ -468,8 +493,11 @@ LunaHookThread::LunaWrapper LunaHookThread::FunctionSignature::AllocateWrapper()
// Backup the original code
memcpy(_origCode, (const void*)_addr, _origCodeSize);

// Calculate _paramCodeSize
_paramCodeSize = _paramCount * 4;

// Calculate the total size of the generated wrapper
size_t WrapperSize = 0x20 + _paramCodeSize + _origCodeSize; // Base size + params + original overwritten code
size_t WrapperSize = 0x0F + _paramCodeSize + _origCodeSize; // Base size + params + original overwritten code
CodeBuffer Wrapper(WrapperSize);

// 1. Push non-volatile registers (ebx, ebp, esi, edi)
Expand All @@ -480,17 +508,23 @@ LunaHookThread::LunaWrapper LunaHookThread::FunctionSignature::AllocateWrapper()

// 2. Push all parameters in reverse order (stack parameters first, then registers)
int cParam = _paramCount - 1;
size_t StackOffset = 0;
size_t StackOffset = 0x14;// non-volatile registers padded the stack by 0x10 bytes. Return address +0x04 bytes.
while (cParam >= 0)
{
// Param = StackOffset + 0x4 * ParamIndex
size_t ParamLocation = StackOffset + (0x04 * cParam);// Location of the parameter on the stack
auto aParam = _parameters[cParam];
aParam.Encode(&Wrapper, StackOffset);
StackOffset += 0x4;
StackOffset += aParam.EncodeIn(&Wrapper, ParamLocation);
cParam--;

// aParam._isRegister:
// Encodes a mov reg, [esp + ParamLocation] and returns 0
// else:
// Encodes a push [esp + ParamLocation] and returns 4
}

// 3. Push L0 (return address for cleanup after function call)
Wrapper.EncodePush(Wrapper.oPtr + 0x10 + _paramCodeSize);
Wrapper.EncodePush(Wrapper.oPtr + 0x0F + _paramCodeSize + _origCodeSize);

// 4. Copy the original code (that was overwritten by the hook) into the wrapper
Wrapper.Copy(_origCode, _origCodeSize);
Expand All @@ -512,4 +546,11 @@ LunaHookThread::LunaWrapper LunaHookThread::FunctionSignature::AllocateWrapper()

// Return the wrapper function (cast it as a LunaWrapper function pointer)
return (LunaWrapper)Wrapper.oPtr;
}

LunaHookThread::LunaWrapper LunaHookThread::FunctionSignature::FinalizeAndWrap(void* DetourTo)
{
auto Wrapper = AllocateWrapper();
Finalize(DetourTo);
return Wrapper;
}
Loading

0 comments on commit 7b71cbb

Please sign in to comment.