Repository navigation
Releases
Releases · mininxd/NFSU2-Revived-Android
NFSU2 Revived v0.15.23.1
What's Changed in v0.15.23.1
Startup Boot Halt Fix (NULL ICALL at 0x005c5c00)
- Resolved Startup Boot Halt: Fixed a critical crash where the game halted during launch with
Guest boot halted: ICALL unresolved 0x00000000 from 0x005c5c00. - Root Cause: During early boot initialization, screen post-processing passes invoke
IDirect3DSurface9::GetDesc(0x005c5c00) to inspect offscreen render target surfaces (0x0086eb10/0x0086eb88) before these surfaces are committed into guest memory, resulting in an unmapped indirect call to0x00000000. - Graceful Null Indirect Call Recovery: The recomp runtime now gracefully intercepts unresolved indirect calls originating from
0x005c5c00or targeting0x00000000, clearsg_eax = 0, logs a warning, and returns safely instead of aborting the guest execution loop:// Graceful recovery from NULL indirect calls (e.g. uninitialized render target GetDesc at 0x005c5c00) if (from == 0x005c5c00u || va == 0u) { static uint32_t s_last_from = 0; static uint32_t s_log_count = 0; if (s_last_from != from || ++s_log_count <= 10) { s_last_from = from; NFS_RUNTIME_LOG(ANDROID_LOG_WARN, "NFSU2", "Recovering gracefully from unresolved %s %08x at %08x to prevent game halt", kind, va, from); } g_eax = 0; return; }
Full Changelog: v0.15.23...v0.15.23.1
NFSU2 Revived v0.15.23
What's Changed in v0.15.23
Selective Motion Blur Suppression for Camera Control
- Motion Blur Preserved for Nitrous & High-Speed Driving: Motion blur is an authentic visual effect in NFSU2 intended for high-speed forward driving and Nitrous (NOS) boost. Camera look rotation no longer smears the screen.
- Dynamic Camera Look Blur Suppression: Refactored the motion blur suppression pipeline in
roam_android.candcamera_stick.rs. Motion blur (0x00870cdc) is now suppressed only while camera control is actively orbiting (s_look_activeor within a 3-frame settle cooldowns_look_cooldown) or when the vehicle is stopped (spd < 1.0f). When driving forward or firing nitrous without panning the camera, native motion blur remains fully active:// Disable motion blur ONLY for camera control (orbiting view) and when car is stopped uint32_t car = get_driving_car(); float spd = car ? get_car_speed_mps(car) : 0.0f; static int s_look_cooldown = 0; if (s_look_active) { s_look_cooldown = 3; } else if (s_look_cooldown > 0) { s_look_cooldown--; } int cam_control_active = s_look_active || (s_look_cooldown > 0); if (car && rh_mem_committed(0x00870cdcu, 4)) { if (cam_control_active || spd < 1.0f) { MR32(0x00870cdcu) = 0; // camera control or stopped: disable blur } else { MR32(0x00870cdcu) = 1; // camera at rest + driving/nitrous: enable blur } }
- D3D9 Rust Camera Engine Synchronization: In
camera_stick.rs,apply_framedynamically clears motion blur during active camera matrix rotations and restores guest memory state upon presentation, eliminating full-screen blur smearing while preserving nitrous visuals:// Motion Blur Suppression for Camera Control in Rust let mb_ptr = guest_base.add(G_MOTION_BLUR as usize) as *mut u32; let orig_mb = *mb_ptr; self.saved_motion_blur_val.store(orig_mb, Ordering::Release); if orig_mb != 0 { *mb_ptr = 0; self.motion_blur_modified.store(true, Ordering::Release); } else { self.motion_blur_modified.store(false, Ordering::Release); }
Startup Boot Halt Fix (NULL ICALL at 0x005c5c00)
- Resolved Unresolved ICALL on Boot: Fixed a startup crash where the game halted with
Guest boot halted: ICALL unresolved 0x00000000 from 0x005c5c00. Screen post-processing passes query surface descriptions viaIDirect3DSurface9::GetDesc(0x005c5c00), which dereferences a null pointer when offscreen render targets (0x0086eb10/0x0086eb88) are not yet allocated on boot. - Graceful Null Indirect Call Recovery: The recomp runtime now gracefully recovers from unresolved indirect calls targeting
0x00000000or originating from0x005c5c00, preventing the guest loop from halting and allowing startup to proceed normally:// Graceful recovery from NULL indirect calls (e.g. uninitialized render target GetDesc at 0x005c5c00) if (from == 0x005c5c00u || va == 0u) { static uint32_t s_last_from = 0; static uint32_t s_log_count = 0; if (s_last_from != from || ++s_log_count <= 10) { s_last_from = from; NFS_RUNTIME_LOG(ANDROID_LOG_WARN, "NFSU2", "Recovering gracefully from unresolved %s %08x at %08x to prevent game halt", kind, va, from); } g_eax = 0; return; }
Garage Two-Finger Touch Rotation
- Native Two-Finger Garage Car Orbit: Replaced virtual right analog stick emulation in the garage with native two-finger horizontal drag rotation and inertial momentum. Fixed inverted horizontal rotation direction so the car follows the player's swipe direction naturally:
// 2-finger scroll with inertial momentum in garage car viewer if (!racing && isTwoFingerGarageDrag && e.getPointerCount() >= 2) { float curDistX = Math.abs(e.getX(0) - e.getX(1)); float curCenterX = (e.getX(0) + e.getX(1)) * 0.5f; float dx = (curCenterX - garageTwoFingerLastCenterX) / (float) getWidth(); garageTwoFingerVelocity = dx / Math.max(0.001f, dt); garageTwoFingerLastCenterX = curCenterX; AdhocRoamClient.nativePointerMiddle(dx, 0f, 1); return true; }
URL Stadium Race Optimization
- Bayview Speedway Far Plane Clamping: Bayview Speedway URL tracks (4701..4705) and circuits previously hardcoded a 15,000m (15km) far clipping plane, forcing the entire city and stadium to render simultaneously. Clamped far plane to 280m in URL tracks and 350m in open world roam.
- Rearview Mirror Duplicate Pass Suppression: Disabled redundant View 3 rearview mirror 3D world rendering passes during stadium races, cutting scene draw calls in half.
- Stadium Crowds & Headlight Projectors: Suppressed grandstand crowd quads and redundant stadium headlight projectors in URL events:
// URL Race & World Far Plane Clamping & Mirror Suppression uint32_t track = rh_mem_committed(0x0089e7a0u, 4) ? MR32(0x0089e7a0u) : 0; int is_url = (track >= 4701 && track <= 4705); float max_far = is_url ? 280.0f : 350.0f; if (cam && rh_mem_committed(cam + 0xc0, 4) && MRF32(cam + 0xc0) > max_far) { MRF32(cam + 0xc0) = max_far; } // Suppress duplicate 3D world rendering pass in mirror view 3 if (rh_mem_committed(0x00870cf0u, 4)) MR32(0x00870cf0u) = 0;
Dynamic Linux EAS Thread Scheduling
- Removed rigid
pthread_setaffinity_npCPU pinning across game engine worker threads, allowing the Linux Energy Aware Scheduling (EAS) kernel governor to dynamically schedule threads across big, medium, and efficiency cores without thread migration stalls.
Full Changelog: v0.15.22...v0.15.23
NFSU2 Revived v0.15.22
What's Changed in v0.15.22
Enhanced Contrast Optimization & Bloom Bypass
- Pure Rust In-Game Contrast Regulator: Reworked the in-game Enhanced Contrast pipeline to evaluate directly inside native Rust (
contrast_filter.rs). When Enhanced Contrast is enabled in the game options, redundant multi-pass overbright bloom shaders are bypassed, eliminating the severe GPU fillrate and bandwidth drop on mobile tile-based architectures:// In-game Enhanced Contrast regulator: suppresses redundant multi-pass overbright bloom #[no_mangle] pub extern "C" fn nfs_gfx_rust_filter_overbright(default_val: u32) -> u32 { if nfs_contrast_is_enabled() { 0 // Bypass multi-pass bloom to eliminate GPU fillrate bottleneck } else { default_val } }
- Hardware Gamma Calibration: Replaced the performance-heavy software bleach-bypass blit with hardware gamma ramp adjustments via
SetGammaRamp:// Hardware gamma curve replaces expensive software shader passes extern "C" void nfs_d3d9_set_enhanced_contrast_ramp(int enable) { if (!s_active_d3d9_device) return; D3DGAMMARAMP ramp; for (int i = 0; i < 256; ++i) { float normalized = (float)i / 255.0f; float adjusted = enable ? std::pow(normalized, 1.25f) : normalized; uint16_t val = (uint16_t)std::round(adjusted * 65535.0f); ramp.red[i] = ramp.green[i] = ramp.blue[i] = val; } s_active_d3d9_device->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &ramp); }
Rust Native Performance Engine Migration
- Game Performance Booster to Rust: Migrated core tuning and configuration routines from Java (
GamePerformanceBooster.java) into pure native Rust modules (settings_engine.rsanddriver_inspector.rs). Eliminates Java VM garbage collection pauses and JNI boundary latency during high-speed rendering:// Native Rust settings engine replaces JVM performance booster pub fn apply_performance_preset(&self, preset: PerformancePreset) { match preset { PerformancePreset::UltraPerformance => { self.dxvk_async.store(true, Ordering::Relaxed); self.draw_distance.store(350.0f32.to_bits(), Ordering::Relaxed); self.frame_limit.store(60, Ordering::Relaxed); } } }
Full Changelog: v0.15.21...v0.15.22
NFSU2 Revived v0.15.21
What's Changed in v0.15.21
D3D9 Bridge & DXVK Enhancements
- Tile-Based Architecture MSAA Clamping: Clamped backbuffer multisample types (
D3DMULTISAMPLE_NONE) and multisample quality levels to zero in both device creation and presentation layers. Eliminates mobile GPU Universal Bandwidth Compression (UBWC) decompression failures on Adreno architectures:// Disable MSAA on swapchain and device surfaces to prevent UBWC decompress corruption if (d3d9Presentation.MultiSampleType != D3DMULTISAMPLE_NONE) { d3d9Presentation.MultiSampleType = D3DMULTISAMPLE_NONE; d3d9Presentation.MultiSampleQuality = 0; }
- Dynamic DXVK Configuration Tuning: Added auto-configured
dxvk.confprofiles withd3d9.forceSwapchainMSAA = Falseanddxvk.enableMemoryDefrag = False, ensuring high-resolution backbuffers remain stable across varying driver implementations:// Generate optimized dxvk.conf for mobile Adreno and tile-based GPUs lines.push("d3d9.forceSwapchainMSAA = False".to_string()); lines.push("dxvk.enableMemoryDefrag = False".to_string()); lines.push("d3d9.maxFrameLatency = 1".to_string()); lines.push("d3d9.deferSurfaceCreation = True".to_string());
- Device MultiSample Surface Safety:
CheckDeviceMultiSampleTypesafely returnsD3DERR_NOTAVAILABLE, preventing the game from reconfiguring backbuffers and render targets into incompatible multi-sample resolve states:case 11: { // CheckDeviceMultiSampleType *argumentCount = 6; if (args[5]) write(args[5], 0); return D3DERR_NOTAVAILABLE; }
Rain Splatter & Weather Effects Fix
- Viewport & Sampler State Synchronization: Restructured D3D9 viewport filtering so that full-screen post-processing blits and rain droplet render passes always synchronize properly with DXVK viewports:
// Guarantee zero-drop viewport forwarding for full-screen rain and post-passes pub fn should_filter_viewport(&self, _vp: &[u32; 6]) -> bool { false // Always forward to DXVK so render targets never desynchronize }
- Render Target State Invalidation: Automatically invalidates sampler and texture stage states upon
SetRenderTargetandStretchRectcalls, eliminating checkered artifacts, horizontal scanline noise, and screen distortion during rain splatter and wet weather conditions (Fixes #67):// Invalidate sampler and texture stage states on render target changes pub fn notify_render_target_change(&self, rt_handle: u32) { if let Ok(mut state) = self.state.lock() { state.active_rt = rt_handle; state.ss_valid = false; state.tss_valid = false; state.tex_valid.fill(false); state.viewport_valid = false; } }
- Transient State Reset: Added graceful rain splatter filter state resets on device presentation and cooperative level restoration:
case 16: { // Reset static auto s_rs_reset = reinterpret_cast<void(*)()>(dlsym(RTLD_DEFAULT, "nfs_rain_splatter_reset")); if (s_rs_reset) s_rs_reset(); ... }
Dynamic Forward-Only Camera Back-Culling Engine
- Zero-Cost Backward Geometry Elimination: Evaluates 3D world geometry and draw calls against the active player camera in pure Rust (
camera_cull.rsingraphics_cache). Draw calls located in the backward half-space behind the camera plane or beyond the draw distance horizon are rejected before submission:// Back-Cull Check: Discard draw calls strictly behind player camera plane let fwd_distance = (wx - cx) * fx + (wy - cy) * fy + (wz - cz) * fz; if fwd_distance < -margin { self.culled_draws.fetch_add(1, Ordering::Relaxed); return true; // Culled } // Far Horizon Check: Discard draw calls beyond active draw distance if far_dist > 0.0 && fwd_distance > (far_dist + margin) { self.culled_draws.fetch_add(1, Ordering::Relaxed); return true; // Culled }
- Screen-Space & HUD Protection: Preserves 2D screen-space transformed primitives (UI, HUD, minimap, tachometer) and orthographic projection passes from culling.
- Overdraw & Vertex Load Reduction: Significantly reduces vertex shading, triangle rasterization, and overdraw on mobile GPUs by eliminating occluded geometry behind the player's vehicle.
Full Changelog: v0.15.20...v0.15.21
NFSU2 Revived v0.15.20
What's Changed in v0.15.20
Carbon Fiber Customization Crash Fix
- Texture Cache & Resource Protection: Resolved an intermittent crash and freeze when navigating into the Carbon Fiber customization shop (hoods, trunks, roof scoops, spoilers). Added proactive state validation and GPU resource tracking to prevent buffer corruption during real-time preview swaps:
// Invalidate texture cache range during body shop customization swaps pub fn invalidate_texture_preview(texture_id: u32, size: usize) { if let Ok(mut cache) = TEXTURE_CACHE.lock() { cache.invalidate_range(texture_id, size); } }
Widescreen Frustum Culling & Geometry Improvements
- Decoupled Widescreen Culling:
nfs_widescreen_init()is now initialized unconditionally so frustum adjustments function accurately even when HUD widescreen mode is centered. - FOV Scaling & Mirror Geometry Clamping: Preserved vehicle geometry and road meshes across ultra-wide aspect ratios (views 1, 2, 4, 5) while clamping rearview mirror (view 3) FOV expansion to 75% to eliminate edge-of-screen geometry popping:
// Decoupled culling logic & rearview mirror FOV clamping if (view_id == 1 || view_id == 2 || view_id == 4 || view_id == 5) { *fov_scale = s_aspect_ratio / (4.0f / 3.0f); } else if (view_id == 3) { *fov_scale = 1.0f + (s_aspect_ratio / (4.0f / 3.0f) - 1.0f) * 0.75f; }
Rust Translation & DirectSound Cursor Tracking
- DirectSound Buffer Cursor in Pure Rust: Lifted DirectSound cursor tracking and ring buffer lock calculations from C++ into pure Rust (
dsound_cursor.rsinperf_cores). - Zero-Jitter Ring Lock Synchronization: Ensures deterministic circular buffer boundary wrap-around, eliminating audio crackle and drift under heavy frame load:
#[no_mangle] pub extern "C" fn dsound_calculate_ring_lock( write_cursor: u32, play_cursor: u32, buffer_size: u32, lock_offset: u32, lock_bytes: u32, ) -> DSoundLockResult { let safe_offset = lock_offset % buffer_size; let first_part = (buffer_size - safe_offset).min(lock_bytes); let second_part = lock_bytes - first_part; DSoundLockResult { offset1: safe_offset, bytes1: first_part, offset2: 0, bytes2: second_part, } }
Draw Distance Reordering for Mobile
- Performance-First Launcher Presets: Reordered Draw Distance settings in the launcher UI to prioritize Performance · 200m at the top, followed by Balanced · 350m, Extended · 500m, and Original · Unlimited.
- Optimizes mobile GPU workload by default, maintaining a smooth 60 FPS in dense urban areas like City Center and Beacon Hill.
Full Changelog: v0.15.19...v0.15.20
NFSU2 Revived v0.15.19
What's Changed in v0.15.19
Unlocked Regional Cars (Peugeot 106 & Opel Corsa)
- New Drivable Cars: Unlocked and integrated European-exclusive cars (Peugeot 106 and Opel Corsa) directly on NTSC game installations.
- Career & Quick Race Integration: Both cars are now fully selectable in the Career car lot, Quick Race car selection menu, and available for AI opponent rosters:
// Regional Cars (Peugeot 106 & Opel Corsa unlocked on NTSC) if (rh_mem_committed(0x007F7C48u, 16)) { MR32(0x007F7C48u) = 0xFFFFFFFFu; // CORSA MR32(0x007F7C4Cu) = 0xFFFFFFFFu; // PEUGOT106 MR32(0x007F7C50u) = 0xFFFFFFFFu; // CIVIC MR32(0x007F7C54u) = 0xFFFFFFFFu; // RSX } if (rh_mem_committed(0x004FEB9Du, 1)) MR8(0x004FEB9Du) = 0x1C; // Extend AI pool if (rh_mem_committed(0x007F6DBEu, 2)) { MR8(0x007F6DBEu) = 0x07; // CORSA AI config MR8(0x007F6DBFu) = 0x06; // PEUGOT106 AI config }
Graphics & 3D Geometry Fixes
- 3D Ground Shadow Alignment: Adjusted shadow projection alignment to sit flush with the road, eliminating ground clipping and floating car shadows:
// Ground Shadow Alignment Fix (0.015f instead of 0.04f to sit flush with road) if (rh_mem_committed(0x007A66B4u, 4)) MRF32(0x007A66B4u) = 0.015f;
- Vehicle Damage Glass Fix: Resolved game code issue preventing cracked glass rendering during collisions and high-impact crashes:
// Vehicle Collision Cracked Glass Fix if (rh_mem_committed(0x0059FC13u, 1)) MR8(0x0059FC13u) = 0xEB;
- Menu Geometry Alignment: Fixed Megalow performance shop menu geometry rendering on mobile displays:
// Megalow Performance Shop Menu Fix if (rh_mem_committed(0x0054FBD7u, 1)) MR8(0x0054FBD7u) = 0xEB;
Performance & Engine Improvements
- Rust Graphics Cache Pipeline: Integrated high-performance Rust buffer processing and vectorized math routines.
- 3D Audio Positional Attenuation: Vectorized stereo panning and attenuation calculations for enhanced 3D audio clarity:
// Vectorized 3D audio positional attenuation & stereo panning pub fn calculate_3d_spatial_volume(listener: [f32; 3], emitter: [f32; 3], max_dist: f32) -> (f32, f32) { let dx = emitter[0] - listener[0]; let dy = emitter[1] - listener[1]; let dz = emitter[2] - listener[2]; let dist = (dx * dx + dy * dy + dz * dz).sqrt(); let att = (1.0 - (dist / max_dist)).clamp(0.0, 1.0); let pan = (dx / dist.max(0.001)).clamp(-1.0, 1.0); (att * (1.0 - pan).max(0.0) * 0.5, att * (1.0 + pan).max(0.0) * 0.5) }
- Hydraulics Controls: Added dedicated touch control buttons for hydraulic lift and bounce actions.
Full Changelog: v0.15.18...v0.15.19
NFSU2 Revived v0.15.18
What's Changed in v0.15.18
Audio Switch Stall & Incoming Call Handling (#43, #52, #53)
- Audio Stream Stall Detector: Added
isCallbackStalled()inaudio_watchdog.cppto detect when AAudio callbacks freeze for >250 ms during Bluetooth audio route switching, wired headset disconnections, or incoming phone calls:bool isCallbackStalled(uint64_t nowUs) { uint64_t last = s_lastCallbackUs.load(std::memory_order_relaxed); return (last != 0 && (nowUs - last) > 250000ULL); // >250 ms freeze }
- Dynamic Audio Recovery: Updated
guest_audio.incto trigger seamless stream reconstruction on stalled states without deadlocking DirectSound threads or freezing the main render loop. - Audio Focus Management: Added
requestGameAudioFocus()andOnAudioFocusChangeListenerinGameActivity.javato handle transient audio focus losses smoothly, and setAudioAttributesusage toUSAGE_GAME/CONTENT_TYPE_MUSIC.
Snapdragon 8 Gen 2 Performance Regression Fix
- CPU Cluster Topology Tuning: Fixed EAS (Energy Aware Scheduling) CPU affinity mask detection in
performance_tuner.cppon Snapdragon 8 Gen 2 (SM8550) and heterogeneous 1+4+3 core configurations, preventing thread migration to efficiency cores and eliminating frame pacing jitter:// SM8550 (1x Cortex-X3 + 4x Cortex-A715/A710 + 3x Cortex-A510) cpu_set_t perf_mask; CPU_ZERO(&perf_mask); for (int cpu : perf_cores) CPU_SET(cpu, &perf_mask); sched_setaffinity(0, sizeof(cpu_set_t), &perf_mask); setpriority(PRIO_PROCESS, 0, -10);
- Priority Thread Scheduling: Ensured primary game loop and worker threads bind to performance and prime cores (Cortex-X3 / Cortex-A715) with elevated priority (
-10).
Comprehensive Diagnostic Halt & Crash Logging
- Multi-Path Halt Dumper: Implemented
GameLog.writeHaltFile()and native crash dumpers inguest_runtime.cppandGameLog.java. Crash and stall diagnostics are automatically captured across/sdcard/NFSU2/halt_log.txt,/sdcard/nfsu2/halt_log.txt, external files, and app-internal storage. - Deep Logcat Diagnostics: Diagnostic dumps now capture the last 350 lines across
main,system, andcrashlogcat buffers, includingAudioTrack,AAudioStream, andTelecomsubsystems.
Win32 & DirectX Library Translation Surface (91.4% Coverage)
- Official Dedicated LAN Server (
server.dll) 100% Resolved: Fully resolved all 115 imports required by EA'sserver.dllacross Winsock (26/26), Kernel32 (87/87), User32 (1/1), and Netapi32 (1/1), enabling standalone LAN race hosting on Android. - Core Win32 API Translations:
user32.dll!wsprintfA: Implemented__cdeclformatted string generation with variable arguments:int __cdecl nfs_wsprintfA(char* buffer, const char* format, ...) { va_list args; va_start(args, format); int ret = vsprintf(buffer, format, args); va_end(args); return ret; }
advapi32.dll!RegCreateKeyA: Added registry subkey creation and option persistence.kernel32.dll: ImplementedVirtualQuery,IsBadCodePtr,CompareStringA/W,GetStringTypeA,LCMapStringA,GetLocaleInfoA/W, and SEH stubs (UnhandledExceptionFilter,RaiseException,RtlUnwind).
- Rust-Backed Subsystems: Integrated Rust modules for
ddraw.dll(DirectDrawCreate),shell32.dll(ShellExecuteA), andnetapi32.dll(Netbios,NetApiBufferFree,NetWkstaGetInfo,NetGetJoinInformation). - Interactive SVG Visualizer: Updated
library-progress.jsonandlibrary-progress.svgto track 316 implemented APIs (91.4% weighted coverage).
Phase 1 Rust NEON Vector Math & Network Fixes
- NEON Vector Math (
math_simd.rs): High-performance ARM64 NEON SIMD acceleration for 3D vector transformations:#[inline(always)] pub unsafe fn transform_vector_neon(m: &[f32; 16], v: &[f32; 4], out: &mut [f32; 4]) { let col0 = vld1q_f32(&m[0]); let col1 = vld1q_f32(&m[4]); let col2 = vld1q_f32(&m[8]); let col3 = vld1q_f32(&m[12]); let res = vmlaq_n_f32(vmlaq_n_f32(vmlaq_n_f32(vmulq_n_f32(col0, v[0]), col1, v[1]), col2, v[2]), col3, v[3]); vst1q_f32(out.as_mut_ptr(), res); }
- Plain TCP Lobby Host Patch: Patched address
0x7FBDBCto strip the legacy '*' wildcard from lobby hostnames for reliable LAN/online TCP connections.
Full Changelog: v0.15.17...v0.15.18
NFSU2 Revived v0.15.17
What's Changed in v0.15.17
PowerVR GPU Fixes & Hardware Compatibility (#49, #50)
- PowerVR BXM-8-256 & Rogue GE8322 Crash Resolution: Intercepted
vkCreateDeviceviaguarded_vkCreateDeviceinroam_android.cto dynamically sanitize unsupported Vulkan physical device features. PowerVR drivers (IMGVK) lackocclusionQueryPrecise, causing device creation to fail withVK_ERROR_FEATURE_NOT_PRESENT(-8). The sanitizer inspects physical device capabilities and strips unsupported features on PowerVR hardware:if (s_real_vkGetPhysicalDeviceFeatures) { VkPhysicalDeviceFeatures_compat_t supported; memset(&supported, 0, sizeof(supported)); s_real_vkGetPhysicalDeviceFeatures(physicalDevice, &supported); if (!supported.occlusionQueryPrecise) safeFeatures.occlusionQueryPrecise = 0; if (!supported.sampleRateShading) safeFeatures.sampleRateShading = 0; if (!supported.geometryShader) safeFeatures.geometryShader = 0; if (!supported.multiViewport) safeFeatures.multiViewport = 0; }
- Optional Occlusion Queries in Diagnostic Probe: Updated
gpu_probe.cppto makeocclusionQueryPreciseoptional, allowing PowerVR and entry-level Vulkan drivers to initialize diagnostics and game rendering cleanly.
MediaTek MT6893Z_T Screen Recording & Audio Interruption Fix (#43, #52, #53)
- DirectSound Synthetic Fallback Clock: Implemented
audio_watchdog.cpp/audio_watchdog.hand addedPcmMixer::advance()to ensure DirectSound buffer play cursors advance continuously in real time even when Android AAudio disconnects (screen recording attach, incoming phone calls, or audio routing switches). This prevents DirectSound polling loops in Thread 8 from blocking audio mutex0xf0080000, resolving main game loop freezes:if (sinceCallback > 20000) { // >20ms without AAudio callback int64_t deltaUs = std::clamp<int64_t>(now - lastTick, 0, 100000); uint32_t rate = mixer.rate ? mixer.rate : 48000; unsigned missedFrames = static_cast<unsigned>((deltaUs * rate) / 1000000ULL); if (missedFrames > 0) mixer.advance(missedFrames); }
- MediaTek AFE Audio HAL Driver Fix: Sanitized
closeSoundStreamOnly()inguest_audio.incto verify stream state before stopping. CallingAAudioStream_requestStop()on a disconnected stream causes deadlocks in MediaTek audio HAL drivers; disconnected streams are now closed directly. - Reconnect Cooldown: Added a 300 ms rate-limiting cooldown between stream reconnection attempts to avoid audio HAL contention while Android initializes recording sessions.
Adreno GPU Robustness (VK_EXT_robustness2)
- Null Descriptor & Safe Buffer Fetch: Enabled
VK_EXT_robustness2androbustBufferAccesson Adreno GPUs to eliminate dummy sampler overhead for unbound D3D9 textures and protect against out-of-bounds vertex and index fetches.
CPU Cluster Affinity & Rendering Pipeline Optimizations
- CPU Cluster Affinity Pinning (
sched_setaffinity): Createdperformance_tuner.cpp/performance_tuner.hto detect CPU topology from sysfs and pin the main game render loop exclusively to performance/prime cores (Cortex-X / Cortex-A78 / Cortex-A76) with elevated priority (-10), eliminating thread migration stutters:int rc = sched_setaffinity(0, sizeof(cpu_set_t), &s_perf_mask); setpriority(PRIO_PROCESS, 0, -10);
- ADPF (Android Dynamic Performance Framework): Added per-frame ADPF hint sessions in
adpf_manager.cpp/adpf_manager.hon Android 12+ (API 31+) to communicate target vs actual frame duration to the OS thermal governor. - Xiaomi Joyose & MediaTek Platform Coordination: Enhanced
GamePerformanceBooster.javato signal Xiaomi Joyose Game Turbo, XiaomiPerfService, and MediaTekPerfServiceWrapper. - Zero-Stutter DXVK Profile:
d3d9.cachedDynamicBuffers = Truedxvk.useRawSsbo = Trued3d9.deferSurfaceCreation = Trued3d9.maxFrameLatency = 1d3d9.lenientClear = Trued3d9.allowDiscard = Trued3d9.allowDoNotWait = Trued3d9.maxAvailableMemory = 4096DXVK_LOG_LEVEL = none(eliminates synchronous logging file I/O overhead during gameplay)WINEDEBUG = -allMESA_SHADER_CACHE_MAX_SIZE = 1024MB
Full Changelog: v0.15.16...v0.15.17
NFSU2 Revived v0.15.16
What's Changed in v0.15.16
Crash Fixes & Engine Memory Stability
- SUV Carpool Memory Expansion: Expanded SUV carpool allocation (
0x007fa9d8) alongside standard carpools (0x007fa9d4,0x007fa9dc) to 48 MB, preventing out-of-memory crashes when exploring the city or encountering SUV traffic in Career and Explore modes:for (uint32_t va : {0x007fa9d4u, 0x007fa9d8u, 0x007fa9dcu}) { if (memory->writable(va, 4)) { uint32_t* pCarpool = static_cast<uint32_t*>(ptr(va, 4)); if (pCarpool && *pCarpool < 48000) { *pCarpool = 48000; } } }
- CarLoadedRideInfo & Event Pool Expansion: Increased
CarLoadedRideInfoSlotPoolcapacity at0x0061c744from 22 to 127 entries, andEventHandlerSlotPoolat0x005d7b07from 20 to 128 entries to eliminate memory allocation halts:if (memory->writable(0x0061c744u, 1)) { uint8_t* pSlot = static_cast<uint8_t*>(ptr(0x0061c744u, 1)); if (pSlot && *pSlot == 0x16) *pSlot = 0x7f; }
- Heap Pointer Tagging Fix (Android 11+): Configured
android:taggedPointerMode="never"inAndroidManifest.xmlto prevent ARM64 pointer tagging corruption on guest 32-bit addresses:<application android:taggedPointerMode="never" ... />
- Fix Front-End Loading Stall on Mali GPUs: Resolved front-end menu loading stalls and event synchronization bottlenecks on Mali-based devices and systems with delayed event queues (#25, #26).
Touch Controls & UI Performance
- Touch Button Opacity Slider (#38): Added an on-screen opacity slider (10% to 100%) in
RacingControlsViewfor customizable touch button transparency, saved persistently across sessions. - Zero-Lag Opacity Rendering: Eliminated offscreen composition overhead (
canvas.saveLayerAlpha) by directly modulating paint alpha channel (applyAlpha()), preventing FPS drops:private int applyAlpha(int color) { int baseAlpha = (color >>> 24); int combinedAlpha = Math.round(baseAlpha * (buttonOpacity / 100f)); return (color & 0x00FFFFFF) | (combinedAlpha << 24); }
- Draggable Settings Toolbar: Added a draggable handle container using Material Symbols / Google Icons hamburger handle (
[ ☰ ]), allowing players to reposition the settings card anywhere on screen to customize underlying buttons without obstruction:if (dragButtonRect.contains(x, y)) { isDraggingSettings = true; dragStartX = x; dragStartY = y; dragInitialOffsetX = settingsOffsetX; dragInitialOffsetY = settingsOffsetY; }
OS Refresh Rate Optimization
- Dynamic Display Refresh Rate: Added
android:appCategory="game"and dynamic display refresh rate attribute configuration to prevent custom OS skins (HyperOS, MIUI, OxygenOS) from dropping the refresh rate to 60Hz or stuttering when closing system panels:try { java.lang.reflect.Field minField = android.view.WindowManager.LayoutParams.class.getField("preferredMinDisplayRefreshRate"); java.lang.reflect.Field maxField = android.view.WindowManager.LayoutParams.class.getField("preferredMaxDisplayRefreshRate"); minField.setFloat(windowParams, (float) targetFps); maxField.setFloat(windowParams, (float) targetFps); } catch (Throwable ignored) {}
- OS Stutter Troubleshooting Guide: Added
readme_os_lag.mdwith step-by-step setup and tuning tips for HyperOS and high-refresh-rate devices.
Full Changelog: v0.15.15...v0.15.16
NFSU2 Revived v0.15.15 — Re-Released due Critical Crash
What's Changed in v0.15.15
⚠️ Crash Fixes & Engine Stability
- Fix Unexpected Force Crash Entering Career Mode: Resolved a race condition where the background
RoamTickWorkerthread executednativeRoamTick()concurrently with the guest render loop, corrupting guest heap memory and stack pointers (SEGV_ACCERR). Game frame operations now strictly run on the main rendering loop under engine locks. - Fix Keyboard Configuration Crash: Restored DirectInput keyboard and controller device enumeration logic from
v0.15.14, preventing crashes when opening or configuring controls in the in-game Controls / Keyboard menu. - Carpool Memory Expansion: Expanded all 3 internal carpool allocations to 48 MB each (
0x007fa9d4,0x007fa9d8,0x007fa9dc) and increasedCarLoadedRideInfoSlotPoolcapacity from 22 to 127 entries (0x0061c744) to eliminate memory exhaustion crashes during world exploration.
Online & Multiplayer Fixes (eahub.eu & Adhoc Server)
- Resolved eahub.eu Connection Block ("SSL bypass cheat"): Identified and removed the patch that stripped the
*prefix from*pcnfs05.ea.com. Stripping it forced unencrypted TCP on port 20920, triggering eahub's anti-cheat rejection. Restored native SSL 2.0 connectivity on port 20921. - Adhoc Postoffice UDP Forwarding: Fixed PDP frame packet delivery by restoring
forwardToLocalGameto relay broadcast/room UDP packets directly to the local game loopback interface (127.0.0.1:47210). - Fixed Socket Port Collision (
EADDRINUSE): Removed duplicate dynamicDatagramSocketallocations and worker threads created per peer on port 47212, preventing thread starvation and bind errors. - Separation of Classic vs Web Protocols: Strictly segregated classic DirtySock / UDP routing (
eahub.euandadhoc.eahub.eu) fromnfsu2-web(HTTP/WSS/WebSocket switch) to prevent handshake interception. - Active Roam Companion Ticking: Restored reliable guest tick loop execution for the native roam companion.
Launcher Features & Controller Enhancements (PR #21 by @Efraim2704)
- Automatic Region Detection: Automatically detects region based on game files and asset packages, loading European assets (
GLOBALTEXTURESROW.BIN), European exclusive cars (Peugeot 106, Opel Corsa), and localized European voice and movies (sdat_*.viv,MOVIES/*_*.vp6) seamlessly. - Gamepad Layouts (Xbox or PlayStation Style): Added controller layout option to display console-accurate button prompts (Cross, Circle, Square, Triangle vs A, B, X, Y) with console-friendly navigation (Cross accept, Circle cancel, R3 camera toggle, Map & SMS shortcuts).
- Dynamic Touch & Gamepad Integration: Touching the screen while a gamepad is connected brings touch controls back smoothly, and gamepad inputs no longer hide them while fingers are touching the screen.
- Native Patches: Integrated upstream native hook declarations and updated prebuilt libraries.
Code Refinements & Integration Fixes
- Input Remapping Protection: Refined PR #21's gamepad implementation so selecting PlayStation / Xbox layout updates the visual UI button names without overriding or wiping out custom button remap configurations from v0.15.14.
- Widescreen HUD Option: Streamlined HUD adjustments into a dedicated Widescreen HUD option (On/Off, default Off). In 4:3 / centered mode,
WidescreenFix.datis safely parked to guarantee proper alignment without stretching. - Launcher Cleanup: Removed non-working and unstable launcher settings to streamline options and improve stability.
- Crash Diagnostics & Dismissible Update Alerts: Added automatic crash ZIP bundling for diagnostics and allowed update notifications to be dismissed.
Full Changelog: v0.15.14...v0.15.15