CodeWalker/CodeWalker.Core/GameFiles/FileTypes/Gxt2File.cs
2019-11-01 20:30:29 +11:00

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;
}
}
}