[Kernel/XMP] Add title-specific file I/O hooks for XMP volume sync

Some games persist BGM volume through their own save files but never
call XMPSetVolume. Add a TitlePatch system that intercepts NtReadFile/
NtWriteFile to apply game-specific logic as well as logic to identify
the memory location that the volume data is read into and monitor that
memory location for changes, updating XMP player volume if it changes
during gameplay.

Includes patches for known games with this issue:
Dead or Alive Xtreme 2 (544307D2), PGR4 (4D5307F9) and PGR3 (4D5307D1)
This commit is contained in:
Herman S.
2026-03-08 14:42:11 +09:00
parent 54400cbc2c
commit 02fccd9113
6 changed files with 246 additions and 4 deletions

View File

@@ -171,6 +171,15 @@ dword_result_t NtReadFile_entry(dword_t file_handle, dword_t event_handle,
// Mark that we should signal the event now. We do this after
// we have written the info out.
signal_event = true;
if (XSUCCEEDED(result)) {
if (auto patch = kernel_state()->xmp_volume_patch()) {
auto host_buf =
kernel_memory()->TranslateVirtual(buffer.guest_address());
patch->OnFileRead(file->entry()->name(), host_buf, buffer_length,
buffer.guest_address());
}
}
} else {
// TODO(benvanik): async.
@@ -346,6 +355,15 @@ dword_result_t NtWriteFile_entry(dword_t file_handle, dword_t event_handle,
// Mark that we should signal the event now. We do this after
// we have written the info out.
signal_event = true;
if (XSUCCEEDED(result)) {
if (auto patch = kernel_state()->xmp_volume_patch()) {
auto host_buf =
kernel_memory()->TranslateVirtual(buffer.guest_address());
patch->OnFileWrite(file->entry()->name(), host_buf, buffer_length,
buffer.guest_address());
}
}
} else {
// X_STATUS_PENDING if not returning immediately.
result = X_STATUS_PENDING;