Compare commits

..

24 Commits
2.0.3 ... dev

Author SHA1 Message Date
defnotken
abc324bf4f bumpers
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m23s
2026-01-19 19:48:39 -06:00
defnotken
eee0e072bd Merge branch '2.0.3' into dev 2026-01-19 19:48:28 -06:00
defnotken
172288c755 bumpers
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 1m57s
2026-01-19 18:31:36 -06:00
defnotken
1c17be53d0 Merge branch '2.0.3' into dev 2026-01-19 18:30:42 -06:00
defnotken
e8f598e695 bumpity bump
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m7s
2026-01-19 12:36:24 -06:00
defnotken
861a337029 Merge branch '2.0.3' into dev
Some checks failed
Tag and Release Lightless / tag-and-release (push) Has been cancelled
2026-01-19 12:35:29 -06:00
defnotken
c7a2b679f2 bumpity bump
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m2s
2026-01-19 11:23:49 -06:00
defnotken
bec69074a5 Merge branch '2.0.3' into dev 2026-01-19 11:23:23 -06:00
defnotken
ac711d9a43 Bump plugin testing
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m19s
2026-01-18 20:53:14 -06:00
defnotken
b875e0c3a1 Merge branch '2.0.3' into dev 2026-01-18 20:51:58 -06:00
defnotken
46e76bbfe6 Merge branch '2.0.3' into dev 2026-01-18 20:29:53 -06:00
cake
3654365f2a bump version
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m6s
2026-01-06 14:45:23 +01:00
cake
9b256dd185 Merge branch '2.0.3' into dev 2026-01-06 14:45:02 +01:00
defnotken
223ade39cb another push
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m13s
2026-01-05 20:48:24 -06:00
defnotken
5aca9e70b2 Merge branch '2.0.3' into dev 2026-01-05 20:47:38 -06:00
defnotken
92772cf334 dev push
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m12s
2026-01-05 20:21:26 -06:00
defnotken
0395e81a9f Merge branch '2.0.3' into dev 2026-01-05 20:17:12 -06:00
defnotken
7734a7bf7e dev build
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m8s
2026-01-05 17:42:21 -06:00
defnotken
db2d19bb1e Merge branch '2.0.3' into dev 2026-01-05 17:41:48 -06:00
defnotken
ab305a249c more checks
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m7s
2026-01-05 15:48:54 -06:00
defnotken
9d104a9dd8 Merge branch '2.0.3' into dev 2026-01-05 15:42:15 -06:00
defnotken
bcd3bd5ca2 add more checks
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m8s
2026-01-05 15:08:26 -06:00
defnotken
c1829a9837 Merge branch '2.0.3' into dev
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m14s
2026-01-05 14:48:47 -06:00
defnotken
cca23f6e05 Building Dev
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m27s
2026-01-05 10:50:25 -06:00
12 changed files with 23 additions and 260 deletions

View File

@@ -92,7 +92,7 @@ public sealed class PenumbraTexture : PenumbraBase
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
logger.LogDebug("Converting texture {Input} -> {Output} ({Target})", job.InputFile, job.OutputFile, job.TargetType); logger.LogInformation("Converting texture {Input} -> {Output} ({Target})", job.InputFile, job.OutputFile, job.TargetType);
var convertTask = _convertTextureFile.Invoke(job.InputFile, job.OutputFile, job.TargetType, job.IncludeMipMaps); var convertTask = _convertTextureFile.Invoke(job.InputFile, job.OutputFile, job.TargetType, job.IncludeMipMaps);
await convertTask.ConfigureAwait(false); await convertTask.ConfigureAwait(false);

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Authors></Authors> <Authors></Authors>
<Company></Company> <Company></Company>
<Version>2.0.3</Version> <Version>2.0.2.82</Version>
<Description></Description> <Description></Description>
<Copyright></Copyright> <Copyright></Copyright>
<PackageProjectUrl>https://github.com/Light-Public-Syncshells/LightlessClient</PackageProjectUrl> <PackageProjectUrl>https://github.com/Light-Public-Syncshells/LightlessClient</PackageProjectUrl>

View File

@@ -125,8 +125,6 @@ public sealed class Plugin : IDalamudPlugin
services.AddSingleton<FileTransferOrchestrator>(); services.AddSingleton<FileTransferOrchestrator>();
services.AddSingleton<LightlessPlugin>(); services.AddSingleton<LightlessPlugin>();
services.AddSingleton<LightlessProfileManager>(); services.AddSingleton<LightlessProfileManager>();
services.AddSingleton<TextureProcessingQueue>();
services.AddSingleton<ModelProcessingQueue>();
services.AddSingleton<TextureCompressionService>(); services.AddSingleton<TextureCompressionService>();
services.AddSingleton<TextureDownscaleService>(); services.AddSingleton<TextureDownscaleService>();
services.AddSingleton<ModelDecimationService>(); services.AddSingleton<ModelDecimationService>();

View File

@@ -1,93 +0,0 @@
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
namespace LightlessSync.Services;
public sealed class AssetProcessingQueue : IDisposable
{
private readonly BlockingCollection<WorkItem> _queue = new();
private readonly Thread _worker;
private readonly ILogger _logger;
private bool _disposed;
public AssetProcessingQueue(ILogger logger, string name)
{
_logger = logger;
_worker = new Thread(Run)
{
IsBackground = true,
Name = string.IsNullOrWhiteSpace(name) ? "LightlessSync.AssetProcessing" : name
};
_worker.Start();
}
public Task Enqueue(Func<CancellationToken, Task> work, CancellationToken token = default)
{
if (work is null)
{
throw new ArgumentNullException(nameof(work));
}
var completion = new TaskCompletionSource<object?>(TaskCreationOptions.RunContinuationsAsynchronously);
if (token.IsCancellationRequested)
{
completion.TrySetCanceled(token);
return completion.Task;
}
if (_queue.IsAddingCompleted || _disposed)
{
completion.TrySetException(new ObjectDisposedException(nameof(AssetProcessingQueue)));
return completion.Task;
}
_queue.Add(new WorkItem(work, token, completion));
return completion.Task;
}
private void Run()
{
foreach (var item in _queue.GetConsumingEnumerable())
{
if (item.Token.IsCancellationRequested)
{
item.Completion.TrySetCanceled(item.Token);
continue;
}
try
{
item.Work(item.Token).GetAwaiter().GetResult();
item.Completion.TrySetResult(null);
}
catch (OperationCanceledException ex)
{
var token = ex.CancellationToken.IsCancellationRequested ? ex.CancellationToken : item.Token;
item.Completion.TrySetCanceled(token);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Asset processing job failed.");
item.Completion.TrySetException(ex);
}
}
}
public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
_queue.CompleteAdding();
_worker.Join(TimeSpan.FromSeconds(2));
_queue.Dispose();
}
private readonly record struct WorkItem(
Func<CancellationToken, Task> Work,
CancellationToken Token,
TaskCompletionSource<object?> Completion);
}

View File

@@ -2104,16 +2104,6 @@ internal static class MdlDecimator
} }
} }
if (boneWeights != null
&& blendWeightEncoding == BlendWeightEncoding.Default
&& format.BlendWeightsElement is { } blendWeightsElement
&& (MdlFile.VertexType)blendWeightsElement.Type == MdlFile.VertexType.UShort4
&& ShouldTreatWeightsAsByteNormalized(boneWeights))
{
RescaleUShortAsByteWeights(boneWeights);
blendWeightEncoding = BlendWeightEncoding.UShortAsByte;
}
decoded = new DecodedMeshData(positions, normals, tangents, tangents2, colors, boneWeights, uvChannels, positionWs, normalWs, blendWeightEncoding); decoded = new DecodedMeshData(positions, normals, tangents, tangents2, colors, boneWeights, uvChannels, positionWs, normalWs, blendWeightEncoding);
return true; return true;
} }
@@ -3423,44 +3413,6 @@ internal static class MdlDecimator
return ToUShortNormalized(normalized); return ToUShortNormalized(normalized);
} }
private static bool ShouldTreatWeightsAsByteNormalized(BoneWeight[] weights)
{
const float maxByteUnorm = byte.MaxValue / (float)ushort.MaxValue;
var maxWeight = 0f;
for (var i = 0; i < weights.Length; i++)
{
var weight = weights[i];
maxWeight = Math.Max(maxWeight, weight.weight0);
maxWeight = Math.Max(maxWeight, weight.weight1);
maxWeight = Math.Max(maxWeight, weight.weight2);
maxWeight = Math.Max(maxWeight, weight.weight3);
if (maxWeight > maxByteUnorm)
{
return false;
}
}
return maxWeight > 0f;
}
private static void RescaleUShortAsByteWeights(BoneWeight[] weights)
{
var scale = ushort.MaxValue / (float)byte.MaxValue;
for (var i = 0; i < weights.Length; i++)
{
var weight = weights[i];
weights[i] = new BoneWeight(
weight.index0,
weight.index1,
weight.index2,
weight.index3,
weight.weight0 * scale,
weight.weight1 * scale,
weight.weight2 * scale,
weight.weight3 * scale);
}
}
private static void NormalizeWeights(float[] weights) private static void NormalizeWeights(float[] weights)
{ {
var sum = weights.Sum(); var sum = weights.Sum();

View File

@@ -1,7 +1,6 @@
using LightlessSync.FileCache; using LightlessSync.FileCache;
using LightlessSync.LightlessConfiguration; using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations; using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.Services;
using LightlessSync.Utils; using LightlessSync.Utils;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@@ -20,7 +19,6 @@ public sealed class ModelDecimationService
private readonly FileCacheManager _fileCacheManager; private readonly FileCacheManager _fileCacheManager;
private readonly PlayerPerformanceConfigService _performanceConfigService; private readonly PlayerPerformanceConfigService _performanceConfigService;
private readonly XivDataStorageService _xivDataStorageService; private readonly XivDataStorageService _xivDataStorageService;
private readonly ModelProcessingQueue _processingQueue;
private readonly SemaphoreSlim _decimationSemaphore = new(MaxConcurrentJobs); private readonly SemaphoreSlim _decimationSemaphore = new(MaxConcurrentJobs);
private readonly TaskRegistry<string> _decimationDeduplicator = new(); private readonly TaskRegistry<string> _decimationDeduplicator = new();
@@ -32,15 +30,13 @@ public sealed class ModelDecimationService
LightlessConfigService configService, LightlessConfigService configService,
FileCacheManager fileCacheManager, FileCacheManager fileCacheManager,
PlayerPerformanceConfigService performanceConfigService, PlayerPerformanceConfigService performanceConfigService,
XivDataStorageService xivDataStorageService, XivDataStorageService xivDataStorageService)
ModelProcessingQueue processingQueue)
{ {
_logger = logger; _logger = logger;
_configService = configService; _configService = configService;
_fileCacheManager = fileCacheManager; _fileCacheManager = fileCacheManager;
_performanceConfigService = performanceConfigService; _performanceConfigService = performanceConfigService;
_xivDataStorageService = xivDataStorageService; _xivDataStorageService = xivDataStorageService;
_processingQueue = processingQueue;
} }
public void ScheduleDecimation(string hash, string filePath, string? gamePath = null) public void ScheduleDecimation(string hash, string filePath, string? gamePath = null)
@@ -57,9 +53,9 @@ public sealed class ModelDecimationService
_logger.LogDebug("Queued model decimation for {Hash}", hash); _logger.LogDebug("Queued model decimation for {Hash}", hash);
_decimationDeduplicator.GetOrStart(hash, () => _processingQueue.Enqueue(async token => _decimationDeduplicator.GetOrStart(hash, async () =>
{ {
await _decimationSemaphore.WaitAsync(token).ConfigureAwait(false); await _decimationSemaphore.WaitAsync().ConfigureAwait(false);
try try
{ {
await DecimateInternalAsync(hash, filePath).ConfigureAwait(false); await DecimateInternalAsync(hash, filePath).ConfigureAwait(false);
@@ -73,7 +69,7 @@ public sealed class ModelDecimationService
{ {
_decimationSemaphore.Release(); _decimationSemaphore.Release();
} }
}, CancellationToken.None)); });
} }
public void ScheduleBatchDecimation(string hash, string filePath, ModelDecimationSettings settings) public void ScheduleBatchDecimation(string hash, string filePath, ModelDecimationSettings settings)
@@ -93,9 +89,9 @@ public sealed class ModelDecimationService
_logger.LogInformation("Queued batch model decimation for {Hash}", hash); _logger.LogInformation("Queued batch model decimation for {Hash}", hash);
_decimationDeduplicator.GetOrStart(hash, () => _processingQueue.Enqueue(async token => _decimationDeduplicator.GetOrStart(hash, async () =>
{ {
await _decimationSemaphore.WaitAsync(token).ConfigureAwait(false); await _decimationSemaphore.WaitAsync().ConfigureAwait(false);
try try
{ {
await DecimateInternalAsync(hash, filePath, settings, allowExisting: false, destinationOverride: filePath, registerDecimatedPath: false).ConfigureAwait(false); await DecimateInternalAsync(hash, filePath, settings, allowExisting: false, destinationOverride: filePath, registerDecimatedPath: false).ConfigureAwait(false);
@@ -109,7 +105,7 @@ public sealed class ModelDecimationService
{ {
_decimationSemaphore.Release(); _decimationSemaphore.Release();
} }
}, CancellationToken.None)); });
} }
public bool ShouldScheduleDecimation(string hash, string filePath, string? gamePath = null) public bool ShouldScheduleDecimation(string hash, string filePath, string? gamePath = null)

View File

@@ -1,19 +0,0 @@
using Microsoft.Extensions.Logging;
namespace LightlessSync.Services;
public sealed class ModelProcessingQueue : IDisposable
{
private readonly AssetProcessingQueue _queue;
public ModelProcessingQueue(ILogger<ModelProcessingQueue> logger)
{
_queue = new AssetProcessingQueue(logger, "LightlessSync.ModelProcessing");
}
public Task Enqueue(Func<CancellationToken, Task> work, CancellationToken token = default)
=> _queue.Enqueue(work, token);
public void Dispose()
=> _queue.Dispose();
}

View File

@@ -8,7 +8,6 @@ using System.Threading;
using OtterTex; using OtterTex;
using OtterImage = OtterTex.Image; using OtterImage = OtterTex.Image;
using LightlessSync.LightlessConfiguration; using LightlessSync.LightlessConfiguration;
using LightlessSync.Services;
using LightlessSync.Utils; using LightlessSync.Utils;
using LightlessSync.FileCache; using LightlessSync.FileCache;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -34,7 +33,6 @@ public sealed class TextureDownscaleService
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService; private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
private readonly FileCacheManager _fileCacheManager; private readonly FileCacheManager _fileCacheManager;
private readonly TextureCompressionService _textureCompressionService; private readonly TextureCompressionService _textureCompressionService;
private readonly TextureProcessingQueue _processingQueue;
private readonly TaskRegistry<string> _downscaleDeduplicator = new(); private readonly TaskRegistry<string> _downscaleDeduplicator = new();
private readonly ConcurrentDictionary<string, string> _downscaledPaths = new(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, string> _downscaledPaths = new(StringComparer.OrdinalIgnoreCase);
@@ -75,15 +73,13 @@ public sealed class TextureDownscaleService
LightlessConfigService configService, LightlessConfigService configService,
PlayerPerformanceConfigService playerPerformanceConfigService, PlayerPerformanceConfigService playerPerformanceConfigService,
FileCacheManager fileCacheManager, FileCacheManager fileCacheManager,
TextureCompressionService textureCompressionService, TextureCompressionService textureCompressionService)
TextureProcessingQueue processingQueue)
{ {
_logger = logger; _logger = logger;
_configService = configService; _configService = configService;
_playerPerformanceConfigService = playerPerformanceConfigService; _playerPerformanceConfigService = playerPerformanceConfigService;
_fileCacheManager = fileCacheManager; _fileCacheManager = fileCacheManager;
_textureCompressionService = textureCompressionService; _textureCompressionService = textureCompressionService;
_processingQueue = processingQueue;
} }
public void ScheduleDownscale(string hash, string filePath, TextureMapKind mapKind) public void ScheduleDownscale(string hash, string filePath, TextureMapKind mapKind)
@@ -94,7 +90,7 @@ public sealed class TextureDownscaleService
if (!filePath.EndsWith(".tex", StringComparison.OrdinalIgnoreCase)) return; if (!filePath.EndsWith(".tex", StringComparison.OrdinalIgnoreCase)) return;
if (_downscaleDeduplicator.TryGetExisting(hash, out _)) return; if (_downscaleDeduplicator.TryGetExisting(hash, out _)) return;
_downscaleDeduplicator.GetOrStart(hash, () => _processingQueue.Enqueue(async token => _downscaleDeduplicator.GetOrStart(hash, async () =>
{ {
TextureMapKind mapKind; TextureMapKind mapKind;
try try
@@ -108,7 +104,7 @@ public sealed class TextureDownscaleService
} }
await DownscaleInternalAsync(hash, filePath, mapKind).ConfigureAwait(false); await DownscaleInternalAsync(hash, filePath, mapKind).ConfigureAwait(false);
}, CancellationToken.None)); });
} }
public bool ShouldScheduleDownscale(string filePath) public bool ShouldScheduleDownscale(string filePath)
@@ -386,12 +382,6 @@ public sealed class TextureDownscaleService
{ {
var isCompressed = sourceFormat.IsCompressed(); var isCompressed = sourceFormat.IsCompressed();
var targetFormat = isCompressed ? sourceFormat : DXGIFormat.B8G8R8A8UNorm; var targetFormat = isCompressed ? sourceFormat : DXGIFormat.B8G8R8A8UNorm;
_logger.LogDebug(
"Downscale convert target {TargetFormat} (source {SourceFormat}, compressed {IsCompressed}, penumbraFallback {PenumbraFallback})",
targetFormat,
sourceFormat,
isCompressed,
attemptPenumbraFallback);
try try
{ {
result = source.Convert(targetFormat); result = source.Convert(targetFormat);
@@ -443,7 +433,6 @@ public sealed class TextureDownscaleService
{ {
try try
{ {
_logger.LogDebug("Downscale Penumbra re-encode target {Target} for {Hash}.", target, hash);
using var uncompressed = resizedScratch.Convert(DXGIFormat.B8G8R8A8UNorm); using var uncompressed = resizedScratch.Convert(DXGIFormat.B8G8R8A8UNorm);
TexFileHelper.Save(destination, uncompressed); TexFileHelper.Save(destination, uncompressed);
} }

View File

@@ -1,19 +0,0 @@
using Microsoft.Extensions.Logging;
namespace LightlessSync.Services;
public sealed class TextureProcessingQueue : IDisposable
{
private readonly AssetProcessingQueue _queue;
public TextureProcessingQueue(ILogger<TextureProcessingQueue> logger)
{
_queue = new AssetProcessingQueue(logger, "LightlessSync.TextureProcessing");
}
public Task Enqueue(Func<CancellationToken, Task> work, CancellationToken token = default)
=> _queue.Enqueue(work, token);
public void Dispose()
=> _queue.Dispose();
}

View File

@@ -56,7 +56,6 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
private readonly ModelDecimationService _modelDecimationService; private readonly ModelDecimationService _modelDecimationService;
private readonly TextureCompressionService _textureCompressionService; private readonly TextureCompressionService _textureCompressionService;
private readonly TextureMetadataHelper _textureMetadataHelper; private readonly TextureMetadataHelper _textureMetadataHelper;
private readonly TextureProcessingQueue _processingQueue;
private readonly List<TextureRow> _textureRows = new(); private readonly List<TextureRow> _textureRows = new();
private readonly Dictionary<string, TextureCompressionTarget> _textureSelections = new(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, TextureCompressionTarget> _textureSelections = new(StringComparer.OrdinalIgnoreCase);
@@ -138,8 +137,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
LightlessConfigService configService, LightlessConfigService configService,
PlayerPerformanceConfigService playerPerformanceConfig, TransientResourceManager transientResourceManager, PlayerPerformanceConfigService playerPerformanceConfig, TransientResourceManager transientResourceManager,
TransientConfigService transientConfigService, ModelDecimationService modelDecimationService, TransientConfigService transientConfigService, ModelDecimationService modelDecimationService,
TextureCompressionService textureCompressionService, TextureMetadataHelper textureMetadataHelper, TextureCompressionService textureCompressionService, TextureMetadataHelper textureMetadataHelper)
TextureProcessingQueue processingQueue)
: base(logger, mediator, "Lightless Character Data Analysis", performanceCollectorService) : base(logger, mediator, "Lightless Character Data Analysis", performanceCollectorService)
{ {
_characterAnalyzer = characterAnalyzer; _characterAnalyzer = characterAnalyzer;
@@ -152,7 +150,6 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
_modelDecimationService = modelDecimationService; _modelDecimationService = modelDecimationService;
_textureCompressionService = textureCompressionService; _textureCompressionService = textureCompressionService;
_textureMetadataHelper = textureMetadataHelper; _textureMetadataHelper = textureMetadataHelper;
_processingQueue = processingQueue;
Mediator.Subscribe<CharacterDataAnalyzedMessage>(this, (_) => Mediator.Subscribe<CharacterDataAnalyzedMessage>(this, (_) =>
{ {
_hasUpdate = true; _hasUpdate = true;
@@ -3719,10 +3716,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
_conversionCurrentFileProgress = 0; _conversionCurrentFileProgress = 0;
_conversionFailed = false; _conversionFailed = false;
var conversionToken = _conversionCancellationTokenSource.Token; _conversionTask = RunTextureConversionAsync(requests, _conversionCancellationTokenSource.Token);
_conversionTask = _processingQueue.Enqueue(
queueToken => RunTextureConversionAsync(requests, queueToken),
conversionToken);
_showModal = true; _showModal = true;
} }

View File

@@ -5,35 +5,19 @@ namespace LightlessSync.Utils
{ {
public static partial class PtrGuard public static partial class PtrGuard
{ {
private const ulong _minLikelyPtr = 0x0000_0001_0000_0000UL;
private const ulong _maxUserPtr = 0x0000_7FFF_FFFF_FFFFUL;
private const ulong _aligmentPtr = 0x7UL; private const ulong _aligmentPtr = 0x7UL;
private static readonly nuint _minAppAddr = (nuint)GetMinAppAddr();
private static readonly nuint _maxAppAddr = (nuint)GetMaxAppAddr();
private static nint GetMinAppAddr() public static bool LooksLikePtr(nint p)
{ {
GetSystemInfo(out var si); if (p == 0) return false;
return si.lpMinimumApplicationAddress; var u = (ulong)p;
if (u < _minLikelyPtr) return false;
if (u > _maxUserPtr) return false;
if ((u & _aligmentPtr) != 0) return false;
return true;
} }
private static nint GetMaxAppAddr()
{
GetSystemInfo(out var si);
return si.lpMaximumApplicationAddress;
}
public static bool LooksLikePtr(nint p)
{
if (p == 0) return false;
nuint u = (nuint)p;
if (u < _minAppAddr) return false;
if (u > _maxAppAddr) return false;
if ((u & _aligmentPtr) != 0) return false;
if ((uint)u == 0x12345679u) return false;
return true;
}
public static bool TryReadIntPtr(nint addr, out nint value) public static bool TryReadIntPtr(nint addr, out nint value)
{ {
value = 0; value = 0;

View File

@@ -32,24 +32,5 @@ namespace LightlessSync.Utils
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
internal static extern nint GetCurrentProcess(); internal static extern nint GetCurrentProcess();
[DllImport("kernel32.dll")]
internal static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEM_INFO
{
public ushort wProcessorArchitecture;
public ushort wReserved;
public uint dwPageSize;
public nint lpMinimumApplicationAddress;
public nint lpMaximumApplicationAddress;
public nint dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public ushort wProcessorLevel;
public ushort wProcessorRevision;
}
} }
} }