Unify randomness fixes to use PS2-like 31-bit rand

This commit is contained in:
Silent 2024-05-21 18:34:44 +02:00
parent a69eca64ef
commit b76637d391
No known key found for this signature in database
GPG Key ID: AE53149BB0C45AF1
12 changed files with 82 additions and 61 deletions

View File

@ -6,6 +6,7 @@
#include "StoredCar.h"
#include "SVF.h"
#include "ParseUtils.hpp"
#include "Random.h"
#include "Utils/DelimStringReader.h"
@ -151,26 +152,6 @@ namespace ExtraCompSpecularity
}
}
// ============= Make script randomness 16-bit, like on PS2 =============
namespace Rand16bit
{
template<std::size_t Index>
static int (*orgRand)();
template<std::size_t Index>
static int rand16bit()
{
const int bottomBits = orgRand<Index>();
const int topBit = (orgRand<Index>() & 1) << 15;
return bottomBits | topBit;
}
HOOK_EACH_FUNC_CTR(Rand_Script, 0, orgRand, rand16bit);
HOOK_EACH_FUNC_CTR(Rand_PedChat, 1, orgRand, rand16bit);
}
// ============= Delayed patches =============
namespace DelayedPatches
{
@ -336,7 +317,7 @@ namespace Common {
// Fix various randomness factors expecting 16-bit rand()
{
// Treat each instance separately
using namespace Rand16bit;
using namespace ConsoleRandomness;
// Script randomness
try
@ -346,7 +327,10 @@ namespace Common {
get_pattern("E8 ? ? ? ? 25 FF FF 00 00 89 84 24 ? ? ? ? 30 C0"),
};
HookEach_Rand_Script(rands, InterceptCall);
for (void* rand : rands)
{
InjectHook(rand, rand16);
}
}
TXN_CATCH();
@ -358,7 +342,10 @@ namespace Common {
get_pattern("E8 ? ? ? ? 66 83 F8 14"),
};
HookEach_Rand_PedChat(rands, InterceptCall);
for (void* rand : rands)
{
InjectHook(rand, rand16);
}
}
TXN_CATCH();
}

27
SilentPatch/Random.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include <cstdint>
#include <ctime>
namespace ConsoleRandomness
{
// PS2 implementation of rand()
inline uint64_t seed_rand_ps2 = std::time(nullptr);
inline int rand31()
{
seed_rand_ps2 = 0x5851F42D4C957F2D * seed_rand_ps2 + 1;
return ((seed_rand_ps2 >> 32) & 0x7FFFFFFF);
}
// PS2 rand, but returning a 16-bit value
inline int rand16()
{
return rand31() & 0xFFFF;
}
// PS2 rand, but matching PC's RAND_MAX
inline int rand15()
{
return rand31() & 0x7FFF;
}
}

View File

@ -72,6 +72,7 @@
<ClInclude Include="..\SilentPatch\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\ParseUtils.hpp" />
<ClInclude Include="..\SilentPatch\Random.h" />
<ClInclude Include="..\SilentPatch\StdAfx.h" />
<ClInclude Include="..\SilentPatch\StoredCar.h" />
<ClInclude Include="..\SilentPatch\SVF.h" />

View File

@ -110,6 +110,9 @@
<ClInclude Include="..\SilentPatch\ParseUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\Random.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">

View File

@ -18,6 +18,7 @@
#include "PNGFile.h"
#include "PlayerInfoSA.h"
#include "FireManagerSA.h"
#include "Random.h"
#include "WaveDecoderSA.h"
#include "FLACDecoderSA.h"
@ -894,15 +895,6 @@ int NewFrameRender(int nEvent, void* pParam)
return RsEventHandler(nEvent, pParam);
}
#include <ctime>
#include <random>
static std::ranlux48 generator (time(nullptr));
int32_t Int32Rand()
{
return generator() & INT32_MAX;
}
auto FlushSpriteBuffer = AddressByVersion<void(*)()>(0x70CF20, 0x70D750, 0x7591E0, { "85 C0 0F 8E ? ? ? ? 83 3D", -5 });
void FlushLensSwitchZ( RwRenderState rwa, void* rwb )
{
@ -1630,7 +1622,7 @@ namespace VariableResets
T m_timer;
TimeNextMadDriverChaseCreated_t()
: m_timer( (static_cast<float>(Int32Rand()) / INT32_MAX) * 600.0f + 600.0f )
: m_timer( (static_cast<float>(ConsoleRandomness::rand31()) / INT32_MAX) * 600.0f + 600.0f )
{
}
};
@ -4628,9 +4620,13 @@ void Patch_SA_10(HINSTANCE hInstance)
Patch(0x61ECE2, { 0x84, 0xC0, 0x74 });
// Proper randomizations
InjectHook(0x44E82E, Int32Rand); // Missing ped paths
InjectHook(0x44ECEE, Int32Rand); // Missing ped paths
InjectHook(0x666EA0, Int32Rand); // Prostitutes
{
using namespace ConsoleRandomness;
InjectHook(0x44E82E, rand31); // Missing ped paths
InjectHook(0x44ECEE, rand31); // Missing ped paths
InjectHook(0x666EA0, rand31); // Prostitutes
}
// Help boxes showing with big message
// Game seems to assume they can show together
@ -5624,9 +5620,13 @@ void Patch_SA_11()
Patch(0x61F502, { 0x84, 0xC0, 0x74 });
// Proper randomizations
InjectHook(0x44E8AE, Int32Rand); // Missing ped paths
InjectHook(0x44ED6E, Int32Rand); // Missing ped paths
InjectHook(0x6676C0, Int32Rand); // Prostitutes
{
using namespace ConsoleRandomness;
InjectHook(0x44E8AE, rand31); // Missing ped paths
InjectHook(0x44ED6E, rand31); // Missing ped paths
InjectHook(0x6676C0, rand31); // Prostitutes
}
// Help boxes showing with big message
// Game seems to assume they can show together
@ -5937,9 +5937,13 @@ void Patch_SA_Steam()
// REMOVED - the fix pointed at some unrelated instruction anyway? I think it never worked
// Proper randomizations
InjectHook(0x452CCF, Int32Rand); // Missing ped paths
InjectHook(0x45322C, Int32Rand); // Missing ped paths
InjectHook(0x690263, Int32Rand); // Prostitutes
{
using namespace ConsoleRandomness;
InjectHook(0x452CCF, rand31); // Missing ped paths
InjectHook(0x45322C, rand31); // Missing ped paths
InjectHook(0x690263, rand31); // Prostitutes
}
// Help boxes showing with big message
// Game seems to assume they can show together
@ -6288,14 +6292,16 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
// Proper randomizations
try
{
using namespace ConsoleRandomness;
auto pedsRand = pattern( "C1 F8 06 99" ).count(2);
void* prostitutesRand = get_pattern( "8B F8 32 C0", -5 );
pedsRand.for_each_result( []( pattern_match match ) {
InjectHook( match.get<void>( -5 ), Int32Rand ); // Missing ped paths
InjectHook( match.get<void>( -5 ), rand31 ); // Missing ped paths
});
InjectHook( prostitutesRand, Int32Rand ); // Prostitutes
InjectHook( prostitutesRand, rand31 ); // Prostitutes
}
TXN_CATCH();

View File

@ -252,6 +252,7 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
<ClInclude Include="..\SilentPatch\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\ParseUtils.hpp" />
<ClInclude Include="..\SilentPatch\Random.h" />
<ClInclude Include="..\SilentPatch\resource1.h" />
<ClInclude Include="..\SilentPatch\RWUtils.hpp" />
<ClInclude Include="..\SilentPatch\SVF.h" />

View File

@ -170,6 +170,9 @@
<ClInclude Include="..\SilentPatch\ParseUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\Random.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">

View File

@ -28,7 +28,6 @@
extern void (*GTAdelete)(void* data);
extern const char* (*GetFrameNodeName)(RwFrame*);
extern RpHAnimHierarchy* (*GetAnimHierarchyFromSkinClump)(RpClump*);
int32_t Int32Rand();
RwObject* GetFirstObject(RwFrame* pFrame);
extern unsigned char& nGameClockDays;

View File

@ -7,6 +7,7 @@
#include "Utils/DelimStringReader.h"
#include "PlayerInfoSA.h"
#include "ParseUtils.hpp"
#include "Random.h"
#include "SVF.h"
@ -122,7 +123,7 @@ void (CPlane::*CPlane::orgPlanePreRender)();
static int32_t random(int32_t from, int32_t to)
{
return from + ( Int32Rand() % (to-from) );
return from + ( ConsoleRandomness::rand31() % (to-from) );
}
static RwObject* GetCurrentAtomicObject( RwFrame* frame )

View File

@ -11,6 +11,7 @@
#include "RWUtils.hpp"
#include "TheFLAUtils.h"
#include "ParseUtils.hpp"
#include "Random.h"
#include <array>
#include <memory>
@ -272,20 +273,6 @@ void __declspec(naked) AutoPilotTimerFix_VC()
}
// PS2 implementation of rand()
static uint64_t seed_rand_ps2 = time(nullptr);
static int rand_ps2()
{
seed_rand_ps2 = 0x5851F42D4C957F2D * seed_rand_ps2 + 1;
return ((seed_rand_ps2 >> 32) & 0x7FFFFFFF);
}
// PS2 rand, but matching PC's RAND_MAX
static int rand15_ps2()
{
return rand_ps2() & 0x7FFF;
}
namespace ZeroAmmoFix
{
@ -1718,8 +1705,10 @@ void Patch_VC_Common()
// The functionality was never broken on PC - but the random distribution seemingly made it looks as if it was
try
{
using namespace ConsoleRandomness;
auto busted_audio_rand = get_pattern("80 BB 48 01 00 00 00 0F 85 ? ? ? ? E8 ? ? ? ? 25 FF FF 00 00", 13);
InjectHook(busted_audio_rand, rand15_ps2);
InjectHook(busted_audio_rand, rand15);
}
TXN_CATCH();

View File

@ -171,6 +171,7 @@
<ClInclude Include="..\SilentPatch\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\ParseUtils.hpp" />
<ClInclude Include="..\SilentPatch\Random.h" />
<ClInclude Include="..\SilentPatch\RWUtils.hpp" />
<ClInclude Include="..\SilentPatch\StdAfx.h" />
<ClInclude Include="..\SilentPatch\StoredCar.h" />

View File

@ -69,6 +69,9 @@
<ClInclude Include="..\SilentPatch\ParseUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\Random.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\SilentPatch\Timer.cpp">