Add debug display for ResidentResources.

This commit is contained in:
Ottermandias 2022-03-20 16:21:14 +01:00
parent ad55d178d4
commit 98b4b29ff5
8 changed files with 59 additions and 102 deletions

View file

@ -16,9 +16,9 @@ public unsafe class ResidentResourceManager
// A static pointer to the resident resource manager address. // A static pointer to the resident resource manager address.
[Signature( "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05", ScanType = ScanType.StaticAddress )] [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; => *_residentResourceManagerAddress;
public ResidentResourceManager() public ResidentResourceManager()

View file

@ -107,6 +107,9 @@ public unsafe partial class PathResolver
? Penumbra.ModManager.Collections.DefaultCollection ? Penumbra.ModManager.Collections.DefaultCollection
: collection, path ); : 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 )] [MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
private IntPtr ResolveWeaponPathDetour( IntPtr drawObject, IntPtr path ) private IntPtr ResolveWeaponPathDetour( IntPtr drawObject, IntPtr path )
{ {

View file

@ -3,9 +3,9 @@ namespace Penumbra.Interop.Structs;
public enum FileMode : uint public enum FileMode : uint
{ {
LoadUnpackedResource = 0, 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 LoadIndexResource = 0xA, // load index/index2
LoadSqPackResource = 0xB, LoadSqPackResource = 0xB,
} }

View 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;
}

View file

@ -79,8 +79,4 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Collection\" />
</ItemGroup>
</Project> </Project>

View file

@ -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() private unsafe void DrawPathResolverDebug()
{ {
if( !ImGui.CollapsingHeader( "Path Resolver##Debug" ) ) if( !ImGui.CollapsingHeader( "Path Resolver##Debug" ) )
@ -404,6 +434,8 @@ public partial class SettingsInterface
ImGui.NewLine(); ImGui.NewLine();
DrawDebugCharacterUtility(); DrawDebugCharacterUtility();
ImGui.NewLine(); ImGui.NewLine();
DrawDebugResidentResources();
ImGui.NewLine();
DrawDebugTabRedraw(); DrawDebugTabRedraw();
ImGui.NewLine(); ImGui.NewLine();
DrawDebugTabIpc(); DrawDebugTabIpc();

View file

@ -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;
}

View file

@ -12,7 +12,7 @@ public static class TempFile
{ {
var name = Path.GetRandomFileName(); var name = Path.GetRandomFileName();
var path = new FileInfo( Path.Combine( baseDir.FullName, 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 ) if( !path.Exists )
{ {
return path; return path;
@ -21,13 +21,4 @@ public static class TempFile
throw new IOException(); 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;
}
} }