mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-16 20:17:30 +08:00
Performance optimalizations and refactoring
This commit is contained in:
parent
ee975e7257
commit
aed7a1e051
1
.gitignore
vendored
1
.gitignore
vendored
@ -241,3 +241,4 @@ ModelManifest.xml
|
|||||||
# FAKE - F# Make
|
# FAKE - F# Make
|
||||||
.fake/
|
.fake/
|
||||||
/Toolbar/cammodes.psd
|
/Toolbar/cammodes.psd
|
||||||
|
Shaders
|
@ -1,12 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="directxtex_desktop_win10" Version="2023.3.30.1" />
|
||||||
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||||
<PackageReference Include="SharpDX" Version="4.2.0" />
|
<PackageReference Include="SharpDX" Version="4.2.0" />
|
||||||
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
|
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
|
||||||
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1917,7 +1917,7 @@ namespace CodeWalker.GameFiles
|
|||||||
Buffer.BlockCopy(data, 16, newdata, 0, newlen);
|
Buffer.BlockCopy(data, 16, newdata, 0, newlen);
|
||||||
data = newdata;
|
data = newdata;
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
ClipDict = rd.ReadBlock<ClipDictionary>();
|
ClipDict = rd.ReadBlock<ClipDictionary>();
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -171,70 +172,45 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static class GlobalText
|
public static class GlobalText
|
||||||
{
|
{
|
||||||
public static Dictionary<uint, string> Index = new Dictionary<uint, string>();
|
public static ConcurrentDictionary<uint, string> Index = new ();
|
||||||
private static object syncRoot = new object();
|
private static object syncRoot = new object();
|
||||||
|
|
||||||
public static volatile bool FullIndexBuilt = false;
|
public static volatile bool FullIndexBuilt = false;
|
||||||
|
|
||||||
public static void Clear()
|
public static void Clear()
|
||||||
{
|
|
||||||
lock (syncRoot)
|
|
||||||
{
|
{
|
||||||
Index.Clear();
|
Index.Clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Ensure(string str)
|
public static bool Ensure(string str)
|
||||||
{
|
{
|
||||||
uint hash = JenkHash.GenHash(str);
|
uint hash = JenkHash.GenHash(str);
|
||||||
if (hash == 0) return true;
|
if (hash == 0) return true;
|
||||||
lock (syncRoot)
|
return !Index.TryAdd(hash, str);
|
||||||
{
|
|
||||||
if (!Index.ContainsKey(hash))
|
|
||||||
{
|
|
||||||
Index.Add(hash, str);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Ensure(string str, uint hash)
|
public static bool Ensure(string str, uint hash)
|
||||||
{
|
{
|
||||||
if (hash == 0) return true;
|
if (hash == 0) return true;
|
||||||
lock (syncRoot)
|
return !Index.TryAdd(hash, str);
|
||||||
{
|
|
||||||
if (!Index.ContainsKey(hash))
|
|
||||||
{
|
|
||||||
Index.Add(hash, str);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetString(uint hash)
|
public static string GetString(uint hash)
|
||||||
{
|
{
|
||||||
string res;
|
string res;
|
||||||
lock (syncRoot)
|
|
||||||
{
|
|
||||||
if (!Index.TryGetValue(hash, out res))
|
if (!Index.TryGetValue(hash, out res))
|
||||||
{
|
{
|
||||||
res = hash.ToString();
|
res = hash.ToString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
public static string TryGetString(uint hash)
|
public static string TryGetString(uint hash)
|
||||||
{
|
{
|
||||||
string res;
|
string res;
|
||||||
lock (syncRoot)
|
|
||||||
{
|
|
||||||
if (!Index.TryGetValue(hash, out res))
|
if (!Index.TryGetValue(hash, out res))
|
||||||
{
|
{
|
||||||
res = string.Empty;
|
res = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
Meta = rd.ReadBlock<Meta>();
|
Meta = rd.ReadBlock<Meta>();
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
|
|
||||||
Bounds = rd.ReadBlock<Bounds>();
|
Bounds = rd.ReadBlock<Bounds>();
|
||||||
|
@ -44,20 +44,20 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rd = new ResourceDataReader(resentry, data);
|
using ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
|
ClipDictionary = rd?.ReadBlock<ClipDictionary>();
|
||||||
|
|
||||||
|
InitDictionaries();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
//data = entry.File.DecompressBytes(data); //??
|
//data = entry.File.DecompressBytes(data); //??
|
||||||
LoadException = ex.ToString();
|
LoadException = ex.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipDictionary = rd?.ReadBlock<ClipDictionary>();
|
|
||||||
|
|
||||||
InitDictionaries();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitDictionaries()
|
public void InitDictionaries()
|
||||||
|
@ -43,7 +43,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
DrawableDict = rd.ReadBlock<DrawableDictionary>();
|
DrawableDict = rd.ReadBlock<DrawableDictionary>();
|
||||||
|
|
||||||
@ -74,6 +74,7 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
var drawable = drawables[i];
|
var drawable = drawables[i];
|
||||||
var hash = hashes[i];
|
var hash = hashes[i];
|
||||||
|
drawable.Hash = hash;
|
||||||
if ((drawable.Name == null) || (drawable.Name.EndsWith("#dd")))
|
if ((drawable.Name == null) || (drawable.Name.EndsWith("#dd")))
|
||||||
{
|
{
|
||||||
string hstr = JenkIndex.TryGetString(hash);
|
string hstr = JenkIndex.TryGetString(hash);
|
||||||
@ -101,6 +102,12 @@ namespace CodeWalker.GameFiles
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new public long MemoryUsage {
|
||||||
|
get {
|
||||||
|
return DrawableDict.MemoryUsage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
//MemoryUsage = 0;
|
//MemoryUsage = 0;
|
||||||
|
|
||||||
@ -58,6 +58,11 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Unload()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] Save()
|
public byte[] Save()
|
||||||
{
|
{
|
||||||
byte[] data = ResourceBuilder.Build(Drawable, 165); //ydr is type/version 165...
|
byte[] data = ResourceBuilder.Build(Drawable, 165); //ydr is type/version 165...
|
||||||
@ -65,7 +70,13 @@ namespace CodeWalker.GameFiles
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new public long MemoryUsage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Drawable.MemoryUsage;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,21 +41,20 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
|
ExpressionDictionary = rd?.ReadBlock<ExpressionDictionary>();
|
||||||
|
|
||||||
|
|
||||||
|
InitDictionaries();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
//data = entry.File.DecompressBytes(data); //??
|
//data = entry.File.DecompressBytes(data); //??
|
||||||
LoadException = ex.ToString();
|
LoadException = ex.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionDictionary = rd?.ReadBlock<ExpressionDictionary>();
|
|
||||||
|
|
||||||
|
|
||||||
InitDictionaries();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Save()
|
public byte[] Save()
|
||||||
|
@ -36,19 +36,17 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
|
FrameFilterDictionary = rd.ReadBlock<FrameFilterDictionary>();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
//data = entry.File.DecompressBytes(data); //??
|
|
||||||
LoadException = ex.ToString();
|
LoadException = ex.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameFilterDictionary = rd?.ReadBlock<FrameFilterDictionary>();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Save()
|
public byte[] Save()
|
||||||
|
@ -40,7 +40,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
Fragment = rd.ReadBlock<FragType>();
|
Fragment = rd.ReadBlock<FragType>();
|
||||||
|
|
||||||
|
@ -40,20 +40,13 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
//data = entry.File.DecompressBytes(data); //??
|
|
||||||
LoadException = ex.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
ClothDictionary = rd?.ReadBlock<ClothDictionary>();
|
ClothDictionary = rd?.ReadBlock<ClothDictionary>();
|
||||||
|
|
||||||
|
|
||||||
if (ClothDictionary != null)
|
if (ClothDictionary != null)
|
||||||
{
|
{
|
||||||
Dict = new Dictionary<uint, CharacterCloth>();
|
Dict = new Dictionary<uint, CharacterCloth>();
|
||||||
@ -71,6 +64,12 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
Loaded = true;
|
Loaded = true;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//data = entry.File.DecompressBytes(data); //??
|
||||||
|
LoadException = ex.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] Save()
|
public byte[] Save()
|
||||||
{
|
{
|
||||||
|
@ -96,7 +96,7 @@ namespace CodeWalker.GameFiles
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
Meta = rd.ReadBlock<Meta>();//maybe null this after load to reduce memory consumption?
|
Meta = rd.ReadBlock<Meta>();//maybe null this after load to reduce memory consumption?
|
||||||
|
|
||||||
@ -1336,15 +1336,11 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
var newnamel = newname.ToLowerInvariant();
|
var newnamel = newname.ToLowerInvariant();
|
||||||
var newnamex = newname + ".ymap";
|
var newnamex = newname + ".ymap";
|
||||||
var newnamexl = newname.ToLowerInvariant();
|
|
||||||
var newhash = JenkHash.GenHash(newnamel);
|
var newhash = JenkHash.GenHash(newnamel);
|
||||||
JenkIndex.Ensure(newnamel);
|
JenkIndex.Ensure(newnamel);
|
||||||
if (RpfFileEntry != null)
|
if (RpfFileEntry != null)
|
||||||
{
|
{
|
||||||
RpfFileEntry.Name = newnamex;
|
RpfFileEntry.Name = newnamex;
|
||||||
RpfFileEntry.NameLower = newnamexl;
|
|
||||||
RpfFileEntry.NameHash = JenkHash.GenHash(newnamexl);
|
|
||||||
RpfFileEntry.ShortNameHash = newhash;
|
|
||||||
}
|
}
|
||||||
Name = newnamex;
|
Name = newnamex;
|
||||||
_CMapData.name = newhash;
|
_CMapData.name = newhash;
|
||||||
@ -3034,6 +3030,8 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public bool Enabled { get; set; } = true;
|
public bool Enabled { get; set; } = true;
|
||||||
|
|
||||||
|
public bool Visible { get; set; } = true;
|
||||||
|
|
||||||
public void Init(YmapLODLights l, YmapDistantLODLights p, int i)
|
public void Init(YmapLODLights l, YmapDistantLODLights p, int i)
|
||||||
{
|
{
|
||||||
LodLights = l;
|
LodLights = l;
|
||||||
@ -3306,7 +3304,7 @@ namespace CodeWalker.GameFiles
|
|||||||
var vertexCount = indicesOffset / 12;
|
var vertexCount = indicesOffset / 12;
|
||||||
var indexCount = (int)(dataSize - indicesOffset);// / 4;
|
var indexCount = (int)(dataSize - indicesOffset);// / 4;
|
||||||
Data = MetaTypes.GetByteArray(meta, vptr, dataSize);
|
Data = MetaTypes.GetByteArray(meta, vptr, dataSize);
|
||||||
Vertices = MetaTypes.ConvertDataArray<Vector3>(Data, 0, vertexCount);
|
Vertices = MetaTypes.ConvertDataArray<Vector3>(Data, 0, vertexCount).ToArray();
|
||||||
Indices = new byte[indexCount];
|
Indices = new byte[indexCount];
|
||||||
Buffer.BlockCopy(Data, indicesOffset, Indices, 0, indexCount);
|
Buffer.BlockCopy(Data, indicesOffset, Indices, 0, indexCount);
|
||||||
BuildTriangles();
|
BuildTriangles();
|
||||||
|
@ -67,14 +67,10 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
Meta = rd.ReadBlock<Meta>();
|
Meta = rd.ReadBlock<Meta>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -90,13 +86,13 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
MapDataGroups = PsoTypes.GetObjectArray<YmfMapDataGroup, CMapDataGroup>(Pso, d.MapDataGroups);
|
MapDataGroups = PsoTypes.GetObjectArray<YmfMapDataGroup, CMapDataGroup>(Pso, d.MapDataGroups);
|
||||||
|
|
||||||
imapDependencies = PsoTypes.GetItemArray<CImapDependency>(Pso, d.imapDependencies);
|
imapDependencies = PsoTypes.GetItemArray<CImapDependency>(Pso, d.imapDependencies).ToArray();
|
||||||
|
|
||||||
imapDependencies2 = PsoTypes.GetObjectArray<YmfImapDependency2, CImapDependencies>(Pso, d.imapDependencies_2);
|
imapDependencies2 = PsoTypes.GetObjectArray<YmfImapDependency2, CImapDependencies>(Pso, d.imapDependencies_2);
|
||||||
|
|
||||||
itypDependencies2 = PsoTypes.GetObjectArray<YmfItypDependency2, CItypDependencies>(Pso, d.itypDependencies_2);
|
itypDependencies2 = PsoTypes.GetObjectArray<YmfItypDependency2, CItypDependencies>(Pso, d.itypDependencies_2);
|
||||||
|
|
||||||
HDTxdAssetBindings = PsoTypes.GetItemArray<CHDTxdAssetBinding>(Pso, d.HDTxdBindingArray);
|
HDTxdAssetBindings = PsoTypes.GetItemArray<CHDTxdAssetBinding>(Pso, d.HDTxdBindingArray).ToArray();
|
||||||
|
|
||||||
Interiors = PsoTypes.GetObjectArray<YmfInterior, CInteriorBoundsFiles>(Pso, d.Interiors);
|
Interiors = PsoTypes.GetObjectArray<YmfInterior, CInteriorBoundsFiles>(Pso, d.Interiors);
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ namespace CodeWalker.GameFiles
|
|||||||
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
|
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
|
||||||
if (resentry != null)
|
if (resentry != null)
|
||||||
{
|
{
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
Meta = rd.ReadBlock<Meta>();
|
Meta = rd.ReadBlock<Meta>();
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
|
|
||||||
NodeDictionary = rd.ReadBlock<NodeDictionary>();
|
NodeDictionary = rd.ReadBlock<NodeDictionary>();
|
||||||
@ -95,8 +95,6 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
//links will be populated by the space... maybe move that code here?
|
//links will be populated by the space... maybe move that code here?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string areaidstr = Name.ToLowerInvariant().Replace("nodes", "").Replace(".ynd", "");
|
string areaidstr = Name.ToLowerInvariant().Replace("nodes", "").Replace(".ynd", "");
|
||||||
int areaid = 0;
|
int areaid = 0;
|
||||||
int.TryParse(areaidstr, out areaid);
|
int.TryParse(areaidstr, out areaid);
|
||||||
|
@ -90,7 +90,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
|
|
||||||
Nav = rd.ReadBlock<NavMesh>();
|
Nav = rd.ReadBlock<NavMesh>();
|
||||||
|
@ -44,7 +44,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
//MemoryUsage = 0;
|
//MemoryUsage = 0;
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
Loaded = true;
|
Loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Load(byte[] data, RpfFileEntry entry)
|
public void Load(byte[] data, RpfFileEntry entry)
|
||||||
{
|
{
|
||||||
Name = entry.Name;
|
Name = entry.Name;
|
||||||
@ -43,7 +44,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
|
|
||||||
TextureDict = rd.ReadBlock<TextureDictionary>();
|
TextureDict = rd.ReadBlock<TextureDictionary>();
|
||||||
@ -64,7 +65,13 @@ namespace CodeWalker.GameFiles
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new public long MemoryUsage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return TextureDict.MemoryUsage;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
Meta = rd.ReadBlock<Meta>();
|
Meta = rd.ReadBlock<Meta>();
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
//MemoryUsage = 0;
|
//MemoryUsage = 0;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
throw new Exception("File entry wasn't a resource! (is it binary data?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDataReader rd = new ResourceDataReader(resentry, data);
|
using var rd = new ResourceDataReader(resentry, data);
|
||||||
|
|
||||||
//MemoryUsage = 0;
|
//MemoryUsage = 0;
|
||||||
|
|
||||||
|
@ -101,6 +101,28 @@ namespace CodeWalker.GameFiles
|
|||||||
Hash = hash;
|
Hash = hash;
|
||||||
Type = type;
|
Type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj == null) return false;
|
||||||
|
if (obj is not GameFileCacheKey gameFileCacheKey) return false;
|
||||||
|
return gameFileCacheKey.Hash == Hash && gameFileCacheKey.Type == Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(GameFileCacheKey first, GameFileCacheKey second)
|
||||||
|
{
|
||||||
|
return first.Equals(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(GameFileCacheKey first, GameFileCacheKey second)
|
||||||
|
{
|
||||||
|
return !first.Equals(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (int)Hash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -88,9 +88,25 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public uint TimeFlags { get; set; }
|
public uint TimeFlags { get; set; }
|
||||||
public bool[] ActiveHours { get; set; }
|
public bool[] ActiveHours { get; set; }
|
||||||
public string[] ActiveHoursText { get; set; }
|
private readonly Lazy<string[]> _activeHoursText;
|
||||||
|
public string[] ActiveHoursText { get => _activeHoursText.Value; }
|
||||||
public bool ExtraFlag { get { return ((TimeFlags >> 24) & 1) == 1; } }
|
public bool ExtraFlag { get { return ((TimeFlags >> 24) & 1) == 1; } }
|
||||||
|
|
||||||
|
public TimeArchetype()
|
||||||
|
{
|
||||||
|
_activeHoursText = new Lazy<string[]>(() =>
|
||||||
|
{
|
||||||
|
var activeHoursText = new string[24];
|
||||||
|
for (int i = 0; i < ActiveHours.Length; i++)
|
||||||
|
{
|
||||||
|
var nxth = (i < 23) ? (i + 1) : 0;
|
||||||
|
var hrs = string.Format("{0:00}:00 - {1:00}:00", i, nxth);
|
||||||
|
activeHoursText[i] = (hrs + (ActiveHours[i] ? " - On" : " - Off"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeHoursText;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void Init(YtypFile ytyp, ref CTimeArchetypeDef arch)
|
public void Init(YtypFile ytyp, ref CTimeArchetypeDef arch)
|
||||||
{
|
{
|
||||||
@ -117,16 +133,11 @@ namespace CodeWalker.GameFiles
|
|||||||
if (ActiveHours == null)
|
if (ActiveHours == null)
|
||||||
{
|
{
|
||||||
ActiveHours = new bool[24];
|
ActiveHours = new bool[24];
|
||||||
ActiveHoursText = new string[24];
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 24; i++)
|
for (int i = 0; i < 24; i++)
|
||||||
{
|
{
|
||||||
bool v = ((TimeFlags >> i) & 1) == 1;
|
bool v = ((TimeFlags >> i) & 1) == 1;
|
||||||
ActiveHours[i] = v;
|
ActiveHours[i] = v;
|
||||||
|
|
||||||
int nxth = (i < 23) ? (i + 1) : 0;
|
|
||||||
string hrs = string.Format("{0:00}:00 - {1:00}:00", i, nxth);
|
|
||||||
ActiveHoursText[i] = (hrs + (v ? " - On" : " - Off"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1179,6 +1179,29 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
return new MetaHash(v);
|
return new MetaHash(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj == null) return false;
|
||||||
|
if (obj is not MetaHash metaHash) return false;
|
||||||
|
|
||||||
|
return metaHash.Hash == Hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (int)Hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(MetaHash a, MetaHash b)
|
||||||
|
{
|
||||||
|
return a.Equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(MetaHash a, MetaHash b)
|
||||||
|
{
|
||||||
|
return !a.Equals(b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,14 +10,21 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static class MetaNames
|
public static class MetaNames
|
||||||
{
|
{
|
||||||
|
public static Dictionary<uint, string> stringCache = new Dictionary<uint, string>();
|
||||||
public static bool TryGetString(uint h, out string str)
|
public static bool TryGetString(uint h, out string str)
|
||||||
{
|
{
|
||||||
|
if (stringCache.TryGetValue(h, out str))
|
||||||
|
{
|
||||||
|
return str != null;
|
||||||
|
}
|
||||||
if (Enum.IsDefined(typeof(MetaName), h))
|
if (Enum.IsDefined(typeof(MetaName), h))
|
||||||
{
|
{
|
||||||
str = ((MetaName)h).ToString();
|
str = ((MetaName)h).ToString();
|
||||||
if (str.StartsWith("@")) str = str.Substring(1); //mainly to handle the @null entry
|
if (str.StartsWith("@")) str = str.Substring(1); //mainly to handle the @null entry
|
||||||
|
stringCache.Add(h, str);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
stringCache.Add(h, str);
|
||||||
str = null;
|
str = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using System.Xml;
|
|||||||
using TC = System.ComponentModel.TypeConverterAttribute;
|
using TC = System.ComponentModel.TypeConverterAttribute;
|
||||||
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
||||||
using CodeWalker.World;
|
using CodeWalker.World;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
{
|
{
|
||||||
@ -1479,22 +1480,29 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static T ConvertData<T>(byte[] data) where T : struct
|
public static T ConvertData<T>(byte[] data) where T : struct
|
||||||
{
|
{
|
||||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
MemoryMarshal.TryRead<T>(data.AsSpan(), out T value);
|
||||||
var h = handle.AddrOfPinnedObject();
|
|
||||||
var r = Marshal.PtrToStructure<T>(h);
|
return value;
|
||||||
handle.Free();
|
//GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||||
return r;
|
//var h = handle.AddrOfPinnedObject();
|
||||||
|
//var r = Marshal.PtrToStructure<T>(h);
|
||||||
|
//handle.Free();
|
||||||
|
//return r;
|
||||||
}
|
}
|
||||||
public static T ConvertData<T>(byte[] data, int offset) where T : struct
|
public static T ConvertData<T>(byte[] data, int offset) where T : struct
|
||||||
{
|
{
|
||||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
MemoryMarshal.TryRead<T>(data.AsSpan(offset), out T value);
|
||||||
var h = handle.AddrOfPinnedObject();
|
|
||||||
var r = Marshal.PtrToStructure<T>(h + offset);
|
return value;
|
||||||
handle.Free();
|
//GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||||
return r;
|
//var h = handle.AddrOfPinnedObject();
|
||||||
|
//var r = Marshal.PtrToStructure<T>(h + offset);
|
||||||
|
//handle.Free();
|
||||||
|
//return r;
|
||||||
}
|
}
|
||||||
public static T[] ConvertDataArray<T>(byte[] data, int offset, int count) where T : struct
|
public static Span<T> ConvertDataArray<T>(byte[] data, int offset, int count) where T : struct
|
||||||
{
|
{
|
||||||
|
return MemoryMarshal.Cast<byte, T>(data.AsSpan(offset, count * Marshal.SizeOf(typeof(T))));
|
||||||
T[] items = new T[count];
|
T[] items = new T[count];
|
||||||
int itemsize = Marshal.SizeOf(typeof(T));
|
int itemsize = Marshal.SizeOf(typeof(T));
|
||||||
//for (int i = 0; i < count; i++)
|
//for (int i = 0; i < count; i++)
|
||||||
@ -1520,8 +1528,6 @@ namespace CodeWalker.GameFiles
|
|||||||
{ return null; }
|
{ return null; }
|
||||||
|
|
||||||
T[] items = new T[count];
|
T[] items = new T[count];
|
||||||
int itemsize = Marshal.SizeOf(typeof(T));
|
|
||||||
int itemsleft = (int)count; //large arrays get split into chunks...
|
|
||||||
|
|
||||||
//MetaName blocktype = 0;
|
//MetaName blocktype = 0;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
@ -1572,13 +1578,18 @@ namespace CodeWalker.GameFiles
|
|||||||
int blockcount = ptrblock.DataLength / itemsize;
|
int blockcount = ptrblock.DataLength / itemsize;
|
||||||
int itemcount = blockcount - itemoffset;
|
int itemcount = blockcount - itemoffset;
|
||||||
if (itemcount > itemsleft)
|
if (itemcount > itemsleft)
|
||||||
{ itemcount = itemsleft; } //don't try to read too many items..
|
|
||||||
for (int i = 0; i < itemcount; i++)
|
|
||||||
{
|
{
|
||||||
int offset = (itemoffset + i) * itemsize;
|
itemcount = itemsleft;
|
||||||
int index = curi + i;
|
} //don't try to read too many items..
|
||||||
items[index] = ConvertData<T>(ptrblock.Data, offset);
|
|
||||||
}
|
|
||||||
|
ConvertDataArray<T>(ptrblock.Data, itemoffset * Marshal.SizeOf(typeof(T)), itemcount).CopyTo(items.AsSpan(curi));
|
||||||
|
//for (int i = 0; i < itemcount; i++)
|
||||||
|
//{
|
||||||
|
// int offset = (itemoffset + i) * itemsize;
|
||||||
|
// int index = curi + i;
|
||||||
|
// items[index] = ConvertData<T>(ptrblock.Data, offset);
|
||||||
|
//}
|
||||||
itemoffset = 0; //start at beginning of next block..
|
itemoffset = 0; //start at beginning of next block..
|
||||||
curi += itemcount;
|
curi += itemcount;
|
||||||
itemsleft -= itemcount;
|
itemsleft -= itemcount;
|
||||||
|
@ -1423,7 +1423,7 @@ namespace CodeWalker.GameFiles
|
|||||||
arrEnum.SwapEnd();
|
arrEnum.SwapEnd();
|
||||||
var enumArr = PsoTypes.GetUintArray(cont.Pso, arrEnum);
|
var enumArr = PsoTypes.GetUintArray(cont.Pso, arrEnum);
|
||||||
var enumDef = cont.GetEnumInfo((MetaName)arrEntry.ReferenceKey);
|
var enumDef = cont.GetEnumInfo((MetaName)arrEntry.ReferenceKey);
|
||||||
WriteItemArray(sb, enumArr, indent, ename, "enum", (ie)=> {
|
WriteItemArray<uint>(sb, enumArr, indent, ename, "enum", (ie)=> {
|
||||||
var eval = enumDef?.FindEntry((int)ie);
|
var eval = enumDef?.FindEntry((int)ie);
|
||||||
return HashString(eval?.EntryNameHash ?? 0);
|
return HashString(eval?.EntryNameHash ?? 0);
|
||||||
});
|
});
|
||||||
@ -1945,9 +1945,10 @@ namespace CodeWalker.GameFiles
|
|||||||
if (lastcol || lastn) sb.AppendLine();
|
if (lastcol || lastn) sb.AppendLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void WriteRawArray<T>(StringBuilder sb, T[] arr, int ind, string name, string typeName, Func<T, string> formatter = null, int arrRowSize = 10) where T : struct
|
|
||||||
|
public static void WriteRawArray<T>(StringBuilder sb, Span<T> arr, int ind, string name, string typeName, Func<T, string> formatter = null, int arrRowSize = 10) where T : struct
|
||||||
{
|
{
|
||||||
var aCount = arr?.Length ?? 0;
|
var aCount = arr.Length;
|
||||||
//var arrRowSize = 10;
|
//var arrRowSize = 10;
|
||||||
var aind = ind + 1;
|
var aind = ind + 1;
|
||||||
var arrTag = name;// + " itemType=\"" + typeName + "\"";
|
var arrTag = name;// + " itemType=\"" + typeName + "\"";
|
||||||
@ -1986,15 +1987,25 @@ namespace CodeWalker.GameFiles
|
|||||||
SelfClosingTag(sb, ind, arrTag);
|
SelfClosingTag(sb, ind, arrTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void WriteRawArray<T>(StringBuilder sb, T[] arr, int ind, string name, string typeName, Func<T, string> formatter = null, int arrRowSize = 10) where T : struct
|
||||||
|
{
|
||||||
|
WriteRawArray<T>(sb, arr.AsSpan(), ind, name, typeName, formatter, arrRowSize);
|
||||||
|
}
|
||||||
public static void WriteItemArray<T>(StringBuilder sb, T[] arr, int ind, string name, string typeName, Func<T, string> formatter) where T : struct
|
public static void WriteItemArray<T>(StringBuilder sb, T[] arr, int ind, string name, string typeName, Func<T, string> formatter) where T : struct
|
||||||
{
|
{
|
||||||
var aCount = arr?.Length ?? 0;
|
WriteItemArray<T>(sb, arr.AsSpan(), ind, name, typeName, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteItemArray<T>(StringBuilder sb, Span<T> arr, int ind, string name, string typeName, Func<T, string> formatter) where T : struct
|
||||||
|
{
|
||||||
|
var itemCount = arr.Length;
|
||||||
var arrTag = name;// + " itemType=\"Hash\"";
|
var arrTag = name;// + " itemType=\"Hash\"";
|
||||||
var aind = ind + 1;
|
var aind = ind + 1;
|
||||||
if (aCount > 0)
|
if (itemCount > 0)
|
||||||
{
|
{
|
||||||
OpenTag(sb, ind, arrTag);
|
OpenTag(sb, ind, arrTag);
|
||||||
for (int n = 0; n < aCount; n++)
|
for (int n = 0; n < itemCount; n++)
|
||||||
{
|
{
|
||||||
Indent(sb, aind);
|
Indent(sb, aind);
|
||||||
sb.Append("<Item>");
|
sb.Append("<Item>");
|
||||||
|
@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
using TC = System.ComponentModel.TypeConverterAttribute;
|
using TC = System.ComponentModel.TypeConverterAttribute;
|
||||||
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
{
|
{
|
||||||
@ -15819,45 +15819,46 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static T ConvertDataRaw<T>(byte[] data) where T : struct
|
public static T ConvertDataRaw<T>(byte[] data) where T : struct
|
||||||
{
|
{
|
||||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
MemoryMarshal.TryRead<T>(data.AsSpan(), out T value);
|
||||||
var h = handle.AddrOfPinnedObject();
|
|
||||||
var r = Marshal.PtrToStructure<T>(h);
|
return value;
|
||||||
handle.Free();
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
public static T ConvertDataRaw<T>(byte[] data, int offset) where T : struct
|
public static T ConvertDataRaw<T>(byte[] data, int offset) where T : struct
|
||||||
{
|
{
|
||||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
MemoryMarshal.TryRead<T>(data.AsSpan(offset), out T value);
|
||||||
var h = handle.AddrOfPinnedObject();
|
|
||||||
var r = Marshal.PtrToStructure<T>(h + offset);
|
return value;
|
||||||
handle.Free();
|
//return MemoryMarshal.GetReference<T>(data.AsSpan(offset));
|
||||||
return r;
|
//GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||||
|
//var h = handle.AddrOfPinnedObject();
|
||||||
|
//var r = Marshal.PtrToStructure<T>(h + offset);
|
||||||
|
//handle.Free();
|
||||||
|
//return r;
|
||||||
}
|
}
|
||||||
public static T ConvertData<T>(byte[] data, int offset) where T : struct, IPsoSwapEnd
|
public static T ConvertData<T>(byte[] data, int offset) where T : struct, IPsoSwapEnd
|
||||||
{
|
{
|
||||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
MemoryMarshal.TryRead<T>(data.AsSpan(offset), out T value);
|
||||||
var h = handle.AddrOfPinnedObject();
|
|
||||||
var r = Marshal.PtrToStructure<T>(h + offset);
|
value.SwapEnd();
|
||||||
handle.Free();
|
|
||||||
r.SwapEnd();
|
return value;
|
||||||
return r;
|
//GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||||
|
//var h = handle.AddrOfPinnedObject();
|
||||||
|
//var r = Marshal.PtrToStructure<T>(h + offset);
|
||||||
|
//handle.Free();
|
||||||
|
//r.SwapEnd();
|
||||||
|
//return r;
|
||||||
}
|
}
|
||||||
public static T[] ConvertDataArrayRaw<T>(byte[] data, int offset, int count) where T : struct
|
public static Span<T>ConvertDataArrayRaw<T>(byte[] data, int offset, int count) where T : struct
|
||||||
{
|
{
|
||||||
T[] items = new T[count];
|
return MemoryMarshal.Cast<byte, T>(data.AsSpan(offset, count * Marshal.SizeOf(typeof(T))));
|
||||||
int itemsize = Marshal.SizeOf(typeof(T));
|
|
||||||
//for (int i = 0; i < count; i++)
|
|
||||||
//{
|
|
||||||
// int off = offset + i * itemsize;
|
|
||||||
// items[i] = ConvertDataRaw<T>(data, off);
|
|
||||||
//}
|
|
||||||
|
|
||||||
GCHandle handle = GCHandle.Alloc(items, GCHandleType.Pinned);
|
//GCHandle handle = GCHandle.Alloc(items, GCHandleType.Pinned);
|
||||||
var h = handle.AddrOfPinnedObject();
|
//var h = handle.AddrOfPinnedObject();
|
||||||
Marshal.Copy(data, offset, h, itemsize * count);
|
//Marshal.Copy(data, offset, h, itemsize * count);
|
||||||
handle.Free();
|
//handle.Free();
|
||||||
|
|
||||||
return items;
|
//return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -15878,7 +15879,7 @@ namespace CodeWalker.GameFiles
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T[] GetItemArrayRaw<T>(PsoFile pso, Array_Structure arr) where T : struct
|
public static Span<T> GetItemArrayRaw<T>(PsoFile pso, Array_Structure arr) where T : struct
|
||||||
{
|
{
|
||||||
if ((arr.Count1 > 0) && (arr.Pointer > 0))
|
if ((arr.Count1 > 0) && (arr.Pointer > 0))
|
||||||
{
|
{
|
||||||
@ -15887,7 +15888,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public static T[] GetItemArray<T>(PsoFile pso, Array_Structure arr) where T : struct, IPsoSwapEnd
|
public static Span<T> GetItemArray<T>(PsoFile pso, Array_Structure arr) where T : struct, IPsoSwapEnd
|
||||||
{
|
{
|
||||||
if ((arr.Count1 > 0) && (arr.Pointer > 0))
|
if ((arr.Count1 > 0) && (arr.Pointer > 0))
|
||||||
{
|
{
|
||||||
@ -15906,7 +15907,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static uint[] GetUintArrayRaw(PsoFile pso, Array_uint arr)
|
public static Span<uint> GetUintArrayRaw(PsoFile pso, Array_uint arr)
|
||||||
{
|
{
|
||||||
byte[] data = pso.DataSection.Data;
|
byte[] data = pso.DataSection.Data;
|
||||||
var entryid = arr.PointerDataId;
|
var entryid = arr.PointerDataId;
|
||||||
@ -15917,12 +15918,12 @@ namespace CodeWalker.GameFiles
|
|||||||
var entryoffset = arr.PointerDataOffset;
|
var entryoffset = arr.PointerDataOffset;
|
||||||
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
||||||
int totoffset = arrentry.Offset + (int)entryoffset;
|
int totoffset = arrentry.Offset + (int)entryoffset;
|
||||||
uint[] readdata = ConvertDataArrayRaw<uint>(data, totoffset, arr.Count1);
|
var readdata = ConvertDataArrayRaw<uint>(data, totoffset, arr.Count1);
|
||||||
return readdata;
|
return readdata;
|
||||||
}
|
}
|
||||||
public static uint[] GetUintArray(PsoFile pso, Array_uint arr)
|
public static Span<uint> GetUintArray(PsoFile pso, Array_uint arr)
|
||||||
{
|
{
|
||||||
uint[] uints = GetUintArrayRaw(pso, arr);
|
var uints = GetUintArrayRaw(pso, arr);
|
||||||
if (uints == null) return null;
|
if (uints == null) return null;
|
||||||
for (int i = 0; i < uints.Length; i++)
|
for (int i = 0; i < uints.Length; i++)
|
||||||
{
|
{
|
||||||
@ -15933,7 +15934,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static MetaHash[] GetHashArray(PsoFile pso, Array_uint arr)
|
public static MetaHash[] GetHashArray(PsoFile pso, Array_uint arr)
|
||||||
{
|
{
|
||||||
uint[] uints = GetUintArrayRaw(pso, arr);
|
var uints = GetUintArrayRaw(pso, arr);
|
||||||
if (uints == null) return null;
|
if (uints == null) return null;
|
||||||
MetaHash[] hashes = new MetaHash[uints.Length];
|
MetaHash[] hashes = new MetaHash[uints.Length];
|
||||||
for (int n = 0; n < uints.Length; n++)
|
for (int n = 0; n < uints.Length; n++)
|
||||||
@ -15946,7 +15947,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static float[] GetFloatArrayRaw(PsoFile pso, Array_float arr)
|
public static Span<float> GetFloatArrayRaw(PsoFile pso, Array_float arr)
|
||||||
{
|
{
|
||||||
byte[] data = pso.DataSection.Data;
|
byte[] data = pso.DataSection.Data;
|
||||||
var entryid = arr.PointerDataId;
|
var entryid = arr.PointerDataId;
|
||||||
@ -15957,12 +15958,12 @@ namespace CodeWalker.GameFiles
|
|||||||
var entryoffset = arr.PointerDataOffset;
|
var entryoffset = arr.PointerDataOffset;
|
||||||
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
||||||
int totoffset = arrentry.Offset + (int)entryoffset;
|
int totoffset = arrentry.Offset + (int)entryoffset;
|
||||||
float[] readdata = ConvertDataArrayRaw<float>(data, totoffset, arr.Count1);
|
var readdata = ConvertDataArrayRaw<float>(data, totoffset, arr.Count1);
|
||||||
return readdata;
|
return readdata;
|
||||||
}
|
}
|
||||||
public static float[] GetFloatArray(PsoFile pso, Array_float arr)
|
public static Span<float> GetFloatArray(PsoFile pso, Array_float arr)
|
||||||
{
|
{
|
||||||
float[] floats = GetFloatArrayRaw(pso, arr);
|
var floats = GetFloatArrayRaw(pso, arr);
|
||||||
if (floats == null) return null;
|
if (floats == null) return null;
|
||||||
for (int i = 0; i < floats.Length; i++)
|
for (int i = 0; i < floats.Length; i++)
|
||||||
{
|
{
|
||||||
@ -15975,7 +15976,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ushort[] GetUShortArrayRaw(PsoFile pso, Array_Structure arr)
|
public static Span<ushort> GetUShortArrayRaw(PsoFile pso, Array_Structure arr)
|
||||||
{
|
{
|
||||||
byte[] data = pso.DataSection.Data;
|
byte[] data = pso.DataSection.Data;
|
||||||
var entryid = arr.PointerDataId;
|
var entryid = arr.PointerDataId;
|
||||||
@ -15986,12 +15987,12 @@ namespace CodeWalker.GameFiles
|
|||||||
var entryoffset = arr.PointerDataOffset;
|
var entryoffset = arr.PointerDataOffset;
|
||||||
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
||||||
int totoffset = arrentry.Offset + (int)entryoffset;
|
int totoffset = arrentry.Offset + (int)entryoffset;
|
||||||
ushort[] readdata = ConvertDataArrayRaw<ushort>(data, totoffset, arr.Count1);
|
Span<ushort> readdata = ConvertDataArrayRaw<ushort>(data, totoffset, arr.Count1);
|
||||||
return readdata;
|
return readdata;
|
||||||
}
|
}
|
||||||
public static ushort[] GetUShortArray(PsoFile pso, Array_Structure arr)
|
public static Span<ushort> GetUShortArray(PsoFile pso, Array_Structure arr)
|
||||||
{
|
{
|
||||||
ushort[] ushorts = GetUShortArrayRaw(pso, arr);
|
var ushorts = GetUShortArrayRaw(pso, arr);
|
||||||
if (ushorts == null) return null;
|
if (ushorts == null) return null;
|
||||||
for (int i = 0; i < ushorts.Length; i++)
|
for (int i = 0; i < ushorts.Length; i++)
|
||||||
{
|
{
|
||||||
@ -16007,7 +16008,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static T[] GetObjectArray<T, U>(PsoFile pso, Array_Structure arr) where U : struct, IPsoSwapEnd where T : PsoClass<U>, new()
|
public static T[] GetObjectArray<T, U>(PsoFile pso, Array_Structure arr) where U : struct, IPsoSwapEnd where T : PsoClass<U>, new()
|
||||||
{
|
{
|
||||||
U[] items = GetItemArray<U>(pso, arr);
|
Span<U> items = GetItemArray<U>(pso, arr);
|
||||||
if (items == null) return null;
|
if (items == null) return null;
|
||||||
if (items.Length == 0) return null;
|
if (items.Length == 0) return null;
|
||||||
T[] result = new T[items.Length];
|
T[] result = new T[items.Length];
|
||||||
@ -16038,13 +16039,11 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static PsoPOINTER[] GetPointerArray(PsoFile pso, Array_StructurePointer array)
|
public static Span<PsoPOINTER> GetPointerArray(PsoFile pso, Array_StructurePointer array)
|
||||||
{
|
{
|
||||||
uint count = array.Count1;
|
uint count = array.Count1;
|
||||||
if (count == 0) return null;
|
if (count == 0) return null;
|
||||||
|
|
||||||
int ptrsize = Marshal.SizeOf(typeof(MetaPOINTER));
|
|
||||||
int itemsleft = (int)count; //large arrays get split into chunks...
|
|
||||||
uint ptrindex = array.PointerDataIndex;
|
uint ptrindex = array.PointerDataIndex;
|
||||||
uint ptroffset = array.PointerDataOffset;
|
uint ptroffset = array.PointerDataOffset;
|
||||||
var ptrblock = (ptrindex < pso.DataMapSection.EntriesCount) ? pso.DataMapSection.Entries[ptrindex] : null;
|
var ptrblock = (ptrindex < pso.DataMapSection.EntriesCount) ? pso.DataMapSection.Entries[ptrindex] : null;
|
||||||
@ -16071,13 +16070,12 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
uint count = array.Count1;
|
uint count = array.Count1;
|
||||||
if (count == 0) return null;
|
if (count == 0) return null;
|
||||||
PsoPOINTER[] ptrs = GetPointerArray(pso, array);
|
var ptrs = GetPointerArray(pso, array);
|
||||||
if (ptrs == null) return null;
|
if (ptrs == null) return null;
|
||||||
if (ptrs.Length < count)
|
if (ptrs.Length < count)
|
||||||
{ return null; }
|
{ return null; }
|
||||||
|
|
||||||
T[] items = new T[count];
|
T[] items = new T[count];
|
||||||
int itemsize = Marshal.SizeOf(typeof(T));
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
@ -243,106 +243,106 @@ namespace CodeWalker.GameFiles
|
|||||||
default: return "XML";
|
default: return "XML";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static MetaFormat GetXMLFormat(string fnamel, out int trimlength)
|
public static MetaFormat GetXMLFormat(string fileName, out int trimlength)
|
||||||
{
|
{
|
||||||
var mformat = MetaFormat.RSC;
|
var mformat = MetaFormat.RSC;
|
||||||
trimlength = 4;
|
trimlength = 4;
|
||||||
|
|
||||||
if (!fnamel.EndsWith(".xml"))
|
if (!fileName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.XML;//not really correct, but have to return something...
|
mformat = MetaFormat.XML;//not really correct, but have to return something...
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".pso.xml"))
|
if (fileName.EndsWith(".pso.xml"))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.PSO;
|
mformat = MetaFormat.PSO;
|
||||||
trimlength = 8;
|
trimlength = 8;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".rbf.xml"))
|
if (fileName.EndsWith(".rbf.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.RBF;
|
mformat = MetaFormat.RBF;
|
||||||
trimlength = 8;
|
trimlength = 8;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".rel.xml"))
|
if (fileName.EndsWith(".rel.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.AudioRel;
|
mformat = MetaFormat.AudioRel;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ynd.xml"))
|
if (fileName.EndsWith(".ynd.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ynd;
|
mformat = MetaFormat.Ynd;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ynv.xml"))
|
if (fileName.EndsWith(".ynv.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ynv;
|
mformat = MetaFormat.Ynv;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ycd.xml"))
|
if (fileName.EndsWith(".ycd.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ycd;
|
mformat = MetaFormat.Ycd;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ybn.xml"))
|
if (fileName.EndsWith(".ybn.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ybn;
|
mformat = MetaFormat.Ybn;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ytd.xml"))
|
if (fileName.EndsWith(".ytd.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ytd;
|
mformat = MetaFormat.Ytd;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ydr.xml"))
|
if (fileName.EndsWith(".ydr.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ydr;
|
mformat = MetaFormat.Ydr;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ydd.xml"))
|
if (fileName.EndsWith(".ydd.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ydd;
|
mformat = MetaFormat.Ydd;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".yft.xml"))
|
if (fileName.EndsWith(".yft.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Yft;
|
mformat = MetaFormat.Yft;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ypt.xml"))
|
if (fileName.EndsWith(".ypt.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ypt;
|
mformat = MetaFormat.Ypt;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".yld.xml"))
|
if (fileName.EndsWith(".yld.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Yld;
|
mformat = MetaFormat.Yld;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".yed.xml"))
|
if (fileName.EndsWith(".yed.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Yed;
|
mformat = MetaFormat.Yed;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ywr.xml"))
|
if (fileName.EndsWith(".ywr.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ywr;
|
mformat = MetaFormat.Ywr;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".yvr.xml"))
|
if (fileName.EndsWith(".yvr.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Yvr;
|
mformat = MetaFormat.Yvr;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".awc.xml"))
|
if (fileName.EndsWith(".awc.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Awc;
|
mformat = MetaFormat.Awc;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".fxc.xml"))
|
if (fileName.EndsWith(".fxc.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Fxc;
|
mformat = MetaFormat.Fxc;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith("cache_y.dat.xml"))
|
if (fileName.EndsWith("cache_y.dat.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.CacheFile;
|
mformat = MetaFormat.CacheFile;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".dat.xml") && fnamel.StartsWith("heightmap"))
|
if (fileName.EndsWith(".dat.xml", StringComparison.OrdinalIgnoreCase) && fileName.StartsWith("heightmap", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Heightmap;
|
mformat = MetaFormat.Heightmap;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".ypdb.xml"))
|
if (fileName.EndsWith(".ypdb.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ypdb;
|
mformat = MetaFormat.Ypdb;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".yfd.xml"))
|
if (fileName.EndsWith(".yfd.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Yfd;
|
mformat = MetaFormat.Yfd;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".mrf.xml"))
|
if (fileName.EndsWith(".mrf.xml", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Mrf;
|
mformat = MetaFormat.Mrf;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -5331,6 +5332,15 @@ namespace CodeWalker.GameFiles
|
|||||||
var d = new Drawable();
|
var d = new Drawable();
|
||||||
d.LightAttributes = dd.LightAttributes;
|
d.LightAttributes = dd.LightAttributes;
|
||||||
d.Name = dd.Name;
|
d.Name = dd.Name;
|
||||||
|
if (d.Hash != 0)
|
||||||
|
{
|
||||||
|
d.Hash = dd.Hash;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d.Hash = JenkHash.GenHash(dd.Name);
|
||||||
|
}
|
||||||
|
|
||||||
d.Bound = dd.Bound;
|
d.Bound = dd.Bound;
|
||||||
r = d;
|
r = d;
|
||||||
}
|
}
|
||||||
@ -5383,6 +5393,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
// reference data
|
// reference data
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
public uint Hash { get; set; }
|
||||||
public Bounds Bound { get; set; }
|
public Bounds Bound { get; set; }
|
||||||
|
|
||||||
public string ErrorMessage { get; set; }
|
public string ErrorMessage { get; set; }
|
||||||
@ -5455,6 +5466,7 @@ namespace CodeWalker.GameFiles
|
|||||||
public override void WriteXml(StringBuilder sb, int indent, string ddsfolder)
|
public override void WriteXml(StringBuilder sb, int indent, string ddsfolder)
|
||||||
{
|
{
|
||||||
YdrXml.StringTag(sb, indent, "Name", YdrXml.XmlEscape(Name));
|
YdrXml.StringTag(sb, indent, "Name", YdrXml.XmlEscape(Name));
|
||||||
|
YdrXml.StringTag(sb, indent, "Hash", Hash.ToString());
|
||||||
base.WriteXml(sb, indent, ddsfolder);
|
base.WriteXml(sb, indent, ddsfolder);
|
||||||
if (Bound != null)
|
if (Bound != null)
|
||||||
{
|
{
|
||||||
@ -5468,6 +5480,10 @@ namespace CodeWalker.GameFiles
|
|||||||
public override void ReadXml(XmlNode node, string ddsfolder)
|
public override void ReadXml(XmlNode node, string ddsfolder)
|
||||||
{
|
{
|
||||||
Name = Xml.GetChildInnerText(node, "Name");
|
Name = Xml.GetChildInnerText(node, "Name");
|
||||||
|
if (uint.TryParse(Xml.GetChildInnerText(node, "Hash"), out var hash))
|
||||||
|
{
|
||||||
|
Hash = hash;
|
||||||
|
}
|
||||||
base.ReadXml(node, ddsfolder);
|
base.ReadXml(node, ddsfolder);
|
||||||
var bnode = node.SelectSingleNode("Bounds");
|
var bnode = node.SelectSingleNode("Bounds");
|
||||||
if (bnode != null)
|
if (bnode != null)
|
||||||
@ -5847,8 +5863,16 @@ namespace CodeWalker.GameFiles
|
|||||||
var d = new Drawable();
|
var d = new Drawable();
|
||||||
d.ReadXml(inode, ddsfolder);
|
d.ReadXml(inode, ddsfolder);
|
||||||
drawables.Add(d);
|
drawables.Add(d);
|
||||||
|
if (d.Hash != 0)
|
||||||
|
{
|
||||||
|
drawablehashes.Add(d.Hash);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
drawablehashes.Add(JenkHash.GenHash(d.Name));//TODO: check this!
|
drawablehashes.Add(JenkHash.GenHash(d.Name));//TODO: check this!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Hashes = drawablehashes.ToArray();
|
Hashes = drawablehashes.ToArray();
|
||||||
|
@ -1791,7 +1791,7 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
int datalength = ItemCount * StructureSize;
|
int datalength = ItemCount * StructureSize;
|
||||||
byte[] data = reader.ReadBytes(datalength);
|
byte[] data = reader.ReadBytes(datalength);
|
||||||
Items = MetaTypes.ConvertDataArray<T>(data, 0, ItemCount);
|
Items = MetaTypes.ConvertDataArray<T>(data, 0, ItemCount).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||||
|
@ -348,9 +348,9 @@ namespace CodeWalker.GameFiles
|
|||||||
fileBase.FilePagesInfo.GraphicsPagesCount = (byte)graphicsPageFlags.Count;
|
fileBase.FilePagesInfo.GraphicsPagesCount = (byte)graphicsPageFlags.Count;
|
||||||
|
|
||||||
|
|
||||||
var systemStream = new MemoryStream();
|
using var systemStream = new MemoryStream();
|
||||||
var graphicsStream = new MemoryStream();
|
using var graphicsStream = new MemoryStream();
|
||||||
var resourceWriter = new ResourceDataWriter(systemStream, graphicsStream);
|
using var resourceWriter = new ResourceDataWriter(systemStream, graphicsStream);
|
||||||
|
|
||||||
resourceWriter.Position = 0x50000000;
|
resourceWriter.Position = 0x50000000;
|
||||||
foreach (var block in systemBlocks)
|
foreach (var block in systemBlocks)
|
||||||
@ -456,15 +456,12 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static byte[] Compress(byte[] data)
|
public static byte[] Compress(byte[] data)
|
||||||
{
|
{
|
||||||
using (MemoryStream ms = new MemoryStream())
|
using (MemoryStream ms = RpfFile.recyclableMemoryStreamManager.GetStream())
|
||||||
{
|
{
|
||||||
DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress, true);
|
DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress, true);
|
||||||
ds.Write(data, 0, data.Length);
|
ds.Write(data, 0, data.Length);
|
||||||
ds.Close();
|
ds.Close();
|
||||||
byte[] deflated = ms.GetBuffer();
|
return ms.ToArray();
|
||||||
byte[] outbuf = new byte[ms.Length]; //need to copy to the right size buffer...
|
|
||||||
Array.Copy(deflated, outbuf, outbuf.Length);
|
|
||||||
return outbuf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static byte[] Decompress(byte[] data)
|
public static byte[] Decompress(byte[] data)
|
||||||
@ -472,14 +469,17 @@ namespace CodeWalker.GameFiles
|
|||||||
using (MemoryStream ms = new MemoryStream(data))
|
using (MemoryStream ms = new MemoryStream(data))
|
||||||
{
|
{
|
||||||
DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress);
|
DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress);
|
||||||
MemoryStream outstr = new MemoryStream();
|
MemoryStream outstr = RpfFile.recyclableMemoryStreamManager.GetStream("Decompress", data.Length);
|
||||||
ds.CopyTo(outstr);
|
ds.CopyTo(outstr);
|
||||||
byte[] deflated = outstr.GetBuffer();
|
return outstr.ToArray();
|
||||||
byte[] outbuf = new byte[outstr.Length]; //need to copy to the right size buffer...
|
|
||||||
Array.Copy(deflated, outbuf, outbuf.Length);
|
|
||||||
return outbuf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DeflateStream Decompress(Stream stream)
|
||||||
|
{
|
||||||
|
DeflateStream ds = new DeflateStream(stream, CompressionMode.Decompress);
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,13 +38,16 @@ namespace CodeWalker.GameFiles
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a resource data reader.
|
/// Represents a resource data reader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ResourceDataReader : DataReader
|
public class ResourceDataReader : DataReader, IDisposable
|
||||||
{
|
{
|
||||||
private const long SYSTEM_BASE = 0x50000000;
|
private const long SYSTEM_BASE = 0x50000000;
|
||||||
private const long GRAPHICS_BASE = 0x60000000;
|
private const long GRAPHICS_BASE = 0x60000000;
|
||||||
|
|
||||||
private Stream systemStream;
|
private readonly Stream systemStream;
|
||||||
private Stream graphicsStream;
|
private readonly Stream graphicsStream;
|
||||||
|
|
||||||
|
private readonly long systemSize = 0;
|
||||||
|
private readonly long graphicsSize = 0;
|
||||||
|
|
||||||
public RpfResourceFileEntry FileEntry { get; set; }
|
public RpfResourceFileEntry FileEntry { get; set; }
|
||||||
|
|
||||||
@ -71,7 +74,7 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
} = SYSTEM_BASE;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new resource data reader for the specified system- and graphics-stream.
|
/// Initializes a new resource data reader for the specified system- and graphics-stream.
|
||||||
@ -81,14 +84,16 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
this.systemStream = systemStream;
|
this.systemStream = systemStream;
|
||||||
this.graphicsStream = graphicsStream;
|
this.graphicsStream = graphicsStream;
|
||||||
|
this.systemSize = systemStream.Length;
|
||||||
|
this.graphicsSize = graphicsStream.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceDataReader(RpfResourceFileEntry resentry, byte[] data, Endianess endianess = Endianess.LittleEndian)
|
public ResourceDataReader(RpfResourceFileEntry resentry, byte[] data, Endianess endianess = Endianess.LittleEndian)
|
||||||
: base((Stream)null, endianess)
|
: base((Stream)null, endianess)
|
||||||
{
|
{
|
||||||
FileEntry = resentry;
|
FileEntry = resentry;
|
||||||
var systemSize = resentry.SystemSize;
|
this.systemSize = resentry.SystemSize;
|
||||||
var graphicsSize = resentry.GraphicsSize;
|
this.graphicsSize = resentry.GraphicsSize;
|
||||||
|
|
||||||
//if (data != null)
|
//if (data != null)
|
||||||
//{
|
//{
|
||||||
@ -103,9 +108,8 @@ namespace CodeWalker.GameFiles
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
this.systemStream = new MemoryStream(data, 0, systemSize);
|
this.systemStream = new MemoryStream(data, 0, (int)systemSize);
|
||||||
this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize);
|
this.graphicsStream = new MemoryStream(data, (int)systemSize, (int)graphicsSize);
|
||||||
Position = 0x50000000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceDataReader(int systemSize, int graphicsSize, byte[] data, Endianess endianess = Endianess.LittleEndian)
|
public ResourceDataReader(int systemSize, int graphicsSize, byte[] data, Endianess endianess = Endianess.LittleEndian)
|
||||||
@ -113,24 +117,21 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
this.systemStream = new MemoryStream(data, 0, systemSize);
|
this.systemStream = new MemoryStream(data, 0, systemSize);
|
||||||
this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize);
|
this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize);
|
||||||
Position = 0x50000000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads data from the underlying stream. This is the only method that directly accesses
|
/// Reads data from the underlying stream. This is the only method that directly accesses
|
||||||
/// the data in the underlying stream.
|
/// the data in the underlying stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override byte[] ReadFromStream(int count, bool ignoreEndianess = false)
|
protected override byte[] ReadFromStream(int count, bool ignoreEndianess = false, byte[] buffer = null)
|
||||||
{
|
{
|
||||||
if ((Position & SYSTEM_BASE) == SYSTEM_BASE)
|
if ((Position & SYSTEM_BASE) == SYSTEM_BASE)
|
||||||
{
|
{
|
||||||
// read from system stream...
|
// read from system stream...
|
||||||
|
|
||||||
systemStream.Position = Position & ~0x50000000;
|
systemStream.Position = Position & ~SYSTEM_BASE;
|
||||||
|
|
||||||
var buffer = new byte[count];
|
buffer ??= new byte[count];
|
||||||
systemStream.Read(buffer, 0, count);
|
systemStream.Read(buffer, 0, count);
|
||||||
|
|
||||||
// handle endianess
|
// handle endianess
|
||||||
@ -139,17 +140,17 @@ namespace CodeWalker.GameFiles
|
|||||||
Array.Reverse(buffer);
|
Array.Reverse(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Position = systemStream.Position | 0x50000000;
|
Position = systemStream.Position | SYSTEM_BASE;
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
if ((Position & GRAPHICS_BASE) == GRAPHICS_BASE)
|
else if ((Position & GRAPHICS_BASE) == GRAPHICS_BASE)
|
||||||
{
|
{
|
||||||
// read from graphic stream...
|
// read from graphic stream...
|
||||||
|
|
||||||
graphicsStream.Position = Position & ~0x60000000;
|
graphicsStream.Position = Position & ~GRAPHICS_BASE;
|
||||||
|
|
||||||
var buffer = new byte[count];
|
buffer ??= new byte[count];
|
||||||
graphicsStream.Read(buffer, 0, count);
|
graphicsStream.Read(buffer, 0, count);
|
||||||
|
|
||||||
// handle endianess
|
// handle endianess
|
||||||
@ -158,12 +159,44 @@ namespace CodeWalker.GameFiles
|
|||||||
Array.Reverse(buffer);
|
Array.Reverse(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Position = graphicsStream.Position | 0x60000000;
|
Position = graphicsStream.Position | GRAPHICS_BASE;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
throw new Exception("illegal position!");
|
throw new Exception("illegal position!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override byte ReadByte()
|
||||||
|
{
|
||||||
|
if ((Position & SYSTEM_BASE) == SYSTEM_BASE)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// read from system stream...
|
||||||
|
|
||||||
|
systemStream.Position = Position & ~SYSTEM_BASE;
|
||||||
|
|
||||||
|
var readByte = (byte)systemStream.ReadByte();
|
||||||
|
|
||||||
|
Position = systemStream.Position | SYSTEM_BASE;
|
||||||
|
return readByte;
|
||||||
|
|
||||||
|
}
|
||||||
|
if ((Position & GRAPHICS_BASE) == GRAPHICS_BASE)
|
||||||
|
{
|
||||||
|
// read from graphic stream...
|
||||||
|
|
||||||
|
graphicsStream.Position = Position & ~GRAPHICS_BASE;
|
||||||
|
|
||||||
|
var readByte = (byte)graphicsStream.ReadByte();
|
||||||
|
|
||||||
|
Position = graphicsStream.Position | GRAPHICS_BASE;
|
||||||
|
return readByte;
|
||||||
|
}
|
||||||
|
throw new Exception("illegal position!");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads a block.
|
/// Reads a block.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -447,6 +480,13 @@ namespace CodeWalker.GameFiles
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
base.Dispose();
|
||||||
|
|
||||||
|
systemStream?.Dispose();
|
||||||
|
graphicsStream?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -454,7 +494,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a resource data writer.
|
/// Represents a resource data writer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ResourceDataWriter : DataWriter
|
public class ResourceDataWriter : DataWriter, IDisposable
|
||||||
{
|
{
|
||||||
private const long SYSTEM_BASE = 0x50000000;
|
private const long SYSTEM_BASE = 0x50000000;
|
||||||
private const long GRAPHICS_BASE = 0x60000000;
|
private const long GRAPHICS_BASE = 0x60000000;
|
||||||
@ -596,7 +636,13 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
base.Dispose();
|
||||||
|
|
||||||
|
systemStream?.Dispose();
|
||||||
|
graphicsStream?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,12 +218,25 @@ namespace CodeWalker.GameFiles
|
|||||||
public uint Unknown_4Ch { get; set; } // 0x00000000
|
public uint Unknown_4Ch { get; set; } // 0x00000000
|
||||||
|
|
||||||
// reference data
|
// reference data
|
||||||
public string Name { get; set; }
|
public string Name { get => name; set
|
||||||
public uint NameHash { get; set; }
|
{
|
||||||
|
name = value;
|
||||||
|
nameHash = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public uint NameHash { get
|
||||||
|
{
|
||||||
|
if (nameHash == 0)
|
||||||
|
{
|
||||||
|
nameHash = JenkHash.GenHashLower(name);
|
||||||
|
}
|
||||||
|
return nameHash;
|
||||||
|
}
|
||||||
|
set => nameHash = value; }
|
||||||
|
|
||||||
private string_r NameBlock = null;
|
private string_r NameBlock = null;
|
||||||
|
private uint nameHash;
|
||||||
|
private string name;
|
||||||
|
|
||||||
public TextureUsage Usage
|
public TextureUsage Usage
|
||||||
{
|
{
|
||||||
@ -281,11 +294,6 @@ namespace CodeWalker.GameFiles
|
|||||||
this.NamePointer // offset
|
this.NamePointer // offset
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Name))
|
|
||||||
{
|
|
||||||
NameHash = JenkHash.GenHash(Name.ToLowerInvariant());
|
|
||||||
}
|
|
||||||
|
|
||||||
//switch (Unknown_32h)
|
//switch (Unknown_32h)
|
||||||
//{
|
//{
|
||||||
// case 0x20:
|
// case 0x20:
|
||||||
@ -405,7 +413,6 @@ namespace CodeWalker.GameFiles
|
|||||||
public virtual void ReadXml(XmlNode node, string ddsfolder)
|
public virtual void ReadXml(XmlNode node, string ddsfolder)
|
||||||
{
|
{
|
||||||
Name = Xml.GetChildInnerText(node, "Name");
|
Name = Xml.GetChildInnerText(node, "Name");
|
||||||
NameHash = JenkHash.GenHash(Name?.ToLowerInvariant());
|
|
||||||
Unknown_32h = (ushort)Xml.GetChildUIntAttribute(node, "Unk32", "value");
|
Unknown_32h = (ushort)Xml.GetChildUIntAttribute(node, "Unk32", "value");
|
||||||
Usage = Xml.GetChildEnumInnerText<TextureUsage>(node, "Usage");
|
Usage = Xml.GetChildEnumInnerText<TextureUsage>(node, "Usage");
|
||||||
UsageFlags = Xml.GetChildEnumInnerText<TextureUsageFlags>(node, "UsageFlags");
|
UsageFlags = Xml.GetChildEnumInnerText<TextureUsageFlags>(node, "UsageFlags");
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
using System;
|
using Microsoft.IO;
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using System.IO.Pipes;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
@ -13,7 +20,24 @@ namespace CodeWalker.GameFiles
|
|||||||
public class RpfFile
|
public class RpfFile
|
||||||
{
|
{
|
||||||
public string Name { get; set; } //name of this RPF file/package
|
public string Name { get; set; } //name of this RPF file/package
|
||||||
public string NameLower { get; set; }
|
|
||||||
|
|
||||||
|
private string _nameLower;
|
||||||
|
public string NameLower
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_nameLower == null)
|
||||||
|
{
|
||||||
|
_nameLower = Name.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
return _nameLower;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_nameLower = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
public string Path { get; set; } //path within the RPF structure
|
public string Path { get; set; } //path within the RPF structure
|
||||||
public string FilePath { get; set; } //full file path of the RPF
|
public string FilePath { get; set; } //full file path of the RPF
|
||||||
public long FileSize { get; set; }
|
public long FileSize { get; set; }
|
||||||
@ -61,7 +85,6 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
FileInfo fi = new FileInfo(fpath);
|
FileInfo fi = new FileInfo(fpath);
|
||||||
Name = fi.Name;
|
Name = fi.Name;
|
||||||
NameLower = Name.ToLowerInvariant();
|
|
||||||
Path = relpath.ToLowerInvariant();
|
Path = relpath.ToLowerInvariant();
|
||||||
FilePath = fpath;
|
FilePath = fpath;
|
||||||
FileSize = fi.Length;
|
FileSize = fi.Length;
|
||||||
@ -69,7 +92,6 @@ namespace CodeWalker.GameFiles
|
|||||||
public RpfFile(string name, string path, long filesize) //for a child RPF
|
public RpfFile(string name, string path, long filesize) //for a child RPF
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
NameLower = Name.ToLowerInvariant();
|
|
||||||
Path = path.ToLowerInvariant();
|
Path = path.ToLowerInvariant();
|
||||||
FilePath = path;
|
FilePath = path;
|
||||||
FileSize = filesize;
|
FileSize = filesize;
|
||||||
@ -147,8 +169,11 @@ namespace CodeWalker.GameFiles
|
|||||||
throw new Exception("Invalid Resource - not GTAV!");
|
throw new Exception("Invalid Resource - not GTAV!");
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] entriesdata = br.ReadBytes((int)EntryCount * 16); //4x uints each
|
byte[] entriesdata = ArrayPool<byte>.Shared.Rent((int)EntryCount * 16);
|
||||||
byte[] namesdata = br.ReadBytes((int)NamesLength);
|
byte[] namesdata = ArrayPool<byte>.Shared.Rent((int)NamesLength);
|
||||||
|
|
||||||
|
br.BaseStream.Read(entriesdata, 0, (int)EntryCount * 16);
|
||||||
|
br.BaseStream.Read(namesdata, 0, (int)NamesLength);
|
||||||
|
|
||||||
switch (Encryption)
|
switch (Encryption)
|
||||||
{
|
{
|
||||||
@ -156,25 +181,25 @@ namespace CodeWalker.GameFiles
|
|||||||
case RpfEncryption.OPEN: //OpenIV style RPF with unencrypted TOC
|
case RpfEncryption.OPEN: //OpenIV style RPF with unencrypted TOC
|
||||||
break;
|
break;
|
||||||
case RpfEncryption.AES:
|
case RpfEncryption.AES:
|
||||||
entriesdata = GTACrypto.DecryptAES(entriesdata);
|
GTACrypto.DecryptAES(entriesdata, (int)EntryCount * 16);
|
||||||
namesdata = GTACrypto.DecryptAES(namesdata);
|
GTACrypto.DecryptAES(namesdata, (int)NamesLength);
|
||||||
|
|
||||||
IsAESEncrypted = true;
|
IsAESEncrypted = true;
|
||||||
break;
|
break;
|
||||||
case RpfEncryption.NG:
|
case RpfEncryption.NG:
|
||||||
entriesdata = GTACrypto.DecryptNG(entriesdata, Name, (uint)FileSize);
|
default:
|
||||||
namesdata = GTACrypto.DecryptNG(namesdata, Name, (uint)FileSize);
|
GTACrypto.DecryptNG(entriesdata, Name, (uint)FileSize, 0, (int)EntryCount * 16);
|
||||||
|
GTACrypto.DecryptNG(namesdata, Name, (uint)FileSize, 0, (int)NamesLength);
|
||||||
|
|
||||||
IsNGEncrypted = true;
|
IsNGEncrypted = true;
|
||||||
break;
|
break;
|
||||||
default: //unknown encryption type? assume NG.. never seems to get here
|
|
||||||
entriesdata = GTACrypto.DecryptNG(entriesdata, Name, (uint)FileSize);
|
|
||||||
namesdata = GTACrypto.DecryptNG(namesdata, Name, (uint)FileSize);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using var entriesrdr = new DataReader(new MemoryStream(entriesdata, 0, (int)EntryCount * 16));
|
||||||
|
using var namesrdr = new DataReader(new MemoryStream(namesdata, 0, (int)NamesLength));
|
||||||
|
|
||||||
var entriesrdr = new DataReader(new MemoryStream(entriesdata));
|
|
||||||
var namesrdr = new DataReader(new MemoryStream(namesdata));
|
AllEntries = new List<RpfEntry>((int)EntryCount);
|
||||||
AllEntries = new List<RpfEntry>();
|
|
||||||
TotalFileCount = 0;
|
TotalFileCount = 0;
|
||||||
TotalFolderCount = 0;
|
TotalFolderCount = 0;
|
||||||
TotalResourceCount = 0;
|
TotalResourceCount = 0;
|
||||||
@ -213,28 +238,24 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
e.Read(entriesrdr);
|
e.Read(entriesrdr);
|
||||||
|
|
||||||
namesrdr.Position = e.NameOffset;
|
|
||||||
e.Name = namesrdr.ReadString();
|
|
||||||
if (e.Name.Length > 256)
|
|
||||||
{
|
|
||||||
// long names can freeze the RPFExplorer
|
|
||||||
e.Name = e.Name.Substring(0, 256);
|
|
||||||
}
|
|
||||||
e.NameLower = e.Name.ToLowerInvariant();
|
|
||||||
|
|
||||||
if ((e is RpfFileEntry) && string.IsNullOrEmpty(e.Name))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
if ((e is RpfResourceFileEntry))// && string.IsNullOrEmpty(e.Name))
|
|
||||||
{
|
|
||||||
var rfe = e as RpfResourceFileEntry;
|
|
||||||
rfe.IsEncrypted = rfe.NameLower.EndsWith(".ysc");//any other way to know..?
|
|
||||||
}
|
|
||||||
|
|
||||||
AllEntries.Add(e);
|
AllEntries.Add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach(var entry in AllEntries)
|
||||||
|
{
|
||||||
|
namesrdr.Position = entry.NameOffset;
|
||||||
|
entry.Name = namesrdr.ReadString(256);
|
||||||
|
if (entry.Name.Length > 256)
|
||||||
|
{
|
||||||
|
// long names can freeze the RPFExplorer
|
||||||
|
entry.Name = entry.Name.Substring(0, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry is RpfResourceFileEntry rfe)// && string.IsNullOrEmpty(e.Name))
|
||||||
|
{
|
||||||
|
rfe.IsEncrypted = rfe.Name.EndsWith(".ysc", StringComparison.OrdinalIgnoreCase);//any other way to know..?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Root = (RpfDirectoryEntry)AllEntries[0];
|
Root = (RpfDirectoryEntry)AllEntries[0];
|
||||||
Root.Path = Path.ToLowerInvariant();// + "\\" + Root.Name;
|
Root.Path = Path.ToLowerInvariant();// + "\\" + Root.Name;
|
||||||
@ -251,17 +272,16 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
RpfEntry e = AllEntries[i];
|
RpfEntry e = AllEntries[i];
|
||||||
e.Parent = item;
|
e.Parent = item;
|
||||||
if (e is RpfDirectoryEntry)
|
if (e is RpfDirectoryEntry rde)
|
||||||
{
|
{
|
||||||
RpfDirectoryEntry rde = e as RpfDirectoryEntry;
|
rde.Path = item.Path + "\\" + rde.Name;
|
||||||
rde.Path = item.Path + "\\" + rde.NameLower;
|
|
||||||
item.Directories.Add(rde);
|
item.Directories.Add(rde);
|
||||||
stack.Push(rde);
|
stack.Push(rde);
|
||||||
}
|
}
|
||||||
else if (e is RpfFileEntry)
|
else if (e is RpfFileEntry)
|
||||||
{
|
{
|
||||||
RpfFileEntry rfe = e as RpfFileEntry;
|
RpfFileEntry rfe = e as RpfFileEntry;
|
||||||
rfe.Path = item.Path + "\\" + rfe.NameLower;
|
rfe.Path = item.Path + "\\" + rfe.Name;
|
||||||
item.Files.Add(rfe);
|
item.Files.Add(rfe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,32 +290,41 @@ namespace CodeWalker.GameFiles
|
|||||||
br.BaseStream.Position = StartPos;
|
br.BaseStream.Position = StartPos;
|
||||||
|
|
||||||
CurrentFileReader = null;
|
CurrentFileReader = null;
|
||||||
|
ArrayPool<byte>.Shared.Return(entriesdata);
|
||||||
|
ArrayPool<byte>.Shared.Return(namesdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void ScanStructure(Action<string> updateStatus, Action<string> errorLog)
|
public bool ScanStructure(Action<string> updateStatus, Action<string> errorLog)
|
||||||
{
|
|
||||||
using (BinaryReader br = new BinaryReader(File.OpenRead(FilePath)))
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using var fileStream = File.OpenRead(FilePath);
|
||||||
|
using var br = new BinaryReader(fileStream);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ScanStructure(br, updateStatus, errorLog);
|
return ScanStructure(br, updateStatus, errorLog);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LastError = ex.ToString();
|
LastError = ex.ToString();
|
||||||
LastException = ex;
|
LastException = ex;
|
||||||
errorLog(FilePath + ": " + LastError);
|
errorLog?.Invoke(FilePath + ": " + LastError);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
private bool ScanStructure(BinaryReader br, Action<string> updateStatus, Action<string> errorLog)
|
||||||
private void ScanStructure(BinaryReader br, Action<string> updateStatus, Action<string> errorLog)
|
{
|
||||||
|
if (FilePath == "update\\update.rpf\\dlc_patch\\patchday1ng\\x64\\patch\\data\\lang\\chinesesimp.rpf") return false;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
ReadHeader(br);
|
ReadHeader(br);
|
||||||
|
} catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
GrandTotalRpfCount = 1; //count this file..
|
GrandTotalRpfCount = 1; //count this file..
|
||||||
GrandTotalFileCount = 1; //start with this one.
|
GrandTotalFileCount = 1; //start with this one.
|
||||||
@ -311,13 +340,10 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (entry is RpfBinaryFileEntry)
|
if (entry is RpfBinaryFileEntry binentry)
|
||||||
{
|
{
|
||||||
RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry;
|
|
||||||
|
|
||||||
//search all the sub resources for YSC files. (recurse!)
|
//search all the sub resources for YSC files. (recurse!)
|
||||||
string lname = binentry.NameLower;
|
if (binentry.Name.EndsWith(".rpf", StringComparison.OrdinalIgnoreCase) && binentry.Path.Length < 5000) // a long path is most likely an attempt to crash CW, so skip it
|
||||||
if (lname.EndsWith(".rpf") && binentry.Path.Length < 5000) // a long path is most likely an attempt to crash CW, so skip it
|
|
||||||
{
|
{
|
||||||
br.BaseStream.Position = StartPos + ((long)binentry.FileOffset * 512);
|
br.BaseStream.Position = StartPos + ((long)binentry.FileOffset * 512);
|
||||||
|
|
||||||
@ -327,8 +353,8 @@ namespace CodeWalker.GameFiles
|
|||||||
subfile.Parent = this;
|
subfile.Parent = this;
|
||||||
subfile.ParentFileEntry = binentry;
|
subfile.ParentFileEntry = binentry;
|
||||||
|
|
||||||
subfile.ScanStructure(br, updateStatus, errorLog);
|
if (subfile.ScanStructure(br, updateStatus, errorLog))
|
||||||
|
{
|
||||||
GrandTotalRpfCount += subfile.GrandTotalRpfCount;
|
GrandTotalRpfCount += subfile.GrandTotalRpfCount;
|
||||||
GrandTotalFileCount += subfile.GrandTotalFileCount;
|
GrandTotalFileCount += subfile.GrandTotalFileCount;
|
||||||
GrandTotalFolderCount += subfile.GrandTotalFolderCount;
|
GrandTotalFolderCount += subfile.GrandTotalFolderCount;
|
||||||
@ -337,6 +363,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
Children.Add(subfile);
|
Children.Add(subfile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//binary file that's not an rpf...
|
//binary file that's not an rpf...
|
||||||
@ -359,7 +386,7 @@ namespace CodeWalker.GameFiles
|
|||||||
errorLog?.Invoke(entry.Path + ": " + ex.ToString());
|
errorLog?.Invoke(entry.Path + ": " + ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -437,26 +464,25 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
br.Read(tbytes, 0, (int)totlen);
|
br.Read(tbytes, 0, (int)totlen);
|
||||||
|
|
||||||
byte[] decr;
|
|
||||||
if (IsAESEncrypted)
|
if (IsAESEncrypted)
|
||||||
{
|
{
|
||||||
decr = GTACrypto.DecryptAES(tbytes);
|
GTACrypto.DecryptAES(tbytes);
|
||||||
|
|
||||||
//special case! probable duplicate pilot_school.ysc
|
//special case! probable duplicate pilot_school.ysc
|
||||||
ofpath = outputfolder + "\\" + Name + "___" + resentry.Name;
|
ofpath = outputfolder + "\\" + Name + "___" + resentry.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
decr = GTACrypto.DecryptNG(tbytes, resentry.Name, resentry.FileSize);
|
GTACrypto.DecryptNG(tbytes, resentry.Name, resentry.FileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MemoryStream ms = new MemoryStream(decr);
|
MemoryStream ms = new MemoryStream(tbytes);
|
||||||
DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress);
|
DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress);
|
||||||
|
|
||||||
MemoryStream outstr = new MemoryStream();
|
MemoryStream outstr = recyclableMemoryStreamManager.GetStream();
|
||||||
ds.CopyTo(outstr);
|
ds.CopyTo(outstr);
|
||||||
byte[] deflated = outstr.GetBuffer();
|
byte[] deflated = outstr.GetBuffer();
|
||||||
byte[] outbuf = new byte[outstr.Length]; //need to copy to the right size buffer for File.WriteAllBytes().
|
byte[] outbuf = new byte[outstr.Length]; //need to copy to the right size buffer for File.WriteAllBytes().
|
||||||
@ -498,7 +524,33 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//public Stream ExtractFileStream(RpfFileEntry entry)
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// using (BinaryReader br = new BinaryReader(File.OpenRead(GetPhysicalFilePath())))
|
||||||
|
// {
|
||||||
|
// if (entry is RpfBinaryFileEntry binaryFileEntry)
|
||||||
|
// {
|
||||||
|
// return ExtractFileBinary(binaryFileEntry, br);
|
||||||
|
// }
|
||||||
|
// else if (entry is RpfResourceFileEntry resourceFileEntry)
|
||||||
|
// {
|
||||||
|
// return ExtractFileResource(resourceFileEntry, br);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// LastError = ex.ToString();
|
||||||
|
// LastException = ex;
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
public byte[] ExtractFile(RpfFileEntry entry)
|
public byte[] ExtractFile(RpfFileEntry entry)
|
||||||
{
|
{
|
||||||
@ -506,13 +558,13 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
using (BinaryReader br = new BinaryReader(File.OpenRead(GetPhysicalFilePath())))
|
using (BinaryReader br = new BinaryReader(File.OpenRead(GetPhysicalFilePath())))
|
||||||
{
|
{
|
||||||
if (entry is RpfBinaryFileEntry)
|
if (entry is RpfBinaryFileEntry binaryFileEntry)
|
||||||
{
|
{
|
||||||
return ExtractFileBinary(entry as RpfBinaryFileEntry, br);
|
return ExtractFileBinary(binaryFileEntry, br);
|
||||||
}
|
}
|
||||||
else if (entry is RpfResourceFileEntry)
|
else if (entry is RpfResourceFileEntry resourceFileEntry)
|
||||||
{
|
{
|
||||||
return ExtractFileResource(entry as RpfResourceFileEntry, br);
|
return ExtractFileResource(resourceFileEntry, br);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -543,27 +595,25 @@ namespace CodeWalker.GameFiles
|
|||||||
br.BaseStream.Position += offset;
|
br.BaseStream.Position += offset;
|
||||||
br.Read(tbytes, 0, (int)totlen);
|
br.Read(tbytes, 0, (int)totlen);
|
||||||
|
|
||||||
byte[] decr = tbytes;
|
|
||||||
|
|
||||||
if (entry.IsEncrypted)
|
if (entry.IsEncrypted)
|
||||||
{
|
{
|
||||||
if (IsAESEncrypted)
|
if (IsAESEncrypted)
|
||||||
{
|
{
|
||||||
decr = GTACrypto.DecryptAES(tbytes);
|
GTACrypto.DecryptAES(tbytes);
|
||||||
}
|
}
|
||||||
else //if (IsNGEncrypted) //assume the archive is set to NG encryption if not AES... (comment: fix for openIV modded files)
|
else //if (IsNGEncrypted) //assume the archive is set to NG encryption if not AES... (comment: fix for openIV modded files)
|
||||||
{
|
{
|
||||||
decr = GTACrypto.DecryptNG(tbytes, entry.Name, entry.FileUncompressedSize);
|
GTACrypto.DecryptNG(tbytes, entry.Name, entry.FileUncompressedSize);
|
||||||
}
|
}
|
||||||
//else
|
//else
|
||||||
//{ }
|
//{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] defl = decr;
|
byte[] defl = tbytes;
|
||||||
|
|
||||||
if (entry.FileSize > 0) //apparently this means it's compressed
|
if (entry.FileSize > 0) //apparently this means it's compressed
|
||||||
{
|
{
|
||||||
defl = DecompressBytes(decr);
|
defl = DecompressBytes(tbytes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -596,23 +646,21 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
br.Read(tbytes, 0, (int)totlen);
|
br.Read(tbytes, 0, (int)totlen);
|
||||||
|
|
||||||
byte[] decr = tbytes;
|
|
||||||
if (entry.IsEncrypted)
|
if (entry.IsEncrypted)
|
||||||
{
|
{
|
||||||
if (IsAESEncrypted)
|
if (IsAESEncrypted)
|
||||||
{
|
{
|
||||||
decr = GTACrypto.DecryptAES(tbytes);
|
GTACrypto.DecryptAES(tbytes);
|
||||||
}
|
}
|
||||||
else //if (IsNGEncrypted) //assume the archive is set to NG encryption if not AES... (comment: fix for openIV modded files)
|
else //if (IsNGEncrypted) //assume the archive is set to NG encryption if not AES... (comment: fix for openIV modded files)
|
||||||
{
|
{
|
||||||
decr = GTACrypto.DecryptNG(tbytes, entry.Name, entry.FileSize);
|
GTACrypto.DecryptNG(tbytes, entry.Name, entry.FileSize);
|
||||||
}
|
}
|
||||||
//else
|
//else
|
||||||
//{ }
|
//{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] deflated = DecompressBytes(decr);
|
byte[] deflated = DecompressBytes(tbytes);
|
||||||
|
|
||||||
byte[] data = null;
|
byte[] data = null;
|
||||||
|
|
||||||
@ -623,7 +671,7 @@ namespace CodeWalker.GameFiles
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
entry.FileSize -= offset;
|
entry.FileSize -= offset;
|
||||||
data = decr;
|
data = tbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -665,6 +713,22 @@ namespace CodeWalker.GameFiles
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T GetFile<T>(RpfEntry e, Stream data) where T : class, PackedFileStream, new()
|
||||||
|
{
|
||||||
|
T file = null;
|
||||||
|
RpfFileEntry entry = e as RpfFileEntry;
|
||||||
|
if ((data != null))
|
||||||
|
{
|
||||||
|
if (entry == null)
|
||||||
|
{
|
||||||
|
entry = CreateResourceFileEntry(data, 0);
|
||||||
|
}
|
||||||
|
file = new T();
|
||||||
|
file.Load(data, entry);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static T GetResourceFile<T>(byte[] data) where T : class, PackedFile, new()
|
public static T GetResourceFile<T>(byte[] data) where T : class, PackedFile, new()
|
||||||
@ -679,6 +743,36 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void LoadResourceFile<T>(T file, Stream data, uint ver) where T : class, PackedFileStream
|
||||||
|
{
|
||||||
|
//direct load from a raw, compressed resource file (openIV-compatible format)
|
||||||
|
|
||||||
|
RpfResourceFileEntry resentry = CreateResourceFileEntry(data, ver);
|
||||||
|
|
||||||
|
if (file is GameFile)
|
||||||
|
{
|
||||||
|
GameFile gfile = file as GameFile;
|
||||||
|
|
||||||
|
var oldresentry = gfile.RpfFileEntry as RpfResourceFileEntry;
|
||||||
|
if (oldresentry != null) //update the existing entry with the new one
|
||||||
|
{
|
||||||
|
oldresentry.SystemFlags = resentry.SystemFlags;
|
||||||
|
oldresentry.GraphicsFlags = resentry.GraphicsFlags;
|
||||||
|
resentry.Name = oldresentry.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gfile.RpfFileEntry = resentry; //just stick it in there for later...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = ResourceBuilder.Decompress(data);
|
||||||
|
|
||||||
|
file.Load(data, resentry);
|
||||||
|
}
|
||||||
|
|
||||||
public static void LoadResourceFile<T>(T file, byte[] data, uint ver) where T : class, PackedFile
|
public static void LoadResourceFile<T>(T file, byte[] data, uint ver) where T : class, PackedFile
|
||||||
{
|
{
|
||||||
//direct load from a raw, compressed resource file (openIV-compatible format)
|
//direct load from a raw, compressed resource file (openIV-compatible format)
|
||||||
@ -695,9 +789,6 @@ namespace CodeWalker.GameFiles
|
|||||||
oldresentry.SystemFlags = resentry.SystemFlags;
|
oldresentry.SystemFlags = resentry.SystemFlags;
|
||||||
oldresentry.GraphicsFlags = resentry.GraphicsFlags;
|
oldresentry.GraphicsFlags = resentry.GraphicsFlags;
|
||||||
resentry.Name = oldresentry.Name;
|
resentry.Name = oldresentry.Name;
|
||||||
resentry.NameHash = oldresentry.NameHash;
|
|
||||||
resentry.NameLower = oldresentry.NameLower;
|
|
||||||
resentry.ShortNameHash = oldresentry.ShortNameHash;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -710,6 +801,45 @@ namespace CodeWalker.GameFiles
|
|||||||
file.Load(data, resentry);
|
file.Load(data, resentry);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RpfResourceFileEntry CreateResourceFileEntry(Stream stream, uint ver, uint? header = null)
|
||||||
|
{
|
||||||
|
var resentry = new RpfResourceFileEntry();
|
||||||
|
|
||||||
|
using var reader = new BinaryReader(stream, Encoding.UTF8, true);
|
||||||
|
|
||||||
|
//hopefully this data has an RSC7 header...
|
||||||
|
uint rsc7 = header ?? reader.ReadUInt32(); // BitConverter.ToUInt32(data, 0);
|
||||||
|
if (rsc7 == 0x37435352) //RSC7 header present!
|
||||||
|
{
|
||||||
|
int version = reader.ReadInt32(); // BitConverter.ToInt32(data, 4);//use this instead of what was given...
|
||||||
|
resentry.SystemFlags = reader.ReadUInt32();// BitConverter.ToUInt32(data, 8);
|
||||||
|
resentry.GraphicsFlags = reader.ReadUInt32(); //BitConverter.ToUInt32(data, 12);
|
||||||
|
//if (stream.Length > 16)
|
||||||
|
//{
|
||||||
|
// int newlen = stream.Length - 16; //trim the header from the data passed to the next step.
|
||||||
|
// byte[] newdata = new byte[newlen];
|
||||||
|
// Buffer.BlockCopy(data, 16, newdata, 0, newlen);
|
||||||
|
// data = newdata;
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// data = null; //shouldn't happen... empty..
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//direct load from file without the rpf header..
|
||||||
|
//assume it's in resource meta format
|
||||||
|
resentry.SystemFlags = RpfResourceFileEntry.GetFlagsFromSize((int)stream.Length, 0);
|
||||||
|
resentry.GraphicsFlags = RpfResourceFileEntry.GetFlagsFromSize(0, ver);
|
||||||
|
}
|
||||||
|
|
||||||
|
resentry.Name = "";
|
||||||
|
|
||||||
|
return resentry;
|
||||||
|
}
|
||||||
|
|
||||||
public static RpfResourceFileEntry CreateResourceFileEntry(ref byte[] data, uint ver)
|
public static RpfResourceFileEntry CreateResourceFileEntry(ref byte[] data, uint ver)
|
||||||
{
|
{
|
||||||
var resentry = new RpfResourceFileEntry();
|
var resentry = new RpfResourceFileEntry();
|
||||||
@ -742,7 +872,6 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
resentry.Name = "";
|
resentry.Name = "";
|
||||||
resentry.NameLower = "";
|
|
||||||
|
|
||||||
return resentry;
|
return resentry;
|
||||||
}
|
}
|
||||||
@ -896,14 +1025,14 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static RecyclableMemoryStreamManager recyclableMemoryStreamManager = new RecyclableMemoryStreamManager();
|
||||||
public byte[] DecompressBytes(byte[] bytes)
|
public byte[] DecompressBytes(byte[] bytes)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (DeflateStream ds = new DeflateStream(new MemoryStream(bytes), CompressionMode.Decompress))
|
using (DeflateStream ds = new DeflateStream(new MemoryStream(bytes), CompressionMode.Decompress))
|
||||||
{
|
{
|
||||||
using (var outstr = new MemoryStream())
|
using (var outstr = recyclableMemoryStreamManager.GetStream("DecompressBytes", bytes.Length))
|
||||||
{
|
{
|
||||||
ds.CopyTo(outstr);
|
ds.CopyTo(outstr);
|
||||||
byte[] deflated = outstr.GetBuffer();
|
byte[] deflated = outstr.GetBuffer();
|
||||||
@ -929,7 +1058,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
public static byte[] CompressBytes(byte[] data) //TODO: refactor this with ResourceBuilder.Compress/Decompress
|
public static byte[] CompressBytes(byte[] data) //TODO: refactor this with ResourceBuilder.Compress/Decompress
|
||||||
{
|
{
|
||||||
using (MemoryStream ms = new MemoryStream())
|
using (MemoryStream ms = recyclableMemoryStreamManager.GetStream("CompressBytes", data.Length))
|
||||||
{
|
{
|
||||||
using (var ds = new DeflateStream(ms, CompressionMode.Compress, true))
|
using (var ds = new DeflateStream(ms, CompressionMode.Compress, true))
|
||||||
{
|
{
|
||||||
@ -1023,7 +1152,6 @@ namespace CodeWalker.GameFiles
|
|||||||
Root = new RpfDirectoryEntry();
|
Root = new RpfDirectoryEntry();
|
||||||
Root.File = this;
|
Root.File = this;
|
||||||
Root.Name = string.Empty;
|
Root.Name = string.Empty;
|
||||||
Root.NameLower = string.Empty;
|
|
||||||
Root.Path = Path.ToLowerInvariant();
|
Root.Path = Path.ToLowerInvariant();
|
||||||
}
|
}
|
||||||
if (Children == null)
|
if (Children == null)
|
||||||
@ -1397,7 +1525,7 @@ namespace CodeWalker.GameFiles
|
|||||||
file.Path = dir.Path + "\\" + file.NameLower;
|
file.Path = dir.Path + "\\" + file.NameLower;
|
||||||
|
|
||||||
RpfBinaryFileEntry binf = file as RpfBinaryFileEntry;
|
RpfBinaryFileEntry binf = file as RpfBinaryFileEntry;
|
||||||
if ((binf != null) && file.NameLower.EndsWith(".rpf"))
|
if ((binf != null) && file.Name.EndsWith(".rpf", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
RpfFile childrpf = FindChildArchive(binf);
|
RpfFile childrpf = FindChildArchive(binf);
|
||||||
if (childrpf != null)
|
if (childrpf != null)
|
||||||
@ -1413,7 +1541,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
foreach (var subdir in dir.Directories)
|
foreach (var subdir in dir.Directories)
|
||||||
{
|
{
|
||||||
subdir.Path = dir.Path + "\\" + subdir.NameLower;
|
subdir.Path = dir.Path + "\\" + subdir.Name;
|
||||||
UpdatePaths(subdir);
|
UpdatePaths(subdir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1531,9 +1659,6 @@ namespace CodeWalker.GameFiles
|
|||||||
entry.File = parent;
|
entry.File = parent;
|
||||||
entry.Path = rpath;
|
entry.Path = rpath;
|
||||||
entry.Name = name;
|
entry.Name = name;
|
||||||
entry.NameLower = namel;
|
|
||||||
entry.NameHash = JenkHash.GenHash(name);
|
|
||||||
entry.ShortNameHash = JenkHash.GenHash(entry.GetShortNameLower());
|
|
||||||
|
|
||||||
dir.Files.Add(entry);
|
dir.Files.Add(entry);
|
||||||
|
|
||||||
@ -1574,13 +1699,10 @@ namespace CodeWalker.GameFiles
|
|||||||
entry.File = parent;
|
entry.File = parent;
|
||||||
entry.Path = rpath;
|
entry.Path = rpath;
|
||||||
entry.Name = name;
|
entry.Name = name;
|
||||||
entry.NameLower = namel;
|
|
||||||
entry.NameHash = JenkHash.GenHash(name);
|
|
||||||
entry.ShortNameHash = JenkHash.GenHash(entry.GetShortNameLower());
|
|
||||||
|
|
||||||
foreach (var exdir in dir.Directories)
|
foreach (var exdir in dir.Directories)
|
||||||
{
|
{
|
||||||
if (exdir.NameLower == entry.NameLower)
|
if (exdir.Name.Equals(entry.Name, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
throw new Exception("RPF Directory \"" + entry.Name + "\" already exists!");
|
throw new Exception("RPF Directory \"" + entry.Name + "\" already exists!");
|
||||||
}
|
}
|
||||||
@ -1600,14 +1722,61 @@ namespace CodeWalker.GameFiles
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RpfFileEntry CreateFileEntry(string name, string path, Stream data)
|
||||||
|
{
|
||||||
|
//this should only really be used when loading a file from the filesystem.
|
||||||
|
RpfFileEntry e;
|
||||||
|
using var reader = new BinaryReader(data, Encoding.UTF8, true);
|
||||||
|
|
||||||
|
uint rsc7 = (reader.BaseStream.Length > 4) ? reader.ReadUInt32() : 0;
|
||||||
|
if (rsc7 == 0x37435352) //RSC7 header present! create RpfResourceFileEntry and decompress data...
|
||||||
|
{
|
||||||
|
e = RpfFile.CreateResourceFileEntry(data, 0);//"version" should be loadable from the header in the data..
|
||||||
|
data = ResourceBuilder.Decompress(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var be = new RpfBinaryFileEntry
|
||||||
|
{
|
||||||
|
FileSize = (uint)(data?.Length ?? 0),
|
||||||
|
FileUncompressedSize = (uint)(data?.Length ?? 0),
|
||||||
|
};
|
||||||
|
e = be;
|
||||||
|
}
|
||||||
|
e.Name = name;
|
||||||
|
e.Path = path;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RpfFileEntry CreateFileEntry(string name, string path, ref byte[] data)
|
||||||
|
{
|
||||||
|
//this should only really be used when loading a file from the filesystem.
|
||||||
|
RpfFileEntry e = null;
|
||||||
|
uint rsc7 = (data?.Length > 4) ? BitConverter.ToUInt32(data, 0) : 0;
|
||||||
|
if (rsc7 == 0x37435352) //RSC7 header present! create RpfResourceFileEntry and decompress data...
|
||||||
|
{
|
||||||
|
e = RpfFile.CreateResourceFileEntry(ref data, 0);//"version" should be loadable from the header in the data..
|
||||||
|
data = ResourceBuilder.Decompress(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var be = new RpfBinaryFileEntry();
|
||||||
|
be.FileSize = (uint)data?.Length;
|
||||||
|
be.FileUncompressedSize = be.FileSize;
|
||||||
|
e = be;
|
||||||
|
}
|
||||||
|
e.Name = name;
|
||||||
|
e.Path = path;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
public static RpfFileEntry CreateFile(RpfDirectoryEntry dir, string name, byte[] data, bool overwrite = true)
|
public static RpfFileEntry CreateFile(RpfDirectoryEntry dir, string name, byte[] data, bool overwrite = true)
|
||||||
{
|
{
|
||||||
string namel = name.ToLowerInvariant();
|
|
||||||
if (overwrite)
|
if (overwrite)
|
||||||
{
|
{
|
||||||
foreach (var exfile in dir.Files)
|
foreach (var exfile in dir.Files)
|
||||||
{
|
{
|
||||||
if (exfile.NameLower == namel)
|
if (exfile.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
//file already exists. delete the existing one first!
|
//file already exists. delete the existing one first!
|
||||||
//this should probably be optimised to just replace the existing one...
|
//this should probably be optimised to just replace the existing one...
|
||||||
@ -1621,6 +1790,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
RpfFile parent = dir.File;
|
RpfFile parent = dir.File;
|
||||||
string fpath = parent.GetPhysicalFilePath();
|
string fpath = parent.GetPhysicalFilePath();
|
||||||
|
string namel = name.ToLowerInvariant();
|
||||||
string rpath = dir.Path + "\\" + namel;
|
string rpath = dir.Path + "\\" + namel;
|
||||||
if (!File.Exists(fpath))
|
if (!File.Exists(fpath))
|
||||||
{
|
{
|
||||||
@ -1644,7 +1814,6 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
//RSC header is present... import as resource
|
//RSC header is present... import as resource
|
||||||
var rentry = new RpfResourceFileEntry();
|
var rentry = new RpfResourceFileEntry();
|
||||||
var version = BitConverter.ToUInt32(data, 4);
|
|
||||||
rentry.SystemFlags = BitConverter.ToUInt32(data, 8);
|
rentry.SystemFlags = BitConverter.ToUInt32(data, 8);
|
||||||
rentry.GraphicsFlags = BitConverter.ToUInt32(data, 12);
|
rentry.GraphicsFlags = BitConverter.ToUInt32(data, 12);
|
||||||
rentry.FileSize = len;
|
rentry.FileSize = len;
|
||||||
@ -1661,11 +1830,11 @@ namespace CodeWalker.GameFiles
|
|||||||
entry = rentry;
|
entry = rentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namel.EndsWith(".rpf") && (hdr == 0x52504637)) //'RPF7'
|
if ((hdr == 0x52504637) && name.EndsWith(".rpf", StringComparison.OrdinalIgnoreCase)) //'RPF7'
|
||||||
{
|
{
|
||||||
isrpf = true;
|
isrpf = true;
|
||||||
}
|
}
|
||||||
if (namel.EndsWith(".awc"))
|
if (name.EndsWith(".awc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
isawc = true;
|
isawc = true;
|
||||||
}
|
}
|
||||||
@ -1693,16 +1862,14 @@ namespace CodeWalker.GameFiles
|
|||||||
entry.File = parent;
|
entry.File = parent;
|
||||||
entry.Path = rpath;
|
entry.Path = rpath;
|
||||||
entry.Name = name;
|
entry.Name = name;
|
||||||
entry.NameLower = name.ToLowerInvariant();
|
entry.NameLower = namel;
|
||||||
entry.NameHash = JenkHash.GenHash(name);
|
|
||||||
entry.ShortNameHash = JenkHash.GenHash(entry.GetShortNameLower());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var exfile in dir.Files)
|
foreach (var exfile in dir.Files)
|
||||||
{
|
{
|
||||||
if (exfile.NameLower == entry.NameLower)
|
if (exfile.Name.Equals(entry.Name, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
throw new Exception("File \"" + entry.Name + "\" already exists!");
|
throw new Exception("File \"" + entry.Name + "\" already exists!");
|
||||||
}
|
}
|
||||||
@ -1715,8 +1882,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
using (var fstream = File.Open(fpath, FileMode.Open, FileAccess.ReadWrite))
|
using (var fstream = File.Open(fpath, FileMode.Open, FileAccess.ReadWrite))
|
||||||
{
|
{
|
||||||
using (var bw = new BinaryWriter(fstream))
|
using var bw = new BinaryWriter(fstream);
|
||||||
{
|
|
||||||
parent.InsertFileSpace(bw, entry);
|
parent.InsertFileSpace(bw, entry);
|
||||||
long bbeg = parent.StartPos + (entry.FileOffset * 512);
|
long bbeg = parent.StartPos + (entry.FileOffset * 512);
|
||||||
long bend = bbeg + (GetBlockCount(entry.GetFileSize()) * 512);
|
long bend = bbeg + (GetBlockCount(entry.GetFileSize()) * 512);
|
||||||
@ -1724,7 +1890,6 @@ namespace CodeWalker.GameFiles
|
|||||||
fstream.Write(data, 0, data.Length);
|
fstream.Write(data, 0, data.Length);
|
||||||
WritePadding(fstream, bend); //write 0's until the end of the block.
|
WritePadding(fstream, bend); //write 0's until the end of the block.
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (isrpf)
|
if (isrpf)
|
||||||
@ -1736,15 +1901,11 @@ namespace CodeWalker.GameFiles
|
|||||||
file.StartPos = parent.StartPos + (entry.FileOffset * 512);
|
file.StartPos = parent.StartPos + (entry.FileOffset * 512);
|
||||||
parent.Children.Add(file);
|
parent.Children.Add(file);
|
||||||
|
|
||||||
using (var fstream = File.OpenRead(fpath))
|
using var fstream = File.OpenRead(fpath);
|
||||||
{
|
using var br = new BinaryReader(fstream);
|
||||||
using (var br = new BinaryReader(fstream))
|
|
||||||
{
|
|
||||||
fstream.Position = file.StartPos;
|
fstream.Position = file.StartPos;
|
||||||
file.ScanStructure(br, null, null);
|
file.ScanStructure(br, null, null);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@ -1756,7 +1917,6 @@ namespace CodeWalker.GameFiles
|
|||||||
//(since all the paths are generated at runtime and not stored)
|
//(since all the paths are generated at runtime and not stored)
|
||||||
|
|
||||||
file.Name = newname;
|
file.Name = newname;
|
||||||
file.NameLower = newname.ToLowerInvariant();
|
|
||||||
file.Path = GetParentPath(file.Path) + newname;
|
file.Path = GetParentPath(file.Path) + newname;
|
||||||
file.FilePath = GetParentPath(file.FilePath) + newname;
|
file.FilePath = GetParentPath(file.FilePath) + newname;
|
||||||
|
|
||||||
@ -1772,13 +1932,9 @@ namespace CodeWalker.GameFiles
|
|||||||
string dirpath = GetParentPath(entry.Path);
|
string dirpath = GetParentPath(entry.Path);
|
||||||
|
|
||||||
entry.Name = newname;
|
entry.Name = newname;
|
||||||
entry.NameLower = newname.ToLowerInvariant();
|
|
||||||
entry.Path = dirpath + newname;
|
entry.Path = dirpath + newname;
|
||||||
|
|
||||||
string sname = entry.GetShortNameLower();
|
JenkIndex.EnsureLower(entry.ShortName);//could be anything... but it needs to be there
|
||||||
JenkIndex.Ensure(sname);//could be anything... but it needs to be there
|
|
||||||
entry.NameHash = JenkHash.GenHash(newname);
|
|
||||||
entry.ShortNameHash = JenkHash.GenHash(sname);
|
|
||||||
|
|
||||||
RpfFile parent = entry.File;
|
RpfFile parent = entry.File;
|
||||||
string fpath = parent.GetPhysicalFilePath();
|
string fpath = parent.GetPhysicalFilePath();
|
||||||
@ -2011,7 +2167,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
if (!dirpath.EndsWith("\\"))
|
if (!dirpath.EndsWith("\\"))
|
||||||
{
|
{
|
||||||
dirpath = dirpath + "\\";
|
dirpath += "\\";
|
||||||
}
|
}
|
||||||
return dirpath;
|
return dirpath;
|
||||||
}
|
}
|
||||||
@ -2038,16 +2194,89 @@ namespace CodeWalker.GameFiles
|
|||||||
public RpfFile File { get; set; }
|
public RpfFile File { get; set; }
|
||||||
public RpfDirectoryEntry Parent { get; set; }
|
public RpfDirectoryEntry Parent { get; set; }
|
||||||
|
|
||||||
public uint NameHash { get; set; }
|
public uint NameHash { get
|
||||||
public uint ShortNameHash { get; set; }
|
{
|
||||||
|
if (nameHash == 0 && !string.IsNullOrEmpty(Name))
|
||||||
|
{
|
||||||
|
nameHash = JenkHash.GenHashLower(Name);
|
||||||
|
}
|
||||||
|
return nameHash;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
nameHash = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public uint ShortNameHash { get
|
||||||
|
{
|
||||||
|
if (shortNameHash == 0 && !string.IsNullOrEmpty(ShortName))
|
||||||
|
{
|
||||||
|
shortNameHash = JenkHash.GenHashLower(ShortName);
|
||||||
|
}
|
||||||
|
return shortNameHash;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
shortNameHash = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public uint NameOffset { get; set; }
|
public uint NameOffset { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get => name; set
|
||||||
public string NameLower { get; set; }
|
{
|
||||||
|
if (name == value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
name = value;
|
||||||
|
nameLower = null;
|
||||||
|
nameHash = 0;
|
||||||
|
shortNameHash = 0;
|
||||||
|
shortName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string NameLower
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return nameLower ??= Name?.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
set { nameLower = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ShortName {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(shortName) && !string.IsNullOrEmpty(Name))
|
||||||
|
{
|
||||||
|
int ind = Name.LastIndexOf('.');
|
||||||
|
if (ind > 0)
|
||||||
|
{
|
||||||
|
shortName = Name.Substring(0, ind);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shortName = Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
shortName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
|
||||||
public uint H1; //first 2 header values from RPF table...
|
public uint H1; //first 2 header values from RPF table...
|
||||||
public uint H2;
|
public uint H2;
|
||||||
|
private string name;
|
||||||
|
private string nameLower;
|
||||||
|
private uint shortNameHash;
|
||||||
|
private uint nameHash;
|
||||||
|
private string shortName;
|
||||||
|
|
||||||
public abstract void Read(DataReader reader);
|
public abstract void Read(DataReader reader);
|
||||||
public abstract void Write(DataWriter writer);
|
public abstract void Write(DataWriter writer);
|
||||||
@ -2059,29 +2288,12 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public string GetShortName()
|
public string GetShortName()
|
||||||
{
|
{
|
||||||
int ind = Name.LastIndexOf('.');
|
return ShortName;
|
||||||
if (ind > 0)
|
|
||||||
{
|
|
||||||
return Name.Substring(0, ind);
|
|
||||||
}
|
|
||||||
return Name;
|
|
||||||
}
|
|
||||||
public string GetShortNameLower()
|
|
||||||
{
|
|
||||||
if (NameLower == null)
|
|
||||||
{
|
|
||||||
NameLower = Name.ToLowerInvariant();
|
|
||||||
}
|
|
||||||
int ind = NameLower.LastIndexOf('.');
|
|
||||||
if (ind > 0)
|
|
||||||
{
|
|
||||||
return NameLower.Substring(0, ind);
|
|
||||||
}
|
|
||||||
return NameLower;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RpfDirectoryEntry : RpfEntry
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||||
|
public class RpfDirectoryEntry : RpfEntry
|
||||||
{
|
{
|
||||||
public uint EntriesIndex { get; set; }
|
public uint EntriesIndex { get; set; }
|
||||||
public uint EntriesCount { get; set; }
|
public uint EntriesCount { get; set; }
|
||||||
@ -2113,7 +2325,8 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public abstract class RpfFileEntry : RpfEntry
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||||
|
public abstract class RpfFileEntry : RpfEntry
|
||||||
{
|
{
|
||||||
public uint FileOffset { get; set; }
|
public uint FileOffset { get; set; }
|
||||||
public uint FileSize { get; set; }
|
public uint FileSize { get; set; }
|
||||||
@ -2144,7 +2357,7 @@ namespace CodeWalker.GameFiles
|
|||||||
case 0: IsEncrypted = false; break;
|
case 0: IsEncrypted = false; break;
|
||||||
case 1: IsEncrypted = true; break;
|
case 1: IsEncrypted = true; break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Error in RPF7 file entry.");
|
throw new Exception($"Error in RPF7 file entry. {EncryptionType}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2516,14 +2729,15 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public override void Read(DataReader reader)
|
public override void Read(DataReader reader)
|
||||||
{
|
{
|
||||||
|
var buffer = ArrayPool<byte>.Shared.Rent(3);
|
||||||
NameOffset = reader.ReadUInt16();
|
NameOffset = reader.ReadUInt16();
|
||||||
|
|
||||||
var buf1 = reader.ReadBytes(3);
|
reader.ReadBytes(3, buffer);
|
||||||
FileSize = (uint)buf1[0] + (uint)(buf1[1] << 8) + (uint)(buf1[2] << 16);
|
FileSize = (uint)buffer[0] + (uint)(buffer[1] << 8) + (uint)(buffer[2] << 16);
|
||||||
|
|
||||||
var buf2 = reader.ReadBytes(3);
|
|
||||||
FileOffset = ((uint)buf2[0] + (uint)(buf2[1] << 8) + (uint)(buf2[2] << 16)) & 0x7FFFFF;
|
|
||||||
|
|
||||||
|
reader.ReadBytes(3, buffer);
|
||||||
|
FileOffset = ((uint)buffer[0] + (uint)(buffer[1] << 8) + (uint)(buffer[2] << 16)) & 0x7FFFFF;
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
SystemFlags = reader.ReadUInt32();
|
SystemFlags = reader.ReadUInt32();
|
||||||
GraphicsFlags = reader.ReadUInt32();
|
GraphicsFlags = reader.ReadUInt32();
|
||||||
|
|
||||||
@ -2751,6 +2965,10 @@ namespace CodeWalker.GameFiles
|
|||||||
void Load(byte[] data, RpfFileEntry entry);
|
void Load(byte[] data, RpfFileEntry entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface PackedFileStream : PackedFile
|
||||||
|
{
|
||||||
|
void Load(Stream stream, RpfFileEntry entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
using System;
|
using CodeWalker.Core.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -10,14 +13,19 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
public class RpfManager
|
public class RpfManager
|
||||||
{
|
{
|
||||||
|
private static RpfManager _instance = new RpfManager();
|
||||||
|
public static RpfManager GetInstance()
|
||||||
|
{
|
||||||
|
return _instance ??= new RpfManager();
|
||||||
|
}
|
||||||
//for caching and management of RPF file data.
|
//for caching and management of RPF file data.
|
||||||
|
|
||||||
public string Folder { get; private set; }
|
public string Folder { get; private set; }
|
||||||
public string[] ExcludePaths { get; set; }
|
public string[] ExcludePaths { get; set; }
|
||||||
public bool EnableMods { get; set; }
|
public bool EnableMods { get; set; }
|
||||||
public bool BuildExtendedJenkIndex { get; set; } = true;
|
public bool BuildExtendedJenkIndex { get; set; } = true;
|
||||||
public Action<string> UpdateStatus { get; private set; }
|
public event Action<string> UpdateStatus;
|
||||||
public Action<string> ErrorLog { get; private set; }
|
public event Action<string> ErrorLog;
|
||||||
|
|
||||||
public List<RpfFile> BaseRpfs { get; private set; }
|
public List<RpfFile> BaseRpfs { get; private set; }
|
||||||
public List<RpfFile> ModRpfs { get; private set; }
|
public List<RpfFile> ModRpfs { get; private set; }
|
||||||
@ -34,8 +42,9 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Init(string folder, Action<string> updateStatus, Action<string> errorLog, bool rootOnly = false, bool buildIndex = true)
|
public void Init(string folder, Action<string> updateStatus, Action<string> errorLog, bool rootOnly = false, bool buildIndex = true)
|
||||||
{
|
{
|
||||||
UpdateStatus = updateStatus;
|
using var _ = new DisposableTimer("RpfManager.Init");
|
||||||
ErrorLog = errorLog;
|
UpdateStatus += updateStatus;
|
||||||
|
ErrorLog += errorLog;
|
||||||
|
|
||||||
string replpath = folder + "\\";
|
string replpath = folder + "\\";
|
||||||
var sopt = rootOnly ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories;
|
var sopt = rootOnly ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories;
|
||||||
@ -52,7 +61,8 @@ namespace CodeWalker.GameFiles
|
|||||||
ModRpfDict = new Dictionary<string, RpfFile>();
|
ModRpfDict = new Dictionary<string, RpfFile>();
|
||||||
ModEntryDict = new Dictionary<string, RpfEntry>();
|
ModEntryDict = new Dictionary<string, RpfEntry>();
|
||||||
|
|
||||||
foreach (string rpfpath in allfiles)
|
var rpfs = new ConcurrentBag<RpfFile>();
|
||||||
|
Parallel.ForEach(allfiles, (rpfpath) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -69,37 +79,66 @@ namespace CodeWalker.GameFiles
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (excl) continue; //skip files in exclude paths.
|
if (excl) return; //skip files in exclude paths.
|
||||||
}
|
}
|
||||||
|
|
||||||
rf.ScanStructure(updateStatus, errorLog);
|
rf.ScanStructure(updateStatus, errorLog);
|
||||||
|
|
||||||
if (rf.LastException != null) //incase of corrupted rpf (or renamed NG encrypted RPF)
|
if (rf.LastException != null) //incase of corrupted rpf (or renamed NG encrypted RPF)
|
||||||
{
|
{
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddRpfFile(rf, false, false);
|
rpfs.Add(rf);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
errorLog(rpfpath + ": " + ex.ToString());
|
errorLog(rpfpath + ": " + ex.ToString());
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var calculateSum = (RpfFile rpf) => { return 0; };
|
||||||
|
|
||||||
|
calculateSum = (RpfFile rpf) =>
|
||||||
|
{
|
||||||
|
return rpf.AllEntries?.Count ?? 0 + rpf.Children?.Sum(calculateSum) ?? 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
var minCapacity = rpfs.Sum(calculateSum);
|
||||||
|
if (minCapacity > AllRpfs.Capacity)
|
||||||
|
{
|
||||||
|
AllRpfs.Capacity = minCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var rpf in rpfs)
|
||||||
|
{
|
||||||
|
AddRpfFile(rpf, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildIndex)
|
if (buildIndex)
|
||||||
{
|
{
|
||||||
updateStatus("Building jenkindex...");
|
updateStatus?.Invoke("Building jenkindex...");
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
BuildBaseJenkIndex();
|
BuildBaseJenkIndex();
|
||||||
|
IsInited = true;
|
||||||
|
});
|
||||||
|
updateStatus?.Invoke("Scan complete");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateStatus?.Invoke("Scan complete");
|
||||||
|
IsInited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus("Scan complete");
|
|
||||||
|
|
||||||
IsInited = true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(List<RpfFile> allRpfs)
|
public void Init(List<RpfFile> allRpfs)
|
||||||
{
|
{
|
||||||
|
using var _ = new DisposableTimer("RpfManager.Init");
|
||||||
//fast init used by RPF explorer's File cache
|
//fast init used by RPF explorer's File cache
|
||||||
AllRpfs = allRpfs;
|
AllRpfs = allRpfs;
|
||||||
|
|
||||||
@ -122,9 +161,11 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
BuildBaseJenkIndex();
|
BuildBaseJenkIndex();
|
||||||
|
|
||||||
IsInited = true;
|
IsInited = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -182,25 +223,13 @@ namespace CodeWalker.GameFiles
|
|||||||
EntryDict[entry.Path] = entry;
|
EntryDict[entry.Path] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry is RpfFileEntry)
|
|
||||||
{
|
|
||||||
RpfFileEntry fentry = entry as RpfFileEntry;
|
|
||||||
entry.NameHash = JenkHash.GenHash(entry.NameLower);
|
|
||||||
int ind = entry.NameLower.LastIndexOf('.');
|
|
||||||
entry.ShortNameHash = (ind > 0) ? JenkHash.GenHash(entry.NameLower.Substring(0, ind)) : entry.NameHash;
|
|
||||||
if (entry.ShortNameHash != 0)
|
|
||||||
{
|
|
||||||
//EntryHashDict[entry.ShortNameHash] = entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
file.LastError = ex.ToString();
|
file.LastError = ex.ToString();
|
||||||
file.LastException = ex;
|
file.LastException = ex;
|
||||||
ErrorLog(entry.Path + ": " + ex.ToString());
|
ErrorLog?.Invoke(entry.Path + ": " + ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,12 +377,12 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void BuildBaseJenkIndex()
|
public void BuildBaseJenkIndex()
|
||||||
{
|
{
|
||||||
JenkIndex.Clear();
|
using var _ = new DisposableTimer("BuildBaseJenkIndex");
|
||||||
StringBuilder sb = new StringBuilder();
|
Parallel.ForEach(AllRpfs, new ParallelOptions { MaxDegreeOfParallelism = 4 }, (file) =>
|
||||||
foreach (RpfFile file in AllRpfs)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
JenkIndex.Ensure(file.Name);
|
JenkIndex.Ensure(file.Name);
|
||||||
foreach (RpfEntry entry in file.AllEntries)
|
foreach (RpfEntry entry in file.AllEntries)
|
||||||
{
|
{
|
||||||
@ -364,6 +393,7 @@ namespace CodeWalker.GameFiles
|
|||||||
int ind = nlow.LastIndexOf('.');
|
int ind = nlow.LastIndexOf('.');
|
||||||
if (ind > 0)
|
if (ind > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
JenkIndex.Ensure(entry.Name.Substring(0, ind));
|
JenkIndex.Ensure(entry.Name.Substring(0, ind));
|
||||||
JenkIndex.Ensure(nlow.Substring(0, ind));
|
JenkIndex.Ensure(nlow.Substring(0, ind));
|
||||||
|
|
||||||
@ -485,11 +515,16 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch
|
catch(Exception err)
|
||||||
{
|
{
|
||||||
|
ErrorLog?.Invoke(err.ToString());
|
||||||
//failing silently!! not so good really
|
//failing silently!! not so good really
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
//foreach (RpfFile file in AllRpfs)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++)
|
for (int i = 0; i < 100; i++)
|
||||||
{
|
{
|
||||||
|
@ -105,6 +105,20 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace CodeWalker.Utils
|
namespace CodeWalker.Utils
|
||||||
{
|
{
|
||||||
|
public class AssertionFailedException : Exception
|
||||||
|
{
|
||||||
|
public AssertionFailedException() : base("Assertion failed")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssertionFailedException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssertionFailedException(string message, Exception inner) : base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class DDSIO
|
public static class DDSIO
|
||||||
{
|
{
|
||||||
@ -176,6 +190,7 @@ namespace CodeWalker.Utils
|
|||||||
swaprb = false;
|
swaprb = false;
|
||||||
break;
|
break;
|
||||||
case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM: // TextureFormat.D3DFMT_A8B8G8R8
|
case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM: // TextureFormat.D3DFMT_A8B8G8R8
|
||||||
|
case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_TYPELESS:
|
||||||
px = imgdata;
|
px = imgdata;
|
||||||
break;
|
break;
|
||||||
case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM: // TextureFormat.D3DFMT_L8
|
case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM: // TextureFormat.D3DFMT_L8
|
||||||
@ -221,8 +236,8 @@ namespace CodeWalker.Utils
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
MemoryStream ms = new MemoryStream();
|
using MemoryStream ms = new MemoryStream(texture.Data.FullData.Length + 128);
|
||||||
BinaryWriter bw = new BinaryWriter(ms);
|
using BinaryWriter bw = new BinaryWriter(ms);
|
||||||
|
|
||||||
int nimages = img.MipMapLevels;
|
int nimages = img.MipMapLevels;
|
||||||
|
|
||||||
@ -353,8 +368,8 @@ namespace CodeWalker.Utils
|
|||||||
throw new Exception("Unsupported texture dimension");
|
throw new Exception("Unsupported texture dimension");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte[] buff = ms.GetBuffer();
|
byte[] buff = ms.GetBuffer();
|
||||||
|
|
||||||
byte[] outbuf = new byte[ms.Length]; //need to copy to the right size buffer for File.WriteAllBytes().
|
byte[] outbuf = new byte[ms.Length]; //need to copy to the right size buffer for File.WriteAllBytes().
|
||||||
Array.Copy(buff, outbuf, outbuf.Length);
|
Array.Copy(buff, outbuf, outbuf.Length);
|
||||||
|
|
||||||
@ -544,8 +559,8 @@ namespace CodeWalker.Utils
|
|||||||
int add = 0;
|
int add = 0;
|
||||||
for (int i = 0; i < img.MipMapLevels; i++)
|
for (int i = 0; i < img.MipMapLevels; i++)
|
||||||
{
|
{
|
||||||
images[i].width = img.Width / div;
|
images[i].width = Math.Max(img.Width / div, 1);
|
||||||
images[i].height = img.Height / div;
|
images[i].height = Math.Max(img.Height / div, 1);
|
||||||
images[i].format = format; //(DXGI_FORMAT)img.Format;
|
images[i].format = format; //(DXGI_FORMAT)img.Format;
|
||||||
images[i].pixels = buf + add;
|
images[i].pixels = buf + add;
|
||||||
|
|
||||||
@ -773,7 +788,7 @@ namespace CodeWalker.Utils
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(IsValid(fmt));
|
assert(IsValid(fmt), $"{fmt} is not a valid texture format");
|
||||||
assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt));
|
assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt));
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -904,11 +919,17 @@ namespace CodeWalker.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assert(bool b)
|
public static void assert(bool b, string message = null)
|
||||||
{
|
{
|
||||||
if (!b)
|
if (!b)
|
||||||
{
|
{
|
||||||
throw new Exception();
|
if (message is null)
|
||||||
|
{
|
||||||
|
throw new AssertionFailedException();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
throw new AssertionFailedException(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,11 +26,9 @@
|
|||||||
|
|
||||||
using SharpDX;
|
using SharpDX;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
{
|
{
|
||||||
@ -54,10 +52,12 @@ namespace CodeWalker.GameFiles
|
|||||||
String = 9,
|
String = 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DataReader
|
public class DataReader : IDisposable
|
||||||
{
|
{
|
||||||
private Stream baseStream;
|
private Stream baseStream;
|
||||||
|
|
||||||
|
private readonly byte[] _buffer = new byte[8];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the endianess of the underlying stream.
|
/// Gets or sets the endianess of the underlying stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -106,15 +106,15 @@ namespace CodeWalker.GameFiles
|
|||||||
/// Reads data from the underlying stream. This is the only method that directly accesses
|
/// Reads data from the underlying stream. This is the only method that directly accesses
|
||||||
/// the data in the underlying stream.
|
/// the data in the underlying stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual byte[] ReadFromStream(int count, bool ignoreEndianess = false)
|
protected virtual byte[] ReadFromStream(int count, bool ignoreEndianess = false, byte[] buffer = null)
|
||||||
{
|
{
|
||||||
var buffer = new byte[count];
|
buffer ??= new byte[count];
|
||||||
baseStream.Read(buffer, 0, count);
|
baseStream.Read(buffer, 0, count);
|
||||||
|
|
||||||
// handle endianess
|
// handle endianess
|
||||||
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
||||||
{
|
{
|
||||||
Array.Reverse(buffer);
|
Array.Reverse(buffer, 0, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
@ -123,17 +123,22 @@ namespace CodeWalker.GameFiles
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads a byte.
|
/// Reads a byte.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte ReadByte()
|
public virtual byte ReadByte()
|
||||||
{
|
{
|
||||||
return ReadFromStream(1)[0];
|
var result = baseStream.ReadByte();
|
||||||
|
if (result == -1)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Tried to read from stream beyond end!");
|
||||||
|
}
|
||||||
|
return (byte) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads a sequence of bytes.
|
/// Reads a sequence of bytes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] ReadBytes(int count)
|
public byte[] ReadBytes(int count, byte[] buffer = null)
|
||||||
{
|
{
|
||||||
return ReadFromStream(count, true);
|
return ReadFromStream(count, true, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -141,7 +146,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public short ReadInt16()
|
public short ReadInt16()
|
||||||
{
|
{
|
||||||
return BitConverter.ToInt16(ReadFromStream(2), 0);
|
return BitConverter.ToInt16(ReadFromStream(2, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -149,7 +154,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int ReadInt32()
|
public int ReadInt32()
|
||||||
{
|
{
|
||||||
return BitConverter.ToInt32(ReadFromStream(4), 0);
|
return BitConverter.ToInt32(ReadFromStream(4, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -157,7 +162,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public long ReadInt64()
|
public long ReadInt64()
|
||||||
{
|
{
|
||||||
return BitConverter.ToInt64(ReadFromStream(8), 0);
|
return BitConverter.ToInt64(ReadFromStream(8, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -165,7 +170,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort ReadUInt16()
|
public ushort ReadUInt16()
|
||||||
{
|
{
|
||||||
return BitConverter.ToUInt16(ReadFromStream(2), 0);
|
return BitConverter.ToUInt16(ReadFromStream(2, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -173,7 +178,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public uint ReadUInt32()
|
public uint ReadUInt32()
|
||||||
{
|
{
|
||||||
return BitConverter.ToUInt32(ReadFromStream(4), 0);
|
return BitConverter.ToUInt32(ReadFromStream(4, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -181,7 +186,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong ReadUInt64()
|
public ulong ReadUInt64()
|
||||||
{
|
{
|
||||||
return BitConverter.ToUInt64(ReadFromStream(8), 0);
|
return BitConverter.ToUInt64(ReadFromStream(8, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -189,7 +194,7 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float ReadSingle()
|
public float ReadSingle()
|
||||||
{
|
{
|
||||||
return BitConverter.ToSingle(ReadFromStream(4), 0);
|
return BitConverter.ToSingle(ReadFromStream(4, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -197,23 +202,51 @@ namespace CodeWalker.GameFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double ReadDouble()
|
public double ReadDouble()
|
||||||
{
|
{
|
||||||
return BitConverter.ToDouble(ReadFromStream(8), 0);
|
return BitConverter.ToDouble(ReadFromStream(8, buffer: _buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads a string.
|
/// Reads a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ReadString()
|
unsafe public string ReadString(int maxLength = 1024)
|
||||||
{
|
{
|
||||||
var bytes = new List<byte>();
|
var bytes = stackalloc byte[Math.Min(maxLength, 1024)];
|
||||||
var temp = ReadFromStream(1)[0];
|
var temp = ReadByte();
|
||||||
while (temp != 0)
|
var charsRead = 0;
|
||||||
|
while (temp != 0 && (Length == -1 || Position <= Length))
|
||||||
{
|
{
|
||||||
bytes.Add(temp);
|
if (charsRead > 1023)
|
||||||
temp = ReadFromStream(1)[0];
|
{
|
||||||
|
throw new Exception("String too long!");
|
||||||
|
}
|
||||||
|
if (charsRead < maxLength)
|
||||||
|
{
|
||||||
|
bytes[charsRead] = temp;
|
||||||
|
}
|
||||||
|
temp = ReadByte();
|
||||||
|
charsRead++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
return Encoding.UTF8.GetString(bytes, Math.Min(charsRead, maxLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe public string ReadStringLower()
|
||||||
|
{
|
||||||
|
var bytes = stackalloc byte[1024];
|
||||||
|
var temp = ReadByte();
|
||||||
|
var charsRead = 0;
|
||||||
|
while (temp != 0 && (Length == -1 || Position <= Length))
|
||||||
|
{
|
||||||
|
if (charsRead > 1023)
|
||||||
|
{
|
||||||
|
throw new Exception("String too long!");
|
||||||
|
}
|
||||||
|
bytes[charsRead] = temp;
|
||||||
|
temp = ReadByte();
|
||||||
|
charsRead++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(bytes, charsRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -279,12 +312,13 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
baseStream?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DataWriter
|
public class DataWriter : IDisposable
|
||||||
{
|
{
|
||||||
private Stream baseStream;
|
private Stream baseStream;
|
||||||
|
|
||||||
@ -476,6 +510,15 @@ namespace CodeWalker.GameFiles
|
|||||||
Write(value.M44);
|
Write(value.M44);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
baseStream.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Close()
|
||||||
|
{
|
||||||
|
baseStream.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,8 +23,12 @@
|
|||||||
//shamelessly stolen
|
//shamelessly stolen
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -34,7 +38,10 @@ namespace CodeWalker.GameFiles
|
|||||||
public class GTACrypto
|
public class GTACrypto
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public static byte[] DecryptAES(byte[] data, int length)
|
||||||
|
{
|
||||||
|
return DecryptAESData(data, GTA5Keys.PC_AES_KEY, length, 1);
|
||||||
|
}
|
||||||
public static byte[] DecryptAES(byte[] data)
|
public static byte[] DecryptAES(byte[] data)
|
||||||
{
|
{
|
||||||
return DecryptAESData(data, GTA5Keys.PC_AES_KEY);
|
return DecryptAESData(data, GTA5Keys.PC_AES_KEY);
|
||||||
@ -45,6 +52,11 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] DecryptAESData(byte[] data, byte[] key, int rounds = 1)
|
public static byte[] DecryptAESData(byte[] data, byte[] key, int rounds = 1)
|
||||||
|
{
|
||||||
|
return DecryptAESData(data, key, data.Length, rounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] DecryptAESData(byte[] data, byte[] key, int length, int rounds = 1)
|
||||||
{
|
{
|
||||||
var rijndael = Rijndael.Create();
|
var rijndael = Rijndael.Create();
|
||||||
rijndael.KeySize = 256;
|
rijndael.KeySize = 256;
|
||||||
@ -53,18 +65,17 @@ namespace CodeWalker.GameFiles
|
|||||||
rijndael.Mode = CipherMode.ECB;
|
rijndael.Mode = CipherMode.ECB;
|
||||||
rijndael.Padding = PaddingMode.None;
|
rijndael.Padding = PaddingMode.None;
|
||||||
|
|
||||||
var buffer = (byte[])data.Clone();
|
length = length - length % 16;
|
||||||
var length = data.Length - data.Length % 16;
|
|
||||||
|
|
||||||
// decrypt...
|
// decrypt...
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
var decryptor = rijndael.CreateDecryptor();
|
var decryptor = rijndael.CreateDecryptor();
|
||||||
for (var roundIndex = 0; roundIndex < rounds; roundIndex++)
|
for (var roundIndex = 0; roundIndex < rounds; roundIndex++)
|
||||||
decryptor.TransformBlock(buffer, 0, length, buffer, 0);
|
decryptor.TransformBlock(data, 0, length, data, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return data;
|
||||||
}
|
}
|
||||||
public static byte[] EncryptAESData(byte[] data, byte[] key, int rounds = 1)
|
public static byte[] EncryptAESData(byte[] data, byte[] key, int rounds = 1)
|
||||||
{
|
{
|
||||||
@ -93,7 +104,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static byte[] GetNGKey(string name, uint length)
|
public static uint[][] GetNGKey(string name, uint length)
|
||||||
{
|
{
|
||||||
uint hash = GTA5Hash.CalculateHash(name);
|
uint hash = GTA5Hash.CalculateHash(name);
|
||||||
uint keyidx = (hash + length + (101 - 40)) % 0x65;
|
uint keyidx = (hash + length + (101 - 40)) % 0x65;
|
||||||
@ -101,63 +112,61 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static byte[] DecryptNG(byte[] data, string name, uint length)
|
public static byte[] DecryptNG(byte[] data, string name, uint fileSize, int offset = 0, int? length = null)
|
||||||
{
|
{
|
||||||
byte[] key = GetNGKey(name, length);
|
var key = GetNGKey(name, fileSize);
|
||||||
return DecryptNG(data, key);
|
return DecryptNG(data, key, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] DecryptNG(byte[] data, byte[] key)
|
public unsafe static byte[] DecryptNG(byte[] data, uint[][] key, int offset = 0, int? length = null)
|
||||||
{
|
{
|
||||||
var decryptedData = new byte[data.Length];
|
length ??= data.Length;
|
||||||
|
fixed (byte* bptr = data)
|
||||||
var keyuints = new uint[key.Length / 4];
|
|
||||||
Buffer.BlockCopy(key, 0, keyuints, 0, key.Length);
|
|
||||||
|
|
||||||
for (int blockIndex = 0; blockIndex < data.Length / 16; blockIndex++)
|
|
||||||
{
|
{
|
||||||
var encryptedBlock = new byte[16];
|
for (int blockIndex = offset * 16; blockIndex < length / 16; blockIndex++)
|
||||||
Array.Copy(data, 16 * blockIndex, encryptedBlock, 0, 16);
|
{
|
||||||
var decryptedBlock = DecryptNGBlock(encryptedBlock, keyuints);
|
DecryptNGBlock(bptr + 16 * blockIndex, key);
|
||||||
Array.Copy(decryptedBlock, 0, decryptedData, 16 * blockIndex, 16);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.Length % 16 != 0)
|
return data;
|
||||||
{
|
|
||||||
var left = data.Length % 16;
|
|
||||||
Buffer.BlockCopy(data, data.Length - left, decryptedData, data.Length - left, left);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return decryptedData;
|
public unsafe static void DecryptNGBlock(byte[] data, uint[][] key)
|
||||||
|
{
|
||||||
|
fixed(byte* bptr = data)
|
||||||
|
{
|
||||||
|
DecryptNGBlock(data, key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] DecryptNGBlock(byte[] data, uint[] key)
|
public unsafe static void DecryptNGBlock(byte* data, uint[][] key)
|
||||||
{
|
{
|
||||||
var buffer = data;
|
DecryptNGRoundA(data, key[0], GTA5Keys.PC_NG_DECRYPT_TABLES[0]);
|
||||||
|
DecryptNGRoundA(data, key[1], GTA5Keys.PC_NG_DECRYPT_TABLES[1]);
|
||||||
// prepare key...
|
|
||||||
var subKeys = new uint[17][];
|
|
||||||
for (int i = 0; i < 17; i++)
|
|
||||||
{
|
|
||||||
subKeys[i] = new uint[4];
|
|
||||||
subKeys[i][0] = key[4 * i + 0];
|
|
||||||
subKeys[i][1] = key[4 * i + 1];
|
|
||||||
subKeys[i][2] = key[4 * i + 2];
|
|
||||||
subKeys[i][3] = key[4 * i + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = DecryptNGRoundA(buffer, subKeys[0], GTA5Keys.PC_NG_DECRYPT_TABLES[0]);
|
|
||||||
buffer = DecryptNGRoundA(buffer, subKeys[1], GTA5Keys.PC_NG_DECRYPT_TABLES[1]);
|
|
||||||
for (int k = 2; k <= 15; k++)
|
for (int k = 2; k <= 15; k++)
|
||||||
buffer = DecryptNGRoundB(buffer, subKeys[k], GTA5Keys.PC_NG_DECRYPT_TABLES[k]);
|
DecryptNGRoundB(data, key[k], GTA5Keys.PC_NG_DECRYPT_TABLES[k]);
|
||||||
buffer = DecryptNGRoundA(buffer, subKeys[16], GTA5Keys.PC_NG_DECRYPT_TABLES[16]);
|
DecryptNGRoundA(data, key[16], GTA5Keys.PC_NG_DECRYPT_TABLES[16]);
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe static void DecryptNGRoundA(byte[] data, uint[] key, uint[][] table)
|
||||||
|
{
|
||||||
|
fixed(byte* bptr = data)
|
||||||
|
{
|
||||||
|
DecryptNGRoundA(bptr, key, table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe static void DecryptNGRoundB(byte[] data, uint[] key, uint[][] table)
|
||||||
|
{
|
||||||
|
fixed (byte* bptr = data)
|
||||||
|
{
|
||||||
|
DecryptNGRoundB(bptr, key, table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// round 1,2,16
|
// round 1,2,16
|
||||||
public static byte[] DecryptNGRoundA(byte[] data, uint[] key, uint[][] table)
|
public unsafe static void DecryptNGRoundA(byte* data, uint[] key, uint[][] table)
|
||||||
{
|
{
|
||||||
var x1 =
|
var x1 =
|
||||||
table[0][data[0]] ^
|
table[0][data[0]] ^
|
||||||
@ -184,18 +193,14 @@ namespace CodeWalker.GameFiles
|
|||||||
table[15][data[15]] ^
|
table[15][data[15]] ^
|
||||||
key[3];
|
key[3];
|
||||||
|
|
||||||
var result = new byte[16];
|
*(uint*)data = x1;
|
||||||
Array.Copy(BitConverter.GetBytes(x1), 0, result, 0, 4);
|
*(uint*)(data + 4) = x2;
|
||||||
Array.Copy(BitConverter.GetBytes(x2), 0, result, 4, 4);
|
*(uint*)(data + 8) = x3;
|
||||||
Array.Copy(BitConverter.GetBytes(x3), 0, result, 8, 4);
|
*(uint*)(data + 12) = x4;
|
||||||
Array.Copy(BitConverter.GetBytes(x4), 0, result, 12, 4);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// round 3-15
|
// round 3-15
|
||||||
public static byte[] DecryptNGRoundB(byte[] data, uint[] key, uint[][] table)
|
public unsafe static void DecryptNGRoundB(byte* data, uint[] key, uint[][] table)
|
||||||
{
|
{
|
||||||
var x1 =
|
var x1 =
|
||||||
table[0][data[0]] ^
|
table[0][data[0]] ^
|
||||||
@ -222,31 +227,10 @@ namespace CodeWalker.GameFiles
|
|||||||
table[12][data[12]] ^
|
table[12][data[12]] ^
|
||||||
key[3];
|
key[3];
|
||||||
|
|
||||||
//var result = new byte[16];
|
*(uint*)data = x1;
|
||||||
//Array.Copy(BitConverter.GetBytes(x1), 0, result, 0, 4);
|
*(uint*)(data + 4) = x2;
|
||||||
//Array.Copy(BitConverter.GetBytes(x2), 0, result, 4, 4);
|
*(uint*)(data + 8) = x3;
|
||||||
//Array.Copy(BitConverter.GetBytes(x3), 0, result, 8, 4);
|
*(uint*)(data + 12) = x4;
|
||||||
//Array.Copy(BitConverter.GetBytes(x4), 0, result, 12, 4);
|
|
||||||
//return result;
|
|
||||||
|
|
||||||
var result = new byte[16];
|
|
||||||
result[0] = (byte)((x1 >> 0) & 0xFF);
|
|
||||||
result[1] = (byte)((x1 >> 8) & 0xFF);
|
|
||||||
result[2] = (byte)((x1 >> 16) & 0xFF);
|
|
||||||
result[3] = (byte)((x1 >> 24) & 0xFF);
|
|
||||||
result[4] = (byte)((x2 >> 0) & 0xFF);
|
|
||||||
result[5] = (byte)((x2 >> 8) & 0xFF);
|
|
||||||
result[6] = (byte)((x2 >> 16) & 0xFF);
|
|
||||||
result[7] = (byte)((x2 >> 24) & 0xFF);
|
|
||||||
result[8] = (byte)((x3 >> 0) & 0xFF);
|
|
||||||
result[9] = (byte)((x3 >> 8) & 0xFF);
|
|
||||||
result[10] = (byte)((x3 >> 16) & 0xFF);
|
|
||||||
result[11] = (byte)((x3 >> 24) & 0xFF);
|
|
||||||
result[12] = (byte)((x4 >> 0) & 0xFF);
|
|
||||||
result[13] = (byte)((x4 >> 8) & 0xFF);
|
|
||||||
result[14] = (byte)((x4 >> 16) & 0xFF);
|
|
||||||
result[15] = (byte)((x4 >> 24) & 0xFF);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -267,11 +251,11 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public static byte[] EncryptNG(byte[] data, string name, uint length)
|
public static byte[] EncryptNG(byte[] data, string name, uint length)
|
||||||
{
|
{
|
||||||
byte[] key = GetNGKey(name, length);
|
var key = GetNGKey(name, length);
|
||||||
return EncryptNG(data, key);
|
return EncryptNG(data, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] EncryptNG(byte[] data, byte[] key)
|
public static byte[] EncryptNG(byte[] data, uint[][] key)
|
||||||
{
|
{
|
||||||
if ((GTA5Keys.PC_NG_ENCRYPT_TABLES == null) || (GTA5Keys.PC_NG_ENCRYPT_LUTs == null))
|
if ((GTA5Keys.PC_NG_ENCRYPT_TABLES == null) || (GTA5Keys.PC_NG_ENCRYPT_LUTs == null))
|
||||||
{
|
{
|
||||||
@ -280,14 +264,11 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
var encryptedData = new byte[data.Length];
|
var encryptedData = new byte[data.Length];
|
||||||
|
|
||||||
var keyuints = new uint[key.Length / 4];
|
|
||||||
Buffer.BlockCopy(key, 0, keyuints, 0, key.Length);
|
|
||||||
|
|
||||||
for (int blockIndex = 0; blockIndex < data.Length / 16; blockIndex++)
|
for (int blockIndex = 0; blockIndex < data.Length / 16; blockIndex++)
|
||||||
{
|
{
|
||||||
byte[] decryptedBlock = new byte[16];
|
byte[] decryptedBlock = new byte[16];
|
||||||
Array.Copy(data, 16 * blockIndex, decryptedBlock, 0, 16);
|
Array.Copy(data, 16 * blockIndex, decryptedBlock, 0, 16);
|
||||||
byte[] encryptedBlock = EncryptBlock(decryptedBlock, keyuints);
|
byte[] encryptedBlock = EncryptBlock(decryptedBlock, key);
|
||||||
Array.Copy(encryptedBlock, 0, encryptedData, 16 * blockIndex, 16);
|
Array.Copy(encryptedBlock, 0, encryptedData, 16 * blockIndex, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,26 +281,15 @@ namespace CodeWalker.GameFiles
|
|||||||
return encryptedData;
|
return encryptedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] EncryptBlock(byte[] data, uint[] key)
|
public static byte[] EncryptBlock(byte[] data, uint[][] key)
|
||||||
{
|
{
|
||||||
var buffer = data;
|
var buffer = data;
|
||||||
|
|
||||||
// prepare key...
|
buffer = EncryptRoundA(buffer, key[16], GTA5Keys.PC_NG_ENCRYPT_TABLES[16]);
|
||||||
var subKeys = new uint[17][];
|
|
||||||
for (int i = 0; i < 17; i++)
|
|
||||||
{
|
|
||||||
subKeys[i] = new uint[4];
|
|
||||||
subKeys[i][0] = key[4 * i + 0];
|
|
||||||
subKeys[i][1] = key[4 * i + 1];
|
|
||||||
subKeys[i][2] = key[4 * i + 2];
|
|
||||||
subKeys[i][3] = key[4 * i + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = EncryptRoundA(buffer, subKeys[16], GTA5Keys.PC_NG_ENCRYPT_TABLES[16]);
|
|
||||||
for (int k = 15; k >= 2; k--)
|
for (int k = 15; k >= 2; k--)
|
||||||
buffer = EncryptRoundB_LUT(buffer, subKeys[k], GTA5Keys.PC_NG_ENCRYPT_LUTs[k]);
|
buffer = EncryptRoundB_LUT(buffer, key[k], GTA5Keys.PC_NG_ENCRYPT_LUTs[k]);
|
||||||
buffer = EncryptRoundA(buffer, subKeys[1], GTA5Keys.PC_NG_ENCRYPT_TABLES[1]);
|
buffer = EncryptRoundA(buffer, key[1], GTA5Keys.PC_NG_ENCRYPT_TABLES[1]);
|
||||||
buffer = EncryptRoundA(buffer, subKeys[0], GTA5Keys.PC_NG_ENCRYPT_TABLES[0]);
|
buffer = EncryptRoundA(buffer, key[0], GTA5Keys.PC_NG_ENCRYPT_TABLES[0]);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@ -425,5 +395,136 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DecryptNGStream : Stream
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
private long _length = 0;
|
||||||
|
|
||||||
|
private Stream _baseStream;
|
||||||
|
|
||||||
|
public Stream BaseStream { get => _baseStream; private set => _baseStream = value; }
|
||||||
|
|
||||||
|
public uint[][] Key { get; set; }
|
||||||
|
private long offset = 0;
|
||||||
|
|
||||||
|
public override long Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_length != 0) return _length;
|
||||||
|
return _baseStream.Length - offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DecryptNGStream(string name, uint length)
|
||||||
|
{
|
||||||
|
_length = length;
|
||||||
|
Name = name;
|
||||||
|
Key = GTACrypto.GetNGKey(name, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecryptNGStream(byte[] data, string name, uint fileSize) : this(name, fileSize)
|
||||||
|
{
|
||||||
|
BaseStream = new MemoryStream(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecryptNGStream(Stream data, string name, uint fileSize) : this(name, fileSize)
|
||||||
|
{
|
||||||
|
BaseStream = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecryptNGStream(Stream data, string name, uint fileSize, int start, int length = 0): this(data, name, fileSize)
|
||||||
|
{
|
||||||
|
this.offset = start;
|
||||||
|
this._length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => _baseStream.CanRead;
|
||||||
|
|
||||||
|
public override bool CanSeek => _baseStream.CanSeek;
|
||||||
|
|
||||||
|
public override bool CanWrite => _baseStream.CanWrite;
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var position = _baseStream.Position - offset;
|
||||||
|
|
||||||
|
position = position - position % 16;
|
||||||
|
return position + positionInBuffer;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
positionInBuffer = 0;
|
||||||
|
_baseStream.Position = (value + offset);
|
||||||
|
ReadBlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadBlock()
|
||||||
|
{
|
||||||
|
_baseStream.Read(_buffer, 0, _buffer.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] _buffer = new byte[16];
|
||||||
|
private byte positionInBuffer = 0;
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (positionInBuffer > 0)
|
||||||
|
{
|
||||||
|
var toCopy = (byte)Math.Min(16 - positionInBuffer, count);
|
||||||
|
Array.Copy(_buffer, positionInBuffer, buffer, offset, toCopy);
|
||||||
|
positionInBuffer += toCopy;
|
||||||
|
if (positionInBuffer >= 16)
|
||||||
|
{
|
||||||
|
positionInBuffer = 0;
|
||||||
|
}
|
||||||
|
offset += toCopy;
|
||||||
|
count -= toCopy;
|
||||||
|
}
|
||||||
|
var i = 0;
|
||||||
|
while (count >= 16)
|
||||||
|
{
|
||||||
|
_baseStream.Read(buffer, offset + i, 16);
|
||||||
|
i += 16;
|
||||||
|
}
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
_baseStream.Read(_buffer, 0, 16);
|
||||||
|
GTACrypto.DecryptNG(_buffer, Key, 0, 16);
|
||||||
|
Array.Copy(_buffer, positionInBuffer, buffer, offset + i, count - i);
|
||||||
|
positionInBuffer += (byte)(count - i);
|
||||||
|
}
|
||||||
|
var data = _baseStream.Read(buffer, offset, count);
|
||||||
|
|
||||||
|
GTACrypto.DecryptNG(buffer, Key, offset, count);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ namespace CodeWalker.GameFiles
|
|||||||
public static byte[] PC_AES_KEY; // 32
|
public static byte[] PC_AES_KEY; // 32
|
||||||
|
|
||||||
// ng decryption/encryption expanded keys...
|
// ng decryption/encryption expanded keys...
|
||||||
public static byte[][] PC_NG_KEYS; // 101, 272
|
public static uint[][][] PC_NG_KEYS; // 101, 272
|
||||||
|
|
||||||
// ng decryption tables...
|
// ng decryption tables...
|
||||||
public static uint[][][] PC_NG_DECRYPT_TABLES; // 17, 16, 256
|
public static uint[][][] PC_NG_DECRYPT_TABLES; // 17, 16, 256
|
||||||
@ -73,15 +73,26 @@ namespace CodeWalker.GameFiles
|
|||||||
var exeStr = new MemoryStream(exeData);
|
var exeStr = new MemoryStream(exeData);
|
||||||
|
|
||||||
updateStatus("Searching for AES key...");
|
updateStatus("Searching for AES key...");
|
||||||
PC_AES_KEY = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_AES_KEY_HASH, 0x20);
|
PC_AES_KEY = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_AES_KEY_HASH, 32);
|
||||||
//updateStatus("aes key found");
|
//updateStatus("aes key found");
|
||||||
|
|
||||||
updateStatus("Searching for NG keys...");
|
updateStatus("Searching for NG keys...");
|
||||||
PC_NG_KEYS = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_KEY_HASHES, 0x110);
|
//PC_NG_KEYS = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_KEY_HASHES, 272);
|
||||||
|
var tabs = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_KEY_HASHES, 272);
|
||||||
|
PC_NG_KEYS = new uint[tabs.Length][][];
|
||||||
|
for (int i = 0; i < tabs.Length; i++)
|
||||||
|
{
|
||||||
|
PC_NG_KEYS[i] = new uint[tabs[i].Length / 4 / 4][];
|
||||||
|
for (int j = 0; j < tabs[i].Length / 4; j++)
|
||||||
|
{
|
||||||
|
Buffer.BlockCopy(tabs[i], 0, PC_NG_KEYS[i][j], 0, 16);
|
||||||
|
}
|
||||||
|
//Buffer.BlockCopy(tabs[i], 0, PC_NG_DECRYPT_TABLES[i][j], 0, tabs[i].Length);
|
||||||
|
}
|
||||||
//updateStatus("ng keys found");
|
//updateStatus("ng keys found");
|
||||||
|
|
||||||
updateStatus("Searching for NG decrypt tables...");
|
updateStatus("Searching for NG decrypt tables...");
|
||||||
var tabs = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_DECRYPT_TABLE_HASHES, 0x400);
|
tabs = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_DECRYPT_TABLE_HASHES, 1024);
|
||||||
//updateStatus("ng decrypt tables found");
|
//updateStatus("ng decrypt tables found");
|
||||||
|
|
||||||
updateStatus("Searching for NG hash lookup tables...");
|
updateStatus("Searching for NG hash lookup tables...");
|
||||||
@ -277,14 +288,14 @@ namespace CodeWalker.GameFiles
|
|||||||
db[i] = (byte)((m[i] - rb1[i] - rb2[i] - rb3[i] - rb4[i]) & 0xFF);
|
db[i] = (byte)((m[i] - rb1[i] - rb2[i] - rb3[i] - rb4[i]) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
db = GTACrypto.DecryptAESData(db, PC_AES_KEY);
|
GTACrypto.DecryptAESData(db, PC_AES_KEY);
|
||||||
|
|
||||||
byte[] b = null;
|
byte[] b = null;
|
||||||
using (MemoryStream dms = new MemoryStream(db))
|
using (MemoryStream dms = new MemoryStream(db))
|
||||||
{
|
{
|
||||||
using (DeflateStream ds = new DeflateStream(dms, CompressionMode.Decompress))
|
using (DeflateStream ds = new DeflateStream(dms, CompressionMode.Decompress))
|
||||||
{
|
{
|
||||||
using (MemoryStream outstr = new MemoryStream())
|
using (MemoryStream outstr = RpfFile.recyclableMemoryStreamManager.GetStream())
|
||||||
{
|
{
|
||||||
ds.CopyTo(outstr);
|
ds.CopyTo(outstr);
|
||||||
b = outstr.GetBuffer();
|
b = outstr.GetBuffer();
|
||||||
@ -848,11 +859,13 @@ namespace CodeWalker.GameFiles
|
|||||||
random.NextBytes(buf_encrypted);
|
random.NextBytes(buf_encrypted);
|
||||||
|
|
||||||
// decrypt
|
// decrypt
|
||||||
var buf_decrypted = GTACrypto.DecryptNGRoundA(
|
GTACrypto.DecryptNGRoundA(
|
||||||
buf_encrypted,
|
buf_encrypted,
|
||||||
noKey,
|
noKey,
|
||||||
tables);
|
tables);
|
||||||
|
|
||||||
|
var buf_decrypted = buf_encrypted;
|
||||||
|
|
||||||
// make row
|
// make row
|
||||||
var row = new RandomGaussRow();
|
var row = new RandomGaussRow();
|
||||||
//row.A[0 + buf_decrypted[inByte0]] = true;
|
//row.A[0 + buf_decrypted[inByte0]] = true;
|
||||||
@ -1148,33 +1161,35 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public class CryptoIO
|
public class CryptoIO
|
||||||
{
|
{
|
||||||
public static byte[][] ReadNgKeys(string fileName)
|
public static uint[][][] ReadNgKeys(string fileName)
|
||||||
{
|
{
|
||||||
byte[][] result;
|
using var fs = new FileStream(fileName, FileMode.Open);
|
||||||
|
using var rd = new DataReader(fs);
|
||||||
|
|
||||||
var fs = new FileStream(fileName, FileMode.Open);
|
return ReadNgKeys(rd);
|
||||||
var rd = new DataReader(fs);
|
}
|
||||||
|
public static uint[][][] ReadNgKeys(byte[] data)
|
||||||
result = new byte[101][];
|
|
||||||
for (int i = 0; i < 101; i++)
|
|
||||||
{
|
{
|
||||||
result[i] = rd.ReadBytes(272);
|
using var rd = new DataReader(new MemoryStream(data));
|
||||||
|
|
||||||
|
return ReadNgKeys(rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.Close();
|
public static uint[][][] ReadNgKeys(DataReader rd)
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
public static byte[][] ReadNgKeys(byte[] data)
|
|
||||||
{
|
{
|
||||||
byte[][] result;
|
var result = new uint[101][][];
|
||||||
|
|
||||||
var rd = new DataReader(new MemoryStream(data));
|
|
||||||
|
|
||||||
result = new byte[101][];
|
|
||||||
for (int i = 0; i < 101; i++)
|
for (int i = 0; i < 101; i++)
|
||||||
{
|
{
|
||||||
result[i] = rd.ReadBytes(272);
|
result[i] = new uint[68 / 4][];
|
||||||
|
for (int j = 0; j < 68 / 4; j++)
|
||||||
|
{
|
||||||
|
result[i][j] = new uint[4];
|
||||||
|
for (int k = 0; k < 4; k++)
|
||||||
|
{
|
||||||
|
result[i][j][k] = rd.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1182,16 +1197,23 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void WriteNgKeys(string fileName, byte[][] keys)
|
public static void WriteNgKeys(string fileName, uint[][][] keys)
|
||||||
{
|
{
|
||||||
//var fs = new FileStream(fileName, FileMode.Create);
|
//var fs = new FileStream(fileName, FileMode.Create);
|
||||||
//var wr = new DataWriter(fs);
|
//var wr = new DataWriter(fs);
|
||||||
var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
var wr = new DataWriter(ms);
|
using var wr = new DataWriter(ms);
|
||||||
|
|
||||||
for (int i = 0; i < 101; i++)
|
for (int i = 0; i < 101; i++)
|
||||||
{
|
{
|
||||||
wr.Write(keys[i]);
|
for (int j = 0; j < keys[i].Length; j++)
|
||||||
|
{
|
||||||
|
for (int k = 0; j < keys[i][j].Length; k++)
|
||||||
|
{
|
||||||
|
wr.Write(keys[i][j][k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//fs.Close();
|
//fs.Close();
|
||||||
@ -1207,8 +1229,8 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
uint[][][] result;
|
uint[][][] result;
|
||||||
|
|
||||||
var fs = new FileStream(fileName, FileMode.Open);
|
using var fs = new FileStream(fileName, FileMode.Open);
|
||||||
var rd = new DataReader(fs);
|
using var rd = new DataReader(fs);
|
||||||
|
|
||||||
// 17 rounds...
|
// 17 rounds...
|
||||||
result = new uint[17][][];
|
result = new uint[17][][];
|
||||||
@ -1235,7 +1257,7 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
uint[][][] result;
|
uint[][][] result;
|
||||||
|
|
||||||
var rd = new DataReader(new MemoryStream(data));
|
using var rd = new DataReader(new MemoryStream(data));
|
||||||
|
|
||||||
// 17 rounds...
|
// 17 rounds...
|
||||||
result = new uint[17][][];
|
result = new uint[17][][];
|
||||||
@ -1263,8 +1285,8 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
//var fs = new FileStream(fileName, FileMode.Create);
|
//var fs = new FileStream(fileName, FileMode.Create);
|
||||||
//var wr = new DataWriter(fs);
|
//var wr = new DataWriter(fs);
|
||||||
var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
var wr = new DataWriter(ms);
|
using var wr = new DataWriter(ms);
|
||||||
|
|
||||||
// 17 rounds...
|
// 17 rounds...
|
||||||
for (int i = 0; i < 17; i++)
|
for (int i = 0; i < 17; i++)
|
||||||
@ -1293,8 +1315,8 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
GTA5NGLUT[][] result;
|
GTA5NGLUT[][] result;
|
||||||
|
|
||||||
var fs = new FileStream(fileName, FileMode.Open);
|
using var fs = new FileStream(fileName, FileMode.Open);
|
||||||
var rd = new DataReader(fs);
|
using var rd = new DataReader(fs);
|
||||||
|
|
||||||
// 17 rounds...
|
// 17 rounds...
|
||||||
result = new GTA5NGLUT[17][];
|
result = new GTA5NGLUT[17][];
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
@ -55,6 +58,24 @@ namespace CodeWalker.GameFiles
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static uint GenHashLower(string text)
|
||||||
|
{
|
||||||
|
if (text == null) return 0;
|
||||||
|
uint h = 0;
|
||||||
|
for (int i = 0; i < text.Length; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
h += (byte)char.ToLowerInvariant(text[i]);
|
||||||
|
h += (h << 10);
|
||||||
|
h ^= (h >> 6);
|
||||||
|
}
|
||||||
|
h += (h << 3);
|
||||||
|
h ^= (h >> 11);
|
||||||
|
h += (h << 15);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
public static uint GenHash(string text)
|
public static uint GenHash(string text)
|
||||||
{
|
{
|
||||||
if (text == null) return 0;
|
if (text == null) return 0;
|
||||||
@ -192,70 +213,104 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class DictionaryExtension
|
||||||
|
{
|
||||||
|
public static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue value)
|
||||||
|
{
|
||||||
|
if (dict.ContainsKey(key))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dict[key] = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static class JenkIndex
|
public static class JenkIndex
|
||||||
{
|
{
|
||||||
public static Dictionary<uint, string> Index = new Dictionary<uint, string>();
|
public static ConcurrentDictionary<uint, string> Index = new ConcurrentDictionary<uint, string>(Environment.ProcessorCount, 1500000);
|
||||||
private static object syncRoot = new object();
|
|
||||||
|
|
||||||
public static void Clear()
|
public static void Clear()
|
||||||
{
|
|
||||||
lock (syncRoot)
|
|
||||||
{
|
{
|
||||||
Index.Clear();
|
Index.Clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Ensure(string str)
|
public static bool Ensure(string str)
|
||||||
{
|
{
|
||||||
uint hash = JenkHash.GenHash(str);
|
uint hash = JenkHash.GenHash(str);
|
||||||
if (hash == 0) return true;
|
if (hash == 0) return true;
|
||||||
lock (syncRoot)
|
if (Index.ContainsKey(hash))
|
||||||
{
|
{
|
||||||
if (!Index.ContainsKey(hash))
|
return true;
|
||||||
|
}
|
||||||
|
lock (Index)
|
||||||
{
|
{
|
||||||
Index.Add(hash, str);
|
Index[hash] = str;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool EnsureLower(string str)
|
||||||
|
{
|
||||||
|
uint hash = JenkHash.GenHashLower(str);
|
||||||
|
if (hash == 0) return true;
|
||||||
|
if (Index.ContainsKey(hash))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Index.TryAdd(hash, str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddRange(params string[] strings)
|
||||||
|
{
|
||||||
|
foreach(var s in strings)
|
||||||
|
{
|
||||||
|
uint hash = JenkHash.GenHash(s);
|
||||||
|
if (hash == 0) continue;
|
||||||
|
|
||||||
|
Index[hash] = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddRangeLower(params string[] strings)
|
||||||
|
{
|
||||||
|
foreach (var s in strings)
|
||||||
|
{
|
||||||
|
uint hash = JenkHash.GenHashLower(s);
|
||||||
|
if (hash == 0) continue;
|
||||||
|
|
||||||
|
Index[hash] = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetString(uint hash)
|
public static string GetString(uint hash)
|
||||||
{
|
{
|
||||||
string res;
|
string res;
|
||||||
lock (syncRoot)
|
|
||||||
{
|
|
||||||
if (!Index.TryGetValue(hash, out res))
|
if (!Index.TryGetValue(hash, out res))
|
||||||
{
|
{
|
||||||
res = hash.ToString();
|
res = hash.ToString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
public static string TryGetString(uint hash)
|
public static string TryGetString(uint hash)
|
||||||
{
|
{
|
||||||
string res;
|
string res;
|
||||||
lock (syncRoot)
|
|
||||||
{
|
|
||||||
if (!Index.TryGetValue(hash, out res))
|
if (!Index.TryGetValue(hash, out res))
|
||||||
{
|
{
|
||||||
res = string.Empty;
|
res = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] GetAllStrings()
|
public static string[] GetAllStrings()
|
||||||
{
|
{
|
||||||
string[] res = null;
|
string[] res = null;
|
||||||
lock (syncRoot)
|
|
||||||
{
|
|
||||||
res = Index.Values.ToArray();
|
res = Index.Values.ToArray();
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2496
CodeWalker.Core/Tests/GameFileCache.cs
Normal file
2496
CodeWalker.Core/Tests/GameFileCache.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using CodeWalker.GameFiles;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -15,6 +17,7 @@ namespace CodeWalker
|
|||||||
public DateTime CurrentTime = DateTime.Now;
|
public DateTime CurrentTime = DateTime.Now;
|
||||||
|
|
||||||
private LinkedList<TVal> loadedList = new LinkedList<TVal>();
|
private LinkedList<TVal> loadedList = new LinkedList<TVal>();
|
||||||
|
private object loadedListLock = new object();
|
||||||
private Dictionary<TKey, LinkedListNode<TVal>> loadedListDict = new Dictionary<TKey, LinkedListNode<TVal>>();
|
private Dictionary<TKey, LinkedListNode<TVal>> loadedListDict = new Dictionary<TKey, LinkedListNode<TVal>>();
|
||||||
|
|
||||||
public int Count
|
public int Count
|
||||||
@ -43,25 +46,30 @@ namespace CodeWalker
|
|||||||
public TVal TryGet(TKey key)
|
public TVal TryGet(TKey key)
|
||||||
{
|
{
|
||||||
LinkedListNode<TVal> lln = null;
|
LinkedListNode<TVal> lln = null;
|
||||||
|
lock (loadedListLock)
|
||||||
|
{
|
||||||
if (loadedListDict.TryGetValue(key, out lln))
|
if (loadedListDict.TryGetValue(key, out lln))
|
||||||
{
|
{
|
||||||
|
|
||||||
loadedList.Remove(lln);
|
loadedList.Remove(lln);
|
||||||
loadedList.AddLast(lln);
|
loadedList.AddLast(lln);
|
||||||
|
|
||||||
lln.Value.LastUseTime = CurrentTime;
|
lln.Value.LastUseTime = CurrentTime;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (lln != null) ? lln.Value : null;
|
return (lln != null) ? lln.Value : null;
|
||||||
}
|
}
|
||||||
public bool TryAdd(TKey key, TVal item)
|
public bool TryAdd(TKey key, TVal item)
|
||||||
{
|
{
|
||||||
if (item.MemoryUsage == 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
item.Key = key;
|
item.Key = key;
|
||||||
if (CanAdd())
|
if (CanAdd())
|
||||||
|
{
|
||||||
|
lock(loadedListLock)
|
||||||
{
|
{
|
||||||
var lln = loadedList.AddLast(item);
|
var lln = loadedList.AddLast(item);
|
||||||
loadedListDict.Add(key, lln);
|
loadedListDict.Add(key, lln);
|
||||||
Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage);
|
Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -73,10 +81,14 @@ namespace CodeWalker
|
|||||||
while (!CanAdd() && (iter<maxiter))
|
while (!CanAdd() && (iter<maxiter))
|
||||||
{
|
{
|
||||||
while ((!CanAdd()) && (oldlln != null) && ((CurrentTime - oldlln.Value.LastUseTime).TotalSeconds > cachetime))
|
while ((!CanAdd()) && (oldlln != null) && ((CurrentTime - oldlln.Value.LastUseTime).TotalSeconds > cachetime))
|
||||||
|
{
|
||||||
|
lock(loadedListLock)
|
||||||
{
|
{
|
||||||
Interlocked.Add(ref CurrentMemoryUsage, -oldlln.Value.MemoryUsage);
|
Interlocked.Add(ref CurrentMemoryUsage, -oldlln.Value.MemoryUsage);
|
||||||
loadedListDict.Remove(oldlln.Value.Key);
|
loadedListDict.Remove(oldlln.Value.Key);
|
||||||
loadedList.Remove(oldlln); //gc should free up memory later..
|
loadedList.Remove(oldlln); //gc should free up memory later..
|
||||||
|
}
|
||||||
|
|
||||||
oldlln.Value = null;
|
oldlln.Value = null;
|
||||||
oldlln = null;
|
oldlln = null;
|
||||||
//GC.Collect();
|
//GC.Collect();
|
||||||
@ -86,10 +98,13 @@ namespace CodeWalker
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
if (CanAdd()) //see if there's enough memory now...
|
if (CanAdd()) //see if there's enough memory now...
|
||||||
|
{
|
||||||
|
lock(loadedListLock)
|
||||||
{
|
{
|
||||||
var newlln = loadedList.AddLast(item);
|
var newlln = loadedList.AddLast(item);
|
||||||
loadedListDict.Add(key, newlln);
|
loadedListDict.Add(key, newlln);
|
||||||
Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage);
|
Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -107,13 +122,22 @@ namespace CodeWalker
|
|||||||
|
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
|
{
|
||||||
|
lock(loadedList)
|
||||||
{
|
{
|
||||||
loadedList.Clear();
|
loadedList.Clear();
|
||||||
loadedListDict.Clear();
|
loadedListDict.Clear();
|
||||||
CurrentMemoryUsage = 0;
|
CurrentMemoryUsage = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Remove(TKey key)
|
public void Remove(TKey key)
|
||||||
|
{
|
||||||
|
if (!loadedListDict.ContainsKey(key))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lock(loadedListLock)
|
||||||
{
|
{
|
||||||
LinkedListNode<TVal> n;
|
LinkedListNode<TVal> n;
|
||||||
if (loadedListDict.TryGetValue(key, out n))
|
if (loadedListDict.TryGetValue(key, out n))
|
||||||
@ -123,9 +147,12 @@ namespace CodeWalker
|
|||||||
Interlocked.Add(ref CurrentMemoryUsage, -n.Value.MemoryUsage);
|
Interlocked.Add(ref CurrentMemoryUsage, -n.Value.MemoryUsage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Compact()
|
public void Compact()
|
||||||
|
{
|
||||||
|
lock(loadedList)
|
||||||
{
|
{
|
||||||
var oldlln = loadedList.First;
|
var oldlln = loadedList.First;
|
||||||
while (oldlln != null)
|
while (oldlln != null)
|
||||||
@ -135,10 +162,12 @@ namespace CodeWalker
|
|||||||
Interlocked.Add(ref CurrentMemoryUsage, -oldlln.Value.MemoryUsage);
|
Interlocked.Add(ref CurrentMemoryUsage, -oldlln.Value.MemoryUsage);
|
||||||
loadedListDict.Remove(oldlln.Value.Key);
|
loadedListDict.Remove(oldlln.Value.Key);
|
||||||
loadedList.Remove(oldlln); //gc should free up memory later..
|
loadedList.Remove(oldlln); //gc should free up memory later..
|
||||||
|
|
||||||
oldlln.Value = null;
|
oldlln.Value = null;
|
||||||
oldlln = nextln;
|
oldlln = nextln;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -781,7 +781,6 @@ namespace CodeWalker
|
|||||||
texParam.Unknown_30h = 1;// 131073;//wtf is this? 2x shorts, 0x00020001
|
texParam.Unknown_30h = 1;// 131073;//wtf is this? 2x shorts, 0x00020001
|
||||||
texParam.Unknown_32h = 2;
|
texParam.Unknown_32h = 2;
|
||||||
texParam.Name = name;
|
texParam.Name = name;
|
||||||
texParam.NameHash = JenkHash.GenHash(name.ToLowerInvariant());
|
|
||||||
return texParam;
|
return texParam;
|
||||||
}
|
}
|
||||||
private void AddShaderParam(List<ShaderParamNames> paramNames, List<ShaderParameter> paramValues, ShaderParamNames paramName, object paramValue)
|
private void AddShaderParam(List<ShaderParamNames> paramNames, List<ShaderParameter> paramValues, ShaderParamNames paramName, object paramValue)
|
||||||
|
35
CodeWalker.Core/Utils/Timer.cs
Normal file
35
CodeWalker.Core/Utils/Timer.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CodeWalker.Core.Utils
|
||||||
|
{
|
||||||
|
public class DisposableTimer : IDisposable
|
||||||
|
{
|
||||||
|
public static event Action<TimeSpan, string> TimerStopped;
|
||||||
|
public readonly Stopwatch _stopwatch;
|
||||||
|
|
||||||
|
static DisposableTimer()
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
TimerStopped += (timeSpan, name) => Debug.WriteLine($"{name} took {timeSpan.TotalMilliseconds} ms");
|
||||||
|
#endif
|
||||||
|
TimerStopped += (timeSpan, name) => Console.WriteLine($"{name} took {timeSpan.TotalMilliseconds} ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public DisposableTimer(string name)
|
||||||
|
{
|
||||||
|
_stopwatch = Stopwatch.StartNew();
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_stopwatch.Stop();
|
||||||
|
TimerStopped?.Invoke(_stopwatch.Elapsed, Name ?? string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -100,6 +101,10 @@ namespace CodeWalker
|
|||||||
}
|
}
|
||||||
return Encoding.UTF8.GetString(bytes);
|
return Encoding.UTF8.GetString(bytes);
|
||||||
}
|
}
|
||||||
|
public static bool Contains(this string source, string toCheck, StringComparison comp)
|
||||||
|
{
|
||||||
|
return source?.IndexOf(toCheck, comp) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,5 +276,23 @@ namespace CodeWalker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class SpanExtensions
|
||||||
|
{
|
||||||
|
public static int Read(this Stream stream, Span<byte> buffer)
|
||||||
|
{
|
||||||
|
var n = Math.Min(stream.Length - stream.Position, buffer.Length);
|
||||||
|
if (n <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < buffer.Length; i++)
|
||||||
|
{
|
||||||
|
var result = stream.ReadByte();
|
||||||
|
buffer[i] = (byte)result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>CW.ico</ApplicationIcon>
|
<ApplicationIcon>CW.ico</ApplicationIcon>
|
||||||
<AssemblyName>CodeWalker Error Report Tool</AssemblyName>
|
<AssemblyName>CodeWalker Error Report Tool</AssemblyName>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -15,6 +15,11 @@
|
|||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||||
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\CodeWalker\CodeWalker.csproj" />
|
<ProjectReference Include="..\CodeWalker\CodeWalker.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -10,12 +10,18 @@
|
|||||||
<Company>dexyfex software</Company>
|
<Company>dexyfex software</Company>
|
||||||
<Authors>dexyfex</Authors>
|
<Authors>dexyfex</Authors>
|
||||||
<AssemblyName>CodeWalker RPF Explorer</AssemblyName>
|
<AssemblyName>CodeWalker RPF Explorer</AssemblyName>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||||
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\CodeWalker\CodeWalker.csproj" />
|
<ProjectReference Include="..\CodeWalker\CodeWalker.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -6,6 +6,7 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using CodeWalker.Utils;
|
||||||
|
|
||||||
namespace CodeWalker.RPFExplorer
|
namespace CodeWalker.RPFExplorer
|
||||||
{
|
{
|
||||||
@ -18,7 +19,7 @@ namespace CodeWalker.RPFExplorer
|
|||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
//Process.Start("CodeWalker.exe", "explorer");
|
//Process.Start("CodeWalker.exe", "explorer");
|
||||||
|
ConsoleWindow.Hide();
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
Application.Run(new ExploreForm());
|
Application.Run(new ExploreForm());
|
||||||
|
@ -9,6 +9,22 @@ struct VS_INPUT
|
|||||||
float4 Tangent : TANGENT;
|
float4 Tangent : TANGENT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PNCTX_OUTPUT
|
||||||
|
{
|
||||||
|
float4 Position : SV_POSITION;
|
||||||
|
float3 Normal : NORMAL;
|
||||||
|
float2 Texcoord0 : TEXCOORD0;
|
||||||
|
float2 Texcoord1 : TEXCOORD1;
|
||||||
|
float2 Texcoord2 : TEXCOORD2;
|
||||||
|
float4 Shadows : TEXCOORD3;
|
||||||
|
float4 LightShadow : TEXCOORD4;
|
||||||
|
float4 Colour0 : COLOR0;
|
||||||
|
float4 Colour1 : COLOR1;
|
||||||
|
float4 Tint : COLOR2;
|
||||||
|
float4 Tangent : TEXCOORD5;
|
||||||
|
float4 Bitangent : TEXCOORD6;
|
||||||
|
float3 CamRelPos : TEXCOORD7;
|
||||||
|
};
|
||||||
|
|
||||||
VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID)
|
VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID)
|
||||||
{
|
{
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
<FxCompile>
|
<FxCompile>
|
||||||
<ObjectFileOutput>$(ProjectDir)..\Shaders\%(Filename).cso</ObjectFileOutput>
|
<ObjectFileOutput>$(ProjectDir)..\Shaders\%(Filename).cso</ObjectFileOutput>
|
||||||
<ShaderModel>4.0</ShaderModel>
|
<ShaderModel>4.0</ShaderModel>
|
||||||
|
<EnableDebuggingInformation>true</EnableDebuggingInformation>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ShaderGlobalLightParams
|
struct ShaderGlobalLightParams
|
||||||
{
|
{
|
||||||
float3 LightDir;
|
float3 LightDir;
|
||||||
|
@ -17,7 +17,8 @@ PS_OUTPUT main(VS_Output input)
|
|||||||
{
|
{
|
||||||
uint3 ssloc = uint3(input.Pos.xy, 0); //pixel location
|
uint3 ssloc = uint3(input.Pos.xy, 0); //pixel location
|
||||||
float depth = DepthTex.Load(ssloc).r;
|
float depth = DepthTex.Load(ssloc).r;
|
||||||
if (depth == 0) discard; //no existing pixel rendered here
|
if (depth <= 0)
|
||||||
|
discard; //no existing pixel rendered here
|
||||||
|
|
||||||
float4 diffuse = DiffuseTex.Load(ssloc);
|
float4 diffuse = DiffuseTex.Load(ssloc);
|
||||||
float4 normal = NormalTex.Load(ssloc);
|
float4 normal = NormalTex.Load(ssloc);
|
||||||
@ -29,9 +30,15 @@ PS_OUTPUT main(VS_Output input)
|
|||||||
|
|
||||||
switch (RenderMode)
|
switch (RenderMode)
|
||||||
{
|
{
|
||||||
case 5: output.Colour = float4(diffuse.rgb, 1); return output;
|
case 5:
|
||||||
case 6: output.Colour = float4(normal.rgb, 1); return output;
|
output.Colour = float4(diffuse.rgb, 1);
|
||||||
case 7: output.Colour = float4(specular.rgb, 1); return output;
|
return output;
|
||||||
|
case 6:
|
||||||
|
output.Colour = float4(normal.rgb, 1);
|
||||||
|
return output;
|
||||||
|
case 7:
|
||||||
|
output.Colour = float4(specular.rgb, 1);
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 spos = float4(input.Screen.xy/input.Screen.w, depth, 1);
|
float4 spos = float4(input.Screen.xy/input.Screen.w, depth, 1);
|
||||||
|
@ -34,7 +34,8 @@ PS_OUTPUT main(VS_Output input)
|
|||||||
for (int i = 0; i < sc; i++)
|
for (int i = 0; i < sc; i++)
|
||||||
{
|
{
|
||||||
float depth = DepthTex.Load(ssloc, i);
|
float depth = DepthTex.Load(ssloc, i);
|
||||||
if (depth == 0) continue; //no existing subpixel rendered here
|
if (depth == 0)
|
||||||
|
continue; //no existing subpixel rendered here
|
||||||
|
|
||||||
float4 diffuse = DiffuseTex.Load(ssloc, i);
|
float4 diffuse = DiffuseTex.Load(ssloc, i);
|
||||||
float4 normal = NormalTex.Load(ssloc, i);
|
float4 normal = NormalTex.Load(ssloc, i);
|
||||||
@ -56,7 +57,8 @@ PS_OUTPUT main(VS_Output input)
|
|||||||
d *= SampleMult;
|
d *= SampleMult;
|
||||||
a *= SampleMult;
|
a *= SampleMult;
|
||||||
|
|
||||||
if (d <= 0) discard;
|
if (d <= 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
PS_OUTPUT output;
|
PS_OUTPUT output;
|
||||||
output.Colour = float4(c, a);
|
output.Colour = float4(c, a);
|
||||||
|
@ -18,7 +18,8 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
{
|
{
|
||||||
uint3 ssloc = uint3(input.Pos.xy, 0); //pixel location
|
uint3 ssloc = uint3(input.Pos.xy, 0); //pixel location
|
||||||
float depth = DepthTex.Load(ssloc).r;
|
float depth = DepthTex.Load(ssloc).r;
|
||||||
if (depth == 0) discard; //no existing pixel rendered here
|
if (depth == 0)
|
||||||
|
discard; //no existing pixel rendered here
|
||||||
|
|
||||||
float4 diffuse = DiffuseTex.Load(ssloc);
|
float4 diffuse = DiffuseTex.Load(ssloc);
|
||||||
float4 normal = NormalTex.Load(ssloc);
|
float4 normal = NormalTex.Load(ssloc);
|
||||||
@ -31,7 +32,8 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
float3 norm = normal.xyz * 2 - 1;
|
float3 norm = normal.xyz * 2 - 1;
|
||||||
|
|
||||||
float4 lcol = DeferredLight(camRel, norm, diffuse, specular, irradiance);
|
float4 lcol = DeferredLight(camRel, norm, diffuse, specular, irradiance);
|
||||||
if (lcol.a <= 0) discard;
|
if (lcol.a <= 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
return lcol;
|
return lcol;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,7 @@ float4 DeferredLODLight(float3 camRel, float3 norm, float4 diffuse, float4 specu
|
|||||||
LODLight lodlight = LODLights[iid];
|
LODLight lodlight = LODLights[iid];
|
||||||
float3 srpos = lodlight.Position - (camRel + CameraPos.xyz); //light position relative to surface position
|
float3 srpos = lodlight.Position - (camRel + CameraPos.xyz); //light position relative to surface position
|
||||||
float ldist = length(srpos);
|
float ldist = length(srpos);
|
||||||
|
|
||||||
if (LightType == 4)//capsule
|
if (LightType == 4)//capsule
|
||||||
{
|
{
|
||||||
float3 ext = lodlight.Direction.xyz * lodlight.OuterAngleOrCapExt;
|
float3 ext = lodlight.Direction.xyz * lodlight.OuterAngleOrCapExt;
|
||||||
@ -125,13 +126,16 @@ float4 DeferredLODLight(float3 camRel, float3 norm, float4 diffuse, float4 specu
|
|||||||
srpos.xyz = lsn.xyz;
|
srpos.xyz = lsn.xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ldist > lodlight.Falloff) return 0; //out of range of the light...
|
if (ldist > lodlight.Falloff)
|
||||||
if (ldist <= 0) return 0;
|
return 0; //out of range of the light...
|
||||||
|
if (ldist <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
float4 rgbi = Unpack4x8UNF(lodlight.Colour).gbar;
|
float4 rgbi = Unpack4x8UNF(lodlight.Colour).gbar;
|
||||||
float3 lcol = rgbi.rgb * rgbi.a * 96.0f;
|
float3 lcol = rgbi.rgb * rgbi.a * 96.0f;
|
||||||
float3 ldir = srpos / ldist;
|
float3 ldir = srpos / ldist;
|
||||||
float pclit = saturate(dot(ldir, norm));
|
float pclit = saturate(dot(ldir, norm));
|
||||||
|
|
||||||
float lamt = 1;
|
float lamt = 1;
|
||||||
|
|
||||||
if (LightType == 1)//point (sphere)
|
if (LightType == 1)//point (sphere)
|
||||||
@ -154,7 +158,8 @@ float4 DeferredLODLight(float3 camRel, float3 norm, float4 diffuse, float4 specu
|
|||||||
|
|
||||||
pclit *= lamt;
|
pclit *= lamt;
|
||||||
|
|
||||||
if (pclit <= 0) return 0;
|
if (pclit <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
float3 refl = GetReflectedDir(camRel, norm);
|
float3 refl = GetReflectedDir(camRel, norm);
|
||||||
float specb = saturate(dot(refl, ldir));
|
float specb = saturate(dot(refl, ldir));
|
||||||
@ -177,11 +182,14 @@ float4 DeferredLight(float3 camRel, float3 norm, float4 diffuse, float4 specular
|
|||||||
ldist = lsn.w;
|
ldist = lsn.w;
|
||||||
srpos.xyz = lsn.xyz;
|
srpos.xyz = lsn.xyz;
|
||||||
}
|
}
|
||||||
if (ldist > InstFalloff) return 0;
|
if (ldist > InstFalloff)
|
||||||
if (ldist <= 0) return 0;
|
return 0;
|
||||||
|
if (ldist <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
float d = dot(srpos, InstCullingPlaneNormal) - InstCullingPlaneOffset;
|
float d = dot(srpos, InstCullingPlaneNormal) - InstCullingPlaneOffset;
|
||||||
if (d > 0) return 0;
|
if (d > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
float4 rgbi = float4(InstColour, InstIntensity);
|
float4 rgbi = float4(InstColour, InstIntensity);
|
||||||
float3 lcol = rgbi.rgb;// * rgbi.a; // * 5.0f;
|
float3 lcol = rgbi.rgb;// * rgbi.a; // * 5.0f;
|
||||||
@ -198,7 +206,8 @@ float4 DeferredLight(float3 camRel, float3 norm, float4 diffuse, float4 specular
|
|||||||
float ang = acos(-dot(ldir, InstDirection));
|
float ang = acos(-dot(ldir, InstDirection));
|
||||||
float iang = InstConeInnerAngle;
|
float iang = InstConeInnerAngle;
|
||||||
float oang = InstConeOuterAngle;
|
float oang = InstConeOuterAngle;
|
||||||
if (ang > oang) return 0;
|
if (ang > oang)
|
||||||
|
return 0;
|
||||||
lamt *= saturate(1 - ((ang - iang) / (oang - iang)));
|
lamt *= saturate(1 - ((ang - iang) / (oang - iang)));
|
||||||
lamt *= GetAttenuation(ldist, InstFalloff, InstFalloffExponent);
|
lamt *= GetAttenuation(ldist, InstFalloff, InstFalloffExponent);
|
||||||
}
|
}
|
||||||
@ -209,7 +218,8 @@ float4 DeferredLight(float3 camRel, float3 norm, float4 diffuse, float4 specular
|
|||||||
|
|
||||||
pclit *= lamt;
|
pclit *= lamt;
|
||||||
|
|
||||||
if (pclit <= 0) return 0;
|
if (pclit <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
float3 refl = GetReflectedDir(camRel, norm);
|
float3 refl = GetReflectedDir(camRel, norm);
|
||||||
float specb = saturate(dot(refl, ldir));
|
float specb = saturate(dot(refl, ldir));
|
||||||
|
@ -18,14 +18,14 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
uint2 ssloc = uint2(input.Pos.xy); //pixel location
|
uint2 ssloc = uint2(input.Pos.xy); //pixel location
|
||||||
float2 spos = float2(input.Screen.xy / input.Screen.w);
|
float2 spos = float2(input.Screen.xy / input.Screen.w);
|
||||||
float4 c = 0;
|
float4 c = 0;
|
||||||
float d = 0;
|
|
||||||
int sc = min(SampleCount, 8);
|
int sc = min(SampleCount, 8);
|
||||||
|
|
||||||
[unroll]
|
[unroll]
|
||||||
for (int i = 0; i < sc; i++)
|
for (int i = 0; i < sc; i++)
|
||||||
{
|
{
|
||||||
float depth = DepthTex.Load(ssloc, i);
|
float depth = DepthTex.Load(ssloc, i);
|
||||||
if (depth == 0) continue; //no existing subpixel rendered here
|
if (depth == 0)
|
||||||
|
continue; //no existing subpixel rendered here
|
||||||
|
|
||||||
float4 diffuse = DiffuseTex.Load(ssloc, i);
|
float4 diffuse = DiffuseTex.Load(ssloc, i);
|
||||||
float4 normal = NormalTex.Load(ssloc, i);
|
float4 normal = NormalTex.Load(ssloc, i);
|
||||||
@ -37,15 +37,16 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
float3 norm = normal.xyz * 2 - 1;
|
float3 norm = normal.xyz * 2 - 1;
|
||||||
|
|
||||||
float4 colour = DeferredLight(camRel, norm, diffuse, specular, irradiance);
|
float4 colour = DeferredLight(camRel, norm, diffuse, specular, irradiance);
|
||||||
|
if (colour.a <= 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
c += colour;
|
c += colour;
|
||||||
d += depth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c *= SampleMult;
|
c *= SampleMult;
|
||||||
d *= SampleMult;
|
|
||||||
|
|
||||||
if (d <= 0) discard;
|
if (c.a <= 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
{
|
{
|
||||||
uint3 ssloc = uint3(input.Pos.xy, 0); //pixel location
|
uint3 ssloc = uint3(input.Pos.xy, 0); //pixel location
|
||||||
float depth = DepthTex.Load(ssloc).r;
|
float depth = DepthTex.Load(ssloc).r;
|
||||||
if (depth == 0) discard; //no existing pixel rendered here
|
if (depth == 0)
|
||||||
|
discard; //no existing pixel rendered here
|
||||||
|
|
||||||
float4 diffuse = DiffuseTex.Load(ssloc);
|
float4 diffuse = DiffuseTex.Load(ssloc);
|
||||||
float4 normal = NormalTex.Load(ssloc);
|
float4 normal = NormalTex.Load(ssloc);
|
||||||
@ -31,7 +32,8 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
float3 norm = normal.xyz * 2 - 1;
|
float3 norm = normal.xyz * 2 - 1;
|
||||||
|
|
||||||
float4 lcol = DeferredLODLight(camRel, norm, diffuse, specular, irradiance, input.IID);
|
float4 lcol = DeferredLODLight(camRel, norm, diffuse, specular, irradiance, input.IID);
|
||||||
if (lcol.a <= 0) discard;
|
if (lcol.a <= 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
return lcol;
|
return lcol;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
for (int i = 0; i < sc; i++)
|
for (int i = 0; i < sc; i++)
|
||||||
{
|
{
|
||||||
float depth = DepthTex.Load(ssloc, i);
|
float depth = DepthTex.Load(ssloc, i);
|
||||||
if (depth == 0) continue; //no existing subpixel rendered here
|
if (depth == 0)
|
||||||
|
continue; //no existing subpixel rendered here
|
||||||
|
|
||||||
float4 diffuse = DiffuseTex.Load(ssloc, i);
|
float4 diffuse = DiffuseTex.Load(ssloc, i);
|
||||||
float4 normal = NormalTex.Load(ssloc, i);
|
float4 normal = NormalTex.Load(ssloc, i);
|
||||||
@ -38,15 +39,16 @@ float4 main(VS_Output input) : SV_TARGET
|
|||||||
float3 norm = normal.xyz * 2 - 1;
|
float3 norm = normal.xyz * 2 - 1;
|
||||||
|
|
||||||
float4 colour = DeferredLODLight(camRel, norm, diffuse, specular, irradiance, input.IID);
|
float4 colour = DeferredLODLight(camRel, norm, diffuse, specular, irradiance, input.IID);
|
||||||
|
if (colour.a <= 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
c += colour;
|
c += colour;
|
||||||
d += depth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c *= SampleMult;
|
c *= SampleMult;
|
||||||
d *= SampleMult;
|
|
||||||
|
|
||||||
if (d <= 0) discard;
|
if (c.a <= 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ struct LODLight
|
|||||||
float FalloffExponent;
|
float FalloffExponent;
|
||||||
float InnerAngle; //for cone
|
float InnerAngle; //for cone
|
||||||
float OuterAngleOrCapExt; //outer angle for cone, cap extent for capsule
|
float OuterAngleOrCapExt; //outer angle for cone, cap extent for capsule
|
||||||
|
float Distance;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VS_Output
|
struct VS_Output
|
||||||
|
@ -9,12 +9,18 @@
|
|||||||
<Company>dexyfex software</Company>
|
<Company>dexyfex software</Company>
|
||||||
<Authors>dexyfex</Authors>
|
<Authors>dexyfex</Authors>
|
||||||
<AssemblyName>CodeWalker Vehicle Viewer</AssemblyName>
|
<AssemblyName>CodeWalker Vehicle Viewer</AssemblyName>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||||
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\CodeWalker\CodeWalker.csproj" />
|
<ProjectReference Include="..\CodeWalker\CodeWalker.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<TargetFramework>net48</TargetFramework>
|
<TargetFramework>net48</TargetFramework>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -43,27 +43,6 @@
|
|||||||
<setting name="Skydome" serializeAs="String">
|
<setting name="Skydome" serializeAs="String">
|
||||||
<value>True</value>
|
<value>True</value>
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="TimeOfDay" serializeAs="String">
|
|
||||||
<value>720</value>
|
|
||||||
</setting>
|
|
||||||
<setting name="LODLights" serializeAs="String">
|
|
||||||
<value>True</value>
|
|
||||||
</setting>
|
|
||||||
<setting name="Region" serializeAs="String">
|
|
||||||
<value>Global</value>
|
|
||||||
</setting>
|
|
||||||
<setting name="Clouds" serializeAs="String">
|
|
||||||
<value>contrails</value>
|
|
||||||
</setting>
|
|
||||||
<setting name="Weather" serializeAs="String">
|
|
||||||
<value>True</value>
|
|
||||||
</setting>
|
|
||||||
<setting name="NatrualAmbientLight" serializeAs="String">
|
|
||||||
<value>True</value>
|
|
||||||
</setting>
|
|
||||||
<setting name="ArtificialAmbientLight" serializeAs="String">
|
|
||||||
<value>True</value>
|
|
||||||
</setting>
|
|
||||||
<setting name="ShowTimedEntities" serializeAs="String">
|
<setting name="ShowTimedEntities" serializeAs="String">
|
||||||
<value>True</value>
|
<value>True</value>
|
||||||
</setting>
|
</setting>
|
||||||
@ -247,6 +226,30 @@
|
|||||||
<setting name="RPFExplorerStartFolder" serializeAs="String">
|
<setting name="RPFExplorerStartFolder" serializeAs="String">
|
||||||
<value />
|
<value />
|
||||||
</setting>
|
</setting>
|
||||||
|
<setting name="TimeOfDay" serializeAs="String">
|
||||||
|
<value>720</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="LODLights" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Region" serializeAs="String">
|
||||||
|
<value>Global</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Clouds" serializeAs="String">
|
||||||
|
<value>contrails</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Weather" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="NatrualAmbientLight" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="ArtificialAmbientLight" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="AntiAliasing" serializeAs="String">
|
||||||
|
<value>2</value>
|
||||||
|
</setting>
|
||||||
</CodeWalker.Properties.Settings>
|
</CodeWalker.Properties.Settings>
|
||||||
</userSettings>
|
</userSettings>
|
||||||
<runtime>
|
<runtime>
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<Copyright>dexyfex</Copyright>
|
<Copyright>dexyfex</Copyright>
|
||||||
<Company>dexyfex software</Company>
|
<Company>dexyfex software</Company>
|
||||||
<Authors>dexyfex</Authors>
|
<Authors>dexyfex</Authors>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
@ -18,6 +19,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DockPanelSuite.ThemeVS2015" Version="3.0.6" />
|
<PackageReference Include="DockPanelSuite.ThemeVS2015" Version="3.0.6" />
|
||||||
<PackageReference Include="FCTB" Version="2.16.24" />
|
<PackageReference Include="FCTB" Version="2.16.24" />
|
||||||
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||||
<PackageReference Include="SharpDX" Version="4.2.0" />
|
<PackageReference Include="SharpDX" Version="4.2.0" />
|
||||||
<PackageReference Include="SharpDX.D3DCompiler" Version="4.2.0" />
|
<PackageReference Include="SharpDX.D3DCompiler" Version="4.2.0" />
|
||||||
<PackageReference Include="SharpDX.Direct2D1" Version="4.2.0" />
|
<PackageReference Include="SharpDX.Direct2D1" Version="4.2.0" />
|
||||||
@ -25,6 +27,7 @@
|
|||||||
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
|
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
|
||||||
<PackageReference Include="SharpDX.XAudio2" Version="4.2.0" />
|
<PackageReference Include="SharpDX.XAudio2" Version="4.2.0" />
|
||||||
<PackageReference Include="SharpDX.XInput" Version="4.2.0" />
|
<PackageReference Include="SharpDX.XInput" Version="4.2.0" />
|
||||||
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
36
CodeWalker/ExploreForm.Designer.cs
generated
36
CodeWalker/ExploreForm.Designer.cs
generated
@ -1,4 +1,6 @@
|
|||||||
namespace CodeWalker
|
using CodeWalker.Core.Utils;
|
||||||
|
|
||||||
|
namespace CodeWalker
|
||||||
{
|
{
|
||||||
partial class ExploreForm
|
partial class ExploreForm
|
||||||
{
|
{
|
||||||
@ -158,6 +160,7 @@
|
|||||||
this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog();
|
this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog();
|
||||||
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
|
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
|
||||||
this.VSExtender = new WeifenLuo.WinFormsUI.Docking.VisualStudioToolStripExtender(this.components);
|
this.VSExtender = new WeifenLuo.WinFormsUI.Docking.VisualStudioToolStripExtender(this.components);
|
||||||
|
this.openConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.MainMenu.SuspendLayout();
|
this.MainMenu.SuspendLayout();
|
||||||
this.MainToolbar.SuspendLayout();
|
this.MainToolbar.SuspendLayout();
|
||||||
this.MainStatusBar.SuspendLayout();
|
this.MainStatusBar.SuspendLayout();
|
||||||
@ -409,6 +412,7 @@
|
|||||||
this.ViewSmallIconsMenu,
|
this.ViewSmallIconsMenu,
|
||||||
this.ViewListMenu,
|
this.ViewListMenu,
|
||||||
this.ViewDetailsMenu,
|
this.ViewDetailsMenu,
|
||||||
|
this.openConsoleToolStripMenuItem,
|
||||||
this.toolStripSeparator11,
|
this.toolStripSeparator11,
|
||||||
this.ViewThemeMenu});
|
this.ViewThemeMenu});
|
||||||
this.ViewMenu.Name = "ViewMenu";
|
this.ViewMenu.Name = "ViewMenu";
|
||||||
@ -418,21 +422,21 @@
|
|||||||
// ViewLargeIconsMenu
|
// ViewLargeIconsMenu
|
||||||
//
|
//
|
||||||
this.ViewLargeIconsMenu.Name = "ViewLargeIconsMenu";
|
this.ViewLargeIconsMenu.Name = "ViewLargeIconsMenu";
|
||||||
this.ViewLargeIconsMenu.Size = new System.Drawing.Size(134, 22);
|
this.ViewLargeIconsMenu.Size = new System.Drawing.Size(180, 22);
|
||||||
this.ViewLargeIconsMenu.Text = "Large Icons";
|
this.ViewLargeIconsMenu.Text = "Large Icons";
|
||||||
this.ViewLargeIconsMenu.Click += new System.EventHandler(this.ViewLargeIconsMenu_Click);
|
this.ViewLargeIconsMenu.Click += new System.EventHandler(this.ViewLargeIconsMenu_Click);
|
||||||
//
|
//
|
||||||
// ViewSmallIconsMenu
|
// ViewSmallIconsMenu
|
||||||
//
|
//
|
||||||
this.ViewSmallIconsMenu.Name = "ViewSmallIconsMenu";
|
this.ViewSmallIconsMenu.Name = "ViewSmallIconsMenu";
|
||||||
this.ViewSmallIconsMenu.Size = new System.Drawing.Size(134, 22);
|
this.ViewSmallIconsMenu.Size = new System.Drawing.Size(180, 22);
|
||||||
this.ViewSmallIconsMenu.Text = "Small Icons";
|
this.ViewSmallIconsMenu.Text = "Small Icons";
|
||||||
this.ViewSmallIconsMenu.Click += new System.EventHandler(this.ViewSmallIconsMenu_Click);
|
this.ViewSmallIconsMenu.Click += new System.EventHandler(this.ViewSmallIconsMenu_Click);
|
||||||
//
|
//
|
||||||
// ViewListMenu
|
// ViewListMenu
|
||||||
//
|
//
|
||||||
this.ViewListMenu.Name = "ViewListMenu";
|
this.ViewListMenu.Name = "ViewListMenu";
|
||||||
this.ViewListMenu.Size = new System.Drawing.Size(134, 22);
|
this.ViewListMenu.Size = new System.Drawing.Size(180, 22);
|
||||||
this.ViewListMenu.Text = "List";
|
this.ViewListMenu.Text = "List";
|
||||||
this.ViewListMenu.Click += new System.EventHandler(this.ViewListMenu_Click);
|
this.ViewListMenu.Click += new System.EventHandler(this.ViewListMenu_Click);
|
||||||
//
|
//
|
||||||
@ -441,14 +445,14 @@
|
|||||||
this.ViewDetailsMenu.Checked = true;
|
this.ViewDetailsMenu.Checked = true;
|
||||||
this.ViewDetailsMenu.CheckState = System.Windows.Forms.CheckState.Checked;
|
this.ViewDetailsMenu.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||||
this.ViewDetailsMenu.Name = "ViewDetailsMenu";
|
this.ViewDetailsMenu.Name = "ViewDetailsMenu";
|
||||||
this.ViewDetailsMenu.Size = new System.Drawing.Size(134, 22);
|
this.ViewDetailsMenu.Size = new System.Drawing.Size(180, 22);
|
||||||
this.ViewDetailsMenu.Text = "Details";
|
this.ViewDetailsMenu.Text = "Details";
|
||||||
this.ViewDetailsMenu.Click += new System.EventHandler(this.ViewDetailsMenu_Click);
|
this.ViewDetailsMenu.Click += new System.EventHandler(this.ViewDetailsMenu_Click);
|
||||||
//
|
//
|
||||||
// toolStripSeparator11
|
// toolStripSeparator11
|
||||||
//
|
//
|
||||||
this.toolStripSeparator11.Name = "toolStripSeparator11";
|
this.toolStripSeparator11.Name = "toolStripSeparator11";
|
||||||
this.toolStripSeparator11.Size = new System.Drawing.Size(131, 6);
|
this.toolStripSeparator11.Size = new System.Drawing.Size(177, 6);
|
||||||
//
|
//
|
||||||
// ViewThemeMenu
|
// ViewThemeMenu
|
||||||
//
|
//
|
||||||
@ -458,7 +462,7 @@
|
|||||||
this.ViewThemeLightMenu,
|
this.ViewThemeLightMenu,
|
||||||
this.ViewThemeDarkMenu});
|
this.ViewThemeDarkMenu});
|
||||||
this.ViewThemeMenu.Name = "ViewThemeMenu";
|
this.ViewThemeMenu.Name = "ViewThemeMenu";
|
||||||
this.ViewThemeMenu.Size = new System.Drawing.Size(134, 22);
|
this.ViewThemeMenu.Size = new System.Drawing.Size(180, 22);
|
||||||
this.ViewThemeMenu.Text = "Theme";
|
this.ViewThemeMenu.Text = "Theme";
|
||||||
//
|
//
|
||||||
// ViewThemeWindowsMenu
|
// ViewThemeWindowsMenu
|
||||||
@ -506,35 +510,35 @@
|
|||||||
// ToolsBinSearchMenu
|
// ToolsBinSearchMenu
|
||||||
//
|
//
|
||||||
this.ToolsBinSearchMenu.Name = "ToolsBinSearchMenu";
|
this.ToolsBinSearchMenu.Name = "ToolsBinSearchMenu";
|
||||||
this.ToolsBinSearchMenu.Size = new System.Drawing.Size(180, 22);
|
this.ToolsBinSearchMenu.Size = new System.Drawing.Size(161, 22);
|
||||||
this.ToolsBinSearchMenu.Text = "Binary Search...";
|
this.ToolsBinSearchMenu.Text = "Binary Search...";
|
||||||
this.ToolsBinSearchMenu.Click += new System.EventHandler(this.ToolsBinSearchMenu_Click);
|
this.ToolsBinSearchMenu.Click += new System.EventHandler(this.ToolsBinSearchMenu_Click);
|
||||||
//
|
//
|
||||||
// ToolsAudioExplorerMenu
|
// ToolsAudioExplorerMenu
|
||||||
//
|
//
|
||||||
this.ToolsAudioExplorerMenu.Name = "ToolsAudioExplorerMenu";
|
this.ToolsAudioExplorerMenu.Name = "ToolsAudioExplorerMenu";
|
||||||
this.ToolsAudioExplorerMenu.Size = new System.Drawing.Size(180, 22);
|
this.ToolsAudioExplorerMenu.Size = new System.Drawing.Size(161, 22);
|
||||||
this.ToolsAudioExplorerMenu.Text = "Audio Explorer";
|
this.ToolsAudioExplorerMenu.Text = "Audio Explorer";
|
||||||
this.ToolsAudioExplorerMenu.Click += new System.EventHandler(this.ToolsAudioExplorerMenu_Click);
|
this.ToolsAudioExplorerMenu.Click += new System.EventHandler(this.ToolsAudioExplorerMenu_Click);
|
||||||
//
|
//
|
||||||
// ToolsRpfBrowserMenu
|
// ToolsRpfBrowserMenu
|
||||||
//
|
//
|
||||||
this.ToolsRpfBrowserMenu.Name = "ToolsRpfBrowserMenu";
|
this.ToolsRpfBrowserMenu.Name = "ToolsRpfBrowserMenu";
|
||||||
this.ToolsRpfBrowserMenu.Size = new System.Drawing.Size(180, 22);
|
this.ToolsRpfBrowserMenu.Size = new System.Drawing.Size(161, 22);
|
||||||
this.ToolsRpfBrowserMenu.Text = "Old RPF Browser";
|
this.ToolsRpfBrowserMenu.Text = "Old RPF Browser";
|
||||||
this.ToolsRpfBrowserMenu.Click += new System.EventHandler(this.ToolsRpfBrowserMenu_Click);
|
this.ToolsRpfBrowserMenu.Click += new System.EventHandler(this.ToolsRpfBrowserMenu_Click);
|
||||||
//
|
//
|
||||||
// ToolsJenkGenMenu
|
// ToolsJenkGenMenu
|
||||||
//
|
//
|
||||||
this.ToolsJenkGenMenu.Name = "ToolsJenkGenMenu";
|
this.ToolsJenkGenMenu.Name = "ToolsJenkGenMenu";
|
||||||
this.ToolsJenkGenMenu.Size = new System.Drawing.Size(180, 22);
|
this.ToolsJenkGenMenu.Size = new System.Drawing.Size(161, 22);
|
||||||
this.ToolsJenkGenMenu.Text = "JenkGen";
|
this.ToolsJenkGenMenu.Text = "JenkGen";
|
||||||
this.ToolsJenkGenMenu.Click += new System.EventHandler(this.ToolsJenkGenMenu_Click);
|
this.ToolsJenkGenMenu.Click += new System.EventHandler(this.ToolsJenkGenMenu_Click);
|
||||||
//
|
//
|
||||||
// ToolsJenkIndMenu
|
// ToolsJenkIndMenu
|
||||||
//
|
//
|
||||||
this.ToolsJenkIndMenu.Name = "ToolsJenkIndMenu";
|
this.ToolsJenkIndMenu.Name = "ToolsJenkIndMenu";
|
||||||
this.ToolsJenkIndMenu.Size = new System.Drawing.Size(180, 22);
|
this.ToolsJenkIndMenu.Size = new System.Drawing.Size(161, 22);
|
||||||
this.ToolsJenkIndMenu.Text = "JenkInd";
|
this.ToolsJenkIndMenu.Text = "JenkInd";
|
||||||
this.ToolsJenkIndMenu.Click += new System.EventHandler(this.ToolsJenkIndMenu_Click);
|
this.ToolsJenkIndMenu.Click += new System.EventHandler(this.ToolsJenkIndMenu_Click);
|
||||||
//
|
//
|
||||||
@ -1308,6 +1312,13 @@
|
|||||||
//
|
//
|
||||||
this.VSExtender.DefaultRenderer = null;
|
this.VSExtender.DefaultRenderer = null;
|
||||||
//
|
//
|
||||||
|
// openConsoleToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.openConsoleToolStripMenuItem.Name = "openConsoleToolStripMenuItem";
|
||||||
|
this.openConsoleToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
|
||||||
|
this.openConsoleToolStripMenuItem.Text = "Open Console";
|
||||||
|
this.openConsoleToolStripMenuItem.Click += new System.EventHandler(this.ViewConsoleMenu_Click);
|
||||||
|
//
|
||||||
// ExploreForm
|
// ExploreForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
@ -1476,5 +1487,6 @@
|
|||||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator13;
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator13;
|
||||||
private System.Windows.Forms.ToolStripMenuItem ListContextNewYtdFileMenu;
|
private System.Windows.Forms.ToolStripMenuItem ListContextNewYtdFileMenu;
|
||||||
private System.Windows.Forms.ToolStripMenuItem ToolsAudioExplorerMenu;
|
private System.Windows.Forms.ToolStripMenuItem ToolsAudioExplorerMenu;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem openConsoleToolStripMenuItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -124,7 +124,7 @@
|
|||||||
<data name="EditViewMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditViewMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAQFJREFUOE+dkz0LglAUhv0H/ZLA3+De1FrQ4NJkY9Du3FRLEAZuRVNQS2FLRDQE
|
vwAADr8BOAVTJAAAAQFJREFUOE+dkz0LglAUhv0H/ZLA3+De1FrQ4NJkY9Du3FRLEAZuRVNQS2FLRDQE
|
||||||
UWu0BBX4Mbie7nvxmslNrQMPXI/nfTgXUUlXGIaUgctQo1F5YVDTNCmmaeZLsgQgV5IUeK7/QSFJEUFS
|
UWu0BBX4Mbie7nvxmslNrQMPXI/nfTgXUUlXGIaUgctQo1F5YVDTNCmmaeZLsgQgV5IUeK7/QSFJEUFS
|
||||||
EsXelSUQiPeYjWLvQtMwDNJ1XRoGXwWsMTxfH9Sxt5zT5U6+FxQTsIfGYn+hUt2itrWhZt9h5xGXFBVM
|
EsXelSUQiPeYjWLvQtMwDNJ1XRoGXwWsMTxfH9Sxt5zT5U6+FxQTsIfGYn+hUt2itrWhZt9h5xGXFBVM
|
||||||
K+acerNDPAgJNklv8U2wgsBenuJBbAJB4OcI2EFluBCUW2MuwSa4jrM7xoE0XCDCte6SlOqAIBFM1kf+
|
K+acerNDPAgJNklv8U2wgsBenuJBbAJB4OcI2EFluBCUW2MuwSa4jrM7xoE0XCDCte6SlOqAIBFM1kf+
|
||||||
@ -134,7 +134,7 @@
|
|||||||
<data name="EditViewHexMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditViewHexMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAGlJREFUOE/ljlsKgEAIRV1Sa3BxbncKxN9CUKbCdIboqwsHxMdB8IjIntCYebHV
|
vgAADr4B6kKxwAAAAGlJREFUOE/ljlsKgEAIRV1Sa3BxbncKxN9CUKbCdIboqwsHxMdB8IjIntCYebHV
|
||||||
OLqIiCFEVEsygVJKzoK1bReGJHdBVCsusbOe7APH57prZz1PH0S9IUHElMDrqPeHDyq+E8xgZ28DcADi
|
OLqIiCFEVEsygVJKzoK1bReGJHdBVCsusbOe7APH57prZz1PH0S9IUHElMDrqPeHDyq+E8xgZ28DcADi
|
||||||
+uZiNACH5wAAAABJRU5ErkJggg==
|
+uZiNACH5wAAAABJRU5ErkJggg==
|
||||||
</value>
|
</value>
|
||||||
@ -142,7 +142,7 @@
|
|||||||
<data name="EditExportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditExportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAKZJREFUOE/Nk0sOwyAMRDlSz8CFOEQqtsldOBitYrFNNa1NXMQnCxaxNIplzzxE
|
vgAADr4B6kKxwAAAAKZJREFUOE/Nk0sOwyAMRDlSz8CFOEQqtsldOBitYrFNNa1NXMQnCxaxNIplzzxE
|
||||||
ophplVI6OopE9GBrvWC01lblvR9DegBoCNGAV3z/6RLkCkBDOHZWDyCSPbwcO+segBDCd1lqCMBbFfO2
|
ophplVI6OopE9GBrvWC01lblvR9DegBoCNGAV3z/6RLkCkBDOHZWDyCSPbwcO+segBDCd1lqCMBbFfO2
|
||||||
btmIHjPaqQ3gcJTFsjzziegxww6QKkDC/HmySZuxQ48ryozjEwDlFZxzOYxeoHhqcfxXAilNSo1/wJgP
|
btmIHjPaqQ3gcJTFsjzziegxww6QKkDC/HmySZuxQ48ryozjEwDlFZxzOYxeoHhqcfxXAilNSo1/wJgP
|
||||||
rxwb6AQLOW8AAAAASUVORK5CYII=
|
rxwb6AQLOW8AAAAASUVORK5CYII=
|
||||||
@ -151,7 +151,7 @@
|
|||||||
<data name="EditExtractRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditExtractRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAKtJREFUOE/NkNENwjAMRDMSM2QFfpkn3wzQLfLflQqiyq/JmVzkthZFIKRaOtU6
|
vwAADr8BOAVTJAAAAKtJREFUOE/NkNENwjAMRDMSM2QFfpkn3wzQLfLflQqiyq/JmVzkthZFIKRaOtU6
|
||||||
3z0pDSLyk0Ip5RTq1K9YNU9vb6eGJgS1dB5U2OmtpNlWfY05rAHqxRi7UkpbCEKX66glC6BnAS6ERRQI
|
3z0pDSLyk0Ip5RTq1K9YNU9vb6eGJgS1dB5U2OmtpNlWfY05rAHqxRi7UkpbCEKX66glC6BnAS6ERRQI
|
||||||
4I7bbbp3uRAstmwh82N2ARYCAH7WAoK9eouyFSHI8BkdAuWcNeCVoQ0AQwhMBrwy5AIwDfI9AHMswJ7+
|
4I7bbbp3uRAstmwh82N2ARYCAH7WAoK9eouyFSHI8BkdAuWcNeCVoQ0AQwhMBrwy5AIwDfI9AHMswJ7+
|
||||||
B/hcRZ4ta4FRmq6ouAAAAABJRU5ErkJggg==
|
B/hcRZ4ta4FRmq6ouAAAAABJRU5ErkJggg==
|
||||||
@ -160,7 +160,7 @@
|
|||||||
<data name="EditImportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditImportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAJVJREFUOE+1kNEJwzAMRDNSZvBCHsLFv8068VJpf/yr+oSckuQCVUMMD8Tp/MAe
|
vwAADr8BOAVTJAAAAJVJREFUOE+1kNEJwzAMRDNSZvBCHsLFv8068VJpf/yr+oSckuQCVUMMD8Tp/MAe
|
||||||
ROQSNPRAQw809PAd7NRax8bSkB3IRqtxAQpWlOk5SZmLghmZ7VRyEGCBQs5Zyyk95LW8FczIbKcSJtDL
|
ROQSNPRAQw809PAd7NRax8bSkB3IRqtxAQpWlOk5SZmLghmZ7VRyEGCBQs5Zyyk95LW8FczIbKcSJtDL
|
||||||
XRBC2NAFXXKLYPOEGON6GXMXoIPuQbD/xBPOP/FfaOiBhh5o6IGGvyPDB6ug8Uv1Fi1pAAAAAElFTkSu
|
XRBC2NAFXXKLYPOEGON6GXMXoIPuQbD/xBPOP/FfaOiBhh5o6IGGvyPDB6ug8Uv1Fi1pAAAAAElFTkSu
|
||||||
QmCC
|
QmCC
|
||||||
@ -169,7 +169,7 @@
|
|||||||
<data name="EditImportRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditImportRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ
|
vwAADr8BOAVTJAAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ
|
||||||
+s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS
|
+s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS
|
||||||
lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV
|
lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV
|
||||||
AAAAAElFTkSuQmCC
|
AAAAAElFTkSuQmCC
|
||||||
@ -178,7 +178,7 @@
|
|||||||
<data name="EditCopyMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditCopyMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB
|
vgAADr4B6kKxwAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB
|
||||||
DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7
|
DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7
|
||||||
k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII=
|
k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
@ -186,14 +186,14 @@
|
|||||||
<data name="EditRenameMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditRenameMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAFBJREFUOE9joBh8+/btPz4MVYYbgBQ5OTmBMUwTMh+qDDegigHYNBKL4S6A0chs
|
vgAADr4B6kKxwAAAAFBJREFUOE9joBh8+/btPz4MVYYbgBQ5OTmBMUwTMh+qDDegigHYNBKL4S6A0chs
|
||||||
YmjauYAQhqkbTi5A1ojMJ0QTNIAQRvECNgxNb4MWMDAAAPsOTf9dAGOQAAAAAElFTkSuQmCC
|
YmjauYAQhqkbTi5A1ojMJ0QTNIAQRvECNgxNb4MWMDAAAPsOTf9dAGOQAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditDeleteMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="EditDeleteMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAVdJREFUOE+lk7FKw1AUhn0BwQdwcHJwEpzcsjkJmZ06+AABfYDqA1h3h+AiHQrS
|
vwAADr8BOAVTJAAAAVdJREFUOE+lk7FKw1AUhn0BwQdwcHJwEpzcsjkJmZ06+AABfYDqA1h3h+AiHQrS
|
||||||
xUkoOjiIEFwERSgOtoqDdcl6/b+bc9OmJHbwhx+Sc/7z33NyT5acc/9iiTzP18S2mIgrFq6AuJiKA2Mr
|
xUkoOjiIEFwERSgOtoqDdcl6/b+bc9OmJHbwhx+Sc/7z33NyT5acc/9iiTzP18S2mIgrFq6AuJiKA2Mr
|
||||||
JKKfz7F7PDv11PtQrJjoPZ58jL4fTo7d2+01mqzU6CGl8Hx92fPu6ADBpeU4tTPK7l0v2nD93W2HkWKb
|
JKKfz7F7PDv11PtQrJjoPZ58jL4fTo7d2+01mqzU6CGl8Hx92fPu6ADBpeU4tTPK7l0v2nD93W2HkWKb
|
||||||
vhjMG0A7hZGGT93UXWytemKkWGylBRTwI+AeDBATo5s508TKqlCiVWcSnulCmtTk9agzgTeH+xRPP1oT
|
vhjMG0A7hZGGT93UXWytemKkWGylBRTwI+AeDBATo5s508TKqlCiVWcSnulCmtTk9agzgTeH+xRPP1oT
|
||||||
@ -267,7 +267,7 @@
|
|||||||
<data name="SearchGlobalButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="SearchGlobalButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAANNJREFUOE+lUjEOgzAM5El9A3skRthZy0yZOvE9vpCh7UCGtAtr6otslIgENepJ
|
vwAADr8BOAVTJAAAANNJREFUOE+lUjEOgzAM5El9A3skRthZy0yZOvE9vpCh7UCGtAtr6otslIgENepJ
|
||||||
J2TfnZ0A1Rm2bWuIC9EFRN2wJQ8y3bXWbpomV9f1TtToQ2frEdgAk1IqCgvR5yHpk5CwyOZxvLnn4+Xe
|
J2TfnZ0A1Rm2bWuIC9EFRN2wJQ8y3bXWbpomV9f1TtToQ2frEdgAk1IqCgvR5yHpk5CwyOZxvLnn4+Xe
|
||||||
9uOfw3XwfejwcSQGCfs2CQtRiwYfR2LgeGIKw8K2bc8H/HUCal4g9H3vTUXvgMN2nud9S4rJr5ALd10X
|
9uOfw3XwfejwcSQGCfs2CQtRiwYfR2LgeGIKw8K2bc8H/HUCal4g9H3vTUXvgMN2nud9S4rJr5ALd10X
|
||||||
1cn/IBfGNYwx/q4B4z+Rimx4XVcLna1ppAb8HBaEQ4rDAhnCLAsLeEhBuKq+87Osda2nLc8AAAAASUVO
|
1cn/IBfGNYwx/q4B4z+Rimx4XVcLna1ppAb8HBaEQ4rDAhnCLAsLeEhBuKq+87Osda2nLc8AAAAASUVO
|
||||||
@ -277,7 +277,7 @@
|
|||||||
<data name="SearchFilterButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="SearchFilterButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAKJJREFUOE/VjLENAjEQBL8ESqEE5NxdfAFU4VYcUocjWnDu4DOnhwdZJyQfFoaI
|
vwAADr8BOAVTJAAAAKJJREFUOE/VjLENAjEQBL8ESqEE5NxdfAFU4VYcUocjWnDu4DOnhwdZJyQfFoaI
|
||||||
lVY67e7NJiI/2QxXrEetVVZsAY5938U5NzUbthbgknMW7735iOnYsB0AqBXXlJL5jOnYsDUBqA1uMcbh
|
lVY67e7NJiI/2QxXrEetVVZsAY5938U5NzUbthbgknMW7735iOnYsB0AqBXXlJL5jOnYsDUBqA1uMcbh
|
||||||
mYyuz6aAU/M9hKDP3GR0ffYegNrwXEpRADdZr5+aAlB7UAB3j1V/Anh1j1UD4Fub4YrN8HPL9gAVE1vf
|
mYyuz6aAU/M9hKDP3GR0ffYegNrwXEpRADdZr5+aAlB7UAB3j1V/Anh1j1UD4Fub4YrN8HPL9gAVE1vf
|
||||||
J6IiRgAAAABJRU5ErkJggg==
|
J6IiRgAAAABJRU5ErkJggg==
|
||||||
@ -304,7 +304,7 @@
|
|||||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
||||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
||||||
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADo
|
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADo
|
||||||
HwAAAk1TRnQBSQFMAgEBGAEAAdABAQHQAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
HwAAAk1TRnQBSQFMAgEBGAEAAfgBAQH4AQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
||||||
AwABQAMAAXADAAEBAQABCAYAARwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
|
AwABQAMAAXADAAEBAQABCAYAARwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
|
||||||
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
|
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
|
||||||
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
|
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
|
||||||
@ -446,7 +446,7 @@
|
|||||||
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAJtJREFUOE+Vj8ENgCAMRdnE1ZzLCwt5cQJvjkDiRfyfUIJQEJo8U2rof5hWOedW
|
vwAADr8BOAVTJAAAAJtJREFUOE+Vj8ENgCAMRdnE1ZzLCwt5cQJvjkDiRfyfUIJQEJo8U2rof5hWOedW
|
||||||
4CNrHI8XLp3PsXjCPo7Hion3tXm/mwD7KQtJlwVTFmW6MGyRp+MYYD9kUaZjlBaQX4s8XVvQtSjTtQWk
|
4CNrHI8XLp3PsXjCPo7Hion3tXm/mwD7KQtJlwVTFmW6MGyRp+MYYD9kUaZjlBaQX4s8XVvQtSjTtQWk
|
||||||
aVGmE4yrBaqFlt6jstDSCX5VBuRj0UtvLSDJopX+R7LAx868X4gGVp5hAQcz4LIxLycs8rg+vnkMAAAA
|
aVGmE4yrBaqFlt6jstDSCX5VBuRj0UtvLSDJopX+R7LAx868X4gGVp5hAQcz4LIxLycs8rg+vnkMAAAA
|
||||||
AElFTkSuQmCC
|
AElFTkSuQmCC
|
||||||
@ -455,7 +455,7 @@
|
|||||||
<data name="pictureBox2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="pictureBox2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAALVJREFUOE/dk70NQjEMhLMHDZuRBZiAadgD6YmGNjNAhaB4okkb/IEtvfgZIaDj
|
vwAADr8BOAVTJAAAALVJREFUOE/dk70NQjEMhLMHDZuRBZiAadgD6YmGNjNAhaB4okkb/IEtvfgZIaDj
|
||||||
pCvi853y4ySPWmsWDsLmSC1r2xwiLoVlON7aandui+2pIzU0euhV2xNqHtf7y8zouTlcCRm7EFkUBN9s
|
pCvi853y4ySPWmsWDsLmSC1r2xwiLoVlON7aandui+2pIzU0euhV2xNqHtf7y8zouTlcCRm7EFkUBN9s
|
||||||
8HUNKWbObM03QUOk6XEyAUN05nfEg5eAsAEaIg3i/ZOAl5doiLTpJf72jDoLJZpCg693gwRk8RjlaBo9
|
8HUNKWbObM03QUOk6XEyAUN05nfEg5eAsAEaIg3i/ZOAl5doiLTpJf72jDoLJZpCg693gwRk8RjlaBo9
|
||||||
w1EGGvLdZ5pCxA++c0p3WGOjVX9N2kUAAAAASUVORK5CYII=
|
w1EGGvLdZ5pCxA++c0p3WGOjVX9N2kUAAAAASUVORK5CYII=
|
||||||
@ -467,7 +467,7 @@
|
|||||||
<data name="ListContextViewMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextViewMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAQFJREFUOE+dkz0LglAUhv0H/ZLA3+De1FrQ4NJkY9Du3FRLEAZuRVNQS2FLRDQE
|
vwAADr8BOAVTJAAAAQFJREFUOE+dkz0LglAUhv0H/ZLA3+De1FrQ4NJkY9Du3FRLEAZuRVNQS2FLRDQE
|
||||||
UWu0BBX4Mbie7nvxmslNrQMPXI/nfTgXUUlXGIaUgctQo1F5YVDTNCmmaeZLsgQgV5IUeK7/QSFJEUFS
|
UWu0BBX4Mbie7nvxmslNrQMPXI/nfTgXUUlXGIaUgctQo1F5YVDTNCmmaeZLsgQgV5IUeK7/QSFJEUFS
|
||||||
EsXelSUQiPeYjWLvQtMwDNJ1XRoGXwWsMTxfH9Sxt5zT5U6+FxQTsIfGYn+hUt2itrWhZt9h5xGXFBVM
|
EsXelSUQiPeYjWLvQtMwDNJ1XRoGXwWsMTxfH9Sxt5zT5U6+FxQTsIfGYn+hUt2itrWhZt9h5xGXFBVM
|
||||||
K+acerNDPAgJNklv8U2wgsBenuJBbAJB4OcI2EFluBCUW2MuwSa4jrM7xoE0XCDCte6SlOqAIBFM1kf+
|
K+acerNDPAgJNklv8U2wgsBenuJBbAJB4OcI2EFluBCUW2MuwSa4jrM7xoE0XCDCte6SlOqAIBFM1kf+
|
||||||
@ -477,7 +477,7 @@
|
|||||||
<data name="ListContextViewHexMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextViewHexMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAGlJREFUOE/ljlsKgEAIRV1Sa3BxbncKxN9CUKbCdIboqwsHxMdB8IjIntCYebHV
|
vgAADr4B6kKxwAAAAGlJREFUOE/ljlsKgEAIRV1Sa3BxbncKxN9CUKbCdIboqwsHxMdB8IjIntCYebHV
|
||||||
OLqIiCFEVEsygVJKzoK1bReGJHdBVCsusbOe7APH57prZz1PH0S9IUHElMDrqPeHDyq+E8xgZ28DcADi
|
OLqIiCFEVEsygVJKzoK1bReGJHdBVCsusbOe7APH57prZz1PH0S9IUHElMDrqPeHDyq+E8xgZ28DcADi
|
||||||
+uZiNACH5wAAAABJRU5ErkJggg==
|
+uZiNACH5wAAAABJRU5ErkJggg==
|
||||||
</value>
|
</value>
|
||||||
@ -485,7 +485,7 @@
|
|||||||
<data name="ListContextExportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextExportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAKZJREFUOE/Nk0sOwyAMRDlSz8CFOEQqtsldOBitYrFNNa1NXMQnCxaxNIplzzxE
|
vgAADr4B6kKxwAAAAKZJREFUOE/Nk0sOwyAMRDlSz8CFOEQqtsldOBitYrFNNa1NXMQnCxaxNIplzzxE
|
||||||
ophplVI6OopE9GBrvWC01lblvR9DegBoCNGAV3z/6RLkCkBDOHZWDyCSPbwcO+segBDCd1lqCMBbFfO2
|
ophplVI6OopE9GBrvWC01lblvR9DegBoCNGAV3z/6RLkCkBDOHZWDyCSPbwcO+segBDCd1lqCMBbFfO2
|
||||||
btmIHjPaqQ3gcJTFsjzziegxww6QKkDC/HmySZuxQ48ryozjEwDlFZxzOYxeoHhqcfxXAilNSo1/wJgP
|
btmIHjPaqQ3gcJTFsjzziegxww6QKkDC/HmySZuxQ48ryozjEwDlFZxzOYxeoHhqcfxXAilNSo1/wJgP
|
||||||
rxwb6AQLOW8AAAAASUVORK5CYII=
|
rxwb6AQLOW8AAAAASUVORK5CYII=
|
||||||
@ -494,7 +494,7 @@
|
|||||||
<data name="ListContextExtractRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextExtractRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAKtJREFUOE/NkNENwjAMRDMSM2QFfpkn3wzQLfLflQqiyq/JmVzkthZFIKRaOtU6
|
vwAADr8BOAVTJAAAAKtJREFUOE/NkNENwjAMRDMSM2QFfpkn3wzQLfLflQqiyq/JmVzkthZFIKRaOtU6
|
||||||
3z0pDSLyk0Ip5RTq1K9YNU9vb6eGJgS1dB5U2OmtpNlWfY05rAHqxRi7UkpbCEKX66glC6BnAS6ERRQI
|
3z0pDSLyk0Ip5RTq1K9YNU9vb6eGJgS1dB5U2OmtpNlWfY05rAHqxRi7UkpbCEKX66glC6BnAS6ERRQI
|
||||||
4I7bbbp3uRAstmwh82N2ARYCAH7WAoK9eouyFSHI8BkdAuWcNeCVoQ0AQwhMBrwy5AIwDfI9AHMswJ7+
|
4I7bbbp3uRAstmwh82N2ARYCAH7WAoK9eouyFSHI8BkdAuWcNeCVoQ0AQwhMBrwy5AIwDfI9AHMswJ7+
|
||||||
B/hcRZ4ta4FRmq6ouAAAAABJRU5ErkJggg==
|
B/hcRZ4ta4FRmq6ouAAAAABJRU5ErkJggg==
|
||||||
@ -503,7 +503,7 @@
|
|||||||
<data name="ListContextImportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextImportXmlMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAJVJREFUOE+1kNEJwzAMRDNSZvBCHsLFv8068VJpf/yr+oSckuQCVUMMD8Tp/MAe
|
vwAADr8BOAVTJAAAAJVJREFUOE+1kNEJwzAMRDNSZvBCHsLFv8068VJpf/yr+oSckuQCVUMMD8Tp/MAe
|
||||||
ROQSNPRAQw809PAd7NRax8bSkB3IRqtxAQpWlOk5SZmLghmZ7VRyEGCBQs5Zyyk95LW8FczIbKcSJtDL
|
ROQSNPRAQw809PAd7NRax8bSkB3IRqtxAQpWlOk5SZmLghmZ7VRyEGCBQs5Zyyk95LW8FczIbKcSJtDL
|
||||||
XRBC2NAFXXKLYPOEGON6GXMXoIPuQbD/xBPOP/FfaOiBhh5o6IGGvyPDB6ug8Uv1Fi1pAAAAAElFTkSu
|
XRBC2NAFXXKLYPOEGON6GXMXoIPuQbD/xBPOP/FfaOiBhh5o6IGGvyPDB6ug8Uv1Fi1pAAAAAElFTkSu
|
||||||
QmCC
|
QmCC
|
||||||
@ -512,7 +512,7 @@
|
|||||||
<data name="ListContextImportRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextImportRawMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ
|
vwAADr8BOAVTJAAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ
|
||||||
+s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS
|
+s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS
|
||||||
lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV
|
lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV
|
||||||
AAAAAElFTkSuQmCC
|
AAAAAElFTkSuQmCC
|
||||||
@ -521,7 +521,7 @@
|
|||||||
<data name="ListContextCopyMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextCopyMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB
|
vgAADr4B6kKxwAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB
|
||||||
DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7
|
DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7
|
||||||
k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII=
|
k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
@ -529,14 +529,14 @@
|
|||||||
<data name="ListContextRenameMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextRenameMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAFBJREFUOE9joBh8+/btPz4MVYYbgBQ5OTmBMUwTMh+qDDegigHYNBKL4S6A0chs
|
vgAADr4B6kKxwAAAAFBJREFUOE9joBh8+/btPz4MVYYbgBQ5OTmBMUwTMh+qDDegigHYNBKL4S6A0chs
|
||||||
YmjauYAQhqkbTi5A1ojMJ0QTNIAQRvECNgxNb4MWMDAAAPsOTf9dAGOQAAAAAElFTkSuQmCC
|
YmjauYAQhqkbTi5A1ojMJ0QTNIAQRvECNgxNb4MWMDAAAPsOTf9dAGOQAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ListContextDeleteMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ListContextDeleteMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1
|
||||||
MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAFjSURBVDhPpVOxSsNQFM0PCP2A
|
MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAADr8AAA6/ATgFUyQAAAFjSURBVDhPpVOxSsNQFM0PCP2A
|
||||||
Dp0cOgmd3Lo5CU4OTh0E14B+QPQDrLtDcBEHRRx0KgQdFKQQXARRENFGxeHpkvV5zs195kUSHXrg0Mc9
|
Dp0cOgmd3Lo5CU4OTh0E14B+QPQDrLtDcBEHRRx0KgQdFKQQXARRENFGxeHpkvV5zs195kUSHXrg0Mc9
|
||||||
956c5N0GRJ7nLTAGLWjAUIRfQD3SHsclJ4RPFyO732sLs/S6FAGcO2B6s7tj92Zn7P3pEfVIZWlIxttb
|
956c5N0GRJ7nLTAGLWjAUIRfQD3SHsclJ4RPFyO732sLs/S6FAGcO2B6s7tj92Zn7P3pEfVIZWlIxttb
|
||||||
IpIni/P28y1jEiYLeT7fWBWNfagd62gBNjGBMyAvN9fZaD4e7sSQNZqgloItHS3AAoXbg7hiwqfxlXj2
|
IpIni/P28y1jEiYLeT7fWBWNfagd62gBNjGBMyAvN9fZaD4e7sSQNZqgloItHS3AAoXbg7hiwqfxlXj2
|
||||||
@ -551,7 +551,7 @@
|
|||||||
<data name="TreeContextCopyPathMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="TreeContextCopyPathMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB
|
vgAADr4B6kKxwAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB
|
||||||
DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7
|
DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7
|
||||||
k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII=
|
k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
@ -559,7 +559,7 @@
|
|||||||
<data name="TreeContextWinExplorerMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="TreeContextWinExplorerMenu.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAALNJREFUOE9jIAS+fftmAMTvgfg/NgxVhh0AFYA1t7W1/XdycsLAKAbATETHIM3N
|
vwAADr8BOAVTJAAAALNJREFUOE9jIAS+fftmAMTvgfg/NgxVhh0AFYA1t7W1/XdycsLAKAbATETHIM3N
|
||||||
zS3/P7z/iIKxGoBuAwgja4aJ4TUAppgQpp4BIAKGyTYAxCEWYzPgfH5+PoZCXPjokaMYBjQsX74cQyEu
|
zS3/P7z/iIKxGoBuAwgja4aJ4TUAppgQpp4BIAKGyTYAxCEWYzPgfH5+PoZCXPjokaMYBjQsX74cQyEu
|
||||||
3NfXj2GAwZUrVzAU4sLJScmoBkBj4H1kZCSGYlz41s3bYBrZgPm4kis2vH7dejCNbEDCvn37MBQSwsgG
|
3NfXj2GAwZUrVzAU4sLJScmoBkBj4H1kZCSGYlz41s3bYBrZgPm4kis2vH7dejCNbEDCvn37MBQSwsgG
|
||||||
CIA45GCG//8pwf8ZANa5gGyReLItAAAAAElFTkSuQmCC
|
CIA45GCG//8pwf8ZANa5gGyReLItAAAAAElFTkSuQmCC
|
||||||
|
@ -185,7 +185,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
||||||
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
||||||
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
|
else if (FilePath.StartsWith(GTAFolder.CurrentGTAFolder, StringComparison.OrdinalIgnoreCase)) saveAs = true;
|
||||||
if (!File.Exists(FilePath)) saveAs = true;
|
if (!File.Exists(FilePath)) saveAs = true;
|
||||||
|
|
||||||
var fn = FilePath;
|
var fn = FilePath;
|
||||||
@ -456,7 +456,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if (rpfFileEntry?.Parent != null)
|
if (rpfFileEntry?.Parent != null)
|
||||||
{
|
{
|
||||||
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
|
if (!rpfFileEntry.Path.StartsWith("mods", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||||
{
|
{
|
||||||
|
4
CodeWalker/Forms/ModelForm.Designer.cs
generated
4
CodeWalker/Forms/ModelForm.Designer.cs
generated
@ -1,4 +1,6 @@
|
|||||||
namespace CodeWalker.Forms
|
using CodeWalker.WinForms;
|
||||||
|
|
||||||
|
namespace CodeWalker.Forms
|
||||||
{
|
{
|
||||||
partial class ModelForm
|
partial class ModelForm
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,6 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
volatile bool formopen = false;
|
volatile bool formopen = false;
|
||||||
//volatile bool running = false;
|
//volatile bool running = false;
|
||||||
volatile bool pauserendering = false;
|
|
||||||
//volatile bool initialised = false;
|
//volatile bool initialised = false;
|
||||||
|
|
||||||
Stopwatch frametimer = new Stopwatch();
|
Stopwatch frametimer = new Stopwatch();
|
||||||
@ -46,6 +45,8 @@ namespace CodeWalker.Forms
|
|||||||
System.Drawing.Point MouseLastPoint;
|
System.Drawing.Point MouseLastPoint;
|
||||||
bool MouseInvert = Settings.Default.MouseInvert;
|
bool MouseInvert = Settings.Default.MouseInvert;
|
||||||
|
|
||||||
|
int VerticesCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector3 prevworldpos = new Vector3(0, 0, 0); //also the start pos
|
Vector3 prevworldpos = new Vector3(0, 0, 0); //also the start pos
|
||||||
@ -69,6 +70,7 @@ namespace CodeWalker.Forms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public string FilePath { get; set; }
|
public string FilePath { get; set; }
|
||||||
|
public bool Pauserendering { get; set; }
|
||||||
|
|
||||||
YdrFile Ydr = null;
|
YdrFile Ydr = null;
|
||||||
YddFile Ydd = null;
|
YddFile Ydd = null;
|
||||||
@ -128,13 +130,70 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
public ModelForm(ExploreForm ExpForm = null)
|
public ModelForm(ExploreForm ExpForm = null)
|
||||||
{
|
{
|
||||||
|
if (this.DesignMode) return;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
exploreForm = ExpForm;
|
exploreForm = ExpForm;
|
||||||
|
|
||||||
gameFileCache = ExpForm?.GetFileCache();
|
gameFileCache = ExpForm?.GetFileCache() ?? GameFileCacheFactory.Create();
|
||||||
|
|
||||||
|
if (ExpForm == null)
|
||||||
|
{
|
||||||
|
gameFileCache.EnableDlc = false;
|
||||||
|
gameFileCache.EnableMods = false;
|
||||||
|
gameFileCache.LoadPeds = false;
|
||||||
|
gameFileCache.LoadVehicles = false;
|
||||||
|
gameFileCache.LoadArchetypes = false;//to speed things up a little
|
||||||
|
gameFileCache.BuildExtendedJenkIndex = true;//to speed things up a little
|
||||||
|
gameFileCache.DoFullStringIndex = false;//to get all global text from DLC...
|
||||||
|
Task.Run(() => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
gameFileCache.Init();
|
||||||
|
if (DetailsPropertyGrid.SelectedObject is DrawableBase drawableBase)
|
||||||
|
{
|
||||||
|
UpdateDrawableUI(drawableBase);
|
||||||
|
}
|
||||||
|
if (Yft != null)
|
||||||
|
{
|
||||||
|
UpdateDrawableUI(Yft.Fragment?.Drawable);
|
||||||
|
}
|
||||||
|
UpdateStatus("Done loading");
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
while (!IsDisposed) //run the file cache content thread until the form exits.
|
||||||
|
{
|
||||||
|
if (gameFileCache.IsInited)
|
||||||
|
{
|
||||||
|
gameFileCache.BeginFrame();
|
||||||
|
|
||||||
|
bool fcItemsPending = gameFileCache.ContentThreadProc();
|
||||||
|
|
||||||
|
if (!fcItemsPending)
|
||||||
|
{
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Thread.Sleep(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Renderer = new Renderer(this, gameFileCache);
|
Renderer = new Renderer(this, gameFileCache);
|
||||||
|
Renderer.waitforchildrentoload = false;
|
||||||
camera = Renderer.camera;
|
camera = Renderer.camera;
|
||||||
timecycle = Renderer.timecycle;
|
timecycle = Renderer.timecycle;
|
||||||
weather = Renderer.weather;
|
weather = Renderer.weather;
|
||||||
@ -159,7 +218,7 @@ namespace CodeWalker.Forms
|
|||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
//called from ModelForm_Load
|
//called from ModelForm_Load
|
||||||
|
if (this.DesignMode) return;
|
||||||
if (!initedOk)
|
if (!initedOk)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
@ -260,13 +319,21 @@ namespace CodeWalker.Forms
|
|||||||
public void BuffersResized(int w, int h)
|
public void BuffersResized(int w, int h)
|
||||||
{
|
{
|
||||||
Renderer.BuffersResized(w, h);
|
Renderer.BuffersResized(w, h);
|
||||||
|
if (WindowState == FormWindowState.Minimized && gameFileCache.IsInited)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Clearing cache");
|
||||||
|
gameFileCache.Clear();
|
||||||
|
gameFileCache.IsInited = true;
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public void RenderScene(DeviceContext context)
|
public void RenderScene(DeviceContext context)
|
||||||
{
|
{
|
||||||
float elapsed = (float)frametimer.Elapsed.TotalSeconds;
|
float elapsed = (float)frametimer.Elapsed.TotalSeconds;
|
||||||
frametimer.Restart();
|
frametimer.Restart();
|
||||||
|
|
||||||
if (pauserendering) return;
|
if (Pauserendering) return;
|
||||||
|
|
||||||
if (!Monitor.TryEnter(Renderer.RenderSyncRoot, 50))
|
if (!Monitor.TryEnter(Renderer.RenderSyncRoot, 50))
|
||||||
{ return; } //couldn't get a lock, try again next time
|
{ return; } //couldn't get a lock, try again next time
|
||||||
@ -627,6 +694,47 @@ namespace CodeWalker.Forms
|
|||||||
selectedLight.UpdateRenderable = true;
|
selectedLight.UpdateRenderable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ViewModel(string path)
|
||||||
|
{
|
||||||
|
var data = File.ReadAllBytes(path);
|
||||||
|
var fileEntry = RpfFile.CreateFileEntry(Path.GetFileName(path), path, ref data);
|
||||||
|
ViewModel(data, fileEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ViewModel(byte[] data, RpfFileEntry e)
|
||||||
|
{
|
||||||
|
var nl = e?.NameLower ?? "";
|
||||||
|
var fe = Path.GetExtension(nl);
|
||||||
|
Show();
|
||||||
|
switch (fe)
|
||||||
|
{
|
||||||
|
case ".ydr":
|
||||||
|
var ydr = RpfFile.GetFile<YdrFile>(e, data);
|
||||||
|
LoadModel(ydr);
|
||||||
|
break;
|
||||||
|
case ".ydd":
|
||||||
|
var ydd = RpfFile.GetFile<YddFile>(e, data);
|
||||||
|
LoadModels(ydd);
|
||||||
|
break;
|
||||||
|
case ".yft":
|
||||||
|
var yft = RpfFile.GetFile<YftFile>(e, data);
|
||||||
|
LoadModel(yft);
|
||||||
|
break;
|
||||||
|
case ".ybn":
|
||||||
|
var ybn = RpfFile.GetFile<YbnFile>(e, data);
|
||||||
|
LoadModel(ybn);
|
||||||
|
break;
|
||||||
|
case ".ypt":
|
||||||
|
var ypt = RpfFile.GetFile<YptFile>(e, data);
|
||||||
|
LoadParticles(ypt);
|
||||||
|
break;
|
||||||
|
case ".ynv":
|
||||||
|
var ynv = RpfFile.GetFile<YnvFile>(e, data);
|
||||||
|
LoadNavmesh(ynv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void RenderSingleItem()
|
private void RenderSingleItem()
|
||||||
{
|
{
|
||||||
@ -794,10 +902,10 @@ namespace CodeWalker.Forms
|
|||||||
Yft = yft;
|
Yft = yft;
|
||||||
rpfFileEntry = Yft.RpfFileEntry;
|
rpfFileEntry = Yft.RpfFileEntry;
|
||||||
ModelHash = Yft.RpfFileEntry?.ShortNameHash ?? 0;
|
ModelHash = Yft.RpfFileEntry?.ShortNameHash ?? 0;
|
||||||
var namelower = Yft.RpfFileEntry?.GetShortNameLower();
|
var namelower = Yft.RpfFileEntry?.ShortName;
|
||||||
if (namelower?.EndsWith("_hi") ?? false)
|
if (namelower?.EndsWith("_hi", StringComparison.OrdinalIgnoreCase) ?? false)
|
||||||
{
|
{
|
||||||
ModelHash = JenkHash.GenHash(namelower.Substring(0, namelower.Length - 3));
|
ModelHash = JenkHash.GenHashLower(namelower.Substring(0, namelower.Length - 3));
|
||||||
}
|
}
|
||||||
if (ModelHash != 0)
|
if (ModelHash != 0)
|
||||||
{
|
{
|
||||||
@ -843,6 +951,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
UpdateBoundsUI(ybn);
|
UpdateBoundsUI(ybn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadParticles(YptFile ypt)
|
public void LoadParticles(YptFile ypt)
|
||||||
{
|
{
|
||||||
if (ypt == null) return;
|
if (ypt == null) return;
|
||||||
@ -948,7 +1057,7 @@ namespace CodeWalker.Forms
|
|||||||
if (gameFileCache == null) return;
|
if (gameFileCache == null) return;
|
||||||
if (!gameFileCache.IsInited) return;//what to do here? wait for it..?
|
if (!gameFileCache.IsInited) return;//what to do here? wait for it..?
|
||||||
|
|
||||||
var ycdhash = JenkHash.GenHash(name.ToLowerInvariant());
|
var ycdhash = JenkHash.GenHashLower(name);
|
||||||
var ycd = gameFileCache.GetYcd(ycdhash);
|
var ycd = gameFileCache.GetYcd(ycdhash);
|
||||||
while ((ycd != null) && (!ycd.Loaded))
|
while ((ycd != null) && (!ycd.Loaded))
|
||||||
{
|
{
|
||||||
@ -1097,19 +1206,15 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateDrawableUI(DrawableBase drawable)
|
||||||
|
|
||||||
|
|
||||||
private void UpdateModelsUI(DrawableBase drawable, object detailsObject = null)
|
|
||||||
{
|
{
|
||||||
DetailsPropertyGrid.SelectedObject = detailsObject ?? drawable;
|
|
||||||
|
|
||||||
DrawableDrawFlags.Clear();
|
DrawableDrawFlags.Clear();
|
||||||
Renderer.SelectionModelDrawFlags.Clear();
|
Renderer.SelectionModelDrawFlags.Clear();
|
||||||
Renderer.SelectionGeometryDrawFlags.Clear();
|
Renderer.SelectionGeometryDrawFlags.Clear();
|
||||||
ModelsTreeView.Nodes.Clear();
|
ModelsTreeView.Nodes.Clear();
|
||||||
ModelsTreeView.ShowRootLines = false;
|
ModelsTreeView.ShowRootLines = false;
|
||||||
TexturesTreeView.Nodes.Clear();
|
TexturesTreeView.Nodes.Clear();
|
||||||
|
|
||||||
if (drawable != null)
|
if (drawable != null)
|
||||||
{
|
{
|
||||||
AddDrawableModelsTreeNodes(drawable.DrawableModels?.High, "High Detail", true);
|
AddDrawableModelsTreeNodes(drawable.DrawableModels?.High, "High Detail", true);
|
||||||
@ -1162,6 +1267,15 @@ namespace CodeWalker.Forms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void UpdateModelsUI(DrawableBase drawable, object detailsObject = null)
|
||||||
|
{
|
||||||
|
DetailsPropertyGrid.SelectedObject = detailsObject ?? drawable;
|
||||||
|
|
||||||
|
UpdateDrawableUI(drawable);
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateModelsUI(Dictionary<uint, Drawable> dict)
|
private void UpdateModelsUI(Dictionary<uint, Drawable> dict)
|
||||||
{
|
{
|
||||||
//DetailsPropertyGrid.SelectedObject = dict; //this won't look good...
|
//DetailsPropertyGrid.SelectedObject = dict; //this won't look good...
|
||||||
@ -1238,6 +1352,7 @@ namespace CodeWalker.Forms
|
|||||||
dnode.Tag = drawable;
|
dnode.Tag = drawable;
|
||||||
dnode.Checked = check;
|
dnode.Checked = check;
|
||||||
|
|
||||||
|
VerticesCount = 0;
|
||||||
AddDrawableModelsTreeNodes(drawable.DrawableModels?.High, "High Detail", true, dnode);
|
AddDrawableModelsTreeNodes(drawable.DrawableModels?.High, "High Detail", true, dnode);
|
||||||
AddDrawableModelsTreeNodes(drawable.DrawableModels?.Med, "Medium Detail", false, dnode);
|
AddDrawableModelsTreeNodes(drawable.DrawableModels?.Med, "Medium Detail", false, dnode);
|
||||||
AddDrawableModelsTreeNodes(drawable.DrawableModels?.Low, "Low Detail", false, dnode);
|
AddDrawableModelsTreeNodes(drawable.DrawableModels?.Low, "Low Detail", false, dnode);
|
||||||
@ -1272,6 +1387,7 @@ namespace CodeWalker.Forms
|
|||||||
foreach (var geom in model.Geometries)
|
foreach (var geom in model.Geometries)
|
||||||
{
|
{
|
||||||
var gname = geom.ToString();
|
var gname = geom.ToString();
|
||||||
|
VerticesCount += geom.VerticesCount;
|
||||||
var gnode = mnode.Nodes.Add(gname);
|
var gnode = mnode.Nodes.Add(gname);
|
||||||
gnode.Tag = geom;
|
gnode.Tag = geom;
|
||||||
gnode.Checked = true;// check;
|
gnode.Checked = true;// check;
|
||||||
@ -1545,6 +1661,10 @@ namespace CodeWalker.Forms
|
|||||||
{
|
{
|
||||||
td = Ypt?.PtfxList?.TextureDictionary;
|
td = Ypt?.PtfxList?.TextureDictionary;
|
||||||
}
|
}
|
||||||
|
else if ((Ydd != null) && (Ydd.Loaded))
|
||||||
|
{
|
||||||
|
td = Ydd?.Drawables.First().ShaderGroup?.TextureDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
if (td != null)
|
if (td != null)
|
||||||
{
|
{
|
||||||
@ -1649,7 +1769,7 @@ namespace CodeWalker.Forms
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
|
if (FilePath.StartsWith(GTAFolder.CurrentGTAFolder, StringComparison.OrdinalIgnoreCase)) saveAs = true;
|
||||||
if (!File.Exists(FilePath)) saveAs = true;
|
if (!File.Exists(FilePath)) saveAs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1727,7 +1847,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if (rpfSave)
|
if (rpfSave)
|
||||||
{
|
{
|
||||||
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
|
if (!rpfFileEntry.Path.StartsWith("mods", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||||
{
|
{
|
||||||
@ -1985,7 +2105,7 @@ namespace CodeWalker.Forms
|
|||||||
File.WriteAllBytes(fpath, dds);
|
File.WriteAllBytes(fpath, dds);
|
||||||
successcount++;
|
successcount++;
|
||||||
}
|
}
|
||||||
catch
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
errordds.Add(tex.Name ?? "???");
|
errordds.Add(tex.Name ?? "???");
|
||||||
}
|
}
|
||||||
@ -2303,7 +2423,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
private void StatsUpdateTimer_Tick(object sender, EventArgs e)
|
private void StatsUpdateTimer_Tick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
StatsLabel.Text = Renderer.GetStatusText();
|
StatsLabel.Text = Renderer.GetStatusText() + $" verts: {VerticesCount}";
|
||||||
|
|
||||||
if (Renderer.timerunning)
|
if (Renderer.timerunning)
|
||||||
{
|
{
|
||||||
|
@ -226,7 +226,7 @@ namespace CodeWalker.Forms
|
|||||||
if (ttex == null)//don't do this for embedded textures!
|
if (ttex == null)//don't do this for embedded textures!
|
||||||
{
|
{
|
||||||
tex.Name = txt;
|
tex.Name = txt;
|
||||||
tex.NameHash = JenkHash.GenHash(txt.ToLowerInvariant());
|
tex.NameHash = JenkHash.GenHashLower(txt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -246,7 +246,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if (rpfFileEntry?.Parent != null)
|
if (rpfFileEntry?.Parent != null)
|
||||||
{
|
{
|
||||||
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
|
if (!rpfFileEntry.Path.StartsWith("mods", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||||
{
|
{
|
||||||
@ -383,7 +383,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
||||||
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
||||||
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
|
else if (FilePath.StartsWith(GTAFolder.CurrentGTAFolder, StringComparison.OrdinalIgnoreCase)) saveAs = true;
|
||||||
if (!File.Exists(FilePath)) saveAs = true;
|
if (!File.Exists(FilePath)) saveAs = true;
|
||||||
|
|
||||||
var fn = FilePath;
|
var fn = FilePath;
|
||||||
@ -536,8 +536,8 @@ namespace CodeWalker.Forms
|
|||||||
{
|
{
|
||||||
if (textsearch)
|
if (textsearch)
|
||||||
{
|
{
|
||||||
if (((rd.Name?.ToLowerInvariant().Contains(textl)) ?? false) || (rd.NameHash == hash) || (rd.NameHash == hashl) ||
|
if (((rd.Name?.Contains(textl, StringComparison.OrdinalIgnoreCase)) ?? false) || (rd.NameHash == hash) || (rd.NameHash == hashl) ||
|
||||||
(rd.NameHash.ToString().ToLowerInvariant().Contains(textl)))
|
rd.NameHash.ToString().Contains(textl, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
results.Add(rd);
|
results.Add(rd);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
||||||
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
||||||
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
|
else if (FilePath.StartsWith(GTAFolder.CurrentGTAFolder, StringComparison.OrdinalIgnoreCase)) saveAs = true;
|
||||||
if (!File.Exists(FilePath)) saveAs = true;
|
if (!File.Exists(FilePath)) saveAs = true;
|
||||||
|
|
||||||
var fn = FilePath;
|
var fn = FilePath;
|
||||||
@ -277,7 +277,7 @@ namespace CodeWalker.Forms
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
|
if (!rpfFileEntry.Path.StartsWith("mods", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||||
{
|
{
|
||||||
|
@ -184,7 +184,7 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
if (string.IsNullOrEmpty(FileName)) saveAs = true;
|
||||||
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
|
||||||
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
|
else if (FilePath.StartsWith(GTAFolder.CurrentGTAFolder, StringComparison.OrdinalIgnoreCase)) saveAs = true;
|
||||||
if (!File.Exists(FilePath)) saveAs = true;
|
if (!File.Exists(FilePath)) saveAs = true;
|
||||||
|
|
||||||
var fn = FilePath;
|
var fn = FilePath;
|
||||||
@ -228,7 +228,7 @@ namespace CodeWalker.Forms
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
|
if (!rpfFileEntry.Path.StartsWith("mods", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||||
{
|
{
|
||||||
|
@ -249,7 +249,6 @@ namespace CodeWalker.Forms
|
|||||||
if (tex == null) return;
|
if (tex == null) return;
|
||||||
|
|
||||||
tex.Name = CurrentTexture.Name;
|
tex.Name = CurrentTexture.Name;
|
||||||
tex.NameHash = CurrentTexture.NameHash;
|
|
||||||
tex.Usage = CurrentTexture.Usage;
|
tex.Usage = CurrentTexture.Usage;
|
||||||
tex.UsageFlags = CurrentTexture.UsageFlags;
|
tex.UsageFlags = CurrentTexture.UsageFlags;
|
||||||
tex.Unknown_32h = CurrentTexture.Unknown_32h;
|
tex.Unknown_32h = CurrentTexture.Unknown_32h;
|
||||||
@ -285,7 +284,6 @@ namespace CodeWalker.Forms
|
|||||||
var tex = CurrentTexture;
|
var tex = CurrentTexture;
|
||||||
|
|
||||||
tex.Name = name;
|
tex.Name = name;
|
||||||
tex.NameHash = JenkHash.GenHash(name.ToLowerInvariant());
|
|
||||||
|
|
||||||
var textures = new List<Texture>();
|
var textures = new List<Texture>();
|
||||||
textures.AddRange(TexDict.Textures.data_items);
|
textures.AddRange(TexDict.Textures.data_items);
|
||||||
@ -323,8 +321,7 @@ namespace CodeWalker.Forms
|
|||||||
var dds = File.ReadAllBytes(fn);
|
var dds = File.ReadAllBytes(fn);
|
||||||
var tex = DDSIO.GetTexture(dds);
|
var tex = DDSIO.GetTexture(dds);
|
||||||
tex.Name = Path.GetFileNameWithoutExtension(fn);
|
tex.Name = Path.GetFileNameWithoutExtension(fn);
|
||||||
tex.NameHash = JenkHash.GenHash(tex.Name?.ToLowerInvariant());
|
JenkIndex.EnsureLower(tex.Name);
|
||||||
JenkIndex.Ensure(tex.Name?.ToLowerInvariant());
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -456,7 +453,7 @@ namespace CodeWalker.Forms
|
|||||||
if (!saveas)
|
if (!saveas)
|
||||||
{
|
{
|
||||||
isinrpf = true;
|
isinrpf = true;
|
||||||
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
|
if (!rpfFileEntry.Path.StartsWith("mods", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||||
{
|
{
|
||||||
|
@ -2,17 +2,25 @@
|
|||||||
|
|
||||||
|
|
||||||
using CodeWalker.Properties;
|
using CodeWalker.Properties;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
{
|
{
|
||||||
|
|
||||||
public static class GameFileCacheFactory
|
public static class GameFileCacheFactory
|
||||||
{
|
{
|
||||||
|
public static GameFileCache _instance = null;
|
||||||
public static GameFileCache Create()
|
public static GameFileCache Create()
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
{
|
{
|
||||||
var s = Settings.Default;
|
var s = Settings.Default;
|
||||||
return new GameFileCache(s.CacheSize, s.CacheTime, GTAFolder.CurrentGTAFolder, s.DLC, s.EnableMods, s.ExcludeFolders);
|
GTA5Keys.LoadFromPath(GTAFolder.CurrentGTAFolder, Settings.Default.Key);
|
||||||
|
_instance = new GameFileCache(s.CacheSize, s.CacheTime, GTAFolder.CurrentGTAFolder, s.DLC, s.EnableMods, s.ExcludeFolders);
|
||||||
|
GTAFolder.OnGTAFolderChanged += _instance.SetGtaFolder;
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,10 @@ namespace CodeWalker
|
|||||||
public Renderer Renderer = null;
|
public Renderer Renderer = null;
|
||||||
public object RenderSyncRoot { get { return Renderer.RenderSyncRoot; } }
|
public object RenderSyncRoot { get { return Renderer.RenderSyncRoot; } }
|
||||||
|
|
||||||
|
public bool Pauserendering { get; set; }
|
||||||
volatile bool formopen = false;
|
volatile bool formopen = false;
|
||||||
volatile bool running = false;
|
volatile bool running = false;
|
||||||
volatile bool pauserendering = false;
|
|
||||||
//volatile bool initialised = false;
|
//volatile bool initialised = false;
|
||||||
|
|
||||||
Stopwatch frametimer = new Stopwatch();
|
Stopwatch frametimer = new Stopwatch();
|
||||||
@ -211,7 +212,7 @@ namespace CodeWalker
|
|||||||
float elapsed = (float)frametimer.Elapsed.TotalSeconds;
|
float elapsed = (float)frametimer.Elapsed.TotalSeconds;
|
||||||
frametimer.Restart();
|
frametimer.Restart();
|
||||||
|
|
||||||
if (pauserendering) return;
|
if (Pauserendering) return;
|
||||||
|
|
||||||
GameFileCache.BeginFrame();
|
GameFileCache.BeginFrame();
|
||||||
|
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
using CodeWalker.Properties;
|
using CodeWalker.Forms;
|
||||||
|
using CodeWalker.GameFiles;
|
||||||
|
using CodeWalker.Properties;
|
||||||
|
using CodeWalker.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Windows.Shell;
|
using System.Windows.Shell;
|
||||||
@ -12,18 +18,23 @@ namespace CodeWalker
|
|||||||
{
|
{
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool AllocConsole();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
|
||||||
|
ConsoleWindow.Hide();
|
||||||
bool menumode = false;
|
bool menumode = false;
|
||||||
bool explorermode = false;
|
bool explorermode = false;
|
||||||
bool projectmode = false;
|
bool projectmode = false;
|
||||||
bool vehiclesmode = false;
|
bool vehiclesmode = false;
|
||||||
bool pedsmode = false;
|
bool pedsmode = false;
|
||||||
|
string path = null;
|
||||||
if ((args != null) && (args.Length > 0))
|
if ((args != null) && (args.Length > 0))
|
||||||
{
|
{
|
||||||
foreach (string arg in args)
|
foreach (string arg in args)
|
||||||
@ -49,6 +60,18 @@ namespace CodeWalker
|
|||||||
{
|
{
|
||||||
pedsmode = true;
|
pedsmode = true;
|
||||||
}
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(arg))
|
||||||
|
{
|
||||||
|
path = arg;
|
||||||
|
}
|
||||||
|
} catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(ex);
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +112,14 @@ namespace CodeWalker
|
|||||||
{
|
{
|
||||||
Application.Run(new PedsForm());
|
Application.Run(new PedsForm());
|
||||||
}
|
}
|
||||||
|
else if (path != null)
|
||||||
|
{
|
||||||
|
var modelForm = new ModelForm();
|
||||||
|
modelForm.Load += new EventHandler(async (sender, eventArgs) => {
|
||||||
|
modelForm.ViewModel(path);
|
||||||
|
});
|
||||||
|
Application.Run(modelForm);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Application.Run(new WorldForm());
|
Application.Run(new WorldForm());
|
||||||
|
@ -123,8 +123,8 @@ namespace CodeWalker.Project
|
|||||||
|
|
||||||
XmlElement enode = node as XmlElement;
|
XmlElement enode = node as XmlElement;
|
||||||
|
|
||||||
var hashstr = Xml.GetChildInnerText(node, "ModelHash").ToLowerInvariant();
|
var hashstr = Xml.GetChildInnerText(node, "ModelHash");
|
||||||
if (hashstr.StartsWith("0x")) hashstr = hashstr.Substring(2);
|
if (hashstr.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) hashstr = hashstr.Substring(2);
|
||||||
ModelHash = Convert.ToUInt32(hashstr, 16);
|
ModelHash = Convert.ToUInt32(hashstr, 16);
|
||||||
|
|
||||||
Type = Xml.GetChildIntInnerText(node, "Type");
|
Type = Xml.GetChildIntInnerText(node, "Type");
|
||||||
|
@ -102,7 +102,7 @@ namespace CodeWalker.Project.Panels
|
|||||||
{
|
{
|
||||||
ymapname = ymap.Name.ToLowerInvariant();
|
ymapname = ymap.Name.ToLowerInvariant();
|
||||||
}
|
}
|
||||||
if (ymapname.EndsWith(".ymap"))
|
if (ymapname.EndsWith(".ymap", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ymapname = ymapname.Substring(0, ymapname.Length - 5);
|
ymapname = ymapname.Substring(0, ymapname.Length - 5);
|
||||||
}
|
}
|
||||||
|
@ -264,12 +264,10 @@ namespace CodeWalker.Project.Panels
|
|||||||
lodymap._CMapData.name = JenkHash.GenHash(lodname);
|
lodymap._CMapData.name = JenkHash.GenHash(lodname);
|
||||||
lodymap.RpfFileEntry = new RpfResourceFileEntry();
|
lodymap.RpfFileEntry = new RpfResourceFileEntry();
|
||||||
lodymap.RpfFileEntry.Name = lodname + ".ymap";
|
lodymap.RpfFileEntry.Name = lodname + ".ymap";
|
||||||
lodymap.RpfFileEntry.NameLower = lodname + ".ymap";
|
|
||||||
distymap.Name = distname;
|
distymap.Name = distname;
|
||||||
distymap._CMapData.name = JenkHash.GenHash(distname);
|
distymap._CMapData.name = JenkHash.GenHash(distname);
|
||||||
distymap.RpfFileEntry = new RpfResourceFileEntry();
|
distymap.RpfFileEntry = new RpfResourceFileEntry();
|
||||||
distymap.RpfFileEntry.Name = distname + ".ymap";
|
distymap.RpfFileEntry.Name = distname + ".ymap";
|
||||||
distymap.RpfFileEntry.NameLower = distname + ".ymap";
|
|
||||||
|
|
||||||
lodymap._CMapData.parent = distymap._CMapData.name;
|
lodymap._CMapData.parent = distymap._CMapData.name;
|
||||||
lodymap.Loaded = true;
|
lodymap.Loaded = true;
|
||||||
|
@ -510,13 +510,11 @@ namespace CodeWalker.Project
|
|||||||
}
|
}
|
||||||
public bool RenameYmap(string oldfilename, string newfilename)
|
public bool RenameYmap(string oldfilename, string newfilename)
|
||||||
{
|
{
|
||||||
oldfilename = oldfilename.ToLowerInvariant();
|
|
||||||
newfilename = newfilename.ToLowerInvariant();
|
|
||||||
for (int i = 0; i < YmapFilenames.Count; i++)
|
for (int i = 0; i < YmapFilenames.Count; i++)
|
||||||
{
|
{
|
||||||
if (YmapFilenames[i]?.ToLowerInvariant() == oldfilename)
|
if (YmapFilenames[i]?.Equals(oldfilename, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||||
{
|
{
|
||||||
YmapFilenames[i] = newfilename;
|
YmapFilenames[i] = newfilename.ToLowerInvariant();
|
||||||
HasChanged = true;
|
HasChanged = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -580,13 +578,11 @@ namespace CodeWalker.Project
|
|||||||
}
|
}
|
||||||
public bool RenameYtyp(string oldfilename, string newfilename)
|
public bool RenameYtyp(string oldfilename, string newfilename)
|
||||||
{
|
{
|
||||||
oldfilename = oldfilename.ToLowerInvariant();
|
|
||||||
newfilename = newfilename.ToLowerInvariant();
|
|
||||||
for (int i = 0; i < YtypFilenames.Count; i++)
|
for (int i = 0; i < YtypFilenames.Count; i++)
|
||||||
{
|
{
|
||||||
if (YtypFilenames[i]?.ToLowerInvariant() == oldfilename)
|
if (YtypFilenames[i]?.Equals(oldfilename, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||||
{
|
{
|
||||||
YtypFilenames[i] = newfilename;
|
YtypFilenames[i] = newfilename.ToLowerInvariant();
|
||||||
HasChanged = true;
|
HasChanged = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -609,7 +605,7 @@ namespace CodeWalker.Project
|
|||||||
{
|
{
|
||||||
string relpath = GetRelativePath(ybn.FilePath);
|
string relpath = GetRelativePath(ybn.FilePath);
|
||||||
if (string.IsNullOrEmpty(relpath)) relpath = ybn.Name;
|
if (string.IsNullOrEmpty(relpath)) relpath = ybn.Name;
|
||||||
if (YndFilenames.Contains(relpath)) return false;
|
if (YndFilenames.Contains(relpath, StringComparer.OrdinalIgnoreCase)) return false;
|
||||||
YbnFilenames.Add(relpath);
|
YbnFilenames.Add(relpath);
|
||||||
YbnFiles.Add(ybn);
|
YbnFiles.Add(ybn);
|
||||||
return true;
|
return true;
|
||||||
@ -626,10 +622,9 @@ namespace CodeWalker.Project
|
|||||||
public bool ContainsYbn(string filename)
|
public bool ContainsYbn(string filename)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
filename = filename.ToLowerInvariant();
|
|
||||||
foreach (var yndfn in YbnFilenames)
|
foreach (var yndfn in YbnFilenames)
|
||||||
{
|
{
|
||||||
if (yndfn == filename)
|
if (yndfn.Equals(filename, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@ -651,7 +646,7 @@ namespace CodeWalker.Project
|
|||||||
newfilename = newfilename.ToLowerInvariant();
|
newfilename = newfilename.ToLowerInvariant();
|
||||||
for (int i = 0; i < YbnFilenames.Count; i++)
|
for (int i = 0; i < YbnFilenames.Count; i++)
|
||||||
{
|
{
|
||||||
if (YbnFilenames[i]?.ToLowerInvariant() == oldfilename)
|
if (YbnFilenames[i]?.Equals(oldfilename, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||||
{
|
{
|
||||||
YbnFilenames[i] = newfilename;
|
YbnFilenames[i] = newfilename;
|
||||||
HasChanged = true;
|
HasChanged = true;
|
||||||
@ -937,7 +932,6 @@ namespace CodeWalker.Project
|
|||||||
RelFile relfile = new RelFile();
|
RelFile relfile = new RelFile();
|
||||||
relfile.RpfFileEntry = new RpfResourceFileEntry();
|
relfile.RpfFileEntry = new RpfResourceFileEntry();
|
||||||
relfile.RpfFileEntry.Name = Path.GetFileName(filename);
|
relfile.RpfFileEntry.Name = Path.GetFileName(filename);
|
||||||
relfile.RpfFileEntry.NameHash = JenkHash.GenHash(relfile.RpfFileEntry.Name);
|
|
||||||
relfile.FilePath = GetFullFilePath(filename);
|
relfile.FilePath = GetFullFilePath(filename);
|
||||||
relfile.Name = relfile.RpfFileEntry.Name;
|
relfile.Name = relfile.RpfFileEntry.Name;
|
||||||
if (!AddAudioRelFile(relfile)) return null;
|
if (!AddAudioRelFile(relfile)) return null;
|
||||||
|
@ -7102,12 +7102,6 @@ namespace CodeWalker.Project
|
|||||||
var ymap = CurrentProjectFile.YmapFiles[i];
|
var ymap = CurrentProjectFile.YmapFiles[i];
|
||||||
if (ymap.Loaded)
|
if (ymap.Loaded)
|
||||||
{
|
{
|
||||||
// make sure we're replacing ymaps that have been added by the end-user.
|
|
||||||
if (ymap.RpfFileEntry.ShortNameHash == 0)
|
|
||||||
{
|
|
||||||
ymap.RpfFileEntry.ShortNameHash = JenkHash.GenHash(ymap.RpfFileEntry.GetShortNameLower());
|
|
||||||
}
|
|
||||||
|
|
||||||
ymaps[ymap.RpfFileEntry.ShortNameHash] = ymap;
|
ymaps[ymap.RpfFileEntry.ShortNameHash] = ymap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
182
CodeWalker/Properties/Settings.Designer.cs
generated
182
CodeWalker/Properties/Settings.Designer.cs
generated
@ -12,7 +12,7 @@ namespace CodeWalker.Properties {
|
|||||||
|
|
||||||
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
|
||||||
public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||||
|
|
||||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
@ -155,42 +155,6 @@ namespace CodeWalker.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
|
||||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
|
||||||
public bool LODLights {
|
|
||||||
get {
|
|
||||||
return ((bool)(this["LODLights"]));
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
this["LODLights"] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
|
||||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
|
||||||
public bool NatrualAmbientLight {
|
|
||||||
get {
|
|
||||||
return ((bool)(this["NatrualAmbientLight"]));
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
this["NatrualAmbientLight"] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
|
||||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
|
||||||
public bool ArtificialAmbientLight {
|
|
||||||
get {
|
|
||||||
return ((bool)(this["ArtificialAmbientLight"]));
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
this["ArtificialAmbientLight"] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||||
@ -527,54 +491,6 @@ namespace CodeWalker.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSetting()]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCode()]
|
|
||||||
[global::System.Configuration.DefaultSettingValue("EXTRASUNNY")]
|
|
||||||
public string Weather {
|
|
||||||
get {
|
|
||||||
return ((string)(this["Weather"]));
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
this["Weather"] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSetting()]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCode()]
|
|
||||||
[global::System.Configuration.DefaultSettingValue("GLOBAL")]
|
|
||||||
public string Region {
|
|
||||||
get {
|
|
||||||
return ((string)(this["Region"]));
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
this["Region"] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSetting()]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCode()]
|
|
||||||
[global::System.Configuration.DefaultSettingValue("contrails")]
|
|
||||||
public string Clouds {
|
|
||||||
get {
|
|
||||||
return ((string)(this["Clouds"]));
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
this["Clouds"] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSetting()]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCode()]
|
|
||||||
[global::System.Configuration.DefaultSettingValue("720")]
|
|
||||||
public int TimeOfDay {
|
|
||||||
get {
|
|
||||||
return ((int)(this["TimeOfDay"]));
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
this["TimeOfDay"] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Configuration.DefaultSettingValueAttribute("DiffuseSampler")]
|
[global::System.Configuration.DefaultSettingValueAttribute("DiffuseSampler")]
|
||||||
@ -914,5 +830,101 @@ namespace CodeWalker.Properties {
|
|||||||
this["RPFExplorerStartFolder"] = value;
|
this["RPFExplorerStartFolder"] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("720")]
|
||||||
|
public int TimeOfDay {
|
||||||
|
get {
|
||||||
|
return ((int)(this["TimeOfDay"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["TimeOfDay"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||||
|
public bool LODLights {
|
||||||
|
get {
|
||||||
|
return ((bool)(this["LODLights"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["LODLights"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("Global")]
|
||||||
|
public string Region {
|
||||||
|
get {
|
||||||
|
return ((string)(this["Region"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["Region"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("contrails")]
|
||||||
|
public string Clouds {
|
||||||
|
get {
|
||||||
|
return ((string)(this["Clouds"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["Clouds"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||||
|
public string Weather {
|
||||||
|
get {
|
||||||
|
return ((string)(this["Weather"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["Weather"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||||
|
public bool NatrualAmbientLight {
|
||||||
|
get {
|
||||||
|
return ((bool)(this["NatrualAmbientLight"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["NatrualAmbientLight"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||||
|
public bool ArtificialAmbientLight {
|
||||||
|
get {
|
||||||
|
return ((bool)(this["ArtificialAmbientLight"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["ArtificialAmbientLight"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("2")]
|
||||||
|
public int AntiAliasing {
|
||||||
|
get {
|
||||||
|
return ((int)(this["AntiAliasing"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["AntiAliasing"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,5 +216,29 @@
|
|||||||
<Setting Name="RPFExplorerStartFolder" Type="System.String" Scope="User">
|
<Setting Name="RPFExplorerStartFolder" Type="System.String" Scope="User">
|
||||||
<Value Profile="(Default)" />
|
<Value Profile="(Default)" />
|
||||||
</Setting>
|
</Setting>
|
||||||
|
<Setting Name="TimeOfDay" Type="System.Int32" Scope="User">
|
||||||
|
<Value Profile="(Default)">720</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="LODLights" Type="System.Boolean" Scope="User">
|
||||||
|
<Value Profile="(Default)">False</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="Region" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">Global</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="Clouds" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">contrails</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="Weather" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">True</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="NatrualAmbientLight" Type="System.Boolean" Scope="User">
|
||||||
|
<Value Profile="(Default)">True</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="ArtificialAmbientLight" Type="System.Boolean" Scope="User">
|
||||||
|
<Value Profile="(Default)">True</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="AntiAliasing" Type="System.Int32" Scope="User">
|
||||||
|
<Value Profile="(Default)">2</Value>
|
||||||
|
</Setting>
|
||||||
</Settings>
|
</Settings>
|
||||||
</SettingsFile>
|
</SettingsFile>
|
@ -19,7 +19,7 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
Form Form { get; }
|
Form Form { get; }
|
||||||
|
|
||||||
|
public bool Pauserendering { get; set; }
|
||||||
void InitScene(Device device);
|
void InitScene(Device device);
|
||||||
void CleanupScene();
|
void CleanupScene();
|
||||||
void RenderScene(DeviceContext context);
|
void RenderScene(DeviceContext context);
|
||||||
|
@ -7,12 +7,14 @@ using SharpDX.Direct3D11;
|
|||||||
using SharpDX.DXGI;
|
using SharpDX.DXGI;
|
||||||
using Color = SharpDX.Color;
|
using Color = SharpDX.Color;
|
||||||
using Device = SharpDX.Direct3D11.Device;
|
using Device = SharpDX.Direct3D11.Device;
|
||||||
using Buffer = SharpDX.Direct3D11.Buffer;
|
|
||||||
using DriverType = SharpDX.Direct3D.DriverType;
|
using DriverType = SharpDX.Direct3D.DriverType;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using SharpDX;
|
using SharpDX;
|
||||||
using SharpDX.Direct3D;
|
using SharpDX.Direct3D;
|
||||||
|
using System.Runtime;
|
||||||
|
using CodeWalker.Core.Utils;
|
||||||
|
using CodeWalker.Properties;
|
||||||
|
|
||||||
namespace CodeWalker.Rendering
|
namespace CodeWalker.Rendering
|
||||||
{
|
{
|
||||||
@ -32,7 +34,7 @@ namespace CodeWalker.Rendering
|
|||||||
private volatile bool Rendering = false;
|
private volatile bool Rendering = false;
|
||||||
private volatile bool Resizing = false;
|
private volatile bool Resizing = false;
|
||||||
private object syncroot = new object(); //for thread safety
|
private object syncroot = new object(); //for thread safety
|
||||||
public int multisamplecount { get; private set; } = 4; //should be a setting..
|
public int multisamplecount { get; private set; } = Settings.Default.AntiAliasing;
|
||||||
public int multisamplequality { get; private set; } = 0; //should be a setting...
|
public int multisamplequality { get; private set; } = 0; //should be a setting...
|
||||||
public Color clearcolour { get; private set; } = new Color(0.2f, 0.4f, 0.6f, 1.0f); //gross
|
public Color clearcolour { get; private set; } = new Color(0.2f, 0.4f, 0.6f, 1.0f); //gross
|
||||||
private System.Drawing.Size beginSize;
|
private System.Drawing.Size beginSize;
|
||||||
@ -209,7 +211,6 @@ namespace CodeWalker.Rendering
|
|||||||
{
|
{
|
||||||
if (Resizing) return;
|
if (Resizing) return;
|
||||||
Monitor.Enter(syncroot);
|
Monitor.Enter(syncroot);
|
||||||
|
|
||||||
int width = dxform.Form.ClientSize.Width;
|
int width = dxform.Form.ClientSize.Width;
|
||||||
int height = dxform.Form.ClientSize.Height;
|
int height = dxform.Form.ClientSize.Height;
|
||||||
|
|
||||||
@ -246,6 +247,7 @@ namespace CodeWalker.Rendering
|
|||||||
Cleanup();
|
Cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dxform_ClientSizeChanged(object sender, EventArgs e)
|
private void Dxform_ClientSizeChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Resize();
|
Resize();
|
||||||
@ -273,21 +275,45 @@ namespace CodeWalker.Rendering
|
|||||||
private void StartRenderLoop()
|
private void StartRenderLoop()
|
||||||
{
|
{
|
||||||
Running = true;
|
Running = true;
|
||||||
new Thread(new ThreadStart(RenderLoop)).Start();
|
new Task(RenderLoop, TaskCreationOptions.LongRunning).Start(TaskScheduler.Default);
|
||||||
|
//new Thread(new ThreadStart(RenderLoop)).Start();
|
||||||
}
|
}
|
||||||
private void RenderLoop()
|
private void RenderLoop()
|
||||||
{
|
{
|
||||||
|
//SharpDX.Configuration.EnableObjectTracking = true;
|
||||||
|
//Task.Run(async () =>
|
||||||
|
//{
|
||||||
|
// while (true)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects());
|
||||||
|
// await Task.Delay(5000);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
Thread.CurrentThread.Name = "RenderLoop";
|
||||||
while (Running)
|
while (Running)
|
||||||
{
|
{
|
||||||
while (Resizing)
|
while (Resizing)
|
||||||
{
|
{
|
||||||
swapchain.Present(1, PresentFlags.None); //just flip buffers when resizing; don't draw
|
swapchain.Present(1, PresentFlags.None); //just flip buffers when resizing; don't draw
|
||||||
}
|
}
|
||||||
|
if (dxform.Form.WindowState == FormWindowState.Minimized)
|
||||||
|
{
|
||||||
|
dxform.Pauserendering = true;
|
||||||
|
|
||||||
|
Console.WriteLine("Window is minimized");
|
||||||
|
dxform.RenderScene(context);
|
||||||
|
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
|
||||||
|
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||||
while (dxform.Form.WindowState == FormWindowState.Minimized)
|
while (dxform.Form.WindowState == FormWindowState.Minimized)
|
||||||
{
|
{
|
||||||
Thread.Sleep(10); //don't hog CPU when minimised
|
Thread.Sleep(100); //don't hog CPU when minimised
|
||||||
if (dxform.Form.IsDisposed) return; //if closed while minimised
|
if (dxform.Form.IsDisposed) return; //if closed while minimised
|
||||||
}
|
}
|
||||||
|
dxform.Pauserendering = false;
|
||||||
|
Console.WriteLine("Window is maximized");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Form.ActiveForm == null)
|
if (Form.ActiveForm == null)
|
||||||
{
|
{
|
||||||
Thread.Sleep(100); //reduce the FPS when the app isn't active (maybe this should be configurable?)
|
Thread.Sleep(100); //reduce the FPS when the app isn't active (maybe this should be configurable?)
|
||||||
@ -295,13 +321,17 @@ namespace CodeWalker.Rendering
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rendering = true;
|
Rendering = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
if (!Monitor.TryEnter(syncroot, 50))
|
if (!Monitor.TryEnter(syncroot, 50))
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("Failed to get lock for syncroot");
|
||||||
Thread.Sleep(10); //don't hog CPU when not able to render...
|
Thread.Sleep(10); //don't hog CPU when not able to render...
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
context.OutputMerger.SetRenderTargets(depthview, targetview);
|
context.OutputMerger.SetRenderTargets(depthview, targetview);
|
||||||
@ -333,10 +363,12 @@ namespace CodeWalker.Rendering
|
|||||||
MessageBox.Show("Error presenting swap chain!\n" + ex.ToString());
|
MessageBox.Show("Error presenting swap chain!\n" + ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
Monitor.Exit(syncroot);
|
Monitor.Exit(syncroot);
|
||||||
Rendering = false;
|
Rendering = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1475,6 +1475,7 @@ namespace CodeWalker.Rendering
|
|||||||
public float FalloffExponent;
|
public float FalloffExponent;
|
||||||
public float InnerAngle;//for cone
|
public float InnerAngle;//for cone
|
||||||
public float OuterAngleOrCapExt;//outer angle for cone, cap extent for capsule
|
public float OuterAngleOrCapExt;//outer angle for cone, cap extent for capsule
|
||||||
|
public float Distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LODLight[] Points;
|
public LODLight[] Points;
|
||||||
@ -1512,7 +1513,7 @@ namespace CodeWalker.Rendering
|
|||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
var l = ll.LodLights[i];
|
var l = ll.LodLights[i];
|
||||||
if (l.Enabled == false) continue;
|
if (l.Enabled == false || l.Visible == false) continue;
|
||||||
var light = new LODLight();
|
var light = new LODLight();
|
||||||
light.Position = l.Position;
|
light.Position = l.Position;
|
||||||
light.Colour = (uint)l.Colour.ToBgra();
|
light.Colour = (uint)l.Colour.ToBgra();
|
||||||
@ -1549,6 +1550,58 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (int, int, int) UpdateLods(Vector3 refPos)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Points.Length; i++)
|
||||||
|
{
|
||||||
|
Points[i].Distance = Vector3.DistanceSquared(refPos, Points[i].Position);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Spots.Length; i++)
|
||||||
|
{
|
||||||
|
Spots[i].Distance = Vector3.DistanceSquared(refPos, Spots[i].Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Caps.Length; i++)
|
||||||
|
{
|
||||||
|
Caps[i].Distance = Vector3.DistanceSquared(refPos, Caps[i].Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.Sort(Points, (a, b) => a.Distance.CompareTo(b.Distance));
|
||||||
|
Array.Sort(Spots, (a, b) => a.Distance.CompareTo(b.Distance));
|
||||||
|
Array.Sort(Caps, (a, b) => a.Distance.CompareTo(b.Distance));
|
||||||
|
|
||||||
|
var spotsIndex = 0;
|
||||||
|
var pointsIndex = 0;
|
||||||
|
var capsIndex = 0;
|
||||||
|
for (int i = 0; i < Points.Length; i++)
|
||||||
|
{
|
||||||
|
if (Points[i].Distance > 100_000)
|
||||||
|
{
|
||||||
|
pointsIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Spots.Length; i++)
|
||||||
|
{
|
||||||
|
if (Spots[i].Distance > 100_000)
|
||||||
|
{
|
||||||
|
spotsIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Caps.Length; i++)
|
||||||
|
{
|
||||||
|
if (Caps[i].Distance > 100_000)
|
||||||
|
{
|
||||||
|
capsIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pointsIndex, spotsIndex, capsIndex);
|
||||||
|
}
|
||||||
|
|
||||||
public override void Load(Device device)
|
public override void Load(Device device)
|
||||||
{
|
{
|
||||||
if ((Points != null) && (Points.Length > 0))
|
if ((Points != null) && (Points.Length > 0))
|
||||||
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using static CodeWalker.Rendering.RenderableLODLights;
|
||||||
|
|
||||||
namespace CodeWalker.Rendering
|
namespace CodeWalker.Rendering
|
||||||
{
|
{
|
||||||
@ -172,11 +173,7 @@ namespace CodeWalker.Rendering
|
|||||||
public Renderer(DXForm form, GameFileCache cache)
|
public Renderer(DXForm form, GameFileCache cache)
|
||||||
{
|
{
|
||||||
Form = form;
|
Form = form;
|
||||||
gameFileCache = cache;
|
gameFileCache = cache ?? GameFileCacheFactory.Create();
|
||||||
if (gameFileCache == null)
|
|
||||||
{
|
|
||||||
gameFileCache = GameFileCacheFactory.Create();
|
|
||||||
}
|
|
||||||
renderableCache = new RenderableCache();
|
renderableCache = new RenderableCache();
|
||||||
|
|
||||||
var s = Settings.Default;
|
var s = Settings.Default;
|
||||||
@ -384,15 +381,13 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
public string GetStatusText()
|
public string GetStatusText()
|
||||||
{
|
{
|
||||||
int rgc = (shaders != null) ? shaders.RenderedGeometries : 0;
|
var rgc = shaders?.RenderedGeometries ?? 0;
|
||||||
int crc = renderableCache.LoadedRenderableCount;
|
var crc = renderableCache.LoadedRenderableCount;
|
||||||
int ctc = renderableCache.LoadedTextureCount;
|
var ctc = renderableCache.LoadedTextureCount;
|
||||||
int tcrc = renderableCache.MemCachedRenderableCount;
|
var vr = renderableCache.TotalGraphicsMemoryUse + (shaders != null ? shaders.TotalGraphicsMemoryUse : 0);
|
||||||
int tctc = renderableCache.MemCachedTextureCount;
|
var vram = TextUtil.GetBytesReadable(vr);
|
||||||
long vr = renderableCache.TotalGraphicsMemoryUse + (shaders != null ? shaders.TotalGraphicsMemoryUse : 0);
|
|
||||||
string vram = TextUtil.GetBytesReadable(vr);
|
return $"Drawn: {rgc} geom, Loaded: {crc} dr, {ctc} tx, Vram: {vram}, Fps: {fps}";
|
||||||
//StatsLabel.Text = string.Format("Drawn: {0} geom, Loaded: {1}/{5} dr, {2}/{6} tx, Vram: {3}, Fps: {4}", rgc, crc, ctc, vram, fps, tcrc, tctc);
|
|
||||||
return string.Format("Drawn: {0} geom, Loaded: {1} dr, {2} tx, Vram: {3}, Fps: {4}", rgc, crc, ctc, vram, fps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1850,7 +1845,7 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void RenderWorld(Dictionary<MetaHash, YmapFile> renderworldVisibleYmapDict, IEnumerable<Entity> spaceEnts)
|
public void RenderWorld(Dictionary<MetaHash, YmapFile> ymapsWithinStreamingExtents, IEnumerable<Entity> spaceEnts)
|
||||||
{
|
{
|
||||||
renderworldentities.Clear();
|
renderworldentities.Clear();
|
||||||
renderworldrenderables.Clear();
|
renderworldrenderables.Clear();
|
||||||
@ -1860,7 +1855,7 @@ namespace CodeWalker.Rendering
|
|||||||
RequiredParents.Clear();
|
RequiredParents.Clear();
|
||||||
RenderEntities.Clear();
|
RenderEntities.Clear();
|
||||||
|
|
||||||
foreach (var ymap in renderworldVisibleYmapDict.Values)
|
foreach (var ymap in ymapsWithinStreamingExtents.Values)
|
||||||
{
|
{
|
||||||
if (!RenderWorldYmapIsVisible(ymap)) continue;
|
if (!RenderWorldYmapIsVisible(ymap)) continue;
|
||||||
VisibleYmaps.Add(ymap);
|
VisibleYmaps.Add(ymap);
|
||||||
@ -1875,7 +1870,7 @@ namespace CodeWalker.Rendering
|
|||||||
LodManager.ShowScriptedYmaps = ShowScriptedYmaps;
|
LodManager.ShowScriptedYmaps = ShowScriptedYmaps;
|
||||||
LodManager.LODLightsEnabled = renderlodlights;
|
LodManager.LODLightsEnabled = renderlodlights;
|
||||||
LodManager.HDLightsEnabled = renderlights;
|
LodManager.HDLightsEnabled = renderlights;
|
||||||
LodManager.Update(renderworldVisibleYmapDict, camera, currentElapsedTime);
|
LodManager.Update(ymapsWithinStreamingExtents, camera, currentElapsedTime);
|
||||||
|
|
||||||
foreach (var updatelodlights in LodManager.UpdateLodLights)
|
foreach (var updatelodlights in LodManager.UpdateLodLights)
|
||||||
{
|
{
|
||||||
@ -2012,120 +2007,6 @@ namespace CodeWalker.Rendering
|
|||||||
RenderWorldYmapExtras();
|
RenderWorldYmapExtras();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenderWorld_Orig(Dictionary<MetaHash, YmapFile> renderworldVisibleYmapDict, IEnumerable<Entity> spaceEnts)
|
|
||||||
{
|
|
||||||
renderworldentities.Clear();
|
|
||||||
renderworldrenderables.Clear();
|
|
||||||
VisibleYmaps.Clear();
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var ymap in renderworldVisibleYmapDict.Values)
|
|
||||||
{
|
|
||||||
if (!RenderWorldYmapIsVisible(ymap)) continue;
|
|
||||||
VisibleYmaps.Add(ymap);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderWorldAdjustMapViewCamera();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (int y = 0; y < VisibleYmaps.Count; y++)
|
|
||||||
{
|
|
||||||
var ymap = VisibleYmaps[y];
|
|
||||||
YmapFile pymap = ymap.Parent;
|
|
||||||
if ((pymap == null) && (ymap._CMapData.parent != 0))
|
|
||||||
{
|
|
||||||
renderworldVisibleYmapDict.TryGetValue(ymap._CMapData.parent, out pymap);
|
|
||||||
ymap.Parent = pymap;
|
|
||||||
}
|
|
||||||
if (ymap.RootEntities != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ymap.RootEntities.Length; i++)
|
|
||||||
{
|
|
||||||
var ent = ymap.RootEntities[i];
|
|
||||||
int pind = ent._CEntityDef.parentIndex;
|
|
||||||
if (pind >= 0) //connect root entities to parents if they have them..
|
|
||||||
{
|
|
||||||
YmapEntityDef p = null;
|
|
||||||
if ((pymap != null) && (pymap.AllEntities != null))
|
|
||||||
{
|
|
||||||
if ((pind < pymap.AllEntities.Length))
|
|
||||||
{
|
|
||||||
p = pymap.AllEntities[pind];
|
|
||||||
ent.Parent = p;
|
|
||||||
ent.ParentName = p._CEntityDef.archetypeName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ }//should only happen if parent ymap not loaded yet...
|
|
||||||
}
|
|
||||||
RenderWorldRecurseCalcEntityVisibility(ent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int y = 0; y < VisibleYmaps.Count; y++)
|
|
||||||
{
|
|
||||||
var ymap = VisibleYmaps[y];
|
|
||||||
if (ymap.RootEntities != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ymap.RootEntities.Length; i++)
|
|
||||||
{
|
|
||||||
var ent = ymap.RootEntities[i];
|
|
||||||
RenderWorldRecurseAddEntities(ent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (spaceEnts != null)
|
|
||||||
{
|
|
||||||
foreach (var ae in spaceEnts) //used by active space entities (eg "bullets")
|
|
||||||
{
|
|
||||||
if (ae.EntityDef == null) continue; //nothing to render...
|
|
||||||
RenderWorldCalcEntityVisibility(ae.EntityDef);
|
|
||||||
renderworldentities.Add(ae.EntityDef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (renderentities)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < renderworldentities.Count; i++)
|
|
||||||
{
|
|
||||||
var ent = renderworldentities[i];
|
|
||||||
var arch = ent.Archetype;
|
|
||||||
var pent = ent.Parent;
|
|
||||||
var drawable = gameFileCache.TryGetDrawable(arch);
|
|
||||||
Renderable rndbl = TryGetRenderable(arch, drawable);
|
|
||||||
if ((rndbl != null) && rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload))
|
|
||||||
{
|
|
||||||
RenderableEntity rent = new RenderableEntity();
|
|
||||||
rent.Entity = ent;
|
|
||||||
rent.Renderable = rndbl;
|
|
||||||
renderworldrenderables.Add(rent);
|
|
||||||
}
|
|
||||||
else if (waitforchildrentoload)
|
|
||||||
{
|
|
||||||
//todo: render parent if children loading.......
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < renderworldrenderables.Count; i++)
|
|
||||||
{
|
|
||||||
var rent = renderworldrenderables[i];
|
|
||||||
var ent = rent.Entity;
|
|
||||||
var arch = ent.Archetype;
|
|
||||||
|
|
||||||
if (HideEntities.ContainsKey(ent.EntityHash)) continue; //don't render hidden entities!
|
|
||||||
|
|
||||||
RenderArchetype(arch, ent, rent.Renderable, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderWorldYmapExtras();
|
|
||||||
}
|
|
||||||
private void RenderWorldCalcEntityVisibility(YmapEntityDef ent)
|
private void RenderWorldCalcEntityVisibility(YmapEntityDef ent)
|
||||||
{
|
{
|
||||||
float dist = (ent.Position - camera.Position).Length();
|
float dist = (ent.Position - camera.Position).Length();
|
||||||
@ -4154,9 +4035,9 @@ namespace CodeWalker.Rendering
|
|||||||
{
|
{
|
||||||
if (VisibleLightsPrev.Contains(light) == false)
|
if (VisibleLightsPrev.Contains(light) == false)
|
||||||
{
|
{
|
||||||
if (LodLightsDict.TryGetValue(light.Hash, out var lodlight))
|
if (LodLightsDict.TryGetValue(light.Hash, out var lodlight) && lodlight.Enabled)
|
||||||
{
|
{
|
||||||
lodlight.Enabled = false;
|
lodlight.Enabled = true;
|
||||||
UpdateLodLights.Add(lodlight.LodLights);
|
UpdateLodLights.Add(lodlight.LodLights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4165,18 +4046,36 @@ namespace CodeWalker.Rendering
|
|||||||
{
|
{
|
||||||
if (VisibleLights.Contains(light) == false)
|
if (VisibleLights.Contains(light) == false)
|
||||||
{
|
{
|
||||||
if (LodLightsDict.TryGetValue(light.Hash, out var lodlight))
|
if (LodLightsDict.TryGetValue(light.Hash, out var lodlight) && !lodlight.Enabled)
|
||||||
{
|
{
|
||||||
lodlight.Enabled = true;
|
lodlight.Enabled = false;
|
||||||
UpdateLodLights.Add(lodlight.LodLights);
|
UpdateLodLights.Add(lodlight.LodLights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//foreach (var light in LodLightsDict.Values)
|
||||||
|
//{
|
||||||
|
// if (LightVisible(light))
|
||||||
|
// {
|
||||||
|
// if (light.Visible)
|
||||||
|
// {
|
||||||
|
// light.Visible = false;
|
||||||
|
// UpdateLodLights.Add(light.LodLights);
|
||||||
|
// }
|
||||||
|
|
||||||
var vl = VisibleLights;
|
// } else
|
||||||
VisibleLights = VisibleLightsPrev;
|
// {
|
||||||
VisibleLightsPrev = vl;
|
// if (!light.Visible)
|
||||||
|
// {
|
||||||
|
// light.Visible = true;
|
||||||
|
// UpdateLodLights.Add(light.LodLights);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
(VisibleLightsPrev, VisibleLights) = (VisibleLights, VisibleLightsPrev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecurseAddVisibleLeaves(YmapEntityDef ent)
|
private void RecurseAddVisibleLeaves(YmapEntityDef ent)
|
||||||
@ -4254,6 +4153,21 @@ namespace CodeWalker.Rendering
|
|||||||
return Camera.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent);
|
return Camera.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool LightVisible(YmapLODLight lodLight)
|
||||||
|
{
|
||||||
|
var position = lodLight.Position;
|
||||||
|
var extent = new Vector3(lodLight.Falloff, lodLight.Falloff, lodLight.Falloff);
|
||||||
|
if (MapViewEnabled)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Camera.ViewFrustum.ContainsAABBNoClip(ref position, ref extent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool EntityVisibleAtMaxLodLevel(YmapEntityDef ent)
|
private bool EntityVisibleAtMaxLodLevel(YmapEntityDef ent)
|
||||||
{
|
{
|
||||||
if (MaxLOD != rage__eLodType.LODTYPES_DEPTH_ORPHANHD)
|
if (MaxLOD != rage__eLodType.LODTYPES_DEPTH_ORPHANHD)
|
||||||
|
@ -18,6 +18,9 @@ namespace CodeWalker.Rendering
|
|||||||
private int GeometryCount;
|
private int GeometryCount;
|
||||||
public int RenderedGeometries;
|
public int RenderedGeometries;
|
||||||
|
|
||||||
|
private int VerticesCount;
|
||||||
|
public int RenderedVeritices;
|
||||||
|
|
||||||
private Device Device;
|
private Device Device;
|
||||||
|
|
||||||
public bool wireframe = Settings.Default.Wireframe;
|
public bool wireframe = Settings.Default.Wireframe;
|
||||||
@ -148,7 +151,7 @@ namespace CodeWalker.Rendering
|
|||||||
IsFrontCounterClockwise = true,
|
IsFrontCounterClockwise = true,
|
||||||
IsMultisampleEnabled = true,
|
IsMultisampleEnabled = true,
|
||||||
IsScissorEnabled = false,
|
IsScissorEnabled = false,
|
||||||
SlopeScaledDepthBias = 0.0f
|
SlopeScaledDepthBias = 0.0f,
|
||||||
};
|
};
|
||||||
rsSolid = new RasterizerState(device, rsd);
|
rsSolid = new RasterizerState(device, rsd);
|
||||||
rsd.FillMode = FillMode.Wireframe;
|
rsd.FillMode = FillMode.Wireframe;
|
||||||
@ -157,6 +160,7 @@ namespace CodeWalker.Rendering
|
|||||||
rsWireframeDblSided = new RasterizerState(device, rsd);
|
rsWireframeDblSided = new RasterizerState(device, rsd);
|
||||||
rsd.FillMode = FillMode.Solid;
|
rsd.FillMode = FillMode.Solid;
|
||||||
rsSolidDblSided = new RasterizerState(device, rsd);
|
rsSolidDblSided = new RasterizerState(device, rsd);
|
||||||
|
rsd.CullMode = CullMode.Back;
|
||||||
|
|
||||||
|
|
||||||
BlendStateDescription bsd = new BlendStateDescription()
|
BlendStateDescription bsd = new BlendStateDescription()
|
||||||
@ -203,6 +207,7 @@ namespace CodeWalker.Rendering
|
|||||||
PassOperation = StencilOperation.Zero
|
PassOperation = StencilOperation.Zero
|
||||||
},
|
},
|
||||||
IsDepthEnabled = true,
|
IsDepthEnabled = true,
|
||||||
|
|
||||||
IsStencilEnabled = false,
|
IsStencilEnabled = false,
|
||||||
StencilReadMask = 0,
|
StencilReadMask = 0,
|
||||||
StencilWriteMask = 0
|
StencilWriteMask = 0
|
||||||
@ -406,6 +411,7 @@ namespace CodeWalker.Rendering
|
|||||||
public void RenderQueued(DeviceContext context, Camera camera, Vector4 wind)
|
public void RenderQueued(DeviceContext context, Camera camera, Vector4 wind)
|
||||||
{
|
{
|
||||||
GeometryCount = 0;
|
GeometryCount = 0;
|
||||||
|
VerticesCount = 0;
|
||||||
Camera = camera;
|
Camera = camera;
|
||||||
|
|
||||||
|
|
||||||
@ -662,7 +668,7 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
|
|
||||||
RenderedGeometries = GeometryCount;
|
RenderedGeometries = GeometryCount;
|
||||||
|
RenderedVeritices = VerticesCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenderFinalPass(DeviceContext context)
|
public void RenderFinalPass(DeviceContext context)
|
||||||
@ -789,6 +795,8 @@ namespace CodeWalker.Rendering
|
|||||||
var gmodel = geom.Geom.Owner;
|
var gmodel = geom.Geom.Owner;
|
||||||
shader.SetEntityVars(context, ref geom.Inst);
|
shader.SetEntityVars(context, ref geom.Inst);
|
||||||
|
|
||||||
|
VerticesCount += geom.Geom.VertexCount;
|
||||||
|
|
||||||
if (gmodel != model)
|
if (gmodel != model)
|
||||||
{
|
{
|
||||||
model = gmodel;
|
model = gmodel;
|
||||||
@ -829,6 +837,7 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
foreach (var geom in batch)
|
foreach (var geom in batch)
|
||||||
{
|
{
|
||||||
|
VerticesCount += geom.Geom.VertexCount;
|
||||||
Basic.RenderBoundGeom(context, geom);
|
Basic.RenderBoundGeom(context, geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,6 +1059,18 @@ namespace CodeWalker.Rendering
|
|||||||
{
|
{
|
||||||
return ShaderFile.ToString() + ": " + ShaderName.ToString();
|
return ShaderFile.ToString() + ": " + ShaderName.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ShaderName.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj == null) return false;
|
||||||
|
if (obj is not ShaderKey shaderKey) return false;
|
||||||
|
return shaderKey.ShaderName == ShaderName && shaderKey.ShaderFile == ShaderFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public class ShaderRenderBucket
|
public class ShaderRenderBucket
|
||||||
{
|
{
|
||||||
@ -1097,7 +1118,7 @@ namespace CodeWalker.Rendering
|
|||||||
ClothBatches.Clear();
|
ClothBatches.Clear();
|
||||||
VehicleBatches.Clear();
|
VehicleBatches.Clear();
|
||||||
|
|
||||||
foreach (var kvp in Batches)
|
foreach (var kvp in Batches.Where(p => p.Value.Geometries.Count > 0).OrderBy(p => p.Value.Geometries.Average(p => p.Inst.Distance)))
|
||||||
{
|
{
|
||||||
if (kvp.Value.Geometries.Count == 0) continue;
|
if (kvp.Value.Geometries.Count == 0) continue;
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ using SharpDX;
|
|||||||
using SharpDX.DXGI;
|
using SharpDX.DXGI;
|
||||||
using SharpDX.Mathematics.Interop;
|
using SharpDX.Mathematics.Interop;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using CodeWalker.Properties;
|
||||||
|
|
||||||
namespace CodeWalker.Rendering
|
namespace CodeWalker.Rendering
|
||||||
{
|
{
|
||||||
@ -110,7 +111,7 @@ namespace CodeWalker.Rendering
|
|||||||
public int SSAASampleCount = 1;
|
public int SSAASampleCount = 1;
|
||||||
|
|
||||||
|
|
||||||
public int MSAASampleCount = 4;
|
public int MSAASampleCount = 8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -460,7 +461,8 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
foreach (var rll in lodlights)
|
foreach (var rll in lodlights)
|
||||||
{
|
{
|
||||||
if (rll.PointsBuffer != null)
|
var (pointsIndex, spotsIndex, capsIndex) = rll.UpdateLods(camera.Position);
|
||||||
|
if (rll.PointsBuffer != null && pointsIndex > 0)
|
||||||
{
|
{
|
||||||
context.VertexShader.SetShaderResources(0, rll.PointsBuffer.SRV);
|
context.VertexShader.SetShaderResources(0, rll.PointsBuffer.SRV);
|
||||||
context.PixelShader.SetShaderResources(6, rll.PointsBuffer.SRV);
|
context.PixelShader.SetShaderResources(6, rll.PointsBuffer.SRV);
|
||||||
@ -470,9 +472,10 @@ namespace CodeWalker.Rendering
|
|||||||
LightPSVars.Vars.LightType = 1;
|
LightPSVars.Vars.LightType = 1;
|
||||||
LightPSVars.Update(context);
|
LightPSVars.Update(context);
|
||||||
LightPSVars.SetPSCBuffer(context, 0);
|
LightPSVars.SetPSCBuffer(context, 0);
|
||||||
LightSphere.DrawInstanced(context, rll.PointsBuffer.StructCount);
|
|
||||||
|
LightSphere.DrawInstanced(context, pointsIndex + 1);
|
||||||
}
|
}
|
||||||
if (rll.SpotsBuffer != null)
|
if (rll.SpotsBuffer != null && spotsIndex > 0)
|
||||||
{
|
{
|
||||||
context.VertexShader.SetShaderResources(0, rll.SpotsBuffer.SRV);
|
context.VertexShader.SetShaderResources(0, rll.SpotsBuffer.SRV);
|
||||||
context.PixelShader.SetShaderResources(6, rll.SpotsBuffer.SRV);
|
context.PixelShader.SetShaderResources(6, rll.SpotsBuffer.SRV);
|
||||||
@ -482,9 +485,9 @@ namespace CodeWalker.Rendering
|
|||||||
LightPSVars.Vars.LightType = 2;
|
LightPSVars.Vars.LightType = 2;
|
||||||
LightPSVars.Update(context);
|
LightPSVars.Update(context);
|
||||||
LightPSVars.SetPSCBuffer(context, 0);
|
LightPSVars.SetPSCBuffer(context, 0);
|
||||||
LightCone.DrawInstanced(context, rll.SpotsBuffer.StructCount);
|
LightCone.DrawInstanced(context, spotsIndex + 1);
|
||||||
}
|
}
|
||||||
if (rll.CapsBuffer != null)
|
if (rll.CapsBuffer != null && capsIndex > 0)
|
||||||
{
|
{
|
||||||
context.VertexShader.SetShaderResources(0, rll.CapsBuffer.SRV);
|
context.VertexShader.SetShaderResources(0, rll.CapsBuffer.SRV);
|
||||||
context.PixelShader.SetShaderResources(6, rll.CapsBuffer.SRV);
|
context.PixelShader.SetShaderResources(6, rll.CapsBuffer.SRV);
|
||||||
@ -494,7 +497,7 @@ namespace CodeWalker.Rendering
|
|||||||
LightPSVars.Vars.LightType = 4;
|
LightPSVars.Vars.LightType = 4;
|
||||||
LightPSVars.Update(context);
|
LightPSVars.Update(context);
|
||||||
LightPSVars.SetPSCBuffer(context, 0);
|
LightPSVars.SetPSCBuffer(context, 0);
|
||||||
LightCapsule.DrawInstanced(context, rll.CapsBuffer.StructCount);
|
LightCapsule.DrawInstanced(context, capsIndex + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,6 +440,9 @@ namespace CodeWalker.Rendering
|
|||||||
case Format.D32_Float:
|
case Format.D32_Float:
|
||||||
dtexf = Format.R32_Typeless;
|
dtexf = Format.R32_Typeless;
|
||||||
break;
|
break;
|
||||||
|
case Format.R8G8B8A8_SNorm:
|
||||||
|
dtexf = Format.R8G8B8A8_SNorm;
|
||||||
|
break;
|
||||||
case Format.D32_Float_S8X24_UInt:
|
case Format.D32_Float_S8X24_UInt:
|
||||||
dtexf = Format.R32G8X24_Typeless;//is this right? who uses this anyway??
|
dtexf = Format.R32G8X24_Typeless;//is this right? who uses this anyway??
|
||||||
break;
|
break;
|
||||||
|
@ -96,7 +96,7 @@ namespace CodeWalker.Rendering
|
|||||||
Cascades.Add(c);
|
Cascades.Add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
DepthRenderRS = DXUtility.CreateRasterizerState(device, FillMode.Solid, CullMode.None, true, false, true, 0, 0.0f, 1.0f);
|
DepthRenderRS = DXUtility.CreateRasterizerState(device, FillMode.Solid, CullMode.None, true, false, Settings.Default.AntiAliasing > 1, 0, 0.0f, 1.0f);
|
||||||
DepthRenderDS = DXUtility.CreateDepthStencilState(device, true, DepthWriteMask.All);
|
DepthRenderDS = DXUtility.CreateDepthStencilState(device, true, DepthWriteMask.All);
|
||||||
|
|
||||||
DepthRenderVP = new ViewportF();
|
DepthRenderVP = new ViewportF();
|
||||||
|
@ -127,7 +127,7 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
|
|
||||||
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, vdata.ToArray());
|
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, vdata.ToArray());
|
||||||
vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0);
|
vbbinding = new VertexBufferBinding(VertexBuffer, 8, 0);
|
||||||
|
|
||||||
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray());
|
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray());
|
||||||
indexcount = idata.Count;
|
indexcount = idata.Count;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using CodeWalker.GameFiles;
|
using CodeWalker.GameFiles;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
@ -37,12 +37,12 @@ namespace CodeWalker.Tools
|
|||||||
DataTextBox.SetTabStopWidth(3);
|
DataTextBox.SetTabStopWidth(3);
|
||||||
|
|
||||||
|
|
||||||
if (RpfMan == null)
|
if (RpfMan == null || !RpfMan.IsInited)
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
GTA5Keys.LoadFromPath(GTAFolder.CurrentGTAFolder, Settings.Default.Key);
|
GTA5Keys.LoadFromPath(GTAFolder.CurrentGTAFolder, Settings.Default.Key);
|
||||||
RpfMan = new RpfManager();
|
RpfMan ??= RpfManager.GetInstance();
|
||||||
RpfMan.Init(GTAFolder.CurrentGTAFolder, UpdateStatus, UpdateStatus, false, false);
|
RpfMan.Init(GTAFolder.CurrentGTAFolder, UpdateStatus, UpdateStatus, false, false);
|
||||||
RPFScanComplete();
|
RPFScanComplete();
|
||||||
});
|
});
|
||||||
@ -417,17 +417,13 @@ namespace CodeWalker.Tools
|
|||||||
DateTime starttime = DateTime.Now;
|
DateTime starttime = DateTime.Now;
|
||||||
int resultcount = 0;
|
int resultcount = 0;
|
||||||
|
|
||||||
for (int f = 0; f < scannedFiles.Count; f++)
|
foreach(var rpffile in scannedFiles)
|
||||||
{
|
{
|
||||||
var rpffile = scannedFiles[f];
|
|
||||||
totfiles += rpffile.TotalFileCount;
|
totfiles += rpffile.TotalFileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach(var rpffile in scannedFiles)
|
||||||
for (int f = 0; f < scannedFiles.Count; f++)
|
|
||||||
{
|
{
|
||||||
var rpffile = scannedFiles[f];
|
|
||||||
|
|
||||||
foreach (var entry in rpffile.AllEntries)
|
foreach (var entry in rpffile.AllEntries)
|
||||||
{
|
{
|
||||||
var duration = DateTime.Now - starttime;
|
var duration = DateTime.Now - starttime;
|
||||||
@ -444,7 +440,7 @@ namespace CodeWalker.Tools
|
|||||||
|
|
||||||
curfile++;
|
curfile++;
|
||||||
|
|
||||||
if (fentry.NameLower.EndsWith(".rpf"))
|
if (fentry.Name.EndsWith(".rpf", StringComparison.OrdinalIgnoreCase))
|
||||||
{ continue; }
|
{ continue; }
|
||||||
|
|
||||||
if (onlyexts != null)
|
if (onlyexts != null)
|
||||||
@ -452,7 +448,7 @@ namespace CodeWalker.Tools
|
|||||||
bool ignore = true;
|
bool ignore = true;
|
||||||
for (int i = 0; i < onlyexts.Length; i++)
|
for (int i = 0; i < onlyexts.Length; i++)
|
||||||
{
|
{
|
||||||
if (fentry.NameLower.EndsWith(onlyexts[i]))
|
if (fentry.Name.EndsWith(onlyexts[i], StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ignore = false;
|
ignore = false;
|
||||||
break;
|
break;
|
||||||
@ -467,7 +463,7 @@ namespace CodeWalker.Tools
|
|||||||
bool ignore = false;
|
bool ignore = false;
|
||||||
for (int i = 0; i < ignoreexts.Length; i++)
|
for (int i = 0; i < ignoreexts.Length; i++)
|
||||||
{
|
{
|
||||||
if (fentry.NameLower.EndsWith(ignoreexts[i]))
|
if (fentry.Name.EndsWith(ignoreexts[i], StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ignore = true;
|
ignore = true;
|
||||||
break;
|
break;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user