From 61365bd06768e08df4cecd94904a7e5bfc1499a9 Mon Sep 17 00:00:00 2001 From: SpeedBreaker Project Date: Sat, 24 Oct 2026 19:31:48 +0000 Subject: [PATCH] SpeedBreaker v0.1.9 Windows beta 1 Co-authored-by: rafidwayne <117944293+rafidwayne@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 --- CMakeLists.txt | 46 +- CMakePresets.json | 38 ++ README.md | 44 +- docs/TESTING.md | 35 +- recomp/CMakeLists.txt | 29 +- runtime/CMakeLists.txt | 75 ++- runtime/apu/audio.cpp | 33 +- runtime/cpu/guest_thread.cpp | 57 +- runtime/cpu/guest_thread.h | 13 +- runtime/gpu/gpu_clock.cpp | 2 +- runtime/gpu/memory_plan.h | 26 + runtime/gpu/renderer.cpp | 513 +++++++++++++++-- runtime/gpu/shader_translator.cpp | 60 +- runtime/hid/input.cpp | 4 + runtime/install/disc_source.cpp | 31 +- runtime/install/install_cli.cpp | 36 +- runtime/install/installer.cpp | 70 ++- runtime/install/locate.cpp | 53 +- runtime/kernel/imports_file.cpp | 32 +- runtime/kernel/imports_object.cpp | 2 + runtime/kernel/imports_rtl.cpp | 6 + runtime/kernel/imports_unleashed.cpp | 20 +- runtime/kernel/memory.cpp | 16 +- runtime/kernel/vmem.cpp | 11 + runtime/kernel/vmem.h | 2 +- runtime/kernel/write_watch.cpp | 15 + runtime/kernel/xam.cpp | 52 +- runtime/main.cpp | 54 +- runtime/platform/fault.h | 21 + runtime/platform/file_io.h | 94 ++++ runtime/platform/folders.h | 41 ++ runtime/platform/memory.h | 31 ++ runtime/platform/os.h | 16 + runtime/platform/posix/file_io.cpp | 129 +++++ runtime/platform/quit_signals.h | 35 +- runtime/platform/stack.h | 87 +++ runtime/platform/startup.h | 70 +++ runtime/platform/thread.h | 72 +++ runtime/platform/timer.h | 53 ++ runtime/platform/win32/cpu_check.cpp | 75 +++ runtime/platform/win32/errors.h | 60 ++ runtime/platform/win32/fault.cpp | 79 +++ runtime/platform/win32/file_io.cpp | 280 ++++++++++ runtime/platform/win32/folders.cpp | 79 +++ runtime/platform/win32/guest_setjmp.h | 37 ++ runtime/platform/win32/memory.cpp | 125 +++++ runtime/platform/win32/os.cpp | 106 ++++ runtime/platform/win32/posix.h | 117 ++++ runtime/platform/win32/speedbreaker.ico | Bin 0 -> 52317 bytes runtime/platform/win32/speedbreaker.manifest | 31 ++ runtime/platform/win32/speedbreaker.rc | 38 ++ runtime/platform/win32/stack.cpp | 472 ++++++++++++++++ runtime/platform/win32/startup.cpp | 136 +++++ runtime/platform/win32/thread.cpp | 68 +++ runtime/platform/win32/timer.cpp | 81 +++ runtime/report/bug_report.cpp | 108 ++-- runtime/report/build_info.cmake | 19 +- runtime/report/build_info.cpp | 49 +- runtime/report/crash.cpp | 319 ++++++++++- runtime/report/crash_marker.h | 26 +- runtime/report/internal.h | 9 +- runtime/report/log.cpp | 152 ++++- runtime/report/report.h | 32 +- runtime/report/scrub.h | 107 ++++ runtime/report/symbol_names.h | 76 +++ runtime/report/system_info.cpp | 159 ++++++ runtime/report/watchdog.cpp | 179 +++++- runtime/report/zip.cpp | 4 + runtime/stdafx.h | 2 +- runtime/ui/installer_screen.cpp | 33 +- runtime/ui/settings_menu.cpp | 4 + runtime/user/paths.cpp | 6 + runtime/user/paths.h | 34 +- runtime/user/portable.cpp | 14 +- runtime/user/settings.cpp | 102 +++- runtime/user/settings.h | 13 +- runtime/video/presenter.cpp | 264 ++++++++- runtime/video/presenter.h | 6 + runtime/video/repeats.h | 38 ++ scripts/windows/make_ico.py | 16 + scripts/windows/make_zip.py | 549 +++++++++++++++++++ tests/CMakeLists.txt | 89 ++- tests/file_io_test.cpp | 355 ++++++++++++ tests/guest_time_test.cpp | 26 +- tests/language_test.cpp | 21 + tests/memory_plan_test.cpp | 72 ++- tests/memory_status_test.cpp | 6 + tests/paths_test.cpp | 94 ++++ tests/pcie_link_test.cpp | 8 +- tests/repeats_test.cpp | 164 ++++++ tests/scrub_test.cpp | 72 +++ tests/settings_keys_test.cpp | 16 + tests/settings_scaling_test.cpp | 6 + tests/settings_test.cpp | 134 +++++ tests/startup_test.cpp | 149 +++++ tests/symbol_names_test.cpp | 65 +++ tests/win_stack_test.cpp | 390 +++++++++++++ tests/win_stack_test_guest.cpp | 34 ++ tests/write_watch_test.cpp | 59 +- 99 files changed, 7457 insertions(+), 431 deletions(-) create mode 100644 CMakePresets.json create mode 100644 runtime/platform/fault.h create mode 100644 runtime/platform/file_io.h create mode 100644 runtime/platform/folders.h create mode 100644 runtime/platform/memory.h create mode 100644 runtime/platform/os.h create mode 100644 runtime/platform/posix/file_io.cpp create mode 100644 runtime/platform/stack.h create mode 100644 runtime/platform/startup.h create mode 100644 runtime/platform/thread.h create mode 100644 runtime/platform/timer.h create mode 100644 runtime/platform/win32/cpu_check.cpp create mode 100644 runtime/platform/win32/errors.h create mode 100644 runtime/platform/win32/fault.cpp create mode 100644 runtime/platform/win32/file_io.cpp create mode 100644 runtime/platform/win32/folders.cpp create mode 100644 runtime/platform/win32/guest_setjmp.h create mode 100644 runtime/platform/win32/memory.cpp create mode 100644 runtime/platform/win32/os.cpp create mode 100644 runtime/platform/win32/posix.h create mode 100644 runtime/platform/win32/speedbreaker.ico create mode 100644 runtime/platform/win32/speedbreaker.manifest create mode 100644 runtime/platform/win32/speedbreaker.rc create mode 100644 runtime/platform/win32/stack.cpp create mode 100644 runtime/platform/win32/startup.cpp create mode 100644 runtime/platform/win32/thread.cpp create mode 100644 runtime/platform/win32/timer.cpp create mode 100644 runtime/report/scrub.h create mode 100644 runtime/report/symbol_names.h create mode 100644 runtime/video/repeats.h create mode 100644 scripts/windows/make_ico.py create mode 100644 scripts/windows/make_zip.py create mode 100644 tests/file_io_test.cpp create mode 100644 tests/paths_test.cpp create mode 100644 tests/repeats_test.cpp create mode 100644 tests/scrub_test.cpp create mode 100644 tests/settings_test.cpp create mode 100644 tests/startup_test.cpp create mode 100644 tests/symbol_names_test.cpp create mode 100644 tests/win_stack_test.cpp create mode 100644 tests/win_stack_test_guest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 97cf8d3..c84a347 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,9 @@ # -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ # ninja -C build/main -j6 # +# Windows (clang-cl, lld-link, the static C runtime; see CMakePresets.json): +# cmake --preset windows-clang -B -DCMAKE_PREFIX_PATH= -DFFMPEG_XMA= +# # Needs ppc/ (XenonRecomp output from your own default.xex) and tools/ # (scripts/setup_tools.sh). -DSB_TESTS=ON adds the unit tests (tests/; run # them with ctest from the build folder). @@ -71,15 +74,52 @@ project(SpeedBreaker VERSION 0.1.9 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# clang-cl (the MSVC front end): its spellings of the flags the other +# platforms pass GCC-style. +if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + set(SB_MSVC_FRONTEND ON) +else() + set(SB_MSVC_FRONTEND OFF) +endif() + +if(WIN32) + if(NOT SB_MSVC_FRONTEND OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Windows builds need clang-cl (the generated code is Clang-only): see CMakePresets.json") + endif() + # One self-contained exe: the static C/C++ runtime (/MT) in every + # configuration, which every dependency must match (lld-link refuses a + # mix). + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded) + # xbox.h includes in every translation unit. + add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_WARNINGS) + # C++ exceptions with /EHs, not CMake's /EHsc: the c lets the compiler + # assume extern "C" functions never throw, and every recompiled function + # is extern "C" (PPC_FUNC_IMPL) with GuestThreadExit thrown through it + # (ExTerminateThread). Under /EHsc that throw ends in std::terminate. + string(REPLACE "/EHsc" "/EHs" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + if(NOT CMAKE_CXX_FLAGS MATCHES "/EHs") + string(APPEND CMAKE_CXX_FLAGS " /EHs") + endif() +endif() + # Binaries name their sources from the repository root (assert messages, # debug information), never by the folders they were built in: a published # build carries no one's home folder (a build folder inside the checkout # reads ./build/...). The real path too, for a checkout reached through a # symlink; both map to the same name, so their order doesn't matter. +# clang-cl takes the option through /clang:, and only C and C++ get it there +# (the resource compiler, platform/win32/speedbreaker.rc, doesn't know it). file(REAL_PATH "${CMAKE_SOURCE_DIR}" SB_SOURCE_REAL) -add_compile_options("-ffile-prefix-map=${CMAKE_SOURCE_DIR}=.") -if(NOT SB_SOURCE_REAL STREQUAL CMAKE_SOURCE_DIR) - add_compile_options("-ffile-prefix-map=${SB_SOURCE_REAL}=.") +if(SB_MSVC_FRONTEND) + add_compile_options("$<$:/clang:-ffile-prefix-map=${CMAKE_SOURCE_DIR}=.>") + if(NOT SB_SOURCE_REAL STREQUAL CMAKE_SOURCE_DIR) + add_compile_options("$<$:/clang:-ffile-prefix-map=${SB_SOURCE_REAL}=.>") + endif() +else() + add_compile_options("-ffile-prefix-map=${CMAKE_SOURCE_DIR}=.") + if(NOT SB_SOURCE_REAL STREQUAL CMAKE_SOURCE_DIR) + add_compile_options("-ffile-prefix-map=${SB_SOURCE_REAL}=.") + endif() endif() # macOS: a call to an API newer than the deployment target is an error unless diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..c2b6516 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,38 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, + "configurePresets": [ + { + "name": "windows-clang", + "displayName": "Windows x64: clang-cl, lld-link, static CRT, Release", + "description": "From a vcvars64 environment (MSVC's headers and libraries, the Windows SDK, rc.exe) with LLVM's clang-cl 19 or newer on PATH; CMake takes lld-link and llvm-lib from clang-cl's folder. Pass the dependency prefix (SDL3, glslang, FFmpeg-XMA, all /MT): -DCMAKE_PREFIX_PATH= -DFFMPEG_XMA=.", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/windows", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "windows-clang-tester", + "inherits": "windows-clang", + "displayName": "Windows x64 beta for testers: no console window, labelled", + "description": "windows-clang for builds that go to testers (scripts/windows/make_zip.py): linked for the Windows subsystem (no console window; the session log has everything) and labelled, so logs, Settings > Advanced and bug-report names say 'SpeedBreaker v Windows beta ()'.", + "binaryDir": "${sourceDir}/build/windows-tester", + "cacheVariables": { + "SB_WINDOWS_GUI": "ON", + "SB_BUILD_LABEL": "Windows beta" + } + } + ] +} diff --git a/README.md b/README.md index 5f81e03..01795ca 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ belongs to its owners. | **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) | Tested here on SteamOS. Players reported v0.1.1 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. Those were Xcode-signed builds: the IPA itself hasn't been installed on a device yet. | -| **Windows** | Coming soon | | +| **Windows** (beta) | [Download][all-releases] `SpeedBreaker-0.1.9-windows-x64-beta.zip` from the Releases page; see [Windows (beta)](#windows-beta) | A laptop with Intel UHD Graphics (60 Hz). NVIDIA, AMD and recent Intel Arc graphics and 120/144 Hz monitors haven't been tested yet: [reports welcome](#reporting-a-bug). | | **Android** | Coming soon | | Each link downloads the newest release. Every file and its `.sha256` checksum file are on the @@ -151,6 +151,8 @@ should say OK. What changed in each release is in [CHANGELOG.md](CHANGELOG.md). - **Steam Frame** (the arm64 SteamOS download): SteamOS on the Steam Frame, kept up to date (v0.1.2 needs the September 2026 release or later). The arm64 download is for the Frame only; it hasn't been tested on any other arm64 Linux device. +- **Windows (beta):** Windows 10 or 11, 64-bit; a CPU with AVX2 (Intel Haswell from 2013 or + newer, or any AMD Ryzen); a Vulkan 1.2 graphics card with a current driver. - **Mac:** Apple silicon and **macOS 15** (Sequoia) or later. The app won't open on older versions of macOS, and there is no Intel Mac build. - **iPhone and iPad:** iOS or iPadOS 17 or later, on an A15-class chip or newer (iPhone 13 and @@ -164,7 +166,7 @@ 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 sideload the experimental IPA or build it + (SteamOS), Linux, Mac or Windows (beta). 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 @@ -181,6 +183,7 @@ should say OK. What changed in each release is in [CHANGELOG.md](CHANGELOG.md). - **Mac:** drag the new SpeedBreaker into Applications, choose **Replace**, then allow it once more with **Open Anyway** (see [Mac setup](#mac)). - **Steam Deck, Steam Machine, Steam Frame and Linux:** unpack the new download over the old folder (`~/Games/SpeedBreaker`); your Steam shortcut keeps working. +- **Windows (beta):** extract the new zip into a new folder, run it from there, then delete the old folder. - **Everywhere:** your saves, settings and the installed game are kept, and no disc image is needed. Settings > Advanced > **Check for Updates** says when there's a new release, and so does GitHub's **Watch > Custom > Releases**. ## Setup by platform @@ -296,6 +299,23 @@ yet: the log's `[video] Vulkan devices:` line says which GPU it chose and why, a that line from yours would help. To pick another, start it with `NFSMW_GPU=`, e.g. `NFSMW_GPU=intel %command%` in Steam's launch options. +### Windows (beta) + +The Windows version is a **beta**: so far it has been tested on one laptop with Intel UHD +Graphics and a 60 Hz screen. Download `SpeedBreaker-0.1.9-windows-x64-beta.zip` from the +[Releases page][all-releases], right-click it, choose **Extract All**, and double-click +`SpeedBreaker.exe` in the extracted folder (not inside the zip). SpeedBreaker isn't signed, so +Windows may say **"Windows protected your PC"**: click **More info**, then **Run anyway**. +(Smart App Control, where it's on, offers no Run anyway.) The installer then works as on the +other platforms: it looks for your `.iso` in your user folder, Downloads, Desktop, Documents and +Games and on your other drives, or takes one (or an extracted disc folder) you browse for, and +puts the game in `%LOCALAPPDATA%\SpeedBreaker`, where your saves, settings and logs go too. +`README.txt` in the zip has the details. **Check for Updates** isn't available on Windows yet. + +Please [report](#reporting-a-bug) how it runs, especially on NVIDIA, AMD and Intel Arc +graphics and on 120 or 144 Hz monitors, with "Windows beta" in the issue's title. Windows +builds made by others aren't supported here. + ### Mac 1. **Download and install.** Download [`SpeedBreaker-macos.dmg`][dl-macos], open it, and drag @@ -627,7 +647,7 @@ pull requests are handled. ## What's next -- **Windows:** coming soon. +- **Windows:** in [beta](#windows-beta) now; a full release once it has run on more PCs. - **Android:** coming soon. **One more thing… SpeedBreaker: Carbon, coming soon.** It's planned, not available yet. @@ -711,6 +731,12 @@ The supported executable is 3,936,256 bytes, with SHA-256 - **Other Linux distributions:** your distribution's equivalents of the package list above (Clang 18 or newer). Untested so far. The GPU needs Vulkan 1.2 and BC (DXT) texture support. +- **Windows (beta):** the Visual Studio Build Tools (MSVC's libraries, the Windows SDK) with + LLVM's `clang-cl` 19 or newer, CMake and Ninja, and SDL3, glslang and FFmpeg's XMA decoder built + as static libraries with the static C runtime (`/MT`) into one folder. FFmpeg's configure + options are `scripts/build_ffmpeg_xma.sh`'s, with FFmpeg's MSVC toolchain; the Windows + third-party source archive on the release page has the exact build script. Step 2 runs on a + Mac or Linux; copy `ppc/` and `tools/XenonRecomp` to the Windows PC. - `gh`, logged in, is optional: it fetches Xenia's instruction tests. #### 2. Toolchain, your game files, recompilation @@ -752,6 +778,17 @@ cmake -S . -B build/main -G Ninja -DCMAKE_BUILD_TYPE=Release \ ninja -C build/main SpeedBreaker ``` +On Windows (beta), from an x64 Visual Studio developer prompt with `clang-cl` on `PATH`: + +```bat +cmake -S . --preset windows-clang -DCMAKE_PREFIX_PATH= -DFFMPEG_XMA= +ninja -C build\windows SpeedBreaker +``` + +`--preset windows-clang-tester` instead links it without a console window and labels it, as the +download is; `python scripts\windows\make_zip.py --public ...` (its header lists the options) +packages it with the license notices. + Run `build/main/runtime/SpeedBreaker` from the repository root. With the whole disc extracted in `game/files`, it plays from there. Otherwise the first-run installer asks for your disc image. @@ -868,6 +905,7 @@ SpeedBreaker is provided "as is", without warranty of any kind, as set out in th Public License. [releases]: https://github.com/SpeedBreakerProject/speedbreaker/releases/latest +[all-releases]: https://github.com/SpeedBreakerProject/speedbreaker/releases [dl-steamos-x86_64]: https://github.com/SpeedBreakerProject/speedbreaker/releases/latest/download/SpeedBreaker-steamos-x86_64.tar.xz [dl-steamos-arm64]: https://github.com/SpeedBreakerProject/speedbreaker/releases/latest/download/SpeedBreaker-steamos-arm64.tar.xz [dl-macos]: https://github.com/SpeedBreakerProject/speedbreaker/releases/latest/download/SpeedBreaker-macos.dmg diff --git a/docs/TESTING.md b/docs/TESTING.md index 598e88d..85e90ac 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -14,6 +14,12 @@ from you. Resolution to **Native**. - **From source:** the README's "Building from source", or [scripts/steamos/README.md](../scripts/steamos/README.md) for SteamOS. +- **Windows (a beta build for testers):** unzip the kit somewhere (not + inside the zip) and run `SpeedBreaker.exe`; its `README-TESTER.txt` has + the rest. It is made with the `windows-clang-tester` CMake preset (no + console window: everything goes to the session log; labelled "Windows + beta") and packed with `scripts/windows/make_zip.py`, which checks that no + game file, user name or user-folder path goes in. ## The menu @@ -31,10 +37,13 @@ from you. 1. Open the menu, go to the **Advanced** page (LB/RB, or Q/E) and choose **Save Bug Report** (A, or Enter). 2. A notice at the bottom of the screen says where the file went: - `speedbreaker-bug-report-v-_