R26_dev8 - First public commit

This commit is contained in:
dexyfex
2017-09-21 20:33:05 +10:00
Unverified
commit a8243c3e0e
391 changed files with 157678 additions and 0 deletions
+702
View File
@@ -0,0 +1,702 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TC = System.ComponentModel.TypeConverterAttribute;
using EXP = System.ComponentModel.ExpandableObjectConverter;
namespace CodeWalker.GameFiles
{
[TC(typeof(EXP))]public class AwcFile : PackedFile
{
public string Name { get; set; }
public RpfFileEntry FileEntry { get; set; }
public byte[] Data { get; set; }
public string ErrorMessage { get; set; }
public uint Magic { get; set; }
public ushort Version { get; set; }
public ushort Flags { get; set; }
public int StreamCount { get; set; }
public int InfoOffset { get; set; }
public bool MultiChannel { get; set; }
public byte[] MultiChannelData { get; set; }
public AwcStreamInfo[] StreamInfos { get; set; }
public uint[] AudioIds { get; set; }
public AwcAudio[] Audios { get; set; }
public void Load(byte[] data, RpfFileEntry entry)
{
//adapted from libertyV code
//MemoryStream ms = new MemoryStream(data);
Name = entry.Name;
FileEntry = entry;
Data = data;
if ((data == null) || (data.Length < 8))
{
ErrorMessage = "Data null or too short!";
return; //nothing to do, not enough data...
}
Magic = BitConverter.ToUInt32(data, 0);
Endianess endianess = Endianess.LittleEndian;
switch (Magic)
{
default:
ErrorMessage = "Unexpected Magic 0x" + Magic.ToString("X");
return;
case 0x54414441:
endianess = Endianess.LittleEndian;
break;
case 0x41444154:
endianess = Endianess.BigEndian;
break;
}
using (MemoryStream ms = new MemoryStream(data))
{
DataReader r = new DataReader(ms, endianess);
Magic = r.ReadUInt32();
Version = r.ReadUInt16();
Flags = r.ReadUInt16();
StreamCount = r.ReadInt32();
InfoOffset = r.ReadInt32();
//notes from libertyV:
// first bit - means that there are unknown word for each stream after this header
// second bit - I think that it means that not all the tags are in the start of the file, but all the tags of a stream are near the data tag
// third bit - Multi channel audio
if ((Flags >> 8) != 0xFF)
{
ErrorMessage = "Flags 0 not supported!";
return;
}
if ((Flags & 0xF8) != 0)
{
//ErrorMessage = "Flags 1 not supported!";
//return;
}
MultiChannel = ((Flags & 4) == 4);
var flag0 = ((Flags & 1) == 1);
var infoStart = 16 + (flag0 ? (StreamCount * 2) : 0);
ms.Position = infoStart;
List<AwcStreamInfo> infos = new List<AwcStreamInfo>();
Dictionary<uint, AwcStreamInfo> infoDict = new Dictionary<uint, AwcStreamInfo>();
List<uint> audioIds = new List<uint>();
List<AwcAudio> audios = new List<AwcAudio>();
for (int i = 0; i < StreamCount; i++)
{
var info = new AwcStreamInfo(r);
infos.Add(info);
infoDict[info.Id] = info;
}
for (int i = 0; i < StreamCount; i++)
{
var info = infos[i];
for (int j = 0; j < info.TagCount; j++)
{
var chunk = new AwcChunkInfo(r);
info.Chunks[chunk.Tag] = chunk;
}
}
StreamInfos = infos.ToArray();
byte hformat = 0xFA;// 250 0x6061D4FA & 0xFF; //JenkHash.GenHash("format");
byte hdata = 0x55;// 85 0x5EB5E655 & 0xFF; //JenkHash.GenHash("data");
byte hycd = 0x5C;// 92 YCD resource chunk... lip sync anims?
byte hunk = 0x36;// 54 unk chunk? small number of bytes (2+)
if (MultiChannel)
{
AwcStreamInfo stream0 = null;
if (!infoDict.TryGetValue(0, out stream0))
{
ErrorMessage = "Couldn't find MultiChannel stream0";
return;
}
AwcChunkInfo chunk72 = null;
if (!stream0.Chunks.TryGetValue(72, out chunk72))
{
ErrorMessage = "Couldn't find MultiChannel chunk72";
return;
}
ms.Position = chunk72.Offset;
AwcChannelChunkInfo chanInfo = new AwcChannelChunkInfo(r);
if (chanInfo.ChannelCount != StreamCount - 1)
{
ErrorMessage = "Channel Count did not match Stream Count";
return;
}
List<AwcChannelChunkItemInfo> chunkItems = new List<AwcChannelChunkItemInfo>();
for (int i = 0; i < chanInfo.ChannelCount; i++)
{
var itemInfo = new AwcChannelChunkItemInfo(r);
chunkItems.Add(itemInfo);
audioIds.Add(infos[i + 1].Id);
}
//AudioStreams.Add(new MultiChannelAudio(new ChunkStream(this.Stream, streamsChunks[0][Tag("data")]), channelsInfoHeader, streamsInfo, header.BigEndian));
AwcChunkInfo cdata = null;
if (!stream0.Chunks.TryGetValue(hdata, out cdata))
{
ErrorMessage = "Couldn't find Stream 0 data chunk";
return;
}
ms.Position = cdata.Offset;
var lastPos = cdata.Offset + cdata.Size;
//int chunkSize = 0x800;
uint bigChunkSize = chanInfo.ChunkSize;
var chanCount = chanInfo.ChannelCount;
MultiChannelData = r.ReadBytes(cdata.Size);
ms.Position = cdata.Offset;
//var d = data;//temporary
////this doesn't seem to work :(
//while (ms.Position < lastPos)
//{
// uint totalChunks = 0;
// var startPos = ms.Position;
// var curPos = startPos;
// //byte[] chunkdata = r.ReadBytes(chunkSize);
// //ms.Position = startPos;
// AwcChannelChunkHeader[] chanHeaders = new AwcChannelChunkHeader[chanCount];
// for (int i = 0; i < chanCount; i++)
// {
// var chanHeader = new AwcChannelChunkHeader(r);
// chanHeaders[i] = chanHeader;
// totalChunks += chanHeader.ChunkCount;
// }
// int headerSize = (int)(totalChunks * 4 + chanInfo.ChannelCount * AwcChannelChunkHeader.Size);
// headerSize += (((-headerSize) % chunkSize) + chunkSize) % chunkSize; //todo: simplify this!
// curPos += headerSize;
// AwcChannelChunk[] chanChunks = new AwcChannelChunk[chanCount];
// for (int i = 0; i < chanCount; i++)
// {
// var chanChunk = new AwcChannelChunk(r, chanHeaders[i], chunkItems[i]);
// chanChunks[i] = chanChunk;
// curPos += chanChunk.TotalDataSize;
// }
// if (curPos - startPos > chanInfo.ChunkSize)
// {
// ErrorMessage = "Chunk was bigger than the chunk size";
// break;
// }
// if ((totalChunks == 0) || ((startPos + chanInfo.ChunkSize) > lastPos))
// {
// ErrorMessage = "Unable to read chunk";
// break;
// }
// var newPos = startPos + bigChunkSize;
// if (newPos >= lastPos) break;
// ms.Position = newPos;
//}
}
else
{
for (int i = 0; i < StreamCount; i++)
{
var info = infos[i];
AwcChunkInfo cformat = null;
if (!info.Chunks.TryGetValue(hformat, out cformat))
{
ErrorMessage = "Couldn't find Stream " + i.ToString() + " format chunk";
continue;
}
AwcChunkInfo cdata = null;
if (!info.Chunks.TryGetValue(hdata, out cdata))
{
ErrorMessage = "Couldn't find Stream " + i.ToString() + " data chunk";
continue;
}
AwcChunkInfo cycd = null;
AwcAudioAnimClipDict oycd = null;
if (info.Chunks.TryGetValue(hycd, out cycd))
{
ms.Position = cycd.Offset;
oycd = new AwcAudioAnimClipDict(r, cycd);
}
AwcChunkInfo cunk = null;
AwcAudioUnk ounk = null;
if (info.Chunks.TryGetValue(hunk, out cunk))
{
ms.Position = cunk.Offset;
ounk = new AwcAudioUnk(r, cunk);
}
ms.Position = cformat.Offset;
AwcFormatChunk formatChunk = new AwcFormatChunk(r);
ms.Position = cdata.Offset;
AwcAudio audio = new AwcAudio(r, info, formatChunk, cdata);
audio.ClipDict = oycd;
audio.UnkData = ounk;
audios.Add(audio);
audioIds.Add(info.Id);
}
}
Audios = audios.ToArray();
AudioIds = audioIds.ToArray();
}
}
}
[TC(typeof(EXP))] public class AwcStreamInfo
{
public uint RawVal { get; set; }
public uint TagCount { get; set; }
public uint Id { get; set; }
public Dictionary<byte, AwcChunkInfo> Chunks { get; set; } = new Dictionary<byte, AwcChunkInfo>();
public AwcStreamInfo(DataReader r)
{
RawVal = r.ReadUInt32();
TagCount = (RawVal >> 29);
Id = (RawVal & 0x1FFFFFFF);
}
public override string ToString()
{
return Id.ToString("X") + ": " + TagCount.ToString() + " tags";
}
}
[TC(typeof(EXP))] public class AwcChunkInfo
{
public ulong RawVal { get; set; }
public byte Tag { get; set; }
public int Size { get; set; }
public int Offset { get; set; }
public AwcChunkInfo(DataReader r)
{
RawVal = r.ReadUInt64();
Tag = (byte)(RawVal >> 56);
Size = (int)((RawVal >> 28) & 0x0FFFFFFF);
Offset = (int)(RawVal & 0x0FFFFFFF);
}
public override string ToString()
{
return Tag.ToString() + ": " + Size.ToString() + ", " + Offset.ToString();
}
}
[TC(typeof(EXP))] public class AwcChannelChunkInfo
{
public uint Unk0 { get; set; }
public uint ChunkSize { get; set; }
public uint ChannelCount { get; set; }
public AwcChannelChunkInfo(DataReader r)
{
Unk0 = r.ReadUInt32();
ChunkSize = r.ReadUInt32();
ChannelCount = r.ReadUInt32();
}
public override string ToString()
{
return Unk0.ToString() + ": " + ChunkSize.ToString() + ", " + ChannelCount.ToString() + " channels";
}
}
[TC(typeof(EXP))] public class AwcChannelChunkItemInfo
{
public uint Id { get; set; }
public uint Samples { get; set; }
public ushort Unk0 { get; set; }
public ushort SamplesPerSecond { get; set; }
public byte Unk1 { get; set; }
public byte RoundSize { get; set; }
public ushort Unk2 { get; set; }
public AwcChannelChunkItemInfo(DataReader r)
{
Id = r.ReadUInt32();
Samples = r.ReadUInt32();
Unk0 = r.ReadUInt16();
SamplesPerSecond = r.ReadUInt16();
Unk1 = r.ReadByte();
RoundSize = r.ReadByte();
Unk2 = r.ReadUInt16();
}
public override string ToString()
{
return Id.ToString() + ": " + Samples.ToString() + " samples, " + SamplesPerSecond.ToString() + " samples/sec, size: " + RoundSize.ToString();
}
}
[TC(typeof(EXP))] public class AwcFormatChunk
{
public uint Samples { get; set; }
public int UnkMinusOne { get; set; }
public ushort SamplesPerSecond { get; set; }
public ushort Unk1 { get; set; }
public ushort Unk2 { get; set; }
public ushort Unk3 { get; set; }
public ushort Unk4 { get; set; }
public byte Unk5 { get; set; }
public byte Unk6 { get; set; }
public AwcFormatChunk(DataReader r)
{
Samples = r.ReadUInt32();
UnkMinusOne = r.ReadInt32();
SamplesPerSecond = r.ReadUInt16();
Unk1 = r.ReadUInt16();
Unk2 = r.ReadUInt16();
Unk3 = r.ReadUInt16();
Unk4 = r.ReadUInt16();
Unk5 = r.ReadByte();
Unk6 = r.ReadByte();
//Apparently sometimes this struct is longer? TODO: fix??
//r.ReadUInt16();
//r.ReadUInt16();
}
public override string ToString()
{
return Unk1.ToString() + ", " + Unk6.ToString() + ": " + Samples.ToString() + " samples, " + SamplesPerSecond.ToString() + " samples/sec";
}
}
[TC(typeof(EXP))] public class AwcAudio
{
public AwcStreamInfo StreamInfo { get; set; }
public AwcFormatChunk Format { get; set; }
public AwcChunkInfo DataInfo { get; set; }
public byte[] Data { get; set; }
public AwcAudioAnimClipDict ClipDict { get; set; }
public AwcAudioUnk UnkData { get; set; }
public short Channels = 1;
public short BitsPerSample = 4;//16;
public int SamplesPerSecond
{
get
{
return Format?.SamplesPerSecond ?? 0;
}
}
public int SampleCount
{
get
{
return (int)(Format?.Samples ?? 0);
}
}
public string Name
{
get
{
return "0x" + StreamInfo?.Id.ToString("X").PadLeft(8, '0') ?? "0";
}
}
public string Type
{
get
{
if (Format == null) return "Unknown";
string fmt = "ADPCM";
switch (Format.Unk6)
{
case 4:
break;
default:
break;
}
var hz = Format?.SamplesPerSecond ?? 0;
return fmt + ((hz > 0) ? (", " + hz.ToString() + " Hz") : "");
}
}
public string LengthStr
{
get
{
if (Format == null) return "0:00";
float sec = (float)Format.Samples / Format.SamplesPerSecond;
TimeSpan ts = TimeSpan.FromSeconds(sec);
return ts.ToString("m\\:ss");
}
}
public AwcAudio(DataReader r, AwcStreamInfo s, AwcFormatChunk f, AwcChunkInfo d)
{
StreamInfo = s;
Format = f;
DataInfo = d;
Data = r.ReadBytes(d.Size);
}
public override string ToString()
{
var hash = (StreamInfo?.Id.ToString("X") ?? "0").PadLeft(8, '0');
return "0x" + hash + ": " + Format?.ToString() ?? "AwcAudio";
}
public Stream GetWavStream()
{
MemoryStream ms = new MemoryStream();
BinaryWriter w = new BinaryWriter(ms);
//see http://icculus.org/SDL_sound/downloads/external_documentation/wavecomp.htm
//see https://github.com/naudio/NAudio/blob/master/NAudio/Wave/WaveFormats/AdpcmWaveFormat.cs
//see https://msdn.microsoft.com/en-us/library/windows/desktop/ff538799(v=vs.85).aspx
int sampleCount = SampleCount;
int samplesPerSec = SamplesPerSecond;
//short sampleSize = (short)((BitsPerSample / 8) * Channels);//2
//int avgBytesPerSec = sampleSize * samplesPerSec;
short blockAlign = 512;
short samplesPerBlock = (short)((((blockAlign - (7 * Channels)) * 8) / (BitsPerSample * Channels)) + 2);
int avgBytesPerSec = ((samplesPerSec / samplesPerBlock) * blockAlign);
w.Write("RIFF".ToCharArray());
w.Write(0); //file size written later...
w.Write("WAVE".ToCharArray());
w.Write("fmt ".ToCharArray());
w.Write(50); //(PCM:16) //header size
w.Write((short)2); //pcm format tag 1=PCM, 2=ADPCM
w.Write(Channels);
w.Write(samplesPerSec);
w.Write(avgBytesPerSec);
w.Write(blockAlign);// sampleSize);
w.Write(BitsPerSample);
w.Write((short)32);//extra byte count for WAVEFORMATEX
w.Write(samplesPerBlock);
w.Write((short)7);//num coefficients
w.Write((short)256); //coeff 0
w.Write((short)0);
w.Write((short)512); //coeff 1
w.Write((short)-256);
w.Write((short)0); //coeff 2
w.Write((short)0);
w.Write((short)192); //coeff 3
w.Write((short)64);
w.Write((short)240); //coeff 4
w.Write((short)0);
w.Write((short)460); //coeff 5
w.Write((short)-208);
w.Write((short)392); //coeff 6
w.Write((short)-232);
w.Write("data".ToCharArray());
w.Write(0); //data size written later...
if (sampleCount != 0)
{
//var sc = sampleCount * sampleSize;
var datalen = Data.Length;
w.Write(Data);
}
else
{
w.Write(Data);
}
ms.Position = 4;
w.Write((int)ms.Length - 8);
ms.Position = 74;// 40;
w.Write((int)ms.Length - 78);// 44);
w.Flush();
ms.Position = 0;
return ms;
}
}
[TC(typeof(EXP))] public class AwcAudioAnimClipDict
{
public byte[] Data { get; set; }
public ClipDictionary ClipDict { get; set; }
public AwcAudioAnimClipDict(DataReader r, AwcChunkInfo info)
{
Data = r.ReadBytes(info.Size);
if ((Data == null) || (Data.Length < 16)) return;
var data = Data;
RpfResourceFileEntry resentry = new RpfResourceFileEntry();
uint rsc7 = BitConverter.ToUInt32(data, 0);
int version = BitConverter.ToInt32(data, 4);
resentry.SystemFlags = BitConverter.ToUInt32(data, 8);
resentry.GraphicsFlags = BitConverter.ToUInt32(data, 12);
if (rsc7 != 0x37435352)
{ } //testing..
if (version != 46) //46 is Clip Dictionary...
{ }
int newlen = data.Length - 16; //trim the header from the data passed to the next step.
int arrlen = Math.Max(newlen, resentry.SystemSize + resentry.GraphicsSize);//expand it as necessary for the reader.
byte[] newdata = new byte[arrlen];
Buffer.BlockCopy(data, 16, newdata, 0, newlen);
data = newdata;
ResourceDataReader rd = new ResourceDataReader(resentry, data);
ClipDict = rd.ReadBlock<ClipDictionary>();
}
public override string ToString()
{
return (ClipDict?.ClipsMapEntries ?? 0).ToString() + " entries";
}
}
[TC(typeof(EXP))] public class AwcAudioUnk
{
public byte[] Data { get; set; }
public AwcAudioUnk(DataReader r, AwcChunkInfo info)
{
Data = r.ReadBytes(info.Size);
}
public override string ToString()
{
if (Data == null) return "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Data.Length; i++)
{
if (sb.Length > 0) sb.Append(' ');
sb.Append(Data[i].ToString());
}
return sb.ToString();
}
}
[TC(typeof(EXP))] public class AwcChannelChunkHeader
{
public static uint Size = 16; //24 for ps3...
public uint StartChunk { get; set; }
public uint ChunkCount { get; set; }
public uint SamplesToSkip { get; set; } //mostly 0
public uint SamplesPerChunk { get; set; }
public uint DataSize { get; set; }
public AwcChannelChunkHeader(DataReader r)
{
StartChunk = r.ReadUInt32();
ChunkCount = r.ReadUInt32();
SamplesToSkip = r.ReadUInt32();
SamplesPerChunk = r.ReadUInt32();
DataSize = ChunkCount * 0x800;
//for ps3, two extra ints:
//uint unk0 = r.ReadUint32();
//DataSize = r.ReadUint32();
}
}
[TC(typeof(EXP))] public class AwcChannelChunk
{
public AwcChannelChunkHeader Header { get; set; }
public AwcChannelChunkItemInfo Info { get; set; }
public byte[] Data { get; set; }
public uint TotalDataSize { get; set; }
public AwcChannelChunk(DataReader r, AwcChannelChunkHeader h, AwcChannelChunkItemInfo i)
{
Header = h;
Info = i;
TotalDataSize = h.DataSize;
var rs = i?.RoundSize ?? 0;
int ds = (int)h.DataSize;
if (rs != 0)
{
TotalDataSize = (uint)(TotalDataSize + (((-ds) % rs) + rs) % rs);
}
}
}
}
+491
View File
@@ -0,0 +1,491 @@
using SharpDX;
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
{
public class CacheDatFile : PackedFile
{
public RpfFileEntry FileEntry { get; set; }
public CacheFileDate[] FileDates { get; set; }
public Dictionary<uint, MapDataStoreNode> MapNodeDict { get; set; }
public MapDataStoreNode[] RootMapNodes { get; set; }
//public Dictionary<MetaHash, CInteriorProxy> InteriorProxyDict { get; set; }
public Dictionary<MetaHash, BoundsStoreItem> BoundsStoreDict { get; set; }
public MapDataStoreNode[] AllMapNodes { get; set; }
public CInteriorProxy[] AllCInteriorProxies { get; set; }
public BoundsStoreItem[] AllBoundsStoreItems { get; set; }
public void Load(byte[] data, RpfFileEntry entry)
{
FileEntry = entry;
MemoryStream ms = new MemoryStream(data);
BinaryReader br = new BinaryReader(ms);
StringBuilder sb = new StringBuilder();
for (int i = 0; (i < 100) && (i < data.Length); i++)
{
//read version string.
byte b = data[i];
if (b == 0) break;
sb.Append((char)b);
}
string versionstr = sb.ToString();
sb.Clear();
int lastn = 0;
int lspos = 0;
uint structcount = 0;
uint modlen;
bool indates = false;
List<string> lines = new List<string>();
var dates = new List<CacheFileDate>();
var allMapNodes = new List<MapDataStoreNode>();
var allCInteriorProxies = new List<CInteriorProxy>();
var allBoundsStoreItems = new List<BoundsStoreItem>();
for (int i = 100; i < data.Length; i++)
{
byte b = data[i];
if (b == 0)
break;
if (b == 0xA)
{
lastn = i;
string line = sb.ToString();
lines.Add(line);
switch (line)
{
case "<fileDates>":
indates = true;
break;
case "</fileDates>":
indates = false;
break;
case "<module>":
break;
case "</module>":
break;
case "fwMapDataStore":
ms.Position = i + 1;
modlen = br.ReadUInt32();
structcount = modlen / 64;
lspos = i + (int)modlen + 5;
while (ms.Position<lspos)
{
allMapNodes.Add(new MapDataStoreNode(br));
}
//if (allMapNodes.Count != structcount)
//{ }//test fail due to variable length struct
i += (int)(modlen + 4);
break;
case "CInteriorProxy":
ms.Position = i + 1;
modlen = br.ReadUInt32();
structcount = modlen / 104;
lspos = i + (int)modlen + 5;
while (ms.Position < lspos)
{
allCInteriorProxies.Add(new CInteriorProxy(br));
}
if (allCInteriorProxies.Count != structcount)
{ }//all pass here
i += (int)(modlen + 4);
break;
case "BoundsStore":
ms.Position = i + 1;
modlen = br.ReadUInt32();
structcount = modlen / 32;
lspos = i + (int)modlen + 5;
while (ms.Position < lspos)
{
allBoundsStoreItems.Add(new BoundsStoreItem(br));
}
if (allBoundsStoreItems.Count != structcount)
{ }//all pass here
i += (int)(modlen + 4);
break;
default:
if (!indates)
{ } //just testing
else
{
dates.Add(new CacheFileDate(line));//eg: 2740459947 130680580712018938 8944
}
break;
}
sb.Clear();
}
else
{
sb.Append((char)b);
}
}
FileDates = dates.ToArray();
AllMapNodes = allMapNodes.ToArray();
AllCInteriorProxies = allCInteriorProxies.ToArray();
AllBoundsStoreItems = allBoundsStoreItems.ToArray();
MapNodeDict = new Dictionary<uint, MapDataStoreNode>();
var rootMapNodes = new List<MapDataStoreNode>();
foreach (var mapnode in AllMapNodes)
{
MapNodeDict[mapnode.Name] = mapnode;
if (mapnode.ParentName == 0)
{
rootMapNodes.Add(mapnode);
}
if (mapnode.UnkExtra != null)
{ }//notsure what to do with this
}
foreach (var mapnode in AllMapNodes)
{
MapDataStoreNode pnode;
if (MapNodeDict.TryGetValue(mapnode.ParentName, out pnode))
{
pnode.AddChildToList(mapnode);
}
else if ((mapnode.ParentName != 0))
{ }
}
foreach (var mapnode in AllMapNodes)
{
mapnode.ChildrenListToArray();
}
RootMapNodes = rootMapNodes.ToArray();
BoundsStoreDict = new Dictionary<MetaHash, BoundsStoreItem>();
foreach (BoundsStoreItem item in AllBoundsStoreItems)
{
BoundsStoreItem mbsi = null;
if (BoundsStoreDict.TryGetValue(item.Name, out mbsi))
{ }
BoundsStoreDict[item.Name] = item;
}
//InteriorProxyDict = new Dictionary<MetaHash, CInteriorProxy>();
foreach (CInteriorProxy prx in AllCInteriorProxies)
{
//CInteriorProxy mprx = null;
//if (InteriorProxyDict.TryGetValue(prx.Name, out mprx))
//{ }
//InteriorProxyDict[prx.Name] = prx;//can't do this! multiples with same name different pos
MapDataStoreNode mnode = null;
if (MapNodeDict.TryGetValue(prx.Parent, out mnode))
{
mnode.AddInteriorToList(prx);
}
else
{ }
}
foreach (var mapnode in AllMapNodes)
{
mapnode.InteriorProxyListToArray();
}
br.Dispose();
ms.Dispose();
}
public override string ToString()
{
if (FileEntry != null)
{
return FileEntry.ToString();
}
return base.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class CacheFileDate
{
public MetaHash FileName { get; set; }
public DateTime TimeStamp { get; set; }
public uint FileID { get; set; }
public CacheFileDate(string line)
{
string[] parts = line.Split(' ');
if (parts.Length == 3)
{
FileName = new MetaHash(uint.Parse(parts[0]));
TimeStamp = DateTime.FromFileTimeUtc(long.Parse(parts[1]));
FileID = uint.Parse(parts[2]);
}
else
{ } //testing
}
public override string ToString()
{
return FileName.ToString() + ", " + TimeStamp.ToString() + ", " + FileID.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class BoundsStoreItem
{
public MetaHash Name { get; set; }
public Vector3 Min { get; set; }
public Vector3 Max { get; set; }
public uint Layer { get; set; }
public BoundsStoreItem(Bounds b)
{
Name = 0;
Min = b.BoundingBoxMin;
Max = b.BoundingBoxMax;
Layer = 0;
}
public BoundsStoreItem(BinaryReader br)
{
Name = new MetaHash(br.ReadUInt32());
Min = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
Max = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
Layer = br.ReadUInt32();
}
public override string ToString()
{
return Name.ToString() + ", " +
Min.ToString() + ", " +
Max.ToString() + ", " +
Layer.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class CInteriorProxy
{
public uint Unk01 { get; set; }
public uint Unk02 { get; set; }
public uint Unk03 { get; set; }
public MetaHash Name { get; set; }
public MetaHash Parent { get; set; }
public Vector3 Position { get; set; }
public Quaternion Orientation { get; set; }
public Vector3 BBMin { get; set; }
public Vector3 BBMax { get; set; }
public float Unk11 { get; set; }
public uint Unk12 { get; set; }
public float Unk13 { get; set; }
public uint Unk14 { get; set; }
public float Unk15 { get; set; }
public uint Unk16 { get; set; }
public uint Unk17 { get; set; }
public uint Unk18 { get; set; }
public CInteriorProxy(BinaryReader br)
{
Unk01 = br.ReadUInt32();
Unk02 = br.ReadUInt32();
Unk03 = br.ReadUInt32();
Name = new MetaHash(br.ReadUInt32());
Parent = new MetaHash(br.ReadUInt32());
Position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
Orientation = new Quaternion(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
BBMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
BBMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
Unk11 = br.ReadSingle();
Unk12 = br.ReadUInt32();
Unk13 = br.ReadSingle();
Unk14 = br.ReadUInt32();
Unk15 = br.ReadSingle();
Unk16 = br.ReadUInt32();
Unk17 = br.ReadUInt32();
Unk18 = br.ReadUInt32();
}
public override string ToString()
{
return Unk01.ToString() + ", " +
Unk02.ToString() + ", " +
Unk03.ToString() + ", " +
Name.ToString() + ", " +
Parent.ToString() + ", " +
Position.ToString() + ", " +
Orientation.ToString() + ", " +
BBMin.ToString() + ", " +
BBMax.ToString() + ", " +
Unk11.ToString() + ", " +
Unk12.ToString() + ", " +
Unk13.ToString() + ", " +
Unk14.ToString() + ", " +
Unk15.ToString() + ", " +
Unk16.ToString() + ", " +
Unk17.ToString() + ", " +
Unk18.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNode
{
public MetaHash Name { get; set; }
public MetaHash ParentName { get; set; }
public uint ContentFlags { get; set; }
public Vector3 streamingExtentsMin { get; set; }
public Vector3 streamingExtentsMax { get; set; }
public Vector3 entitiesExtentsMin { get; set; }
public Vector3 entitiesExtentsMax { get; set; }
public byte Unk02 { get; set; }
public byte Unk03 { get; set; }
public byte Unk04 { get; set; }
public byte Unk05 { get; set; }
public MapDataStoreNodeExtra UnkExtra { get; set; }
public MapDataStoreNode[] Children { get; set; }
private List<MapDataStoreNode> ChildrenList; //used when building the array
public CInteriorProxy[] InteriorProxies { get; set; }
private List<CInteriorProxy> InteriorProxyList;
public MapDataStoreNode(YmapFile ymap)
{
Name = ymap._CMapData.name;
ParentName = ymap._CMapData.parent;
ContentFlags = ymap._CMapData.contentFlags;
streamingExtentsMin = ymap._CMapData.streamingExtentsMin;
streamingExtentsMax = ymap._CMapData.streamingExtentsMax;
entitiesExtentsMin = ymap._CMapData.entitiesExtentsMin;
entitiesExtentsMax = ymap._CMapData.entitiesExtentsMax;
}
public MapDataStoreNode(BinaryReader br)
{
Name = new MetaHash(br.ReadUInt32());
ParentName = new MetaHash(br.ReadUInt32());
ContentFlags = br.ReadUInt32();
streamingExtentsMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
streamingExtentsMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
entitiesExtentsMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
entitiesExtentsMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
Unk02 = br.ReadByte();
Unk03 = br.ReadByte();
Unk04 = br.ReadByte();
Unk05 = br.ReadByte();
if (Unk05 == 0xFE)
{
UnkExtra = new MapDataStoreNodeExtra(br);
}
}
public void AddChildToList(MapDataStoreNode child)
{
if (ChildrenList == null)
{
ChildrenList = new List<MapDataStoreNode>();
}
ChildrenList.Add(child);
}
public void ChildrenListToArray()
{
if (ChildrenList != null)
{
Children = ChildrenList.ToArray();
ChildrenList = null; //plz get this GC
}
}
public void AddInteriorToList(CInteriorProxy iprx)
{
if (InteriorProxyList == null)
{
InteriorProxyList = new List<CInteriorProxy>();
}
InteriorProxyList.Add(iprx);
}
public void InteriorProxyListToArray()
{
if (InteriorProxyList != null)
{
InteriorProxies = InteriorProxyList.ToArray();
InteriorProxyList = null; //plz get this GC
}
}
public override string ToString()
{
return Name.ToString() + ", " +
ParentName.ToString() + ", " +
ContentFlags.ToString() + ", " +
streamingExtentsMin.ToString() + ", " +
streamingExtentsMax.ToString() + ", " +
entitiesExtentsMin.ToString() + ", " +
entitiesExtentsMax.ToString();// + ", " +
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNodeExtra
{
public uint Unk01; //0
public byte[] Unk02; //1 - 16 (60 bytes)
public uint Unk03;//16
public uint Unk04;
public uint Unk05;
public uint Unk06;
public uint Unk07;
public uint Unk08;
public uint Unk09;
public uint Unk10;
public string Unk02str
{
get
{
StringBuilder sb = new StringBuilder();
if (Unk02 != null)
{
for (int i = 0; i < Unk02.Length; i++)
{
if (Unk02[i] == 0) break;
sb.Append((char)Unk02[i]);
}
}
return sb.ToString();
}
}
public MapDataStoreNodeExtra(BinaryReader br)
{
Unk01 = br.ReadUInt32();
Unk02 = new byte[60];
for (int i = 0; i < 60; i++)
{
Unk02[i] = br.ReadByte();
}
Unk03 = br.ReadUInt32();
Unk04 = br.ReadUInt32();
Unk05 = br.ReadUInt32();
Unk06 = br.ReadUInt32();
Unk07 = br.ReadUInt32();
Unk08 = br.ReadUInt32();
Unk09 = br.ReadUInt32();
Unk10 = br.ReadUInt32();
}
public override string ToString()
{
return Unk01.ToString() + ", " + Unk02str;
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class CutFile : PackedFile
{
public RpfFileEntry FileEntry { get; set; }
public PsoFile Pso { get; set; }
public void Load(byte[] data, RpfFileEntry entry)
{
//MemoryStream ms = new MemoryStream(data);
FileEntry = entry;
MemoryStream ms = new MemoryStream(data);
if (PsoFile.IsPSO(ms))
{
Pso = new PsoFile();
Pso.Load(ms);
//PsoTypes.EnsurePsoTypes(Pso);
var root = PsoTypes.GetRootEntry(Pso);
if (root != null)
{
}
return;
}
else
{
}
}
}
}
+431
View File
@@ -0,0 +1,431 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace CodeWalker.GameFiles
{
public class DlcContentFile
{
public List<DlcContentDataFile> dataFiles { get; set; } = new List<DlcContentDataFile>();
public List<DlcContentChangeSet> contentChangeSets { get; set; } = new List<DlcContentChangeSet>();
public RpfFile DlcFile { get; set; } //used by GameFileCache
public Dictionary<string, DlcExtraFolderMountFile> ExtraMounts { get; set; } = new Dictionary<string, DlcExtraFolderMountFile>();
public Dictionary<string, DlcContentDataFile> RpfDataFiles { get; set; } = new Dictionary<string, DlcContentDataFile>();
public DlcExtraTitleUpdateFile ExtraTitleUpdates { get; set; }
public void Load(XmlDocument doc)
{
var root = doc.DocumentElement;
dataFiles.Clear();
contentChangeSets.Clear();
foreach (XmlNode node in root.ChildNodes)
{
switch (node.Name)
{
case "disabledFiles":
foreach (XmlNode disabledFile in node.ChildNodes)
{ } //nothing to see here..
break;
case "includedXmlFiles":
foreach (XmlNode includedXmlFile in node.ChildNodes)
{ } //nothing to see here..
break;
case "includedDataFiles":
foreach (XmlNode includedDataFile in node.ChildNodes)
{ } //nothing to see here..
break;
case "dataFiles":
foreach (XmlNode dataFile in node.ChildNodes)
{
if (dataFile.NodeType == XmlNodeType.Element)
{
dataFiles.Add(new DlcContentDataFile(dataFile));
}
}
break;
case "contentChangeSets":
foreach (XmlNode contentChangeSet in node.ChildNodes)
{
if (contentChangeSet.NodeType == XmlNodeType.Element)
{
contentChangeSets.Add(new DlcContentChangeSet(contentChangeSet));
}
}
break;
case "patchFiles":
foreach (XmlNode patchFile in node.ChildNodes)
{ } //nothing to see here..
break;
default:
break;
}
}
}
public void LoadDicts(DlcSetupFile setupfile, RpfManager rpfman, GameFileCache gfc)
{
ExtraMounts.Clear();
RpfDataFiles.Clear();
foreach (var datafile in dataFiles)
{
string dfn = GameFileCache.GetDlcPlatformPath(datafile.filename).ToLower();
if (datafile.fileType == "EXTRA_FOLDER_MOUNT_DATA")
{
string efmdxmlpath = datafile.filename.Replace(setupfile.deviceName + ":", DlcFile.Path).Replace('/', '\\');
efmdxmlpath = gfc.GetDlcPatchedPath(efmdxmlpath);
XmlDocument efmdxml = rpfman.GetFileXml(efmdxmlpath);
DlcExtraFolderMountFile efmf = new DlcExtraFolderMountFile();
efmf.Load(efmdxml);
ExtraMounts[dfn] = efmf;
}
if (datafile.fileType == "EXTRA_TITLE_UPDATE_DATA")
{
string etudxmlpath = datafile.filename.Replace(setupfile.deviceName + ":", DlcFile.Path).Replace('/', '\\');
etudxmlpath = gfc.GetDlcPatchedPath(etudxmlpath);
XmlDocument etudxml = rpfman.GetFileXml(etudxmlpath);
DlcExtraTitleUpdateFile etuf = new DlcExtraTitleUpdateFile();
etuf.Load(etudxml);
ExtraTitleUpdates = etuf;
}
if (datafile.fileType == "RPF_FILE")
{
RpfDataFiles[dfn] = datafile;
}
}
}
public override string ToString()
{
return dataFiles.Count.ToString() + " dataFiles, " + contentChangeSets.Count.ToString() + " contentChangeSets";
}
}
public class DlcContentDataFile
{
public string filename { get; set; }
public string fileType { get; set; }
public string contents { get; set; }
public string installPartition { get; set; }
public bool overlay { get; set; }
public bool disabled { get; set; }
public bool persistent { get; set; }
public bool loadCompletely { get; set; }
public bool locked { get; set; }
public DlcContentDataFile(XmlNode node)
{
Load(node);
}
public void Load(XmlNode node)
{
foreach (XmlNode child in node.ChildNodes)
{
switch (child.Name)
{
case "filename":
filename = child.InnerText;
break;
case "fileType":
fileType = child.InnerText;
break;
case "contents":
contents = child.InnerText;
break;
case "installPartition":
installPartition = child.InnerText;
break;
case "overlay":
overlay = Xml.GetBoolAttribute(child, "value");
break;
case "disabled":
disabled = Xml.GetBoolAttribute(child, "value");
break;
case "persistent":
persistent = Xml.GetBoolAttribute(child, "value");
break;
case "loadCompletely":
loadCompletely = Xml.GetBoolAttribute(child, "value");
break;
case "locked":
locked = Xml.GetBoolAttribute(child, "value");
break;
default:
break;
}
}
}
public override string ToString()
{
return filename + ": " + fileType + ": " + contents + ": " + installPartition +
(overlay ? ", overlay" : "") +
(disabled ? ", disabled" : "") +
(persistent ? ", persistent" : "") +
(loadCompletely ? ", loadCompletely" : "") +
(locked ? ", locked" : "");
}
}
public class DlcContentChangeSet
{
public string changeSetName { get; set; }
public List<string> filesToInvalidate { get; set; }
public List<string> filesToDisable { get; set; }
public List<string> filesToEnable { get; set; }
public List<string> txdToLoad { get; set; }
public List<string> txdToUnload { get; set; }
public List<string> residentResources { get; set; }
public List<string> unregisterResources { get; set; }
public List<DlcContentChangeSet> mapChangeSetData { get; set; }
public string associatedMap { get; set; }
public bool requiresLoadingScreen { get; set; }
public string loadingScreenContext { get; set; }
public bool useCacheLoader { get; set; }
public DlcContentChangeSetExecutionConditions executionConditions { get; set; }
public DlcContentChangeSet(XmlNode node)
{
Load(node);
}
public void Load(XmlNode node)
{
foreach (XmlNode child in node.ChildNodes)
{
switch (child.Name)
{
case "changeSetName":
changeSetName = child.InnerText;
break;
case "filesToInvalidate":
filesToInvalidate = GetChildStringArray(child);
if (filesToInvalidate != null)
{ }
break;
case "filesToDisable":
filesToDisable = GetChildStringArray(child);
if (filesToDisable != null)
{ }
break;
case "filesToEnable":
filesToEnable = GetChildStringArray(child);
if (filesToEnable != null)
{ }
break;
case "txdToLoad":
txdToLoad = GetChildStringArray(child);
if (txdToLoad != null)
{ }
break;
case "txdToUnload":
txdToUnload = GetChildStringArray(child);
if (txdToUnload != null)
{ }
break;
case "residentResources":
residentResources = GetChildStringArray(child);
if (residentResources != null)
{ }
break;
case "unregisterResources":
unregisterResources = GetChildStringArray(child);
if (unregisterResources != null)
{ }
break;
case "mapChangeSetData":
mapChangeSetData = new List<DlcContentChangeSet>();
foreach (XmlNode mapChangeSetDataItem in child.ChildNodes)
{
mapChangeSetData.Add(new DlcContentChangeSet(mapChangeSetDataItem));
}
break;
case "associatedMap":
associatedMap = child.InnerText;
break;
case "requiresLoadingScreen":
requiresLoadingScreen = Xml.GetBoolAttribute(child, "value");
break;
case "loadingScreenContext":
loadingScreenContext = child.InnerText;
break;
case "useCacheLoader":
useCacheLoader = Xml.GetBoolAttribute(child, "value");
break;
case "executionConditions":
executionConditions = new DlcContentChangeSetExecutionConditions(child);
break;
default:
break;
}
}
}
private List<string> GetChildStringArray(XmlNode node)
{
if (!node.HasChildNodes) return null;
var result = new List<string>();
foreach (XmlNode child in node.ChildNodes)
{
if (child.NodeType == XmlNodeType.Element)
{
result.Add(child.InnerText);
}
}
return result;
}
public override string ToString()
{
return (changeSetName != null) ? changeSetName : (associatedMap != null) ? associatedMap : null;
}
}
public class DlcContentChangeSetExecutionConditions
{
public string activeChangesetConditions { get; set; }
public string genericConditions { get; set; }
public DlcContentChangeSetExecutionConditions(XmlNode node)
{
Load(node);
}
public void Load(XmlNode node)
{
foreach (XmlNode child in node.ChildNodes)
{
if (child.NodeType != XmlNodeType.Element) continue;
switch (child.Name)
{
case "activeChangesetConditions":
activeChangesetConditions = child.InnerText;
break;
case "genericConditions":
genericConditions = child.InnerText;
break;
default:
break;
}
}
}
public override string ToString()
{
return (string.IsNullOrEmpty(activeChangesetConditions) ? "" : activeChangesetConditions + ", ") + (string.IsNullOrEmpty(genericConditions) ? "" : genericConditions);
}
}
public class DlcExtraFolderMountFile
{
public List<DlcExtraFolderMount> FolderMounts { get; set; } = new List<DlcExtraFolderMount>();
public void Load(XmlDocument doc)
{
var root = doc.DocumentElement;
XmlNodeList mountitems = doc.SelectNodes("SExtraFolderMountData/FolderMounts/Item");
FolderMounts.Clear();
for (int i = 0; i < mountitems.Count; i++)
{
var mount = new DlcExtraFolderMount();
mount.Init(mountitems[i]);
FolderMounts.Add(mount);
}
}
public override string ToString()
{
return "(" + FolderMounts.Count.ToString() + " FolderMounts)";
}
}
public class DlcExtraFolderMount
{
public string type { get; set; }
public string platform { get; set; }
public string path { get; set; }
public string mountAs { get; set; }
public void Init(XmlNode node)
{
type = Xml.GetStringAttribute(node, "type");
platform = Xml.GetStringAttribute(node, "platform");
path = Xml.GetChildInnerText(node, "path");
mountAs = Xml.GetChildInnerText(node, "mountAs");
}
public override string ToString()
{
return type + ": " + path + " - " + mountAs + ((platform != null) ? (" (" + platform + ")") : "");
}
}
public class DlcExtraTitleUpdateFile
{
public List<DlcExtraTitleUpdateMount> Mounts { get; set; } = new List<DlcExtraTitleUpdateMount>();
public void Load(XmlDocument doc)
{
var root = doc.DocumentElement;
XmlNodeList mountitems = doc.SelectNodes("SExtraTitleUpdateData/Mounts/Item");
Mounts.Clear();
for (int i = 0; i < mountitems.Count; i++)
{
var mount = new DlcExtraTitleUpdateMount();
mount.Init(mountitems[i]);
Mounts.Add(mount);
}
}
public override string ToString()
{
return "(" + Mounts.Count.ToString() + " Mounts)";
}
}
public class DlcExtraTitleUpdateMount
{
public string type { get; set; }
public string deviceName { get; set; }
public string path { get; set; }
public void Init(XmlNode node)
{
type = Xml.GetStringAttribute(node, "type");
deviceName = Xml.GetChildInnerText(node, "deviceName");
path = Xml.GetChildInnerText(node, "path");
}
public override string ToString()
{
return type + ": " + deviceName + " - " + path;
}
}
}
+82
View File
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace CodeWalker.GameFiles
{
public class DlcSetupFile
{
public string deviceName { get; set; }
public string datFile { get; set; }
public string nameHash { get; set; }
public List<DlcSetupContentChangesetGroup> contentChangeSetGroups { get; set; }
public string type { get; set; }
public string timeStamp { get; set; }
public int order { get; set; }
public int minorOrder { get; set; }
public int subPackCount { get; set; }
public bool isLevelPack { get; set; }
public RpfFile DlcFile { get; set; } //used by GameFileCache
public DlcContentFile ContentFile { get; set; }
public void Load(XmlDocument doc)
{
var root = doc.DocumentElement;
deviceName = Xml.GetChildInnerText(root, "deviceName");
datFile = Xml.GetChildInnerText(root, "datFile");
nameHash = Xml.GetChildInnerText(root, "nameHash");
type = Xml.GetChildInnerText(root, "type");
timeStamp = Xml.GetChildInnerText(root, "timeStamp");
order = Xml.GetIntAttribute(root.SelectSingleNode("order"), "value");
minorOrder = Xml.GetIntAttribute(root.SelectSingleNode("minorOrder"), "value");
subPackCount = Xml.GetIntAttribute(root.SelectSingleNode("subPackCount"), "value");
isLevelPack = Xml.GetBoolAttribute(root.SelectSingleNode("isLevelPack"), "value");
contentChangeSetGroups = new List<DlcSetupContentChangesetGroup>();
var groups = root.SelectNodes("contentChangeSetGroups/Item");
foreach (XmlNode node in groups)
{
var group = new DlcSetupContentChangesetGroup();
group.Load(node);
contentChangeSetGroups.Add(group);
}
if (root.ChildNodes.Count > 15)
{ }
}
public override string ToString()
{
return deviceName + ", " + datFile + ", " + nameHash + ", " + type + ", " + order.ToString() + ", " + ((contentChangeSetGroups != null) ? contentChangeSetGroups.Count.ToString() : "0") + " groups, " + timeStamp;
}
}
public class DlcSetupContentChangesetGroup
{
public string NameHash { get; set; }
public List<string> ContentChangeSets { get; set; }
public void Load(XmlNode node)
{
if (node.ChildNodes.Count != 2)
{ }
NameHash = Xml.GetChildInnerText(node, "NameHash");
ContentChangeSets = new List<string>();
var changesets = node.SelectNodes("ContentChangeSets/Item");
foreach (XmlNode changeset in changesets)
{
ContentChangeSets.Add(changeset.InnerText);
}
}
public override string ToString()
{
return NameHash + " (" + ((ContentChangeSets != null) ? ContentChangeSets.Count.ToString() : "0") + " changesets)";
}
}
}
File diff suppressed because it is too large Load Diff
+164
View File
@@ -0,0 +1,164 @@
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;
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class JPsoFile : PackedFile
{
public RpfFileEntry FileEntry { get; set; }
public PsoFile Pso { get; set; }
public void Load(byte[] data, RpfFileEntry entry)
{
//MemoryStream ms = new MemoryStream(data);
FileEntry = entry;
MemoryStream ms = new MemoryStream(data);
if (PsoFile.IsPSO(ms))
{
Pso = new PsoFile();
Pso.Load(ms);
//PsoTypes.EnsurePsoTypes(Pso);
var root = PsoTypes.GetRootEntry(Pso);
if (root != null)
{
}
return;
}
else
{
}
}
}
}
+800
View File
@@ -0,0 +1,800 @@
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;
}
}
}
+84
View File
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public static class StatsNames
{
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;
}
}
}
+44
View File
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YbnFile : GameFile, PackedFile
{
public Bounds Bounds { get; set; }
public YbnFile() : base(null, GameFileType.Ybn)
{
}
public YbnFile(RpfFileEntry entry) : base(entry, GameFileType.Ybn)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
Bounds = rd.ReadBlock<Bounds>();
Bounds.OwnerName = entry.Name;
Loaded = true;
}
}
}
+55
View File
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YcdFile : GameFile, PackedFile
{
public ClipDictionary ClipDictionary { get; set; }
public Dictionary<MetaHash, ClipMapEntry> ClipMap { get; set; }
public YcdFile() : base(null, GameFileType.Ycd)
{
}
public YcdFile(RpfFileEntry entry) : base(entry, GameFileType.Ycd)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
//Name = entry.Name;
//Hash = entry.ShortNameHash;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
ClipDictionary = rd.ReadBlock<ClipDictionary>();
ClipMap = new Dictionary<MetaHash, ClipMapEntry>();
if ((ClipDictionary != null) && (ClipDictionary.Clips != null) && (ClipDictionary.Clips.data_items != null))
{
foreach (var cme in ClipDictionary.Clips.data_items)
{
if (cme != null)
{
ClipMap[cme.Hash] = cme;
}
}
}
}
}
}
+89
View File
@@ -0,0 +1,89 @@
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 YddFile : GameFile, PackedFile
{
//public DrawableDictionary DrawableDict { get; set; }
public Dictionary<uint, Drawable> Dict { get; set; }
public Drawable[] Drawables { get; set; }
public YddFile() : base(null, GameFileType.Ydd)
{
}
public YddFile(RpfFileEntry entry) : base(entry, GameFileType.Ydd)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
DrawableDictionary DrawableDict = rd.ReadBlock<DrawableDictionary>();
//MemoryUsage = 0; //uses decompressed filesize now...
//if (DrawableDict != null)
//{
// MemoryUsage += DrawableDict.MemoryUsage;
//}
if ((DrawableDict != null) &&
(DrawableDict.Drawables != null) &&
(DrawableDict.Drawables.data_items != null) &&
(DrawableDict.Hashes != null))
{
Dict = new Dictionary<uint, Drawable>();
var drawables = DrawableDict.Drawables.data_items;
var hashes = DrawableDict.Hashes;
for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++)
{
var drawable = drawables[i];
var hash = hashes[i];
Dict[hash] = drawable;
drawable.Owner = this;
}
for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++)
{
var drawable = drawables[i];
var hash = hashes[i];
if ((drawable.Name == null) || (drawable.Name.EndsWith("#dd")))
{
string hstr = JenkIndex.TryGetString(hash);
if (!string.IsNullOrEmpty(hstr))
{
drawable.Name = hstr;
}
else
{ }
}
}
Drawables = Dict.Values.ToArray();
}
Loaded = true;
}
}
}
+59
View File
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YdrFile : GameFile, PackedFile
{
public Drawable Drawable { get; set; }
public YdrFile() : base(null, GameFileType.Ydr)
{
}
public YdrFile(RpfFileEntry entry) : base(entry, GameFileType.Ydr)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
//MemoryUsage = 0;
try
{
Drawable = rd.ReadBlock<Drawable>();
Drawable.Owner = this;
//MemoryUsage += Drawable.MemoryUsage; //uses decompressed filesize now...
}
catch (Exception ex)
{
string err = ex.ToString();
}
Loaded = true;
}
}
}
+50
View File
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YftFile : GameFile, PackedFile
{
public FragType Fragment { get; set; }
public YftFile() : base(null, GameFileType.Yft)
{
}
public YftFile(RpfFileEntry entry) : base(entry, GameFileType.Yft)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
Fragment = rd.ReadBlock<FragType>();
if (Fragment.Drawable != null)
{
Fragment.Drawable.Owner = this;
}
if (Fragment.Unknown_F8h_Data != null)
{
Fragment.Unknown_F8h_Data.Owner = this;
}
Loaded = true;
}
}
}
File diff suppressed because it is too large Load Diff
+187
View File
@@ -0,0 +1,187 @@
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
{
public class YmfFile : PackedFile
{
public RpfFileEntry FileEntry { get; set; }
public Meta Meta { get; set; }
public PsoFile Pso { get; set; }
public RbfFile Rbf { get; set; }
public YmfMapDataGroup[] MapDataGroups { get; set; }
public CImapDependency[] imapDependencies { get; set; }
public YmfImapDependency2[] imapDependencies2 { get; set; }
public YmfItypDependency2[] itypDependencies2 { get; set; }
public CHDTxdAssetBinding[] HDTxdAssetBindings { get; set; }
public YmfInterior[] Interiors { get; set; }
public void Load(byte[] data, RpfFileEntry entry)
{
FileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
MemoryStream ms = new MemoryStream(data);
if (RbfFile.IsRBF(ms))
{
Rbf = new RbfFile();
Rbf.Load(ms);
//x64j.rpf\\levels\\gta5\\_citye\\indust_01\\id1_props.rpf\\_manifest.ymf
//x64j.rpf\\levels\\gta5\\_citye\\indust_02\\id2_props.rpf\\_manifest.ymf
//x64q.rpf\\levels\\gta5\\_hills\\country_01\\cs1_railwyc.rpf\\_manifest.ymf
//all just HDTxd bindings
return;
}
if (PsoFile.IsPSO(ms))
{
Pso = new PsoFile();
Pso.Load(ms);
//PsoTypes.EnsurePsoTypes(Pso);
ProcessPSO();
return;
}
else
{
}
return;
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
Meta = rd.ReadBlock<Meta>();
}
private void ProcessPSO()
{
//See x64m.rpf\levels\gta5\_cityw\venice_01\venice_metadata.rpf\_manifest.ymf
//for TIMED YMAP stuff!!!!
//check CMapDataGroup.HoursOnOff
var d = PsoTypes.GetRootItem<CPackFileMetaData>(Pso);
MapDataGroups = PsoTypes.GetObjectArray<YmfMapDataGroup, CMapDataGroup>(Pso, d.MapDataGroups);
imapDependencies = PsoTypes.GetItemArray<CImapDependency>(Pso, d.imapDependencies);
imapDependencies2 = PsoTypes.GetObjectArray<YmfImapDependency2, CImapDependencies>(Pso, d.imapDependencies_2);
itypDependencies2 = PsoTypes.GetObjectArray<YmfItypDependency2, CItypDependencies>(Pso, d.itypDependencies_2);
HDTxdAssetBindings = PsoTypes.GetItemArray<CHDTxdAssetBinding>(Pso, d.HDTxdBindingArray);
Interiors = PsoTypes.GetObjectArray<YmfInterior, Unk_741495440>(Pso, d.Interiors);
}
public override string ToString()
{
return (FileEntry != null) ? FileEntry.Path : string.Empty;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YmfMapDataGroup : PsoClass<CMapDataGroup>
{
public CMapDataGroup DataGroup { get; set; } //ymap name
public MetaHash[] Bounds { get; set; }
public MetaHash[] WeatherTypes { get; set; }
public MetaHash Name { get; set; }
public ushort Flags { get; set; }
public uint HoursOnOff { get; set; }
public override string ToString()
{
return DataGroup.ToString();
}
public override void Init(PsoFile pso, ref CMapDataGroup v)
{
DataGroup = v;
Bounds = PsoTypes.GetHashArray(pso, v.Bounds);
WeatherTypes = PsoTypes.GetHashArray(pso, v.WeatherTypes);
Name = v.Name;
Flags = v.Flags;
HoursOnOff = v.HoursOnOff;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YmfImapDependency2 : PsoClass<CImapDependencies>
{
public CImapDependencies Dep { get; set; }
public MetaHash[] itypDepArray { get; set; }//ybn hashes?
public override void Init(PsoFile pso, ref CImapDependencies v)
{
Dep = v;
itypDepArray = PsoTypes.GetHashArray(pso, v.itypDepArray);
}
public override string ToString()
{
return Dep.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YmfItypDependency2 : PsoClass<CItypDependencies>
{
public CItypDependencies Dep { get; set; }
public MetaHash[] itypDepArray { get; set; }//ytyp hashes?
public override void Init(PsoFile pso, ref CItypDependencies v)
{
Dep = v;
itypDepArray = PsoTypes.GetHashArray(pso, v.itypDepArray);
}
public override string ToString()
{
return Dep.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YmfInterior : PsoClass<Unk_741495440>
{
public Unk_741495440 Interior { get; set; }
public MetaHash[] Bounds { get; set; }//ybn hashes?
public override string ToString()
{
return Interior.ToString();
}
public override void Init(PsoFile pso, ref Unk_741495440 v)
{
Interior = v;
Bounds = PsoTypes.GetHashArray(pso, v.Bounds);
}
}
}
+372
View File
@@ -0,0 +1,372 @@
using CodeWalker.World;
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 YmtFile : GameFile, PackedFile
{
public Meta Meta { get; set; }
public PsoFile Pso { get; set; }
public RbfFile Rbf { get; set; }
public YmtFileFormat FileFormat { get; set; } = YmtFileFormat.Unknown;
public YmtFileContentType ContentType { get; set; } = YmtFileContentType.None;
public Dictionary<string,string> CMapParentTxds { get; set; }
public YmtScenarioPointManifest CScenarioPointManifest { get; set; }
public MCScenarioPointRegion CScenarioPointRegion { get; set; }
public ScenarioRegion ScenarioRegion { get; set; }
//fields used by the editor:
public bool HasChanged { get; set; } = false;
public List<string> SaveWarnings = null;
public YmtFile() : base(null, GameFileType.Ymt)
{
}
public YmtFile(RpfFileEntry entry) : base(entry, GameFileType.Ymt)
{
}
public void LoadRSC(byte[] data)
{
//direct load from a raw, compressed ymt resource file (openIV-compatible format)
RpfResourceFileEntry resentry = new RpfResourceFileEntry();
//hopefully this format has an RSC7 header...
uint rsc7 = BitConverter.ToUInt32(data, 0);
if (rsc7 == 0x37435352) //RSC7 header present!
{
int version = BitConverter.ToInt32(data, 4);
resentry.SystemFlags = BitConverter.ToUInt32(data, 8);
resentry.GraphicsFlags = BitConverter.ToUInt32(data, 12);
if (data.Length > 16)
{
int newlen = data.Length - 16; //trim the header from the data passed to the next step.
byte[] newdata = new byte[newlen];
Buffer.BlockCopy(data, 16, newdata, 0, newlen);
data = newdata;
}
else
{
data = null; //shouldn't happen... empty..
}
}
else
{
//direct load from file without the rpf header..
//assume it's in resource meta format
resentry.SystemFlags = RpfResourceFileEntry.GetFlagsFromSize(data.Length, 0);
resentry.GraphicsFlags = RpfResourceFileEntry.GetFlagsFromSize(0, 2); //graphics type 2 for ymt/meta
}
var oldresentry = RpfFileEntry as RpfResourceFileEntry;
if (oldresentry != null) //update the existing entry with the new one
{
oldresentry.SystemFlags = resentry.SystemFlags;
oldresentry.GraphicsFlags = resentry.GraphicsFlags;
resentry.Name = oldresentry.Name;
resentry.NameHash = oldresentry.NameHash;
resentry.NameLower = oldresentry.NameLower;
resentry.ShortNameHash = oldresentry.ShortNameHash;
}
else
{
RpfFileEntry = resentry; //just stick it in there for later...
}
data = ResourceBuilder.Decompress(data);
Load(data, resentry);
//Loaded = true;
}
public void Load(byte[] data, RpfFileEntry entry)
{
RpfFileEntry = entry;
Name = entry.Name;
FilePath = Name;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry != null)
{
ResourceDataReader rd = new ResourceDataReader(resentry, data);
Meta = rd.ReadBlock<Meta>();
var rootblock = Meta.GetRootBlock();
if (rootblock != null)
{
if (rootblock.StructureNameHash == MetaName.CScenarioPointRegion)
{
LoadScenarioPointRegion(Meta, rootblock);
}
}
Loaded = true;
return;
}
MemoryStream ms = new MemoryStream(data);
if (RbfFile.IsRBF(ms))
{
Rbf = new RbfFile();
var rbfstruct = Rbf.Load(ms);
if (rbfstruct.Name == "CMapParentTxds")
{
LoadMapParentTxds(rbfstruct);
}
Loaded = true;
return;
}
if (PsoFile.IsPSO(ms))
{
Pso = new PsoFile();
Pso.Load(ms);
//PsoTypes.EnsurePsoTypes(Pso);
var root = PsoTypes.GetRootEntry(Pso);
if (root != null)
{
if (root.NameHash == MetaName.CScenarioPointManifest)
{
LoadScenarioPointManifest(Pso);
}
}
Loaded = true;
return;
}
else
{
}
}
private void LoadMapParentTxds(RbfStructure rbfstruct)
{
FileFormat = YmtFileFormat.RBF;
ContentType = YmtFileContentType.MapParentTxds;
CMapParentTxds = new Dictionary<string, string>();
//StringBuilder sblist = new StringBuilder();
foreach(var child in rbfstruct.Children)
{
var childstruct = child as RbfStructure;
if ((childstruct != null) && (childstruct.Name == "txdRelationships"))
{
foreach (var txdrel in childstruct.Children)
{
var txdrelstruct = txdrel as RbfStructure;
if ((txdrelstruct != null) && (txdrelstruct.Name == "item"))
{
string parentstr = string.Empty;
string childstr = string.Empty;
foreach(var item in txdrelstruct.Children)
{
var itemstruct = item as RbfStructure;
if ((itemstruct != null))
{
var strbytes = itemstruct.Children[0] as RbfBytes;
string thisstr = string.Empty;
if (strbytes != null)
{
thisstr = Encoding.ASCII.GetString(strbytes.Value).Replace("\0", "");
}
switch (item.Name)
{
case "parent":
parentstr = thisstr;
break;
case "child":
childstr = thisstr;
break;
}
}
}
if((!string.IsNullOrEmpty(parentstr)) && (!string.IsNullOrEmpty(childstr)))
{
if (!CMapParentTxds.ContainsKey(childstr))
{
CMapParentTxds.Add(childstr, parentstr);
}
else
{
}
//sblist.AppendLine(childstr + ": " + parentstr);
}
}
}
}
}
//string alltxdmap = sblist.ToString();
//if (!string.IsNullOrEmpty(alltxdmap))
//{
//}
}
private void LoadScenarioPointManifest(PsoFile pso)
{
FileFormat = YmtFileFormat.PSO;
ContentType = YmtFileContentType.ScenarioPointManifest;
CScenarioPointManifest = new YmtScenarioPointManifest();
CScenarioPointManifest.Load(pso);
}
private void LoadScenarioPointRegion(Meta meta, MetaDataBlock rootblock)
{
FileFormat = YmtFileFormat.RSC;
ContentType = YmtFileContentType.ScenarioPointRegion;
var cdata = MetaTypes.ConvertData<CScenarioPointRegion>(rootblock.Data);
CScenarioPointRegion = new MCScenarioPointRegion();
CScenarioPointRegion.Ymt = this;
CScenarioPointRegion.Load(meta, cdata);
ScenarioRegion = new ScenarioRegion();
ScenarioRegion.Load(this);
//string stypes = MetaTypes.GetTypesInitString(meta);
//if (!string.IsNullOrEmpty(stypes))
//{ }
}
public byte[] Save()
{
switch (ContentType)
{
case YmtFileContentType.MapParentTxds: return SaveMapParentTxds();
case YmtFileContentType.ScenarioPointManifest: return SaveScenarioPointManifest();
case YmtFileContentType.ScenarioPointRegion: return SaveScenarioPointRegion();
}
return null;
}
private byte[] SaveMapParentTxds()
{
return null;
}
private byte[] SaveScenarioPointManifest()
{
return null;
}
private byte[] SaveScenarioPointRegion()
{
if (ScenarioRegion != null)
{
return ScenarioRegion.Save();
}
return null;
}
private void LogSaveWarning(string w)
{
if (SaveWarnings == null) SaveWarnings = new List<string>();
SaveWarnings.Add(w);
}
public override string ToString()
{
return RpfFileEntry.ToString();
}
}
public enum YmtFileFormat
{
Unknown = 0,
RSC = 1,
PSO = 2,
RBF = 3,
}
public enum YmtFileContentType
{
None = 0,
MapParentTxds = 1,
ScenarioPointManifest = 2,
ScenarioPointRegion = 3,
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YmtScenarioPointManifest
{
public CScenarioPointManifest _Data;
public CScenarioPointManifest Data { get { return _Data; } set { _Data = value; } }
public CScenarioPointRegionDef[] RegionDefs { get; set; }
public CScenarioPointGroup[] Groups { get; set; }
public MetaHash[] InteriorNames { get; set; }
public void Load(PsoFile pso)
{
Data = PsoTypes.GetRootItem<CScenarioPointManifest>(pso);
RegionDefs = PsoTypes.ConvertDataArray<CScenarioPointRegionDef>(pso, _Data.RegionDefs);
Groups = PsoTypes.ConvertDataArray<CScenarioPointGroup>(pso, _Data.Groups);
InteriorNames = PsoTypes.GetHashArray(pso, _Data.InteriorNames);
}
}
}
File diff suppressed because it is too large Load Diff
+405
View File
@@ -0,0 +1,405 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
namespace CodeWalker.GameFiles
{
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvFile : GameFile, PackedFile, BasePathData
{
public NavMesh Nav { get; set; }
public List<Vector3> Vertices { get; set; }
public List<ushort> Indices { get; set; }
public List<YnvPoly> Polys { get; set; }
public VertexTypePC[] TriangleVerts { get; set; }
public Vector4[] NodePositions { get; set; }
//fields used by the editor:
public bool HasChanged { get; set; } = false;
public List<string> SaveWarnings = null;
public int AreaID
{
get
{
return (int)(Nav?.AreaID ?? 0);
}
}
public YnvFile() : base(null, GameFileType.Ynv)
{
}
public YnvFile(RpfFileEntry entry) : base(entry, GameFileType.Ynv)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
Nav = rd.ReadBlock<NavMesh>();
if ((Nav != null) && (Nav.SectorTree != null))
{
if (Nav.Vertices != null)
{
Vector3 posoffset = Nav.SectorTree.AABBMin.XYZ();
Vector3 aabbsize = Nav.AABBSize;
var verts = Nav.Vertices.GetFullList();
Vertices = new List<Vector3>(verts.Count);
for (int i = 0; i < verts.Count; i++)
{
var ov = verts[i].ToVector3();
Vertices.Add(posoffset + ov * aabbsize);
}
}
if (Nav.Indices != null)
{
Indices = Nav.Indices.GetFullList();
}
if (Nav.Polys != null)
{
var polys = Nav.Polys.GetFullList();
Polys = new List<YnvPoly>(polys.Count);
for (int i = 0; i < polys.Count; i++)
{
YnvPoly poly = new YnvPoly();
poly.Init(this, polys[i]);
poly.Index = i;
Polys.Add(poly);
//calc poly center.
if ((Indices == null) || (Vertices == null))
{ continue; }
var vc = Vertices.Count;
var ic = poly._RawData.IndexCount;
var startid = poly._RawData.IndexID;
var endid = startid + ic;
if (startid >= Indices.Count)
{ continue; }
if (endid > Indices.Count)
{ continue; }
Vector3 pcenter = Vector3.Zero;
float pcount = 0.0f;
for (int id = startid; id < endid; id++)
{
var ind = Indices[id];
if(ind>=vc)
{ continue; }
pcenter += Vertices[ind];
pcount += 1.0f;
}
poly.Position = pcenter * (1.0f / pcount);
}
}
}
UpdateAllNodePositions();
UpdateTriangleVertices();
Loaded = true;
LoadQueued = true;
}
public bool RemovePoly(YnvPoly poly)
{
return false;
}
public void UpdateAllNodePositions()
{
if (Nav == null) return;
if (Nav.Portals == null) return;
int cnt = Nav.Portals?.Length ?? 0;
if (cnt <= 0)
{
NodePositions = null;
return;
}
Vector3 posoffset = Nav.SectorTree.AABBMin.XYZ();
Vector3 aabbsize = Nav.AABBSize;
var np = new Vector4[cnt];
for (int i = 0; i < cnt; i++)
{
var portal = Nav.Portals[i];
var pv = portal.Position1.ToVector3();
//var pv = portal.Position2.ToVector3();
np[i] = new Vector4(posoffset + pv * aabbsize, 1.0f);
}
NodePositions = np;
}
public void UpdateTriangleVertices()
{
if (Nav == null) return;
if (Nav.Polys == null) return;
if (Nav.Vertices == null) return;
//need position and colour for each vertex.
//render as a triangle list... (no indices needed)
//go through the nav mesh polys and generate verts to render...
if ((Vertices == null) || (Vertices.Count == 0)) return;
if ((Indices == null) || (Indices.Count == 0)) return;
if ((Polys == null) || (Polys.Count == 0)) return;
int vc = Vertices.Count;
List<VertexTypePC> rverts = new List<VertexTypePC>();
foreach (var ypoly in Polys)
{
var poly = ypoly.RawData;
var colour = ypoly.GetColour();
var colourval = (uint)colour.ToRgba();
var ic = poly.IndexCount;
var startid = poly.IndexID;
var endid = startid + ic;
if (startid >= Indices.Count)
{ continue; }
if (endid > Indices.Count)
{ continue; }
if(ic<3)
{ continue; }//not enough verts to make a triangle...
if (ic > 15)
{ }
VertexTypePC p0 = new VertexTypePC();
VertexTypePC p1 = new VertexTypePC();
VertexTypePC p2 = new VertexTypePC();
p0.Colour = colourval;
p1.Colour = colourval;
p2.Colour = colourval;
var startind = Indices[startid];
if (startind >= vc)
{ continue; }
p0.Position = Vertices[startind];
//build triangles for the poly.
int tricount = ic - 2;
for (int t = 0; t < tricount; t++)
{
int tid = startid + t;
int ind1 = Indices[tid + 1];
int ind2 = Indices[tid + 2];
if ((ind1 >= vc) || (ind2 >= vc))
{ continue; }
p1.Position = Vertices[ind1];
p2.Position = Vertices[ind2];
rverts.Add(p0);
rverts.Add(p1);
rverts.Add(p2);
}
}
TriangleVerts = rverts.ToArray();
}
public VertexTypePC[] GetPathVertices()
{
return null;
}
public VertexTypePC[] GetTriangleVertices()
{
return TriangleVerts;
}
public Vector4[] GetNodePositions()
{
return NodePositions;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoly
{
public NavMeshPoly _RawData;
public YnvFile Ynv { get; set; }
public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } }
public ushort AreaID { get { return _RawData.AreaID; } }
public bool B00_AvoidUnk { get { return (_RawData.Unknown_00h & 1) > 0; } }
public bool B01_AvoidUnk { get { return (_RawData.Unknown_00h & 2) > 0; } }
public bool B02_IsFootpath { get { return (_RawData.Unknown_00h & 4) > 0; } }
public bool B03_IsUnderground { get { return (_RawData.Unknown_00h & 8) > 0; } }
//public bool B04_Unused { get { return (_RawData.Unknown_00h & 16) > 0; } }
//public bool B05_Unused { get { return (_RawData.Unknown_00h & 32) > 0; } }
public bool B06_SteepSlope { get { return (_RawData.Unknown_00h & 64) > 0; } }
public bool B07_IsWater { get { return (_RawData.Unknown_00h & 128) > 0; } }
public bool B08_UndergroundUnk1 { get { return (_RawData.Unknown_24h.Value & 1) > 0; } }
public bool B09_UndergroundUnk2 { get { return (_RawData.Unknown_24h.Value & 2) > 0; } }
public bool B10_UndergroundUnk3 { get { return (_RawData.Unknown_24h.Value & 4) > 0; } }
public bool B11_UndergroundUnk4 { get { return (_RawData.Unknown_24h.Value & 8) > 0; } }
//public bool B12_Unused { get { return (_RawData.Unknown_24h.Value & 16) > 0; } }
public bool B13_HasPathNode { get { return (_RawData.Unknown_24h.Value & 32) > 0; } }
public bool B14_IsInterior { get { return (_RawData.Unknown_24h.Value & 64) > 0; } }
public bool B15_InteractionUnk { get { return (_RawData.Unknown_24h.Value & 128) > 0; } }
//public bool B16_Unused { get { return (_RawData.Unknown_24h.Value & 256) > 0; } }
public bool B17_IsFlatGround { get { return (_RawData.Unknown_24h.Value & 512) > 0; } }
public bool B18_IsRoad { get { return (_RawData.Unknown_24h.Value & 1024) > 0; } }
public bool B19_IsCellEdge { get { return (_RawData.Unknown_24h.Value & 2048) > 0; } }
public bool B20_IsTrainTrack { get { return (_RawData.Unknown_24h.Value & 4096) > 0; } }
public bool B21_IsShallowWater { get { return (_RawData.Unknown_24h.Value & 8192) > 0; } }
public bool B22_FootpathUnk1 { get { return (_RawData.Unknown_24h.Value & 16384) > 0; } }
public bool B23_FootpathUnk2 { get { return (_RawData.Unknown_24h.Value & 32768) > 0; } }
public bool B24_FootpathMall { get { return (_RawData.Unknown_24h.Value & 65536) > 0; } }
public bool B25_SlopeSouth { get { return (_RawData.Unknown_28h.Value & 65536) > 0; } }
public bool B26_SlopeSouthEast { get { return (_RawData.Unknown_28h.Value & 131072) > 0; } }
public bool B27_SlopeEast { get { return (_RawData.Unknown_28h.Value & 262144) > 0; } }
public bool B28_SlopeNorthEast { get { return (_RawData.Unknown_28h.Value & 524288) > 0; } }
public bool B29_SlopeNorth { get { return (_RawData.Unknown_28h.Value & 1048576) > 0; } }
public bool B30_SlopeNorthWest { get { return (_RawData.Unknown_28h.Value & 2097152) > 0; } }
public bool B31_SlopeWest { get { return (_RawData.Unknown_28h.Value & 4194304) > 0; } }
public bool B32_SlopeSouthWest { get { return (_RawData.Unknown_28h.Value & 8388608) > 0; } }
public bool B33_PortalUnk1 { get { return (_RawData.PartUnk2 & 1) > 0; } }
public bool B34_PortalUnk2 { get { return (_RawData.PartUnk2 & 2) > 0; } }
public bool B35_PortalUnk3 { get { return (_RawData.PartUnk2 & 4) > 0; } }
public bool B36_PortalUnk4 { get { return (_RawData.PartUnk2 & 8) > 0; } }
public byte HeuristicXUnk { get { return (byte)_RawData.Unknown_28h_8a; } }
public byte HeuristicYUnk { get { return (byte)_RawData.Unknown_28h_8b; } }
public Vector3 Position { get; set; }
public int Index { get; set; }
public void Init(YnvFile ynv, NavMeshPoly poly)
{
Ynv = ynv;
RawData = poly;
}
public Color4 GetColour()
{
var colour = new Color4();
var u0 = _RawData.Unknown_00h;
if ((u0 & 1) > 0) colour.Red += 0.01f;//avoid? loiter?
if ((u0 & 2) > 0) colour.Red += 0.01f; //avoid?
if ((u0 & 4) > 0) colour.Green += 0.25f; //ped/footpath
if ((u0 & 8) > 0) colour.Green += 0.02f; //underground?
////if ((u0 & 16) > 0) colour.Red += 1.0f; //not used?
////if ((u0 & 32) > 0) colour.Green += 1.0f;//not used?
if ((u0 & 64) > 0) colour.Red += 0.25f; //steep slope
if ((u0 & 128) > 0) colour.Blue += 0.25f; //water
var u2 = _RawData.Unknown_24h.Value;
//colour.Green = (u2 & 15) / 15.0f; //maybe underground amount..?
//if ((u2 & 1) > 0) colour.Blue += 1.0f; //peds interact with something? underground?
//if ((u2 & 2) > 0) colour.Green += 1.0f;//underneath something?
//if ((u2 & 4) > 0) colour.Red += 0.5f;//peds interact with something..? underground?
//if ((u2 & 8) > 0) colour.Red += 0.5f; //underground?
//if ((u2 & 16) > 0) colour.Red += 1.0f; //not used..
//if ((u2 & 32) > 0) colour.Green += 1.0f;//use path node?
if ((u2 & 64) > 0) colour.Blue += 0.1f; //is interior?
//if ((u2 & 128) > 0) colour.Red += 1.0f; //interacting areas? veg branches, roofs, vents, worker areas?
//if ((u2 & 256) > 0) colour.Green += 1.0f; //not used?
if ((u2 & 512) > 0) colour.Green += 0.1f;//is flat ground? ped-navigable?
if ((u2 & 1024) > 0) colour.Blue += 0.03f;//is a road
//if ((u2 & 2048) > 0) colour.Green += 1.0f; //poly is on a cell edge
if ((u2 & 4096) > 0) colour.Green += 0.75f; //is a train track
if ((u2 & 8192) > 0) colour.Blue += 0.75f;//shallow water/moving water
if ((u2 & 16384) > 0) colour.Red += 0.2f; //footpaths/beach - peds walking?
if ((u2 & 32768) > 0) colour.Blue += 0.2f; //footpaths - special?
if ((u2 & 65536) > 0) colour.Green = 0.2f;//footpaths - mall areas? eg mall, vinewood blvd
//if (u2 >= 131072) { }//other bits unused
var u5 = _RawData.Unknown_28h.Value; //32 bits
//colour.Red = poly.Unknown_28h_8a / 255.0f; //heuristic vals..?
//colour.Green = poly.Unknown_28h_8b / 255.0f; //heuristic vals..?
//if ((u5 & 65536) > 0) colour.Red += 1.0f; //slope facing -Y (south)
//if ((u5 & 131072) > 0) colour.Blue += 1.0f; //slope facing +X,-Y (southeast)
//if ((u5 & 262144) > 0) colour.Green += 1.0f; //slope facing +X (east)
//if ((u5 & 524288) > 0) colour.Red += 1.0f; //slope facing +X,+Y (northeast)
//if ((u5 & 1048576) > 0) colour.Green += 1.0f; //slope facing +Y (north)
//if ((u5 & 2097152) > 0) colour.Blue += 1.0f; //slope facing -X,+Y (northwest)
//if ((u5 & 4194304) > 0) colour.Green += 1.0f; //slope facing -X (west)
//if ((u5 & 8388608) > 0) colour.Red += 1.0f; //slope facing -X,-Y (southwest)
//if (u5 >= 16777216) { } //other bits unused
var u1 = _RawData.PartUnk2;
//if ((u1 & 1) > 0) colour.Red += 1.0f; //portal - don't interact?
//if ((u1 & 2) > 0) colour.Green += 1.0f; //portal - ladder/fence interaction?
//if ((u1 & 4) > 0) colour.Blue += 1.0f; //portal - fence interaction / go away from?
//if ((u1 & 8) > 0) colour.Red += 1.0f;//something file-specific? portal index related?
colour.Alpha = 0.75f;
return colour;
}
public override string ToString()
{
return AreaID.ToString() + ", " + Index.ToString();
}
}
}
+106
View File
@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YptFile : GameFile, PackedFile
{
public ParticleEffectsList PtfxList { get; set; }
public Dictionary<uint, Drawable> DrawableDict { get; set; }
public string ErrorMessage { get; set; }
public YptFile() : base(null, GameFileType.Ypt)
{
}
public YptFile(RpfFileEntry entry) : base(entry, GameFileType.Ypt)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
//MemoryUsage = 0;
try
{
PtfxList = rd.ReadBlock<ParticleEffectsList>();
//Drawable.Owner = this;
//MemoryUsage += Drawable.MemoryUsage; //uses decompressed filesize now...
}
catch (Exception ex)
{
ErrorMessage = ex.ToString();
}
var dDict = PtfxList?.DrawableDictionary;
if ((dDict != null) &&
(dDict.Drawables != null) &&
(dDict.Drawables.data_items != null) &&
(dDict.Hashes != null))
{
DrawableDict = new Dictionary<uint, Drawable>();
var drawables = dDict.Drawables.data_items;
var hashes = dDict.Hashes;
for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++)
{
var drawable = drawables[i];
var hash = hashes[i];
DrawableDict[hash] = drawable;
drawable.Owner = this;
}
for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++)
{
var drawable = drawables[i];
var hash = hashes[i];
if ((drawable.Name == null) || (drawable.Name.EndsWith("#dd")))
{
string hstr = JenkIndex.TryGetString(hash);
if (!string.IsNullOrEmpty(hstr))
{
drawable.Name = hstr;
}
else
{
drawable.Name = "0x" + hash.ToString("X").PadLeft(8, '0');
}
}
}
}
Loaded = true;
}
}
}
+49
View File
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YtdFile : GameFile, PackedFile
{
public TextureDictionary TextureDict { get; set; }
public YtdFile() : base(null, GameFileType.Ytd)
{
}
public YtdFile(RpfFileEntry entry) : base(entry, GameFileType.Ytd)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
TextureDict = rd.ReadBlock<TextureDictionary>();
//MemoryUsage = 0; //uses decompressed file size now..
//if (TextureDict != null)
//{
// MemoryUsage += TextureDict.MemoryUsage;
//}
}
}
}
+265
View File
@@ -0,0 +1,265 @@
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 YtypFile : PackedFile
{
public RpfFileEntry FileEntry { get; set; }
public Meta Meta { get; set; }
public PsoFile Pso { get; set; }
public RbfFile Rbf { get; set; }
public CMapTypes CMapTypes { get; set; }
//public CBaseArchetypeDef[] CBaseArchetypeDefs { get; set; }
//public CTimeArchetypeDef[] CTimeArchetypeDefs { get; set; }
//public CMloArchetypeDef[] CMloArchetypeDefs { get; set; }
public CExtensionDefAudioEmitter[] AudioEmitters { get; set; }
//public CEntityDef[] CEntityDefs { get; set; }
public CCompositeEntityType[] CompositeEntityTypes { get; set; }
public uint NameHash { get; set; }
public string[] Strings { get; set; }
public Archetype[] AllArchetypes { get; set; }
public MetaWrapper[] Extensions { get; set; }
public override string ToString()
{
return (FileEntry != null) ? FileEntry.Name : string.Empty;
}
public void Load(byte[] data, RpfFileEntry entry)
{
FileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
MemoryStream ms = new MemoryStream(data);
if (RbfFile.IsRBF(ms))
{
Rbf = new RbfFile();
Rbf.Load(ms);
}
else if (PsoFile.IsPSO(ms))
{
Pso = new PsoFile();
Pso.Load(ms);
//PsoTypes.EnsurePsoTypes(Pso);
}
else
{
}
return;
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
Meta = rd.ReadBlock<Meta>();
CMapTypes = MetaTypes.GetTypedData<CMapTypes>(Meta, MetaName.CMapTypes);
List<Archetype> allarchs = new List<Archetype>();
var ptrs = MetaTypes.GetPointerArray(Meta, CMapTypes.archetypes);
if (ptrs != null)
{
for (int i = 0; i < ptrs.Length; i++)
{
var ptr = ptrs[i];
int blocki = ptr.BlockID - 1;
int offset = ptr.ItemOffset * 16;//block data size...
if (blocki >= Meta.DataBlocks.Count)
{ continue; }
var block = Meta.DataBlocks[blocki];
if ((offset < 0) || (block.Data == null) || (offset >= block.Data.Length))
{ continue; }
var ba = new Archetype();
switch (block.StructureNameHash)
{
case MetaName.CBaseArchetypeDef:
var basearch = PsoTypes.ConvertDataRaw<CBaseArchetypeDef>(block.Data, offset);
ba.Init(this, basearch);
ba.Extensions = MetaTypes.GetExtensions(Meta, basearch.extensions);
break;
case MetaName.CTimeArchetypeDef:
var timearch = PsoTypes.ConvertDataRaw<CTimeArchetypeDef>(block.Data, offset);
ba.Init(this, timearch);
ba.Extensions = MetaTypes.GetExtensions(Meta, timearch.CBaseArchetypeDef.extensions);
break;
case MetaName.CMloArchetypeDef:
var mloarch = PsoTypes.ConvertDataRaw<CMloArchetypeDef>(block.Data, offset);
ba.Init(this, mloarch);
ba.Extensions = MetaTypes.GetExtensions(Meta, mloarch.CBaseArchetypeDef.extensions);
MloArchetypeData mlod = new MloArchetypeData();
mlod.entities = MetaTypes.ConvertDataArray<CEntityDef>(Meta, MetaName.CEntityDef, mloarch.entities);
mlod.rooms = MetaTypes.ConvertDataArray<CMloRoomDef>(Meta, MetaName.CMloRoomDef, mloarch.rooms);
mlod.portals = MetaTypes.ConvertDataArray<CMloPortalDef>(Meta, MetaName.CMloPortalDef, mloarch.portals);
mlod.entitySets = MetaTypes.ConvertDataArray<CMloEntitySet>(Meta, MetaName.CMloEntitySet, mloarch.entitySets);
mlod.timeCycleModifiers = MetaTypes.ConvertDataArray<CMloTimeCycleModifier>(Meta, MetaName.CMloTimeCycleModifier, mloarch.timeCycleModifiers);
ba.MloData = mlod;
//if (mlod.entities != null)
//{
// for (int e = 0; e < mlod.entities.Length; e++)
// {
// EnsureEntityExtensions(Meta, ref mlod.entities[e]);
// }
//}
break;
default:
continue;
}
allarchs.Add(ba);
}
}
AllArchetypes = allarchs.ToArray();
Extensions = MetaTypes.GetExtensions(Meta, CMapTypes.extensions);
if (Extensions != null)
{ }
AudioEmitters = MetaTypes.GetTypedDataArray<CExtensionDefAudioEmitter>(Meta, MetaName.CExtensionDefAudioEmitter);
if (AudioEmitters != null)
{ }
//CEntityDefs = MetaTypes.GetTypedDataArray<CEntityDef>(Meta, MetaName.CEntityDef);
CompositeEntityTypes = MetaTypes.ConvertDataArray<CCompositeEntityType>(Meta, MetaName.CCompositeEntityType, CMapTypes.compositeEntityTypes);
if (CompositeEntityTypes != null)
{ }
NameHash = CMapTypes.name;
if (NameHash == 0)
{
int ind = entry.NameLower.LastIndexOf('.');
if (ind > 0)
{
NameHash = JenkHash.GenHash(entry.NameLower.Substring(0, ind));
}
else
{
NameHash = JenkHash.GenHash(entry.NameLower);
}
}
Strings = MetaTypes.GetStrings(Meta);
if (Strings != null)
{
foreach (string str in Strings)
{
JenkIndex.Ensure(str); //just shove them in there
}
}
foreach (var block in Meta.DataBlocks)
{
switch(block.StructureNameHash)
{
case MetaName.CMapTypes:
case MetaName.CTimeArchetypeDef:
case MetaName.CBaseArchetypeDef:
case MetaName.CMloArchetypeDef:
case MetaName.CMloTimeCycleModifier:
case MetaName.CMloRoomDef:
case MetaName.CMloPortalDef:
case MetaName.CMloEntitySet:
case MetaName.CEntityDef:
case MetaName.CExtensionDefParticleEffect:
case MetaName.CExtensionDefAudioCollisionSettings:
case MetaName.CExtensionDefSpawnPoint:
case MetaName.CExtensionDefSpawnPointOverride:
case MetaName.CExtensionDefExplosionEffect:
case MetaName.CExtensionDefAudioEmitter:
case MetaName.CExtensionDefLadder:
case MetaName.CExtensionDefBuoyancy:
case MetaName.CExtensionDefExpression:
case MetaName.CExtensionDefLightShaft:
case MetaName.CExtensionDefLightEffect:
case MetaName.CExtensionDefDoor:
case MetaName.CExtensionDefWindDisturbance:
case MetaName.CExtensionDefProcObject:
case MetaName.CLightAttrDef:
case MetaName.STRING:
//case MetaName.SectionUNKNOWN2:
//case MetaName.SectionUNKNOWN3:
//case MetaName.SectionUNKNOWN8:
case MetaName.POINTER:
case MetaName.UINT:
case MetaName.VECTOR4:
break;
default:
break;
}
}
//MetaTypes.ParseMetaData(Meta);
//RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
//if (resentry == null)
//{
// throw new Exception("File entry wasn't a resource! (is it binary data?)");
//}
//ResourceDataReader rd = new ResourceDataReader(resentry, data);
//Meta = rd.ReadBlock<Meta>();
//MetaTypes.EnsureMetaTypes(Meta);
//MetaTypes.ParseMetaData(Meta);
}
}
}
+54
View File
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YvrFile : GameFile, PackedFile
{
public VehicleRecordList Records { get; set; }
public YvrFile() : base(null, GameFileType.Yvr)
{
}
public YvrFile(RpfFileEntry entry) : base(entry, GameFileType.Yvr)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
//MemoryUsage = 0;
try
{
Records = rd.ReadBlock<VehicleRecordList>();
}
catch (Exception ex)
{
string err = ex.ToString();
}
Loaded = true;
}
}
}
+54
View File
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class YwrFile : GameFile, PackedFile
{
public WaypointRecordList Waypoints { get; set; }
public YwrFile() : base(null, GameFileType.Ywr)
{
}
public YwrFile(RpfFileEntry entry) : base(entry, GameFileType.Ywr)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
Name = entry.Name;
RpfFileEntry = entry;
RpfResourceFileEntry resentry = entry as RpfResourceFileEntry;
if (resentry == null)
{
throw new Exception("File entry wasn't a resource! (is it binary data?)");
}
ResourceDataReader rd = new ResourceDataReader(resentry, data);
//MemoryUsage = 0;
try
{
Waypoints = rd.ReadBlock<WaypointRecordList>();
}
catch (Exception ex)
{
string err = ex.ToString();
}
Loaded = true;
}
}
}