mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-08-20 08:59:21 +08:00
180 lines
4.6 KiB
C#
180 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace CodeWalker.GameFiles
|
|
{
|
|
[TypeConverter(typeof(ExpandableObjectConverter))] public class Gxt2File : PackedFile
|
|
{
|
|
public string Name { get; set; }
|
|
public RpfFileEntry FileEntry { get; set; }
|
|
public uint EntryCount { get; set; }
|
|
public Gxt2Entry[] TextEntries { get; set; }
|
|
//public Dictionary<uint, string> Dict { get; set; }
|
|
|
|
|
|
public void Load(byte[] data, RpfFileEntry entry)
|
|
{
|
|
Name = entry.Name;
|
|
FileEntry = entry;
|
|
//Dict = new Dictionary<uint, string>();
|
|
|
|
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
|
{
|
|
uint gxt2 = br.ReadUInt32(); //"GXT2" - 1196971058
|
|
if (gxt2 != 1196971058)
|
|
{ return; }
|
|
|
|
EntryCount = br.ReadUInt32();
|
|
TextEntries = new Gxt2Entry[EntryCount];
|
|
for (uint i = 0; i < EntryCount; i++)
|
|
{
|
|
var e = new Gxt2Entry();
|
|
e.Hash = br.ReadUInt32();
|
|
e.Offset = br.ReadUInt32();
|
|
TextEntries[i] = e;
|
|
}
|
|
|
|
gxt2 = br.ReadUInt32(); //another "GXT2"
|
|
if (gxt2 != 1196971058)
|
|
{ return; }
|
|
|
|
uint endpos = br.ReadUInt32();
|
|
|
|
List<byte> buf = new List<byte>();
|
|
|
|
for (uint i = 0; i < EntryCount; i++)
|
|
{
|
|
var e = TextEntries[i];
|
|
br.BaseStream.Position = e.Offset;
|
|
|
|
buf.Clear();
|
|
byte b = br.ReadByte();
|
|
while ((b != 0) && (br.BaseStream.Position<endpos))
|
|
{
|
|
buf.Add(b);
|
|
b = br.ReadByte();
|
|
}
|
|
e.Text = Encoding.UTF8.GetString(buf.ToArray());
|
|
|
|
//Dict[e.Hash] = e.Text;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
[TypeConverter(typeof(ExpandableObjectConverter))] public class Gxt2Entry
|
|
{
|
|
public uint Hash { get; set; }
|
|
public uint Offset { get; set; }
|
|
public string Text { get; set; }
|
|
|
|
public override string ToString()
|
|
{
|
|
return Convert.ToString(Hash, 16).ToUpper().PadLeft(8, '0') + ": " + Text;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static class GlobalText
|
|
{
|
|
public static Dictionary<uint, string> Index = new Dictionary<uint, string>();
|
|
private static object syncRoot = new object();
|
|
|
|
public static volatile bool FullIndexBuilt = false;
|
|
|
|
public static void Clear()
|
|
{
|
|
lock (syncRoot)
|
|
{
|
|
Index.Clear();
|
|
}
|
|
}
|
|
|
|
public static bool Ensure(string str)
|
|
{
|
|
uint hash = JenkHash.GenHash(str);
|
|
if (hash == 0) return true;
|
|
lock (syncRoot)
|
|
{
|
|
if (!Index.ContainsKey(hash))
|
|
{
|
|
Index.Add(hash, str);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static bool Ensure(string str, uint hash)
|
|
{
|
|
if (hash == 0) return true;
|
|
lock (syncRoot)
|
|
{
|
|
if (!Index.ContainsKey(hash))
|
|
{
|
|
Index.Add(hash, str);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static string GetString(uint hash)
|
|
{
|
|
string res;
|
|
lock (syncRoot)
|
|
{
|
|
if (!Index.TryGetValue(hash, out res))
|
|
{
|
|
res = hash.ToString();
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
public static string TryGetString(uint hash)
|
|
{
|
|
string res;
|
|
lock (syncRoot)
|
|
{
|
|
if (!Index.TryGetValue(hash, out res))
|
|
{
|
|
res = string.Empty;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public static uint TryFindHash(string text)
|
|
{
|
|
lock (syncRoot)
|
|
{
|
|
foreach (var kvp in Index)
|
|
{
|
|
if (kvp.Value == text)
|
|
{
|
|
return kvp.Key;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|