Skip to content

Commit 3af301d

Browse files
007hacky007TalhaMudo
authored andcommitted
Reflections for the HD engine: sky, car lights and more detail (#42)
Three optional switches, off by default, in Settings > Picture (Reflections), following what Aero_'s NFS HD Reflections mod changes (no code from it): - Sky (NFSU2_REFLECT_SKY=1): the road reflection (0x5cab69) and the rear-view mirror (0x5cae71) draw the sky the way the main view does, scaled to their far plane (0x60f9f6), mirrored in z for the road. - Car lights (NFSU2_REFLECT_LIGHTS=1): the cars' own light glows (0x6154a0) are drawn in the road reflection's glow pass instead of the dimmer generic 0x494270. - More detail (NFSU2_REFLECT_DETAIL=1): full-detail scenery (0x5d6666) and cars (0x63167d, 0x6311fc) in the reflections, cube map far plane 10 km. NA addresses are mapped in build_na.h. As with #43 these belong to the HD engine: in the original engine the hooks do nothing and the two overrides call the game's functions. The PR's Sharpness picker (larger reflection targets in the original engine) is left out: the HD engine already draws them larger. With ray tracing on, the game's road reflection shows where rays miss, so the sky fills exactly those areas. tools/check.sh passes the three variables through.
1 parent ea3f672 commit 3af301d

12 files changed

Lines changed: 243 additions & 9 deletions

File tree

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ them; tests/save_manager.sh). **Settings…** (Cmd-,) holds the options on tabs:
290290
Original or HD graphics and the HUD on **Graphics**; on **Picture**, optional
291291
settings of the HD engine only (the PC version's colour tint, console gamma, edge
292292
smoothing, sharpening; `TINT` / `CONSOLEGAMMA` / `EDGEAA` / `SHARPEN`, all off by
293-
default; the Original engine ignores them); on **Controls**, the game
293+
default; the Original engine ignores them) and the reflections' sky, car lights
294+
and detail (`NFSU2_REFLECT_SKY` / `_LIGHTS` / `_DETAIL`, HD engine only too); on
295+
**Controls**, the game
294296
controller on or off, its stick dead zone and the XtendedInput layout
295297
(`NFSU2_PAD` / `NFSU2_PAD_DEADZONE` / `NFSU2_XTINPUT`, which still win when set by
296298
hand); on **More**, **Make Copy…** builds a portable

‎launcher/Game.swift‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ enum Prefs {
7474
static let wideHUD = "LauncherWideHUD" // HUDPOS=1 for the engine
7575
static let frameRate = "LauncherFrameRate" // 30 | 60 | 120 | 240 -> NFSU2_FPS
7676
static let fpsCounter = "LauncherFPSCounter" // -> NFSU2_FPSCOUNTER
77+
// HD engine only (Settings > Picture, Reflections; runtime/reflect.c).
78+
static let reflectSky = "LauncherReflectSky" // -> NFSU2_REFLECT_SKY
79+
static let reflectLights = "LauncherReflectLights" // -> NFSU2_REFLECT_LIGHTS
80+
static let reflectDetail = "LauncherReflectDetail" // -> NFSU2_REFLECT_DETAIL
7781

7882
/// Each game option with its value in the original, unmodified game: Settings ›
7983
/// Restore Original Game sets them all. A new option adds its line here. (The
@@ -84,6 +88,9 @@ enum Prefs {
8488
OriginalValue(\.frameRate, 120),
8589
OriginalValue(\.fpsCounter, false),
8690
OriginalValue(\.picture, PictureOptions.original),
91+
OriginalValue(\.reflectSky, false),
92+
OriginalValue(\.reflectLights, false),
93+
OriginalValue(\.reflectDetail, false),
8794
]
8895
}
8996

‎launcher/Model.swift‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ final class LauncherModel: ObservableObject {
3131
@Published var xtendedInput: Bool { didSet { defaults.set(xtendedInput, forKey: Prefs.xtendedInput) } }
3232
/// Settings › Picture: PictureOptions.all[i] -> the chosen index (0 = the original game).
3333
@Published var picture: [Int] { didSet { for (o, i) in zip(PictureOptions.all, picture) { defaults.set(i, forKey: o.key) } } }
34-
/// Picture variables that were set by hand when the launcher started: those win.
35-
private let pictureFromEnv = Set(PictureOptions.all.map { $0.env }
34+
@Published var reflectSky: Bool { didSet { defaults.set(reflectSky, forKey: Prefs.reflectSky) } }
35+
@Published var reflectLights: Bool { didSet { defaults.set(reflectLights, forKey: Prefs.reflectLights) } }
36+
@Published var reflectDetail: Bool { didSet { defaults.set(reflectDetail, forKey: Prefs.reflectDetail) } }
37+
/// HD picture / reflection variables set by hand when the launcher started: those win.
38+
private let pictureFromEnv = Set((PictureOptions.all.map { $0.env }
39+
+ ["NFSU2_REFLECT_SKY", "NFSU2_REFLECT_LIGHTS", "NFSU2_REFLECT_DETAIL"])
3640
.filter { ProcessInfo.processInfo.environment[$0] != nil })
3741
private let xtendedInputFromEnv = ProcessInfo.processInfo.environment["NFSU2_XTINPUT"] != nil
3842
@Published var job: Job? = nil
@@ -73,6 +77,9 @@ final class LauncherModel: ObservableObject {
7377
xtendedInput = defaults.bool(forKey: Prefs.xtendedInput)
7478
let d = defaults
7579
picture = PictureOptions.all.map { o in min(max(d.integer(forKey: o.key), 0), o.choices.count - 1) }
80+
reflectSky = d.bool(forKey: Prefs.reflectSky)
81+
reflectLights = d.bool(forKey: Prefs.reflectLights)
82+
reflectDetail = d.bool(forKey: Prefs.reflectDetail)
7683
}
7784

7885
/// runtime/xtinput.c has the North American v1.2 executable's addresses only.
@@ -168,6 +175,10 @@ final class LauncherModel: ObservableObject {
168175
for (o, i) in zip(PictureOptions.all, picture) where !pictureFromEnv.contains(o.env) {
169176
if e == .hd && i > 0 { setenv(o.env, o.choices[i].value, 1) } else { unsetenv(o.env) }
170177
}
178+
for (name, on) in [("NFSU2_REFLECT_SKY", reflectSky), ("NFSU2_REFLECT_LIGHTS", reflectLights),
179+
("NFSU2_REFLECT_DETAIL", reflectDetail)] where !pictureFromEnv.contains(name) {
180+
if e == .hd && on { setenv(name, "1", 1) } else { unsetenv(name) }
181+
}
171182
let path = Paths.engine(loc.build, hd: e == .hd).path
172183
// A child process, not exec(): macOS attributes the child's file access to
173184
// this launcher (the "responsible" process), so folder permissions the

‎launcher/Settings.swift‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,20 @@ struct PictureSettings: View {
142142
.disabled(!active).opacity(active ? 1 : 0.5)
143143
}
144144
}
145+
Card("Reflections") {
146+
Group {
147+
SettingRow(title: "Sky in reflections",
148+
description: "The wet road and the rear-view mirror show the sky instead of black. Off: as in the original game.",
149+
isOn: $model.reflectSky)
150+
SettingRow(title: "Car lights in reflections",
151+
description: "Head and tail lights of the cars shine in the wet road. Off: as in the original game.",
152+
isOn: $model.reflectLights)
153+
SettingRow(title: "More detail in reflections",
154+
description: "Full-detail buildings and cars in the reflections, and the car paint reflects the city. More work for the Mac. Off: as in the original game.",
155+
isOn: $model.reflectDetail)
156+
}
157+
.disabled(!active).opacity(active ? 1 : 0.5)
158+
}
145159
}
146160
}
147161
}

‎link.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ case "${BUILD:-eu}" in
4242
*) echo "BUILD must be eu or na"; exit 1 ;;
4343
esac
4444

45-
CSRC="mem dispatch genexec win32 win32_ext com debug res fileio overrides d3dx_hle vsemu enhance perflog wsfov gheap sndlead xpatch highfps xtinput visual"
45+
CSRC="mem dispatch genexec win32 win32_ext com debug res fileio overrides d3dx_hle vsemu enhance perflog wsfov gheap sndlead xpatch highfps xtinput visual reflect"
4646
MSRC="metal audio bundle gamepad picture"
4747
FW="-lm -framework Cocoa -framework Metal -framework QuartzCore -framework ImageIO -framework CoreGraphics -framework CoreServices -framework AudioToolbox -framework GameController -framework CoreText"
4848
SHARDS="$SOBJ/shard_*.o $SOBJ/fntab.o $SOBJ/stubs.o"

‎run.sh‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ fi
2929
# EDGEAA=1 edge smoothing (post-process) of the 3D scene, not the HUD
3030
# SHARPEN=1..100 contrast adaptive sharpening of the 3D scene, not the HUD
3131
# Details: runtime/visual.c (TINT), runtime/picture.m (the others)
32+
# Reflections, HD engine only (launcher Settings > Picture; unset = the original game; runtime/reflect.c):
33+
# NFSU2_REFLECT_SKY=1 the sky in the road reflection and the mirror
34+
# NFSU2_REFLECT_LIGHTS=1 the cars' lights in the road reflection
35+
# NFSU2_REFLECT_DETAIL=1 full-detail models in the reflections, car cube map far plane 10 km
3236
# In game, Cmd+Shift+D: a PNG of that frame + the draw list (~/Library/Logs/NFSU2/
3337
# or the PERFLOG directory). Measurement recording while playing: tools/session.sh [hd].
3438
MODE="${1:-window}"

‎runtime/build_na.h‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,17 @@
1818
#define GA_0x005c6766u 0x005c6756u /* function 005c6530 + 0x236 */
1919
#define GA_0x005c7ffeu 0x005c7feeu /* function 005c7ed0 + 0x12e */
2020
#define GA_0x005c804eu 0x005c803eu /* function 005c7ed0 + 0x17e */
21+
#define GA_0x005cab69u 0x005cab59u /* function 005caae0 + 0x89 */
22+
#define GA_0x005cae71u 0x005cae61u /* function 005caae0 + 0x391 */
2123
#define GA_0x005cbe54u 0x005cbe44u /* function 005cbdd0 + 0x84 */
24+
#define GA_0x005cf430u 0x005cf420u /* function 005cf430 + 0x0 */
2225
#define GA_0x005d2c27u 0x005d2c17u /* function 005d2922 + 0x305 */
26+
#define GA_0x005d6666u 0x005d6656u /* function 005d6580 + 0xe6 */
27+
#define GA_0x0060f890u 0x0060f880u /* function 0060f890 + 0x0 */
28+
#define GA_0x0060f9f6u 0x0060f9e6u /* function 0060f890 + 0x166 */
2329
#define GA_0x0061ad90u 0x0061ad80u /* function 0061ad90 + 0x0 */
30+
#define GA_0x006311fcu 0x006311ecu /* function 00630df0 + 0x40c */
31+
#define GA_0x0063167du 0x0063166du /* function 00631260 + 0x41d */
2432
#define GA_0x0065acf5u 0x0065ace5u /* function 0065acf5 + 0x0 */
2533
#define GA_0x0065addbu 0x0065adcbu /* function 0065addb + 0x0 */
2634
#define GA_0x0065ae35u 0x0065ae25u /* function 0065ae35 + 0x0 */
@@ -68,10 +76,12 @@
6876
#define GA_0x007fb700u 0x007fb700u /* operand pair */
6977
#define GA_0x007fb710u 0x007fb710u /* operand pair */
7078
#define GA_0x007fb714u 0x007fb714u /* operand pair */
79+
#define GA_0x007fee8cu 0x007fee8cu /* operand pair */
7180
#define GA_0x008183e4u 0x008183e4u /* operand pair */
7281
#define GA_0x0081a1d0u 0x0081a1d0u /* operand pair */
7382
#define GA_0x00828028u 0x00828028u /* operand pair */
7483
#define GA_0x008284e4u 0x008284e4u /* operand pair */
84+
#define GA_0x0082da5cu 0x0082da5cu /* operand pair */
7585
#define GA_0x00835860u 0x00835860u /* operand pair */
7686
#define GA_0x00836488u 0x00836488u /* operand pair */
7787
#define GA_0x0083648cu 0x0083648cu /* operand pair */
@@ -175,6 +185,10 @@
175185
#define GA_0x8b466cu 0x008b466cu /* operand pair */
176186
#define GA_0x8ba4a4u 0x008ba4a4u /* operand pair */
177187
#define GA_0x8ba4a8u 0x008ba4a8u /* operand pair */
188+
#define sub_00494270 sub_00494270
189+
#define sub_00494270_orig sub_00494270_orig
190+
#define sub_00494270_m sub_00494270_m
191+
#define sub_00494270_orig_m sub_00494270_orig_m
178192
#define sub_004c5330 sub_004c5330
179193
#define sub_004c5330_orig sub_004c5330_orig
180194
#define sub_004c5330_m sub_004c5330_m
@@ -203,6 +217,10 @@
203217
#define sub_0060fab0_orig sub_0060faa0_orig
204218
#define sub_0060fab0_m sub_0060faa0_m
205219
#define sub_0060fab0_orig_m sub_0060faa0_orig_m
220+
#define sub_006154a0 sub_00615490
221+
#define sub_006154a0_orig sub_00615490_orig
222+
#define sub_006154a0_m sub_00615490_m
223+
#define sub_006154a0_orig_m sub_00615490_orig_m
206224
#define sub_0061e390 sub_0061e380
207225
#define sub_0061e390_orig sub_0061e380_orig
208226
#define sub_0061e390_m sub_0061e380_m

‎runtime/com.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4872,6 +4872,7 @@ void com_report(void){
48724872
{ void ws_report(void); ws_report(); } /* wsfov.c */
48734873
{ void visual_report(void); visual_report(); } /* visual.c */
48744874
{ void pic_report(void); pic_report(); } /* picture.m */
4875+
{ void refl_report(void); refl_report(); } /* reflect.c */
48754876
{ void gamepad_report(void); gamepad_report(); } /* gamepad.m */
48764877
{ void xpatch_report(void); xpatch_report(); }
48774878
{ void highfps_report(void); highfps_report(); } /* LOCAL PATCH: highfps.c */

‎runtime/debug.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ void guest_hook(CPU *c, uint32_t ip){
9797
{ int sndlead_hook(CPU *, uint32_t); if (sndlead_hook(c, ip)) return; } /* sndlead.c */
9898
{ int highfps_hook(CPU *, uint32_t); if (highfps_hook(c, ip)) return; } /* highfps.c */
9999
{ int visual_hook(CPU *, uint32_t); if (visual_hook(c, ip)) return; } /* visual.c */
100+
{ int refl_hook(CPU *, uint32_t); if (refl_hook(c, ip)) return; } /* reflect.c */
100101
if (ip == GA(0x0065ae35u)){
101102
uint32_t a1=MR32(c->esp+4u), a2=MR32(c->esp+8u), a3=MR32(c->esp+12u);
102103
if (!g_rec_esp0) g_rec_esp0 = c->esp;

‎runtime/reflect.c‎

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/* reflect.c - the sky, the car lights and more detail in the reflections.
2+
* HD engine only (NFS_ENHANCED): the original engine stays the 2004 picture, so
3+
* there the hooks do nothing and the two overrides call the game's own
4+
* functions. Every part is off unless asked for (launcher Settings > Picture,
5+
* Reflections). The HD engine already draws the reflection targets larger
6+
* (enhance.c "REFLECTION RESOLUTION").
7+
*
8+
* Follows what Aero_'s "NFS HD Reflections" mod changes in Underground 2 (which
9+
* values and which calls); the code here is our own.
10+
*
11+
* The game draws three reflections into separate render targets:
12+
* road reflection view 4 320x240 (the wet road)
13+
* rear-view mirror view 3 256x256 (bumper and hood views)
14+
* car cube map views 16-21 128 per face (the car's paint)
15+
*
16+
* NFSU2_REFLECT_SKY=1: the sky in the road reflection and the mirror.
17+
* The sky (0x60f890: puts the sky model around the view's camera) is only
18+
* drawn for the main view and, as its own small sky, in the car cube map; the
19+
* road reflection and the mirror show black where the sky would be. Here the
20+
* road reflection (before its scenery, 0x5cab69) and the mirror (0x5cae71)
21+
* draw it too, the way the main view does (sky, then 0x5cf430 draws the
22+
* queued models). In 0x60f890 both take the main view's path (0x60f9f6,
23+
* edx = 1), the sky scaled to fit inside the view's far plane (10 km for the
24+
* road reflection, 192 m for the mirror). The road reflection draws the
25+
* scenery mirrored in z (0x5d67b9 negates each model's z axis), so its sky's
26+
* matrix (the newest one in the per-frame pool at 0x82da5c) is mirrored too.
27+
*
28+
* NFSU2_REFLECT_LIGHTS=1: the cars' lights in the road reflection.
29+
* The game calls 0x6154a0 (the cars' light glows for a reflection, from each
30+
* car's own light colours) for the road reflection inside the scenery
31+
* shader's pass (0x5cac17), where it draws nothing, and draws the glows with
32+
* the generic 0x494270 instead (0x5cacb5, a dimmer shader). Here 0x6154a0 is
33+
* skipped at the first place and drawn instead of 0x494270 for the road
34+
* reflection, in the light glows' own pass: the same glows, white and bright.
35+
*
36+
* NFSU2_REFLECT_DETAIL=1: more detail in the reflections.
37+
* The reflections draw the scenery's low-detail models (0x5d6666: flags
38+
* 0x1800 of the view = reflection, 0x20 = mirror) and the cars in the road
39+
* reflection at their lowest level of detail (0x63167d, 0x6311fc: the model
40+
* and wheel LOD); here they get the main view's. The cube map's far plane
41+
* (0x7fee8c, 64 m) moves to 10 km, so the car's paint reflects the city
42+
* rather than the street around it. It roughly doubles the draws into the
43+
* reflections. */
44+
#include "cpu.h"
45+
#include <stdio.h>
46+
#include <stdlib.h>
47+
#include <string.h>
48+
#include <strings.h>
49+
50+
void sub_006154a0_orig(CPU *c);
51+
void sub_00494270_orig(CPU *c);
52+
53+
#if NFS_ENHANCED
54+
55+
uint32_t call_guest(CPU *c, uint32_t fn, int nargs, const uint32_t *args); /* com.c */
56+
57+
/* hook sites (tools/gen_v2.sh HOOKS) */
58+
#define H_ROAD_SCENERY GA(0x005cab69u) /* push 8: view 4's scenery list */
59+
#define H_MIRROR_SCENERY GA(0x005cae71u) /* push 1: view 3's scenery list */
60+
#define H_SKY_SCALE GA(0x0060f9f6u) /* cmp edx,1: the sky's scale is in st0 */
61+
#define H_SCENERY_LOD GA(0x005d6666u) /* test bh,0x18: ebx = the view's flags */
62+
#define H_CAR_LOD GA(0x0063167du) /* push ecx: ecx/edx = model/wheel LOD */
63+
#define H_CAR_LOD2 GA(0x006311fcu) /* mov edx,[ebp+0xc]: eax/ecx = model/wheel LOD */
64+
#define FN_SKY GA(0x0060f890u)
65+
#define FN_DRAW_QUEUED GA(0x005cf430u)
66+
#define CUBE_FAR GA(0x007fee8cu) /* float, 64.0 */
67+
#define SKY_POOL GA(0x0082da5cu) /* next free 4x4 in the per-frame matrix pool */
68+
69+
static int g_init, g_sky, g_lights, g_detail;
70+
static unsigned long g_n_sky[2], g_n_lod, g_n_car, g_n_lights;
71+
static int g_lights_here;
72+
73+
static int on(const char *name){
74+
const char *e = getenv(name);
75+
return e && *e && *e != '0';
76+
}
77+
78+
static void refl_init(void){
79+
if (g_init) return;
80+
g_init = 1;
81+
g_sky = on("NFSU2_REFLECT_SKY");
82+
g_lights = on("NFSU2_REFLECT_LIGHTS");
83+
g_detail = on("NFSU2_REFLECT_DETAIL");
84+
if (g_sky || g_lights || g_detail)
85+
fprintf(stderr, "reflections:%s%s%s\n",
86+
g_sky ? " sky" : "", g_lights ? " car-lights" : "", g_detail ? " more-detail" : "");
87+
}
88+
89+
/* ---- hooks (debug.c guest_hook, before the instruction at ip) ------------- */
90+
static int refl_view(uint32_t id){ return id == 3u || id == 4u || (id >= 16u && id <= 21u); }
91+
92+
int refl_hook(CPU *c, uint32_t ip){
93+
switch (ip){
94+
case H_ROAD_SCENERY: case H_MIRROR_SCENERY:
95+
refl_init();
96+
if (g_sky && c->esi){
97+
uint32_t a[1] = { c->esi }, pool = MR32(SKY_POOL);
98+
call_guest(c, FN_SKY, 1, a);
99+
/* The road reflection draws the scenery mirrored in z (0x5d67b9 negates
100+
* each model's z axis); mirror the sky the same way, about the camera:
101+
* the sky is far enough for the plane not to matter. */
102+
if (ip == H_ROAD_SCENERY && MR32(SKY_POOL) == pool + 0x40u)
103+
MRF32(pool + 0x28u) = -MRF32(pool + 0x28u);
104+
call_guest(c, FN_DRAW_QUEUED, 0, a);
105+
g_n_sky[ip == H_MIRROR_SCENERY]++;
106+
}
107+
return 1;
108+
case H_SKY_SCALE:
109+
/* The road reflection takes the main views' path (edx 1-3 draw the sky).
110+
* The main views' sky (scale 1) fits inside their 10 km far plane; the
111+
* mirror's far plane is 192 m, so its sky is scaled to fit inside its own. */
112+
if (g_sky && (c->edx == 3u || c->edx == 4u)){
113+
uint32_t v = MR32(c->ebp + 8u), cam = v ? MR32(v + 0x40u) : 0u;
114+
float far = cam ? MRF32(cam + 0xc0u) : 0.f, k = far / 10400.f;
115+
if (k > 0.f) ST(0) = (double)(k < 1.f ? k : 1.f);
116+
c->edx = 1u;
117+
}
118+
return 1;
119+
case H_SCENERY_LOD:
120+
refl_init();
121+
if (g_detail && (c->ebx & 0x1820u)){
122+
static int far_set;
123+
if (!far_set){ far_set = 1; MRF32(CUBE_FAR) = 10000.f; }
124+
c->ebx &= ~0x1820u; g_n_lod++;
125+
}
126+
return 1;
127+
case H_CAR_LOD: case H_CAR_LOD2:
128+
if (g_detail){
129+
uint32_t v = MR32(c->ebp + 8u);
130+
if (v && refl_view(MR32(v + 4u))){
131+
if (ip == H_CAR_LOD){ c->ecx = 0; c->edx = 0; }
132+
else { c->eax = 0; c->ecx = 0; }
133+
g_n_car++;
134+
}
135+
}
136+
return 1;
137+
}
138+
return 0;
139+
}
140+
141+
/* ---- car lights in the road reflection (tools/gen_v2.sh OVR) -------------- */
142+
void sub_006154a0(CPU *c){ /* cdecl (eView *view) */
143+
refl_init();
144+
if (g_lights && !g_lights_here){ POP32(c->eip); return; } /* drawn below instead */
145+
sub_006154a0_orig(c);
146+
}
147+
148+
void sub_00494270(CPU *c){ /* cdecl (eView *view, int, int pass) */
149+
refl_init();
150+
uint32_t v = MR32(c->esp + 4u);
151+
if (g_lights && v && MR32(v + 4u) == 4u && MR32(c->esp + 12u) == 1u){
152+
g_lights_here = 1;
153+
PUSH32(v); PUSH32(MR32(c->esp + 4u));
154+
sub_006154a0_orig(c);
155+
c->esp += 4u;
156+
g_lights_here = 0;
157+
g_n_lights++;
158+
POP32(c->eip);
159+
return;
160+
}
161+
sub_00494270_orig(c);
162+
}
163+
164+
void refl_report(void){
165+
if (!g_init || !(g_sky || g_lights || g_detail)) return;
166+
fprintf(stderr, " reflections : sky road %lu / mirror %lu, scenery LOD raised %lu, car LOD raised %lu, car lights drawn %lu\n",
167+
g_n_sky[0], g_n_sky[1], g_n_lod, g_n_car, g_n_lights);
168+
}
169+
170+
#else /* original engine: the game's own reflections */
171+
int refl_hook(CPU *c, uint32_t ip){ (void)c; (void)ip; return 0; }
172+
void sub_006154a0(CPU *c){ sub_006154a0_orig(c); }
173+
void sub_00494270(CPU *c){ sub_00494270_orig(c); }
174+
void refl_report(void){}
175+
#endif

0 commit comments

Comments
 (0)