Move file cache to standalone module, add timer fix, fix refcount crashes

File cache (filecache module):
- Moved from transform44 sub-module to standalone src/filecache/
- 2-way set-associative cache (32768 sets x 2 ways) with FNV-1a hash + finalizer
- Fixed negative cache hit crash: zero output params before returning 0
  (FindFileInArchive reuses filename slot for out_outer_archive)
- Fixed path 2 crash: set out_outer_archive on all cache hit paths
- Fixed stale block_entry crash: cache block index instead of raw pointer,
  recompute from archive+0x290 on each hit
- Fixed archive-freed crash: use game's FindAndIncrementResourceReference
  (0x650780) instead of manual +0x38 increment -- validates archive is alive
- Periodic stats dump with projected time savings (hit=~1000cy vs miss=~30000cy)

Timer fix (transform44 sub-module, ported from VanillaFixes):
- TSC calibration via QPC reference over 500ms
- Enables TSC mode if game was using GetTickCount fallback
- NtSetTimerResolution for 0.5ms OS timer granularity
- SetProcessInformation to disable Windows 11 power throttling
- Always-on (no A/B toggle -- no measurable impact on Wine/Linux)
This commit is contained in:
MarcelineVQ
2026-03-14 14:57:58 -07:00
parent 0833d23e28
commit 692a02ed2c
6 changed files with 571 additions and 172 deletions
+7 -17
View File
@@ -15,7 +15,6 @@ const std = @import("std");
const hook = @import("zhook");
const logging = @import("../logging.zig");
const mod_mutex = @import("../mutex.zig");
pub const file_cache = @import("file_cache.zig");
const timer_fix = @import("timer_fix.zig");
extern fn clipPolygonToSinglePlane(u32, u32, u32) void;
extern fn buildTrianglePlanes(u32, u32, u32, u32, u32) u32;
@@ -38,7 +37,7 @@ pub fn isActive() bool {
// Profiling state — unified dump every DUMP_FRAMES render passes
// =============================================================================
const DUMP_FRAMES: u64 = 1800; // ~30s at 60fps
const DUMP_FRAMES: u64 = 900; // ~15s at 60fps
var prof = ProfState{};
var t44_depth: u64 = 0; // recursion depth — survives resets
@@ -237,9 +236,11 @@ fn transformDetour(this: u32, edx: u32, mat1: u32, mat2: u32, mat3: u32, mat4: u
t44_depth +|= 1;
if (t44_depth > prof.t44_max_depth) prof.t44_max_depth = t44_depth;
// bone_sse disabled — investigating crash in post-bone-loop sections
_ = transformMatrix4x4_SSE;
transform_hook.callOriginal(.{ this, edx, mat1, mat2, mat3, mat4 });
if (ab_use_custom) {
transformMatrix4x4_SSE(this, mat1, mat2, mat3, mat4);
} else {
transform_hook.callOriginal(.{ this, edx, mat1, mat2, mat3, mat4 });
}
t44_depth -|= 1;
const elapsed = rdtsc() - start;
@@ -1306,18 +1307,7 @@ fn dumpStats() void {
});
}
// File cache stats
const fc = file_cache.getCacheStats();
if (fc.total > 0) {
const fc_hit_pct = pct(fc.hits + fc.neg_hits, fc.total);
log.fmt(" file_cache: {d}.{d}% hit ({d}hit/{d}neg/{d}miss) {d} entries\n", .{
fc_hit_pct / 10, fc_hit_pct % 10,
fc.hits, fc.neg_hits, fc.misses, fc.entries,
});
}
// Reset per-period cache stats, flip A/B mode
file_cache.resetStats();
// Flip A/B mode
ab_use_custom = !ab_use_custom;
prof = ProfState{};
}