CodeWalker/GameFiles/FileTypes/RelFile.cs
2017-09-21 20:33:05 +10:00

801 lines
24 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 RelFile : PackedFile
{
public RpfFileEntry FileEntry { get; set; }
public string Name { get; set; }
public uint Type { get; set; }
public uint DataLength { get; set; }
public byte[] DataBlock { get; set; }
public uint DataUnkVal { get; set; }
public uint NameTableLength { get; set; }
public uint NameTableCount { get; set; }
public uint[] NameTableOffsets { get; set; }
public string[] NameTable { get; set; }
public uint IndexCount { get; set; }
public uint IndexStringFlags { get; set; }
public RelIndexHash[] IndexHashes { get; set; }
public RelIndexString[] IndexStrings { get; set; }
public uint Unk05Count { get; set; }
public uint[] Unk05Arr { get; set; }
public MetaHash[] Unk05Hashes { get; set; }
public uint Unk06Count { get; set; }
public uint[] Unk06Arr { get; set; }
public MetaHash[] Unk06Hashes { get; set; }
public RelData[] RelDatas { get; set; }
public RelData[] RelDatasSorted { get; set; }
//testing zone for decoding .rel audio files.
public RelFile()
{
}
public RelFile(RpfFileEntry entry)
{
FileEntry = entry;
}
public void Load(byte[] data, RpfFileEntry entry)
{
FileEntry = entry;
Name = entry.Name;
MemoryStream ms = new MemoryStream(data);
BinaryReader br = new BinaryReader(ms);
StringBuilder sb = new StringBuilder();
Type = br.ReadUInt32(); //type/version?
DataLength = br.ReadUInt32(); //length of data block
DataBlock = br.ReadBytes((int)DataLength); //data block... synth infos? script?
NameTableLength = br.ReadUInt32(); //length of this nametable block
NameTableCount = br.ReadUInt32();
if (NameTableCount > 0)
{
uint[] d02 = new uint[NameTableCount]; //string offsets
for (uint i = 0; i < NameTableCount; i++)
{
d02[i] = br.ReadUInt32();
}
NameTableOffsets = d02;
string[] names = new string[NameTableCount];
for (uint i = 0; i < NameTableCount; i++)
{
sb.Clear();
while (true)
{
char c = (char)br.ReadByte();
if (c != 0) sb.Append(c);
else break;
}
names[i] = sb.ToString();
}
NameTable = names;
}
IndexCount = br.ReadUInt32(); //count of index items
if (IndexCount > 0)
{
//checking NameTableLength here doesn't make sense!
if ((Type == 4) && (NameTableLength == 4))//audioconfig.dat4.rel
{
IndexStringFlags = br.ReadUInt32(); //what is this? 2524
RelIndexString[] indexstrs = new RelIndexString[IndexCount];
for (uint i = 0; i < IndexCount; i++)
{
byte sl = br.ReadByte();
sb.Clear();
for (int j = 0; j < sl; j++)
{
char c = (char)br.ReadByte();
if (c != 0) sb.Append(c);
}
RelIndexString cunk01 = new RelIndexString();
cunk01.Name = sb.ToString();
cunk01.Offset = br.ReadUInt32();
cunk01.Length = br.ReadUInt32();
indexstrs[i] = cunk01;
}
IndexStrings = indexstrs;
}
else //for all other .rel files...
{
RelIndexHash[] indexhashes = new RelIndexHash[IndexCount];
for (uint i = 0; i < IndexCount; i++)
{
RelIndexHash unk01 = new RelIndexHash();
unk01.Name = new MetaHash(br.ReadUInt32());
unk01.Offset = br.ReadUInt32();
unk01.Length = br.ReadUInt32();
indexhashes[i] = unk01;
}
IndexHashes = indexhashes;
}
}
Unk05Count = br.ReadUInt32();
if (Unk05Count != 0)
{
uint[] d05 = new uint[Unk05Count];
MetaHash[] d05h = new MetaHash[Unk05Count];
for (uint i = 0; i < Unk05Count; i++)
{
d05[i] = br.ReadUInt32();
var pos = ms.Position;
ms.Position = d05[i];
d05h[i] = new MetaHash(br.ReadUInt32());
ms.Position = pos;
}
Unk05Arr = d05;
Unk05Hashes = d05h;
}
Unk06Count = br.ReadUInt32();
if (Unk06Count != 0)
{
uint[] d06 = new uint[Unk06Count];
MetaHash[] d06h = new MetaHash[Unk06Count];
for (uint i = 0; i < Unk06Count; i++)
{
d06[i] = br.ReadUInt32();
var pos = ms.Position;
ms.Position = d06[i];
d06h[i] = new MetaHash(br.ReadUInt32());
ms.Position = pos;
}
Unk06Arr = d06;
Unk06Hashes = d06h;
}
if (ms.Position != ms.Length)
{ }
//EOF!
br.Dispose();
ms.Dispose();
ParseDataBlock();
}
private void ParseDataBlock()
{
MemoryStream ms = new MemoryStream(DataBlock);
BinaryReader br = new BinaryReader(ms);
DataUnkVal = br.ReadUInt32(); //3 bytes used... for? ..version?
switch (DataUnkVal)
{
case 5252715: //dlcbusiness_amp.dat10.rel
case 5301323: //dlcbeach_game.dat149.rel
case 5378673: //dlcmpheist_game.dat150.rel
case 5750395: //dlcbeach_game.dat150.rel
case 6353778: //dlcbeach_game.dat151.rel
case 6894089: //dlcpilotschool_game.dat151.rel
case 6978435: //dlcxmas2_amp.dat10.rel
case 7126027: //audioconfig.dat4.rel
case 7314721: //dlcmpheist_amp.dat10.rel
case 7516460: //dlcpd03_game.dat151.rel
case 7917027: //dlcluxe_amp.dat10.rel
case 7921508: //dlcluxe_game.dat151.rel
case 8149475: //dlcluxe2_amp.dat10.rel
case 8751734: //dlcsfx1_game.dat151.rel
case 9028036: //dlchalloween_amp.dat10.rel
case 9037528: //dlclowrider_amp.dat10.rel
case 9458585: //dlcapartment_amp.dat10.rel
case 9486222: //dlcapartment_mix.dat15.rel
case 9806108: //mpvalentines2_amp.dat10.rel
case 9813679: //dlcjanuary2016_amp.dat10.rel
case 10269543://dlclow2_amp.dat10.rel
case 10891463://dlcexec1_amp.dat10.rel
case 11171338://dlcstunt_amp.dat10.rel
case 11918985://dlcbiker_amp.dat10.rel
case 12470522://dlcimportexport_amp.dat10.rel
case 12974726://audioconfig.dat4.rel
case 13117164://dlcspecialraces_amp.dat10.rel
break;
default:
break;
}
List<RelData> reldatas = new List<RelData>();
if (IndexHashes != null)
{
foreach (var indexhash in IndexHashes)
{
ms.Position = indexhash.Offset;
RelData d = new RelData();
d.NameHash = indexhash.Name;
d.Offset = indexhash.Offset;
d.Length = indexhash.Length;
d.Data = br.ReadBytes((int)indexhash.Length);
reldatas.Add(d);
}
}
else if (IndexStrings != null)
{
foreach (var indexstr in IndexStrings)
{
ms.Position = indexstr.Offset;
RelData d = new RelData();
d.Name = indexstr.Name;
d.Offset = indexstr.Offset;
d.Length = indexstr.Length;
d.Data = br.ReadBytes((int)indexstr.Length);
reldatas.Add(d);
}
}
RelDatas = reldatas.ToArray();
reldatas.Sort((d1, d2) => d1.Offset.CompareTo(d2.Offset));
RelDatasSorted = reldatas.ToArray();
br.Dispose();
ms.Dispose();
foreach (var d in RelDatas)
{
using (BinaryReader dbr = new BinaryReader(new MemoryStream(d.Data)))
{
switch (Type)
{
case 4: //00000100 //speech.dat4.rel, audioconfig.dat4.rel
ParseData4(d, dbr);
break;
case 10: //00001010 //amp.dat10.rel
ParseData10(d, dbr);
break;
case 15: //00001111 //mix.dat15.rel
ParseData15(d, dbr);
break;
case 16: //00010000 //curves.dat16.rel
ParseData16(d, dbr);
break;
case 22: //00010110 //categories.dat22.rel
ParseData22(d, dbr);
break;
case 54: //00110110 //sounds.dat54.rel
ParseData54(d, dbr);
break;
case 149: //10010101 //game.dat149.rel
ParseData149(d, dbr);
break;
case 150: //10010110 //game.dat150.rel
ParseData150(d, dbr);
break;
case 151: //10010111 //game.dat151.rel
ParseData151(d, dbr);
break;
default:
break;
}
}
}
}
private void ParseData4(RelData d, BinaryReader br)
{
//speech.dat4.rel, audioconfig.dat4.rel
if (d.Length == 1)
{
byte b = br.ReadByte();
switch (b)
{
case 0:
case 25:
case 28:
case 34:
case 89:
case 94:
case 178:
break;
default:
break;
}
return;
}
if (d.Length == 2)
{
byte b = br.ReadByte();
switch (b)
{
case 4:
case 1:
case 15:
case 12:
case 3:
case 2:
case 7:
case 5:
case 158:
case 25:
case 16:
case 64:
case 6:
case 8:
case 14:
case 22:
case 18:
case 20:
case 32:
case 17:
case 30:
case 9:
case 0:
case 47:
case 224:
case 200:
case 136:
case 45:
case 54:
case 28:
case 19:
case 37:
case 61:
case 38:
case 128:
case 24:
case 26:
case 40:
case 13:
case 36:
case 78:
case 34:
case 10:
case 21:
case 192:
case 60:
case 29:
case 33:
case 72:
case 57:
case 133:
case 11:
break;
default:
break;
}
return;
}
if (d.Length == 4)
{
uint h = br.ReadUInt32();
return;
}
byte b00 = br.ReadByte();
switch (b00)
{
case 4:
case 1:
case 0:
case 6:
case 3:
case 2:
case 5:
case 7:
case 15:
case 10:
case 8:
case 9:
break;
case 23:
case 12:
case 11:
case 16:
case 13:
case 36:
case 30:
case 31:
case 27:
case 20:
case 19:
case 14:
case 40:
case 46:
case 22:
case 18:
case 21:
case 45:
case 17:
case 48:
case 87:
case 38:
case 28:
case 29:
case 43:
case 69:
case 50:
case 25:
case 32:
case 35:
case 34:
break;
default:
break;
}
}
private void ParseData10(RelData d, BinaryReader br)
{
//amp.dat10.rel
byte b00 = br.ReadByte();
switch (b00)
{
case 1:
case 3:
break;
default:
break;
}
}
private void ParseData15(RelData d, BinaryReader br)
{
//mix.dat15.rel
byte b00 = br.ReadByte();
switch (b00)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
break;
default:
break;
}
}
private void ParseData16(RelData d, BinaryReader br)
{
//curves.dat16.rel
byte b00 = br.ReadByte();
switch (b00)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 12:
case 13:
case 15:
break;
default:
break;
}
}
private void ParseData22(RelData d, BinaryReader br)
{
//categories.dat22.rel
byte b00 = br.ReadByte();
switch (b00)
{
case 0:
break;
default:
break;
}
}
private void ParseData54(RelData d, BinaryReader br)
{
//sounds.dat54.rel
byte b00 = br.ReadByte();
switch (b00)
{
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:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
break;
default:
break;
}
}
private void ParseData149(RelData d, BinaryReader br)
{
//game.dat149.rel
byte b00 = br.ReadByte();
switch (b00)
{
case 3:
case 4:
case 17:
case 50:
case 57:
case 62:
case 63:
case 66:
case 76:
case 88:
case 90:
break;
default:
break;
}
}
private void ParseData150(RelData d, BinaryReader br)
{
//game.dat150.rel
byte b00 = br.ReadByte();
switch (b00)
{
case 3:
case 4:
case 6:
case 8:
case 17:
case 32:
case 37:
case 38:
case 39:
case 47:
case 50:
case 52:
case 57:
case 62:
case 63:
case 64:
case 65:
case 66:
case 76:
case 88:
case 90:
case 117:
break;
default:
break;
}
}
private void ParseData151(RelData d, BinaryReader br)
{
//game.dat151.rel
byte b00 = br.ReadByte(); //???
switch (b00)
{
case 1://new
case 2://new
case 3:
case 4:
case 5://new
case 6:
case 7://new
case 8://
case 9://new
case 11://new
case 12://new
case 13://new
case 14://new
case 15://new
case 16://new
case 17:
case 18://new
case 22://new
case 23://new
case 24://new
case 25://new
case 26://new
case 27://new
case 28://new
case 29://new
case 30://new
case 31://new
case 32://
case 33://new
case 35://new
case 36://new
case 37://
case 38://
case 39://
case 40://new
case 41://new
case 42://new
case 44://new
case 45://new
case 46://new
case 47://
case 48://new
case 49://new
case 50:
case 51://new
case 52://
case 53://new
case 54://new
case 55://new
case 56://new
case 57:
case 59://new
case 62:
case 63:
case 64:
case 65://
case 66:
case 67://new
case 68://new
case 69://new
case 70://new
case 71://new
case 72://new
case 73://new
case 74://new
case 75://new
case 76:
case 77://new
case 78://new
case 79://new
case 80://new
case 81://new
case 82://new
case 83://new
case 84://new
case 85://new
case 86://new
case 87://new
case 88:
case 90:
case 91://new
case 92://new
case 93://new
case 94://new
case 95://new
case 96://new
case 98://new
case 99://new
case 100://new
case 101://new
case 102://new
case 103://new
case 104://new
case 105://new
case 106://new
case 107://new
case 108://new
case 109://new
case 110://new
case 111://new
case 112://new
case 113://new
case 114://new
case 115://new
case 116://new
case 117:
case 118://new
case 119://new
case 120://new
case 121://new
break;
default:
break;
}
}
public override string ToString()
{
return Name;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public struct RelIndexHash
{
public MetaHash Name { get; set; }
public uint Offset { get; set; }
public uint Length { get; set; }
public override string ToString()
{
return Name.ToString() + ", " + Offset.ToString() + ", " + Length.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public struct RelIndexString
{
public string Name { get; set; }
public uint Offset { get; set; }
public uint Length { get; set; }
public override string ToString()
{
return Name + ", " + Offset.ToString() + ", " + Length.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class RelData
{
public MetaHash NameHash { get; set; }
public string Name { get; set; }
public uint Offset { get; set; }
public uint Length { get; set; }
public byte[] Data { get; set; }
public override string ToString()
{
string ol= ", " + Offset.ToString() + ", " + Length.ToString();
if (!string.IsNullOrEmpty(Name)) return Name + ol;
return NameHash.ToString() + ol;
}
}
}