Skip to content

Commit b65e9d2

Browse files
committed
Fix late-game crash on 1.0.3570.0
* The solomon1 nop was split between two different code pages. Trying to memset it resulted in memory access violation. * YscUtils now use the ip offset instead of a raw pointer to support access across multiple code pages.
1 parent 1bd6d05 commit b65e9d2

File tree

11 files changed

+108
-34
lines changed

11 files changed

+108
-34
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ if (MSVC_VERSION GREATER_EQUAL "1900")
1414
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
1515
endif()
1616

17-
set (CMAKE_CXX_STANDARD 17)
17+
set (CMAKE_CXX_STANDARD 23)
1818

1919
# Sources
2020
include_directories(include lib src)

lib/CTheScripts.hh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,15 @@ public:
205205
{
206206
NativeManager::HookNative (hash, func);
207207
}
208+
209+
void
210+
Disable ()
211+
{
212+
NativeManager::HookNative (hash, [] (scrThread::Info *) {});
213+
}
208214
};
209215

210-
inline NativeWrapper operator"" _n (char const *s, size_t len)
216+
inline NativeWrapper operator""_n (char const *s, size_t len)
211217
{
212218
return NativeWrapper (
213219
rage::atLiteralStringHash (std::string_view (s, len)));

lib/rage.hh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ public:
187187
Vec4V pos;
188188
};
189189

190+
class Mat43V
191+
{
192+
public:
193+
Vec4V right;
194+
Vec4V up;
195+
Vec4V at;
196+
};
197+
190198
} // namespace rage
191199

192200
/* Not a part of rage */
@@ -214,7 +222,7 @@ public:
214222
}
215223
};
216224

217-
constexpr std::uint32_t operator"" _joaat (char const *s, size_t len)
225+
constexpr std::uint32_t operator""_joaat (char const *s, size_t len)
218226
{
219227
return rage::atLiteralStringHash (std::string_view (s, len), 0);
220228
}

lib/scrThread.hh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ struct scrProgram
201201
return *(T *) &(m_pCodeBlocks[offset / PAGE_SIZE][offset % PAGE_SIZE]);
202202
}
203203

204+
uint32_t
205+
GetPageSizeLeft (uint32_t offset)
206+
{
207+
return PAGE_SIZE - (offset % PAGE_SIZE);
208+
}
209+
204210
static inline int
205211
GetTotalPages (uint32_t size)
206212
{

src/common/ysc.hh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class YscCodeEdits
1111
{
1212
std::string Name;
1313
CodeEditFunction Function;
14+
bool Enabled;
1415
};
1516

1617
static std::vector<CodeEdit> &
@@ -30,6 +31,9 @@ class YscCodeEdits
3031

3132
for (const auto &i : GetEdits ())
3233
{
34+
if (!i.Enabled)
35+
continue;
36+
3337
if (!i.Function (utils))
3438
continue;
3539

@@ -43,10 +47,10 @@ class YscCodeEdits
4347

4448
public:
4549
static void
46-
Add (std::string_view name, CodeEditFunction f)
50+
Add (std::string_view name, CodeEditFunction f, bool enabled = true)
4751
{
4852
Initialise ();
49-
GetEdits ().push_back ({std::string (name), f});
53+
GetEdits ().push_back ({std::string (name), f, enabled});
5054
}
5155

5256
static void
@@ -57,4 +61,6 @@ public:
5761
REGISTER_HOOK ("8b cb e8 ? ? ? ? 8b 43 70 ? 03 c4 a9 00 c0 ff ff",
5862
2, ApplyCodeFixes, bool, scrProgram *);
5963
}
64+
65+
friend class CodeEditDebugInterface;
6066
};

src/misc/credits.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class RainbomizerCredits
5353

5454
auto GetCreditItems ()
5555
{
56-
return CCreditArray::sm_Instance->GetCreditItems();
56+
return CCreditArray::sm_Instance->GetCreditItems ();
5757
}
5858

5959
public:

src/mission/missions_Code.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,13 @@ MissionRandomizer_CodeFixes::ApplyPrepNoRepeatFix (YscUtilsOps &utils)
129129
if (!utils.IsAnyOf ("replay_controller"_joaat))
130130
return false;
131131

132+
uint8_t shellCode[]
133+
= {utils.OpCode(PUSH_CONST_1), utils.OpCode(LEAVE), 0x0, 0x1};
134+
132135
utils.Init ("2d 00 03 00 ? 6e 5d ? ? ? 06 56 ? ? 5d ? ? ? 6f");
133-
utils.Write (/*Offset=*/11, utils.OpCode(J));
136+
utils.WriteBytes (/*Offset=*/5, shellCode);
137+
138+
//utils.Write (/*Offset=*/11, utils.OpCode(J));
134139

135140
return true;
136141
}
@@ -166,13 +171,13 @@ MissionRandomizer_CodeFixes::ApplySolomonCamFix (YscUtilsOps &utils)
166171
return false;
167172

168173
utils.Init ("5d ? ? ? 2c ? ? ? 51 ? ? 50");
169-
auto nopEnd = utils.Get<uint8_t> (11);
174+
auto nopEnd = utils.GetWorkingIp () + 11;
170175

171176
utils.Init ("29 00 00 48 42 6e 70 2c");
172-
utils.NOP (/*Offset=*/7, /*Size=*/nopEnd - utils.Get<uint8_t> (7));
177+
utils.NOP (/*Offset=*/7, /*Size=*/nopEnd - utils.GetWorkingIp() + 7);
173178

174179
Rainbomizer::Logger::LogMessage ("solomon1 nop size: %d",
175-
nopEnd - utils.Get<uint8_t> (7));
180+
nopEnd - utils.GetWorkingIp() + 7);
176181

177182
return true;
178183
}

src/mission/missions_YscUtils.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ YscUtils::FindCodePattern (std::string_view pattern_str,
3131
});
3232
}
3333

34+
/*******************************************************/
35+
void
36+
YscUtils::FindCodePattern (std::string_view pattern_str,
37+
std::function<void (uint32_t)> CB, bool translate)
38+
{
39+
m_pProgram->ForEachCodePage ([&] (int blockId, uint8_t *block,
40+
size_t size) {
41+
auto pattern
42+
= hook::make_range_pattern (uintptr_t (block),
43+
uintptr_t (block) + size, pattern_str);
44+
45+
// Translate patterns to new version
46+
auto &bytes = pattern.getBytes ();
47+
for (size_t offset = 0; translate && offset < bytes.size (); offset++)
48+
{
49+
auto instSize = scrThread::FindInstSize (bytes.data () + offset,
50+
bytes.size ());
51+
52+
bytes[offset] = OpCode (YscOpCode (bytes[offset]));
53+
54+
offset += instSize - 1;
55+
}
56+
57+
pattern.for_each_result (
58+
[CB, block, blockId] (hook::pattern_match match) {
59+
CB (blockId * scrProgram::PAGE_SIZE
60+
+ (match.get<unsigned char> () - block));
61+
});
62+
});
63+
}
64+
3465
/*******************************************************/
3566
void
3667
YscUtils::FindString (const char *str, void (*CB) (char *))

src/mission/missions_YscUtils.hh

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public:
3333
std::function<void (hook::pattern_match)> CB,
3434
bool translate = true);
3535

36+
void FindCodePattern (std::string_view pattern,
37+
std::function<void (uint32_t)> CB,
38+
bool translate = true);
39+
3640
void FindString (const char *str, void (*CB) (char *));
3741

3842
template <typename... Args>
@@ -371,7 +375,7 @@ public:
371375
class YscUtilsOps : public YscUtils
372376
{
373377
bool bOperationFailed = false;
374-
uint8_t *pPatternResult = nullptr;
378+
uint32_t nPatternResultIp = -1u;
375379

376380
public:
377381
using YscUtils::YscUtils;
@@ -380,29 +384,24 @@ public:
380384
void
381385
Init (std::string_view pattern, bool translate = true)
382386
{
383-
uint8_t *ptr = nullptr;
384-
FindCodePattern (pattern, [&ptr] (hook::pattern_match m) {
385-
if (!ptr)
386-
ptr = m.get<uint8_t> (0);
387-
});
388-
389-
pPatternResult = ptr;
387+
nPatternResultIp = -1u;
388+
FindCodePattern (pattern, [this] (uint32_t match) {
389+
if (nPatternResultIp == -1u)
390+
nPatternResultIp = match;
391+
}, translate);
390392
}
391393

392394
/* Initialise the UtilsOps to a certain pattern for further operations */
393395
void
394396
Init (uint32_t ip)
395397
{
396-
uint8_t *ptr = &GetProgram ()->GetCodeByte<uint8_t> (ip);
397-
pPatternResult = ptr;
398+
nPatternResultIp = ip;
398399
}
399400

400401
uint32_t
401402
GetWorkingIp ()
402403
{
403-
if (pPatternResult)
404-
return GetCodeOffset (pPatternResult);
405-
return -1u;
404+
return nPatternResultIp;
406405
}
407406

408407
/* Reinitialises the UtilsOps to the branch destination at offset of stored
@@ -414,8 +413,7 @@ public:
414413
{
415414
// Absolute offset
416415
case YscOpCode::CALL:
417-
pPatternResult = &GetProgram ()->GetCodeByte<uint8_t> (
418-
(*Get<uint32_t> (offset) >> 8));
416+
nPatternResultIp = (*Get<uint32_t> (offset) >> 8);
419417
break;
420418

421419
// Relative offset
@@ -427,7 +425,7 @@ public:
427425
case YscOpCode::IGE_JZ:
428426
case YscOpCode::ILT_JZ:
429427
case YscOpCode::ILE_JZ:
430-
pPatternResult += *Get<uint16_t> (offset + 1) + (offset + 3);
428+
nPatternResultIp += *Get<uint16_t> (offset + 1) + (offset + 3);
431429
break;
432430

433431
default: bOperationFailed = true; break;
@@ -439,24 +437,37 @@ public:
439437
T *
440438
Get (int64_t offset)
441439
{
442-
return reinterpret_cast<T *> (pPatternResult + offset);
440+
return &GetProgram ()->GetCodeByte<T> (nPatternResultIp + offset);
443441
}
444442

445443
/* Makes a NOP at offset of size */
446444
void
447445
NOP (int64_t offset, size_t size)
448446
{
449-
if (!pPatternResult)
447+
if (nPatternResultIp == -1u)
450448
return void (bOperationFailed = true);
451-
memset (pPatternResult + offset, uint8_t (YscOpCode::NOP), size);
449+
450+
while (size != 0)
451+
{
452+
size_t nopSize
453+
= std::min (size_t (GetProgram ()->GetPageSizeLeft (
454+
nPatternResultIp + offset)),
455+
size);
456+
457+
memset (Get<uint8_t> (offset), uint8_t (YscOpCode::NOP),
458+
nopSize);
459+
460+
size -= nopSize;
461+
offset += nopSize;
462+
}
452463
}
453464

454465
/* Writes a value of type T at offset */
455466
template <typename T>
456467
void
457468
Write (int64_t offset, T value)
458469
{
459-
if (!pPatternResult)
470+
if (nPatternResultIp == -1u)
460471
return void (bOperationFailed = true);
461472
*Get<T> (offset) = value;
462473
}
@@ -465,13 +476,13 @@ public:
465476
void
466477
WriteBytes (int64_t offset, const T &bytes)
467478
{
468-
if (!pPatternResult)
479+
if (nPatternResultIp == -1u)
469480
return void (bOperationFailed = true);
470-
memcpy (pPatternResult + offset, &bytes[0], std::size (bytes));
481+
memcpy (Get<uint8_t> (offset), &bytes[0], std::size (bytes));
471482
}
472483

473484
explicit operator bool () const
474485
{
475-
return bOperationFailed || !pPatternResult;
486+
return bOperationFailed || nPatternResultIp == -1u;
476487
}
477488
};

src/vehicles/vehicle_cacheMgr.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdio.h>
99

1010
const uint32_t CacheVersion = 1;
11+
std::unique_ptr<VehicleModelInfoCacheMgr> VehicleModelInfoCacheMgr::sm_Instance;
1112

1213
/*******************************************************/
1314
bool

0 commit comments

Comments
 (0)