Repository navigation
NFSU2 Revived v0.15.6
What's Changed in v0.15.6
In-Game Frame Rate Limiting & Real-Time Pacing
- Direct3D9 Companion Frame Pacing: Added high-precision microsecond frame pacing inside
nfs_roam_frame_tick()inroam_android.c. Selecting an FPS limit in touch control settings (30, 60, 90, 120 FPS, or uncapped) takes effect immediately during gameplay:static void pace_frame(void) { uint32_t limit = s_target_fps; if (limit < 30 || limit > 240) return; int64_t now_us = roam_plat_now_us(); int64_t target_interval_us = 1000000 / (int64_t)limit; if (s_next_deadline_us < now_us) s_next_deadline_us = now_us; int64_t wait_us = s_next_deadline_us - now_us; if (wait_us > 500 && wait_us <= target_interval_us) { struct timespec req; req.tv_sec = wait_us / 1000000; req.tv_nsec = (wait_us % 1000000) * 1000; nanosleep(&req, NULL); now_us = roam_plat_now_us(); } s_next_deadline_us = ((now_us > s_next_deadline_us) ? now_us : s_next_deadline_us) + target_interval_us; }
- Physics Delta Synchronization: Synchronized real elapsed time with
G_WORLDDT(0x00865154) andA_REALDT(0x00865198) viaframerate_pacing_fix(). Pacing down to 30 FPS automatically rescales physics simulation dt so car handling and racing speeds remain in real time without slow motion. - JNI Limiter Integration: Wired
nativeSetFrameLimitthroughRoamNativeBridge.javaandGameActivity.javato dynamically push updated targets directly tolibnfsu2_roam.so.
Touch Controls Editor UX Polish
- Dismiss on Initial Tap: In
RacingControlsView.java, tapping the control settings button before dragging or repositioning any controls closes the editor immediately:Control hitControl = hit(e.getX(index), e.getY(index)); if (!hasMovedControl && hitControl != null && hitControl.scan == EDIT) { setEditing(false); layoutControls(); invalidate(); return true; }
- Display Logs Suppression: Suspended the DiagnosticOverlay telemetry display while the touch controls editor is open, restoring it automatically when exiting the editor:
touchControls.setOnEditingChangeListener(editing -> { if (diagnosticOverlay != null) { diagnosticOverlay.setSuspended(editing); } });
Rust D3D9 State Deduplication & NEON SIMD Audio Engine
- D3D9 Redundant State Deduplication Filter (
d3d9_filter.rs): D3DX effect passes inSPEED2.EXEissue thousands of redundant render state calls per frame. The Rust shadow filter deduplicatesSetRenderState,SetTexture, andSetSamplerState, returningD3D_OKimmediately:// SetRenderState(State, Value) 57 => { *out_count = 3; let state = args[1] as usize; let val = args[2]; if state < 256 { if self.rs_valid[state] && self.rs[state] == val { return true; } self.rs[state] = val; self.rs_valid[state] = true; } false }
- ARM64 NEON SIMD Audio Resampler (
simd_audio.rs): Replaced scalar sinc kernel interpolation with 128-bit ARM64 NEON vector multiply-accumulate operations:for i in (0..16).step_by(4) { let w_curr = vld1q_f32(weights_curr.add(i)); let w_next = vld1q_f32(weights_next.add(i)); let w_diff = vsubq_f32(w_next, w_curr); let w = vmlaq_f32(w_curr, w_diff, v_blend); let s_l = vld1q_f32(samples_left.add(i)); let s_r = vld1q_f32(samples_right.add(i)); acc_l = vmlaq_f32(acc_l, s_l, w); acc_r = vmlaq_f32(acc_r, s_r, w); }
Rust OpenGL ES Optimizer & Graphics Pipeline Cache
- GLES State Shadow Filter & Program Binary Cache (
gles_optimizer.rs): Dropped redundant GLES driver state switches before crossing intolibGLESv2and cached compiled shader program binaries to disk. - Async Pipeline Compiler (
async_compiler.rs): Pre-compiles Vulkan and GLES pipeline states in worker threads. Removed the redundant manual cache reset button from the launcher settings.
Full Changelog: v0.15.5...v0.15.6