mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 13:57:05 +02:00
Entity limit 4x, replay crash guard, -map launch option, memory tools; pause-menu fixes
Memory - The entity and pending-update pages are four times the game's own size (524,288 slots), down from eight times. At eight, the game kept a 3.5 GB block for them that was fully in RAM on custom maps; the largest map load seen needs about 150,000 slots. The render-instance pool and spatial buckets stay at eight times. - The log has a "Memory:" line when the game's memory, the players in the session or the skaters built change: committed, in RAM, players, skaters built, player distance and map. - Console: `perf memory` lists the game's memory by block size. `perf memory mark` remembers it, and the next `perf memory` says what was added since. `perf memory trace` also records who asked for each block until `perf memory stop`. `perf memory big` lists the largest blocks with how much of each is in RAM and a sample of what is in them. RESKATE_MEMORY_TRACE=<megabytes|all> starts the trace with the game. Replay crash guard - The game's replay recorder crashes when its stream has no room for the next chunk: it writes to the chunk it was not given (Skate.exe+0x48efa34, crash reports of 2026-10-10). The function now runs under a handler that, for that one fault alone, returns as if no chunk was ended, and says so in the log. Any other fault still goes to the crash reporter. The skip path has not been triggered in testing. Launcher - `-map <name>` (also --map, -map=<name>) loads that map as soon as the game is up, named as the console's `load` names one. With --no-gui and no other options the launch still uses the saved launcher settings. Pause menu - The Multiplayer and Mod Options pages step aside while the game's side menu, or a screen opened from it such as Settings, is over them. They drew over both before. - A button still held when a page comes back is not a press on it: the Back that closed the side menu no longer dismissed the page as well. Multiplayer cosmetics - A player whose mods add or remove cosmetic slots (stickers, say) no longer has the whole outfit refused. Their items go to this game's slots by slot: a slot they lack stays empty, an item in a slot this game lacks is left out, and the log says how many of each.
This commit is contained in:
1 parent
5b7395c3ac
commit
f289666c2c
26 files changed
+1107
-446
No files matched your search
@@ -144,6 +144,39 @@ std::uint64_t offline_steam_id() noexcept {
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
namespace {
|
||||
bool map_option(std::wstring_view argument) {
|
||||
return argument == L"-map" || argument == L"--map" || argument.starts_with(L"-map=") || argument.starts_with(L"--map=");
|
||||
}
|
||||
// The name goes into a console command the game runs: one line of plain text.
|
||||
std::wstring map_name(std::wstring_view value) {
|
||||
while (!value.empty() && value.front() == L' ') value.remove_prefix(1);
|
||||
while (!value.empty() && value.back() == L' ') value.remove_suffix(1);
|
||||
if (value.empty() || value.size() > 96) fail("-map requires a map's name, at most 96 characters");
|
||||
for (const auto character : value)
|
||||
if (character < 0x20 || character > 0x7e || character == L';' || character == L'"')
|
||||
fail("-map takes a map's name in plain letters, digits and spaces");
|
||||
return std::wstring(value);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::wstring take_map_option(std::vector<std::wstring>& arguments) {
|
||||
std::wstring map;
|
||||
for (std::size_t index = 0; index < arguments.size();) {
|
||||
const std::wstring_view argument(arguments[index]);
|
||||
if (!map_option(argument)) { ++index; continue; }
|
||||
const auto equals = argument.find(L'=');
|
||||
if (equals != std::wstring_view::npos) map = map_name(argument.substr(equals + 1));
|
||||
else {
|
||||
if (index + 1 == arguments.size()) fail("-map requires a map's name");
|
||||
map = map_name(arguments[index + 1]);
|
||||
arguments.erase(arguments.begin() + static_cast<std::ptrdiff_t>(index) + 1);
|
||||
}
|
||||
arguments.erase(arguments.begin() + static_cast<std::ptrdiff_t>(index));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
LaunchOptions parse_launch_options(const std::vector<std::wstring>& arguments) {
|
||||
LaunchOptions options;
|
||||
bool log_level_explicit = false;
|
||||
@@ -181,6 +214,15 @@ LaunchOptions parse_launch_options(const std::vector<std::wstring>& arguments) {
|
||||
if (!logging::parse_level(level)) fail("--log-level requires trace, debug, info, warning, error, critical, or off");
|
||||
options.log_level = std::move(level); log_level_explicit = true; continue;
|
||||
}
|
||||
if (map_option(argument)) {
|
||||
const auto equals = argument.find(L'=');
|
||||
if (equals != std::wstring_view::npos) options.map = map_name(argument.substr(equals + 1));
|
||||
else {
|
||||
if (++index == arguments.size()) fail("-map requires a map's name");
|
||||
options.map = map_name(arguments[index]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (argument == L"--gpu-diagnostics") { options.gpu_diagnostics = true; continue; }
|
||||
if (argument == L"--no-discord") { options.discord = false; continue; }
|
||||
const bool menu_key = argument.starts_with(L"--menu-key=");
|
||||
|
||||
@@ -52,12 +52,19 @@ struct LaunchOptions {
|
||||
unsigned menu_key{0x2D}; // VK_INSERT
|
||||
unsigned console_key{0xC0}; // VK_OEM_3, the key left of 1
|
||||
std::string log_level{"info"};
|
||||
// -map <name>: the map the game loads once it is up, named as the console's "load" names
|
||||
// one (a map's name, short name or asset path, or the start of one). Empty: none.
|
||||
std::wstring map;
|
||||
std::vector<std::wstring> game_arguments;
|
||||
};
|
||||
|
||||
// Arguments exclude argv[0]. Saved game display settings apply by default.
|
||||
// --windowed or an explicit width/height requests the windowed override.
|
||||
LaunchOptions parse_launch_options(const std::vector<std::wstring>& arguments);
|
||||
// Takes "-map <name>" (--map, -map=<name>) out of `arguments` and returns the name it gave,
|
||||
// checked as parse_launch_options checks it; empty when there is none. For a launch whose
|
||||
// other options come from somewhere else (the launcher's saved settings).
|
||||
std::wstring take_map_option(std::vector<std::wstring>& arguments);
|
||||
std::wstring windowed_arguments(const LaunchOptions& options);
|
||||
// Detect mods beside Skate.exe. Explicit game data paths take precedence.
|
||||
std::wstring mod_data_arguments(const std::filesystem::path& game_directory,
|
||||
|
||||
@@ -8,8 +8,11 @@ namespace dingosdk::game::build::v20260929::entity_pages {
|
||||
// EntityBus TransformSpace and property-space snapshots have 128 page pointers.
|
||||
// Slot 131072 formerly indexed pointer 128, overwriting snapshot bookkeeping.
|
||||
// Enlarge the leaf pages without changing owners, snapshots, IDs or their ABI.
|
||||
// Four times the game's 131,072 slots (it was eight until 2026-10-10): the largest map load
|
||||
// seen needed 150,152, and every page set the game keeps is this many times its own size,
|
||||
// whether a map uses it or not.
|
||||
inline constexpr std::size_t page_count = 128;
|
||||
inline constexpr unsigned page_shift = 13;
|
||||
inline constexpr unsigned page_shift = 12;
|
||||
inline constexpr std::size_t page_entries = std::size_t{1} << page_shift;
|
||||
inline constexpr std::size_t page_bytes = page_entries * sizeof(std::uint64_t);
|
||||
inline constexpr std::size_t capacity = page_count * page_entries;
|
||||
@@ -17,13 +20,14 @@ inline constexpr std::size_t capacity = page_count * page_entries;
|
||||
// object addresses. Grow its 464-byte-record pages without changing that ABI.
|
||||
inline constexpr unsigned render_instance_page_shift = 11;
|
||||
inline constexpr std::size_t render_instance_page_bytes = (std::size_t{1} << render_instance_page_shift) * 0x1d0;
|
||||
static_assert((512u << render_instance_page_shift) == capacity);
|
||||
// (Left at eight times the game's: its pages are its own, by its own shift.)
|
||||
static_assert((512u << render_instance_page_shift) >= capacity);
|
||||
static_assert(render_instance_page_bytes == 0xe8000);
|
||||
// The cull-ID list and this separate monotonic bounds arena must both fit the
|
||||
// city. Retail config can override GridSize after Game.cfg has been processed.
|
||||
// Preserve native allocation/reset ownership and any larger configured value.
|
||||
inline constexpr std::size_t spatial_arena_min_bytes = 128 * 1024 * 1024;
|
||||
static_assert(capacity == 1'048'576 && page_bytes == 65'536);
|
||||
static_assert(capacity == 524'288 && page_bytes == 32'768);
|
||||
|
||||
enum class Kind {
|
||||
index_shift, page_bytes, page_entries, spatial_arena_bytes,
|
||||
@@ -67,303 +71,303 @@ inline constexpr Patch patches[]{
|
||||
patch(0x050e244d, Kind::render_instance_pages, "41b800a00300", "41b800800e00"),
|
||||
patch(0x050e245b, Kind::render_instance_pages, "c1e309", "c1e30b"),
|
||||
patch(0x0489ee29, Kind::spatial_arena_bytes, "bb00001000", "bb00000008"),
|
||||
patch(0x048a5e2c, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048a5e31, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x048a5fec, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048a6015, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x048b2713, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x048b271c, Kind::index_shift, "41c1e00a", "41c1e00d"),
|
||||
patch(0x048b27b6, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048b27c4, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048b292a, Kind::index_shift, "41c1ea0a", "41c1ea0d"),
|
||||
patch(0x048b2935, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048b3816, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x048b3823, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x048b5112, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x048b5122, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x048b51a2, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x048b51b2, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x048b52d6, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048b52dd, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048b53cc, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048b53d3, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048b5692, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x048b56a2, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x048b57a9, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048b57b0, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048b58b6, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048b58bd, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048b7ed4, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x048b7ef5, Kind::index_shift, "41c1e00a", "41c1e00d"),
|
||||
patch(0x048b8530, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048b8556, Kind::index_shift, "41c1e20a", "41c1e20d"),
|
||||
patch(0x048b9879, Kind::page_entries, "81c600040000", "81c600200000"),
|
||||
patch(0x048b9881, Kind::page_bytes, "488daf00200000", "488daf00000100"),
|
||||
patch(0x048b99d8, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x048b99e4, Kind::page_bytes, "498dbe00200000", "498dbe00000100"),
|
||||
patch(0x048bb417, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x048bb41f, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x048bb76a, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bb771, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bb83a, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bb841, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bb8fa, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bb901, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bb9b9, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bb9c0, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bba89, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bba90, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bbb89, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bbb90, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bbc4b, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bbc52, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bbd39, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bbd40, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bbf26, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bbf2d, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bd05e, Kind::page_bytes, "b900200000", "b900000100"),
|
||||
patch(0x048bd06d, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048bd42b, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bd432, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048bd516, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048bd51d, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048c019e, Kind::page_entries, "4181c600040000", "4181c600200000"),
|
||||
patch(0x048c01a7, Kind::page_bytes, "4c8da500200000", "4c8da500000100"),
|
||||
patch(0x048c024e, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x048c025a, Kind::page_bytes, "4c8dad00200000", "4c8dad00000100"),
|
||||
patch(0x048c069c, Kind::page_entries, "81c500040000", "81c500200000"),
|
||||
patch(0x048c06a4, Kind::page_bytes, "4c8db600200000", "4c8db600000100"),
|
||||
patch(0x048c07f8, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x048c0804, Kind::page_bytes, "498dbe00200000", "498dbe00000100"),
|
||||
patch(0x048c3942, Kind::page_bytes, "b900200000", "b900000100"),
|
||||
patch(0x048c394f, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c39bb, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x048c39c0, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x048c4fbd, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x048c4fc5, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x048c50cf, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x048c50d6, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048c5d01, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x048c5d06, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x048c5e1c, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c5e53, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c5e8d, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c5ec7, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c5f01, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c5f3b, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c5f75, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c5faf, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x048c703c, Kind::index_shift, "c1ea0a", "c1ea0d"),
|
||||
patch(0x048c7049, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ea3670, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ea3692, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ea3b1d, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ea3b42, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04ea3bd0, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ea3bf8, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04ec12e3, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ec12eb, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ec13c7, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ec13d5, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04ec2b13, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ec2b1b, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ec2bf7, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ec2c05, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04ec2dc6, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ec2dce, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ec2eb7, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ec2ec5, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04ed56e9, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ed56ef, Kind::index_shift, "41c1e20a", "41c1e20d"),
|
||||
patch(0x04ed7296, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ed72bb, Kind::index_shift, "41c1e20a", "41c1e20d"),
|
||||
patch(0x04ed78d3, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ed78f8, Kind::index_shift, "41c1e20a", "41c1e20d"),
|
||||
patch(0x04edde6d, Kind::page_entries, "81c500040000", "81c500200000"),
|
||||
patch(0x04edde78, Kind::page_bytes, "4c8dbf00200000", "4c8dbf00000100"),
|
||||
patch(0x04eddff8, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x04ede004, Kind::page_bytes, "498dbe00200000", "498dbe00000100"),
|
||||
patch(0x04edf33d, Kind::page_entries, "81c500040000", "81c500200000"),
|
||||
patch(0x04edf348, Kind::page_bytes, "4c8dbf00200000", "4c8dbf00000100"),
|
||||
patch(0x04edf508, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x04edf514, Kind::page_bytes, "498dbe00200000", "498dbe00000100"),
|
||||
patch(0x04edf719, Kind::page_entries, "81c600040000", "81c600200000"),
|
||||
patch(0x04edf724, Kind::page_bytes, "488daf00200000", "488daf00000100"),
|
||||
patch(0x04edf888, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x04edf894, Kind::page_bytes, "498dbe00200000", "498dbe00000100"),
|
||||
patch(0x04ee3b47, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ee3b4f, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ee4c77, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ee4c7f, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ee4f47, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ee4f4f, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04ee7daa, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04ee7db9, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04eeb19e, Kind::page_bytes, "b900200000", "b900000100"),
|
||||
patch(0x04eeb1ad, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04eeba26, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eeba2d, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eec74e, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eec755, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eec8ac, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eec8b3, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eecd45, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x04eecd58, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04eece4d, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04eece6e, Kind::index_shift, "41c1e00a", "41c1e00d"),
|
||||
patch(0x04eecf6d, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eecf74, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eed0a0, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eed0a7, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eed221, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eed228, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eed31c, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eed323, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eed468, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04eed474, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eed6a0, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eed6a7, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eed869, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eed870, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eed9f4, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eed9fb, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eee208, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x04eee21b, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04eee292, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x04eee2a5, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04eee328, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x04eee33b, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04eee3b2, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x04eee3c5, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04eee432, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x04eee445, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04eee4a2, Kind::index_shift, "41c1e80a", "41c1e80d"),
|
||||
patch(0x04eee4b5, Kind::index_shift, "c1e00a", "c1e00d"),
|
||||
patch(0x04eee60a, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04eee62b, Kind::index_shift, "41c1e00a", "41c1e00d"),
|
||||
patch(0x04eee72f, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eee736, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eee89f, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eee8a6, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eeea0a, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eeea11, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eeecbe, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eeecc5, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eeede9, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eeedf0, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eef06f, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef076, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eef15d, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef164, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04eef214, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef21b, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef0113, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef011a, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef5deb, Kind::page_entries, "4181c700040000", "4181c700200000"),
|
||||
patch(0x04ef5df7, Kind::page_bytes, "498db600200000", "498db600000100"),
|
||||
patch(0x04ef5f89, Kind::page_entries, "4181c700040000", "4181c700200000"),
|
||||
patch(0x04ef5f95, Kind::page_bytes, "498db600200000", "498db600000100"),
|
||||
patch(0x04ef60ae, Kind::page_entries, "4181c500040000", "4181c500200000"),
|
||||
patch(0x04ef60ba, Kind::page_bytes, "4d8dbe00200000", "4d8dbe00000100"),
|
||||
patch(0x04efc57b, Kind::page_entries, "4181c700040000", "4181c700200000"),
|
||||
patch(0x04efc587, Kind::page_bytes, "498db600200000", "498db600000100"),
|
||||
patch(0x04efc729, Kind::page_entries, "4181c700040000", "4181c700200000"),
|
||||
patch(0x04efc735, Kind::page_bytes, "498db600200000", "498db600000100"),
|
||||
patch(0x04efc858, Kind::page_entries, "4181c500040000", "4181c500200000"),
|
||||
patch(0x04efc864, Kind::page_bytes, "4d8dbe00200000", "4d8dbe00000100"),
|
||||
patch(0x04f097dc, Kind::page_entries, "4181c600040000", "4181c600200000"),
|
||||
patch(0x04f097e5, Kind::page_bytes, "4c8da500200000", "4c8da500000100"),
|
||||
patch(0x04f0988f, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x04f0989b, Kind::page_bytes, "4c8dad00200000", "4c8dad00000100"),
|
||||
patch(0x04f0b69c, Kind::page_entries, "81c500040000", "81c500200000"),
|
||||
patch(0x04f0b6a7, Kind::page_bytes, "4c8db600200000", "4c8db600000100"),
|
||||
patch(0x04f0b828, Kind::page_entries, "4181c400040000", "4181c400200000"),
|
||||
patch(0x04f0b834, Kind::page_bytes, "498dbe00200000", "498dbe00000100"),
|
||||
patch(0x04f16e2d, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f16e34, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f16ee4, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f16eeb, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f1700c, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f17013, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f172d4, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f172db, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f17618, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f1761f, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f19462, Kind::page_bytes, "b900200000", "b900000100"),
|
||||
patch(0x04f1946f, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f194db, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f194e0, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f19ca2, Kind::page_bytes, "b900200000", "b900000100"),
|
||||
patch(0x04f19caf, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f19d1b, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f19d20, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f19f22, Kind::page_bytes, "b900200000", "b900000100"),
|
||||
patch(0x04f19f2f, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f19f9b, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f19fa0, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f1e856, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f1e863, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f1e8f0, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f1e8f8, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f1ea31, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f1ea39, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f216fd, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f2170a, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f21796, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f2179e, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f218d6, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f218de, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f21f09, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f21f16, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f21fa2, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f21faa, Kind::index_shift, "c1e20a", "c1e20d"),
|
||||
patch(0x04f220e8, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f220f0, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f2b166, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f2b16b, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f2b2e4, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f2b2ec, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f2b38c, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2b3c3, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2b3fd, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2b437, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2b471, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2b4ab, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2b4e5, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2b51f, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2e6e6, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f2e6eb, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f2e877, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f2e87f, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f2e92c, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2e963, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2e99d, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2e9d7, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2ea11, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2ea4b, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2ea85, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2eabf, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2ec86, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f2ec8b, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f2ee27, Kind::index_shift, "c1e90a", "c1e90d"),
|
||||
patch(0x04f2ee2f, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f2eedc, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2ef13, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2ef4d, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2ef87, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2efc1, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2effb, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2f035, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f2f06f, Kind::page_bytes, "41b800200000", "41b800000100"),
|
||||
patch(0x04f34fea, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f34ff1, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f35b60, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f35b66, Kind::index_shift, "41c1e00a", "41c1e00d"),
|
||||
patch(0x04f38418, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f3841f, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f38958, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f3895f, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x04f38a78, Kind::index_shift, "c1e80a", "c1e80d"),
|
||||
patch(0x04f38a7f, Kind::index_shift, "c1e10a", "c1e10d"),
|
||||
patch(0x048a5e2c, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048a5e31, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x048a5fec, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048a6015, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x048b2713, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x048b271c, Kind::index_shift, "41c1e00a", "41c1e00c"),
|
||||
patch(0x048b27b6, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048b27c4, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048b292a, Kind::index_shift, "41c1ea0a", "41c1ea0c"),
|
||||
patch(0x048b2935, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048b3816, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x048b3823, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x048b5112, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x048b5122, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x048b51a2, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x048b51b2, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x048b52d6, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048b52dd, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048b53cc, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048b53d3, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048b5692, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x048b56a2, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x048b57a9, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048b57b0, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048b58b6, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048b58bd, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048b7ed4, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x048b7ef5, Kind::index_shift, "41c1e00a", "41c1e00c"),
|
||||
patch(0x048b8530, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048b8556, Kind::index_shift, "41c1e20a", "41c1e20c"),
|
||||
patch(0x048b9879, Kind::page_entries, "81c600040000", "81c600100000"),
|
||||
patch(0x048b9881, Kind::page_bytes, "488daf00200000", "488daf00800000"),
|
||||
patch(0x048b99d8, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x048b99e4, Kind::page_bytes, "498dbe00200000", "498dbe00800000"),
|
||||
patch(0x048bb417, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x048bb41f, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x048bb76a, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bb771, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bb83a, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bb841, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bb8fa, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bb901, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bb9b9, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bb9c0, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bba89, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bba90, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bbb89, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bbb90, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bbc4b, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bbc52, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bbd39, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bbd40, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bbf26, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bbf2d, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bd05e, Kind::page_bytes, "b900200000", "b900800000"),
|
||||
patch(0x048bd06d, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048bd42b, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bd432, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048bd516, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048bd51d, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048c019e, Kind::page_entries, "4181c600040000", "4181c600100000"),
|
||||
patch(0x048c01a7, Kind::page_bytes, "4c8da500200000", "4c8da500800000"),
|
||||
patch(0x048c024e, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x048c025a, Kind::page_bytes, "4c8dad00200000", "4c8dad00800000"),
|
||||
patch(0x048c069c, Kind::page_entries, "81c500040000", "81c500100000"),
|
||||
patch(0x048c06a4, Kind::page_bytes, "4c8db600200000", "4c8db600800000"),
|
||||
patch(0x048c07f8, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x048c0804, Kind::page_bytes, "498dbe00200000", "498dbe00800000"),
|
||||
patch(0x048c3942, Kind::page_bytes, "b900200000", "b900800000"),
|
||||
patch(0x048c394f, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c39bb, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x048c39c0, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x048c4fbd, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x048c4fc5, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x048c50cf, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x048c50d6, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x048c5d01, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x048c5d06, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x048c5e1c, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c5e53, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c5e8d, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c5ec7, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c5f01, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c5f3b, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c5f75, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c5faf, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x048c703c, Kind::index_shift, "c1ea0a", "c1ea0c"),
|
||||
patch(0x048c7049, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ea3670, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ea3692, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ea3b1d, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ea3b42, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04ea3bd0, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ea3bf8, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04ec12e3, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ec12eb, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ec13c7, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ec13d5, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04ec2b13, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ec2b1b, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ec2bf7, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ec2c05, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04ec2dc6, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ec2dce, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ec2eb7, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ec2ec5, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04ed56e9, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ed56ef, Kind::index_shift, "41c1e20a", "41c1e20c"),
|
||||
patch(0x04ed7296, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ed72bb, Kind::index_shift, "41c1e20a", "41c1e20c"),
|
||||
patch(0x04ed78d3, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ed78f8, Kind::index_shift, "41c1e20a", "41c1e20c"),
|
||||
patch(0x04edde6d, Kind::page_entries, "81c500040000", "81c500100000"),
|
||||
patch(0x04edde78, Kind::page_bytes, "4c8dbf00200000", "4c8dbf00800000"),
|
||||
patch(0x04eddff8, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x04ede004, Kind::page_bytes, "498dbe00200000", "498dbe00800000"),
|
||||
patch(0x04edf33d, Kind::page_entries, "81c500040000", "81c500100000"),
|
||||
patch(0x04edf348, Kind::page_bytes, "4c8dbf00200000", "4c8dbf00800000"),
|
||||
patch(0x04edf508, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x04edf514, Kind::page_bytes, "498dbe00200000", "498dbe00800000"),
|
||||
patch(0x04edf719, Kind::page_entries, "81c600040000", "81c600100000"),
|
||||
patch(0x04edf724, Kind::page_bytes, "488daf00200000", "488daf00800000"),
|
||||
patch(0x04edf888, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x04edf894, Kind::page_bytes, "498dbe00200000", "498dbe00800000"),
|
||||
patch(0x04ee3b47, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ee3b4f, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ee4c77, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ee4c7f, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ee4f47, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ee4f4f, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04ee7daa, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04ee7db9, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04eeb19e, Kind::page_bytes, "b900200000", "b900800000"),
|
||||
patch(0x04eeb1ad, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04eeba26, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eeba2d, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eec74e, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eec755, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eec8ac, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eec8b3, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eecd45, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x04eecd58, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04eece4d, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04eece6e, Kind::index_shift, "41c1e00a", "41c1e00c"),
|
||||
patch(0x04eecf6d, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eecf74, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eed0a0, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eed0a7, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eed221, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eed228, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eed31c, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eed323, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eed468, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04eed474, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eed6a0, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eed6a7, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eed869, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eed870, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eed9f4, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eed9fb, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eee208, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x04eee21b, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04eee292, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x04eee2a5, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04eee328, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x04eee33b, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04eee3b2, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x04eee3c5, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04eee432, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x04eee445, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04eee4a2, Kind::index_shift, "41c1e80a", "41c1e80c"),
|
||||
patch(0x04eee4b5, Kind::index_shift, "c1e00a", "c1e00c"),
|
||||
patch(0x04eee60a, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04eee62b, Kind::index_shift, "41c1e00a", "41c1e00c"),
|
||||
patch(0x04eee72f, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eee736, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eee89f, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eee8a6, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eeea0a, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eeea11, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eeecbe, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eeecc5, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eeede9, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eeedf0, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eef06f, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef076, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eef15d, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef164, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04eef214, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef21b, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef0113, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef011a, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef5deb, Kind::page_entries, "4181c700040000", "4181c700100000"),
|
||||
patch(0x04ef5df7, Kind::page_bytes, "498db600200000", "498db600800000"),
|
||||
patch(0x04ef5f89, Kind::page_entries, "4181c700040000", "4181c700100000"),
|
||||
patch(0x04ef5f95, Kind::page_bytes, "498db600200000", "498db600800000"),
|
||||
patch(0x04ef60ae, Kind::page_entries, "4181c500040000", "4181c500100000"),
|
||||
patch(0x04ef60ba, Kind::page_bytes, "4d8dbe00200000", "4d8dbe00800000"),
|
||||
patch(0x04efc57b, Kind::page_entries, "4181c700040000", "4181c700100000"),
|
||||
patch(0x04efc587, Kind::page_bytes, "498db600200000", "498db600800000"),
|
||||
patch(0x04efc729, Kind::page_entries, "4181c700040000", "4181c700100000"),
|
||||
patch(0x04efc735, Kind::page_bytes, "498db600200000", "498db600800000"),
|
||||
patch(0x04efc858, Kind::page_entries, "4181c500040000", "4181c500100000"),
|
||||
patch(0x04efc864, Kind::page_bytes, "4d8dbe00200000", "4d8dbe00800000"),
|
||||
patch(0x04f097dc, Kind::page_entries, "4181c600040000", "4181c600100000"),
|
||||
patch(0x04f097e5, Kind::page_bytes, "4c8da500200000", "4c8da500800000"),
|
||||
patch(0x04f0988f, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x04f0989b, Kind::page_bytes, "4c8dad00200000", "4c8dad00800000"),
|
||||
patch(0x04f0b69c, Kind::page_entries, "81c500040000", "81c500100000"),
|
||||
patch(0x04f0b6a7, Kind::page_bytes, "4c8db600200000", "4c8db600800000"),
|
||||
patch(0x04f0b828, Kind::page_entries, "4181c400040000", "4181c400100000"),
|
||||
patch(0x04f0b834, Kind::page_bytes, "498dbe00200000", "498dbe00800000"),
|
||||
patch(0x04f16e2d, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f16e34, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f16ee4, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f16eeb, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f1700c, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f17013, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f172d4, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f172db, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f17618, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f1761f, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f19462, Kind::page_bytes, "b900200000", "b900800000"),
|
||||
patch(0x04f1946f, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f194db, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f194e0, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f19ca2, Kind::page_bytes, "b900200000", "b900800000"),
|
||||
patch(0x04f19caf, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f19d1b, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f19d20, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f19f22, Kind::page_bytes, "b900200000", "b900800000"),
|
||||
patch(0x04f19f2f, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f19f9b, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f19fa0, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f1e856, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f1e863, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f1e8f0, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f1e8f8, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f1ea31, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f1ea39, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f216fd, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f2170a, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f21796, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f2179e, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f218d6, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f218de, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f21f09, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f21f16, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f21fa2, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f21faa, Kind::index_shift, "c1e20a", "c1e20c"),
|
||||
patch(0x04f220e8, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f220f0, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f2b166, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f2b16b, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f2b2e4, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f2b2ec, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f2b38c, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2b3c3, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2b3fd, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2b437, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2b471, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2b4ab, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2b4e5, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2b51f, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2e6e6, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f2e6eb, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f2e877, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f2e87f, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f2e92c, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2e963, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2e99d, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2e9d7, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2ea11, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2ea4b, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2ea85, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2eabf, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2ec86, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f2ec8b, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f2ee27, Kind::index_shift, "c1e90a", "c1e90c"),
|
||||
patch(0x04f2ee2f, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f2eedc, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2ef13, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2ef4d, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2ef87, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2efc1, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2effb, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2f035, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f2f06f, Kind::page_bytes, "41b800200000", "41b800800000"),
|
||||
patch(0x04f34fea, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f34ff1, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f35b60, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f35b66, Kind::index_shift, "41c1e00a", "41c1e00c"),
|
||||
patch(0x04f38418, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f3841f, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f38958, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f3895f, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
patch(0x04f38a78, Kind::index_shift, "c1e80a", "c1e80c"),
|
||||
patch(0x04f38a7f, Kind::index_shift, "c1e10a", "c1e10c"),
|
||||
};
|
||||
} // namespace dingosdk::game::build::v20260929::entity_pages
|
||||
@@ -12,7 +12,7 @@ using entity_pages::patch;
|
||||
// treating its allocator pointer and metadata as additional page pointers.
|
||||
inline constexpr std::size_t entry_bytes = 24;
|
||||
inline constexpr std::size_t page_bytes = entity_pages::page_entries * entry_bytes;
|
||||
static_assert(page_bytes == 0x30000);
|
||||
static_assert(page_bytes == 0x18000);
|
||||
|
||||
// Keep owner offsets and stack-frame layouts intact. Disable only the two
|
||||
// undersized inline pages; the existing lazy allocator/destructor owns every
|
||||
@@ -21,141 +21,141 @@ static_assert(page_bytes == 0x30000);
|
||||
inline constexpr Patch patches[]{
|
||||
patch(0x048a7450, Kind::pending_update_pages, "41c7800c04000002000000", "41c7800c04000000000000"),
|
||||
patch(0x048a745b, Kind::pending_update_pages, "833db6cf910206", "e9300000009090"),
|
||||
patch(0x048a944c, Kind::pending_update_pages, "41b800600000", "41b800000300"),
|
||||
patch(0x048abf3e, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x048abf44, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x048afad8, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048afae2, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x048bdd9b, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048bdda9, Kind::pending_update_pages, "41c1e20a", "41c1e20d"),
|
||||
patch(0x048bddcb, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048bddd2, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x048be423, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048be437, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x048be45b, Kind::pending_update_pages, "c1e70a", "c1e70d"),
|
||||
patch(0x048bffb9, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048bffbe, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x048bfff2, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048bfff9, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x048c0012, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048c0017, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x048c04c2, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x048c04c8, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x048c0e14, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x048c0e1c, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04eb2fce, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04eb2fd4, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04eb30ae, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04eb30b4, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04eb318e, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04eb3194, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04eef54b, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef559, Kind::pending_update_pages, "41c1e20a", "41c1e20d"),
|
||||
patch(0x04eef57b, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef582, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04eef61b, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef629, Kind::pending_update_pages, "41c1e20a", "41c1e20d"),
|
||||
patch(0x04eef64b, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef652, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04eef6fb, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef709, Kind::pending_update_pages, "41c1e20a", "41c1e20d"),
|
||||
patch(0x04eef72b, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04eef732, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef55da, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04ef5601, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef5628, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef566f, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef569d, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef56a5, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef56b4, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04ef574d, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef576f, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef579b, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef5813, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef583c, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef5863, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef58aa, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef58d8, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef58e0, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef58ef, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04ef5971, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef5978, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef59a4, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef59ab, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef5a72, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef5a91, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef5ab8, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef5b01, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef5b06, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04ef5b4f, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef5b6e, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef5b95, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef5bdd, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef5be2, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04ef5c1f, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef5c26, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04ef5c41, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04ef5c46, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04ef5e59, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04ef5e78, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef5e97, Kind::pending_update_pages, "c1e60a", "c1e60d"),
|
||||
patch(0x04ef5feb, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04ef600a, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04ef6029, Kind::pending_update_pages, "c1e60a", "c1e60d"),
|
||||
patch(0x04ef61af, Kind::pending_update_pages, "418d8dff030000", "418d8dff1f0000"),
|
||||
patch(0x04ef61b6, Kind::pending_update_pages, "48c1e90a", "48c1e90d"),
|
||||
patch(0x04ef61f3, Kind::pending_update_pages, "b800040000", "b800200000"),
|
||||
patch(0x04ef628b, Kind::pending_update_pages, "4181c500fcffff", "4181c500e0ffff"),
|
||||
patch(0x04ef630d, Kind::pending_update_pages, "41b800600000", "41b800000300"),
|
||||
patch(0x04efbdf3, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04efbe1a, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efbe41, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efbe88, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efbeb6, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efbebe, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efbecd, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04efbf6c, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efbf8e, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efbfba, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efc035, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efc062, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efc08e, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efc0e9, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efc117, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efc11f, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efc12e, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04efc202, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efc221, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efc248, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efc2c2, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efc2e1, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efc308, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efc353, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efc358, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04efc399, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efc3a0, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04efc3bb, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04efc3c0, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04efc5ef, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04efc60e, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efc62d, Kind::pending_update_pages, "c1e60a", "c1e60d"),
|
||||
patch(0x04efc78e, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04efc7ad, Kind::pending_update_pages, "ba00600000", "ba00000300"),
|
||||
patch(0x04efc7cc, Kind::pending_update_pages, "c1e60a", "c1e60d"),
|
||||
patch(0x04efc96c, Kind::pending_update_pages, "418d8dff030000", "418d8dff1f0000"),
|
||||
patch(0x04efc973, Kind::pending_update_pages, "48c1e90a", "48c1e90d"),
|
||||
patch(0x04efc9b3, Kind::pending_update_pages, "b800040000", "b800200000"),
|
||||
patch(0x04efca54, Kind::pending_update_pages, "4181c500fcffff", "4181c500e0ffff"),
|
||||
patch(0x04efcad9, Kind::pending_update_pages, "41b800600000", "41b800000300"),
|
||||
patch(0x04f095de, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04f095e3, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04f0961e, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04f09625, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04f0963e, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04f09643, Kind::pending_update_pages, "c1e00a", "c1e00d"),
|
||||
patch(0x04f09af2, Kind::pending_update_pages, "c1e90a", "c1e90d"),
|
||||
patch(0x04f09af8, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x04f0db17, Kind::pending_update_pages, "c1e80a", "c1e80d"),
|
||||
patch(0x04f0db1f, Kind::pending_update_pages, "c1e10a", "c1e10d"),
|
||||
patch(0x048a944c, Kind::pending_update_pages, "41b800600000", "41b800800100"),
|
||||
patch(0x048abf3e, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x048abf44, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x048afad8, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048afae2, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x048bdd9b, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048bdda9, Kind::pending_update_pages, "41c1e20a", "41c1e20c"),
|
||||
patch(0x048bddcb, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048bddd2, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x048be423, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048be437, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x048be45b, Kind::pending_update_pages, "c1e70a", "c1e70c"),
|
||||
patch(0x048bffb9, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048bffbe, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x048bfff2, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048bfff9, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x048c0012, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048c0017, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x048c04c2, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x048c04c8, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x048c0e14, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x048c0e1c, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04eb2fce, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04eb2fd4, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04eb30ae, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04eb30b4, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04eb318e, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04eb3194, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04eef54b, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef559, Kind::pending_update_pages, "41c1e20a", "41c1e20c"),
|
||||
patch(0x04eef57b, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef582, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04eef61b, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef629, Kind::pending_update_pages, "41c1e20a", "41c1e20c"),
|
||||
patch(0x04eef64b, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef652, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04eef6fb, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef709, Kind::pending_update_pages, "41c1e20a", "41c1e20c"),
|
||||
patch(0x04eef72b, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04eef732, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef55da, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04ef5601, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef5628, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef566f, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef569d, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef56a5, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef56b4, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04ef574d, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef576f, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef579b, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef5813, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef583c, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef5863, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef58aa, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef58d8, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef58e0, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef58ef, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04ef5971, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef5978, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef59a4, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef59ab, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef5a72, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef5a91, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef5ab8, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef5b01, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef5b06, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04ef5b4f, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef5b6e, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef5b95, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef5bdd, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef5be2, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04ef5c1f, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef5c26, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04ef5c41, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04ef5c46, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04ef5e59, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04ef5e78, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef5e97, Kind::pending_update_pages, "c1e60a", "c1e60c"),
|
||||
patch(0x04ef5feb, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04ef600a, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04ef6029, Kind::pending_update_pages, "c1e60a", "c1e60c"),
|
||||
patch(0x04ef61af, Kind::pending_update_pages, "418d8dff030000", "418d8dff0f0000"),
|
||||
patch(0x04ef61b6, Kind::pending_update_pages, "48c1e90a", "48c1e90c"),
|
||||
patch(0x04ef61f3, Kind::pending_update_pages, "b800040000", "b800100000"),
|
||||
patch(0x04ef628b, Kind::pending_update_pages, "4181c500fcffff", "4181c500f0ffff"),
|
||||
patch(0x04ef630d, Kind::pending_update_pages, "41b800600000", "41b800800100"),
|
||||
patch(0x04efbdf3, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04efbe1a, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efbe41, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efbe88, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efbeb6, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efbebe, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efbecd, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04efbf6c, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efbf8e, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efbfba, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efc035, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efc062, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efc08e, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efc0e9, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efc117, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efc11f, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efc12e, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04efc202, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efc221, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efc248, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efc2c2, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efc2e1, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efc308, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efc353, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efc358, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04efc399, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efc3a0, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04efc3bb, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04efc3c0, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04efc5ef, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04efc60e, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efc62d, Kind::pending_update_pages, "c1e60a", "c1e60c"),
|
||||
patch(0x04efc78e, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04efc7ad, Kind::pending_update_pages, "ba00600000", "ba00800100"),
|
||||
patch(0x04efc7cc, Kind::pending_update_pages, "c1e60a", "c1e60c"),
|
||||
patch(0x04efc96c, Kind::pending_update_pages, "418d8dff030000", "418d8dff0f0000"),
|
||||
patch(0x04efc973, Kind::pending_update_pages, "48c1e90a", "48c1e90c"),
|
||||
patch(0x04efc9b3, Kind::pending_update_pages, "b800040000", "b800100000"),
|
||||
patch(0x04efca54, Kind::pending_update_pages, "4181c500fcffff", "4181c500f0ffff"),
|
||||
patch(0x04efcad9, Kind::pending_update_pages, "41b800600000", "41b800800100"),
|
||||
patch(0x04f095de, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04f095e3, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04f0961e, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04f09625, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04f0963e, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04f09643, Kind::pending_update_pages, "c1e00a", "c1e00c"),
|
||||
patch(0x04f09af2, Kind::pending_update_pages, "c1e90a", "c1e90c"),
|
||||
patch(0x04f09af8, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
patch(0x04f0db17, Kind::pending_update_pages, "c1e80a", "c1e80c"),
|
||||
patch(0x04f0db1f, Kind::pending_update_pages, "c1e10a", "c1e10c"),
|
||||
};
|
||||
} // namespace dingosdk::game::build::v20260929::pending_updates
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "Engine/Game/Build/fingerprint.h"
|
||||
#include <cstdint>
|
||||
|
||||
// The game's rolling replay recording (Extension/Settings/replay_guard.cpp).
|
||||
namespace dingosdk::game::build::v20260929::replay_recorder {
|
||||
// end_chunk(recorder, force): run on a job worker as the game plays. Every recorder + 0x110
|
||||
// frames, or when the stream (recorder + 0x950) is as full as recorder + 0x30 allows, it ends
|
||||
// the chunk being recorded (recorder + 0xa80) with a "Tail" marker and starts the next: it has
|
||||
// the stream drop old chunks (0x48f0e30), then asks it for the new chunk's head (0x48fb5a0, an
|
||||
// allocation tagged "rplyFreezeClip"). It returns whether a chunk was ended (al).
|
||||
inline constexpr Fingerprint end_chunk{0x48ef8a0, {
|
||||
0x40,0x53,0x55,0x57,0x48,0x81,0xec,0xc0,0x01,0x00,0x00,0x48,0x8b,0x05,0x0e,0x4b,
|
||||
0x8d,0x02,0x48,0x33,0xc4,0x48,0x89,0x84,0x24,0x90,0x01,0x00,0x00,0xc5,0xfb,0x10}};
|
||||
// The store of the new head's first field, right after that allocation, with no check that the
|
||||
// stream had room for one: an access violation writing 0x24 when it had none (crash reports of
|
||||
// 2026-10-10, v2.0.3, skating on a server).
|
||||
inline constexpr std::uintptr_t end_chunk_head_store = 0x48efa34;
|
||||
}
|
||||
@@ -26,7 +26,8 @@ struct alignas(16) RootLayout {
|
||||
BucketLayout nodes[nodes_per_root];
|
||||
std::uint32_t node_count;
|
||||
};
|
||||
static_assert(blocks_per_bucket * entries_per_block == entity_pages::capacity);
|
||||
// (Left at eight times the game's while the entity pages are at four: room to spare.)
|
||||
static_assert(blocks_per_bucket * entries_per_block >= entity_pages::capacity);
|
||||
static_assert(blocks_per_bucket < 65'536);
|
||||
static_assert(offsetof(BucketLayout, block_pointers) == 0x10000);
|
||||
static_assert(offsetof(BucketLayout, block_count) == 0x30000);
|
||||
|
||||
@@ -391,7 +391,12 @@ void installed_mods(const fs::path& game, const fs::path& folder, const StoreIte
|
||||
<< found.game_costumes << " of the game's costumes, " << found.items.size() << " copy(ies) of store items in "
|
||||
<< found.mods.size() << " of them\n";
|
||||
for (const auto& source : found.mods)
|
||||
std::cout << " " << source.mod << ": " << source.count << ", e.g. " << source.example << " is " << source.original << '\n';
|
||||
std::cout << " " << source.mod << ": " << source.count << ", e.g. " << source.example << " is " << source.original
|
||||
<< (source.by_mesh ? " (by its mesh)" : " (by what its item is fitted on)") << '\n';
|
||||
for (const auto& mesh : found.meshes_seen)
|
||||
std::cout << " mesh " << mesh.mod << ": " << mesh.mesh << ", " << mesh.points << " points, " << mesh.closest.shared
|
||||
<< " of them only in " << (mesh.closest.key.empty() ? std::string("no store costume") : mesh.closest.key + " (" +
|
||||
std::to_string(mesh.closest.costume_points) + " points)") << '\n';
|
||||
for (const auto& note : notes) std::cout << " note: " << note << '\n';
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -615,6 +615,16 @@ std::string StoreMeshes::original(const std::vector<std::uint64_t>& points) cons
|
||||
return most ? *most : std::string();
|
||||
}
|
||||
|
||||
StoreMeshes::Closest StoreMeshes::closest(const std::vector<std::uint64_t>& points) const {
|
||||
std::vector<std::size_t> shared(owners_.size());
|
||||
for (const auto point : points)
|
||||
if (const auto found = points_.find(point); found != points_.end() && found->second != nobody) ++shared[found->second];
|
||||
Closest most;
|
||||
for (std::size_t owner = 0; owner < owners_.size(); ++owner)
|
||||
if (owners_[owner].sold && shared[owner] > most.shared) most = {owners_[owner].key, shared[owner], owners_[owner].largest};
|
||||
return most;
|
||||
}
|
||||
|
||||
StoreCopies check_store_copies(const Catalog& catalog, const StoreItem& sold, std::vector<std::string>* notes,
|
||||
std::size_t threads, bool background) noexcept {
|
||||
StoreCopies result;
|
||||
@@ -680,11 +690,13 @@ StoreCopies check_store_copies(const Catalog& catalog, const StoreItem& sold, st
|
||||
for (const auto& [mod, items, meshes] : added) {
|
||||
StoreCopies::Source source{mod->name};
|
||||
for (const auto& mesh : meshes) {
|
||||
result.meshes_seen.push_back({mod->name, mesh.name, mesh.points.size(), costumes.closest(mesh.points)});
|
||||
const auto original = costumes.original(mesh.points);
|
||||
if (original.empty()) continue;
|
||||
if (!source.count++) {
|
||||
source.example = mesh.name;
|
||||
source.original = original;
|
||||
source.by_mesh = true;
|
||||
}
|
||||
result.items.insert_or_assign(lower(mesh.name), lower(original));
|
||||
}
|
||||
|
||||
@@ -98,6 +98,13 @@ public:
|
||||
// an item anyone has.
|
||||
[[nodiscard]] std::string original(const std::vector<std::uint64_t>& points) const;
|
||||
static constexpr std::size_t shared_least = 300;
|
||||
// For a report: the store costume most of these points are only in, and how many are, whether
|
||||
// or not that is enough to call the mesh taken from it (empty key: none are any costume's).
|
||||
struct Closest {
|
||||
std::string key;
|
||||
std::size_t shared{}, costume_points{};
|
||||
};
|
||||
[[nodiscard]] Closest closest(const std::vector<std::uint64_t>& points) const;
|
||||
|
||||
private:
|
||||
static constexpr std::uint32_t nobody = 0xffffffffU;
|
||||
@@ -119,8 +126,19 @@ struct StoreCopies {
|
||||
std::string mod;
|
||||
std::size_t count{};
|
||||
std::string example, original; // one of its copies and what that copies, as written
|
||||
// How that one was found: its mesh has the costume's geometry, or its item is fitted on
|
||||
// what the costume is (its shape, or a store item's looks or data).
|
||||
bool by_mesh{};
|
||||
};
|
||||
std::vector<Source> mods;
|
||||
// Every mesh level a mod ships and how much of a store costume's geometry is in it, for a
|
||||
// report of the check (the Paid Cosmetics Detector, the test tool): a copy or not.
|
||||
struct MeshSeen {
|
||||
std::string mod, mesh;
|
||||
std::size_t points{};
|
||||
StoreMeshes::Closest closest;
|
||||
};
|
||||
std::vector<MeshSeen> meshes_seen;
|
||||
// How many of the game's own items the mods' were held against; none when no mod adds an item.
|
||||
std::size_t game_items{};
|
||||
// And how many of the mods' meshes against how many of the game's costumes.
|
||||
|
||||
@@ -22,6 +22,8 @@ void register_object_commands(Commands &);
|
||||
void register_park_editor_commands(Commands &);
|
||||
void register_multiplayer_commands(Commands &);
|
||||
void register_perf_commands(Commands &);
|
||||
// perf_commands.cpp: starts `perf memory`'s trace with the game when RESKATE_MEMORY_TRACE asks for it.
|
||||
void start_memory_trace_from_environment() noexcept;
|
||||
void register_item_commands(Commands &);
|
||||
void register_trainer_commands(Commands &);
|
||||
void register_hall_of_meat_commands(Commands &);
|
||||
|
||||
@@ -3,7 +3,16 @@
|
||||
#include "Extension/Settings/engine_tweaks.h"
|
||||
#include "Extension/Settings/job_spin.h"
|
||||
#include "Extension/UI/ui_pointer_skip.h"
|
||||
#include "Engine/Core/Hooks/hooks.h"
|
||||
#include <Windows.h>
|
||||
#include <Psapi.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <format>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
// The performance profiler's console commands (Engine/Core/Profiling/profiler.h). Everything but
|
||||
// the saved HUD switch runs on the overlay's thread: the profiler is thread-safe.
|
||||
@@ -64,6 +73,202 @@ void print_report(const Output& out) {
|
||||
}
|
||||
}
|
||||
|
||||
// `perf memory`: what the game's memory is made of, by allocation, and what was added since a
|
||||
// mark: for finding what a full server's memory goes on. An allocation is one VirtualAlloc
|
||||
// reservation (the engine's arenas and pools are each one or a few); its size here is what of
|
||||
// it is committed, which is what counts against the PC's memory.
|
||||
struct MemoryMap {
|
||||
std::map<std::uintptr_t, std::uint64_t> allocations; // private memory: base -> committed bytes
|
||||
std::uint64_t committed{}, mapped{}, image{};
|
||||
};
|
||||
MemoryMap read_memory_map() {
|
||||
MemoryMap map;
|
||||
SYSTEM_INFO system{};
|
||||
GetSystemInfo(&system);
|
||||
auto at = reinterpret_cast<std::uintptr_t>(system.lpMinimumApplicationAddress);
|
||||
const auto end = reinterpret_cast<std::uintptr_t>(system.lpMaximumApplicationAddress);
|
||||
MEMORY_BASIC_INFORMATION info{};
|
||||
while (at < end && VirtualQuery(reinterpret_cast<void*>(at), &info, sizeof(info)) == sizeof(info)) {
|
||||
if (info.State == MEM_COMMIT) {
|
||||
if (info.Type == MEM_PRIVATE) {
|
||||
map.allocations[reinterpret_cast<std::uintptr_t>(info.AllocationBase)] += info.RegionSize;
|
||||
map.committed += info.RegionSize;
|
||||
} else (info.Type == MEM_IMAGE ? map.image : map.mapped) += info.RegionSize;
|
||||
}
|
||||
at = reinterpret_cast<std::uintptr_t>(info.BaseAddress) + info.RegionSize;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
std::string megabytes(std::uint64_t bytes) {
|
||||
return bytes >= (1ull << 30) ? std::format("{:.2f} GB", static_cast<double>(bytes) / (1ull << 30))
|
||||
: std::format("{:.1f} MB", static_cast<double>(bytes) / (1ull << 20));
|
||||
}
|
||||
// How much of [base, base + bytes) is in RAM now: the pages the game has written to and
|
||||
// Windows has not moved out. The rest of a committed block is promised and unused.
|
||||
std::uint64_t resident_bytes(std::uintptr_t base, std::uint64_t bytes) {
|
||||
constexpr std::size_t batch = 16384;
|
||||
std::vector<PSAPI_WORKING_SET_EX_INFORMATION> pages(batch);
|
||||
std::uint64_t resident{};
|
||||
for (std::uint64_t done = 0; done < bytes;) {
|
||||
const auto count = static_cast<std::size_t>(std::min<std::uint64_t>(batch, (bytes - done + 4095) / 4096));
|
||||
for (std::size_t i = 0; i < count; ++i) pages[i].VirtualAddress = reinterpret_cast<void*>(base + done + i * 4096);
|
||||
if (!QueryWorkingSetEx(GetCurrentProcess(), pages.data(), static_cast<DWORD>(count * sizeof(pages[0])))) break;
|
||||
for (std::size_t i = 0; i < count; ++i) resident += pages[i].VirtualAttributes.Valid ? 4096 : 0;
|
||||
done += count * 4096ull;
|
||||
}
|
||||
return resident;
|
||||
}
|
||||
// Allocations by size, the sizes that add up to most first: "126 x 32.0 MB = 3.94 GB".
|
||||
void print_by_size(const std::vector<std::uint64_t>& sizes, const Output& out, std::size_t most) {
|
||||
std::map<std::uint64_t, std::pair<std::uint64_t, std::uint64_t>> groups; // size rounded to 64 KB -> count, bytes
|
||||
for (const auto size : sizes) {
|
||||
auto& group = groups[(size + 0xffff) & ~0xffffull];
|
||||
++group.first;
|
||||
group.second += size;
|
||||
}
|
||||
std::vector<std::pair<std::uint64_t, std::pair<std::uint64_t, std::uint64_t>>> order(groups.begin(), groups.end());
|
||||
std::sort(order.begin(), order.end(), [](const auto& a, const auto& b) { return a.second.second > b.second.second; });
|
||||
for (std::size_t i = 0; i < order.size() && i < most; ++i)
|
||||
out(std::format(" {} x {} = {}", order[i].second.first, megabytes(order[i].first), megabytes(order[i].second.second)));
|
||||
}
|
||||
|
||||
// `perf memory trace`: who asks Windows for the middle-sized blocks (2 to 64 MB) while it is on,
|
||||
// by the code that called for each: where a block of a size `perf memory` showed many of comes
|
||||
// from. Every commit of memory in the process passes the hook while it is on, so it is a
|
||||
// research aid and off until asked for.
|
||||
namespace trace {
|
||||
constexpr std::size_t callers = 8192, depth = 14;
|
||||
struct Caller {
|
||||
std::uint64_t hash{}, count{}, bytes{}, size{}, largest{}; // size: the smallest such block; largest: the largest
|
||||
std::array<void*, depth> frames{};
|
||||
unsigned frame_count{};
|
||||
};
|
||||
std::mutex mutex;
|
||||
std::vector<Caller> table(callers); // found by hash: a commit of any size can be traced
|
||||
std::atomic<bool> on{};
|
||||
// The sizes traced: 2 to 64 MB from the console; the largest blocks alone from the start of
|
||||
// the game (RESKATE_MEMORY_TRACE), where nearly everything is being allocated.
|
||||
std::atomic<std::uint64_t> least{2ull << 20}, most{64ull << 20};
|
||||
bool prepared{};
|
||||
using Allocate = LONG (NTAPI*)(HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG);
|
||||
Allocate original{};
|
||||
|
||||
// The newer call for the same (VirtualAlloc2, which graphics drivers and the D3D12 runtime use).
|
||||
using AllocateEx = LONG (NTAPI*)(HANDLE, PVOID*, PSIZE_T, ULONG, ULONG, void*, ULONG);
|
||||
AllocateEx original_ex{};
|
||||
void note(HANDLE process, SIZE_T asked, ULONG type) noexcept;
|
||||
|
||||
LONG NTAPI hooked(HANDLE process, PVOID* base, ULONG_PTR zero_bits, PSIZE_T size, ULONG type, ULONG protect) {
|
||||
const auto asked = size ? *size : 0;
|
||||
const auto status = original(process, base, zero_bits, size, type, protect);
|
||||
if (status >= 0) note(process, asked, type);
|
||||
return status;
|
||||
}
|
||||
LONG NTAPI hooked_ex(HANDLE process, PVOID* base, PSIZE_T size, ULONG type, ULONG protect, void* parameters, ULONG parameter_count) {
|
||||
const auto asked = size ? *size : 0;
|
||||
const auto status = original_ex(process, base, size, type, protect, parameters, parameter_count);
|
||||
if (status >= 0) note(process, asked, type);
|
||||
return status;
|
||||
}
|
||||
void note(HANDLE process, SIZE_T asked, ULONG type) noexcept {
|
||||
if (!on.load(std::memory_order_relaxed) || !(type & (MEM_COMMIT | MEM_RESERVE)) || process != GetCurrentProcess() ||
|
||||
asked < least.load(std::memory_order_relaxed) || asked > most.load(std::memory_order_relaxed)) return;
|
||||
// (Reservations count too: a block reserved whole and committed a piece at a time is only
|
||||
// this large when it is reserved.)
|
||||
Caller seen;
|
||||
seen.frame_count = CaptureStackBackTrace(2, static_cast<DWORD>(depth), seen.frames.data(), nullptr);
|
||||
// By who asked alone: one caller's blocks of every size add up together.
|
||||
std::uint64_t hash = 1469598103934665603ull;
|
||||
for (unsigned i = 0; i < seen.frame_count; ++i) hash = hash * 1099511628211ull ^ reinterpret_cast<std::uintptr_t>(seen.frames[i]);
|
||||
if (!hash) hash = 1;
|
||||
std::lock_guard lock(mutex);
|
||||
for (std::size_t probe = 0; probe < 128; ++probe) {
|
||||
auto& caller = table[(hash + probe) % callers];
|
||||
if (caller.count && caller.hash != hash) continue;
|
||||
if (!caller.count) { caller = seen; caller.hash = hash; caller.size = asked; }
|
||||
++caller.count;
|
||||
caller.bytes += asked;
|
||||
caller.size = std::min<std::uint64_t>(caller.size, asked);
|
||||
caller.largest = std::max<std::uint64_t>(caller.largest, asked);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool start(std::string& error) {
|
||||
if (!prepared) {
|
||||
const auto target = reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtAllocateVirtualMemory"));
|
||||
if (!target || hook_prepare(target, reinterpret_cast<void*>(&hooked), reinterpret_cast<void**>(&original)) != HookOk) {
|
||||
error = "the allocation hook could not be prepared";
|
||||
return false;
|
||||
}
|
||||
// (Missing on an older Windows: then only the first is traced.)
|
||||
if (const auto ex = reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtAllocateVirtualMemoryEx"));
|
||||
ex && hook_prepare(ex, reinterpret_cast<void*>(&hooked_ex), reinterpret_cast<void**>(&original_ex)) != HookOk)
|
||||
original_ex = nullptr;
|
||||
prepared = true;
|
||||
}
|
||||
{ std::lock_guard lock(mutex); std::fill(table.begin(), table.end(), Caller{}); }
|
||||
const auto target = reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtAllocateVirtualMemory"));
|
||||
if (!on.load() && hook_enable(target) != HookOk) { error = "the allocation hook could not be attached"; return false; }
|
||||
if (!on.load() && original_ex) hook_enable(reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtAllocateVirtualMemoryEx")));
|
||||
on.store(true);
|
||||
return true;
|
||||
}
|
||||
void stop() {
|
||||
if (!on.exchange(false)) return;
|
||||
hook_disable(reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtAllocateVirtualMemory")));
|
||||
if (original_ex) hook_disable(reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtAllocateVirtualMemoryEx")));
|
||||
}
|
||||
std::string place(void* address) {
|
||||
HMODULE module{};
|
||||
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCWSTR>(address), &module) || !module)
|
||||
return std::format("{:#x}", reinterpret_cast<std::uintptr_t>(address));
|
||||
wchar_t path[MAX_PATH]{};
|
||||
GetModuleFileNameW(module, path, MAX_PATH);
|
||||
const wchar_t* name = path;
|
||||
for (const wchar_t* c = path; *c; ++c) if (*c == L'\\') name = c + 1;
|
||||
std::string text;
|
||||
for (; *name; ++name) text += static_cast<char>(*name);
|
||||
return std::format("{}+{:#x}", text, reinterpret_cast<std::uintptr_t>(address) - reinterpret_cast<std::uintptr_t>(module));
|
||||
}
|
||||
void report(const Output& out) {
|
||||
std::vector<Caller> seen;
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
for (const auto& caller : table) if (caller.count) seen.push_back(caller);
|
||||
}
|
||||
std::sort(seen.begin(), seen.end(), [](const Caller& a, const Caller& b) { return a.bytes > b.bytes; });
|
||||
out(std::format("Memory asked for while tracing (blocks of {} and up), by who asked ({} callers), the most first:",
|
||||
megabytes(least.load()), seen.size()));
|
||||
for (std::size_t i = 0; i < seen.size() && i < 16; ++i) {
|
||||
out(seen[i].size == seen[i].largest
|
||||
? std::format(" {} x {} bytes = {}", seen[i].count, seen[i].size, megabytes(seen[i].bytes))
|
||||
: std::format(" {} blocks of {} to {} bytes = {}", seen[i].count, seen[i].size, seen[i].largest, megabytes(seen[i].bytes)));
|
||||
std::string line = " ";
|
||||
for (unsigned frame = 0; frame < seen[i].frame_count; ++frame) line += " < " + place(seen[i].frames[frame]);
|
||||
out(line);
|
||||
}
|
||||
}
|
||||
} // namespace trace
|
||||
|
||||
// RESKATE_MEMORY_TRACE=<megabytes>: from the start of the game, who asks for each block of at
|
||||
// least that size (`perf memory` then lists them). A research aid for what a map's load commits.
|
||||
void start_memory_trace_from_environment() noexcept {
|
||||
wchar_t value[16]{};
|
||||
const auto length = GetEnvironmentVariableW(L"RESKATE_MEMORY_TRACE", value, 16);
|
||||
if (!length || length >= 16) return;
|
||||
// (In megabytes; "all" for every block, however small.)
|
||||
const bool all = value[0] == L'a';
|
||||
const auto megabytes_least = std::wcstoul(value, nullptr, 10);
|
||||
if (!megabytes_least && !all) return;
|
||||
try {
|
||||
trace::least.store(all ? 1 : static_cast<std::uint64_t>(megabytes_least) << 20);
|
||||
trace::most.store(UINT64_MAX);
|
||||
std::string error;
|
||||
(void)trace::start(error);
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
void register_perf_commands(Commands& registry) {
|
||||
// The HUD starts off every launch; these turn it on for the session.
|
||||
auto toggle = action("perf", "Show or hide the performance HUD", Group::console);
|
||||
@@ -234,6 +439,116 @@ void register_perf_commands(Commands& registry) {
|
||||
};
|
||||
registry.add(std::move(tweaks));
|
||||
|
||||
auto what = argument("mark", Type::text, true);
|
||||
what.complete = [](const Model&, auto) { return std::vector<std::string>{"mark", "trace", "stop", "big"}; };
|
||||
auto memory = action("perf memory", "The game's memory by allocation; `perf memory mark` remembers it and the next `perf memory` says what was added since; "
|
||||
"`perf memory trace` then also says who asked for the middle-sized blocks, until `perf memory stop`; `perf memory big` lists the largest blocks and how much of each is in use",
|
||||
Group::console, {std::move(what)});
|
||||
memory.execution = Execution::local;
|
||||
memory.run = [](const Model&, const Values& args, const Output& out) {
|
||||
static std::mutex mutex;
|
||||
static MemoryMap marked;
|
||||
static bool has_mark{};
|
||||
std::lock_guard lock(mutex);
|
||||
const auto now = read_memory_map();
|
||||
out(std::format("Memory: {} committed in {} allocations, {} of files mapped in, {} of programs.", megabytes(now.committed),
|
||||
now.allocations.size(), megabytes(now.mapped), megabytes(now.image)));
|
||||
if (!args.empty() && equal(std::get<std::string>(args[0]), "big")) {
|
||||
// The largest blocks one by one: where each is, its exact size, and how much of it is used.
|
||||
std::vector<std::pair<std::uint64_t, std::uintptr_t>> order;
|
||||
for (const auto& [base, size] : now.allocations) order.emplace_back(size, base);
|
||||
std::sort(order.rbegin(), order.rend());
|
||||
out("The largest blocks (committed, of which in RAM now):");
|
||||
for (std::size_t i = 0; i < order.size() && i < 24; ++i) {
|
||||
// (The whole reservation is walked: what is not committed in it is not in RAM either.)
|
||||
MEMORY_BASIC_INFORMATION info{};
|
||||
std::uint64_t span = order[i].first;
|
||||
for (auto at = order[i].second; VirtualQuery(reinterpret_cast<void*>(at), &info, sizeof(info)) == sizeof(info) &&
|
||||
reinterpret_cast<std::uintptr_t>(info.AllocationBase) == order[i].second;
|
||||
at = reinterpret_cast<std::uintptr_t>(info.BaseAddress) + info.RegionSize)
|
||||
span = reinterpret_cast<std::uintptr_t>(info.BaseAddress) + info.RegionSize - order[i].second;
|
||||
out(std::format(" {:#x}: {} bytes ({}), {} in RAM", order[i].second, order[i].first, megabytes(order[i].first),
|
||||
megabytes(resident_bytes(order[i].second, span))));
|
||||
if (i >= 3) continue;
|
||||
// What kind of memory the three largest are, and a look at what is in them: how
|
||||
// they are protected and held, and the bytes at a few places that are in RAM.
|
||||
VirtualQuery(reinterpret_cast<void*>(order[i].second), &info, sizeof(info));
|
||||
PSAPI_WORKING_SET_EX_INFORMATION page{reinterpret_cast<void*>(order[i].second)};
|
||||
QueryWorkingSetEx(GetCurrentProcess(), &page, sizeof(page));
|
||||
out(std::format(" reserved {:#x} bytes, protection {:#x} (as reserved {:#x}), first region {:#x} bytes; first page: {}{}{}{}",
|
||||
span, info.Protect, info.AllocationProtect, static_cast<std::uint64_t>(info.RegionSize),
|
||||
page.VirtualAttributes.Valid ? "in RAM" : "not in RAM", page.VirtualAttributes.Shared ? ", shared" : "",
|
||||
page.VirtualAttributes.Locked ? ", locked" : "", page.VirtualAttributes.LargePage ? ", large pages" : ""));
|
||||
std::size_t looked{}, zero_pages{};
|
||||
for (std::uint64_t part = 0; part < 64; ++part) {
|
||||
const auto at = order[i].second + ((span / 64) * part & ~0xfffull);
|
||||
PSAPI_WORKING_SET_EX_INFORMATION here{reinterpret_cast<void*>(at)};
|
||||
if (!QueryWorkingSetEx(GetCurrentProcess(), &here, sizeof(here)) || !here.VirtualAttributes.Valid) continue;
|
||||
std::array<unsigned char, 4096> bytes{};
|
||||
SIZE_T got{};
|
||||
if (!ReadProcessMemory(GetCurrentProcess(), reinterpret_cast<void*>(at), bytes.data(), bytes.size(), &got) || got != bytes.size()) continue;
|
||||
++looked;
|
||||
const bool zero = std::all_of(bytes.begin(), bytes.end(), [](unsigned char byte) { return byte == 0; });
|
||||
zero_pages += zero;
|
||||
if (zero || looked - zero_pages > 4) continue;
|
||||
std::string hex;
|
||||
for (std::size_t byte = 0; byte < 48; ++byte) hex += std::format("{:02x}{}", bytes[byte], byte % 8 == 7 ? " " : "");
|
||||
out(std::format(" +{:#x}: {}", at - order[i].second, hex));
|
||||
}
|
||||
out(std::format(" of {} sampled pages in RAM, {} are all zero", looked, zero_pages));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const bool tracing = !args.empty() && equal(std::get<std::string>(args[0]), "trace");
|
||||
if (!args.empty() && equal(std::get<std::string>(args[0]), "stop")) {
|
||||
trace::stop();
|
||||
out("Tracing stopped.");
|
||||
return;
|
||||
}
|
||||
if (tracing) {
|
||||
std::string error;
|
||||
// Every size: a large block is often set aside whole and filled a page at a time.
|
||||
trace::least.store(1);
|
||||
trace::most.store(UINT64_MAX);
|
||||
if (!trace::start(error)) { out("error: " + error); return; }
|
||||
}
|
||||
if (tracing || (!args.empty() && equal(std::get<std::string>(args[0]), "mark"))) {
|
||||
marked = now;
|
||||
has_mark = true;
|
||||
out(tracing ? "Marked, and tracing who asks for memory. Change what you want to measure, then run `perf memory`; `perf memory stop` ends the tracing."
|
||||
: "Marked. Change what you want to measure, then run `perf memory`.");
|
||||
return;
|
||||
}
|
||||
if (!has_mark) {
|
||||
std::vector<std::uint64_t> sizes;
|
||||
for (const auto& [base, size] : now.allocations) sizes.push_back(size);
|
||||
out("The allocation sizes that add up to most:");
|
||||
print_by_size(sizes, out, 20);
|
||||
if (trace::on.load()) trace::report(out);
|
||||
return;
|
||||
}
|
||||
std::vector<std::uint64_t> added, grown;
|
||||
std::uint64_t added_bytes{}, grown_bytes{}, freed_bytes{};
|
||||
for (const auto& [base, size] : now.allocations) {
|
||||
const auto before = marked.allocations.find(base);
|
||||
if (before == marked.allocations.end()) added.push_back(size), added_bytes += size;
|
||||
else if (size > before->second) grown.push_back(size - before->second), grown_bytes += size - before->second;
|
||||
else freed_bytes += before->second - size;
|
||||
}
|
||||
for (const auto& [base, size] : marked.allocations)
|
||||
if (!now.allocations.contains(base)) freed_bytes += size;
|
||||
out(std::format("Since the mark: {} to {} ({}{}).", megabytes(marked.committed), megabytes(now.committed),
|
||||
now.committed >= marked.committed ? "+" : "-",
|
||||
megabytes(now.committed >= marked.committed ? now.committed - marked.committed : marked.committed - now.committed)));
|
||||
out(std::format("New allocations: {} in {}. By size:", megabytes(added_bytes), added.size()));
|
||||
print_by_size(added, out, 20);
|
||||
out(std::format("Growth of allocations that were there: {} in {}. By how much each grew:", megabytes(grown_bytes), grown.size()));
|
||||
print_by_size(grown, out, 12);
|
||||
out(std::format("Given back: {}.", megabytes(freed_bytes)));
|
||||
if (trace::on.load()) trace::report(out);
|
||||
};
|
||||
registry.add(std::move(memory));
|
||||
|
||||
auto status = action("perf status", "Client update and frame timing, ReSkate's zones, CPU per thread", Group::console);
|
||||
status.execution = Execution::local;
|
||||
status.run = [](const Model&, const Values&, const Output& out) { print_summary(out); };
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <Windows.h>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
namespace dingosdk::multiplayer {
|
||||
namespace {
|
||||
@@ -71,6 +72,33 @@ void apply_cosmetic_recipe(std::uintptr_t base, std::uintptr_t entity, std::uint
|
||||
// Items this PC does not have (a player's cosmetics mod) would reject the
|
||||
// whole outfit: they become the matching default, or an empty slot.
|
||||
auto usable = recipe;
|
||||
// A slot the peer's game does not have takes this player's own parameters for it: they
|
||||
// are the right shape for the slot, and it is shown empty.
|
||||
const auto own = [&](std::uint32_t slot, std::size_t size) {
|
||||
std::vector<std::uint32_t> out;
|
||||
try {
|
||||
for (const auto &item : memory.array<NativeCosmeticItem>(memory.ptr(local, 0x158), max_cosmetic_slots))
|
||||
if (item.slot == slot) {
|
||||
out = memory.array<std::uint32_t>(reinterpret_cast<std::uintptr_t>(item.parameters),
|
||||
max_cosmetic_parameters);
|
||||
break;
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
out.clear();
|
||||
}
|
||||
if (out.size() != size) out.assign(size, 0);
|
||||
return out;
|
||||
};
|
||||
if (const auto [empty, left_out] = memory.fit_slots(resource, usable, own); empty || left_out) {
|
||||
static std::mutex logged_mutex;
|
||||
static std::set<std::tuple<std::uint32_t, std::size_t, std::size_t>> logged;
|
||||
std::lock_guard lock(logged_mutex);
|
||||
if (logged.size() < 32 && logged.emplace(recipe.key, empty, left_out).second)
|
||||
logging::log(logging::Level::info, logging::Channel::runtime,
|
||||
"Multiplayer: a player's {} has different cosmetic slots from this game's (a mod adds or "
|
||||
"removes some): {} of this game's slots left empty, {} of their items left out.",
|
||||
recipe.key == board_recipe_key ? "board" : "skater", empty, left_out);
|
||||
}
|
||||
const auto reserved = [](const std::string &asset) { return profile_runtime::reserved_cosmetic(asset); };
|
||||
for (const auto &[missing, replacement] :
|
||||
memory.substitute_missing(resource, usable, default_cosmetic_items, reserved)) {
|
||||
|
||||
@@ -200,6 +200,46 @@ template <class Read> struct CosmeticMemory {
|
||||
}
|
||||
return swaps;
|
||||
}
|
||||
// A mod can add slots to the skater or the board (stickers, say), and then two players'
|
||||
// templates hold different slots. Puts a peer's items in this game's slots by slot hash:
|
||||
// a slot the peer does not have stays empty, and an item in a slot this game does not
|
||||
// have is left out. `own(slot, count)` gives the parameters for a slot the peer sent none
|
||||
// for (or a different number of). Returns {slots left empty, items left out}; a recipe
|
||||
// that already has this game's slots in order is not touched.
|
||||
template <class Parameters>
|
||||
std::pair<std::size_t, std::size_t> fit_slots(std::uintptr_t res, CosmeticRecipe &r, const Parameters &own) const {
|
||||
const auto slots = ptr(res, 0x28);
|
||||
const auto wanted = count(slots, 24, max_cosmetic_slots);
|
||||
std::vector<std::uint32_t> ids(wanted);
|
||||
std::vector<std::size_t> sizes(wanted);
|
||||
bool same = r.items.size() == wanted;
|
||||
for (std::size_t i = 0; i < wanted; ++i) {
|
||||
const auto slot = ptr(slots, i * 24 + 8) & ~std::uintptr_t{4};
|
||||
ids[i] = get<std::uint32_t>(slot, 0x4c);
|
||||
sizes[i] = count(ptr(slot, 0x18), 4, max_cosmetic_parameters);
|
||||
same = same && r.items[i].slot == ids[i] && r.items[i].parameters.size() == sizes[i];
|
||||
}
|
||||
if (same) return {};
|
||||
std::vector<bool> used(r.items.size());
|
||||
std::vector<CosmeticSlot> fitted;
|
||||
fitted.reserve(wanted);
|
||||
std::size_t empty{};
|
||||
for (std::size_t i = 0; i < wanted; ++i) {
|
||||
std::size_t from = 0;
|
||||
while (from < r.items.size() && (used[from] || r.items[from].slot != ids[i])) ++from;
|
||||
if (from == r.items.size()) {
|
||||
++empty;
|
||||
fitted.push_back({ids[i], {}, own(ids[i], sizes[i])});
|
||||
continue;
|
||||
}
|
||||
used[from] = true;
|
||||
fitted.push_back(std::move(r.items[from]));
|
||||
if (fitted.back().parameters.size() != sizes[i]) fitted.back().parameters = own(ids[i], sizes[i]);
|
||||
}
|
||||
const auto left_out = static_cast<std::size_t>(std::count(used.begin(), used.end(), false));
|
||||
r.items = std::move(fitted);
|
||||
return {empty, left_out};
|
||||
}
|
||||
void validate(std::uintptr_t res, const CosmeticRecipe &r) const {
|
||||
check(r.key == get<std::uint32_t>(res, 0x38) && r.version == get<std::uint32_t>(res, 0x3c),
|
||||
"Peer cosmetic template differs from this game.");
|
||||
|
||||
@@ -618,6 +618,23 @@ void cosmetic_layout_regression() {
|
||||
check(modded.items[0].asset.empty() && !reject(m, modded), "A missing peer item without a default must become empty");
|
||||
modded = one;
|
||||
check(fake.substitute_missing(res, modded, fallbacks).empty() && modded == one, "Installed peer items must stay");
|
||||
// A peer whose mods add slots (or who lacks this game's): items go to this game's slots by slot hash.
|
||||
const auto own = [](std::uint32_t, std::size_t size) { return std::vector<std::uint32_t>(size, 7); };
|
||||
modded = one;
|
||||
check(fake.fit_slots(res, modded, own) == std::pair<std::size_t, std::size_t>{} && modded == one,
|
||||
"A recipe with this game's slots must not be touched");
|
||||
modded.items = {{99, "Own_Sticker", {1, 2}}, one.items[0]};
|
||||
check(fake.fit_slots(res, modded, own) == std::pair<std::size_t, std::size_t>{0, 1} && modded == one && !reject(m, modded),
|
||||
"An item in a slot this game lacks must be left out, and the rest kept");
|
||||
modded.items = {{99, "Own_Sticker", {1, 2}}};
|
||||
check(fake.fit_slots(res, modded, own) == std::pair<std::size_t, std::size_t>{1, 1} && modded.items.size() == 1 &&
|
||||
modded.items[0] == CosmeticSlot{11, "", {7}} && !reject(m, modded),
|
||||
"A slot the peer lacks must stay empty with this player's parameters");
|
||||
modded = one;
|
||||
modded.items[0].parameters = {1, 2, 3};
|
||||
check(fake.fit_slots(res, modded, own) == std::pair<std::size_t, std::size_t>{} &&
|
||||
modded.items[0] == CosmeticSlot{11, "Own_Shirt", {7}} && !reject(m, modded),
|
||||
"An item whose slot takes other parameters here must keep its place");
|
||||
auto bad = m;
|
||||
bad.put(categories, category + 0x100);
|
||||
bad.put(category + 0x138, std::uint32_t{88});
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "replay_guard.h"
|
||||
#include "Engine/Core/Hooks/hooks.h"
|
||||
#include "Engine/Core/Log/logging.h"
|
||||
#include "Engine/Core/Platform/memory.h"
|
||||
#include "Engine/Game/Build/addresses.h"
|
||||
#include "Engine/Game/Build/20260929/replay_recorder.h"
|
||||
#include <Windows.h>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
|
||||
namespace dingosdk::replay_guard {
|
||||
namespace {
|
||||
namespace rr = addr::replay_recorder;
|
||||
// (Two arguments are read; the others are passed on as they came.)
|
||||
using EndChunk = std::uint64_t (*)(void*, std::uint64_t, std::uint64_t, std::uint64_t);
|
||||
EndChunk original{};
|
||||
std::uintptr_t fault_at{};
|
||||
std::atomic<bool> installed{};
|
||||
std::atomic<std::uint64_t> skips{};
|
||||
|
||||
// Only the write to the chunk head the stream did not give: nothing else is this guard's.
|
||||
int ours(const EXCEPTION_POINTERS* info) noexcept {
|
||||
const auto& record = *info->ExceptionRecord;
|
||||
return record.ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
|
||||
reinterpret_cast<std::uintptr_t>(record.ExceptionAddress) == fault_at
|
||||
? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
// Said the first time and then now and again: it can happen every few frames once it starts.
|
||||
__declspec(noinline) void note_skip() noexcept {
|
||||
const auto count = skips.fetch_add(1, std::memory_order_relaxed) + 1;
|
||||
if (count != 1 && count % 1000) return;
|
||||
try {
|
||||
logging::log(logging::Level::warning, logging::Channel::runtime,
|
||||
"Replay recording: the game had no room for its next chunk and would have crashed; the chunk was skipped "
|
||||
"({} so far). Replays of this stretch may have gaps.", count);
|
||||
} catch (...) {}
|
||||
}
|
||||
std::uint64_t guarded(void* recorder, std::uint64_t force, std::uint64_t third, std::uint64_t fourth) {
|
||||
__try {
|
||||
return original(recorder, force, third, fourth);
|
||||
} __except (ours(GetExceptionInformation())) {
|
||||
note_skip();
|
||||
return 0; // no chunk was ended
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool install(std::uintptr_t base) noexcept {
|
||||
if (installed.exchange(true)) return original != nullptr;
|
||||
if (!base) return false;
|
||||
std::array<unsigned char, 32> bytes{};
|
||||
if (!memory::peek(base + rr::end_chunk.rva, bytes) || bytes != rr::end_chunk.bytes) {
|
||||
logging::log(logging::Level::warning, logging::Channel::runtime,
|
||||
"Replay guard: this build's replay recorder differs; it is left as it is.");
|
||||
return false;
|
||||
}
|
||||
fault_at = base + rr::end_chunk_head_store;
|
||||
const auto target = reinterpret_cast<void*>(base + rr::end_chunk.rva);
|
||||
if (hook_prepare(target, reinterpret_cast<void*>(&guarded), reinterpret_cast<void**>(&original)) != HookOk ||
|
||||
hook_enable(target) != HookOk) {
|
||||
original = nullptr;
|
||||
logging::log(logging::Level::warning, logging::Channel::runtime, "Replay guard: the replay recorder could not be hooked.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::uint64_t skipped() noexcept { return skips.load(std::memory_order_relaxed); }
|
||||
} // namespace dingosdk::replay_guard
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
// The game's replay recording crashes when its stream has no room for the next chunk: it writes
|
||||
// to the chunk it was not given (Engine/Game/Build/<build>/replay_recorder.h). The guard runs
|
||||
// that one function under an exception handler and, for that one fault alone, has it return as
|
||||
// if no chunk was ended: the game goes on, with a gap or a glitch in the replay where it would
|
||||
// have closed. Every other fault is left to the crash reporter.
|
||||
namespace dingosdk::replay_guard {
|
||||
// Checks this build's function and hooks it; once. False when the build differs (no guard).
|
||||
bool install(std::uintptr_t base) noexcept;
|
||||
// How many chunks were skipped since the game started.
|
||||
std::uint64_t skipped() noexcept;
|
||||
}
|
||||
@@ -565,8 +565,22 @@ void tick_page(std::uintptr_t base, bool loading) noexcept {
|
||||
// Tell the overlay while this page is the one on screen: it draws the body.
|
||||
const bool ours = shown_tab == our_key || shown_tab == our_key + tools_page * 0x100;
|
||||
const auto& shown_page = page_state(shown_tab == our_key ? 0 : tools_page);
|
||||
const bool on_screen = ours && game_in_menu.load(std::memory_order_relaxed) && shown_page.page.handle &&
|
||||
context.type_of(shown_page.page.handle) == shown_page.page.type;
|
||||
bool on_screen = ours && game_in_menu.load(std::memory_order_relaxed) && shown_page.page.handle &&
|
||||
context.type_of(shown_page.page.handle) == shown_page.page.type;
|
||||
// The game's side menu (pause pressed again) and what opens from it (Settings...) go
|
||||
// over the page without closing it: the page's focused index is -1 for that long,
|
||||
// and 0 or more while the page has the player. Not ours to draw over then.
|
||||
if (on_screen) {
|
||||
try {
|
||||
// (The page's screen record, the part every screen of the game has, and in it the index.)
|
||||
on_screen = read<int>(context.address(context.path(shown_page.page, {0xfafda1a6, 0x20a39d92, 0x6b01fd01}))) >= 0;
|
||||
} catch (const std::exception& e) {
|
||||
// A page laid out another way: as before, and said once.
|
||||
static bool said{};
|
||||
if (!std::exchange(said, true)) logging::write(logging::Level::warning, logging::Channel::ui,
|
||||
std::string("Native menu: the page's focus could not be read (") + e.what() + "); it stays up under the game's side menu.");
|
||||
} catch (...) {}
|
||||
}
|
||||
// (Said at once when another page takes its place, not left to go stale.)
|
||||
page_shown.store(shown_tab == our_key ? 0 : 1, std::memory_order_relaxed);
|
||||
page_seen.store(on_screen ? now : 0, std::memory_order_relaxed);
|
||||
|
||||
@@ -1345,6 +1345,11 @@ bool hub_page_pending() {
|
||||
set_typing(h, 0);
|
||||
wipe(h.password), wipe(h.code_password), wipe(h.host_password);
|
||||
h.notice.clear();
|
||||
} else {
|
||||
// What is held as the page comes up is not a press on it: the Back that closed the
|
||||
// game's side menu over it would dismiss the page as well.
|
||||
h.keys_before.fill(true);
|
||||
h.pad_before = ~0U;
|
||||
}
|
||||
}
|
||||
// With the overlay's own menu or console open the page stays where it is, behind them, and
|
||||
|
||||
@@ -470,6 +470,9 @@ void Launcher::run_play() {
|
||||
if (std::find(arguments_.begin(), arguments_.end(), L"-offline") != arguments_.end() ||
|
||||
std::find(arguments_.begin(), arguments_.end(), L"--offline") != arguments_.end())
|
||||
options.offline = true;
|
||||
// And a map to start on, over one in the saved launch options.
|
||||
if (auto arguments = arguments_; true)
|
||||
if (auto map = launcher::take_map_option(arguments); !map.empty()) options.map = std::move(map);
|
||||
launched_ = false;
|
||||
launcher_app::start_game(session_, options, [this](DWORD id) { game_ = id; });
|
||||
launched_ = true;
|
||||
|
||||
@@ -711,6 +711,15 @@ DWORD start_game(const Session& session, const launcher::LaunchOptions& options,
|
||||
command += quote_argument(argument);
|
||||
}
|
||||
set_environment(L"RESKATE_GPU_DIAGNOSTICS", options.gpu_diagnostics ? L"1" : L"0");
|
||||
// -map: the game loads it once it is up, as the console's "load" would (client_tick.cpp),
|
||||
// ahead of any startup commands already asked for.
|
||||
if (!options.map.empty()) {
|
||||
std::wstring commands = L"load " + options.map;
|
||||
std::wstring already(4096, L'\0');
|
||||
const auto length = GetEnvironmentVariableW(L"RESKATE_STARTUP_COMMANDS", already.data(), 4096);
|
||||
if (length && length < 4096) commands += L";" + already.substr(0, length);
|
||||
set_environment(L"RESKATE_STARTUP_COMMANDS", commands.c_str());
|
||||
}
|
||||
set_environment(L"RESKATE_DISCORD", options.discord ? L"1" : L"0");
|
||||
if (options.menu_key == options.console_key)
|
||||
throw std::runtime_error("The menu and console need different keys. Change one in Settings.");
|
||||
|
||||
+5
-2
@@ -72,8 +72,11 @@ void run_headless(const app::Session& session, std::vector<std::wstring> argumen
|
||||
const bool relaunched = take_flag(arguments, L"--reskate-updated");
|
||||
const bool updates = !take_flag(arguments, L"--no-update") && dingosdk::launcher_gui::updates_enabled(session);
|
||||
// With no options of its own, the launch is the one the launcher window's Play would make.
|
||||
const auto options = arguments.empty() ? dingosdk::launcher_gui::saved_launch_options(session)
|
||||
: dingosdk::launcher::parse_launch_options(arguments);
|
||||
// A map to start on is not one of those: "--no-gui -map <name>" is that launch, on that map.
|
||||
auto map = dingosdk::launcher::take_map_option(arguments);
|
||||
auto options = arguments.empty() ? dingosdk::launcher_gui::saved_launch_options(session)
|
||||
: dingosdk::launcher::parse_launch_options(arguments);
|
||||
if (!map.empty()) options.map = std::move(map);
|
||||
update::remove_previous_launcher(session.self);
|
||||
if (updates) {
|
||||
const auto config = update::fetch_config();
|
||||
|
||||
@@ -215,6 +215,7 @@ Useful launcher flags:
|
||||
| `--log-trace` | the same as `--log-level=trace`; an explicit `--log-level` wins |
|
||||
| `-wconsole` | also show the log live in a console window while the game runs |
|
||||
| `--menu-key=0x2D`, `--console-key=0xC0` | menu and console keys (virtual-key codes) |
|
||||
| `-map <name>` | load that map as soon as the game is up, e.g. `-map "San Vansterdam"`; the name is a map's name, short name or asset path, or the start of one |
|
||||
| `--no-loose-files` | ignore loose Lua and config files beside the game |
|
||||
| `--gpu-diagnostics` | record extra detail when the graphics driver crashes (DRED) |
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ bool initialize_bootstrap(std::uintptr_t base) {
|
||||
error.clear(); ready = start_native_render_resource_pool(base, error);
|
||||
if (!stage(Channel::assets, "Native render-resource pools", ready, error)) return false;
|
||||
error.clear(); ready = start_native_entity_pages(base, error);
|
||||
if (!stage(Channel::world, "Native entity pages (1048576 entity/update/render slots, 16384 spatial blocks/bucket, 128 MiB arena minimum)", ready, error)) return false;
|
||||
if (!stage(Channel::world, "Native entity pages (524288 entity/update slots, 1048576 render slots, 16384 spatial blocks/bucket, 128 MiB arena minimum)", ready, error)) return false;
|
||||
error.clear(); ready = start_physics_world_size(base, error);
|
||||
if (!stage(Channel::world, "Physics world pools (65000 static bodies)", ready, error)) return false;
|
||||
error.clear(); ready = start_native_route_lookahead(base, error);
|
||||
|
||||
+29
-1
@@ -35,6 +35,7 @@
|
||||
#include "Extension/World/level_loading.h"
|
||||
#include "Extension/World/loading_screen.h"
|
||||
#include <dxgi.h>
|
||||
#include <Psapi.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
@@ -294,7 +295,8 @@ void update_model(std::uintptr_t client, TickState& frame) {
|
||||
r.next_named_settings_publish = settings_now + 250;
|
||||
publish_named_settings(r);
|
||||
}
|
||||
// RESKATE_STARTUP_COMMANDS="load skate1map;noclip 1" (development): console commands
|
||||
// RESKATE_STARTUP_COMMANDS="load skate1map;noclip 1" (development, and the launcher's
|
||||
// -map <name>, which is a "load" at the front of it): console commands
|
||||
// queued in order once the world is up and can accept them, so a build can be exercised
|
||||
// without anyone driving the overlay. A load waits for its destination to be listed.
|
||||
{
|
||||
@@ -1186,6 +1188,32 @@ void tick(std::uintptr_t client, std::uintptr_t update) {
|
||||
dingosdk::map_download::tick();
|
||||
}
|
||||
dingosdk::multiplayer::refresh_identity_lists();
|
||||
// How much memory the game holds, beside what a session adds to it: said when it has
|
||||
// moved by a quarter of a gigabyte or the players or skaters have changed much, at most
|
||||
// every ten seconds. For telling what a full server's memory goes on (the map, every
|
||||
// player, or only the skaters that are built).
|
||||
if (static std::uint64_t next_memory{}; GetTickCount64() >= next_memory) {
|
||||
next_memory = GetTickCount64() + 10000;
|
||||
PROCESS_MEMORY_COUNTERS_EX counters{};
|
||||
counters.cb = sizeof(counters);
|
||||
if (GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&counters), sizeof(counters))) {
|
||||
const auto mp = dingosdk::multiplayer::model();
|
||||
const bool session = mp.active && !mp.echo && (mp.hosting || mp.connected);
|
||||
const int players = session ? static_cast<int>(mp.roster.size()) : 0;
|
||||
const int skaters = session ? static_cast<int>(std::ranges::count_if(mp.roster, [](const auto& player) { return player.visible; })) : 0;
|
||||
static std::uint64_t said_private{};
|
||||
static int said_players = -1, said_skaters = -1;
|
||||
const auto moved = counters.PrivateUsage > said_private ? counters.PrivateUsage - said_private : said_private - counters.PrivateUsage;
|
||||
if (moved >= (256ull << 20) || std::abs(players - said_players) >= 5 || std::abs(skaters - said_skaters) >= 5) {
|
||||
said_private = counters.PrivateUsage; said_players = players; said_skaters = skaters;
|
||||
const auto gigabytes = [](std::uint64_t bytes) { return static_cast<double>(bytes) / (1024.0 * 1024.0 * 1024.0); };
|
||||
dingosdk::logging::printf(dingosdk::logging::Level::info, dingosdk::logging::Channel::runtime,
|
||||
"Memory: %.2f GB committed, %.2f GB in RAM; %d player(s) in the session, %d built as skaters (player distance %.0f m); map %s.",
|
||||
gigabytes(counters.PrivateUsage), gigabytes(counters.WorkingSetSize), players, skaters, mp.player_distance,
|
||||
(session && !mp.map.empty() ? mp.map : r.multiplayer_map).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
// The player's Discord status (discord_presence.h): where they skate and with whom,
|
||||
// looked at every couple of seconds.
|
||||
if (static std::uint64_t next_presence{}; dingosdk::discord_presence::available() && GetTickCount64() >= next_presence) {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "Engine/Core/Log/logging.h"
|
||||
#include "Engine/Core/Profiling/profiler.h"
|
||||
#include "Extension/Settings/engine_tweaks.h"
|
||||
#include "Extension/Settings/replay_guard.h"
|
||||
#include "Extension/Console/commands.h"
|
||||
#include "Extension/UI/ui_pointer_skip.h"
|
||||
#include "Engine/Game/Build/addresses.h"
|
||||
#include "Engine/Game/Build/20260929/profiler_labels.h"
|
||||
@@ -310,6 +312,8 @@ extern "C" __declspec(dllexport) BOOL WINAPI DingoSDKDebugInitialize() {
|
||||
start_frame_timing();
|
||||
(void)dingosdk::ui_pointer::install(r.base);
|
||||
(void)dingosdk::engine_tweaks::install(r.base);
|
||||
(void)dingosdk::replay_guard::install(r.base);
|
||||
dingosdk::console::start_memory_trace_from_environment();
|
||||
const bool fixed_stop_provider = (global_offline_hook && progression_guard_armed) &&
|
||||
dingosdk::prepare_fixed_stop_entitlement_provider(r.base);
|
||||
record("{\"event\":\"fixed_stop_entitlement_provider_initialized\",\"prepared\":" +
|
||||
|
||||
@@ -69,6 +69,7 @@ add_library(dingosdk_runtime SHARED
|
||||
Extension/Settings/console_commands.cpp
|
||||
Extension/Settings/job_spin.cpp
|
||||
Extension/Settings/engine_tweaks.cpp
|
||||
Extension/Settings/replay_guard.cpp
|
||||
Extension/UI/ui_pointer_skip.cpp
|
||||
Extension/Settings/named_settings.cpp
|
||||
Extension/World/console_commands.cpp
|
||||
|
||||
Reference in new issue
Block a user