Skip to content

Instantly share code, notes, and snippets.

@ikt32
Created January 30, 2018 02:25
Show Gist options
  • Save ikt32/4cadaab095bfcc68da8c390a3ab6085a to your computer and use it in GitHub Desktop.
Save ikt32/4cadaab095bfcc68da8c390a3ab6085a to your computer and use it in GitHub Desktop.
Texture list Test
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