The first level the game loads from the splash took San Vansterdam, and the startup commands'
"load" then loaded the start map over it. queue_menu_bam now takes the map from the front of
RESKATE_STARTUP_COMMANDS when it is installed and can load (its start point as the console's
"load" picks one), and the startup commands drop that "load" rather than run it again. A map that
cannot load then still leaves the game in San Vansterdam.
The launcher lists San Vansterdam, the game's other maps and the custom maps of the mods that
load (start_maps.h), keeps the choice with its settings and starts the game in it, as its -map
does: a "load" at the front of the startup commands. A map no longer listed when the world can
load it (a map mod switched off or left out of the merge) is dropped after 20 s, and the game stays
in San Vansterdam. A launcher kept open no longer adds a launch's map to the last one's commands.
Tests: Launcher/Test/start_maps_tests.cpp.
Now that features are Luau plugins, nothing needs mods of ReSkate's own:
- The OFFICIAL tab and its rail tile are gone, with Launcher/official_mods (the backend's list, the
install, update and sync, and Play's wait for them).
- GET MODS lists and updates Board Break, Road Rash and the rest like any other package, and MY
MODS no longer marks them Official or keeps them out of UPDATE ALL.
- The merge may leave one out over a conflict like any other mod; the version stamp, the on/off
helpers and the move out of the old .reskate-official folder are gone from builtin_packs.
- Installed copies stay in Mods as ordinary mods. The retired first Board Break is still left out.
From pull request 301 (tsullivan13), fitted to the newer MY MODS page:
- UPDATE ALL leaves the left rail for a bar over the list, made like the conflicts bar and
under it: how many updates wait and what they download, each mod's old -> new version (the
first six, then how many more), Show only these (the Updates filter and back) and
UPDATE ALL (N) with the download size. Hidden with nothing waiting, off while an install runs.
- A row with an update shows its old -> new version in blue after the author.
- Ctrl+F goes to the search box on MY MODS and GET MODS, as their placeholders say.
Co-authored-by: tsullivan13 <25965236+tsullivan13@users.noreply.github.com>
Resolved where main's trainer meets the plugin branch:
- Board Break, the drone, Road Rash, Hall of Meat and Grind Exits are plugins here, so their
built-in code stays deleted: the trainer no longer hands Board Break's wear values back (the
plugin does not tune physics), its QUICK SETTINGS list no longer names Grind Exits or Board
Break, and the drone's debug action and menu are not brought back.
- The trainer's pump power, gravity, revert boost and transition help run beside the plugins'
pushes and velocities on each physics step; both sides' new declarations are kept.
- The game's own pad reads go through game_pad_read (the gamepad filter, Dark Pop's D-pad hiding,
the grind sticks) and then the plugin branch's menu and hidden-button handling.
- The trainer's forced grind settings are noted as the stance like any other value.
From 2.1.1's Sentry reports (60,000 in three days, 2026-10-21):
- Textures: a stale render texture handle takes the game's default texture instead of reading
through null (Skate.exe+0x3e897fb, a third of all reports, every one with TheVlixOne-Nike_Pack 2.3.x).
- Physics: the wake pass's bitset is made as long as the world's owner list once indices pass
20000, after long multiplayer sessions (+0x3d99e2f, +0x3d9ee43, +0x3d9ee47).
- Music: more than 1024 candidates are picked by ReSkate; the game's shuffle wrote past its stack table.
- Streaming: a staged read's piece that reaches past its 64 KB buffer is left unfilled (VCRUNTIME memcpy).
- Multiplayer: a remote skater or board whose parent bus link is damaged is left alive instead of
destroyed (+0x2b94cd0).
- Mesh pool: on an integrated GPU its budget is capped by the RAM and page file free; the Memory
line says what the PC has left.
Launcher:
- A folder with non-ASCII letters is a hard stop (the boot crash +0x18df4cf came after "Start anyway").
- The game's data files are checked against the supported build's sizes (from Steam's manifest);
missing, cut-short or online-only files send the player to verifying.
- One game per folder: the launcher will not merge or start while one runs there, and ReSkate.dll
holds the folder's mutex.
- Advice on the ready screen for PCs short of RAM and page file; reports carry pc.ram_gb and
pc.commit_free_gb.
Stuck loads:
- A load in one stage for two minutes sends a stuck-load report (every thread's stack and the log,
error.type stall, load.stage, load.seconds) while the game goes on (crash protocol 6).
- A load the player closes sends its timing with the stage it was in.
Logs: the PanelTrace diagnostics and the neighborhood unlock override's observation lines are gone.
The launcher fell back on a list of its own (Board Break's pack and Road Rash) before it had ever
read one from ReSkate. Official mods now come only from that list.
MY MODS: a table with an animated drag for the load order, a conflicts bar with Check conflicts, and a Resolve popup whose choices are kept. The check runs at startup and after changes; conflicts no longer show as problems, block Play, or hold mod files during an update.
Conflicts: only game EBX that cannot be combined, or Lua scripts with different versions; colourways and same-name additions are not conflicts.
Official mods: installed in Mods/<Namespace-Name> and turned on or off through mods.json, so they show in MY MODS; the old .reskate-official folder is moved over.
Merge: a scan cache (Mods/.reskate-scan.txt) keeps each unchanged mod's repair, mesh and texture scans, so big maps are not re-read every merge.
Launcher: an announcement from the backend shows under STATUS, with HIDE.
The device-removal watcher always runs, and the fatal handler notes a DXGI stop in gpu-breadcrumbs.txt. Crash reports carry a gpu.breadcrumbs tag (protocol 5).
Where two mods change one of the game's assets in ways that cannot both be
in the game (a resource or chunk changed differently, an EBX whose changes
cannot be combined, different assets added under one name), the one lower
in the load order is left out whole, so neither loads half its changes.
The merge used to keep the higher copy of each asset and lose the rest of
the lower mod's change silently, which broke Skaterize beside deckorate.
A check before the merge (find_conflicts) reads only the bundles two or
more mods ship and applies the merge's rule: about 2 s for 296 mods, on
several threads, each mod's copy of a bundle by itself. When it finds
conflicts nothing is built, the catalog leaves the losing mods out and
merges once. The merge keeps its own check behind it, tracking per asset
the last change a mod made itself, so a change carried through other mods'
copies is still caught. A conflict is remembered in .reskate-excluded.json
with the mod it lost to, and stays out while both are unchanged and the
winner still loads above it.
The launcher says "Checking the mods" and "Checking the mods for
conflicts" during those steps. Its mod problems screen says MOD CONFLICT
when that is all there is, and the Mod Manager shows a CONFLICT badge, an
N CONFLICTS banner, a Conflicts filter and, on the mod, which mod it lost
to and how to load it instead.
The trainer keeps upstream's page and naming (SANDBOX; noclip, No Bail and
the boosts on Skater > Cheats; the full screen controller menu) with its own
TUNE sections, presets card and search inside. The MOVEMENT tab is gone:
`trainer open movement` opens Skater > Cheats, where the Revert Boost rows
now sit. Upstream's Hardcore preset sits beside Realistic; saving
trainer.json and reading the map file stay off the client thread.
Board Break's wear and the trainer no longer undo each other: wear writes
four tuning values itself, and every trainer write used to put them back to
the trainer's copy (and a level loaded on a worn board took them as stock).
board_break::handling_value() tells the trainer what wear wants; values the
player has not changed are handed back to it, their stock is the game's own.
Tests: Hardcore's check follows the sections (topic, not the old lists);
the session test pokes a flip speed past the trainer's own limit (100).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
UNINSTALL, under OPEN FOLDER, takes the mod's stamp away first (a folder
without it is no mod to the game), then its folder, and clears whether it
was turned off so an install brings it back on. The card says UNINSTALLING
meanwhile, and UNINSTALL FAILED when Windows keeps the files (Skate still
running). Cards are as tall as their buttons.
The launcher still reads the list at start and looks up each mod's latest
version, moves in a copy installed from Thunderstore and takes away retired
mods, but it downloads nothing by itself. Each card on the OFFICIAL tab says
NOT INSTALLED, INSTALLED, UPDATE AVAILABLE, DOWNLOADING or UPDATING, with an
INSTALL or UPDATE TO vX button (official_mods::install, on a thread of its
own), OPEN FOLDER once installed, and the On / Off switch beside its pills.
The banner counts how many are installed. Play waits for an install under
way.
Board Break and Road Rash start only when their official mod is installed
and on (mods::official_in_use), and say in the log which it is not; the
menus leave them out otherwise, as when turned off.
The live test (RESKATE_OFFICIAL_LIVE) checks that nothing downloads until
asked, then installs each.
The OFFICIAL tab has an on/off switch on each mod's card, with an OFF pill
while it is off. The list of those turned off is
Mods/.reskate-official/official-off.txt, one folder name a line, which the
launcher's sync never removes. A mod turned off stays downloaded and kept
up to date, but official_packs() leaves it out, so nothing merges it, no
deck comes from it and the in-game Mods page does not list it.
Board Break and Road Rash do not start while their official mod is off,
and say so in the log. The menu model carries that as `off`, and the side
rail, the addon tabs and tiles, the home tiles, the pause menu's settings
and the native tools menu leave them out without a gap. category_tabs
takes a list built at run time for that.
Tests: an official mod turned off stays in place and is left out, comes
back when turned on, and only a plain folder name is written.
Both documents come from the ReSkate backend (GET /api/v1/legal/privacy and /terms, edited on its
Legal page), so a change reaches players without a release. Settings has a button for each, opening
a panel like the changelogs': title, version and date, the Markdown drawn as the README viewer draws
it, and a switch to the other one.
Each launch looks up the current versions (GET /api/v1/legal) in the background. One newer than
the player agreed to, or none agreed to yet, puts up an agreement over the home screen: a short
summary, a way into each document, QUIT and I AGREE, which saves the versions agreed to
(accepted_privacy_version, accepted_terms_version in the launcher's settings). A backend that
cannot be reached holds nobody up. Launches that skip the window (--no-gui, Discord joins) are
not asked.
The game finds its own folder with the ANSI GetModuleFileNameA and decodes it as UTF-8, so a path
with Cyrillic, accented or Japanese characters (often a OneDrive folder) crashes it on start
(Skate.exe+0x18df4cf in Sentry). The launcher now says so and asks before starting; No is the default.
Steam for Mac with NotProton or CrossOver passes the compatibility tool a path inside its app
bundle, below the folder with config/loginusers.vdf, and the tool's stand-in keeps no record of the
running client, so the launcher said Steam was not running and started offline. It now looks up
from that path for config/loginusers.vdf, and when started by the native Steam client under Wine
takes its most recent account where the running-client checks fail. Windows and Proton, where those
checks pass, are unchanged. The offline panel's hint about the launch option shows only under Wine.
MACOS-SETUP.md gives the launch option (/bin/bash, ROSETTA_ADVERTISE_AVX=1 for the game's CPU
check) for the launcher in a folder of its own.
Based on https://github.com/Dingo-Shenanigans/ReSkate/pull/219.
Co-authored-by: codejunky <pmp.codejunky@gmail.com>
The update check reads GitHub's release list either way (one call, as before) and notes whether a
pre-release newer than the latest release is there; the setting is offered only then, or while it
is on so it can be turned off. Unreachable GitHub keeps what the last check found.
Flipping "Install ReSkate updates" or "Test pre-releases" saves and checks again straight away, so
PLAY or the update button changes to match: updates off while one is offered goes back to PLAY,
pre-releases on offers the pre-release, off the latest release. A flip while a check is running is
checked as soon as it ends (each frame asks; it only compares two settings).
Reported in #265 by Kayyo321; first fixed in #267 by Jean-LucTch, whose
approach this keeps to the folder being installed.
"Install folder" named each file with fs::relative, which follows links:
a file link inside the folder to a file outside it came out as
../../<file>, and the copy wrote over that file (ReSkate.dll among what
it could reach).
- Files are named by where they sit in the chosen folder
(lexically_relative), never by where a link leads, and go through
safe_entry like a zip's entries.
- A symbolic link, junction or mount point inside the folder refuses the
install, saying which. Links on the way to the folder or to the Mods
folder (a library moved to another drive) stay fine, as do cloud
placeholders such as OneDrive's, which name nothing else: #267 refused
any reparse point on those paths, so a game reached through a junction
could install nothing.
- Tests: a junction inside a mod folder is refused and the file it leads
to is untouched, with no staging left behind (this fails without the
fix); a Mods folder and a picked folder reached through junctions still
install; a file symbolic link is refused (skipped without Developer
Mode, which creating one needs).
Co-authored-by: Jean-Luc T. <88255067+Jean-LucTch@users.noreply.github.com>
- page_banner: each page opens with its heading, what it is for, and how
things stand at the right (a status pill and a caption). card: the
panel the pages draw on, lighter edged on hover, blue edged when marked.
- MY MODS and GET MODS rows are cards with a gap between them (list_row),
in lists without a border. MY MODS' banner counts problems and waiting
updates and holds the load-order explanation; GET MODS' says whether
the listing loaded and what is installed or waiting. The ticked bar on
GET MODS is a card.
- OFFICIAL: a card per mod with its status and version pills, its
Thunderstore facts, and THUNDERSTORE and OPEN FOLDER.
- PROFILES: new-profile and import cards side by side; a card per profile
with a picture of its first mods' icons, pills for what it holds, LOAD
and UPDATE, and the rest in a menu.
- The borderless window has a frame style for resizing, snapping and its
shadow, with WM_NCCALCSIZE keeping the whole window client. Its edges
and corners resize it; maximised, it is inset by the frame Windows puts
past the screen.
- WM_GETMINMAXINFO holds it to the size it opens at.
- The swap chain's buffers follow the client size (Renderer::resize).
- Frames are drawn from WM_SIZE too, so dragging an edge (Windows' own
message loop) does not stretch the last frame.
Every update, and every install over an installed mod, sent the old
folder to the Recycle Bin, which filled up with old versions.
- commit() moves the installed copy aside into the staging folder, moves
the new one in, then deletes the old for good. A new copy that cannot
go in puts the old one back; a copy with a file in use is not replaced
and stays whole.
- Uninstalling still goes to the Recycle Bin. The Replace dialog says the
installed copy is deleted.
The launcher reads the official list from the ReSkate backend (or the last one it read, or its own)
and keeps each mod in Mods/.reskate-official at its latest version; a copy the player installed is
moved in, the deprecated Board Break retired. The game loads them always on and leaves out Mods
folder copies; the browser no longer lists them. The built-in zips are gone (FPV drone too), and
built-in folders no longer carried are removed.
Fourth Studio's Board Break pack (ten decks and every sound) and Road Rash wounds are built into
ReSkate.dll beside the FPV drone, unpacked under Mods/.reskate-builtin and always on.
- The Thunderstore copies (Fourth_Studio-Board_Break_Pack, Fourth_Studio-Road_Rash and the
deprecated Fourth_Studio-Board_Break, or the same put in by hand) are moved to the Recycle Bin
as the launcher starts and dropped from mods.json; the merge leaves them out should one still
be there, and the Thunderstore browser no longer lists, updates or installs them, a dependency
on one included.
- Board Break's deck list, sounds and deck settings look in the built-in packs too.
- Names with spaces inside them (Board Break's "Body Impact 1.wav") unpack.
- The build makes each zip in assets/builtin into one zstd stream (ReSkateBuiltinPacker,
Engine/Vfs/builtin_pack_format.h), which the DLL carries: repeated files across a pack cost next
to nothing. Board Break 15.0 -> 5.4 MB, the drone 6.0 -> 5.4 MB, Road Rash 36.1 -> 34.2 MB;
ReSkate.dll 86 -> 70 MB. Plain zips still unpack.
- Tests: the mods taken for built-in ones and their retirement, and a pack unpacking to exactly
its files, refusing one that leaves its folder or is cut short (RESKATE_BUILTIN_PACKS also
unpacks the packs a build made).
path::string() uses the ANSI code page and throws on a character it lacks (a Cyrillic folder on
an English Windows). The remaining places it was used now go through path_utf8:
- Mods: a deck folder or a mod folder named outside the code page no longer leaves the Board Break
decks empty, or the Mods folder ignored altogether.
- Game and mod archives: a file under Win32 with such a name is passed over instead of stopping
the read.
- pose-dump no longer ends the multiplayer session when the game folder is not ASCII.
- The item browser's status line and a Board Break warning no longer fail on such a path.
- Launcher: system fonts are named to ImGui in UTF-8, which it reads.
Sentry's minidump endpoint streams every attachment but the dump to an object store, which this
self-hosted Sentry does not run: ReSkate.log and report.json were dropped from every crash
(outcome upload_failed). Each crash now goes to the envelope endpoint as sentry-native sends one:
the event, the minidump, report.json and the log, all kept.
- The event carries the log's last 100 lines as breadcrumbs (debug lines only among the last 25),
the mods the game ran with (enabled, outdated, excluded), how long it had run, and an anonymous
install ID as its user. Its time is the crash's, however late it is sent.
- crash.site tags where it crashed ("Skate.exe+0x3d9ed9d"), as Sentry names game code by the
nearest export; mods.count how many mods were on.
- An accepted report is kept in sent/ (the newest 10) instead of deleted, so the player still has
their crashes.
- multipart.* is report_envelope.*; the receipt check also reads the envelope endpoint's
{"id": ...}.
Most crashes are caught by the game's own fatal handlers, which write a
dump of thread stacks only; the launcher could only copy it after the
game had exited. A crash on a freed or overwritten object then showed
the faulting registers but not the object or the list it came from.
- game_fatal_dump: the game's MiniDumpWriteDump import points at
ReSkate. Before the game writes its dump, the crash reporter takes its
own of the still-running game for the faulting thread; the game's dump
follows as before. Reports say capture.source "game-fatal-handler".
- The reporter's dumps include the memory the stacks point at
(MiniDumpWithIndirectlyReferencedMemory), a few MB more a report.
- The shared report says who asked for the dump (protocol version 4).
- Tests: a game-handler crash is captured with a heap block only its
stack points at; ReSkate's own capture keeps it too.
Turning "Install ReSkate updates" or "Test pre-releases" on or off took
effect at the next start. Closing settings after changing either now runs
the update check again: a pre-release is offered as soon as it is wanted,
the latest release when it no longer is, and a pending update is dropped
when updates are turned off.
- Not while a download, an update or a launch is under way, while the game
runs, or while a merge waits on an answer about mods; nor as the launcher
closes. The next check or start picks the change up then.
- The "Test pre-releases" help says the check happens when settings close.
Merges ReSkate v2.0.9.
- Wallies (the game's own switch) with their measured numbers; double / triple jump, jump
on release and wipeout bounce on foot; foot flip / spin speeds; no speed limit on foot.
- Flip speed and the per-trick Late flip speed now change late flips; Late flip start /
buffer rows.
- The trainer never changes the game's own settings (GAME SETTINGS rows only show them).
- Dark Pop 3.1 (Sivaes/darkpop, GPL-3.0), saved on and off like No Bail; Revert Boost 2.0.
- The search for the game's values walks memory once and shows in the panel.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Settings > Launcher > "Test pre-releases" (off by default). On, the update
check takes the newest GitHub release that is not a draft and carries a
launcher.json, pre-release or not, in place of the latest full release:
a pre-release newer than the last release is installed, pinned by size
and SHA-256 as any release is. Turned off, the next check goes back to
the latest release, whose files then replace the pre-release's.
- The update notice says "Pre-release" for one, and the log names which
kind of release was taken.
- The changelog shows the release the setting picks, marked as a
pre-release, and is fetched again when the setting changes.
- --no-gui launches follow the same setting.
The renderer gives each frame 131,072 shader-visible descriptors past a persistent 120,000, in
heaps of 333,333. Dense custom maps (the Los Santos City sublevels, San Andreas) draw more than
that in a frame, and the renderer wrote past the end of the heap: shaders read garbage
descriptors, which faulted or hung the GPU (page faults at nonsense addresses, in draws, texture
fetches and ray tracing alike). ReSkate now patches the device setup at boot so each heap is
D3D12's 1,000,000 and a frame may use 524,288; heaps are 644,288 descriptors. LS-B2, LS-B3 and
San Andreas (210,000 a frame at its peak) now hold.
Also in this change:
- Memory: perf memory owners/heap/gpu/report, a ledger of who commits the game's RAM; the
render-resource pool no longer allocates its 115 MB twice; the EadpErrorsData arena is
capped at 32 MiB (EA's error reporting is blocked anyway).
- Crash reports: tagged with the map, destination, graphics card and driver version (protocol
v3), so Sentry can group GPU hangs by map and card.
- GPU diagnostics (--gpu-diagnostics): a fuller DRED report, the device-removal and video
memory watches, a large-draw watch, a record of which game code made and freed each GPU heap
and resource, checks of every GPU address bound, and a meter of each descriptor heap's use.
- World pools: peak use of entity pages, render instances and spatial blocks in the log.
- dingosdk_mod_mesh_check: checks every MeshSet a mod ships against its geometry; the MeshSet
reader now knows static meshes' layout.
After Steam updated skate., some installs had the supported Skate.exe over
the new build's data (a copied game, or a download that stopped part-way).
The launcher called that ready, every mod was left out as "made for game
build 29544144, not the installed 29663206; rebuild it with ReSkate Studio",
and the mods stayed out after the game files were put right.
Launcher
- Ready now also needs the game's data to be the supported build, read from
Data\layout.toc against supported_build::game_data_changelist (29544144).
Data of another build, or none, reads "Game files need verifying".
- DOWNLOAD in that state checks every file (-validate) instead of fetching
only what is missing. A download that fails part-way no longer ends on
ready because Skate.exe arrived.
- Data whose build cannot be read does not block.
Mods
- A mod left out because the game was of another build is no longer
remembered in .reskate-excluded.json: it is checked on every launch. One
already remembered for it is looked at again.
- When it is the game that is not the supported build, the mod's message
says to verify the game files in the launcher, not to rebuild the mod.
"The Steam download did not finish" is the launcher's message for any
failed download, and what DepotDownloader said (the account does not own
the game, Steam refused the sign-in, the disk is full) was only written at
the debug level, so Open logs showed nothing to go on.
When a download fails, its last 40 lines are now written to the log as
warnings, after the exit code. The Steam login name is still left out, and
so are the rows of a QR code and the progress lines.
- The launcher refuses to start from a Steam library folder under
Wine/Proton as well; the check is no longer skipped there.
- README, Linux (Proton): the launcher and ReSkate.dll go in a new, empty
folder, and the Steam launch option swaps in the launcher's full path in
place of EA's anti-cheat launcher. Noted as not yet tested on Proton; the
earlier test was with the launcher beside Skate.exe.
Launcher: ReSkate lives in a folder of its own, not Steam's skate. folder
- The launcher refuses to start from a Steam library folder
(...\steamapps\common\<game>): it shows an error saying to move
ReSkateLauncher.exe and ReSkate.dll to a new, empty folder, then closes.
Checked before anything is read or written there. Not under Wine: on
Proton, Steam starts the launcher from the game's folder.
- The "not in your skate. folder" error no longer tells players to put the
files beside Skate.exe in Steam's folder; it now says to keep them together
in a folder of their own.
- README: Getting started says to extract into a new, empty folder, where the
launcher installs its own copy of the game, so a Steam update cannot break
it. The Proton section says why it is the one exception.
The Mods page has a third tab, PROFILES. A profile is a saved list of which
mods are on, in what order and at what version; every mod stays installed
once, in the one Mods folder. Loading a profile rewrites mods.json, switches
off what it does not name, and downloads from Thunderstore what it names
that is missing. Profiles live in Mods/profiles.json.
A profile travels the way r2modman's do, so the two managers read each
other's: export.r2x inside a .r2z file, and a code on Thunderstore's
profile service. Config files in an r2modman profile are ignored.
Installing or updating a Thunderstore package now brings the packages it
depends on, needed ones first, leaving out any already installed at a new
enough version. A mod pack is a package that is nothing else.
A kick, by an admin or by a passed vote, used to keep the player out until
the server restarted. "kick_minutes" in the players section of the config
(1-1440; 0, the default, is still until the restart) and the console
command "kick-time <minutes>|restart" now set how long it lasts.
The player is told how long when they are kicked, and how many minutes are
left if they try to join early. A kick keeps the time it was given, so
changing the setting is for later kicks. Bans are unchanged.
Crash dumps now go to the project's own Sentry server. The launcher's
out-of-process helper is unchanged; only where it posts and what it expects
back are:
- The default endpoint is the Sentry project's minidump URL. Report
attributes travel as Sentry tags, with the release as reskate@<version>.
- An upload counts as accepted when the server answers with an event ID.
- "backtrace" is "crash_report" throughout: the namespace, files, CMake
targets, DINGOSDK_CRASH_REPORT_URL, DINGOSDK_BUILD_CRASH_REPORT_TESTS and
the RESKATE_CRASH_REPORT_URL override.
Performance timings are new, and off unless "Send performance timings" is
ticked in the launcher's settings (RESKATE_TRACING=1). A small tracer
(Engine/Core/Debug/trace.h) posts each finished step to Sentry as a
transaction from a background thread; the launcher and the game it starts
share one trace. Timed: the update check, the Steam download, Thunderstore
installs, the mod merge, starting the game, the launch up to the first
playable level, each level load, joining a session, fetching the identity
lists, and the time spent in each level with its average frame rate and
long frames. Turning crash reports off turns timings off too.
- Gravity slider (POP AND TRICKS): gravity in the air on the board and on foot.
- TUNE's first section is PRESETS AND QUICK SETTINGS: every kind of preset in one card, and
everything that is changed in one list (change in place, Hide, Go to, Reset).
- trainer setup <key> <value>.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wk6Y7hSKoBANMm9ZHbStLg
TUNE as one page of folding sections, presets above the tabs, Skate 3 grind and
transition feel, Dark Pop, manual pop height, slow flips pop higher, per-trick
speeds, and a release audit of stock / resets / presets. See Extension/Trainer/CHANGELOG.md.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wk6Y7hSKoBANMm9ZHbStLg
Since 2.0.4 the DX12 backend compiles only the HDR-aware pixel shader at
runtime with D3DCompile(). Wine's builtin d3dcompiler (macOS, Apple's Game
Porting Toolkit) cannot build it, so ImGui_ImplDX12_CreateDeviceObjects()
failed and the launcher refused to open on every Mac.
Try the HDR-aware shader first, then the stock one 2.0.3 shipped (on a
failed compile or a failed pipeline). ImGui_ImplDX12_HasOutputTransfer()
tells the launcher and overlay which one is drawing, and they log it.
Windows keeps the HDR shader and HDR output as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In MY MODS, mods that have an update on Thunderstore come first, in every
sort order and with any filter or search. They keep their order among
themselves, and so do the rest.
Only the list changes: the load order, and so which mod wins where two
change the same thing, is as it was.
The arrows that move a mod in the load order are off while an update is
waiting, since the list is not in load order then; the tooltip says so.
Overlay in HDR
- ImGui draws sRGB colours, and the overlay wrote them straight into the
game's HDR buffer, where they came out far too bright and washed out.
The DX12 backend's pixel shader now converts them: to scRGB for an FP16
buffer, and to HDR10 (BT.2020, PQ) for a 10-bit buffer while the display
is in HDR, with white at 200 nits. An SDR buffer is drawn as before.
- The log says which was chosen ("Overlay output: ..."), and now also says
when the game presents in a format the overlay does not draw to, which
left its menus hidden with no reason given.
- Not seen on an HDR display. The changed shader compiles with the D3D
compiler.
DualSense
- While a menu holds the game's input, the reports the game reads from a
PlayStation pad are rewritten as untouched. USB and Bluetooth lay a
report out differently, and the two were told apart by the size of the
buffer the game read into. A USB DualSense read into a larger buffer had
its d-pad byte written as "up", which placed a session marker whenever T
or Insert opened something. The device's own report length decides now.
- The log line for the first rewritten report gives the pad, USB or
Bluetooth, the report and the two lengths.
- Not tested with a DualSense.
Launcher
- The controller pointer learned where the right stick rests while no pad
was being read, which includes the launcher being in the background, and
took the middle for it. A stick that rests off the middle, or a wheel or
throttle on that axis, then steered the pointer for good once the
launcher had the focus again, and the mouse stopped responding until a
restart. Nothing is learned while no pad is read, and a pad that goes
away gives the pointer back. Two tests for it.
Item search
- The cosmetic search bar showed in the world: a grid keeps its focused
item after its screen has gone. It needs the game's menu to be up, and
to have been for a second, as well.