From e128baca5e9aa068c0adb2f1c24b4c36701eecc3 Mon Sep 17 00:00:00 2001 From: SpeedBreaker Project Date: Sun, 11 Oct 2026 06:51:57 +0000 Subject: [PATCH] SpeedBreaker v0.1.2 Co-authored-by: Lydacious <81742991+lydacious@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 57 ++ CMakeLists.txt | 2 +- README.md | 60 +- THIRD_PARTY_NOTICES.md | 6 +- docs/TESTING.md | 3 +- runtime/game/glare.cpp | 110 +++ runtime/game/glare.h | 63 ++ runtime/game/ultrawide.cpp | 6 +- runtime/gpu/edge_bars.h | 154 +++- runtime/gpu/pipeline_cache_header.h | 163 +++++ runtime/gpu/render_scale.h | 240 +++++++ runtime/gpu/renderer.cpp | 640 +++++++++++------ runtime/install/install_cli.cpp | 60 +- runtime/install/install_cli.h | 4 +- runtime/install/locate.cpp | 66 +- runtime/install/locate.h | 13 +- runtime/install/placement.cpp | 38 +- runtime/install/placement.h | 7 + runtime/install/portable_switch.cpp | 374 ++++++++++ runtime/install/portable_switch.h | 58 ++ runtime/kernel/memory.cpp | 38 +- runtime/kernel/memory.h | 7 + runtime/kernel/memory_status.cpp | 237 +++++++ runtime/kernel/memory_status.h | 105 +++ runtime/main.cpp | 64 +- runtime/platform/code_signature.cpp | 242 +++++++ runtime/platform/code_signature.h | 66 ++ runtime/platform/ios_ui.h | 52 ++ runtime/platform/ios_ui.mm | 238 +++++++ runtime/report/system_info.cpp | 3 +- runtime/ui/installer_screen.cpp | 5 +- runtime/ui/startup_error.cpp | 97 +++ runtime/ui/ui.cpp | 40 +- runtime/ui/ui.h | 16 +- runtime/user/paths.cpp | 2 + runtime/user/paths.h | 34 +- runtime/user/portable.cpp | 116 +++ runtime/user/portable.h | 114 +++ runtime/user/settings.cpp | 12 +- runtime/user/settings.h | 6 +- runtime/video/band_filter.h | 59 ++ runtime/video/gpu_choice.h | 224 ++++++ runtime/video/picture_fit.cpp | 18 + runtime/video/picture_fit.h | 12 + runtime/video/presenter.cpp | 502 ++++++++++--- runtime/video/scale_budget.cpp | 73 ++ runtime/video/scale_budget.h | 32 + runtime/video/swapchain_policy.cpp | 220 ++++++ runtime/video/swapchain_policy.h | 157 ++++ scripts/ios/README.md | 177 ++++- scripts/ios/build.sh | 30 +- scripts/ios/make_ipa.sh | 184 +++++ scripts/macos/make_app.py | 144 +++- scripts/steamos/bundle/README-steam-frame.md | 12 + scripts/steamos/bundle/README.md | 59 +- scripts/steamos/bundle/speedbreaker.sh | 101 ++- scripts/steamos/make_bundle.sh | 12 + tests/CMakeLists.txt | 50 ++ tests/band_filter_test.cpp | 314 ++++++++ tests/code_signature_test.cpp | 311 ++++++++ tests/edge_bars_test.cpp | 310 +++++++- tests/glare_fit_test.cpp | 186 +++++ tests/gpu_choice_test.cpp | 298 ++++++++ tests/install_folder_test.cpp | 2 +- tests/launcher_prime_test.sh | 152 ++++ tests/memory_status_test.cpp | 246 +++++++ tests/pipeline_cache_header_test.cpp | 176 +++++ tests/portable_test.cpp | 711 +++++++++++++++++++ tests/render_scale_test.cpp | 451 ++++++++++++ tests/scale_budget_test.cpp | 85 +++ tests/swapchain_policy_test.cpp | 509 +++++++++++++ 71 files changed, 9012 insertions(+), 423 deletions(-) create mode 100644 runtime/game/glare.cpp create mode 100644 runtime/game/glare.h create mode 100644 runtime/gpu/pipeline_cache_header.h create mode 100644 runtime/gpu/render_scale.h create mode 100644 runtime/install/portable_switch.cpp create mode 100644 runtime/install/portable_switch.h create mode 100644 runtime/kernel/memory_status.cpp create mode 100644 runtime/kernel/memory_status.h create mode 100644 runtime/platform/code_signature.cpp create mode 100644 runtime/platform/code_signature.h create mode 100644 runtime/ui/startup_error.cpp create mode 100644 runtime/user/portable.cpp create mode 100644 runtime/user/portable.h create mode 100644 runtime/video/band_filter.h create mode 100644 runtime/video/gpu_choice.h create mode 100644 runtime/video/scale_budget.cpp create mode 100644 runtime/video/scale_budget.h create mode 100644 runtime/video/swapchain_policy.cpp create mode 100644 runtime/video/swapchain_policy.h create mode 100755 scripts/ios/make_ipa.sh create mode 100644 tests/band_filter_test.cpp create mode 100644 tests/code_signature_test.cpp create mode 100644 tests/glare_fit_test.cpp create mode 100644 tests/gpu_choice_test.cpp create mode 100755 tests/launcher_prime_test.sh create mode 100644 tests/memory_status_test.cpp create mode 100644 tests/pipeline_cache_header_test.cpp create mode 100644 tests/portable_test.cpp create mode 100644 tests/render_scale_test.cpp create mode 100644 tests/scale_budget_test.cpp create mode 100644 tests/swapchain_policy_test.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index d16cf34..60931d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,63 @@ What changed in each SpeedBreaker release, newest first. Each release's notes on its entry here, and the game shows the entry once, the first time a new version starts (offline: it's built into the game). +## v0.1.2 + +### What's new + +- Internal Resolution 1.5x (1080p), in Settings > Graphics: a much sharper picture than 1x, with + a little over half the pixels of 2x: for a GPU with room above 1x but not for 2x. Thanks to the + Reddit player who asked for it. +- Laptops with two GPUs: the game now runs on the dedicated graphics card (NVIDIA or AMD), not on + the one built into the processor. On Linux with NVIDIA's driver, the launcher also turns on + NVIDIA's PRIME render offload: thanks to lydacious for the idea and the first version (GitHub + pull request #6). +- Portable mode on Steam Deck, Steam Machine and Linux: put a file named `portable.txt` next to + `speedbreaker.sh`, and SpeedBreaker keeps your settings, saves, logs and caches in that folder, + and installs the game there too. Move or copy the whole folder to another machine and play on + (GitHub issue #1). +- Taller and wider screens: the sun's glare is round again (it was stretched up to 1.33 times + taller on the Steam Deck, 4:3 and 3:2, and wider on ultrawides); no faint line of a letterboxed + movie shows in the black past the 16:9 picture; and the race results screen is black past its + 16:9 picture, as on a 16:9 TV, instead of showing the road behind it. +- iPhone: after a screenshot, the picture no longer shrinks into a corner of the screen with the + settings menu blown up. +- Experimental: an IPA for iPhone and iPad, to sideload with your own Apple Account. + +### More about it + +- 1.5x renders 2.25 times the pixels of 1x, where 2x renders 4 times. Auto still chooses between + whole scales (1x, 2x or 3x) as before. +- The game picks a dedicated (discrete) GPU over a built-in (integrated) one, and of two alike the + one with more video memory. The log's `[video] Vulkan devices:` line lists every GPU it found, + the one it uses, and why. To use another, put `NFSMW_GPU=` in + the launch options, e.g. `NFSMW_GPU=intel %command%`. On the Steam Deck, Steam Machine, Steam + Frame, a Mac, an iPhone or an iPad (one GPU each) nothing changes. The launcher sets + `__NV_PRIME_RENDER_OFFLOAD=1` only on a PC where NVIDIA's driver runs one GPU beside another and + NVIDIA's Vulkan driver is installed, and keeps a value you set yourself. +- `speedbreaker.sh --portable on` copies what you have now (settings, saves and the installed game) + into the folder and turns portable mode on; `--portable off` copies them back. Both copy and + never delete: your old files stay until you remove them. Not on the Mac, where an app can't keep + its data inside itself. +- The IPA: the game asks iOS for two memory entitlements, and a free Apple Account can give at most + one of them, with some tools only: with a free account it may not start, or iOS may close it in + busy scenes. scripts/ios/README.md says which tools keep what. When iOS refuses the memory, the + game now says why on screen instead of closing. +- iPhone and iPad: on iOS 27 the screenshot screen could leave the game laid out as if the phone + were held upright, until the game was closed. The game now checks its picture against the + screen after coming back from the screenshot screen, the app switcher or Control Center, and + puts it right if they disagree; an iPhone, which plays only in landscape, never draws upright. +- iPhone and iPad: Internal Resolution's Auto now decides chip by chip, and the log says what it + chose and why. Every chip still gets 1x (720p) under Auto, the iPhone 18 Pro Max included: in a + long race on a charger it got hot even at 1x. 1.5x and 2x are in Settings > Graphics > Internal + Resolution. The log also records the battery level and charging state. +- After a macOS, SteamOS or graphics driver update, the first drive can stutter for a moment while + the game rebuilds its shaders for the new system. It happens once, and the game's log now says + so. +- Updating keeps your saves, settings and the installed game, and needs no disc image: on a Mac, + drag the new app into Applications and choose Replace, then Open Anyway once more; on SteamOS, + unpack the new download over the old folder. + ## v0.1.1 ### What's new diff --git a/CMakeLists.txt b/CMakeLists.txt index 43ea514..20c52ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,7 @@ endif() # apps' versions, the SteamOS bundles' VERSION file and the release tag # (v). CHANGELOG.md has an entry for each version (the in-game # "What's new" note is built from it). -project(SpeedBreaker VERSION 0.1.1 LANGUAGES C CXX) +project(SpeedBreaker VERSION 0.1.2 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/README.md b/README.md index 8b1f017..06aadc0 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,8 @@ and a settings menu you can open mid-race. ## Highlights -- **Up to 4K.** The 3D scene renders at 1x, 2x or 3x the console's 720p (3x is 3840x2160). - *Auto* picks a scale for your screen and device. +- **Up to 4K.** The 3D scene renders at 1x, 1.5x, 2x or 3x the console's 720p (1.5x is 1080p, + 3x is 3840x2160). *Auto* picks a scale for your screen and device. - **Ultrawide done right.** On 21:9 screens the view gets wider instead of stretched, and the HUD and the rear-view mirror stay in place. A 4:3 iPad, a 3:2 screen or the 16:10 screens of the Steam Deck and many Macs show more above and below instead, and fill the screen. @@ -111,9 +111,9 @@ belongs to its owners. |---|---|---| | **Steam Deck** and **Steam Machine** (SteamOS) | [Download][dl-steamos-x86_64]
`SpeedBreaker-steamos-x86_64.tar.xz` | Steam Deck OLED (SteamOS 3.9.2). Steam Machine (SteamOS 3.8) on a 3440x1440 ultrawide. The Steam Deck LCD hasn't been tested yet. | | **Steam Frame** (SteamOS, arm64) | [Download][dl-steamos-arm64]
`SpeedBreaker-steamos-arm64.tar.xz` | Steam Frame (SteamOS 0.3.0). It plays as a big flat screen in the headset; it is not a VR mode. | -| **Linux** (x86-64) | [Download][dl-steamos-x86_64] the x86-64 SteamOS build, `SpeedBreaker-steamos-x86_64.tar.xz`, or [build from source](#building-from-source) | SteamOS only so far. Other distributions and NVIDIA or Intel GPUs are untested: reports welcome. | -| **Mac** (Apple silicon) | [Download][dl-macos]
`SpeedBreaker-macos.dmg` | MacBook Pro (M1 Pro) and Mac Studio (M4 Max), on macOS 26; macOS 15.6 (Sequoia) in a virtual machine. There is no Intel Mac build. | -| **iPhone** and **iPad** | [Build it yourself](#iphone-and-ipad) with Xcode | iPhone 15 Pro Max (iOS 27). iPad Pro 12.9-inch (M2, iPadOS 27) with a Backbone Pro. Not on the App Store. | +| **Linux** (x86-64) | [Download][dl-steamos-x86_64] the x86-64 SteamOS build, `SpeedBreaker-steamos-x86_64.tar.xz`, or [build from source](#building-from-source) | SteamOS here. Players report it working on Fedora 44 (GeForce GTX 1080 Ti) and Ubuntu 24.04 (Intel Arc 140T). Other setups: reports welcome. | +| **Mac** (Apple silicon) | [Download][dl-macos]
`SpeedBreaker-macos.dmg` | MacBook Pro (M1 Pro) on macOS 27 and Mac Studio (M4 Max) on macOS 26; macOS 15.6 (Sequoia) in a virtual machine. There is no Intel Mac build. | +| **iPhone** and **iPad** | [Sideload the IPA](#iphone-and-ipad) (experimental), `SpeedBreaker--ios.ipa` on the [release page][releases], or [build it yourself](#iphone-and-ipad) with Xcode | iPhone 15 Pro Max and iPhone 18 Pro Max (iOS 27). iPad Pro 12.9-inch (M2, iPadOS 27) with a Backbone Pro. Not on the App Store. The IPA hasn't been tested with a free Apple Account yet. | | **Windows** | Coming soon | | | **Android** | Coming soon | | @@ -146,7 +146,8 @@ should say OK. What changed in each release is in [CHANGELOG.md](CHANGELOG.md). the extracted disc files. No title update is needed. SpeedBreaker doesn't provide game files or disc images, or link to them. 2. **Get SpeedBreaker.** [Download it](#download) for Steam Deck, Steam Machine and Steam Frame - (SteamOS), Linux or Mac. On iPhone and iPad you build it yourself. Then follow the + (SteamOS), Linux or Mac. On iPhone and iPad you sideload the experimental IPA or build it + yourself. Then follow the [setup for your platform](#setup-by-platform). 3. **Start it and install.** On first run, SpeedBreaker looks for your disc image, checks that it is the right game and version, then copies and verifies every file. This takes a few @@ -212,6 +213,13 @@ right of the screen). **Uninstall:** delete `~/Games/SpeedBreaker/`, `~/.local/share/speedbreaker/` (this deletes your saves too) and `~/.cache/speedbreaker/`, and remove the shortcut from Steam. +**Portable mode:** to keep everything in the SpeedBreaker folder (saves, settings, logs, shader +caches and the installed game), so the whole folder can be moved or copied to another Steam Deck, +Steam Machine or Linux PC, make an empty file named `portable.txt` next to `speedbreaker.sh`. That +starts fresh; to bring your current settings, saves and game along, run +`~/Games/SpeedBreaker/speedbreaker.sh --portable on` in Konsole instead, and `--portable off` to +go back. Both copy and never delete. The folder's README says more. + ### Steam Frame The Steam Frame has its own download. You set it up on the Frame's desktop: open the @@ -261,6 +269,11 @@ screen. The installer puts the game in `~/.local/share/speedbreaker/game`, or on any folder you pick with *Choose a folder...* (it needs a file chooser portal or zenity; without one, use `--dest`, below). +On a laptop with two GPUs, SpeedBreaker uses the dedicated one (NVIDIA or AMD); with NVIDIA's +driver the launcher also turns on PRIME render offload. The log's `[video] Vulkan devices:` line +says which GPU it chose and why. To pick another, start it with `NFSMW_GPU=`, e.g. `NFSMW_GPU=intel %command%` in Steam's launch options. + ### Mac 1. **Download and install.** Download [`SpeedBreaker-macos.dmg`][dl-macos], open it, and drag @@ -286,9 +299,18 @@ Display > Fullscreen switches to full screen. SpeedBreaker needs macOS 15 (Sequo ### iPhone and iPad -There's no download for iPhone and iPad, and SpeedBreaker isn't on the App Store. You build it -yourself with Xcode on a Mac and install it on your own device, signed with your own Apple -developer account: [scripts/ios/README.md](scripts/ios/README.md) walks you through it. +SpeedBreaker isn't on the App Store. There are two ways to get it onto your iPhone or iPad: + +- **Sideload the IPA (experimental).** Each release has an IPA, `SpeedBreaker--ios.ipa`, + on the [release page][releases]. A sideloading tool such as AltStore signs it with your own Apple + Account and installs it. The game asks iOS for more memory than most apps, and a free Apple + Account can't give all of it, so with a free account it may not start, or iOS may close it in + busy scenes. When iOS refuses the memory, the game says so on screen. It hasn't been tested with + a free Apple Account yet: read + [Sideloading the IPA](scripts/ios/README.md#sideloading-the-ipa-experimental) first, and please + report how it goes. +- **Build it yourself** with Xcode on a Mac, signed with your own Apple developer account: + [scripts/ios/README.md](scripts/ios/README.md) walks you through it. Once SpeedBreaker is on your device: @@ -370,7 +392,7 @@ Each page has a *Reset page* button. | Sharpening | 0.00 to 1.00 | 0.30 (0 turns it off) | | Anisotropic Filtering | Auto / Off / 2x / 4x / 8x / 16x / Original | Auto: 16x on dedicated graphics cards and M-series iPads, 4x elsewhere. Original uses each texture's own setting, as on the 360. | | Mipmaps | On / Off | On, so distant textures don't shimmer | -| Internal Resolution | Auto / 1x (720p) / 2x (1440p) / 3x (2160p) | Auto: enough to cover your screen, within what the device can afford. On iPhone and iPad, Auto always picks 1x. | +| Internal Resolution | Auto / 1x (720p) / 1.5x (1080p) / 2x (1440p) / 3x (2160p) | Auto: enough to cover your screen, within what the device can afford (1x, 2x or 3x). On iPhone and iPad, Auto always picks 1x. | **Audio:** Master Volume (100%), Mute (Off), and Mute in Background (Off), which silences the game while its window isn't in front. @@ -393,8 +415,11 @@ online, and only when you press it). The page also shows which build you're runn let Frame Rate *Auto* fall back to a steady 30. - **30 fps is a real option.** It's a steady 30 at full game speed, and the smooth choice in the Steam Frame headset. +- **Between 1x and 2x,** try 1.5x (1080p): much sharper than 1x for a little over half the work + of 2x. - **On iPhone and iPad,** keep Internal Resolution at Auto (1x). On the tested iPad Pro (M2), 2x - is too slow for races. Screen Resolution 75% saves more. + is too slow for races. The iPhone 18 Pro Max mostly holds 60 fps at 1.5x, but gets hot within + about ten minutes, and Frame Rate Auto then drops to 30. Screen Resolution 75% saves more. - **Docked Deck or Steam Machine:** set the shortcut's Game Resolution to Native. - **See what's happening:** Settings > Advanced > Performance Overlay. @@ -441,6 +466,10 @@ or later on Apple silicon. **The game stutters on my Steam Deck OLED.** Set the screen to 60 Hz (see [Steam Deck setup](#steam-deck-and-steam-machine)). +**My laptop runs the game on the slow built-in graphics.** Since v0.1.2 SpeedBreaker picks the +dedicated GPU by itself. If it still doesn't, see the `[video] Vulkan devices:` line in +`last-run.log` and set `NFSMW_GPU` (see [Linux](#linux)). + **The picture is small or stretched on my TV or monitor in Game Mode.** Set the shortcut's Properties > General > Game Resolution to Native. @@ -474,7 +503,9 @@ Touch only works in SpeedBreaker's own screens; a three-finger tap opens the set | Shader caches (safe to delete) | `~/.cache/speedbreaker/` | `~/Library/Caches/SpeedBreaker/` | Inside the app | Deleting that folder, or deleting the iPhone or iPad app, deletes your saves. A game you -installed in a folder of your own stays there until you delete that folder. +installed in a folder of your own stays there until you delete that folder. In +[portable mode](#steam-deck-and-steam-machine) (SteamOS and Linux) all of it is in the +SpeedBreaker folder instead: `data/`, `data/game` and `cache/`. ### Reporting a bug @@ -482,7 +513,7 @@ installed in a folder of your own stays there until you delete that folder. 2. A notice says where the zip file went: your **Desktop** (on SteamOS, pick it up in Desktop Mode, or in the Desktop app on a Steam Frame), the **SpeedBreaker** folder in the Files app on iPhone and iPad, or the data folder above when there is no Desktop. Its name says which - version you were running, for example `speedbreaker-bug-report-v0.1.1-_