OrangeGuidanceTomestone/client/MiniPenumbra/VfxReplacer.cs

74 lines
2.9 KiB
C#
Raw Normal View History

2022-09-05 09:56:13 +00:00
using Dalamud.Hooking;
using Dalamud.Utility.Signatures;
namespace OrangeGuidanceTomestone.MiniPenumbra;
internal unsafe class VfxReplacer : IDisposable {
private delegate byte ReadSqPackDelegate(void* resourceManager, SeFileDescriptor* pFileDesc, int priority, bool isSync);
2024-06-26 15:48:54 +00:00
[Signature("40 55 56 48 83 EC 28 44 0F BE 12", DetourName = nameof(ReadSqPackDetour))]
2022-09-05 09:56:13 +00:00
private Hook<ReadSqPackDelegate> _readSqPackHook;
2024-06-26 15:48:54 +00:00
[Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 63 42 28")]
2022-09-05 09:56:13 +00:00
private delegate* unmanaged<void*, SeFileDescriptor*, int, bool, byte> _readFile;
private Plugin Plugin { get; }
internal VfxReplacer(Plugin plugin) {
this.Plugin = plugin;
2023-09-29 00:53:50 +00:00
this.Plugin.GameInteropProvider.InitializeFromAttributes(this);
2022-09-05 09:56:13 +00:00
this._readSqPackHook!.Enable();
}
public void Dispose() {
this._readSqPackHook.Dispose();
}
private byte ReadSqPackDetour(void* resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync) {
if (!this.Plugin.Config.RemoveGlow) {
goto Original;
}
if (fileDescriptor == null || fileDescriptor->ResourceHandle == null) {
goto Original;
}
var path = fileDescriptor->ResourceHandle->FileName.ToString();
2022-09-06 04:24:32 +00:00
var index = Array.IndexOf(Messages.VfxPaths, path);
if (index == -1) {
2022-09-05 09:56:13 +00:00
goto Original;
}
2022-09-06 04:24:32 +00:00
var letter = (char) ('a' + index);
var newPath = Path.Join(this.Plugin.AvfxFilePath, $"sign_{letter}.avfx");
return this.DefaultRootedResourceLoad(newPath, resourceManager, fileDescriptor, priority, isSync);
2022-09-05 09:56:13 +00:00
Original:
return this._readSqPackHook.Original(resourceManager, fileDescriptor, priority, isSync);
}
// Load the resource from a path on the users hard drives.
private byte DefaultRootedResourceLoad(string gamePath, void* resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync) {
// Specify that we are loading unpacked files from the drive.
// We need to copy the actual file path in UTF16 (Windows-Unicode) on two locations,
// but since we only allow ASCII in the game paths, this is just a matter of upcasting.
fileDescriptor->FileMode = SeFileMode.LoadUnpackedResource;
var fd = stackalloc byte[0x20 + 2 * gamePath.Length + 0x16];
fileDescriptor->FileDescriptor = fd;
var fdPtr = (char*) (fd + 0x21);
for (var i = 0; i < gamePath.Length; ++i) {
(&fileDescriptor->Utf16FileName)[i] = gamePath[i];
fdPtr[i] = gamePath[i];
}
(&fileDescriptor->Utf16FileName)[gamePath.Length] = '\0';
fdPtr[gamePath.Length] = '\0';
// Use the SE ReadFile function.
var ret = this._readFile(resourceManager, fileDescriptor, priority, isSync);
return ret;
}
}