Skip to content

NFSU2 Revived v0.15.6

Choose a tag to compare

@mininxd mininxd released this 01 Nov 22:23
· 177 commits to main since this release

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() in roam_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) and A_REALDT (0x00865198) via framerate_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 nativeSetFrameLimit through RoamNativeBridge.java and GameActivity.java to dynamically push updated targets directly to libnfsu2_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 in SPEED2.EXE issue thousands of redundant render state calls per frame. The Rust shadow filter deduplicates SetRenderState, SetTexture, and SetSamplerState, returning D3D_OK immediately:
    // 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 into libGLESv2 and 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