Created
January 30, 2018 02:25
-
-
Save ikt32/4cadaab095bfcc68da8c390a3ab6085a to your computer and use it in GitHub Desktop.
Texture list Test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
using GTA; | |
using GTA.Native; | |
struct myTexture | |
{ | |
public myTexture(string name, UInt16 resX, UInt16 resY) | |
{ | |
this.name = name; | |
this.resX = resX; | |
this.resY = resY; | |
} | |
public string name; | |
public UInt16 resX; | |
public UInt16 resY; | |
} | |
[StructLayout(LayoutKind.Explicit)] | |
public unsafe struct grcTexture | |
{ | |
[FieldOffset(0x28)] | |
public byte* name; // 0x0028 | |
[FieldOffset(0x50)] | |
public UInt16 resolutionX; // 0x0050 | |
[FieldOffset(0x52)] | |
public UInt16 resolutionY; // 0x0052 | |
[FieldOffset(0x60)] | |
public grcTexture* previous; // 0x0060 | |
[FieldOffset(0x68)] | |
public grcTexture* next; // 0x0068 | |
} | |
[StructLayout(LayoutKind.Explicit)] | |
public unsafe struct pgDictionary | |
{ | |
[FieldOffset(0x30)] | |
public grcTexture** textures; // 0x0030 | |
[FieldOffset(0x38)] | |
public UInt16 textureCount; // 0x0038 | |
}; | |
public class TextureListTest : Script | |
{ | |
unsafe public TextureListTest() | |
{ | |
// init txd store | |
var addr = FindPattern("\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x8B\x45\xEC", | |
"xxx????x????xxx"); | |
g_fwTxdStore = (ulong)(addr + *(int*)(addr + 3) + 7); | |
System.IO.File.AppendAllText(@"" + file, "g_fwTxdStore " + g_fwTxdStore + "\n"); | |
addr = FindPattern("\x48\x03\x0D\x00\x00\x00\x00\x48\x85\xD1\x75\x04\x44\x89\x4D\xF0", | |
"xxx????xxxxxxxxx"); | |
g_txdCollectionItemSize = *(uint*)((addr + *(int*)(addr + 3) + 7) + 0x14); | |
System.IO.File.AppendAllText(@"" + file, "g_txdCollectionItemSize " + g_txdCollectionItemSize + "\n"); | |
Tick += OnTick; | |
} | |
private int maxAttempts = 100; | |
private string file = "textures.txt"; | |
UInt64 g_fwTxdStore; | |
UInt32 g_txdCollectionItemSize; | |
public static bool WasCheatStringJustEntered(string cheat) | |
{ | |
return Function.Call<bool>(Hash._0x557E43C447E700A8, Game.GenerateHash(cheat)); | |
} | |
unsafe void OnTick(object sender, EventArgs e) | |
{ | |
if (WasCheatStringJustEntered("dict")) | |
{ | |
int attempts = 0; | |
string dict = Game.GetUserInput(60); | |
Function.Call(Hash.REQUEST_STREAMED_TEXTURE_DICT, dict); | |
while (!Function.Call<bool>(Hash.HAS_STREAMED_TEXTURE_DICT_LOADED, dict)) | |
{ | |
Wait(100); | |
attempts++; | |
if (attempts > maxAttempts) | |
{ | |
UI.Notify("Couldn't load dictionary"); | |
return; | |
} | |
} | |
System.IO.File.AppendAllText(@"" + file, dict + ", " + (uint)Game.GenerateHash(dict) + "\n"); | |
var textures = GetTexturesFromTxd((uint)Game.GenerateHash(dict)); | |
foreach (var texture in textures) | |
{ | |
System.IO.File.AppendAllText(@"" + file, texture.name + "\n"); | |
System.IO.File.AppendAllText(@"" + file, ""+ texture.resX + "x" + texture.resY + "" + "\n\n"); | |
} | |
System.IO.File.AppendAllText(@"" + file, "Logged " + textures.Count + " textures!\n"); | |
UI.Notify("Logged " + textures.Count + " textures!"); | |
} | |
} | |
// Thank you, Unknown Modder! | |
unsafe List<myTexture> GetTexturesFromTxd(uint txdHash) | |
{ | |
List<myTexture> vecTextures = new List<myTexture>(); | |
if (g_fwTxdStore != 0 && g_fwTxdStore != 7) | |
{ | |
UInt64 txds = *(UInt64*)(g_fwTxdStore + 0x70u); | |
if (txds != 0) | |
{ | |
UInt16 size = *(UInt16*)(g_fwTxdStore + 0x82u); | |
for (UInt16 i = (UInt16)(txdHash % (size - 1u)); i < size - 1; i++) | |
{ | |
uint hash = *(uint*)(txds + i * 8u); | |
//System.IO.File.AppendAllText(@"" + file, "it " + i + " " + hash + "\n"); | |
if (hash != txdHash) continue; | |
//System.IO.File.AppendAllText(@"" + file, "got em!\n"); | |
UInt16 index = *(UInt16*)(txds + i * 8u + 4u); | |
if (index == -1) break; | |
UInt64 pgDictionaryCollection = *(UInt64*)(g_fwTxdStore + 0x38); | |
if (pgDictionaryCollection != 0) | |
{ | |
pgDictionary* dictionary = *(pgDictionary**)(pgDictionaryCollection + index * g_txdCollectionItemSize); | |
if (dictionary != null) | |
{ | |
grcTexture** textures = (dictionary)->textures; | |
if (textures != null) | |
{ | |
UInt16 count = dictionary->textureCount; | |
for (UInt16 j = 0; j < count; j++) | |
{ | |
if (textures[j] == null) continue; | |
//string name = MarshalUnsafeCStringToString((IntPtr)textures[j]->name, Encoding.Default); | |
string name = Marshal.PtrToStringAnsi((IntPtr)(byte*)textures[j]->name); | |
UInt16 resX = textures[j]->resolutionX; | |
UInt16 resY = textures[j]->resolutionY; | |
vecTextures.Add(new myTexture(name, resX, resY)); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
return vecTextures; | |
} | |
public unsafe static byte* FindPattern(string pattern, string mask) | |
{ | |
ProcessModule module = Process.GetCurrentProcess().MainModule; | |
ulong address = (ulong)module.BaseAddress.ToInt64(); | |
ulong endAddress = address + (ulong)module.ModuleMemorySize; | |
for (; address < endAddress; address++) | |
{ | |
for (int i = 0; i < pattern.Length; i++) | |
{ | |
if (mask[i] != '?' && ((byte*)address)[i] != pattern[i]) | |
{ | |
break; | |
} | |
else if (i + 1 == pattern.Length) | |
{ | |
return (byte*)address; | |
} | |
} | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment