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 "StoredCar.h"
#include "SVF.h" #include "SVF.h"
#include "ParseUtils.hpp" #include "ParseUtils.hpp"
#include "Random.h"
#include "Utils/DelimStringReader.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 ============= // ============= Delayed patches =============
namespace DelayedPatches namespace DelayedPatches
{ {
@ -336,7 +317,7 @@ namespace Common {
// Fix various randomness factors expecting 16-bit rand() // Fix various randomness factors expecting 16-bit rand()
{ {
// Treat each instance separately // Treat each instance separately
using namespace Rand16bit; using namespace ConsoleRandomness;
// Script randomness // Script randomness
try try
@ -346,7 +327,10 @@ namespace Common {
get_pattern("E8 ? ? ? ? 25 FF FF 00 00 89 84 24 ? ? ? ? 30 C0"), 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(); TXN_CATCH();
@ -358,7 +342,10 @@ namespace Common {
get_pattern("E8 ? ? ? ? 66 83 F8 14"), get_pattern("E8 ? ? ? ? 66 83 F8 14"),
}; };
HookEach_Rand_PedChat(rands, InterceptCall); for (void* rand : rands)
{
InjectHook(rand, rand16);
}
} }
TXN_CATCH(); 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\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" /> <ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\ParseUtils.hpp" /> <ClInclude Include="..\SilentPatch\ParseUtils.hpp" />
<ClInclude Include="..\SilentPatch\Random.h" />
<ClInclude Include="..\SilentPatch\StdAfx.h" /> <ClInclude Include="..\SilentPatch\StdAfx.h" />
<ClInclude Include="..\SilentPatch\StoredCar.h" /> <ClInclude Include="..\SilentPatch\StoredCar.h" />
<ClInclude Include="..\SilentPatch\SVF.h" /> <ClInclude Include="..\SilentPatch\SVF.h" />

View file

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

View file

@ -18,6 +18,7 @@
#include "PNGFile.h" #include "PNGFile.h"
#include "PlayerInfoSA.h" #include "PlayerInfoSA.h"
#include "FireManagerSA.h" #include "FireManagerSA.h"
#include "Random.h"
#include "WaveDecoderSA.h" #include "WaveDecoderSA.h"
#include "FLACDecoderSA.h" #include "FLACDecoderSA.h"
@ -894,15 +895,6 @@ int NewFrameRender(int nEvent, void* pParam)
return RsEventHandler(nEvent, 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 }); auto FlushSpriteBuffer = AddressByVersion<void(*)()>(0x70CF20, 0x70D750, 0x7591E0, { "85 C0 0F 8E ? ? ? ? 83 3D", -5 });
void FlushLensSwitchZ( RwRenderState rwa, void* rwb ) void FlushLensSwitchZ( RwRenderState rwa, void* rwb )
{ {
@ -1630,7 +1622,7 @@ namespace VariableResets
T m_timer; T m_timer;
TimeNextMadDriverChaseCreated_t() 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 }); Patch(0x61ECE2, { 0x84, 0xC0, 0x74 });
// Proper randomizations // Proper randomizations
InjectHook(0x44E82E, Int32Rand); // Missing ped paths {
InjectHook(0x44ECEE, Int32Rand); // Missing ped paths using namespace ConsoleRandomness;
InjectHook(0x666EA0, Int32Rand); // Prostitutes
InjectHook(0x44E82E, rand31); // Missing ped paths
InjectHook(0x44ECEE, rand31); // Missing ped paths
InjectHook(0x666EA0, rand31); // Prostitutes
}
// Help boxes showing with big message // Help boxes showing with big message
// Game seems to assume they can show together // Game seems to assume they can show together
@ -5624,9 +5620,13 @@ void Patch_SA_11()
Patch(0x61F502, { 0x84, 0xC0, 0x74 }); Patch(0x61F502, { 0x84, 0xC0, 0x74 });
// Proper randomizations // Proper randomizations
InjectHook(0x44E8AE, Int32Rand); // Missing ped paths {
InjectHook(0x44ED6E, Int32Rand); // Missing ped paths using namespace ConsoleRandomness;
InjectHook(0x6676C0, Int32Rand); // Prostitutes
InjectHook(0x44E8AE, rand31); // Missing ped paths
InjectHook(0x44ED6E, rand31); // Missing ped paths
InjectHook(0x6676C0, rand31); // Prostitutes
}
// Help boxes showing with big message // Help boxes showing with big message
// Game seems to assume they can show together // 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 // REMOVED - the fix pointed at some unrelated instruction anyway? I think it never worked
// Proper randomizations // Proper randomizations
InjectHook(0x452CCF, Int32Rand); // Missing ped paths {
InjectHook(0x45322C, Int32Rand); // Missing ped paths using namespace ConsoleRandomness;
InjectHook(0x690263, Int32Rand); // Prostitutes
InjectHook(0x452CCF, rand31); // Missing ped paths
InjectHook(0x45322C, rand31); // Missing ped paths
InjectHook(0x690263, rand31); // Prostitutes
}
// Help boxes showing with big message // Help boxes showing with big message
// Game seems to assume they can show together // Game seems to assume they can show together
@ -6288,14 +6292,16 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
// Proper randomizations // Proper randomizations
try try
{ {
using namespace ConsoleRandomness;
auto pedsRand = pattern( "C1 F8 06 99" ).count(2); auto pedsRand = pattern( "C1 F8 06 99" ).count(2);
void* prostitutesRand = get_pattern( "8B F8 32 C0", -5 ); void* prostitutesRand = get_pattern( "8B F8 32 C0", -5 );
pedsRand.for_each_result( []( pattern_match match ) { 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(); 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\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" /> <ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\ParseUtils.hpp" /> <ClInclude Include="..\SilentPatch\ParseUtils.hpp" />
<ClInclude Include="..\SilentPatch\Random.h" />
<ClInclude Include="..\SilentPatch\resource1.h" /> <ClInclude Include="..\SilentPatch\resource1.h" />
<ClInclude Include="..\SilentPatch\RWUtils.hpp" /> <ClInclude Include="..\SilentPatch\RWUtils.hpp" />
<ClInclude Include="..\SilentPatch\SVF.h" /> <ClInclude Include="..\SilentPatch\SVF.h" />

View file

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

View file

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

View file

@ -7,6 +7,7 @@
#include "Utils/DelimStringReader.h" #include "Utils/DelimStringReader.h"
#include "PlayerInfoSA.h" #include "PlayerInfoSA.h"
#include "ParseUtils.hpp" #include "ParseUtils.hpp"
#include "Random.h"
#include "SVF.h" #include "SVF.h"
@ -122,7 +123,7 @@ void (CPlane::*CPlane::orgPlanePreRender)();
static int32_t random(int32_t from, int32_t to) 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 ) static RwObject* GetCurrentAtomicObject( RwFrame* frame )

View file

@ -11,6 +11,7 @@
#include "RWUtils.hpp" #include "RWUtils.hpp"
#include "TheFLAUtils.h" #include "TheFLAUtils.h"
#include "ParseUtils.hpp" #include "ParseUtils.hpp"
#include "Random.h"
#include <array> #include <array>
#include <memory> #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 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 // The functionality was never broken on PC - but the random distribution seemingly made it looks as if it was
try 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); 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(); TXN_CATCH();

View file

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

View file

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