Add MPQ archive file cache: skip redundant chain walks on repeat file opens

Hook File_FindInArchive (0x6549a0) with a direct-mapped filename-verified
cache. First open does the full MPQ chain walk (~60K cycles), subsequent
opens hit the cache (~300 cycles). 80% hit rate in gameplay testing.

Cache design: 16384 entries, FNV-1a hash for slot index, raw filename
comparison (128 bytes) for collision safety. Stores outer_archive,
inner_archive, and block_entry per file. Negative cache for not-found files.
Refcount at +0x38 incremented on all output archives to match original
File_FindInArchive behavior (verified via Ghidra: FindAndIncrementResourceReference
at 0x650780, DecrementResourceReference at 0x6507e0).

Also: default build changed to ReleaseFast (works around Zig fastcall inreg
bug in Debug mode), logging gate changed to != ReleaseSmall, file cache
integrated as transform44 sub-module with A/B comparison timing in readout.
This commit is contained in:
MarcelineVQ
2026-03-13 23:05:38 -07:00
parent bb8a6ef8a6
commit 55735d7b9e
6 changed files with 295 additions and 47 deletions
+11 -3
View File
@@ -30,7 +30,6 @@ const module_list = [_]ModuleDesc{
.{ .name = "dpslog", .desc = "Enable structured combat log events for addons", .default = false },
.{ .name = "transform44", .desc = "Enable transformMatrix4x4 hook", .default = false },
.{ .name = "addonperf", .desc = "Enable addon memory/CPU profiling API" },
.{ .name = "file_perf", .desc = "Enable file access profiling", .default = false, .addon_name = "FilePerf", .addon_hidden = true },
};
pub fn build(b: *std.Build) void {
@@ -40,7 +39,7 @@ pub fn build(b: *std.Build) void {
.abi = .msvc,
.cpu_features_add = std.Target.x86.featureSet(&.{ .sse, .sse2 }),
});
const optimize = b.standardOptimizeOption(.{});
const optimize = b.option(std.builtin.OptimizeMode, "optimize", "Optimization mode (default: ReleaseFast)") orelse .ReleaseFast;
const build_options = b.addOptions();
addModuleOptions(b, build_options);
@@ -52,7 +51,7 @@ pub fn build(b: *std.Build) void {
});
const zhook_mod = zhook_dep.module("zhook");
// Hot math — separate compilation unit, always ReleaseFast
// Hot math — separate compilation units, always ReleaseFast
const clip_sse_obj = b.addObject(.{
.name = "clip_sse",
.root_module = b.createModule(.{
@@ -61,6 +60,14 @@ pub fn build(b: *std.Build) void {
.optimize = .ReleaseFast,
}),
});
const bone_sse_obj = b.addObject(.{
.name = "bone_sse",
.root_module = b.createModule(.{
.root_source_file = b.path("src/transform44/bone_sse.zig"),
.target = target,
.optimize = .ReleaseFast,
}),
});
const lib = b.addLibrary(.{
.name = "weirdutils",
@@ -76,6 +83,7 @@ pub fn build(b: *std.Build) void {
}),
});
lib.root_module.addObject(clip_sse_obj);
lib.root_module.addObject(bone_sse_obj);
b.installArtifact(lib);
// Convenience step to build all single-module variants