mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2025-01-10 07:42:56 +08:00
AWC research progress
This commit is contained in:
parent
6c1afda9a2
commit
cfa7243417
@ -6,6 +6,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TC = System.ComponentModel.TypeConverterAttribute;
|
||||
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
@ -17,16 +18,16 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public uint Magic { get; set; }
|
||||
public uint Magic { get; set; } = 0x54414441;
|
||||
public ushort Version { get; set; }
|
||||
public ushort Flags { get; set; }
|
||||
public ushort Flags { get; set; } = 0xFF00;
|
||||
public int StreamCount { get; set; }
|
||||
public int InfoOffset { get; set; }
|
||||
|
||||
public bool UnkUshortsFlag { get { return ((Flags & 1) == 1); } }
|
||||
public bool SingleChannelEncryptFlag { get { return ((Flags & 2) == 2); } }
|
||||
public bool MultiChannelFlag { get { return ((Flags & 4) == 4); } }
|
||||
public bool MultiChannelEncryptFlag { get { return ((Flags & 8) == 8); } }
|
||||
public bool UnkUshortsFlag { get { return ((Flags & 1) == 1); } set { Flags = (ushort)((Flags & 0xFFFE) + (value ? 1 : 0)); } }
|
||||
public bool SingleChannelEncryptFlag { get { return ((Flags & 2) == 2); } set { Flags = (ushort)((Flags & 0xFFFD) + (value ? 2 : 0)); } }
|
||||
public bool MultiChannelFlag { get { return ((Flags & 4) == 4); } set { Flags = (ushort)((Flags & 0xFFFB) + (value ? 4 : 0)); } }
|
||||
public bool MultiChannelEncryptFlag { get { return ((Flags & 8) == 8); } set { Flags = (ushort)((Flags & 0xFFF7) + (value ? 8 : 0)); } }
|
||||
|
||||
public ushort[] UnkUshorts { get; set; } //offsets of some sort?
|
||||
|
||||
@ -62,11 +63,6 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
public void Load(byte[] data, RpfFileEntry entry)
|
||||
{
|
||||
|
||||
//adapted from libertyV code
|
||||
|
||||
|
||||
//MemoryStream ms = new MemoryStream(data);
|
||||
Name = entry.Name;
|
||||
FileEntry = entry;
|
||||
Data = data;
|
||||
@ -111,63 +107,74 @@ namespace CodeWalker.GameFiles
|
||||
{
|
||||
DataReader r = new DataReader(ms, endianess);
|
||||
|
||||
Magic = r.ReadUInt32();
|
||||
Version = r.ReadUInt16();
|
||||
Flags = r.ReadUInt16();
|
||||
StreamCount = r.ReadInt32();
|
||||
InfoOffset = r.ReadInt32();
|
||||
|
||||
|
||||
if ((Flags >> 8) != 0xFF)
|
||||
{
|
||||
ErrorMessage = "Flags 0 not supported!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (UnkUshortsFlag)
|
||||
{
|
||||
UnkUshorts = new ushort[StreamCount]; //offsets of some sort?
|
||||
for (int i = 0; i < StreamCount; i++)
|
||||
{
|
||||
UnkUshorts[i] = r.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var infoStart = 16 + (UnkUshortsFlag ? (StreamCount * 2) : 0);
|
||||
if (ms.Position != infoStart)
|
||||
{ }//no hit
|
||||
ms.Position = infoStart;
|
||||
|
||||
|
||||
List<AwcStreamInfo> infos = new List<AwcStreamInfo>();
|
||||
Dictionary<uint, AwcStreamInfo> infoDict = new Dictionary<uint, AwcStreamInfo>();
|
||||
|
||||
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.ChunkCount; j++)
|
||||
{
|
||||
var chunk = new AwcChunkInfo(r);
|
||||
info.ChunkList.Add(chunk);
|
||||
info.ChunkDict[chunk.Tag] = chunk;
|
||||
}
|
||||
}
|
||||
|
||||
StreamInfos = infos.ToArray();
|
||||
|
||||
ReadAudios(r);
|
||||
|
||||
|
||||
Read(r);
|
||||
}
|
||||
}
|
||||
|
||||
private void Read(DataReader r)
|
||||
{
|
||||
Magic = r.ReadUInt32();
|
||||
Version = r.ReadUInt16();
|
||||
Flags = r.ReadUInt16();
|
||||
StreamCount = r.ReadInt32();
|
||||
InfoOffset = r.ReadInt32();
|
||||
|
||||
|
||||
if ((Flags >> 8) != 0xFF)
|
||||
{
|
||||
ErrorMessage = "Flags 0 not supported!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (UnkUshortsFlag)
|
||||
{
|
||||
UnkUshorts = new ushort[StreamCount]; //offsets of some sort?
|
||||
for (int i = 0; i < StreamCount; i++)
|
||||
{
|
||||
UnkUshorts[i] = r.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var infoStart = 16 + (UnkUshortsFlag ? (StreamCount * 2) : 0);
|
||||
if (r.Position != infoStart)
|
||||
{ }//no hit
|
||||
|
||||
|
||||
List<AwcStreamInfo> infos = new List<AwcStreamInfo>();
|
||||
Dictionary<uint, AwcStreamInfo> infoDict = new Dictionary<uint, AwcStreamInfo>();
|
||||
|
||||
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.ChunkCount; j++)
|
||||
{
|
||||
var chunk = new AwcChunkInfo(r);
|
||||
info.ChunkList.Add(chunk);
|
||||
info.ChunkDict[chunk.Tag] = chunk;
|
||||
}
|
||||
}
|
||||
StreamInfos = infos.ToArray();
|
||||
|
||||
|
||||
var infoOffset = infoStart + StreamCount * 4;
|
||||
foreach (var info in infos) infoOffset += (int)info.ChunkCount * 8;
|
||||
if (infoOffset != InfoOffset)
|
||||
{ }//no hit
|
||||
if (r.Position != InfoOffset)
|
||||
{ }//no hit
|
||||
|
||||
|
||||
ReadAudios(r);
|
||||
|
||||
}
|
||||
|
||||
private void ReadAudios(DataReader r)
|
||||
{
|
||||
|
||||
@ -185,6 +192,10 @@ namespace CodeWalker.GameFiles
|
||||
{
|
||||
var chunk = info.ChunkList[j];
|
||||
r.Position = chunk.Offset;
|
||||
|
||||
if ((chunk.Offset % 2) != 0)
|
||||
{ }
|
||||
|
||||
switch (chunk.Tag)
|
||||
{
|
||||
case 85: //data
|
||||
@ -197,29 +208,29 @@ namespace CodeWalker.GameFiles
|
||||
case 92: //animation - YCD resource chunk
|
||||
audio.ClipDict = new AwcAudioAnimClipDict(r, chunk);
|
||||
break;
|
||||
case 43: //unk2B
|
||||
audio.UnkData2B = new AwcAudioUnk(r, chunk);
|
||||
case 43: //0x2B
|
||||
audio.UnkData2B = new AwcAudioUnk2B(r, chunk);
|
||||
break;
|
||||
case 54: //unk36 - small number of bytes (2+)
|
||||
audio.UnkData36 = new AwcAudioUnk(r, chunk);
|
||||
case 54: //0x36 - peak
|
||||
audio.PeakData = new AwcAudioPeak(r, chunk);
|
||||
break;
|
||||
case 90: //unk5A
|
||||
audio.UnkData5A = new AwcAudioUnk(r, chunk);
|
||||
case 90: //0x5A
|
||||
audio.UnkData5A = new AwcAudioUnk5A(r, chunk);
|
||||
break;
|
||||
case 104://MIDI
|
||||
audio.MIDIData = new AwcAudioMIDI(r, chunk);
|
||||
break;
|
||||
case 217://unkD9 - length 200+
|
||||
audio.UnkDataD9 = new AwcAudioUnk(r, chunk);
|
||||
case 217://0xD9 - length 200+
|
||||
audio.UnkDataD9 = new AwcAudioUnkD9(r, chunk);
|
||||
break;
|
||||
case 72: //multi channel info
|
||||
audio.MultiChannelInfo = new AwcChannelBlockInfo(r);
|
||||
break;
|
||||
case 163://multi unkA3
|
||||
case 163://multi sample offsets
|
||||
audio.MultiChannelSampleOffsets = new AwcChannelOffsetsInfo(r, chunk);
|
||||
break;
|
||||
case 189://multi unkBD
|
||||
audio.UnkDataBD = new AwcAudioUnk(r, chunk);
|
||||
case 189://multi 0xBD - markers
|
||||
audio.MarkersData = new AwcAudioMarkers(r, chunk);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -310,6 +321,66 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
}
|
||||
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
//TODO
|
||||
return new byte[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void WriteXml(StringBuilder sb, int indent, string wavfolder)
|
||||
{
|
||||
//AwcXml.StringTag(sb, indent, "Name", AwcXml.XmlEscape(Name));
|
||||
AwcXml.ValueTag(sb, indent, "Version", Version.ToString());
|
||||
|
||||
|
||||
if (UnkUshorts != null)
|
||||
{
|
||||
AwcXml.WriteRawArray(sb, UnkUshorts, indent, "UnkUshorts", "", null, 32);
|
||||
}
|
||||
|
||||
}
|
||||
public void ReadXml(XmlNode node, string wavfolder)
|
||||
{
|
||||
//Name = Xml.GetChildInnerText(node, "Name");
|
||||
Version = (ushort)Xml.GetChildUIntAttribute(node, "Version");
|
||||
|
||||
|
||||
|
||||
var unode = node.SelectSingleNode("UnkUshorts");
|
||||
if (unode != null)
|
||||
{
|
||||
UnkUshorts = Xml.GetRawUshortArray(node);
|
||||
UnkUshortsFlag = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public static void WriteXmlNode(AwcFile f, StringBuilder sb, int indent, string wavfolder, string name = "AudioWaveContainer")
|
||||
{
|
||||
if (f == null) return;
|
||||
AwcXml.OpenTag(sb, indent, name);
|
||||
f.WriteXml(sb, indent + 1, wavfolder);
|
||||
AwcXml.CloseTag(sb, indent, name);
|
||||
}
|
||||
public static AwcFile ReadXmlNode(XmlNode node, string wavfolder)
|
||||
{
|
||||
if (node == null) return null;
|
||||
var f = new AwcFile();
|
||||
f.ReadXml(node, wavfolder);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public enum AwcCodecFormat
|
||||
@ -546,15 +617,15 @@ namespace CodeWalker.GameFiles
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public AwcAudioAnimClipDict ClipDict { get; set; }
|
||||
public AwcAudioUnk UnkData2B { get; set; }
|
||||
public AwcAudioUnk UnkData36 { get; set; }
|
||||
public AwcAudioUnk UnkData5A { get; set; }
|
||||
public AwcAudioUnk2B UnkData2B { get; set; }
|
||||
public AwcAudioPeak PeakData { get; set; }
|
||||
public AwcAudioUnk5A UnkData5A { get; set; }
|
||||
public AwcAudioMIDI MIDIData { get; set; }
|
||||
public AwcAudioUnk UnkDataD9 { get; set; }
|
||||
public AwcAudioUnkD9 UnkDataD9 { get; set; }
|
||||
public AwcChannelBlockInfo MultiChannelInfo { get; set; }
|
||||
public AwcChannelOffsetsInfo MultiChannelSampleOffsets { get; set; }
|
||||
public AwcChannelDataBlock[] MultiChannelBlocks { get; set; }
|
||||
public AwcAudioUnk UnkDataBD { get; set; }
|
||||
public AwcAudioMarkers MarkersData { get; set; }
|
||||
|
||||
public AwcAudio MultiChannelSource { get; set; }
|
||||
public AwcChannelBlockItemInfo MultiChannelFormat { get; set; }
|
||||
@ -843,15 +914,24 @@ namespace CodeWalker.GameFiles
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public class AwcAudioUnk
|
||||
[TC(typeof(EXP))] public class AwcAudioPeak
|
||||
{
|
||||
public AwcChunkInfo ChunkInfo { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
public ushort[] Data { get; set; }
|
||||
|
||||
public AwcAudioUnk(DataReader r, AwcChunkInfo info)
|
||||
public AwcAudioPeak(DataReader r, AwcChunkInfo info)
|
||||
{
|
||||
ChunkInfo = info;
|
||||
Data = r.ReadBytes(info.Size);
|
||||
|
||||
//if ((info.Size % 2) != 0)
|
||||
//{ }//no hit
|
||||
var count = info.Size / 2;
|
||||
Data = new ushort[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Data[i] = r.ReadUInt16();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@ -867,7 +947,337 @@ namespace CodeWalker.GameFiles
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TC(typeof(EXP))] public class AwcAudioUnk2B
|
||||
{
|
||||
public AwcChunkInfo ChunkInfo { get; set; }
|
||||
public Item[] Items { get; set; }
|
||||
|
||||
public class Item
|
||||
{
|
||||
public MetaHash Name { get; set; }
|
||||
public uint UnkUint1 { get; set; }
|
||||
public float UnkFloat1 { get; set; }
|
||||
public float UnkFloat2 { get; set; }
|
||||
public float UnkFloat3 { get; set; }
|
||||
public float UnkFloat4 { get; set; }
|
||||
public float UnkFloat5 { get; set; }
|
||||
public float UnkFloat6 { get; set; }
|
||||
public uint UnkUint2 { get; set; }
|
||||
|
||||
public Item(DataReader r)
|
||||
{
|
||||
Name = r.ReadUInt32();
|
||||
UnkUint1 = r.ReadUInt32();
|
||||
UnkFloat1 = r.ReadSingle();
|
||||
UnkFloat2 = r.ReadSingle();
|
||||
UnkFloat3 = r.ReadSingle();
|
||||
UnkFloat4 = r.ReadSingle();
|
||||
UnkFloat5 = r.ReadSingle();
|
||||
UnkFloat6 = r.ReadSingle();
|
||||
UnkUint2 = r.ReadUInt32();
|
||||
|
||||
//switch (Name)
|
||||
//{
|
||||
// case 0xceda50be: //
|
||||
// case 0x452c06fc: //
|
||||
// case 0xba377ce2: //
|
||||
// case 0xbe4c6d06: //
|
||||
// case 0x9db051b4: //
|
||||
// case 0x8a726e9f: //
|
||||
// case 0x1f60ea95: //
|
||||
// case 0x14e63a65: //
|
||||
// case 0x32b4abf4: //
|
||||
// case 0xe2b1dd62: //
|
||||
// case 0x482d3572: //
|
||||
// case 0x32f8d7a7: //
|
||||
// case 0x9144296b: //
|
||||
// case 0x3c73a8a4: //
|
||||
// case 0x057c10c5: //
|
||||
// case 0x981a4da0: //
|
||||
// case 0x519d5f74: //
|
||||
// case 0x0de43bc8: //
|
||||
// case 0x89c16359: //
|
||||
// case 0xd8884a6b: //
|
||||
// case 0xfec7eb20: //
|
||||
// case 0x06f0f709: //
|
||||
// case 0x788a8abd: //
|
||||
// break;
|
||||
// default:
|
||||
// break;//and more...
|
||||
//}
|
||||
|
||||
//switch (UnkUint2)
|
||||
//{
|
||||
// case 1:
|
||||
// case 0:
|
||||
// break;
|
||||
// default:
|
||||
// break;//no hit
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name.ToString() + ": " + UnkUint1.ToString() + ", " + UnkFloat1.ToString() + ", " + UnkFloat2.ToString() + ", " + UnkFloat3.ToString() + ", " + UnkFloat4.ToString() + ", " + UnkFloat5.ToString() + ", " + UnkFloat6.ToString() + ", " + UnkUint2.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public AwcAudioUnk2B(DataReader r, AwcChunkInfo info)
|
||||
{
|
||||
ChunkInfo = info;
|
||||
|
||||
// (hash, uint, 6x floats, uint) * n
|
||||
|
||||
//if ((info.Size % 36) != 0)
|
||||
//{ }//no hit
|
||||
var count = info.Size / 36;
|
||||
Items = new Item[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Items[i] = new Item(r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return (Items?.Length ?? 0).ToString() + " items";
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public class AwcAudioUnk5A
|
||||
{
|
||||
public AwcChunkInfo ChunkInfo { get; set; }
|
||||
public Item[] Items { get; set; }
|
||||
public float UnkFloat1 { get; set; }
|
||||
|
||||
public class Item
|
||||
{
|
||||
public uint UnkUint1 { get; set; }
|
||||
public float UnkFloat1 { get; set; }
|
||||
public ushort UnkUshort1 { get; set; }
|
||||
public ushort UnkUshort2 { get; set; }
|
||||
|
||||
public Item(DataReader r)
|
||||
{
|
||||
UnkUint1 = r.ReadUInt32();
|
||||
UnkFloat1 = r.ReadSingle();
|
||||
UnkUshort1 = r.ReadUInt16();
|
||||
UnkUshort2 = r.ReadUInt16();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return UnkUint1.ToString() + ", " + UnkFloat1.ToString() + ", " + UnkUshort1.ToString() + ", " + UnkUshort2.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public AwcAudioUnk5A(DataReader r, AwcChunkInfo info)
|
||||
{
|
||||
ChunkInfo = info;
|
||||
|
||||
//int, (2x floats, int) * n ?
|
||||
|
||||
//if ((info.Size % 12) != 4)
|
||||
//{ }//no hit
|
||||
var count = (info.Size - 4) / 12;
|
||||
Items = new Item[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Items[i] = new Item(r);
|
||||
}
|
||||
UnkFloat1 = r.ReadSingle();
|
||||
|
||||
//if (UnkFloat1 > 1.0f)
|
||||
//{ }//no hit
|
||||
//if (UnkFloat1 < 0.45833f)
|
||||
//{ }//no hit
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return (Items?.Length ?? 0).ToString() + " items";
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public class AwcAudioUnkD9
|
||||
{
|
||||
public AwcChunkInfo ChunkInfo { get; set; }
|
||||
public uint ItemCount { get; set; }
|
||||
public Item[] Items { get; set; }
|
||||
|
||||
public class Item
|
||||
{
|
||||
public uint UnkUint1 { get; set; } = 2;
|
||||
public uint ItemCount { get; set; }
|
||||
public MetaHash Hash { get; set; } = 0x4c633d07;
|
||||
public uint[] Items { get; set; }
|
||||
|
||||
public Item(DataReader r)
|
||||
{
|
||||
UnkUint1 = r.ReadUInt32();
|
||||
ItemCount = r.ReadUInt32();
|
||||
Hash = r.ReadUInt32();
|
||||
Items = new uint[ItemCount];
|
||||
for (int i = 0; i < ItemCount; i++)
|
||||
{
|
||||
Items[i] = r.ReadUInt32();
|
||||
}
|
||||
|
||||
switch (UnkUint1)
|
||||
{
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (Hash)
|
||||
{
|
||||
case 0x4c633d07:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Hash.ToString() + ": " + UnkUint1.ToString() + ": " + ItemCount.ToString() + " items";
|
||||
}
|
||||
}
|
||||
|
||||
public AwcAudioUnkD9(DataReader r, AwcChunkInfo info)
|
||||
{
|
||||
ChunkInfo = info;
|
||||
|
||||
|
||||
//uint count
|
||||
// [count*items]: uint(type?), uint(count2), hash, [count2*uint]
|
||||
|
||||
ItemCount = r.ReadUInt32();
|
||||
Items = new Item[ItemCount];
|
||||
for (int i = 0; i < ItemCount; i++)
|
||||
{
|
||||
Items[i] = new Item(r);
|
||||
}
|
||||
|
||||
////if ((info.Size % 4) != 0)
|
||||
////{ }//no hit
|
||||
//var count = info.Size / 4;
|
||||
//Data = new uint[count];
|
||||
//for (int i = 0; i < count; i++)
|
||||
//{
|
||||
// Data[i] = r.ReadUInt32();
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return (Items?.Length ?? 0).ToString() + " items";
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public class AwcAudioMarkers
|
||||
{
|
||||
public AwcChunkInfo ChunkInfo { get; set; }
|
||||
public Marker[] Markers { get; set; }
|
||||
|
||||
public class Marker
|
||||
{
|
||||
public MetaHash Name { get; set; }
|
||||
public MetaHash Value { get; set; }//usually a float, but in some cases a hash, or other value
|
||||
public uint SampleOffset { get; set; }
|
||||
public uint Unused { get; set; }
|
||||
|
||||
public Marker(DataReader r)
|
||||
{
|
||||
Name = r.ReadUInt32();
|
||||
Value = r.ReadUInt32();
|
||||
SampleOffset = r.ReadUInt32();
|
||||
Unused = r.ReadUInt32();
|
||||
|
||||
//switch (Name)
|
||||
//{
|
||||
// case 0:
|
||||
// case 0xa6d93246: // trackid
|
||||
// case 0xe89ae78c: // beat
|
||||
// case 0xf31b4f6a: // rockout
|
||||
// case 0x08dba0f8: // dj
|
||||
// case 0x7a495db3: // tempo
|
||||
// case 0x14d857be: // g_s
|
||||
// break;
|
||||
// case 0xcd171e55: //
|
||||
// case 0x806b80c9: // 1
|
||||
// case 0x91aa2346: // 2
|
||||
// case 0x11976678: // r_p
|
||||
// case 0x91be54cb: //
|
||||
// case 0xab2238c0: //
|
||||
// case 0xdb599288: //
|
||||
// case 0x2ce40eb5: //
|
||||
// case 0xa35e1092: // 01
|
||||
// case 0x1332b405: // tank_jump
|
||||
// case 0x2b20b891: //
|
||||
// case 0x8aa726e7: // tank_jump_land
|
||||
// case 0xe0bfba99: // tank_turret_move
|
||||
// case 0x1d91339e: //
|
||||
// case 0xa5344b07: //
|
||||
// case 0x7a7cba39: // tank_weapon_main_cannon_hit
|
||||
// case 0xd66a90c3: //
|
||||
// case 0x1fd18857: // 14
|
||||
// case 0x65a52c67: //
|
||||
// case 0xd8846402: // uihit
|
||||
// case 0x8958bce4: // m_p
|
||||
// if (Value != 0)
|
||||
// { }//no hit
|
||||
// break;
|
||||
// default:
|
||||
// break;//no hit
|
||||
//}
|
||||
|
||||
//if (Unused != 0)
|
||||
//{ }//no hit
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var valstr = Value.Float.ToString();
|
||||
switch (Name)
|
||||
{
|
||||
case 0xf31b4f6a: // rockout
|
||||
case 0x08dba0f8: // dj
|
||||
case 0x14d857be: // g_s
|
||||
valstr = Value.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
return Name.ToString() + ": " + valstr + ", " + SampleOffset.ToString() + ", " + Unused.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AwcAudioMarkers(DataReader r, AwcChunkInfo info)
|
||||
{
|
||||
ChunkInfo = info;
|
||||
|
||||
//if ((info.Size % 16) != 0)
|
||||
//{ }//no hit
|
||||
var count = info.Size / 16;
|
||||
Markers = new Marker[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Markers[i] = new Marker(r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return (Markers?.Length ?? 0).ToString() + " markers";
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public class AwcAudioMIDI
|
||||
{
|
||||
public AwcChunkInfo ChunkInfo { get; set; }
|
||||
@ -893,10 +1303,10 @@ namespace CodeWalker.GameFiles
|
||||
public AwcChannelOffsetsInfo(DataReader r, AwcChunkInfo info)
|
||||
{
|
||||
ChunkInfo = info;
|
||||
|
||||
//if ((info.Size % 4) != 0)
|
||||
//{ }//no hit
|
||||
var count = info.Size / 4;
|
||||
var rem = info.Size % 4;
|
||||
if (rem != 0)
|
||||
{ }
|
||||
SampleOffsets = new uint[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
@ -1013,9 +1423,6 @@ namespace CodeWalker.GameFiles
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class ADPCMCodec
|
||||
{
|
||||
|
||||
@ -1175,4 +1582,56 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class AwcXml : MetaXmlBase
|
||||
{
|
||||
|
||||
public static string GetXml(AwcFile awc, string outputFolder = "")
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine(XmlHeader);
|
||||
|
||||
if (awc != null)
|
||||
{
|
||||
AwcFile.WriteXmlNode(awc, sb, 0, outputFolder);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class XmlAwc
|
||||
{
|
||||
|
||||
public static AwcFile AwcYft(string xml, string inputFolder = "")
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(xml);
|
||||
return GetAwc(doc, inputFolder);
|
||||
}
|
||||
|
||||
public static AwcFile GetAwc(XmlDocument doc, string inputFolder = "")
|
||||
{
|
||||
AwcFile r = null;
|
||||
|
||||
var node = doc.DocumentElement;
|
||||
if (node != null)
|
||||
{
|
||||
r = AwcFile.ReadXmlNode(node, inputFolder);
|
||||
}
|
||||
|
||||
r.Name = Path.GetFileName(inputFolder);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -3888,6 +3888,20 @@ namespace CodeWalker.GameFiles
|
||||
camerashrink = 2170767496,
|
||||
|
||||
|
||||
//AWC markers names from Siprus
|
||||
tank_jump = 322089989,
|
||||
tank_weapon_main_cannon_hit = 2054994489,
|
||||
tank_jump_land = 2326210279,
|
||||
tank_turret_move = 3770661529,
|
||||
tempo = 2051628467,
|
||||
beat = 3902465932,
|
||||
dj = 148611320,
|
||||
//01 = 2740850834,//this one added in RpfManager.BuildBaseJenkIndex
|
||||
rockout = 4078653290,
|
||||
uihit = 3632555010,//is this right?
|
||||
r_p = 295134840,//is this right?
|
||||
g_s = 349722558,//is this right?
|
||||
m_p = 2304294116,//is this right?
|
||||
|
||||
|
||||
|
||||
|
@ -102,6 +102,11 @@ namespace CodeWalker.GameFiles
|
||||
YldFile yld = RpfFile.GetFile<YldFile>(e, data);
|
||||
return GetXml(yld, out filename, outputfolder);
|
||||
}
|
||||
else if (fnl.EndsWith(".awc"))
|
||||
{
|
||||
AwcFile awc = RpfFile.GetFile<AwcFile>(e, data);
|
||||
return GetXml(awc, out filename, outputfolder);
|
||||
}
|
||||
filename = fn;
|
||||
return string.Empty;
|
||||
}
|
||||
@ -215,6 +220,12 @@ namespace CodeWalker.GameFiles
|
||||
filename = fn + ".xml";
|
||||
return YldXml.GetXml(yld, outputfolder);
|
||||
}
|
||||
public static string GetXml(AwcFile awc, out string filename, string outputfolder)
|
||||
{
|
||||
var fn = (awc?.Name) ?? "";
|
||||
filename = fn + ".xml";
|
||||
return AwcXml.GetXml(awc, outputfolder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2122,6 +2133,7 @@ namespace CodeWalker.GameFiles
|
||||
Yft = 12,
|
||||
Ypt = 13,
|
||||
Yld = 14,
|
||||
Awc = 15,
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -490,6 +490,11 @@ namespace CodeWalker.GameFiles
|
||||
//failing silently!! not so good really
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
JenkIndex.Ensure(i.ToString("00"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ namespace CodeWalker
|
||||
InitFileType(".ytyp", "Archetype Definitions", 20, FileTypeAction.ViewYtyp, true);
|
||||
InitFileType(".ymap", "Map Data", 21, FileTypeAction.ViewYmap, true);
|
||||
InitFileType(".ipl", "Item Placements", 21, FileTypeAction.ViewText);
|
||||
InitFileType(".awc", "Audio Wave Container", 22, FileTypeAction.ViewAwc);
|
||||
InitFileType(".awc", "Audio Wave Container", 22, FileTypeAction.ViewAwc, true);
|
||||
InitFileType(".rel", "Audio Data (REL)", 23, FileTypeAction.ViewRel, true);
|
||||
|
||||
InitSubFileType(".dat", "cache_y.dat", "Cache File", 6, FileTypeAction.ViewCacheDat);
|
||||
@ -1919,7 +1919,7 @@ namespace CodeWalker
|
||||
var nl = file?.File?.NameLower;
|
||||
if (!string.IsNullOrEmpty(nl))
|
||||
{
|
||||
needfolder = nl.EndsWith(".ytd") || nl.EndsWith(".ydr") || nl.EndsWith(".ydd") || nl.EndsWith(".yft") || nl.EndsWith(".ypt");
|
||||
needfolder = nl.EndsWith(".ytd") || nl.EndsWith(".ydr") || nl.EndsWith(".ydd") || nl.EndsWith(".yft") || nl.EndsWith(".ypt") || nl.EndsWith(".awc");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2494,6 +2494,10 @@ namespace CodeWalker
|
||||
{
|
||||
mformat = MetaFormat.Yld;
|
||||
}
|
||||
if (fnamel.EndsWith(".awc.xml"))
|
||||
{
|
||||
mformat = MetaFormat.Awc;
|
||||
}
|
||||
|
||||
fname = fname.Substring(0, fname.Length - trimlength);
|
||||
fnamel = fnamel.Substring(0, fnamel.Length - trimlength);
|
||||
@ -2654,6 +2658,17 @@ namespace CodeWalker
|
||||
data = yld.Save();
|
||||
break;
|
||||
}
|
||||
case MetaFormat.Awc:
|
||||
{
|
||||
var awc = XmlAwc.GetAwc(doc, fpathin);
|
||||
if (awc.Audios == null)
|
||||
{
|
||||
MessageBox.Show(fname + ": Schema not supported.", "Cannot import AWC XML");
|
||||
continue;
|
||||
}
|
||||
data = awc.Save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user