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-_