Initial commit: Complete open-source Decal rebuild

All 5 phases of the open-source Decal rebuild:

Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil)
Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs
  - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters
  - Decal.Core, DecalControls, DecalRender, D3DService
Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL
Phase 4: DenAgent WinForms tray application
Phase 5: WiX installer and build script

25 C# projects building with 0 errors.
Native C++ projects require VS 2022 + Windows SDK (x86).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erik 2026-02-08 18:27:56 +01:00
commit d1442e3747
1382 changed files with 170725 additions and 0 deletions

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Decal.FileService</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Decal.Adapter\Decal.Adapter.csproj" />
<ProjectReference Include="..\Decal.Interop.Dat\Decal.Interop.Dat.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,46 @@
namespace Decal.Filters;
public class Attrib : IIdNameTableEntry
{
private int mID;
private string mName;
private int mIconId;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
public int IconId
{
get
{
return mIconId;
}
internal set
{
mIconId = value;
}
}
internal Attrib(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,35 @@
namespace Decal.Filters;
public sealed class AttributeTable : IdNameTable<Attrib>
{
internal AttributeTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 620756998)
{
return false;
}
Index++;
int num = Get.Byte(Data, ref Index);
InitializeTable(num);
for (int i = 0; i < num; i++)
{
Attrib attrib = new Attrib(Get.DWord(Data, ref Index));
attrib.IconId = Get.DWord(Data, ref Index);
Add(attrib);
}
Index++;
num = Get.Byte(Data, ref Index);
for (int j = 0; j < num; j++)
{
int id = Get.DWord(Data, ref Index);
GetById(id).Name = Get.PString(Data, ref Index);
}
return true;
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Filters;
public sealed class AttributeXPTable : RawTable<long>
{
internal AttributeXPTable(int Length)
{
InitializeTable(Length);
}
internal override bool LoadFrom(byte[] Data)
{
return true;
}
internal new void Add(long Entry)
{
base.Add(Entry);
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Filters;
public sealed class CharacterSkillCreditsTable : RawTable<byte>
{
internal CharacterSkillCreditsTable(int Length)
{
InitializeTable(Length);
}
internal override bool LoadFrom(byte[] Data)
{
return true;
}
internal new void Add(byte Entry)
{
base.Add(Entry);
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Filters;
public sealed class CharacterXPTable : RawTable<long>
{
internal CharacterXPTable(int Length)
{
InitializeTable(Length);
}
internal override bool LoadFrom(byte[] Data)
{
return true;
}
internal new void Add(long Entry)
{
base.Add(Entry);
}
}

View file

@ -0,0 +1,130 @@
namespace Decal.Filters;
public class Component : IIdNameTableEntry
{
private int mID;
private string mName;
private ComponentType mType;
private int mIconId;
private int mSort;
private int mGestureID;
private float mGestureSpeed;
private string mWord;
private float mBurnRate;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
public ComponentType Type
{
get
{
return mType;
}
internal set
{
mType = value;
}
}
public int IconId
{
get
{
return mIconId;
}
internal set
{
mIconId = value;
}
}
public int SortKey
{
get
{
return mSort;
}
internal set
{
mSort = value;
}
}
public int GestureId
{
get
{
return mGestureID;
}
internal set
{
mGestureID = value;
}
}
public float GestureSpeed
{
get
{
return mGestureSpeed;
}
internal set
{
mGestureSpeed = value;
}
}
public string Word
{
get
{
return mWord;
}
internal set
{
mWord = value;
}
}
public float BurnRate
{
get
{
return mBurnRate;
}
internal set
{
mBurnRate = value;
}
}
internal Component(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,35 @@
namespace Decal.Filters;
public sealed class ComponentTable : IdNameTable<Component>
{
internal ComponentTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 234881039)
{
return false;
}
int num = Get.Word(Data, ref Index);
InitializeTable(num);
Index += 2;
for (int i = 0; i < num; i++)
{
Component component = new Component(Get.DWord(Data, ref Index));
component.Name = Get.EncString(Data, ref Index);
component.Type = ComponentType.GetById(Get.DWord(Data, ref Index));
component.IconId = Get.DWord(Data, ref Index);
component.SortKey = Get.DWord(Data, ref Index);
component.GestureId = Get.DWord(Data, ref Index);
component.GestureSpeed = Get.Float(Data, ref Index);
component.Word = Get.EncString(Data, ref Index);
component.BurnRate = Get.Float(Data, ref Index);
Add(component);
}
return true;
}
}

View file

@ -0,0 +1,60 @@
using System.Globalization;
namespace Decal.Filters;
public class ComponentType
{
private static ComponentType[] sTypes = new ComponentType[7]
{
new ComponentType(0, "Scarab"),
new ComponentType(1, "Herb"),
new ComponentType(2, "Powder"),
new ComponentType(3, "Potion"),
new ComponentType(4, "Talisman"),
new ComponentType(5, "Taper"),
new ComponentType(6, "Pea")
};
private int mId;
private string mName;
public int Id => mId;
public string Name => mName;
public static ComponentType GetById(int id)
{
for (int i = 0; i < sTypes.Length; i++)
{
if (sTypes[i].Id == id)
{
return sTypes[i];
}
}
return null;
}
public static ComponentType GetByName(string name)
{
for (int i = 0; i < sTypes.Length; i++)
{
if (string.Compare(sTypes[i].Name, name, ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
return sTypes[i];
}
}
return null;
}
private ComponentType(int id, string Name)
{
mId = id;
mName = Name;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,179 @@
using System;
using Decal.Adapter;
using Decal.Interop.Dat;
namespace Decal.Filters;
public sealed class FileService : FilterBase
{
private AttributeTable mAttributeTable;
private VitalTable mVitalTable;
private VitalFormulaTable mVitalFormulaTable;
private SkillTable mSkillTable;
private ComponentTable mComponentTable;
private SpellTable mSpellTable;
private LevelTables mLevelTables;
private GenderTable mGenderTable;
private HeritageTable mHeritageTable;
private SpeciesTable mSpeciesTable;
private MaterialTable mMaterialTable;
public override string ReferenceName => "Decal.FileService";
public AttributeTable AttributeTable => mAttributeTable;
public VitalTable VitalTable => mVitalTable;
public VitalFormulaTable VitalFormulaTable => mVitalFormulaTable;
public SkillTable SkillTable => mSkillTable;
public ComponentTable ComponentTable => mComponentTable;
public SpellTable SpellTable => mSpellTable;
public LevelTables LevelTables => mLevelTables;
public GenderTable GenderTable => mGenderTable;
public HeritageTable HeritageTable => mHeritageTable;
public SpeciesTable SpeciesTable => mSpeciesTable;
public MaterialTable MaterialTable => mMaterialTable;
public event EventHandler<UpdateEventArgs> OnUpdatePortal;
public event EventHandler<UpdateEventArgs> OnUpdateCell;
protected override void Startup()
{
base.ServerDispatch += OnServerDispatch;
mAttributeTable = new AttributeTable(GetPortalFile(620756998));
mVitalTable = new VitalTable(GetPortalFile(620756999));
mVitalFormulaTable = new VitalFormulaTable(GetPortalFile(234881027));
mSkillTable = new SkillTable(GetPortalFile(234881028));
mComponentTable = new ComponentTable(GetPortalFile(234881039));
mSpellTable = new SpellTable(GetPortalFile(234881038));
mLevelTables = new LevelTables(GetPortalFile(234881048));
mGenderTable = new GenderTable(GetPortalFile(570425354));
mHeritageTable = new HeritageTable(GetPortalFile(570425355));
mSpeciesTable = new SpeciesTable(GetPortalFile(570425358));
mMaterialTable = new MaterialTable(GetPortalFile(654311424));
}
protected override void Shutdown()
{
base.ServerDispatch -= OnServerDispatch;
mAttributeTable = null;
mVitalTable = null;
mVitalFormulaTable = null;
mSkillTable = null;
mComponentTable = null;
mSpellTable = null;
mLevelTables = null;
mGenderTable = null;
mHeritageTable = null;
mSpeciesTable = null;
mMaterialTable = null;
}
private void OnServerDispatch(object sender, NetworkMessageEventArgs e)
{
Message message = e.Message;
if (message.Type != 63458)
{
return;
}
int num = message.Value<int>("type");
if (num == 1 || num == 2)
{
int num2 = message.Value<int>("resource");
byte[] data = message.Value<byte>("compression") switch
{
0 => message.RawValue("data"),
1 => zlib.Inflate(message.RawValue("data"), message.Value<int>("fileSize")),
_ => null,
};
switch (num2)
{
case 620756998:
mAttributeTable.UpdateFrom(data);
break;
case 620756999:
mVitalTable.UpdateFrom(data);
break;
case 234881027:
mVitalFormulaTable.UpdateFrom(data);
break;
case 234881028:
mSkillTable.UpdateFrom(data);
break;
case 234881039:
mComponentTable.UpdateFrom(data);
break;
case 234881038:
mSpellTable.UpdateFrom(data);
break;
case 234881048:
mLevelTables.UpdateFrom(data);
break;
case 570425354:
mGenderTable.UpdateFrom(data);
break;
case 570425355:
mHeritageTable.UpdateFrom(data);
break;
case 570425358:
mSpeciesTable.UpdateFrom(data);
break;
case 654311424:
mMaterialTable.UpdateFrom(data);
break;
}
switch (num)
{
case 1:
this.OnUpdatePortal(this, new UpdateEventArgs(num2));
break;
case 2:
this.OnUpdateCell(this, new UpdateEventArgs(num2));
break;
}
}
}
public byte[] GetPortalFile(int fileId)
{
return GetFile("services\\DecalDat.DatService\\portal\\" + fileId.ToString("X8"));
}
public byte[] GetCellFile(int fileId)
{
return GetFile("services\\DecalDat.DatService\\cell\\" + fileId.ToString("X8"));
}
private byte[] GetFile(string decalObject)
{
IDatStream datStream = (IDatStream)base.Host.Decal.GetObject(decalObject, "{B27D3F72-2640-432F-BAE4-175E1AA0CA39}");
if (datStream == null)
{
return null;
}
int size = datStream.Size;
byte[] array = (byte[])Array.CreateInstance(typeof(byte), size);
datStream.Restart();
datStream.ReadBinary(size, ref array[0]);
return array;
}
}

View file

@ -0,0 +1,32 @@
namespace Decal.Filters;
public class Gender : IIdNameTableEntry
{
private int mID;
private string mName;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
internal Gender(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,28 @@
namespace Decal.Filters;
public sealed class GenderTable : IdNameTable<Gender>
{
internal GenderTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 570425354)
{
return false;
}
Index += 5;
int num = Get.Byte(Data, ref Index);
InitializeTable(num);
for (int i = 0; i < num; i++)
{
Gender gender = new Gender(Get.DWord(Data, ref Index));
gender.Name = Get.PString(Data, ref Index);
Add(gender);
}
return true;
}
}

View file

@ -0,0 +1,102 @@
using System;
using System.Text;
namespace Decal.Filters;
internal static class Get
{
internal static byte Byte(byte[] Data, ref int Index)
{
return Data[Index++];
}
internal static int Word(byte[] Data, ref int Index)
{
ushort result = BitConverter.ToUInt16(Data, Index);
Index += 2;
return result;
}
internal static int DWord(byte[] Data, ref int Index)
{
int result = BitConverter.ToInt32(Data, Index);
Index += 4;
return result;
}
internal static long QWord(byte[] Data, ref int Index)
{
long result = BitConverter.ToInt64(Data, Index);
Index += 8;
return result;
}
internal static float Float(byte[] Data, ref int Index)
{
float result = BitConverter.ToSingle(Data, Index);
Index += 4;
return result;
}
internal static double Double(byte[] Data, ref int Index)
{
double result = BitConverter.ToDouble(Data, Index);
Index += 8;
return result;
}
internal static string String(byte[] Data, ref int Index)
{
int num = Word(Data, ref Index);
if (num == 65535)
{
num = DWord(Data, ref Index);
}
StringBuilder stringBuilder = new StringBuilder(num);
Encoding encoding = Encoding.GetEncoding(1252);
byte[] array = (byte[])Array.CreateInstance(typeof(byte), 1);
while (num-- > 0)
{
array[0] = Byte(Data, ref Index);
stringBuilder.Append(encoding.GetChars(array));
}
Index += 3;
Index &= -4;
return stringBuilder.ToString();
}
internal static string EncString(byte[] Data, ref int Index)
{
int num = Word(Data, ref Index);
if (num == 65535)
{
num = DWord(Data, ref Index);
}
StringBuilder stringBuilder = new StringBuilder(num);
Encoding encoding = Encoding.GetEncoding(1252);
byte[] array = (byte[])Array.CreateInstance(typeof(byte), 1);
while (num-- > 0)
{
byte b = Byte(Data, ref Index);
array[0] = (byte)((b >> 4) | (b << 4));
stringBuilder.Append(encoding.GetChars(array));
}
Index += 3;
Index &= -4;
return stringBuilder.ToString();
}
internal static string PString(byte[] Data, ref int Index)
{
int capacity = Byte(Data, ref Index);
StringBuilder stringBuilder = new StringBuilder(capacity);
Encoding encoding = Encoding.GetEncoding(1252);
byte[] array = (byte[])Array.CreateInstance(typeof(byte), 1);
while (capacity-- > 0)
{
array[0] = Byte(Data, ref Index);
stringBuilder.Append(encoding.GetChars(array));
}
return stringBuilder.ToString();
}
}

View file

@ -0,0 +1,32 @@
namespace Decal.Filters;
public class Heritage : IIdNameTableEntry
{
private int mID;
private string mName;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
internal Heritage(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,28 @@
namespace Decal.Filters;
public sealed class HeritageTable : IdNameTable<Heritage>
{
internal HeritageTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 570425355)
{
return false;
}
Index += 5;
int num = Get.Byte(Data, ref Index);
InitializeTable(num);
for (int i = 0; i < num; i++)
{
Heritage heritage = new Heritage(Get.DWord(Data, ref Index));
heritage.Name = Get.PString(Data, ref Index);
Add(heritage);
}
return true;
}
}

View file

@ -0,0 +1,8 @@
namespace Decal.Filters;
public interface IIdNameTableEntry
{
int Id { get; }
string Name { get; }
}

View file

@ -0,0 +1,104 @@
using System;
namespace Decal.Filters;
public abstract class IdNameTable<EntryType> where EntryType : IIdNameTableEntry
{
private int mCount;
private EntryType[] mTable;
public EntryType this[int index]
{
get
{
if (index >= 0 && index < mCount)
{
return mTable[index];
}
return default(EntryType);
}
}
public int Length => mCount;
public event EventHandler Update;
internal abstract bool LoadFrom(byte[] data);
internal bool UpdateFrom(byte[] data)
{
bool num = LoadFrom(data);
if (num)
{
this.Update(this, null);
}
return num;
}
protected void InitializeTable(int n)
{
mCount = 0;
mTable = (EntryType[])Array.CreateInstance(typeof(EntryType), n);
}
protected void Add(EntryType entry)
{
if (mCount < mTable.Length)
{
int num = mCount++;
while (num > 0 && mTable[num - 1].Id > entry.Id)
{
mTable[num] = mTable[num - 1];
num--;
}
mTable[num] = entry;
}
}
public int IndexFromId(int id)
{
int num = 0;
int num2 = mCount - 1;
while (num <= num2)
{
int num3 = (num2 - num >> 1) + num;
int id2 = mTable[num3].Id;
if (id == id2)
{
return num3;
}
if (id < id2)
{
num2 = num3 - 1;
}
else
{
num = num3 + 1;
}
}
return -1;
}
public int IndexFromName(string name)
{
for (int i = 0; i < mCount; i++)
{
if (string.Compare(mTable[i].Name, name, ignoreCase: true) == 0)
{
return i;
}
}
return -1;
}
public EntryType GetById(int id)
{
return this[IndexFromId(id)];
}
public EntryType GetByName(string name)
{
return this[IndexFromName(name)];
}
}

View file

@ -0,0 +1,78 @@
namespace Decal.Filters;
public sealed class LevelTables : RawTable<object>
{
private AttributeXPTable mAttrXP;
private VitalXPTable mVitalXP;
private TrainedSkillXPTable mTrainXP;
private SpecializedSkillXPTable mSpecXP;
private CharacterXPTable mLevelXP;
private CharacterSkillCreditsTable mSkillCredits;
public AttributeXPTable AttributeXP => mAttrXP;
public VitalXPTable VitalXP => mVitalXP;
public TrainedSkillXPTable TrainedSkillXP => mTrainXP;
public SpecializedSkillXPTable SpecializedSkillXP => mSpecXP;
public CharacterXPTable CharacterXP => mLevelXP;
public CharacterSkillCreditsTable CharacterSkillCredits => mSkillCredits;
internal LevelTables(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 234881048)
{
return false;
}
int num = Get.DWord(Data, ref Index) + 1;
int num2 = Get.DWord(Data, ref Index) + 1;
int num3 = Get.DWord(Data, ref Index) + 1;
int num4 = Get.DWord(Data, ref Index) + 1;
int num5 = Get.DWord(Data, ref Index) + 1;
mAttrXP = new AttributeXPTable(num);
mVitalXP = new VitalXPTable(num2);
mTrainXP = new TrainedSkillXPTable(num3);
mSpecXP = new SpecializedSkillXPTable(num4);
mLevelXP = new CharacterXPTable(num5);
mSkillCredits = new CharacterSkillCreditsTable(num5);
for (int i = 0; i < num; i++)
{
mAttrXP.Add(Get.DWord(Data, ref Index) & 0xFFFFFFFFu);
}
for (int j = 0; j < num2; j++)
{
mVitalXP.Add(Get.DWord(Data, ref Index) & 0xFFFFFFFFu);
}
for (int k = 0; k < num3; k++)
{
mTrainXP.Add(Get.DWord(Data, ref Index) & 0xFFFFFFFFu);
}
for (int l = 0; l < num4; l++)
{
mSpecXP.Add(Get.DWord(Data, ref Index) & 0xFFFFFFFFu);
}
for (int m = 0; m < num5; m++)
{
mLevelXP.Add(Get.QWord(Data, ref Index));
}
for (int n = 0; n < num5; n++)
{
mSkillCredits.Add(Get.Byte(Data, ref Index));
}
return true;
}
}

View file

@ -0,0 +1,46 @@
namespace Decal.Filters;
public class Material : IIdNameTableEntry
{
private int mID;
private string mName;
private int mUnk;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
public int Unknown
{
get
{
return mUnk;
}
internal set
{
mUnk = value;
}
}
internal Material(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,35 @@
namespace Decal.Filters;
public sealed class MaterialTable : IdNameTable<Material>
{
internal MaterialTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 654311424)
{
return false;
}
Index++;
int num = Get.Byte(Data, ref Index);
InitializeTable(num);
for (int i = 0; i < num; i++)
{
Material material = new Material(Get.DWord(Data, ref Index));
material.Unknown = Get.DWord(Data, ref Index);
Add(material);
}
Index++;
num = Get.Byte(Data, ref Index);
for (int j = 0; j < num; j++)
{
int id = Get.DWord(Data, ref Index);
GetById(id).Name = Get.PString(Data, ref Index).Replace('_', ' ');
}
return true;
}
}

View file

@ -0,0 +1,59 @@
using System;
namespace Decal.Filters;
public abstract class RawTable<EntryType>
{
private int mCount;
private EntryType[] mTable;
public EntryType this[int index]
{
get
{
if (index >= 0 && index < mCount)
{
return mTable[index];
}
return default(EntryType);
}
protected set
{
if (index >= 0 && index < mCount)
{
mTable[index] = value;
}
}
}
public int Length => mCount;
public event EventHandler Update;
internal abstract bool LoadFrom(byte[] Data);
internal bool UpdateFrom(byte[] Data)
{
bool num = LoadFrom(Data);
if (num)
{
this.Update(this, null);
}
return num;
}
protected void InitializeTable(int n)
{
mCount = 0;
mTable = (EntryType[])Array.CreateInstance(typeof(EntryType), n);
}
protected void Add(EntryType entry)
{
if (mCount < mTable.Length)
{
mTable[mCount++] = entry;
}
}
}

View file

@ -0,0 +1,256 @@
namespace Decal.Filters;
public class Skill : IIdNameTableEntry
{
private int mID;
private string mName;
private string mDesc;
private int mIconId;
private int mTrainCost;
private int mSpecCost;
private SkillType mType;
private int mUnk1;
private SkillState mUsability;
private int mUnk2;
private bool mAttr1Valid;
private bool mAttr2Valid;
private int mDivisor;
private int mAttr1ID;
private int mAttr2ID;
private double mTimerLimit;
private double mTimerStart;
private double mUnk3;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
public string Description
{
get
{
return mDesc;
}
internal set
{
mDesc = value;
}
}
public int IconId
{
get
{
return mIconId;
}
internal set
{
mIconId = value;
}
}
public int CreditsToTrain
{
get
{
return mTrainCost;
}
internal set
{
mTrainCost = value;
}
}
public int CreditsToSpecialize
{
get
{
return mSpecCost;
}
internal set
{
mSpecCost = value;
}
}
public SkillType Type
{
get
{
return mType;
}
internal set
{
mType = value;
}
}
public SkillState Usability
{
get
{
return mUsability;
}
internal set
{
mUsability = value;
}
}
public bool IsAttribute1Valid
{
get
{
return mAttr1Valid;
}
internal set
{
mAttr1Valid = value;
}
}
public bool IsAttribute2Valid
{
get
{
return mAttr2Valid;
}
internal set
{
mAttr2Valid = value;
}
}
public int Attribute1Id
{
get
{
return mAttr1ID;
}
internal set
{
mAttr1ID = value;
}
}
public int Attribute2Id
{
get
{
return mAttr2ID;
}
internal set
{
mAttr2ID = value;
}
}
public int AttributeDivisor
{
get
{
return mDivisor;
}
internal set
{
mDivisor = value;
}
}
public double XPTimerStart
{
get
{
return mTimerStart;
}
internal set
{
mTimerStart = value;
}
}
public double XPTimerLimit
{
get
{
return mTimerLimit;
}
internal set
{
mTimerLimit = value;
}
}
public int Unknown1
{
get
{
return mUnk1;
}
internal set
{
mUnk1 = value;
}
}
public int Unknown2
{
get
{
return mUnk2;
}
internal set
{
mUnk2 = value;
}
}
public double Unknown3
{
get
{
return mUnk3;
}
internal set
{
mUnk3 = value;
}
}
internal Skill(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,56 @@
using System.Globalization;
namespace Decal.Filters;
public class SkillState
{
private static SkillState[] sStates = new SkillState[3]
{
new SkillState(1, "Untrained"),
new SkillState(2, "Trained"),
new SkillState(3, "Specialized")
};
private int mId;
private string mName;
public int Id => mId;
public string Name => mName;
public static SkillState GetById(int id)
{
for (int i = 0; i < sStates.Length; i++)
{
if (sStates[i].Id == id)
{
return sStates[i];
}
}
return null;
}
public static SkillState GetByName(string name)
{
for (int i = 0; i < sStates.Length; i++)
{
if (string.Compare(sStates[i].Name, name, ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
return sStates[i];
}
}
return null;
}
private SkillState(int id, string name)
{
mId = id;
mName = name;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,44 @@
namespace Decal.Filters;
public sealed class SkillTable : IdNameTable<Skill>
{
internal SkillTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 234881028)
{
return false;
}
int num = Get.Word(Data, ref Index);
InitializeTable(num);
Index += 2;
for (int i = 0; i < num; i++)
{
Skill skill = new Skill(Get.DWord(Data, ref Index));
skill.Description = Get.String(Data, ref Index);
skill.Name = Get.String(Data, ref Index);
skill.IconId = Get.DWord(Data, ref Index);
skill.CreditsToTrain = Get.DWord(Data, ref Index);
skill.CreditsToSpecialize = Get.DWord(Data, ref Index);
skill.Type = SkillType.GetById(Get.DWord(Data, ref Index));
skill.Unknown1 = Get.DWord(Data, ref Index);
skill.Usability = SkillState.GetById(Get.DWord(Data, ref Index));
skill.Unknown2 = Get.DWord(Data, ref Index);
skill.IsAttribute1Valid = Get.DWord(Data, ref Index) == 1;
skill.IsAttribute2Valid = Get.DWord(Data, ref Index) == 1;
skill.AttributeDivisor = Get.DWord(Data, ref Index);
skill.Attribute1Id = Get.DWord(Data, ref Index);
skill.Attribute2Id = Get.DWord(Data, ref Index);
skill.XPTimerLimit = Get.Double(Data, ref Index);
skill.XPTimerStart = Get.Double(Data, ref Index);
skill.Unknown3 = Get.Double(Data, ref Index);
Add(skill);
}
return true;
}
}

View file

@ -0,0 +1,56 @@
using System.Globalization;
namespace Decal.Filters;
public class SkillType
{
private static SkillType[] sTypes = new SkillType[3]
{
new SkillType(1, "Combat"),
new SkillType(2, "Other"),
new SkillType(3, "Magic")
};
private int mId;
private string mName;
public int Id => mId;
public string Name => mName;
public static SkillType GetById(int id)
{
for (int i = 0; i < sTypes.Length; i++)
{
if (sTypes[i].Id == id)
{
return sTypes[i];
}
}
return null;
}
public static SkillType GetByName(string name)
{
for (int i = 0; i < sTypes.Length; i++)
{
if (string.Compare(sTypes[i].Name, name, ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
return sTypes[i];
}
}
return null;
}
private SkillType(int id, string name)
{
mId = id;
mName = name;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Filters;
public sealed class SpecializedSkillXPTable : RawTable<long>
{
internal SpecializedSkillXPTable(int Length)
{
InitializeTable(Length);
}
internal override bool LoadFrom(byte[] Data)
{
return true;
}
internal new void Add(long Entry)
{
base.Add(Entry);
}
}

View file

@ -0,0 +1,32 @@
namespace Decal.Filters;
public class Species : IIdNameTableEntry
{
private int mID;
private string mName;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
internal Species(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,28 @@
namespace Decal.Filters;
public sealed class SpeciesTable : IdNameTable<Species>
{
internal SpeciesTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 570425358)
{
return false;
}
Index += 5;
int num = Get.Byte(Data, ref Index);
InitializeTable(num);
for (int i = 0; i < num; i++)
{
Species species = new Species(Get.DWord(Data, ref Index));
species.Name = Get.PString(Data, ref Index);
Add(species);
}
return true;
}
}

View file

@ -0,0 +1,427 @@
namespace Decal.Filters;
public class Spell : IIdNameTableEntry
{
private int mID;
private string mName;
private string mDesc;
private int mIconId;
private int mFamily;
private int mType;
private int mFlags;
private SpellSchool mSchool;
private int mDiff;
private int mMana;
private SpellComponentIDs mComps;
private float mSpeed;
private double mDuration;
private int mCasterEffect;
private int mTargetEffect;
private int mTargetMask;
private int mGen;
private int mSort;
private float mUnk1;
private float mUnk2;
private float mUnk3;
private int mUnk4;
private double mUnk5;
private int mUnk6;
private int mUnk7;
private int mUnk8;
private int mUnk9;
private int mUnk10;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
public string Description
{
get
{
return mDesc;
}
internal set
{
mDesc = value;
}
}
public int IconId
{
get
{
return mIconId;
}
internal set
{
mIconId = value;
}
}
public int Family
{
get
{
return mFamily;
}
internal set
{
mFamily = value;
}
}
public int Type
{
get
{
return mType;
}
internal set
{
mType = value;
}
}
public int Flags
{
get
{
return mFlags;
}
internal set
{
mFlags = value;
}
}
public bool IsOffensive => (mFlags & 1) != 0;
public bool IsIrresistible => (mFlags & 4) != 0;
public bool IsUntargetted => (mFlags & 8) != 0;
public bool IsDebuff => (mFlags & 0x10) != 0;
public bool IsFellowship => (mFlags & 0x2000) != 0;
public bool IsFastWindup => (mFlags & 0x4000) != 0;
public SpellSchool School
{
get
{
return mSchool;
}
internal set
{
mSchool = value;
}
}
public int Difficulty
{
get
{
return mDiff;
}
internal set
{
mDiff = value;
}
}
public int Mana
{
get
{
return mMana;
}
internal set
{
mMana = value;
}
}
public SpellComponentIDs ComponentIDs
{
get
{
return mComps;
}
internal set
{
mComps = value;
}
}
public float Speed
{
get
{
return mSpeed;
}
internal set
{
mSpeed = value;
}
}
public double Duration
{
get
{
return mDuration;
}
internal set
{
mDuration = value;
}
}
public int CasterEffect
{
get
{
return mCasterEffect;
}
internal set
{
mCasterEffect = value;
}
}
public int TargetEffect
{
get
{
return mTargetEffect;
}
internal set
{
mTargetEffect = value;
}
}
public int TargetMask
{
get
{
return mTargetMask;
}
internal set
{
mTargetMask = value;
}
}
public int Generation
{
get
{
return mGen;
}
internal set
{
mGen = value;
}
}
public int SortKey
{
get
{
return mSort;
}
internal set
{
mSort = value;
}
}
public float Unknown1
{
get
{
return mUnk1;
}
internal set
{
mUnk1 = value;
}
}
public float Unknown2
{
get
{
return mUnk2;
}
internal set
{
mUnk2 = value;
}
}
public float Unknown3
{
get
{
return mUnk3;
}
internal set
{
mUnk3 = value;
}
}
public int Unknown4
{
get
{
return mUnk4;
}
internal set
{
mUnk4 = value;
}
}
public double Unknown5
{
get
{
return mUnk5;
}
internal set
{
mUnk5 = value;
}
}
public int Unknown6
{
get
{
return mUnk6;
}
internal set
{
mUnk6 = value;
}
}
public int Unknown7
{
get
{
return mUnk7;
}
internal set
{
mUnk7 = value;
}
}
public int Unknown8
{
get
{
return mUnk8;
}
internal set
{
mUnk8 = value;
}
}
public int Unknown9
{
get
{
return mUnk9;
}
internal set
{
mUnk9 = value;
}
}
public int Unknown10
{
get
{
return mUnk10;
}
internal set
{
mUnk10 = value;
}
}
internal Spell(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
internal static int Hash(string Name, string Description)
{
return Hash(Name, 303068800u) + Hash(Description, 3199061829u);
}
internal static int Hash(string Buffer, uint Seed)
{
int num = 0;
for (int i = 0; i < Buffer.Length; i++)
{
num = (num << 4) + (byte)Buffer[i];
if ((num & 0xF0000000u) != 0L)
{
num = (num & 0xFFFFFFF) ^ ((num >> 24) & 0xF0);
}
}
return (int)(num % Seed);
}
}

View file

@ -0,0 +1,25 @@
namespace Decal.Filters;
public sealed class SpellComponentIDs : RawTable<int>
{
private int mHash;
internal SpellComponentIDs(int length, int hash)
{
InitializeTable(length);
mHash = hash;
}
internal override bool LoadFrom(byte[] data)
{
return true;
}
internal new void Add(int entry)
{
if (entry != 0 && entry - mHash != 0)
{
base.Add(entry - mHash);
}
}
}

View file

@ -0,0 +1,58 @@
using System.Globalization;
namespace Decal.Filters;
public sealed class SpellSchool
{
private static SpellSchool[] sSchools = new SpellSchool[5]
{
new SpellSchool(1, "War Magic"),
new SpellSchool(2, "Life Magic"),
new SpellSchool(3, "Item Enchantment"),
new SpellSchool(4, "Creature Enchantment"),
new SpellSchool(5, "Void Magic")
};
private int mId;
private string mName;
public int Id => mId;
public string Name => mName;
public static SpellSchool GetById(int id)
{
for (int i = 0; i < sSchools.Length; i++)
{
if (sSchools[i].Id == id)
{
return sSchools[i];
}
}
return null;
}
public static SpellSchool GetByName(string name)
{
for (int i = 0; i < sSchools.Length; i++)
{
if (string.Compare(sSchools[i].Name, name, ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
return sSchools[i];
}
}
return null;
}
private SpellSchool(int id, string name)
{
mId = id;
mName = name;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,58 @@
namespace Decal.Filters;
public sealed class SpellTable : IdNameTable<Spell>
{
internal SpellTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 234881038)
{
return false;
}
int num = Get.Word(Data, ref Index);
InitializeTable(num);
Index += 2;
for (int i = 0; i < num; i++)
{
Spell spell = new Spell(Get.DWord(Data, ref Index));
spell.Name = Get.EncString(Data, ref Index);
spell.Description = Get.EncString(Data, ref Index);
spell.School = SpellSchool.GetById(Get.DWord(Data, ref Index));
spell.IconId = Get.DWord(Data, ref Index);
spell.Family = Get.DWord(Data, ref Index);
spell.Flags = Get.DWord(Data, ref Index);
spell.Mana = Get.DWord(Data, ref Index);
spell.Unknown1 = Get.Float(Data, ref Index);
spell.Unknown2 = Get.Float(Data, ref Index);
spell.Difficulty = Get.DWord(Data, ref Index);
spell.Unknown3 = Get.Float(Data, ref Index);
spell.Generation = Get.DWord(Data, ref Index);
spell.Speed = Get.Float(Data, ref Index);
spell.Type = Get.DWord(Data, ref Index);
spell.Unknown4 = Get.DWord(Data, ref Index);
spell.Duration = ((spell.Type == 1 || spell.Type == 7 || spell.Type == 12) ? Get.Double(Data, ref Index) : (-1.0));
spell.Unknown5 = ((spell.Type == 1 || spell.Type == 12) ? Get.Double(Data, ref Index) : (-1.0));
spell.ComponentIDs = new SpellComponentIDs(8, Spell.Hash(spell.Name, spell.Description));
for (int j = 0; j < 8; j++)
{
spell.ComponentIDs.Add(Get.DWord(Data, ref Index));
}
spell.CasterEffect = Get.DWord(Data, ref Index);
spell.TargetEffect = Get.DWord(Data, ref Index);
spell.Unknown6 = Get.DWord(Data, ref Index);
spell.Unknown7 = Get.DWord(Data, ref Index);
spell.Unknown8 = Get.DWord(Data, ref Index);
spell.Unknown9 = Get.DWord(Data, ref Index);
spell.SortKey = Get.DWord(Data, ref Index);
spell.TargetMask = Get.DWord(Data, ref Index);
spell.Unknown10 = Get.DWord(Data, ref Index);
Add(spell);
}
return true;
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Filters;
public sealed class TrainedSkillXPTable : RawTable<long>
{
internal TrainedSkillXPTable(int Length)
{
InitializeTable(Length);
}
internal override bool LoadFrom(byte[] Data)
{
return true;
}
internal new void Add(long Entry)
{
base.Add(Entry);
}
}

View file

@ -0,0 +1,25 @@
using System;
namespace Decal.Filters;
public class UpdateEventArgs : EventArgs
{
private int mFileId;
public int FileId
{
get
{
return mFileId;
}
set
{
mFileId = value;
}
}
internal UpdateEventArgs(int fileId)
{
mFileId = fileId;
}
}

View file

@ -0,0 +1,46 @@
namespace Decal.Filters;
public class Vital : IIdNameTableEntry
{
private int mID;
private string mName;
private int mIconId;
public int Id => mID;
public string Name
{
get
{
return mName;
}
internal set
{
mName = value;
}
}
public int IconId
{
get
{
return mIconId;
}
internal set
{
mIconId = value;
}
}
internal Vital(int ID)
{
mID = ID;
}
public override string ToString()
{
return mName;
}
}

View file

@ -0,0 +1,92 @@
namespace Decal.Filters;
public class VitalFormula
{
private bool mAttr1Valid;
private bool mAttr2Valid;
private int mAttr1Id;
private int mAttr2Id;
private int mDivisor;
private int mUnk;
public bool IsAttribute1Valid
{
get
{
return mAttr1Valid;
}
internal set
{
mAttr1Valid = value;
}
}
public bool IsAttribute2Valid
{
get
{
return mAttr2Valid;
}
internal set
{
mAttr2Valid = value;
}
}
public int Attribute1Id
{
get
{
return mAttr1Id;
}
internal set
{
mAttr1Id = value;
}
}
public int Attribute2Id
{
get
{
return mAttr2Id;
}
internal set
{
mAttr2Id = value;
}
}
public int AttributeDivisor
{
get
{
return mDivisor;
}
internal set
{
mDivisor = value;
}
}
public int Unknown
{
get
{
return mUnk;
}
internal set
{
mUnk = value;
}
}
internal VitalFormula()
{
}
}

View file

@ -0,0 +1,36 @@
namespace Decal.Filters;
public sealed class VitalFormulaTable : RawTable<VitalFormula>
{
internal VitalFormulaTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 234881027)
{
return false;
}
if ((Data.Length - Index) % 24 != 0)
{
return false;
}
int num = (Data.Length - 4) / 24;
InitializeTable(num);
for (int i = 0; i < num; i++)
{
VitalFormula vitalFormula = new VitalFormula();
vitalFormula.Unknown = Get.DWord(Data, ref Index);
vitalFormula.IsAttribute1Valid = Get.DWord(Data, ref Index) == 1;
vitalFormula.IsAttribute2Valid = Get.DWord(Data, ref Index) == 1;
vitalFormula.AttributeDivisor = Get.DWord(Data, ref Index);
vitalFormula.Attribute1Id = Get.DWord(Data, ref Index);
vitalFormula.Attribute2Id = Get.DWord(Data, ref Index);
Add(vitalFormula);
}
return true;
}
}

View file

@ -0,0 +1,35 @@
namespace Decal.Filters;
public sealed class VitalTable : IdNameTable<Vital>
{
internal VitalTable(byte[] Data)
{
LoadFrom(Data);
}
internal override bool LoadFrom(byte[] Data)
{
int Index = 0;
if (Get.DWord(Data, ref Index) != 620756999)
{
return false;
}
Index++;
int num = Get.Byte(Data, ref Index);
InitializeTable(num);
for (int i = 0; i < num; i++)
{
Vital vital = new Vital(Get.DWord(Data, ref Index));
vital.IconId = Get.DWord(Data, ref Index);
Add(vital);
}
Index++;
num = Get.Byte(Data, ref Index);
for (int j = 0; j < num; j++)
{
int id = Get.DWord(Data, ref Index);
GetById(id).Name = Get.PString(Data, ref Index);
}
return true;
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Filters;
public sealed class VitalXPTable : RawTable<long>
{
internal VitalXPTable(int Length)
{
InitializeTable(Length);
}
internal override bool LoadFrom(byte[] Data)
{
return true;
}
internal new void Add(long Entry)
{
base.Add(Entry);
}
}

View file

@ -0,0 +1,434 @@
#define TRACE
using System;
using System.Diagnostics;
using System.Text;
namespace Decal.Filters;
internal class zlib
{
private byte[] mInData;
private int mInIndex;
private int mInCount;
private int mInBuf;
private int mInBufSize;
private byte[] mOutData;
private int mOutIndex;
private int mOutCount;
private short[] mDynLCodeTree;
private short[] mDynDCodeTree;
private static short[] mFixLCodeTree;
private static short[] mFixDCodeTree;
public static byte[] Inflate(byte[] CompressedData, int UncompressedSize)
{
byte[] array = (byte[])Array.CreateInstance(typeof(byte), UncompressedSize);
new zlib(CompressedData, 0, CompressedData.Length, array, 0, UncompressedSize).Inflate();
return array;
}
internal zlib(byte[] InData, int InIndex, int InCount, byte[] OutData, int OutIndex, int OutCount)
{
mInData = InData;
mInIndex = InIndex;
mInCount = InCount;
mOutData = OutData;
mOutIndex = OutIndex;
mOutCount = OutCount;
}
internal bool Inflate()
{
byte b = Get.Byte(mInData, ref mInIndex);
mInCount--;
byte b2 = Get.Byte(mInData, ref mInIndex);
mInCount--;
int num = 0;
if ((b2 & 0x20) != 0)
{
num = Get.DWord(mInData, ref mInIndex);
mInCount -= 4;
}
if ((b & 0xF) != 8)
{
Trace.WriteLine(new StringBuilder(64).AppendFormat("zlib.Inflate() Warning: unknown compression method 0x{0:x1}", b & 0xF).ToString());
return false;
}
if (b >> 4 != 7)
{
Trace.WriteLine("zlib.Inflate() Warning: window size other than 32K");
return false;
}
if ((b2 & 0x20) != 0)
{
Trace.WriteLine(new StringBuilder(64).AppendFormat("zlib.Inflate() Warning: unknown DICTID 0x{0:x8}", num).ToString());
return false;
}
int bits;
do
{
bits = GetBits(1);
switch (GetBits(2))
{
case 0:
{
GetBits(0);
int bits2 = GetBits(16);
int bits3 = GetBits(16);
if (bits2 != (~bits3 & 0xFFFF))
{
Trace.WriteLine("zlib.Inflate() Warning: LEN != ~NLEN");
}
Buffer.BlockCopy(mInData, mInIndex, mOutData, mOutIndex, bits2);
mInIndex += bits2;
mOutIndex += bits2;
break;
}
case 1:
if ((mFixLCodeTree == null || mFixDCodeTree == null) && !InitFixedCodes())
{
return false;
}
if (!Decompress(mFixLCodeTree, mFixDCodeTree))
{
return false;
}
break;
case 2:
if (!InitDynamicCodes())
{
return false;
}
if (!Decompress(mDynLCodeTree, mDynDCodeTree))
{
return false;
}
break;
case 3:
Trace.WriteLine("zlib.Inflate() Warning: unhandled block type 3");
return false;
}
}
while (bits != 1);
for (int i = 0; i < 4; i++)
{
GetBits(8);
}
return true;
}
private static bool InitFixedCodes()
{
int[] array = (int[])Array.CreateInstance(typeof(int), 288);
int[] array2 = (int[])Array.CreateInstance(typeof(int), 32);
int i;
for (i = 0; i < 144; i++)
{
array[i] = 8;
}
for (; i < 256; i++)
{
array[i] = 9;
}
for (; i < 280; i++)
{
array[i] = 7;
}
for (; i < 288; i++)
{
array[i] = 8;
}
for (i = 0; i < 32; i++)
{
array2[i] = 5;
}
mFixLCodeTree = BuildCodeTree(array, 0, 288, 65536);
mFixDCodeTree = BuildCodeTree(array2, 0, 32, 65536);
return true;
}
private bool InitDynamicCodes()
{
int[] array = new int[19]
{
16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
11, 4, 12, 3, 13, 2, 14, 1, 15
};
int num = GetBits(5) + 257;
int num2 = GetBits(5) + 1;
int num3 = GetBits(4) + 4;
int[] array2 = (int[])Array.CreateInstance(typeof(int), 19);
for (int i = 0; i < num3; i++)
{
array2[array[i]] = GetBits(3);
}
short[] codeTree = BuildCodeTree(array2, 0, 19, 256);
int num4 = num + num2;
int[] array3 = (int[])Array.CreateInstance(typeof(int), num4);
int num5 = 0;
while (num5 < num4)
{
int code = GetCode(codeTree);
if (code >= 0 && code < 16)
{
array3[num5++] = code;
continue;
}
switch (code)
{
case 16:
{
int num7 = GetBits(2) + 3;
while (num7-- > 0)
{
array3[num5] = array3[num5 - 1];
num5++;
}
break;
}
case 17:
{
int num8 = GetBits(3) + 3;
while (num8-- > 0)
{
array3[num5++] = 0;
}
break;
}
case 18:
{
int num6 = GetBits(7) + 11;
while (num6-- > 0)
{
array3[num5++] = 0;
}
break;
}
default:
Trace.WriteLine(new StringBuilder(64).AppendFormat("Deflate.InitDynamicCodes Warning: invalid code 0x{0:x4}", code).ToString());
return false;
}
}
mDynLCodeTree = BuildCodeTree(array3, 0, num, 65536);
mDynDCodeTree = BuildCodeTree(array3, num, num2, 65536);
return true;
}
private static short[] BuildCodeTree(int[] CodeLens, int Start, int Count, int CodeTreeLength)
{
short[] array = (short[])Array.CreateInstance(typeof(short), CodeTreeLength);
int[] array2 = (int[])Array.CreateInstance(typeof(int), 16);
int[] array3 = (int[])Array.CreateInstance(typeof(int), 16);
for (int i = Start; i < Start + Count; i++)
{
array2[CodeLens[i]]++;
}
array2[0] = 0;
int num = 0;
for (int j = 1; j < 16; j++)
{
num = (array3[j] = num + array2[j - 1] << 1);
}
for (int k = 0; k < CodeTreeLength; k++)
{
array[k] = -1;
}
for (int l = 0; l < Count; l++)
{
int num2 = CodeLens[Start + l];
if (num2 > 0)
{
int num3 = Reverse(array3[num2]++, num2);
int num4 = 1;
while (num2-- > 0)
{
num4 <<= 1;
num4 += num3 & 1;
num3 >>= 1;
}
array[num4] = (short)l;
}
}
return array;
}
private bool Decompress(short[] LCodeTree, short[] DCodeTree)
{
int[,] array = new int[29, 2]
{
{ 0, 3 },
{ 0, 4 },
{ 0, 5 },
{ 0, 6 },
{ 0, 7 },
{ 0, 8 },
{ 0, 9 },
{ 0, 10 },
{ 1, 11 },
{ 1, 13 },
{ 1, 15 },
{ 1, 17 },
{ 2, 19 },
{ 2, 23 },
{ 2, 27 },
{ 2, 31 },
{ 3, 35 },
{ 3, 43 },
{ 3, 51 },
{ 3, 59 },
{ 4, 67 },
{ 4, 83 },
{ 4, 99 },
{ 4, 115 },
{ 5, 131 },
{ 5, 163 },
{ 5, 195 },
{ 5, 227 },
{ 0, 258 }
};
int[,] array2 = new int[30, 2]
{
{ 0, 1 },
{ 0, 2 },
{ 0, 3 },
{ 0, 4 },
{ 1, 5 },
{ 1, 7 },
{ 2, 9 },
{ 2, 13 },
{ 3, 17 },
{ 3, 25 },
{ 4, 33 },
{ 4, 49 },
{ 5, 65 },
{ 5, 97 },
{ 6, 129 },
{ 6, 193 },
{ 7, 257 },
{ 7, 385 },
{ 8, 513 },
{ 8, 769 },
{ 9, 1025 },
{ 9, 1537 },
{ 10, 2049 },
{ 10, 3073 },
{ 11, 4097 },
{ 11, 6145 },
{ 12, 8193 },
{ 12, 12289 },
{ 13, 16385 },
{ 13, 24577 }
};
int code;
while ((code = GetCode(LCodeTree)) != 256)
{
if (code >= 0 && code < 256)
{
mOutData[mOutIndex++] = (byte)code;
mOutCount--;
continue;
}
if (code > 256)
{
code -= 257;
int numBits;
int num = (((numBits = array[code, 0]) > 0) ? GetBits(numBits) : 0);
num += array[code, 1];
code = GetCode(DCodeTree);
int num2 = (((numBits = array2[code, 0]) > 0) ? GetBits(numBits) : 0);
num2 += array2[code, 1];
while (num-- > 0)
{
mOutData[mOutIndex] = mOutData[mOutIndex - num2];
mOutIndex++;
mOutCount--;
}
continue;
}
Trace.WriteLine(new StringBuilder(64).AppendFormat("Deflate.Decompress Warning: invalid code 0x{0:x4}", code).ToString());
return false;
}
return true;
}
private short GetCode(short[] CodeTree)
{
int num = CodeTree.Length;
int num2 = 1;
while (CodeTree[num2] == -1)
{
num2 <<= 1;
num2 += GetBits(1);
if (num2 >= num)
{
return -1;
}
}
return CodeTree[num2];
}
private int GetBits(int NumBits)
{
int num;
switch (NumBits)
{
default:
return -1;
case 0:
num = mInBufSize & 7;
mInBuf >>= num;
mInBufSize -= num;
return 0;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
break;
}
while (mInBufSize < NumBits)
{
int num2 = mInData[mInIndex++];
mInCount--;
mInBuf |= num2 << mInBufSize;
mInBufSize += 8;
}
num = mInBuf & ((1 << NumBits) - 1);
mInBuf >>= NumBits;
mInBufSize -= NumBits;
return num;
}
private static int Reverse(int Bits, int Length)
{
int num = 0;
while (Length-- > 0)
{
num = (num << 1) | (Bits & 1);
Bits >>= 1;
}
return num;
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
[assembly: AssemblyTitle("FileService")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FileService")]
[assembly: AssemblyCopyright("Copyright © 2005 Kenneth Gober")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5E9B2FC3-C251-4589-8CE3-2BCA542B98B6")]
[assembly: CLSCompliant(true)]
[assembly: ReliabilityContract(Consistency.MayCorruptProcess, Cer.None)]
[assembly: AssemblyFileVersion("2.9.8.3")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum)]
[assembly: AssemblyVersion("2.9.8.3")]