Skip to content

MXB App v0.9.0

Choose a tag to compare

@github-actions github-actions released this 10 Aug 08:56
78a724e

What's new in v0.9.0 — A studio for paints, the Shop installing what you bought, and presets that carry their own mods

Added

  • Share a preset as a complete bundle, not just a code. A share code carries the names
    of what a look is made of, which is no use to someone who owns none of it — they get your
    preset and a list of things to go and find. Create full bundle in the Share dialog
    gathers every asset the loadout actually references — bike livery, helmet and its paint,
    goggles, suit, gloves, boots, protection, tyres, even a model-swap variant — zips them into
    a mods/-shaped tree with the preset beside them, and puts the download inside the code.
    Full import at the other end unpacks the lot into the folders the game reads, so a rider
    with an empty mods folder ends up wearing exactly what you built, first try. Folders are
    resolved as they're gathered, so a bundle carries real files rather than links pointing at
    your disk. A bundle over 200 MB is refused up front, with its size named, instead of after
    the upload.

  • A paint designer, and one Studio instead of three tabs. Designing a livery meant leaving
    for a web editor, exporting a .tga, packing it, launching, looking, and starting over —
    the loop was long enough that most of it happened blind. The Designer closes it: start
    from a paint already installed for the model (which is how the sheets arrive named the way
    the mesh binds them), stack images and text on top, drag them around, and the bike or
    rider beside you wears the drawing as you draw it
    . Save writes the packed .pnt the game
    reads, through the same destination picker, overwrite prompt and folder rules Paints already
    used. No brushes and no filters — pixels still come from wherever you like drawing them;
    this places them and knows where they go.

  • Designer, Paints and Rider now live under one Studio tab, switched by a segmented
    control. They were three sidebar entries answering three halves of one question, and the
    sidebar had started listing features rather than places; it's back to seven entries.

  • The Studio works under GP Bikes too. Building a .pnt is the same job for either title —
    same container, same encoder, same folders — and only the 3D preview needs part bindings GP
    Bikes doesn't have yet. So Designer and Paints are both there, the preview says plainly why
    it isn't, and the Rider tab (which is the rig) stays MX Bikes-only. Paint destinations are
    read from the game's own rider layout rather than listed in the app, so GP Bikes is offered
    its three — bike livery, helmet, rider kit — instead of MX Bikes' boots and protection
    folders it has no use for.

  • The sidebar collapses to icons, and the Designer's sheets/layers rail folds away, for
    when the canvas and the model are what you want the width for.

  • A new Paints tab turns image files into paints the game loads. MX Bikes reads a paint
    as a packed container of compressed texture sheets, which no image editor writes — so
    until now a livery drawn in GIMP or Photoshop had to go through somebody else's converter
    before the game, or this app's 3D preview, would look at it. Pick the sheets (.tga,
    .png, .jpg, .bmp, .webp), say what they're for, and the app builds the .pnt and
    installs it where the game expects it: mods/bikes/<Bike>/paints,
    rider/helmets/<Helmet>/paints or goggles, boots, protection, and a rider profile's
    kit or gloves. Or save it to a folder of your own, to share.

  • Unpack an existing paint into editable .tga sheets. This is how you get a template
    that actually fits the model: the sheets come out named the way the mesh binds them
    (livery, rider, shell…), open in any editor, and go straight back in under the same
    names. Extracted to Documents\MXB App\Paint Templates\<paint> and loaded into the studio
    in one step, so the round trip is edit → Reload from diskSave paint.

  • Names are the part that decides whether a paint works, so the studio shows them. A
    .pnt supplies textures by name and the mesh binds whichever names it asked for — a
    sheet called livery lands on the bodywork, the same sheet called my_livery lands
    nowhere. The studio reads the names the paints already installed for that model use (from
    their headers — no pixels decoded), lists them, and flags a sheet whose name isn't one of
    them before you save.

  • Preview what you just saved on the real model, through the viewer the app already
    has: a bike livery on its bike, a helmet or goggle paint on that helmet, a kit on the
    rider.

  • Sheets that aren't a power of two are resized to one, and say so. MX Bikes is a
    DirectX 9 title and its textures are powers of two throughout; a 1000×1000 export — which
    GIMP will happily make — would otherwise be packed into a file the game refuses, and the
    failure would land in-game rather than in the app.

  • Pick a ReShade preset from Settings. A new ReShade card lists every preset you have —
    the ones the app installed and any already sitting loose in your game folder — and switching
    between them is one click. There's an "Off" entry that runs no effects, so you can compare a
    preset against the stock look without uninstalling anything.

  • Browse and install ReShade presets like any other mod. mxb-mods' ReShade Presets
    category is now a tab in Browse. Installing one files the preset where the app can find it,
    and puts any effects and lookup textures the download bundles where ReShade looks for them —
    the usual reason a preset "does nothing" after a manual install.

  • Drop a preset on the app. A .ini or an archive of them is recognised as a ReShade
    preset and goes straight to the right place.

  • The app says when ReShade is installed for the wrong graphics API. MX Bikes and GP Bikes
    render with OpenGL, and ReShade's installer offers DirectX first — a DirectX install is
    never loaded by the game and looks like ReShade simply not working. The card names that
    specifically, and points at the fix.

  • Presets warn when they need effects you don't have. A preset that switches on a shader
    that isn't installed renders without it and looks like it did nothing; the card lists what's
    missing instead.

    Getting ReShade itself is still a trip to reshade.me — it asks that its binaries not be
    redistributed, so the app detects it and links out rather than bundling or downloading it.

  • Install what you bought on the MX Bikes Shop, from inside the app. The Shop tab now has
    two halves — Catalog, the store's public listing as before, and My purchases, which
    signs in to your own mxbikes-shop.com account and shows everything you've already paid for.
    Cards carry the store's own artwork and author, a product that ships several files (PRO/AMS
    and the like) is one card with a picker rather than several, and anything already in your
    library is badged as installed.

  • Purchases install through the same review sheet a drag-and-drop uses. The file is
    downloaded with a progress bar, then read to see what it actually contains, and the sheet
    says where each piece will land and warns about collisions before anything is written.

  • An Import button in the Library, for setups drag-and-drop never reaches. Dropping a
    download on the window stays the fast path, but the OS drop event doesn't arrive
    everywhere — remote desktops and some shells eat it — and where it doesn't, there was no
    other way to install a file you'd already downloaded. Import → Choose files… (or
    Choose a folder…, for an unpacked track) stages exactly what a drop stages: same
    classification, same review sheet showing where each piece lands, same collision
    warnings, and nothing written until you confirm.

  • Presets can use a custom riding style. The Riding style slot only ever offered the
    two styles the game ships, so a style you had installed could not be picked — you could
    type its name in by hand, but the preset then flagged it as a mod you were missing, never
    packed it into a share code, and Manage was free to park it right before a race. The slot
    now lists what is installed in mods/rider/animations alongside the stock mx and sm,
    a shared preset carries the style with it like it already carries helmets and paints, and
    Manage keeps it. MX Bikes and GP Bikes both, which is the point: the two games load
    riding styles from the same folder and record the pick in the same [riding_style] line.

  • MX Bikes lists riding styles in the Library, in the Rider tab under their own heading,
    and offers mods/rider/animations when you install one. GP Bikes already did both; MX
    Bikes was treated as if it had no such folder, so a riding style installed there was
    invisible to the app.

  • FrostMod can be stopped from the app. The sidebar pill and the FrostMod section in
    Settings now offer a stop control while it's running, next to the reload and start ones —
    until now the only way out was Task Manager or quitting the app from the tray. It stops
    FrostMod whoever started it: a frostmod.exe left behind by an earlier session, or one
    launched by hand, is no longer out of reach just because this app didn't spawn it. The app
    waits for the process to actually go before saying it stopped, so a FrostMod that survives
    the attempt (running elevated, or as another user) is reported rather than papered over with
    a success message the status pill contradicts a second later. Stopping is a one-off — it
    doesn't touch the "Run FrostMod automatically" setting, so the next app launch behaves as
    configured.

  • "msvcr90.dll was not found" is now something the app explains and fixes. MX Bikes is
    a Visual C++ 2008 build, and it asks Windows for that runtime by manifest rather than by
    path — which resolves either machine-wide or out of a private copy sitting in the game
    folder. On a PC living on the second one the game launches perfectly while nothing loaded
    from anywhere else can find the runtime, and FrostMod is loaded from somewhere else. The
    result was the worst kind of bug report: the game works, FrostMod doesn't, and Windows
    puts a bare error box over the screen that names a DLL and nothing else. The app now
    checks for that runtime, and for the newer one frostmod.dll itself needs, says which is
    missing in plain language, and installs it from Microsoft with one button.

  • The warning goes where it'll be seen. A bar at the top of the app, not just a line in
    Settings — nothing about the symptom suggests Settings is where to look.

  • A beta now announces itself in the beta Discord channel. Until now a suffixed tag
    built and published quietly and testers only heard about it if someone told them, because
    the announcement job skipped pre-releases outright. It runs for them now, and the tag
    decides which channel it reaches: a beta posts to the beta webhook, a full release to the
    release one, so testers hear immediately while everyone else still hears about a version
    once — when the updater can actually hand it to them.

    • The beta message says what it is before it says what's in it — a beta build of the
      version it names, which the updater won't offer you, so install it from the links in the
      message. Same fact the release page leads with. It's titled and coloured as a beta, and
      reads the changelog section for the version it's a build of, so it carries that
      release's headline once it's written and simply omits it before then.
    • The beta webhook is its own DISCORD_BETA_WEBHOOK_URL secret and the script never falls
      back from one webhook to the other: a beta landing in the channel every player watches
      is worse than a beta nobody announced.
  • Purchases works like the rest of the app now. The tab you install your bought mods from
    was a bare grid: no way to see what something actually was before installing it, no way to
    find one among sixty, and an "Installed" badge that mostly didn't light up. It now has the
    catalog's search, category pills, sorting (recently purchased, name, or not-installed-first)
    and a full detail page — screenshots, description, author — reached by clicking a purchase's
    artwork, the same as the catalog.

  • Installing a purchase now works exactly like installing from Browse. Add to Library asks
    where it should go — the same destination picker, with the folders you already use and the
    one you picked last time — confirms first if you already have it, then queues the install and
    reports it on the same card, with the same FrostMod reload. Starting a second install while
    one is running queues it instead of freezing the grid, which is what the purchases tab used
    to do.

  • The "Installed" badge is now a fact rather than a guess. It used to compare the store's
    product name against your folder names, and those routinely disagree — 2022 ARL MX Round 1
    ships as 2022.ARL.MX.RD01.pkz and lands in a folder named after the file, so the badge
    missed. Each install now records what it put where. Anything installed before this keeps the
    old fuzzy match as a fallback.

Changed

  • Share and Expand look like the buttons they are. Sharing a preset was one of four
    identical grey glyphs on the card, and the 3D preview's expand control was a tooltip away
    from invisible. Both now keep a background at rest.
  • The 3D viewer can be handed textures the backend has never seen, which is what lets the
    Designer's canvas appear on real geometry. Everything else still arrives by token, unchanged.
  • Switching between the Studio's tabs no longer throws away what you were doing in the one you
    left.
  • Sheets unpacked in Paints can be sent straight to the Designer to draw on, rather than
    unpacked a second time.
  • FrostMod still starts when a runtime is missing. It's a warning, not a gate: we can't
    tell from outside which PCs manage to inject anyway, and refusing to launch would take
    FrostMod away from anyone the check is wrong about.
  • Opening a paint in the viewer is fast. A gear paint is tens of megabytes of compressed
    pixels — three 4096² sheets — and every one of them was inflated one after another, then
    copied whole before being downscaled. They now inflate in parallel off a header walk that
    reads the image table without touching a pixel, and the copy is gone. The roughness sheet
    isn't decoded at all: the viewer samples a diffuse and a normal map, so that plane was 67 MB
    allocated, resized, sent to the webview and turned into a mipmapped texture nothing binds.
    Paints are also kept once decoded, so re-opening one or flicking back to it in the picker
    costs nothing.
  • Developer builds no longer run the paint decoder unoptimized. cargo's default leaves
    every crate at opt-level = 0 in a debug build, and essentially all of this work happens
    inside flate2 and image. Dependencies now build optimized and our own crate lightly so,
    which is what made a locally-run app take seconds where the shipped one took a fraction of
    one. Release builds are untouched.

Fixed

  • A dialog keeps its contents inside its own window. A dialog lays itself out as a grid,
    and a grid column grows to fit whatever inside it refuses to wrap — so a footer carrying a
    third button, or a mod name with no spaces in it, quietly pushed the text box out past the
    dialog's edge. Fixed for every dialog at once rather than the one it was noticed in: a
    crowded footer wraps, and long names break instead of shoving.

  • Dropping paints no longer leaves the review sheet spinning. Working out what a dropped
    .pnt is comes down to one question — which model does it paint? — and the file answers it
    in its texture names: an outfit carries rider, a bike livery carries framecompletemap.
    Reading those names decompressed every sheet in the file first, which for one 38 MB outfit is
    a fifth of a second and 200 MB of pixels, all of it thrown away unlooked-at. A pack with one
    folder per paint paid that bill for every paint in it, one after another, and never got to
    the end. The names sit in the file's headers, each of which states how far the next one is,
    so they are now read by seeking past the pixels rather than through them: 0.6 ms instead of
    204 ms for that same outfit, and nothing decompressed at all. A sealed paint still has to be
    decrypted whole before it has headers to read, and comes out about five times faster.

  • A drop no longer rescans your mods folder once per row. The list of bikes a paint could
    go on, and of folders a track could be filed in, was rebuilt for every row in the sheet —
    reopening every installed bike's .pkz each time — for lists that cannot change while you
    are looking at them. The folder is now read once per drop and every row shares it.

  • A corrupt .pnt is refused instead of being believed. How many textures a paint holds
    and how big each one is are numbers read out of the file before anything has checked them,
    and both were handed straight to an allocation. A damaged or truncated paint could ask for
    more memory than the machine has, or expand without limit while decompressing. Both are now
    bounded well above anything a real paint carries, so a bad file is an error on that file
    rather than something that takes the app down with it.

  • Protection paints were being saved to a folder the game doesn't read. Paint Studio wrote
    them to rider/protection/<model>/paints — the singular folder an old version of this app
    used, marked un-installable ever since — while the model itself lives in rider/protections/
    and every other path in the app installs there. The paint saved, the app said so, and the
    gear turned up unpainted in game. Destinations are now derived from the folders the game
    actually loads, so the two can't drift apart again.

  • The Designer's "Start from a paint…" gave no sign it was working while it unpacked, and said
    nothing at all if the paint yielded no sheets.

  • Signing in to the Shop no longer signs you straight back out. A sign-in would land, show
    the Purchases tab for a second, and drop to the signed-out screen again — every time, for
    anyone whose stored session had gone stale. Your purchases are read out of a hidden browser
    window that stays parked on the store, and nothing was closing that window when the session
    underneath it changed: it kept the page it already had, which — after a failed read, or a
    sign-out — was the store's own login form. So the very first thing a successful sign-in did
    was re-read that form and conclude the session had expired. Signing in now drops the window
    along with the old cookies, and re-loads the purchases page rather than trusting whatever was
    on screen. The same window is also dropped whenever the store answers that you are signed
    out, so one failed read can no longer make every attempt after it fail the same way.

  • The Purchases tab no longer claims you are signed in when you aren't. The app remembered
    a sign-in in a file that could outlive the browser's cookies, so opening the tab rendered as
    signed in, failed its first read, and flipped to signed out — the same flicker, with no
    sign-in involved. The store telling us you are signed out now clears that record. Your
    Cloudflare pass is deliberately kept, so signing back in doesn't have to sit through a fresh
    challenge; Log out still clears everything, as it always did.

  • The MX Bikes Shop sign-in no longer loops on "Verify you are human", and your purchases
    install again.
    The store now puts a Cloudflare managed challenge in front of every page
    the signed-in half touches — the login form, the purchases list, and the file downloads
    themselves. Only a real browser can clear one of those, by running its JavaScript, and the
    pass it earns can't be handed to an HTTP client, so the app was asking for pages it could
    never be given. Two things came of that: signing in sent you to the purchases page the
    moment your password was accepted, straight into a second challenge, which is the loop; and
    even a sign-in that got through had nothing behind it, because listing and downloading were
    refused the same way.

    The whole signed-in flow now happens inside a real browser window instead. Signing in lands
    on a page Cloudflare doesn't gate, your purchases are read from a hidden window that has
    actually cleared the check, and a bought file is downloaded by the browser itself straight
    into the staging folder — so nothing large is squeezed through JavaScript. Browsing the
    public catalog was never affected and is unchanged.

    Two side effects worth knowing: an install now shows megabytes downloaded rather than a
    percentage, because the browser reports a start and a finish and nothing in between; and
    Log out now clears the browser's cookies too, which it has to, so the next sign-in is a
    real one.

  • A sign-in that fails now says so. After five minutes of getting nowhere the app gave up
    in complete silence — no message, no log line — which is what made a stuck challenge look
    like an app that had simply hung. It now reports the failure and closes the dead window, and
    writes which cookies the window ended up with (names only, never values) so a log says
    whether the challenge ever cleared.

  • Helmets, boots and protection now install into a folder of their own. A gear mod
    packaged as a .pkz — which is how locked mods are distributed — unpacks to a single
    folder, and the app was unwrapping it and dropping the contents straight into
    mods/rider/helmets. The game only loads a model as helmets/<Model>/…, so the helmet
    became unloadable and invisible: it never appeared in the Rider tab's picker, and the
    paints and goggles folders it arrived with were listed there in its place.

  • The Rider tab offers to gather a gear mod that was installed loose. Anything already
    scattered by the above stays broken until it's moved, so the tab now spots it, names the
    folder it will make (taken from the mod's own descriptor) and lists exactly what will
    move before you press Repair. Packaged .pkz models and models already filed correctly
    are left alone.

  • "A helmets mod was installed loose" no longer fires on a paint pack. The repair asked
    to gather anything it found sitting in mods/rider/helmets — including a bare
    paints//goggles/ pair, which is not a scattered helmet at all but liveries for one that
    is already installed. Paints for a packaged helmet have nowhere else to live, since nothing
    can be written inside a .pkz. Repairing them built a helmet out of the liveries: a folder
    with no mesh, offered by every picker as a model, with the real helmet's paints filed under
    a name the loader never looks for. The repair now only offers itself when a model is
    genuinely there — a mesh in the gear areas, a descriptor for riding-style animations, which
    ship no mesh and no paints either.

  • Two mods scattered into one folder are left alone instead of fused. Nothing on disk
    says which mesh, config or livery came from which mod, so gathering them under one name
    produced a model that never existed. Two descriptors in an area root is now a refusal, with
    the reason in the log.

  • A repair that fails part-way puts everything back. It stopped at the first file that
    wouldn't move — a file the running game holds open, on Windows — leaving the mesh gathered
    and paints//goggles/ still in the area root, which shows the model and both strays in
    the picker and reads as the repair having split the helmet up. It is now all-or-nothing.

  • A packed gear item and a folder of the same name are now one item, not two. A .pkz
    helmet with paints installed loose beside it (which is where the game looks, and where the
    studio writes) only ever showed one side of itself: whichever the loader resolved first.
    A folder holding nothing but paints hid the archive entirely — the picker listed the new
    paint alone and the preview lost the mesh it belonged to. Both are read now, the folder
    winning a name clash because it's what was installed last.

  • An empty paint slot shows the model's own look, not a paint you never chose. The stock
    helmet came out bronze on the Rider tab while the Library showed that same helmet white
    under "Stock", and picking a helmet mod without naming a paint quietly dressed it in
    whichever paint that mod happened to list first. Leaving a paint slot empty is how a
    loadout says "the model's own look" — but the loader read it as a name it couldn't find,
    and that case deliberately falls back to the first paint in the folder so a renamed livery
    still shows up textured rather than bare grey. The game's own helmet folder happens to list
    black_yellow first, and that is the bronze. An empty slot now reaches the texture baked
    into the mesh, which is exactly what the Library means by "Stock" — both ask the model the
    same question now, so the two views can't disagree about it again. A paint that is named
    but missing still falls back as it always did, and a mod that ships paints without baking a
    shell texture into its mesh keeps that fallback too, rather than turning up bare.

  • A purchased bike or gear set no longer installs as if it were a track. The old path
    picked a destination by looking for keywords in the product name and otherwise assumed
    tracks, so bikes, paints and gear were filed into a tracks-derived folder silently, with no
    preview and no collision check. Destination now comes from the archive's contents.

  • Retrying a failed install no longer breaks the install. Downloads are meant to run one
    at a time, but the Retry button on a failure went straight to the installer instead of the
    queue — so a second, impatient click started a parallel run of the same mod. Both runs
    used a staging folder named after the mod, and the newcomer wiped it clean on the way in,
    deleting the files the first run was still copying. The failure landed as a bare
    "os error 2", most often on a livery, and clicking Retry again only made it likelier. Retry
    now joins the queue, a mod already installing to the same place ignores a repeat click, and
    every install stages into a folder of its own.

  • A failed install says which file it failed on. The error reached you as a raw system
    code with no path in it — nothing to act on and nothing to report. It now names the file
    and where it was going, and the failure is written to the log rather than living only in a
    toast you have to catch before it goes.

  • One unreadable file no longer sinks a whole install. A shortcut whose target has gone
    away, or a file an antivirus pulls out mid-install, used to fail everything that came with
    it. Those entries are skipped and noted in the log; the rest of the mod installs.

  • Installing over a running copy no longer stops at "error opening file for writing".
    The file it named, frost.exe, is the app's own program file, and Windows won't let
    anything overwrite a program image that is still held — which the app's often is, since it
    hides in the tray, starts at login, and launches the installer from inside itself when you
    update in-app. Closing it first isn't enough on its own: the hold can outlive the process,
    by a copy still tearing down or an antivirus reading the image as it exits, which is why
    the installer's own "MXB App is running" prompt never appeared before the failure. The
    installer now clears the name by whatever means Windows allows — delete it, retry for a
    couple of seconds while a dying copy lets go, and failing that rename it aside, which
    Windows permits even for a file in use — then sweeps up what it moved once the new build
    is in place. The uninstaller does the same, since it's the installed build's uninstaller
    that the next version runs, and a failed one is what used to bounce you back to the
    "already installed" page for good.

  • An in-app update can no longer kill its own installer. Closing the app took the whole
    process tree with it, and the installer the app had just launched was part of that tree.
    It now closes the app alone; the browser processes that the tree kill was there for exit
    with it anyway.

  • Opening MXB App while it's already running shows the window you had, instead of starting
    a second copy.
    Closing the window parks the app in the tray rather than quitting it —
    that part is deliberate, it's what keeps FrostMod connected — but nothing stopped the next
    launch from building a whole new app beside it. Open it five times over a day and you ended
    up with five of everything: five windows, five tray icons to go and quit one by one under
    the overflow arrow, five FrostMods. A launch now hands off to the copy already running and
    brings its window forward, the same as clicking the tray icon. Launch-at-login is covered
    too — the instance that started with Windows is the one your first launch of the day
    reveals, rather than the one it stacks on top of.

  • A mods folder you moved with mxbikes.ini now works. Plenty of players keep their
    content somewhere short like C:\mods — junctioning one rider paint into six model
    folders needs paths that OneDrive and a deep Documents tree can't give you. The app
    couldn't be pointed at such a folder: picking it silently rewrote your setting to the
    drive root, and auto-detection went to Documents\PiBoSo\MX Bikes instead, found no
    mods inside it, and came up missing gear, paints and bikes with nothing to explain why.
    The folder you pick is now the folder used, whether it's the game folder or the mods
    folder itself.

  • The app reads mxbikes.ini to find a relocated mods folder on its own. The game
    already knows where your content is; setup now asks it instead of guessing. Profiles,
    which don't move with the mods folder, are pinned to where they actually stayed.

  • FrostMod was being handed the wrong folder. It appends \tracks and \bikes to what
    the app gives it, and the app was sending the folder one level above — so its track
    manager and model swap were pointed at folders that don't exist. Affected everyone, not
    just relocated setups; it just never announced itself.

  • Settings says which folder mods are actually read from when that isn't the obvious
    <picked>\mods, and warns when the folder isn't there at all.

  • Settings offers Stop for a FrostMod it didn't install. The button was hidden unless
    the app had put FrostMod there itself — so the one case that most needs a stop, a
    frostmod.exe running that the app didn't start, had no button. The backend could
    always kill it; only the button was missing. (The sidebar's stop control was unaffected.)

  • Browse keeps your place when you look at a mod and come back. Opening a mod used to
    throw away the search you typed, the category you picked, the sort order, every page you'd
    loaded with "Load more" and how far you'd scrolled — Back dropped you at the top of a fresh,
    unfiltered listing, which made working through a long category one mod at a time miserable.
    The grid now sits exactly where you left it, down to the row of cards, and nothing is
    re-fetched on the way back. It survives a trip to Library or Settings too, and the in-game
    overlay behaves the same way.

  • The Linux app opens to its interface instead of a white screen. On SteamOS the window
    appeared, the title bar drew, and the inside stayed blank with nothing in the terminal to
    explain it. The AppImage carries its own copy of the web engine, and that engine tries to
    hand frames to the graphics driver through a fast path the host's driver answers
    differently than the one it was built against — so it drew nothing at all, silently. It now
    takes the ordinary path by default, which paints on every machine and costs nothing anyone
    will notice on a UI this static. A machine that handles the fast path can still ask for it
    back with WEBKIT_DISABLE_DMABUF_RENDERER=0. The startup log now records which path a run
    took, so the next report of a blank window can be read straight from the log.


Which file do I download?

Windows — download the .exe. That's the installer, and it's what almost everyone
needs. Run it and you're done.

macOS and Linux
  • macOS (Apple Silicon) — the .dmg.
  • Linux — the .AppImage works on any distro: download, chmod +x, run it. Prefer
    your package manager? .deb for Debian/Ubuntu, .rpm for Fedora. Note MX Bikes itself
    runs through Proton on Linux.

The .sig and .tar.gz files are used by the in-app updater — you don't need to download
those.