mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-20 14:57:50 +01:00
Compare commits
9 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eec8ee7094 | ||
|
|
13500264b7 | ||
|
|
6ba735eefb | ||
|
|
73f02851a6 | ||
|
|
069323cfb8 | ||
|
|
9aa566f521 | ||
|
|
eff3784a85 | ||
|
|
9cf7030f87 | ||
|
|
deb3686df5 |
6 changed files with 74 additions and 42 deletions
2
.github/workflows/test_release.yml
vendored
2
.github/workflows/test_release.yml
vendored
|
|
@ -9,7 +9,7 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1750c41b53e1000c99a7fb9d8a0f082aef639a41
|
Subproject commit 52a3216a525592205198303df2844435e382cf87
|
||||||
|
|
@ -19,6 +19,12 @@ public class EditingApi(TextureManager textureManager) : IPenumbraApiEditing, IA
|
||||||
TextureType.Bc3Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC3, mipMaps, false, inputFile, outputFile),
|
TextureType.Bc3Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC3, mipMaps, false, inputFile, outputFile),
|
||||||
TextureType.Bc7Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, true, inputFile, outputFile),
|
TextureType.Bc7Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, true, inputFile, outputFile),
|
||||||
TextureType.Bc7Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, false, inputFile, outputFile),
|
TextureType.Bc7Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, false, inputFile, outputFile),
|
||||||
|
TextureType.Bc1Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC1, mipMaps, true, inputFile, outputFile),
|
||||||
|
TextureType.Bc1Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC1, mipMaps, false, inputFile, outputFile),
|
||||||
|
TextureType.Bc4Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC4, mipMaps, true, inputFile, outputFile),
|
||||||
|
TextureType.Bc4Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC4, mipMaps, false, inputFile, outputFile),
|
||||||
|
TextureType.Bc5Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC5, mipMaps, true, inputFile, outputFile),
|
||||||
|
TextureType.Bc5Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC5, mipMaps, false, inputFile, outputFile),
|
||||||
_ => Task.FromException(new Exception($"Invalid input value {textureType}.")),
|
_ => Task.FromException(new Exception($"Invalid input value {textureType}.")),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -36,6 +42,12 @@ public class EditingApi(TextureManager textureManager) : IPenumbraApiEditing, IA
|
||||||
TextureType.Bc3Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC3, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
TextureType.Bc3Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC3, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
TextureType.Bc7Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
TextureType.Bc7Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
TextureType.Bc7Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
TextureType.Bc7Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC7, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
TextureType.Bc1Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC1, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
TextureType.Bc1Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC1, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
TextureType.Bc4Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC4, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
TextureType.Bc4Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC4, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
TextureType.Bc5Tex => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC5, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
TextureType.Bc5Dds => textureManager.SaveAs(CombinedTexture.TextureSaveType.BC5, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
_ => Task.FromException(new Exception($"Invalid input value {textureType}.")),
|
_ => Task.FromException(new Exception($"Invalid input value {textureType}.")),
|
||||||
};
|
};
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Text.Unicode;
|
using System.Text.Unicode;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Iced.Intel;
|
using Iced.Intel;
|
||||||
|
using static Iced.Intel.AssemblerRegisters;
|
||||||
using OtterGui.Extensions;
|
using OtterGui.Extensions;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Swan;
|
using Swan;
|
||||||
|
|
@ -46,36 +47,32 @@ public sealed class PapRewriter(PeSigScanner sigScanner, PapRewriter.PapResource
|
||||||
stackAccesses.RemoveAll(instr => instr.IP == hp.IP);
|
stackAccesses.RemoveAll(instr => instr.IP == hp.IP);
|
||||||
|
|
||||||
var detourPointer = Marshal.GetFunctionPointerForDelegate(papResourceHandler);
|
var detourPointer = Marshal.GetFunctionPointerForDelegate(papResourceHandler);
|
||||||
var targetRegister = hookPoint.Op0Register.ToString().ToLower();
|
var targetRegister = GetRegister64(hookPoint.Op0Register);
|
||||||
var hookAddress = new IntPtr((long)detourPoint.IP);
|
var hookAddress = new IntPtr((long)detourPoint.IP);
|
||||||
|
|
||||||
var caveAllocation = NativeAllocCave(16);
|
var caveAllocation = NativeAllocCave(16);
|
||||||
var hook = new AsmHook(
|
var assembler = new Assembler(64);
|
||||||
hookAddress,
|
assembler.mov(targetRegister, stringAllocation); // Move our char *path into the relevant register (rdx)
|
||||||
[
|
|
||||||
"use64",
|
|
||||||
$"mov {targetRegister}, 0x{stringAllocation:x8}", // Move our char *path into the relevant register (rdx)
|
|
||||||
|
|
||||||
// After this asm stub, we have a call to Crc32(); since r9 is a volatile, unused register, we can use it ourselves
|
// After this asm stub, we have a call to Crc32(); since r9 is a volatile, unused register, we can use it ourselves
|
||||||
// We're essentially storing the original 2 arguments ('this', 'path'), in case they get mangled in our call
|
// We're essentially storing the original 2 arguments ('this', 'path'), in case they get mangled in our call
|
||||||
// We technically don't need to save rdx ('path'), since it'll be stringLoc, but eh
|
// We technically don't need to save rdx ('path'), since it'll be stringLoc, but eh
|
||||||
$"mov r9, 0x{caveAllocation:x8}",
|
assembler.mov(r9, caveAllocation);
|
||||||
"mov [r9], rcx",
|
assembler.mov(__qword_ptr[r9], rcx);
|
||||||
"mov [r9+0x8], rdx",
|
assembler.mov(__qword_ptr[r9 + 8], rdx);
|
||||||
|
|
||||||
// We can use 'rax' here too since it's also volatile, and it'll be overwritten by Crc32()'s return anyway
|
// We can use 'rax' here too since it's also volatile, and it'll be overwritten by Crc32()'s return anyway
|
||||||
$"mov rax, 0x{detourPointer:x8}", // Get a pointer to our detour in place
|
assembler.mov(rax, detourPointer);
|
||||||
"call rax", // Call detour
|
assembler.call(rax);
|
||||||
|
|
||||||
// Do the reverse process and retrieve the stored stuff
|
// Do the reverse process and retrieve the stored stuff
|
||||||
$"mov r9, 0x{caveAllocation:x8}",
|
assembler.mov(r9, caveAllocation);
|
||||||
"mov rcx, [r9]",
|
assembler.mov(rcx, __qword_ptr[r9]);
|
||||||
"mov rdx, [r9+0x8]",
|
assembler.mov(rdx, __qword_ptr[r9 + 8]);
|
||||||
|
|
||||||
// Plop 'rax' (our return value, the path size) into r8, so it's the third argument for the subsequent Crc32() call
|
// Plop 'rax' (our return value, the path size) into r8, so it's the third argument for the subsequent Crc32() call
|
||||||
"mov r8, rax",
|
assembler.mov(r8, rax);
|
||||||
], $"{name}.PapRedirection"
|
var hook = new AsmHook(hookAddress, AssembleToBytes(assembler), $"{name}.PapRedirection");
|
||||||
);
|
|
||||||
|
|
||||||
_hooks.Add(hookAddress, hook);
|
_hooks.Add(hookAddress, hook);
|
||||||
hook.Enable();
|
hook.Enable();
|
||||||
|
|
@ -95,19 +92,45 @@ public sealed class PapRewriter(PeSigScanner sigScanner, PapRewriter.PapResource
|
||||||
if (_hooks.ContainsKey(hookAddress))
|
if (_hooks.ContainsKey(hookAddress))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var targetRegister = stackAccess.Op0Register.ToString().ToLower();
|
var targetRegister = GetRegister64(stackAccess.Op0Register);
|
||||||
var hook = new AsmHook(
|
var assembler = new Assembler(64);
|
||||||
hookAddress,
|
assembler.mov(targetRegister, stringAllocation);
|
||||||
[
|
var hook = new AsmHook(hookAddress, AssembleToBytes(assembler), $"{name}.PapStackAccess[{index}]");
|
||||||
"use64",
|
|
||||||
$"mov {targetRegister}, 0x{stringAllocation:x8}",
|
|
||||||
], $"{name}.PapStackAccess[{index}]"
|
|
||||||
);
|
|
||||||
|
|
||||||
_hooks.Add(hookAddress, hook);
|
_hooks.Add(hookAddress, hook);
|
||||||
hook.Enable();
|
hook.Enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AssemblerRegister64 GetRegister64(Register reg)
|
||||||
|
=> reg switch
|
||||||
|
{
|
||||||
|
Register.RAX => rax,
|
||||||
|
Register.RCX => rcx,
|
||||||
|
Register.RDX => rdx,
|
||||||
|
Register.RBX => rbx,
|
||||||
|
Register.RSP => rsp,
|
||||||
|
Register.RBP => rbp,
|
||||||
|
Register.RSI => rsi,
|
||||||
|
Register.RDI => rdi,
|
||||||
|
Register.R8 => r8,
|
||||||
|
Register.R9 => r9,
|
||||||
|
Register.R10 => r10,
|
||||||
|
Register.R11 => r11,
|
||||||
|
Register.R12 => r12,
|
||||||
|
Register.R13 => r13,
|
||||||
|
Register.R14 => r14,
|
||||||
|
Register.R15 => r15,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(reg), reg, "Unsupported register."),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static byte[] AssembleToBytes(Assembler assembler)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream();
|
||||||
|
var writer = new StreamCodeWriter(stream);
|
||||||
|
assembler.Assemble(writer, 0);
|
||||||
|
return stream.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerable<Instruction> ScanStackAccesses(IEnumerable<Instruction> instructions, Instruction hookPoint)
|
private static IEnumerable<Instruction> ScanStackAccesses(IEnumerable<Instruction> instructions, Instruction hookPoint)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable
|
||||||
/// <remarks> Caching this across frames will cause a crash to desktop. </remarks>
|
/// <remarks> Caching this across frames will cause a crash to desktop. </remarks>
|
||||||
public ImTextureID GetImGuiHandle(Texture* texture, byte sliceIndex)
|
public ImTextureID GetImGuiHandle(Texture* texture, byte sliceIndex)
|
||||||
{
|
{
|
||||||
if (texture == null)
|
if (texture is null)
|
||||||
throw new ArgumentNullException(nameof(texture));
|
throw new ArgumentNullException(nameof(texture));
|
||||||
if (sliceIndex >= texture->ArraySize)
|
if (sliceIndex >= texture->ArraySize)
|
||||||
throw new ArgumentOutOfRangeException(nameof(sliceIndex),
|
throw new ArgumentOutOfRangeException(nameof(sliceIndex),
|
||||||
|
|
@ -74,9 +74,6 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable
|
||||||
{
|
{
|
||||||
ID3D11ShaderResourceView* slicedSrv = null;
|
ID3D11ShaderResourceView* slicedSrv = null;
|
||||||
Marshal.ThrowExceptionForHR(device->CreateShaderResourceView(resource, &description, &slicedSrv));
|
Marshal.ThrowExceptionForHR(device->CreateShaderResourceView(resource, &description, &slicedSrv));
|
||||||
resource->Release();
|
|
||||||
device->Release();
|
|
||||||
|
|
||||||
state = new SliceState(slicedSrv);
|
state = new SliceState(slicedSrv);
|
||||||
_activeSlices.Add(((nint)texture, sliceIndex), state);
|
_activeSlices.Add(((nint)texture, sliceIndex), state);
|
||||||
return new ImTextureID((nint)state.ShaderResourceView);
|
return new ImTextureID((nint)state.ShaderResourceView);
|
||||||
|
|
|
||||||
10
repo.json
10
repo.json
|
|
@ -5,8 +5,8 @@
|
||||||
"Punchline": "Runtime mod loader and manager.",
|
"Punchline": "Runtime mod loader and manager.",
|
||||||
"Description": "Runtime mod loader and manager.",
|
"Description": "Runtime mod loader and manager.",
|
||||||
"InternalName": "Penumbra",
|
"InternalName": "Penumbra",
|
||||||
"AssemblyVersion": "1.5.1.8",
|
"AssemblyVersion": "1.5.1.13",
|
||||||
"TestingAssemblyVersion": "1.5.1.8",
|
"TestingAssemblyVersion": "1.5.1.13",
|
||||||
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
||||||
"ApplicableVersion": "any",
|
"ApplicableVersion": "any",
|
||||||
"DalamudApiLevel": 14,
|
"DalamudApiLevel": 14,
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
"LoadPriority": 69420,
|
"LoadPriority": 69420,
|
||||||
"LoadRequiredState": 2,
|
"LoadRequiredState": 2,
|
||||||
"LoadSync": true,
|
"LoadSync": true,
|
||||||
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.8/Penumbra.zip",
|
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.13/Penumbra.zip",
|
||||||
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.8/Penumbra.zip",
|
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.13/Penumbra.zip",
|
||||||
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.8/Penumbra.zip",
|
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.13/Penumbra.zip",
|
||||||
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue