Skip to content

Commit 1add308

Browse files
committed
guiupdate2
1 parent 295c599 commit 1add308

7 files changed

Lines changed: 412 additions & 27 deletions

File tree

‎PROJECT.md‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,3 +2161,46 @@ Verified: Original and HD started through `open` + launcher, 1200–1500 frames,
21612161
clean exit, 0 traps; portable copy signed (`codesign --verify --strict`), no
21622162
quarantine, runs from its embedded data; user prefs and registry unchanged.
21632163
`tools/session.sh` opens NFSU2.app with `NFSU2_SKIP_LAUNCHER=1 NFSU2_ENGINE=…`.
2164+
2165+
## 2026-10-26: HD black screen at start, Spotlight, menu car
2166+
2167+
### HD: ~8 s black screen on the first start of a build (fixed)
2168+
2169+
The game creates all its pixel shaders while it boots; each was translated and
2170+
compiled from MSL source on the spot, one after another. With a cold Metal cache
2171+
(the first start of every new build, or after macOS clears the cache) that held
2172+
the first frames back: measured, the first 150 frames took 10.0 s in the HD build
2173+
(more variants per shader) against 2.4 s with a warm cache. Now `metal_register_ps`
2174+
starts each compile in the background (up to 8 at once: the Metal compiler runs
2175+
them in parallel), and a draw waits only for the shader it needs; a draw that
2176+
needs a shader still waiting in the queue compiles it itself right away
2177+
(`ps_wait` / `ps_run`). Cold HD start: 150 frames in 3.1 s. Menu frames differ
2178+
from the old path no more than two runs of the old path differ from each other.
2179+
`PSASYNC=0`: old behaviour. Note for measurements: total process time is
2180+
misleading on a cold cache, Metal writes its cache at exit; time the frames.
2181+
2182+
### Spotlight opens 3-7 s late while the game runs (open)
2183+
2184+
Measured (user at the keyboard, ~15 runs): Spotlight's UI process ("Siri AI" on
2185+
macOS 27) is backgrounded (darwinbg, priority 4) while hidden and gets the
2186+
Cmd+Space ~5 s late; once it has it, it opens fast. Not the cause: the system
2187+
shortcut block (`NFSKISAYOL=0` was worse), Game Mode (`GCSupportsGameMode=false`
2188+
kept it off, still slow), GPU load (menu ~9 %), `framebufferOnly`
2189+
(`FBONLY=1`: readable middle texture + one copy pass, validated with the Metal
2190+
debug layer), disk I/O (a few KB/s), CPU cluster load (E-cluster ~62 %). A
2191+
control app presenting 120 Hz full screen with the same layer settings does NOT
2192+
slow Spotlight, so it is something in the engine; `FPSCAP=10` makes it fast,
2193+
`FPSCAP=60` does not. Next: grow the control app towards the engine (threads,
2194+
wakeups ~1160/s, GPU work) until Spotlight slows. Test switches: `FPSCAP=<n>`,
2195+
`BGFPS=<n>` (cap only while another app is in front), `FBONLY=1`. The layer is
2196+
now explicitly opaque.
2197+
2198+
### Menu car headlights
2199+
2200+
The main menu's 350Z (no profile) shows a large pale lilac highlight over the
2201+
hood front and headlights from the first frame on, and it stays after visiting
2202+
car select. Isolated with `SKIPPS`/`SKIPDRAW`: car = ps 265 (draws 167-285 in
2203+
frame 1650); the headlight lenses are draws 213-222 (light atlas texture 813,
2204+
64x64, complete with 4 mips; 807 = tail lights); the highlight itself is the
2205+
scene's reflection on the body panels, not a missing texture and not post
2206+
processing. Not decided whether anything is wrong without a reference image.

‎README.md‎

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ The game boots, reaches the menus, and races are playable with sound.
4040

4141
### Known limitations
4242

43-
- **Exactly one build of `SPEED2.EXE` is supported** (see [Requirements](#requirements)).
43+
- **Exactly one build of `SPEED2.EXE` is supported**, the European v1.2 one
44+
(see [Game versions](#game-versions)).
4445
Game addresses are hard-coded in the runtime, and the pipeline relies on a
4546
property of that particular file (below).
4647
- Videos are skipped: there is no VP6 decoder.
@@ -158,12 +159,61 @@ HD build draws about 18 W.
158159
| | |
159160
|---|---|
160161
| File | `SPEED2.EXE`, 4,788,224 bytes |
161-
| Build | European v1.2 executable without the CD check |
162+
| Build | **European** (PAL) v1.2 executable without the CD check, built Feb 9 2005 |
162163
| SHA-256 | `8f6a9ae2c4cfa01181d2fd755d99c6f4b7103f60273908ea1de1e719dfe2a297` |
163164

164-
Other builds (for example the US retail executable) have not been tested and
165-
will not work without changes. The app checks the file at startup and says so
166-
instead of crashing; `NFSU2_ANY_EXE=1` skips the check.
165+
The app checks the file at startup and says so instead of crashing;
166+
`NFSU2_ANY_EXE=1` skips the check.
167+
168+
### Game versions
169+
170+
The recompiled code and the addresses in the runtime belong to one executable,
171+
so every other build of `SPEED2.EXE` needs its own lifting pass and address
172+
table. The game *data* is a separate matter (see the note under the table).
173+
174+
| `SPEED2.EXE` | Size | SHA-256 | Status |
175+
|---|---|---|---|
176+
| European v1.2, no CD check | 4,788,224 | `8f6a9ae2c4cfa01181d2fd755d99c6f4b7103f60273908ea1de1e719dfe2a297` | **Supported** |
177+
| North American v1.2, no CD check (the build most PC mods target) | 4,800,512 | `f9dd86c054878ce6276beb07c1fd61874f7a1e4bf1f241b084c65b73e24168a7` | Not supported yet. Same Feb 9 2005 build; the data addresses match ours, the code is shifted by small amounts. Planned. |
178+
| US v1.0 retail disc | 5,987,981 | `2cbd698fee8338a13d1891bc17d27e6641b4b9dd40580de818594b9140222899` | **Cannot be supported.** Protected by SafeDisc: the code section is encrypted on disc and only decrypted at run time, so there is nothing to recompile. |
179+
180+
The retail disc executable carries the disc's copy protection, and the official
181+
v1.2 patch most likely keeps it (not verified here). A static recompiler needs
182+
readable machine code, so the port cannot use a protected executable, and this
183+
project does not remove copy protection.
184+
185+
**Data from the discs.** The US discs and the European release share 1,218 of
186+
their ~1,250 files byte for byte. The differences are the region's cars (the US
187+
release has `CARS/CIVIC` and `CARS/RSX`; the European one has `CARS/CORSA` and
188+
`CARS/PEUGOT106`), the per-language movies, `FRONTEND/FrontB.lzc` and
189+
`server.dll`.
190+
191+
**US data works with the supported executable.** The game's region is a
192+
constant in the executable (`0` in the US build, `6` in the European one), and
193+
it decides which of the region-only cars exist. Left at the European value, US
194+
data hangs on the "Loading" screen as soon as a race picks a Corsa or a 106. The
195+
runtime therefore looks at the data at startup: if `CARS/CIVIC` and `CARS/RSX`
196+
are there but `CARS/CORSA` and `CARS/PEUGOT106` are not, it switches the game to
197+
the US region (log line `region: North American data`). Tested on US disc data:
198+
races load, the Civic is in the Quick Race car list and the Mazda is called
199+
Miata, as in the US release; the region check hides the Corsa and 106.
200+
`NFSU2_REGION=na` or `eu` forces either region.
201+
202+
### Installing from the PC discs on a Mac
203+
204+
The discs hold the game in plain zip files, so the Windows installer is not
205+
needed. With the two disc images (`.cue`/`.bin`, `.iso`, or the disc folders):
206+
207+
```bash
208+
brew install sevenzip # only needed for .bin/.iso images
209+
python3 tools/install_from_discs.py ~/Games/NFSU2 "Disc 1.cue" "Disc 2.cue"
210+
```
211+
212+
This writes a normal game folder (about 1.7 GB) that the launcher can point at.
213+
It copies the disc's `SPEED2.EXE` too, but see the table above: the launcher
214+
accepts only the supported executable. With that executable in the folder, the
215+
US disc data plays in the US region (see "US data works with the supported
216+
executable" above).
167217

168218
## Build and run
169219

@@ -247,9 +297,15 @@ game files inside (about 1.4 GB). It runs on its own; saves stay in
247297
so keep it for yourself.
248298

249299
**Which version of the game does it need?**
250-
The Windows PC version, with the exact `SPEED2.EXE` listed under
251-
[Requirements](#requirements). Other builds, including the console versions,
252-
are not supported.
300+
The Windows PC version, with the European v1.2 `SPEED2.EXE` listed under
301+
[Requirements](#requirements). The North American v1.2 executable is not
302+
supported yet; the US v1.0 disc executable cannot be (it is copy-protected).
303+
Console versions are not supported. See [Game versions](#game-versions).
304+
305+
**I only have the PC discs. Can I install them on a Mac?**
306+
Yes, without Windows: `tools/install_from_discs.py` unpacks the disc images
307+
into a game folder. See [Installing from the PC discs on a
308+
Mac](#installing-from-the-pc-discs-on-a-mac).
253309

254310
**Does it work on Intel Macs?**
255311
No. Only Apple Silicon is targeted and tested.

‎run.sh‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ if [ -n "$NFSU2_DATA" ]; then
88
if [ -d "$NFSU2_DATA" ]; then EXE="$NFSU2_DATA/SPEED2.EXE"; else EXE="$NFSU2_DATA"; fi
99
fi
1010
[ -f "$EXE" ] || { echo "SPEED2.EXE not found: $EXE"; exit 1; }
11+
# NFSU2_REGION=na|eu: the game's region. Default: detected from the data's region
12+
# cars (CARS/CIVIC + RSX without CORSA + PEUGOT106 = North American, e.g. US discs).
13+
# See runtime/overrides.c, region_install.
1114
# TWO BUILDS (see link.sh):
1215
# ./run.sh [mode] original (out/nfsu2_boot)
1316
# NFSHD=1 ./run.sh [mode] HD (out/nfsu2_hd_boot) -- graphics improvements
@@ -51,7 +54,7 @@ unset AUTOKEY AUTOCLICK FORCESWITCH FETICK GAMELOG DUMPFRAME BOOTFLOW \
5154
FPSCSV AUTOKEYSTOP VCLOCK VCLOCK_MAXD DECLLOG CULLWIND RSLOG NOFOG BLITQUAD RESSCAN ASPFIX ASPLOG PSHIST MIPLIN NOANISO LODMAX \
5255
RTIDLOG DRAWVPS ZSHARELOG XFORMAT CAMLOG HD_SSR_DEBUG VIEWLOG HD_RTPROBE HD_RTPROBE2 HD_RT_STAGE HD_RT_NOTEX HD_RT_PLAIN HD_RT_ONLYCX HD_RT_SLOWBUILD HD_RT_LOG HD_RT_DUMPTAB HD_RT_STRESS HD_COMP HD_MSLAZY HD_REORDER HD_RT_AB HD_RT_FIX HD_RT_POISON FORCERAIN FORCETOD FORCETOD_STATE GPUWIN PASSPROF PASSPROF_MODE GPUVSDUMP \
5356
SNDMUTE YAKALAKARE DRAWLIST NODRAW LIMFREE ABTEST PASSPROF_CSV HD_MBLOG HD_RT_DLOG HD_RT_ONLY HD_RTPROBE2_HER \
54-
STALL MEMDUMP REGFIRST ADAPTERID
57+
STALL MEMDUMP REGFIRST ADAPTERID FPSCAP BGFPS FBONLY
5558

5659
export FIXMAT="${FIXMAT:-1}"
5760
export NOMOVIES="${NOMOVIES:-1}"

‎runtime/fileio.c‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ static int resolve_in(const char *root, const char *win, char *out, size_t outsz
8686
return !missing;
8787
}
8888

89+
/* Does the game folder hold this file? Windows-style path, case-insensitive. */
90+
int fileio_game_file_exists(const char *win){
91+
char p[1024]; struct stat st;
92+
return resolve_in(g_root, win, p, sizeof p) && stat(p, &st) == 0 && S_ISREG(st.st_mode);
93+
}
94+
8995
/* --- write root (save layer) ---------------------------------------------
9096
* The game writes its saves and profiles into its OWN folder ("C:\NFSU2\NFS
9197
* Underground 2\<name>\<name>"). Writing there deletes the saves when a new

0 commit comments

Comments
 (0)