Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LUAList Editor #22

Merged
merged 11 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions BundleManager.sln
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{DA4D9C10-E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorldCollisionHandler", "WorldCollisionHandler\WorldCollisionHandler.csproj", "{754DDA1C-8F2F-4F6C-8BC0-D6553A9A7451}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaList", "LuaList\LuaList.csproj", "{D1395FDE-6A64-4D9F-9DCA-60825BD0A43C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -133,6 +135,10 @@ Global
{754DDA1C-8F2F-4F6C-8BC0-D6553A9A7451}.Debug|Any CPU.Build.0 = Debug|Any CPU
{754DDA1C-8F2F-4F6C-8BC0-D6553A9A7451}.Release|Any CPU.ActiveCfg = Release|Any CPU
{754DDA1C-8F2F-4F6C-8BC0-D6553A9A7451}.Release|Any CPU.Build.0 = Release|Any CPU
{D1395FDE-6A64-4D9F-9DCA-60825BD0A43C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1395FDE-6A64-4D9F-9DCA-60825BD0A43C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1395FDE-6A64-4D9F-9DCA-60825BD0A43C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1395FDE-6A64-4D9F-9DCA-60825BD0A43C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -156,6 +162,7 @@ Global
{4FC1C1EE-618A-4B65-A103-A51568A01629} = {3BA7CE56-4E22-418F-9D13-F2189413D30B}
{7743D330-6A1A-496C-872B-E36C9EB38CE7} = {60F98E02-807F-4EDC-8747-147C365606B1}
{754DDA1C-8F2F-4F6C-8BC0-D6553A9A7451} = {60F98E02-807F-4EDC-8747-147C365606B1}
{D1395FDE-6A64-4D9F-9DCA-60825BD0A43C} = {60F98E02-807F-4EDC-8747-147C365606B1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {566130B7-31A2-4407-A2E1-C22E60C85C2C}
Expand Down
26 changes: 26 additions & 0 deletions BundleUtilities/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ public void Log(string logMessage, TextWriter txtWriter)
}
}
}

public static class Util
{
// reverse byte order (64-bit)
public static UInt64 ReverseBytes(UInt64 value)
{
return (value & 0x00000000000000FFUL) << 56 | (value & 0x000000000000FF00UL) << 40 |
(value & 0x0000000000FF0000UL) << 24 | (value & 0x00000000FF000000UL) << 8 |
(value & 0x000000FF00000000UL) >> 8 | (value & 0x0000FF0000000000UL) >> 24 |
(value & 0x00FF000000000000UL) >> 40 | (value & 0xFF00000000000000UL) >> 56;
}
}
public static class Utilities
{
public static ulong calcLookup8(string text)
Expand All @@ -56,6 +68,20 @@ public static ulong calcLookup8(string text)
return hashValue;
}

public static EncryptedString ReadEncryptedString(this BinaryReader self)
{
ulong value = self.ReadUInt64();
EncryptedString id = new EncryptedString(value);
return id;
}

public static void WriteEncryptedString(this BinaryWriter self, EncryptedString id, bool xbox = false)
{
ulong value = id.Encrypted;
if (xbox)
value = Util.ReverseBytes(value);
self.Write(value);
}

public static bool IsValidPath(string path)
{
Expand Down
64 changes: 64 additions & 0 deletions LuaList/EncryptedStringConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.ComponentModel;

namespace LuaList
{
// Included...
// [1] Define TypeConverter class for hex.
// [2] use it when defining a member of a data class using attribute TypeConverter.
// [3] Connect the data class to a PropertyGrid.


// [1] define UInt32HexTypeConverter is-a TypeConverter
public class EncryptedStringConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
else
{
return base.CanConvertFrom(context, sourceType);
}
}

public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
else
{
return base.CanConvertTo(context, destinationType);
}
}

public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value.GetType() == typeof(BundleUtilities.EncryptedString))
{
return ((BundleUtilities.EncryptedString)value).Value;
}
else
{
return base.ConvertTo(context, culture, value, destinationType);
}
}

public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value.GetType() == typeof(string))
{
string input = (string)value;
return new BundleUtilities.EncryptedString(input);
}
else
{
return base.ConvertFrom(context, culture, value);
}
}
}
}
209 changes: 209 additions & 0 deletions LuaList/LuaList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
using BundleFormat;
using PluginAPI;
using BundleUtilities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System;

namespace LuaList
{
public class LuaList : IEntryData
{
public int version { get; set; }

[TypeConverter(typeof(EncryptedStringConverter))]
public EncryptedString CgsId { get; set; }

public int dataLength;
public string listTitle { get; set; }
public List<LuaListEntry> entries { get; set; }
public List<string> types { get; set; }
public List<string> variables { get; set; }
public IEntryEditor GetEditor(BundleEntry entry)
{
LuaListEditor luaListEditor = new LuaListEditor();
luaListEditor.LuaList = this;
luaListEditor.EditEvent += () =>
{
Write(entry);
};
return luaListEditor;
}

public EntryType GetEntryType(BundleEntry entry)
{
return EntryType.LUAList;
}

public int getLengthOfHeader()
{
List<byte[]> bytes = new List<byte[]>();
bytes.Add(BitConverter.GetBytes(version));
bytes.Add(new byte[4]);
bytes.Add(BitConverter.GetBytes(CgsId.Encrypted));
bytes.Add(BitConverter.GetBytes(192));
bytes.Add(BitConverter.GetBytes(1231));
bytes.Add(BitConverter.GetBytes(312312));
bytes.Add(BitConverter.GetBytes(entries.Count));
bytes.Add(BitConverter.GetBytes(dataLength));
bytes.Add(Encoding.ASCII.GetBytes((listTitle.PadRight(128).Substring(0, 128).ToCharArray())));
bytes.Add(new byte[] { (byte)types.Count() });
bytes.Add(new byte[] { (byte)variables.Count() });
bytes.Add(new byte[26]);
return bytes.SelectMany(i => i).Count();
}

public int getLengthOfTypes()
{
if (types.Count == 0)
{
return 0;
}
return (types.Count * 32) + 32; // Pointer Array of 32 bytes
}

public int getLengthOfVariables()
{
if (variables.Count == 0)
{
return 0;
}
return (variables.Count * 32) + 32; // Pointer Array of 32 bytes
}

public int getLengthOfEntries()
{
return entries.Sum(i => i.getDataSize());
}

public bool Read(BundleEntry entry, ILoader loader = null)
{
MemoryStream ms = entry.MakeStream();
BinaryReader2 br = new BinaryReader2(ms);

version = br.ReadInt32(); //0x0 0x4 int32_t Version number 1
br.ReadBytes(4); // 0x4 0x4 padding
CgsId = br.ReadEncryptedString(); //0x8 0x8 CgsID List ID Encoded
var entriesPointer = br.ReadInt32(); //0x10 0x4 Unk0* Script list Unk0 format
var typePointer = br.ReadInt32(); //0x14 0x4 char[32] * * Types
var variablePointer = br.ReadInt32(); //0x18 0x4 char[32] * * Variables
var numScripts = br.ReadInt32(); //0x1C 0x4 uint32_t Num scripts
var dataLength = br.ReadInt32(); //0x20 0x4 uint32_t Data length Not including padding to end
listTitle = br.ReadLenString(128); //0x24 0x80 char[128] List title
var numTypes = br.ReadByte(); //0xA4 0x1 uint8_t Num types
var numVariables = br.ReadByte(); //0xA5 0x1 uint8_t Num variables
br.ReadBytes(26); // padding

entries = new List<LuaListEntry>();
for (int i = 0; i < numScripts; i++)
{
LuaListEntry luaentry = new LuaListEntry();
luaentry.Read(loader, br);
entries.Add(luaentry);
}

br.BaseStream.Position = typePointer;
long currentAddress = br.BaseStream.Position;
types = new List<string>();
for (int i = 0; i < numTypes; i++)
{
int pointer = br.ReadInt32();
currentAddress = br.BaseStream.Position;
br.BaseStream.Position = pointer;
types.Add(br.ReadLenString(32));
br.BaseStream.Position = currentAddress;
}
br.BaseStream.Position = variablePointer;
variables = new List<string>();
for (int i = 0; i < numVariables; i++)
{
int pointer = br.ReadInt32();
currentAddress = br.BaseStream.Position;
br.BaseStream.Position = pointer;
if (dataLength - pointer > 31)
{
variables.Add(br.ReadLenString(32));
}
else
{
Console.WriteLine(dataLength - pointer);
variables.Add(br.ReadLenString(dataLength - pointer));
}
br.BaseStream.Position = currentAddress;
}
Console.WriteLine(getLengthOfHeader() + getLengthOfEntries() + getLengthOfTypes() + getLengthOfVariables());
Console.WriteLine(dataLength);
br.Close();
ms.Close();

return true;
}

public bool Write(BundleEntry entry)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(version);
bw.WriteUniquePadding(4);
bw.WriteEncryptedString(CgsId);
bw.Write(getLengthOfHeader());
bw.Write(getLengthOfHeader() + getLengthOfEntries());
bw.Write(getLengthOfHeader() + getLengthOfEntries() + getLengthOfTypes());
bw.Write(entries.Count);
bw.Write(getLengthOfHeader() + getLengthOfEntries() + getLengthOfTypes() + getLengthOfVariables()); //Calculate this
bw.Write(listTitle.PadRight(128, '\0').Substring(0, 128).ToCharArray());
bw.Write((byte)types.Count);
bw.Write((byte)variables.Count);
bw.WriteUniquePadding(26);
foreach (LuaListEntry luaentry in entries)
{
luaentry.Write(bw);
}
var counter = 0;
var pointerAddress = bw.BaseStream.Position;
// Skip pointer address for now
bw.BaseStream.Position = bw.BaseStream.Position + 32;
foreach (string type in types)
{
// Save pointer to text
int pointer = (int)bw.BaseStream.Position;
bw.Write(type.PadRight(32, '\0').Substring(0, 32).ToCharArray());
long currentAddress = bw.BaseStream.Position;
// Go to pointer array
bw.BaseStream.Position = pointerAddress + (4 * counter);
bw.Write(pointer);
counter++;
// Go back to old position
bw.BaseStream.Position = currentAddress;
}
counter = 0;
pointerAddress = bw.BaseStream.Position;
// Skip pointer address for now
bw.BaseStream.Position = bw.BaseStream.Position + 32;
foreach (string variable in variables)
{
// Save pointer to text
int pointer = (int)bw.BaseStream.Position;
bw.Write(variable.PadRight(32, '\0').Substring(0, 32).ToCharArray());
long currentAddress = bw.BaseStream.Position;
// Go to pointer array
bw.BaseStream.Position = pointerAddress + (4 * counter);
bw.Write(pointer);
counter++;
// Go back to old position
bw.BaseStream.Position = currentAddress;
}
bw.Flush();
byte[] data = ms.ToArray();
bw.Close();
ms.Close();

entry.EntryBlocks[0].Data = data;
entry.Dirty = true;
return true;
}
}
}
Loading