mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Add debug display for ResidentResources.
This commit is contained in:
parent
ad55d178d4
commit
98b4b29ff5
8 changed files with 59 additions and 102 deletions
|
|
@ -16,9 +16,9 @@ public unsafe class ResidentResourceManager
|
|||
|
||||
// A static pointer to the resident resource manager address.
|
||||
[Signature( "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05", ScanType = ScanType.StaticAddress )]
|
||||
private readonly void** _residentResourceManagerAddress = null;
|
||||
private readonly Structs.ResidentResourceManager** _residentResourceManagerAddress = null;
|
||||
|
||||
public void* Address
|
||||
public Structs.ResidentResourceManager* Address
|
||||
=> *_residentResourceManagerAddress;
|
||||
|
||||
public ResidentResourceManager()
|
||||
|
|
|
|||
|
|
@ -107,6 +107,9 @@ public unsafe partial class PathResolver
|
|||
? Penumbra.ModManager.Collections.DefaultCollection
|
||||
: collection, path );
|
||||
|
||||
// Weapons have the characters DrawObject as a parent,
|
||||
// but that may not be set yet when creating a new object, so we have to do the same detour
|
||||
// as for Human DrawObjects that are just being created.
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
|
||||
private IntPtr ResolveWeaponPathDetour( IntPtr drawObject, IntPtr path )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ namespace Penumbra.Interop.Structs;
|
|||
public enum FileMode : uint
|
||||
{
|
||||
LoadUnpackedResource = 0,
|
||||
LoadFileResource = 1, // Shit in My Games uses this
|
||||
LoadFileResource = 1, // The config files in MyGames use this.
|
||||
|
||||
// some shit here, the game does some jump if its < 0xA for other files for some reason but there's no impl, probs debug?
|
||||
// Probably debug options only.
|
||||
LoadIndexResource = 0xA, // load index/index2
|
||||
LoadSqPackResource = 0xB,
|
||||
}
|
||||
19
Penumbra/Interop/Structs/ResidentResourceManager.cs
Normal file
19
Penumbra/Interop/Structs/ResidentResourceManager.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Penumbra.Interop.Structs;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public unsafe struct ResidentResourceManager
|
||||
{
|
||||
[FieldOffset( 0x00 )]
|
||||
public void** VTable;
|
||||
|
||||
[FieldOffset( 0x08 )]
|
||||
public void** ResourceListVTable;
|
||||
|
||||
[FieldOffset( 0x14 )]
|
||||
public uint NumResources;
|
||||
|
||||
[FieldOffset( 0x18 )]
|
||||
public ResourceHandle** ResourceList;
|
||||
}
|
||||
|
|
@ -79,8 +79,4 @@
|
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Collection\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -327,6 +327,36 @@ public partial class SettingsInterface
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public unsafe void DrawDebugResidentResources()
|
||||
{
|
||||
if( !ImGui.CollapsingHeader( "Resident Resources##Debug" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( Penumbra.ResidentResources.Address == null || Penumbra.ResidentResources.Address->NumResources == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( !ImGui.BeginTable( "##Resident ResourcesDebugList", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit, -Vector2.UnitX ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var end = ImGuiRaii.DeferredEnd( ImGui.EndTable );
|
||||
|
||||
for( var i = 0; i < Penumbra.ResidentResources.Address->NumResources; ++i )
|
||||
{
|
||||
var resource = Penumbra.ResidentResources.Address->ResourceList[ i ];
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Text( $"0x{( ulong )resource:X}" );
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiNative.igTextUnformatted( resource->FileName(), resource->FileName() + resource->FileNameLength );
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void DrawPathResolverDebug()
|
||||
{
|
||||
if( !ImGui.CollapsingHeader( "Path Resolver##Debug" ) )
|
||||
|
|
@ -404,6 +434,8 @@ public partial class SettingsInterface
|
|||
ImGui.NewLine();
|
||||
DrawDebugCharacterUtility();
|
||||
ImGui.NewLine();
|
||||
DrawDebugResidentResources();
|
||||
ImGui.NewLine();
|
||||
DrawDebugTabRedraw();
|
||||
ImGui.NewLine();
|
||||
DrawDebugTabIpc();
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Penumbra.GameData.ByteString;
|
||||
using Penumbra.GameData.Util;
|
||||
|
||||
namespace Penumbra.Util;
|
||||
|
||||
public readonly struct RelPath : IComparable
|
||||
{
|
||||
public const int MaxRelPathLength = 256;
|
||||
|
||||
private readonly string _path;
|
||||
|
||||
private RelPath( string path, bool _ )
|
||||
=> _path = path;
|
||||
|
||||
private RelPath( string? path )
|
||||
{
|
||||
if( path != null && path.Length < MaxRelPathLength )
|
||||
{
|
||||
_path = Trim( ReplaceSlash( path ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
_path = "";
|
||||
}
|
||||
}
|
||||
|
||||
public RelPath( FullPath file, DirectoryInfo baseDir )
|
||||
=> _path = CheckPre( file.FullName, baseDir ) ? ReplaceSlash( Trim( Substring( file.FullName, baseDir ) ) ) : string.Empty;
|
||||
|
||||
public RelPath( FileInfo file, DirectoryInfo baseDir )
|
||||
=> _path = CheckPre( file.FullName, baseDir ) ? Trim( Substring( file.FullName, baseDir ) ) : string.Empty;
|
||||
|
||||
public RelPath( GamePath gamePath )
|
||||
=> _path = ReplaceSlash( gamePath );
|
||||
|
||||
public GamePath ToGamePath( int skipFolders = 0 )
|
||||
{
|
||||
string p = this;
|
||||
if( skipFolders > 0 )
|
||||
{
|
||||
p = string.Join( "/", p.Split( '\\' ).Skip( skipFolders ) );
|
||||
return GamePath.GenerateUncheckedLower( p );
|
||||
}
|
||||
|
||||
return GamePath.GenerateUncheckedLower( p.Replace( '\\', '/' ) );
|
||||
}
|
||||
|
||||
private static bool CheckPre( string file, DirectoryInfo baseDir )
|
||||
=> file.StartsWith( baseDir.FullName ) && file.Length < MaxRelPathLength;
|
||||
|
||||
private static string Substring( string file, DirectoryInfo baseDir )
|
||||
=> file.Substring( baseDir.FullName.Length );
|
||||
|
||||
private static string ReplaceSlash( string path )
|
||||
=> path.Replace( '/', '\\' );
|
||||
|
||||
private static string Trim( string path )
|
||||
=> path.TrimStart( '\\' );
|
||||
|
||||
public static implicit operator string( RelPath relPath )
|
||||
=> relPath._path;
|
||||
|
||||
public static explicit operator RelPath( string relPath )
|
||||
=> new(relPath);
|
||||
|
||||
public bool Empty
|
||||
=> _path.Length == 0;
|
||||
|
||||
public int CompareTo( object? rhs )
|
||||
{
|
||||
return rhs switch
|
||||
{
|
||||
string path => string.Compare( _path, path, StringComparison.InvariantCulture ),
|
||||
RelPath path => string.Compare( _path, path._path, StringComparison.InvariantCulture ),
|
||||
_ => -1,
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> _path;
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ public static class TempFile
|
|||
{
|
||||
var name = Path.GetRandomFileName();
|
||||
var path = new FileInfo( Path.Combine( baseDir.FullName,
|
||||
suffix.Any() ? name.Substring( 0, name.LastIndexOf( '.' ) ) + suffix : name ) );
|
||||
suffix.Length > 0 ? name[ ..name.LastIndexOf( '.' ) ] + suffix : name ) );
|
||||
if( !path.Exists )
|
||||
{
|
||||
return path;
|
||||
|
|
@ -21,13 +21,4 @@ public static class TempFile
|
|||
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
public static FileInfo WriteNew( DirectoryInfo baseDir, byte[] data, string suffix = "" )
|
||||
{
|
||||
var fileName = TempFileName( baseDir, suffix );
|
||||
using var stream = fileName.OpenWrite();
|
||||
stream.Write( data, 0, data.Length );
|
||||
fileName.Refresh();
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue