mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-17 12:32:54 +08:00
theme commit
This commit is contained in:
parent
79a9cf1eb6
commit
bc3c6c02b0
96
AboutForm.Designer.cs
generated
Normal file
96
AboutForm.Designer.cs
generated
Normal file
@ -0,0 +1,96 @@
|
||||
namespace CodeWalker
|
||||
{
|
||||
partial class AboutForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm));
|
||||
this.OkButton = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// OkButton
|
||||
//
|
||||
this.OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.OkButton.Location = new System.Drawing.Point(317, 173);
|
||||
this.OkButton.Name = "OkButton";
|
||||
this.OkButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.OkButton.TabIndex = 0;
|
||||
this.OkButton.Text = "Ok";
|
||||
this.OkButton.UseVisualStyleBackColor = true;
|
||||
this.OkButton.Click += new System.EventHandler(this.OkButton_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.label1.Location = new System.Drawing.Point(12, 35);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(380, 164);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = resources.GetString("label1.Text");
|
||||
this.label1.TextAlign = System.Drawing.ContentAlignment.TopCenter;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label2.Location = new System.Drawing.Point(12, 9);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(380, 26);
|
||||
this.label2.TabIndex = 2;
|
||||
this.label2.Text = "CodeWalker by dexyfex";
|
||||
this.label2.TextAlign = System.Drawing.ContentAlignment.TopCenter;
|
||||
//
|
||||
// AboutForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(404, 208);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.OkButton);
|
||||
this.Controls.Add(this.label1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "AboutForm";
|
||||
this.Text = "About CodeWalker by dexyfex";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button OkButton;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
}
|
||||
}
|
25
AboutForm.cs
Normal file
25
AboutForm.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
public partial class AboutForm : Form
|
||||
{
|
||||
public AboutForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
419
AboutForm.resx
Normal file
419
AboutForm.resx
Normal file
@ -0,0 +1,419 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="label1.Text" xml:space="preserve">
|
||||
<value>A tool for visualising data pertaining to the search for the next paradigm.
|
||||
|
||||
Special thanks to:
|
||||
|
||||
-- Neodymium -- tgascoigne -- CamxxCore --
|
||||
-- Tadden -- Gramz -- Kai -- Vertigo -- HL -- Pouaichh --
|
||||
-- Dilapidated -- dav90 -- Neos7 -- Jevi -- sollaholla --
|
||||
-- The .White team -- CP -- Kilian -- PNWParksFan --</value>
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v//
|
||||
/////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO
|
||||
6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f//
|
||||
/wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA
|
||||
AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc
|
||||
skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU
|
||||
0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq
|
||||
+ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz
|
||||
/eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR
|
||||
p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm
|
||||
+P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB
|
||||
AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/
|
||||
/f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/
|
||||
+fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd
|
||||
4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
|
||||
1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2OL+NjZ7AAArX2Ok
|
||||
4uz/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
|
||||
2eP/LjJ1DAxKfYTE4Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//v7//f7//f7//v7//v//
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
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
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/
|
||||
/P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/
|
||||
/f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
|
||||
///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB///////
|
||||
//AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA
|
||||
H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A
|
||||
A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA
|
||||
/f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A
|
||||
AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf
|
||||
AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4
|
||||
AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A//
|
||||
///////gD/////////Af//////////////8=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
207
App.config
Normal file
207
App.config
Normal file
@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="CodeWalker.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>
|
||||
<userSettings>
|
||||
<CodeWalker.Properties.Settings>
|
||||
<setting name="Key" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="GTAFolder" serializeAs="String">
|
||||
<value>C:\Program Files (x86)\Steam\SteamApps\common\Grand Theft Auto V</value>
|
||||
</setting>
|
||||
<setting name="CompiledScriptFolder" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="DecompiledScriptFolder" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="GTAExeDumpFile" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="ExtractedTexturesFolder" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="ExtractedRawFilesFolder" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="ExtractedShadersFolder" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="FullScreen" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="Wireframe" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="Skydome" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="ShowTimedEntities" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="ShowCollisionMeshes" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="CollisionMeshRange" serializeAs="String">
|
||||
<value>4</value>
|
||||
</setting>
|
||||
<setting name="DynamicLOD" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="DetailDist" serializeAs="String">
|
||||
<value>5</value>
|
||||
</setting>
|
||||
<setting name="MarkerStyle" serializeAs="String">
|
||||
<value>Glokon Marker</value>
|
||||
</setting>
|
||||
<setting name="LocatorStyle" serializeAs="String">
|
||||
<value>Glokon Debug</value>
|
||||
</setting>
|
||||
<setting name="MarkerDepthClip" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="BoundsStyle" serializeAs="String">
|
||||
<value>None</value>
|
||||
</setting>
|
||||
<setting name="BoundsDepthClip" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="BoundsRange" serializeAs="String">
|
||||
<value>100</value>
|
||||
</setting>
|
||||
<setting name="ShowErrorConsole" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="Shadows" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="ShadowCascades" serializeAs="String">
|
||||
<value>6</value>
|
||||
</setting>
|
||||
<setting name="Grass" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="ShowStatusBar" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="WaitForChildren" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="CacheSize" serializeAs="String">
|
||||
<value>2147483648</value>
|
||||
</setting>
|
||||
<setting name="CacheTime" serializeAs="String">
|
||||
<value>10</value>
|
||||
</setting>
|
||||
<setting name="GPUGeometryCacheSize" serializeAs="String">
|
||||
<value>536870912</value>
|
||||
</setting>
|
||||
<setting name="GPUTextureCacheSize" serializeAs="String">
|
||||
<value>1073741824</value>
|
||||
</setting>
|
||||
<setting name="GPUBoundCompCacheSize" serializeAs="String">
|
||||
<value>134217728</value>
|
||||
</setting>
|
||||
<setting name="GPUCacheTime" serializeAs="String">
|
||||
<value>1</value>
|
||||
</setting>
|
||||
<setting name="GPUCacheFlushTime" serializeAs="String">
|
||||
<value>0.1</value>
|
||||
</setting>
|
||||
<setting name="CameraSmoothing" serializeAs="String">
|
||||
<value>10</value>
|
||||
</setting>
|
||||
<setting name="CameraSensitivity" serializeAs="String">
|
||||
<value>0.005</value>
|
||||
</setting>
|
||||
<setting name="CameraFieldOfView" serializeAs="String">
|
||||
<value>1</value>
|
||||
</setting>
|
||||
<setting name="RenderMode" serializeAs="String">
|
||||
<value>Default</value>
|
||||
</setting>
|
||||
<setting name="RenderTextureSampler" serializeAs="String">
|
||||
<value>DiffuseSampler</value>
|
||||
</setting>
|
||||
<setting name="RenderTextureSamplerCoord" serializeAs="String">
|
||||
<value>Texture coord 1</value>
|
||||
</setting>
|
||||
<setting name="ExcludeFolders" serializeAs="String">
|
||||
<value>Installers;_CommonRedist</value>
|
||||
</setting>
|
||||
<setting name="AnisotropicFiltering" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="HDR" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="WindowMaximized" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="EnableMods" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="DLC" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="KeyBindings" serializeAs="Xml">
|
||||
<value>
|
||||
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<string>Move Forwards: W</string>
|
||||
<string>Move Backwards: S</string>
|
||||
<string>Move Left: A</string>
|
||||
<string>Move Right: D</string>
|
||||
<string>Move Up: R</string>
|
||||
<string>Move Down: F</string>
|
||||
<string>Move Slower / Zoom In: Z</string>
|
||||
<string>Move Faster / Zoom Out: X</string>
|
||||
<string>Toggle Mouse Select: C</string>
|
||||
<string>Toggle Toolbar: T</string>
|
||||
<string>Exit Edit Mode: Q</string>
|
||||
<string>Edit Position: W</string>
|
||||
<string>Edit Rotation: E</string>
|
||||
<string>Edit Scale: R</string>
|
||||
</ArrayOfString>
|
||||
</value>
|
||||
</setting>
|
||||
<setting name="XInputLThumbInvert" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="XInputRThumbInvert" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="XInputLThumbSensitivity" serializeAs="String">
|
||||
<value>2</value>
|
||||
</setting>
|
||||
<setting name="XInputRThumbSensitivity" serializeAs="String">
|
||||
<value>2</value>
|
||||
</setting>
|
||||
<setting name="XInputZoomSpeed" serializeAs="String">
|
||||
<value>2</value>
|
||||
</setting>
|
||||
<setting name="XInputMoveSpeed" serializeAs="String">
|
||||
<value>15</value>
|
||||
</setting>
|
||||
<setting name="MouseInvert" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="RememberGTAFolder" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="ProjectWindowTheme" serializeAs="String">
|
||||
<value>Blue</value>
|
||||
</setting>
|
||||
<setting name="ExplorerWindowTheme" serializeAs="String">
|
||||
<value>Windows</value>
|
||||
</setting>
|
||||
</CodeWalker.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
625
BinarySearchForm.Designer.cs
generated
Normal file
625
BinarySearchForm.Designer.cs
generated
Normal file
@ -0,0 +1,625 @@
|
||||
namespace CodeWalker
|
||||
{
|
||||
partial class BinarySearchForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BinarySearchForm));
|
||||
this.FileSearchTextRadio = new System.Windows.Forms.RadioButton();
|
||||
this.FileSearchHexRadio = new System.Windows.Forms.RadioButton();
|
||||
this.FileSearchAbortButton = new System.Windows.Forms.Button();
|
||||
this.FileSearchResultsTextBox = new System.Windows.Forms.TextBox();
|
||||
this.FileSearchTextBox = new System.Windows.Forms.TextBox();
|
||||
this.FileSearchFolderBrowseButton = new System.Windows.Forms.Button();
|
||||
this.FileSearchButton = new System.Windows.Forms.Button();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.FileSearchFolderTextBox = new System.Windows.Forms.TextBox();
|
||||
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
|
||||
this.MainTabControl = new System.Windows.Forms.TabControl();
|
||||
this.SearchRPFTabPage = new System.Windows.Forms.TabPage();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.RpfSearchOnlyTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RpfSearchOnlyCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.RpfSearchSaveResultsButton = new System.Windows.Forms.Button();
|
||||
this.RpfSearchIgnoreTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RpfSearchIgnoreCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.RpfSearchBothDirectionsCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.RpfSearchCaseSensitiveCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.RpfSearchHexRadioButton = new System.Windows.Forms.RadioButton();
|
||||
this.RpfSearchTextRadioButton = new System.Windows.Forms.RadioButton();
|
||||
this.RpfSearchResultsListView = new System.Windows.Forms.ListView();
|
||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.RpfSearchAbortButton = new System.Windows.Forms.Button();
|
||||
this.RpfSearchButton = new System.Windows.Forms.Button();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.RpfSearchTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ExportCompressCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ExportButton = new System.Windows.Forms.Button();
|
||||
this.FileInfoLabel = new System.Windows.Forms.Label();
|
||||
this.ShowLargeFileContentsCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.DataHexLineCombo = new System.Windows.Forms.ComboBox();
|
||||
this.DataTextRadio = new System.Windows.Forms.RadioButton();
|
||||
this.DataHexRadio = new System.Windows.Forms.RadioButton();
|
||||
this.DataTextBox = new System.Windows.Forms.TextBox();
|
||||
this.SearchFileSystemTab = new System.Windows.Forms.TabPage();
|
||||
this.FileSearchPanel = new System.Windows.Forms.Panel();
|
||||
this.MainStatusStrip = new System.Windows.Forms.StatusStrip();
|
||||
this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||
this.MainTabControl.SuspendLayout();
|
||||
this.SearchRPFTabPage.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.SearchFileSystemTab.SuspendLayout();
|
||||
this.FileSearchPanel.SuspendLayout();
|
||||
this.MainStatusStrip.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// FileSearchTextRadio
|
||||
//
|
||||
this.FileSearchTextRadio.AutoSize = true;
|
||||
this.FileSearchTextRadio.Location = new System.Drawing.Point(162, 30);
|
||||
this.FileSearchTextRadio.Name = "FileSearchTextRadio";
|
||||
this.FileSearchTextRadio.Size = new System.Drawing.Size(48, 19);
|
||||
this.FileSearchTextRadio.TabIndex = 45;
|
||||
this.FileSearchTextRadio.Text = "Text";
|
||||
this.FileSearchTextRadio.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// FileSearchHexRadio
|
||||
//
|
||||
this.FileSearchHexRadio.AutoSize = true;
|
||||
this.FileSearchHexRadio.Checked = true;
|
||||
this.FileSearchHexRadio.Location = new System.Drawing.Point(112, 30);
|
||||
this.FileSearchHexRadio.Name = "FileSearchHexRadio";
|
||||
this.FileSearchHexRadio.Size = new System.Drawing.Size(47, 19);
|
||||
this.FileSearchHexRadio.TabIndex = 44;
|
||||
this.FileSearchHexRadio.TabStop = true;
|
||||
this.FileSearchHexRadio.Text = "Hex";
|
||||
this.FileSearchHexRadio.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// FileSearchAbortButton
|
||||
//
|
||||
this.FileSearchAbortButton.Location = new System.Drawing.Point(420, 27);
|
||||
this.FileSearchAbortButton.Name = "FileSearchAbortButton";
|
||||
this.FileSearchAbortButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.FileSearchAbortButton.TabIndex = 43;
|
||||
this.FileSearchAbortButton.Text = "Abort";
|
||||
this.FileSearchAbortButton.UseVisualStyleBackColor = true;
|
||||
this.FileSearchAbortButton.Click += new System.EventHandler(this.FileSearchAbortButton_Click);
|
||||
//
|
||||
// FileSearchResultsTextBox
|
||||
//
|
||||
this.FileSearchResultsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.FileSearchResultsTextBox.Location = new System.Drawing.Point(85, 78);
|
||||
this.FileSearchResultsTextBox.Multiline = true;
|
||||
this.FileSearchResultsTextBox.Name = "FileSearchResultsTextBox";
|
||||
this.FileSearchResultsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.FileSearchResultsTextBox.Size = new System.Drawing.Size(685, 403);
|
||||
this.FileSearchResultsTextBox.TabIndex = 42;
|
||||
this.FileSearchResultsTextBox.WordWrap = false;
|
||||
//
|
||||
// FileSearchTextBox
|
||||
//
|
||||
this.FileSearchTextBox.Location = new System.Drawing.Point(214, 29);
|
||||
this.FileSearchTextBox.Name = "FileSearchTextBox";
|
||||
this.FileSearchTextBox.Size = new System.Drawing.Size(119, 20);
|
||||
this.FileSearchTextBox.TabIndex = 41;
|
||||
this.FileSearchTextBox.Text = "4a03746e";
|
||||
//
|
||||
// FileSearchFolderBrowseButton
|
||||
//
|
||||
this.FileSearchFolderBrowseButton.Location = new System.Drawing.Point(339, 1);
|
||||
this.FileSearchFolderBrowseButton.Name = "FileSearchFolderBrowseButton";
|
||||
this.FileSearchFolderBrowseButton.Size = new System.Drawing.Size(27, 23);
|
||||
this.FileSearchFolderBrowseButton.TabIndex = 40;
|
||||
this.FileSearchFolderBrowseButton.Text = "...";
|
||||
this.FileSearchFolderBrowseButton.UseVisualStyleBackColor = true;
|
||||
this.FileSearchFolderBrowseButton.Click += new System.EventHandler(this.FileSearchFolderBrowseButton_Click);
|
||||
//
|
||||
// FileSearchButton
|
||||
//
|
||||
this.FileSearchButton.Location = new System.Drawing.Point(339, 27);
|
||||
this.FileSearchButton.Name = "FileSearchButton";
|
||||
this.FileSearchButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.FileSearchButton.TabIndex = 39;
|
||||
this.FileSearchButton.Text = "Search";
|
||||
this.FileSearchButton.UseVisualStyleBackColor = true;
|
||||
this.FileSearchButton.Click += new System.EventHandler(this.FileSearchButton_Click);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(3, 6);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(83, 15);
|
||||
this.label2.TabIndex = 38;
|
||||
this.label2.Text = "Search folder:";
|
||||
//
|
||||
// FileSearchFolderTextBox
|
||||
//
|
||||
this.FileSearchFolderTextBox.Location = new System.Drawing.Point(82, 3);
|
||||
this.FileSearchFolderTextBox.Name = "FileSearchFolderTextBox";
|
||||
this.FileSearchFolderTextBox.Size = new System.Drawing.Size(251, 20);
|
||||
this.FileSearchFolderTextBox.TabIndex = 37;
|
||||
this.FileSearchFolderTextBox.Text = "Compiled944";
|
||||
//
|
||||
// MainTabControl
|
||||
//
|
||||
this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.MainTabControl.Controls.Add(this.SearchRPFTabPage);
|
||||
this.MainTabControl.Controls.Add(this.SearchFileSystemTab);
|
||||
this.MainTabControl.Location = new System.Drawing.Point(3, 5);
|
||||
this.MainTabControl.Name = "MainTabControl";
|
||||
this.MainTabControl.SelectedIndex = 0;
|
||||
this.MainTabControl.Size = new System.Drawing.Size(846, 525);
|
||||
this.MainTabControl.TabIndex = 46;
|
||||
//
|
||||
// SearchRPFTabPage
|
||||
//
|
||||
this.SearchRPFTabPage.Controls.Add(this.splitContainer1);
|
||||
this.SearchRPFTabPage.Location = new System.Drawing.Point(4, 22);
|
||||
this.SearchRPFTabPage.Name = "SearchRPFTabPage";
|
||||
this.SearchRPFTabPage.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.SearchRPFTabPage.Size = new System.Drawing.Size(838, 499);
|
||||
this.SearchRPFTabPage.TabIndex = 0;
|
||||
this.SearchRPFTabPage.Text = "Search RPF contents";
|
||||
this.SearchRPFTabPage.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(3, 3);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchOnlyTextBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchOnlyCheckBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchSaveResultsButton);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchIgnoreTextBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchIgnoreCheckBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchBothDirectionsCheckBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchCaseSensitiveCheckBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchHexRadioButton);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchTextRadioButton);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchResultsListView);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchAbortButton);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchButton);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.label3);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.RpfSearchTextBox);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.ExportCompressCheckBox);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.ExportButton);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.FileInfoLabel);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.ShowLargeFileContentsCheckBox);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.DataHexLineCombo);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.DataTextRadio);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.DataHexRadio);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.DataTextBox);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(832, 493);
|
||||
this.splitContainer1.SplitterDistance = 270;
|
||||
this.splitContainer1.TabIndex = 1;
|
||||
//
|
||||
// RpfSearchOnlyTextBox
|
||||
//
|
||||
this.RpfSearchOnlyTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.RpfSearchOnlyTextBox.Enabled = false;
|
||||
this.RpfSearchOnlyTextBox.Location = new System.Drawing.Point(68, 92);
|
||||
this.RpfSearchOnlyTextBox.Name = "RpfSearchOnlyTextBox";
|
||||
this.RpfSearchOnlyTextBox.Size = new System.Drawing.Size(198, 20);
|
||||
this.RpfSearchOnlyTextBox.TabIndex = 66;
|
||||
this.RpfSearchOnlyTextBox.Text = ".ysc, .rel";
|
||||
//
|
||||
// RpfSearchOnlyCheckBox
|
||||
//
|
||||
this.RpfSearchOnlyCheckBox.AutoSize = true;
|
||||
this.RpfSearchOnlyCheckBox.Location = new System.Drawing.Point(9, 94);
|
||||
this.RpfSearchOnlyCheckBox.Name = "RpfSearchOnlyCheckBox";
|
||||
this.RpfSearchOnlyCheckBox.Size = new System.Drawing.Size(53, 19);
|
||||
this.RpfSearchOnlyCheckBox.TabIndex = 65;
|
||||
this.RpfSearchOnlyCheckBox.Text = "Only:";
|
||||
this.RpfSearchOnlyCheckBox.UseVisualStyleBackColor = true;
|
||||
this.RpfSearchOnlyCheckBox.CheckedChanged += new System.EventHandler(this.RpfSearchOnlyCheckBox_CheckedChanged);
|
||||
//
|
||||
// RpfSearchSaveResultsButton
|
||||
//
|
||||
this.RpfSearchSaveResultsButton.Enabled = false;
|
||||
this.RpfSearchSaveResultsButton.Location = new System.Drawing.Point(181, 118);
|
||||
this.RpfSearchSaveResultsButton.Name = "RpfSearchSaveResultsButton";
|
||||
this.RpfSearchSaveResultsButton.Size = new System.Drawing.Size(86, 22);
|
||||
this.RpfSearchSaveResultsButton.TabIndex = 62;
|
||||
this.RpfSearchSaveResultsButton.Text = "Save results...";
|
||||
this.RpfSearchSaveResultsButton.UseVisualStyleBackColor = true;
|
||||
this.RpfSearchSaveResultsButton.Click += new System.EventHandler(this.RpfSearchSaveResultsButton_Click);
|
||||
//
|
||||
// RpfSearchIgnoreTextBox
|
||||
//
|
||||
this.RpfSearchIgnoreTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.RpfSearchIgnoreTextBox.Location = new System.Drawing.Point(68, 68);
|
||||
this.RpfSearchIgnoreTextBox.Name = "RpfSearchIgnoreTextBox";
|
||||
this.RpfSearchIgnoreTextBox.Size = new System.Drawing.Size(198, 20);
|
||||
this.RpfSearchIgnoreTextBox.TabIndex = 59;
|
||||
this.RpfSearchIgnoreTextBox.Text = ".ydr, .ydd, .ytd, .yft, .ybn, .ycd, .awc, .bik";
|
||||
//
|
||||
// RpfSearchIgnoreCheckBox
|
||||
//
|
||||
this.RpfSearchIgnoreCheckBox.AutoSize = true;
|
||||
this.RpfSearchIgnoreCheckBox.Checked = true;
|
||||
this.RpfSearchIgnoreCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.RpfSearchIgnoreCheckBox.Location = new System.Drawing.Point(9, 70);
|
||||
this.RpfSearchIgnoreCheckBox.Name = "RpfSearchIgnoreCheckBox";
|
||||
this.RpfSearchIgnoreCheckBox.Size = new System.Drawing.Size(64, 19);
|
||||
this.RpfSearchIgnoreCheckBox.TabIndex = 58;
|
||||
this.RpfSearchIgnoreCheckBox.Text = "Ignore:";
|
||||
this.RpfSearchIgnoreCheckBox.UseVisualStyleBackColor = true;
|
||||
this.RpfSearchIgnoreCheckBox.CheckedChanged += new System.EventHandler(this.RpfSearchIgnoreCheckBox_CheckedChanged);
|
||||
//
|
||||
// RpfSearchBothDirectionsCheckBox
|
||||
//
|
||||
this.RpfSearchBothDirectionsCheckBox.AutoSize = true;
|
||||
this.RpfSearchBothDirectionsCheckBox.Checked = true;
|
||||
this.RpfSearchBothDirectionsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.RpfSearchBothDirectionsCheckBox.Location = new System.Drawing.Point(109, 48);
|
||||
this.RpfSearchBothDirectionsCheckBox.Name = "RpfSearchBothDirectionsCheckBox";
|
||||
this.RpfSearchBothDirectionsCheckBox.Size = new System.Drawing.Size(107, 19);
|
||||
this.RpfSearchBothDirectionsCheckBox.TabIndex = 57;
|
||||
this.RpfSearchBothDirectionsCheckBox.Text = "Both directions";
|
||||
this.RpfSearchBothDirectionsCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// RpfSearchCaseSensitiveCheckBox
|
||||
//
|
||||
this.RpfSearchCaseSensitiveCheckBox.AutoSize = true;
|
||||
this.RpfSearchCaseSensitiveCheckBox.Location = new System.Drawing.Point(9, 48);
|
||||
this.RpfSearchCaseSensitiveCheckBox.Name = "RpfSearchCaseSensitiveCheckBox";
|
||||
this.RpfSearchCaseSensitiveCheckBox.Size = new System.Drawing.Size(105, 19);
|
||||
this.RpfSearchCaseSensitiveCheckBox.TabIndex = 56;
|
||||
this.RpfSearchCaseSensitiveCheckBox.Text = "Case-sensitive";
|
||||
this.RpfSearchCaseSensitiveCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// RpfSearchHexRadioButton
|
||||
//
|
||||
this.RpfSearchHexRadioButton.AutoSize = true;
|
||||
this.RpfSearchHexRadioButton.Location = new System.Drawing.Point(158, 5);
|
||||
this.RpfSearchHexRadioButton.Name = "RpfSearchHexRadioButton";
|
||||
this.RpfSearchHexRadioButton.Size = new System.Drawing.Size(47, 19);
|
||||
this.RpfSearchHexRadioButton.TabIndex = 55;
|
||||
this.RpfSearchHexRadioButton.Text = "Hex";
|
||||
this.RpfSearchHexRadioButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// RpfSearchTextRadioButton
|
||||
//
|
||||
this.RpfSearchTextRadioButton.AutoSize = true;
|
||||
this.RpfSearchTextRadioButton.Checked = true;
|
||||
this.RpfSearchTextRadioButton.Location = new System.Drawing.Point(106, 5);
|
||||
this.RpfSearchTextRadioButton.Name = "RpfSearchTextRadioButton";
|
||||
this.RpfSearchTextRadioButton.Size = new System.Drawing.Size(48, 19);
|
||||
this.RpfSearchTextRadioButton.TabIndex = 54;
|
||||
this.RpfSearchTextRadioButton.TabStop = true;
|
||||
this.RpfSearchTextRadioButton.Text = "Text";
|
||||
this.RpfSearchTextRadioButton.UseVisualStyleBackColor = true;
|
||||
this.RpfSearchTextRadioButton.CheckedChanged += new System.EventHandler(this.RpfSearchTextRadioButton_CheckedChanged);
|
||||
//
|
||||
// RpfSearchResultsListView
|
||||
//
|
||||
this.RpfSearchResultsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.RpfSearchResultsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader1,
|
||||
this.columnHeader2});
|
||||
this.RpfSearchResultsListView.FullRowSelect = true;
|
||||
this.RpfSearchResultsListView.HideSelection = false;
|
||||
this.RpfSearchResultsListView.Location = new System.Drawing.Point(3, 146);
|
||||
this.RpfSearchResultsListView.MultiSelect = false;
|
||||
this.RpfSearchResultsListView.Name = "RpfSearchResultsListView";
|
||||
this.RpfSearchResultsListView.Size = new System.Drawing.Size(263, 347);
|
||||
this.RpfSearchResultsListView.TabIndex = 63;
|
||||
this.RpfSearchResultsListView.UseCompatibleStateImageBehavior = false;
|
||||
this.RpfSearchResultsListView.View = System.Windows.Forms.View.Details;
|
||||
this.RpfSearchResultsListView.VirtualMode = true;
|
||||
this.RpfSearchResultsListView.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.RpfSearchResultsListView_RetrieveVirtualItem);
|
||||
this.RpfSearchResultsListView.SelectedIndexChanged += new System.EventHandler(this.RpfSearchResultsListView_SelectedIndexChanged);
|
||||
//
|
||||
// columnHeader1
|
||||
//
|
||||
this.columnHeader1.Text = "File";
|
||||
this.columnHeader1.Width = 176;
|
||||
//
|
||||
// columnHeader2
|
||||
//
|
||||
this.columnHeader2.Text = "Offset";
|
||||
//
|
||||
// RpfSearchAbortButton
|
||||
//
|
||||
this.RpfSearchAbortButton.Location = new System.Drawing.Point(90, 118);
|
||||
this.RpfSearchAbortButton.Name = "RpfSearchAbortButton";
|
||||
this.RpfSearchAbortButton.Size = new System.Drawing.Size(75, 22);
|
||||
this.RpfSearchAbortButton.TabIndex = 61;
|
||||
this.RpfSearchAbortButton.Text = "Abort";
|
||||
this.RpfSearchAbortButton.UseVisualStyleBackColor = true;
|
||||
this.RpfSearchAbortButton.Click += new System.EventHandler(this.RpfSearchAbortButton_Click);
|
||||
//
|
||||
// RpfSearchButton
|
||||
//
|
||||
this.RpfSearchButton.Location = new System.Drawing.Point(9, 119);
|
||||
this.RpfSearchButton.Name = "RpfSearchButton";
|
||||
this.RpfSearchButton.Size = new System.Drawing.Size(75, 22);
|
||||
this.RpfSearchButton.TabIndex = 60;
|
||||
this.RpfSearchButton.Text = "Search";
|
||||
this.RpfSearchButton.UseVisualStyleBackColor = true;
|
||||
this.RpfSearchButton.Click += new System.EventHandler(this.RpfSearchButton_Click);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(7, 7);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(104, 15);
|
||||
this.label3.TabIndex = 64;
|
||||
this.label3.Text = "Search in files for:";
|
||||
//
|
||||
// RpfSearchTextBox
|
||||
//
|
||||
this.RpfSearchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.RpfSearchTextBox.Location = new System.Drawing.Point(3, 23);
|
||||
this.RpfSearchTextBox.Name = "RpfSearchTextBox";
|
||||
this.RpfSearchTextBox.Size = new System.Drawing.Size(263, 20);
|
||||
this.RpfSearchTextBox.TabIndex = 53;
|
||||
//
|
||||
// ExportCompressCheckBox
|
||||
//
|
||||
this.ExportCompressCheckBox.AutoSize = true;
|
||||
this.ExportCompressCheckBox.Location = new System.Drawing.Point(87, 35);
|
||||
this.ExportCompressCheckBox.Name = "ExportCompressCheckBox";
|
||||
this.ExportCompressCheckBox.Size = new System.Drawing.Size(119, 19);
|
||||
this.ExportCompressCheckBox.TabIndex = 112;
|
||||
this.ExportCompressCheckBox.Text = "Compress export";
|
||||
this.ExportCompressCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ExportButton
|
||||
//
|
||||
this.ExportButton.Location = new System.Drawing.Point(6, 31);
|
||||
this.ExportButton.Name = "ExportButton";
|
||||
this.ExportButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.ExportButton.TabIndex = 111;
|
||||
this.ExportButton.Text = "Export...";
|
||||
this.ExportButton.UseVisualStyleBackColor = true;
|
||||
this.ExportButton.Click += new System.EventHandler(this.ExportButton_Click);
|
||||
//
|
||||
// FileInfoLabel
|
||||
//
|
||||
this.FileInfoLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.FileInfoLabel.AutoEllipsis = true;
|
||||
this.FileInfoLabel.Location = new System.Drawing.Point(3, 7);
|
||||
this.FileInfoLabel.Name = "FileInfoLabel";
|
||||
this.FileInfoLabel.Size = new System.Drawing.Size(549, 16);
|
||||
this.FileInfoLabel.TabIndex = 110;
|
||||
this.FileInfoLabel.Text = "[Nothing selected]";
|
||||
//
|
||||
// ShowLargeFileContentsCheckBox
|
||||
//
|
||||
this.ShowLargeFileContentsCheckBox.AutoSize = true;
|
||||
this.ShowLargeFileContentsCheckBox.Location = new System.Drawing.Point(392, 62);
|
||||
this.ShowLargeFileContentsCheckBox.Name = "ShowLargeFileContentsCheckBox";
|
||||
this.ShowLargeFileContentsCheckBox.Size = new System.Drawing.Size(156, 19);
|
||||
this.ShowLargeFileContentsCheckBox.TabIndex = 109;
|
||||
this.ShowLargeFileContentsCheckBox.Text = "Show large file contents";
|
||||
this.ShowLargeFileContentsCheckBox.UseVisualStyleBackColor = true;
|
||||
this.ShowLargeFileContentsCheckBox.CheckedChanged += new System.EventHandler(this.ShowLargeFileContentsCheckBox_CheckedChanged);
|
||||
//
|
||||
// DataHexLineCombo
|
||||
//
|
||||
this.DataHexLineCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.DataHexLineCombo.FormattingEnabled = true;
|
||||
this.DataHexLineCombo.Items.AddRange(new object[] {
|
||||
"8",
|
||||
"16",
|
||||
"32"});
|
||||
this.DataHexLineCombo.Location = new System.Drawing.Point(56, 60);
|
||||
this.DataHexLineCombo.Name = "DataHexLineCombo";
|
||||
this.DataHexLineCombo.Size = new System.Drawing.Size(49, 21);
|
||||
this.DataHexLineCombo.TabIndex = 106;
|
||||
this.DataHexLineCombo.SelectedIndexChanged += new System.EventHandler(this.DataHexLineCombo_SelectedIndexChanged);
|
||||
//
|
||||
// DataTextRadio
|
||||
//
|
||||
this.DataTextRadio.AutoSize = true;
|
||||
this.DataTextRadio.Location = new System.Drawing.Point(135, 61);
|
||||
this.DataTextRadio.Name = "DataTextRadio";
|
||||
this.DataTextRadio.Size = new System.Drawing.Size(48, 19);
|
||||
this.DataTextRadio.TabIndex = 107;
|
||||
this.DataTextRadio.Text = "Text";
|
||||
this.DataTextRadio.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// DataHexRadio
|
||||
//
|
||||
this.DataHexRadio.AutoSize = true;
|
||||
this.DataHexRadio.Checked = true;
|
||||
this.DataHexRadio.Location = new System.Drawing.Point(6, 61);
|
||||
this.DataHexRadio.Name = "DataHexRadio";
|
||||
this.DataHexRadio.Size = new System.Drawing.Size(47, 19);
|
||||
this.DataHexRadio.TabIndex = 105;
|
||||
this.DataHexRadio.TabStop = true;
|
||||
this.DataHexRadio.Text = "Hex";
|
||||
this.DataHexRadio.UseVisualStyleBackColor = true;
|
||||
this.DataHexRadio.CheckedChanged += new System.EventHandler(this.DataHexRadio_CheckedChanged);
|
||||
//
|
||||
// DataTextBox
|
||||
//
|
||||
this.DataTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.DataTextBox.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.DataTextBox.HideSelection = false;
|
||||
this.DataTextBox.Location = new System.Drawing.Point(4, 92);
|
||||
this.DataTextBox.Multiline = true;
|
||||
this.DataTextBox.Name = "DataTextBox";
|
||||
this.DataTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.DataTextBox.Size = new System.Drawing.Size(552, 401);
|
||||
this.DataTextBox.TabIndex = 108;
|
||||
this.DataTextBox.Text = "[Please select a search result]";
|
||||
this.DataTextBox.WordWrap = false;
|
||||
//
|
||||
// SearchFileSystemTab
|
||||
//
|
||||
this.SearchFileSystemTab.Controls.Add(this.FileSearchPanel);
|
||||
this.SearchFileSystemTab.Controls.Add(this.FileSearchResultsTextBox);
|
||||
this.SearchFileSystemTab.Location = new System.Drawing.Point(4, 22);
|
||||
this.SearchFileSystemTab.Name = "SearchFileSystemTab";
|
||||
this.SearchFileSystemTab.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.SearchFileSystemTab.Size = new System.Drawing.Size(838, 499);
|
||||
this.SearchFileSystemTab.TabIndex = 1;
|
||||
this.SearchFileSystemTab.Text = "Search file system";
|
||||
this.SearchFileSystemTab.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// FileSearchPanel
|
||||
//
|
||||
this.FileSearchPanel.Controls.Add(this.FileSearchFolderTextBox);
|
||||
this.FileSearchPanel.Controls.Add(this.FileSearchFolderBrowseButton);
|
||||
this.FileSearchPanel.Controls.Add(this.FileSearchTextRadio);
|
||||
this.FileSearchPanel.Controls.Add(this.FileSearchTextBox);
|
||||
this.FileSearchPanel.Controls.Add(this.FileSearchButton);
|
||||
this.FileSearchPanel.Controls.Add(this.FileSearchHexRadio);
|
||||
this.FileSearchPanel.Controls.Add(this.FileSearchAbortButton);
|
||||
this.FileSearchPanel.Controls.Add(this.label2);
|
||||
this.FileSearchPanel.Location = new System.Drawing.Point(3, 6);
|
||||
this.FileSearchPanel.Name = "FileSearchPanel";
|
||||
this.FileSearchPanel.Size = new System.Drawing.Size(536, 66);
|
||||
this.FileSearchPanel.TabIndex = 46;
|
||||
//
|
||||
// MainStatusStrip
|
||||
//
|
||||
this.MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.StatusLabel});
|
||||
this.MainStatusStrip.Location = new System.Drawing.Point(0, 533);
|
||||
this.MainStatusStrip.Name = "MainStatusStrip";
|
||||
this.MainStatusStrip.Size = new System.Drawing.Size(852, 22);
|
||||
this.MainStatusStrip.TabIndex = 47;
|
||||
this.MainStatusStrip.Text = "statusStrip1";
|
||||
//
|
||||
// StatusLabel
|
||||
//
|
||||
this.StatusLabel.Name = "StatusLabel";
|
||||
this.StatusLabel.Size = new System.Drawing.Size(806, 17);
|
||||
this.StatusLabel.Spring = true;
|
||||
this.StatusLabel.Text = "Initialising...";
|
||||
this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// SaveFileDialog
|
||||
//
|
||||
this.SaveFileDialog.AddExtension = false;
|
||||
//
|
||||
// BinarySearchForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(852, 555);
|
||||
this.Controls.Add(this.MainStatusStrip);
|
||||
this.Controls.Add(this.MainTabControl);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Name = "BinarySearchForm";
|
||||
this.Text = "Binary Search - CodeWalker by dexyfex";
|
||||
this.Load += new System.EventHandler(this.BinarySearchForm_Load);
|
||||
this.MainTabControl.ResumeLayout(false);
|
||||
this.SearchRPFTabPage.ResumeLayout(false);
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel1.PerformLayout();
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.SearchFileSystemTab.ResumeLayout(false);
|
||||
this.SearchFileSystemTab.PerformLayout();
|
||||
this.FileSearchPanel.ResumeLayout(false);
|
||||
this.FileSearchPanel.PerformLayout();
|
||||
this.MainStatusStrip.ResumeLayout(false);
|
||||
this.MainStatusStrip.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.RadioButton FileSearchTextRadio;
|
||||
private System.Windows.Forms.RadioButton FileSearchHexRadio;
|
||||
private System.Windows.Forms.Button FileSearchAbortButton;
|
||||
private System.Windows.Forms.TextBox FileSearchResultsTextBox;
|
||||
private System.Windows.Forms.TextBox FileSearchTextBox;
|
||||
private System.Windows.Forms.Button FileSearchFolderBrowseButton;
|
||||
private System.Windows.Forms.Button FileSearchButton;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox FileSearchFolderTextBox;
|
||||
private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog;
|
||||
private System.Windows.Forms.TabControl MainTabControl;
|
||||
private System.Windows.Forms.TabPage SearchRPFTabPage;
|
||||
private System.Windows.Forms.TabPage SearchFileSystemTab;
|
||||
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
|
||||
private System.Windows.Forms.Panel FileSearchPanel;
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private System.Windows.Forms.Button RpfSearchSaveResultsButton;
|
||||
private System.Windows.Forms.TextBox RpfSearchIgnoreTextBox;
|
||||
private System.Windows.Forms.CheckBox RpfSearchIgnoreCheckBox;
|
||||
private System.Windows.Forms.CheckBox RpfSearchBothDirectionsCheckBox;
|
||||
private System.Windows.Forms.CheckBox RpfSearchCaseSensitiveCheckBox;
|
||||
private System.Windows.Forms.RadioButton RpfSearchHexRadioButton;
|
||||
private System.Windows.Forms.RadioButton RpfSearchTextRadioButton;
|
||||
private System.Windows.Forms.ListView RpfSearchResultsListView;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
||||
private System.Windows.Forms.Button RpfSearchAbortButton;
|
||||
private System.Windows.Forms.Button RpfSearchButton;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox RpfSearchTextBox;
|
||||
private System.Windows.Forms.TextBox RpfSearchOnlyTextBox;
|
||||
private System.Windows.Forms.CheckBox RpfSearchOnlyCheckBox;
|
||||
private System.Windows.Forms.CheckBox ShowLargeFileContentsCheckBox;
|
||||
private System.Windows.Forms.ComboBox DataHexLineCombo;
|
||||
private System.Windows.Forms.RadioButton DataTextRadio;
|
||||
private System.Windows.Forms.RadioButton DataHexRadio;
|
||||
private System.Windows.Forms.TextBox DataTextBox;
|
||||
private System.Windows.Forms.Label FileInfoLabel;
|
||||
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
|
||||
private System.Windows.Forms.CheckBox ExportCompressCheckBox;
|
||||
private System.Windows.Forms.Button ExportButton;
|
||||
public System.Windows.Forms.StatusStrip MainStatusStrip;
|
||||
}
|
||||
}
|
980
BinarySearchForm.cs
Normal file
980
BinarySearchForm.cs
Normal file
@ -0,0 +1,980 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using CodeWalker.Properties;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
public partial class BinarySearchForm : Form
|
||||
{
|
||||
private volatile bool InProgress = false;
|
||||
private volatile bool AbortOperation = false;
|
||||
|
||||
private GameFileCache FileCache = null;
|
||||
private RpfManager RpfMan = null;
|
||||
|
||||
|
||||
public BinarySearchForm(GameFileCache cache = null)
|
||||
{
|
||||
FileCache = cache;
|
||||
RpfMan = cache?.RpfMan;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BinarySearchForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
FileSearchFolderTextBox.Text = Settings.Default.CompiledScriptFolder;
|
||||
|
||||
DataHexLineCombo.Text = "16";
|
||||
DataTextBox.SetTabStopWidth(3);
|
||||
|
||||
|
||||
if (RpfMan == null)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
GTA5Keys.LoadFromPath(GTAFolder.CurrentGTAFolder, Settings.Default.Key);
|
||||
RpfMan = new RpfManager();
|
||||
RpfMan.Init(GTAFolder.CurrentGTAFolder, UpdateStatus, UpdateStatus, false, false);
|
||||
RPFScanComplete();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
RPFScanComplete();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStatus(string text)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => { UpdateStatus(text); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusLabel.Text = text;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
private void RPFScanComplete()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => { RPFScanComplete(); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusLabel.Text = "Ready";
|
||||
//RpfSearchPanel.Enabled = true;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void FileSearchFolderBrowseButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
FolderBrowserDialog.SelectedPath = FileSearchFolderTextBox.Text;
|
||||
DialogResult res = FolderBrowserDialog.ShowDialog();
|
||||
if (res == DialogResult.OK)
|
||||
{
|
||||
FileSearchFolderTextBox.Text = FolderBrowserDialog.SelectedPath;
|
||||
}
|
||||
}
|
||||
|
||||
private void FileSearchButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
string searchtxt = FileSearchTextBox.Text;
|
||||
string searchfolder = FileSearchFolderTextBox.Text;
|
||||
AbortOperation = false;
|
||||
|
||||
if (InProgress) return;
|
||||
if (searchfolder.Length == 0)
|
||||
{
|
||||
MessageBox.Show("Please select a folder...");
|
||||
return;
|
||||
}
|
||||
if (!Directory.Exists(searchfolder))
|
||||
{
|
||||
MessageBox.Show("Please select a valid folder!");
|
||||
return;
|
||||
}
|
||||
|
||||
FileSearchResultsTextBox.Clear();
|
||||
|
||||
byte[] searchbytes1;
|
||||
byte[] searchbytes2;
|
||||
int bytelen;
|
||||
|
||||
if (FileSearchHexRadio.Checked)
|
||||
{
|
||||
try
|
||||
{
|
||||
bytelen = searchtxt.Length / 2;
|
||||
searchbytes1 = new byte[bytelen];
|
||||
searchbytes2 = new byte[bytelen];
|
||||
for (int i = 0; i < bytelen; i++)
|
||||
{
|
||||
searchbytes1[i] = Convert.ToByte(searchtxt.Substring(i * 2, 2), 16);
|
||||
searchbytes2[bytelen - i - 1] = searchbytes1[i];
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageBox.Show("Please enter a valid hex string.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bytelen = searchtxt.Length;
|
||||
searchbytes1 = new byte[bytelen];
|
||||
searchbytes2 = new byte[bytelen];
|
||||
for (int i = 0; i < bytelen; i++)
|
||||
{
|
||||
searchbytes1[i] = (byte)searchtxt[i];
|
||||
searchbytes2[bytelen - i - 1] = searchbytes1[i];
|
||||
}
|
||||
}
|
||||
|
||||
FileSearchPanel.Enabled = false;
|
||||
|
||||
InProgress = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
|
||||
FileSearchAddResult("Searching " + searchfolder + "...");
|
||||
|
||||
string[] filenames = Directory.GetFiles(searchfolder);
|
||||
|
||||
int matchcount = 0;
|
||||
|
||||
foreach (string filename in filenames)
|
||||
{
|
||||
|
||||
|
||||
FileInfo finf = new FileInfo(filename);
|
||||
byte[] filebytes = File.ReadAllBytes(filename);
|
||||
|
||||
int hitlen1 = 0;
|
||||
int hitlen2 = 0;
|
||||
|
||||
for (int i = 0; i < filebytes.Length; i++)
|
||||
{
|
||||
byte b = filebytes[i];
|
||||
byte b1 = searchbytes1[hitlen1]; //current test byte 1
|
||||
byte b2 = searchbytes2[hitlen2];
|
||||
|
||||
if (b == b1) hitlen1++; else hitlen1 = 0;
|
||||
if (b == b2) hitlen2++; else hitlen2 = 0;
|
||||
|
||||
if (hitlen1 == bytelen)
|
||||
{
|
||||
FileSearchAddResult(finf.Name + ":" + (i - bytelen));
|
||||
matchcount++;
|
||||
hitlen1 = 0;
|
||||
}
|
||||
if (hitlen2 == bytelen)
|
||||
{
|
||||
FileSearchAddResult(finf.Name + ":" + (i - bytelen));
|
||||
matchcount++;
|
||||
hitlen2 = 0;
|
||||
}
|
||||
|
||||
if (AbortOperation)
|
||||
{
|
||||
FileSearchAddResult("Search aborted.");
|
||||
FileSearchComplete();
|
||||
InProgress = false;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FileSearchAddResult(string.Format("Search complete. {0} results found.", matchcount));
|
||||
FileSearchComplete();
|
||||
InProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
private void FileSearchAddResult(string result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => { FileSearchAddResult(result); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSearchResultsTextBox.AppendText(result + "\r\n");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void FileSearchComplete()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => { FileSearchComplete(); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSearchPanel.Enabled = true;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void FileSearchAbortButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
AbortOperation = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private List<RpfSearchResult> RpfSearchResults = new List<RpfSearchResult>();
|
||||
private RpfEntry RpfSelectedEntry = null;
|
||||
private int RpfSelectedOffset = -1;
|
||||
private int RpfSelectedLength = 0;
|
||||
|
||||
private class RpfSearchResult
|
||||
{
|
||||
public RpfFileEntry FileEntry { get; set; }
|
||||
public int Offset { get; set; }
|
||||
public int Length { get; set; }
|
||||
|
||||
public RpfSearchResult(RpfFileEntry entry, int offset, int length)
|
||||
{
|
||||
FileEntry = entry;
|
||||
Offset = offset;
|
||||
Length = length;
|
||||
}
|
||||
}
|
||||
private byte LowerCaseByte(byte b)
|
||||
{
|
||||
if ((b >= 65) && (b <= 90)) //upper case alphabet...
|
||||
{
|
||||
b += 32;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private void RpfSearchAddResult(RpfSearchResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => { RpfSearchAddResult(result); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
RpfSearchResults.Add(result);
|
||||
RpfSearchResultsListView.VirtualListSize = RpfSearchResults.Count;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void RpfSearch()
|
||||
{
|
||||
if (InProgress) return;
|
||||
if (!(RpfMan?.IsInited ?? false))
|
||||
{
|
||||
MessageBox.Show("Please wait for the scan to complete.");
|
||||
return;
|
||||
}
|
||||
if (RpfSearchTextBox.Text.Length == 0)
|
||||
{
|
||||
MessageBox.Show("Please enter a search term.");
|
||||
return;
|
||||
}
|
||||
|
||||
string searchtxt = RpfSearchTextBox.Text;
|
||||
bool hex = RpfSearchHexRadioButton.Checked;
|
||||
bool casesen = RpfSearchCaseSensitiveCheckBox.Checked || hex;
|
||||
bool bothdirs = RpfSearchBothDirectionsCheckBox.Checked;
|
||||
string[] ignoreexts = null;
|
||||
string[] onlyexts = null;
|
||||
byte[] searchbytes1;
|
||||
byte[] searchbytes2;
|
||||
int bytelen;
|
||||
|
||||
if (!casesen) searchtxt = searchtxt.ToLowerInvariant(); //case sensitive search in lower case.
|
||||
|
||||
if (RpfSearchIgnoreCheckBox.Checked)
|
||||
{
|
||||
ignoreexts = RpfSearchIgnoreTextBox.Text.Split(',');
|
||||
for (int i = 0; i < ignoreexts.Length; i++)
|
||||
{
|
||||
ignoreexts[i] = ignoreexts[i].Trim();
|
||||
}
|
||||
}
|
||||
if (RpfSearchOnlyCheckBox.Checked)
|
||||
{
|
||||
onlyexts = RpfSearchOnlyTextBox.Text.Split(',');
|
||||
for (int i = 0; i < onlyexts.Length; i++)
|
||||
{
|
||||
onlyexts[i] = onlyexts[i].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
if (hex)
|
||||
{
|
||||
if (searchtxt.Length < 2)
|
||||
{
|
||||
MessageBox.Show("Please enter at least one byte of hex (2 characters).");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
bytelen = searchtxt.Length / 2;
|
||||
searchbytes1 = new byte[bytelen];
|
||||
searchbytes2 = new byte[bytelen];
|
||||
for (int i = 0; i < bytelen; i++)
|
||||
{
|
||||
searchbytes1[i] = Convert.ToByte(searchtxt.Substring(i * 2, 2), 16);
|
||||
searchbytes2[bytelen - i - 1] = searchbytes1[i];
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageBox.Show("Please enter a valid hex string.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bytelen = searchtxt.Length;
|
||||
searchbytes1 = new byte[bytelen];
|
||||
searchbytes2 = new byte[bytelen]; //reversed text...
|
||||
for (int i = 0; i < bytelen; i++)
|
||||
{
|
||||
searchbytes1[i] = (byte)searchtxt[i];
|
||||
searchbytes2[bytelen - i - 1] = searchbytes1[i];
|
||||
}
|
||||
}
|
||||
|
||||
RpfSearchTextBox.Enabled = false;
|
||||
RpfSearchHexRadioButton.Enabled = false;
|
||||
RpfSearchTextRadioButton.Enabled = false;
|
||||
RpfSearchCaseSensitiveCheckBox.Enabled = false;
|
||||
RpfSearchBothDirectionsCheckBox.Enabled = false;
|
||||
RpfSearchIgnoreCheckBox.Enabled = false;
|
||||
RpfSearchIgnoreTextBox.Enabled = false;
|
||||
RpfSearchButton.Enabled = false;
|
||||
RpfSearchSaveResultsButton.Enabled = false;
|
||||
|
||||
InProgress = true;
|
||||
AbortOperation = false;
|
||||
RpfSearchResultsListView.VirtualListSize = 0;
|
||||
RpfSearchResults.Clear();
|
||||
uint totfiles = 0;
|
||||
uint curfile = 0;
|
||||
var scannedFiles = RpfMan.AllRpfs;
|
||||
Task.Run(() =>
|
||||
{
|
||||
|
||||
DateTime starttime = DateTime.Now;
|
||||
int resultcount = 0;
|
||||
|
||||
for (int f = 0; f < scannedFiles.Count; f++)
|
||||
{
|
||||
var rpffile = scannedFiles[f];
|
||||
totfiles += rpffile.TotalFileCount;
|
||||
}
|
||||
|
||||
|
||||
for (int f = 0; f < scannedFiles.Count; f++)
|
||||
{
|
||||
var rpffile = scannedFiles[f];
|
||||
|
||||
foreach (var entry in rpffile.AllEntries)
|
||||
{
|
||||
var duration = DateTime.Now - starttime;
|
||||
if (AbortOperation)
|
||||
{
|
||||
UpdateStatus(duration.ToString(@"hh\:mm\:ss") + " - Search aborted.");
|
||||
InProgress = false;
|
||||
RpfSearchComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
RpfFileEntry fentry = entry as RpfFileEntry;
|
||||
if (fentry == null) continue;
|
||||
|
||||
curfile++;
|
||||
|
||||
if (fentry.NameLower.EndsWith(".rpf"))
|
||||
{ continue; }
|
||||
|
||||
if (onlyexts != null)
|
||||
{
|
||||
bool ignore = true;
|
||||
for (int i = 0; i < onlyexts.Length; i++)
|
||||
{
|
||||
if (fentry.NameLower.EndsWith(onlyexts[i]))
|
||||
{
|
||||
ignore = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ignore)
|
||||
{ continue; }
|
||||
}
|
||||
|
||||
if (ignoreexts != null)
|
||||
{
|
||||
bool ignore = false;
|
||||
for (int i = 0; i < ignoreexts.Length; i++)
|
||||
{
|
||||
if (fentry.NameLower.EndsWith(ignoreexts[i]))
|
||||
{
|
||||
ignore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ignore)
|
||||
{ continue; }
|
||||
}
|
||||
|
||||
UpdateStatus(string.Format("{0} - Searching {1}/{2} : {3}", duration.ToString(@"hh\:mm\:ss"), curfile, totfiles, fentry.Path));
|
||||
|
||||
byte[] filebytes = fentry.File.ExtractFile(fentry);
|
||||
if (filebytes == null) continue;
|
||||
|
||||
|
||||
int hitlen1 = 0;
|
||||
int hitlen2 = 0;
|
||||
|
||||
for (int i = 0; i < filebytes.Length; i++)
|
||||
{
|
||||
byte b = casesen ? filebytes[i] : LowerCaseByte(filebytes[i]);
|
||||
byte b1 = searchbytes1[hitlen1]; //current test byte 1
|
||||
byte b2 = searchbytes2[hitlen2];
|
||||
|
||||
if (b == b1) hitlen1++; else hitlen1 = 0;
|
||||
if (hitlen1 == bytelen)
|
||||
{
|
||||
RpfSearchAddResult(new RpfSearchResult(fentry, (i - bytelen), bytelen));
|
||||
resultcount++;
|
||||
hitlen1 = 0;
|
||||
}
|
||||
if (bothdirs)
|
||||
{
|
||||
if (b == b2) hitlen2++; else hitlen2 = 0;
|
||||
if (hitlen2 == bytelen)
|
||||
{
|
||||
RpfSearchAddResult(new RpfSearchResult(fentry, (i - bytelen), bytelen));
|
||||
resultcount++;
|
||||
hitlen2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var totdur = DateTime.Now - starttime;
|
||||
UpdateStatus(totdur.ToString(@"hh\:mm\:ss") + " - Search complete. " + resultcount.ToString() + " results found.");
|
||||
InProgress = false;
|
||||
RpfSearchComplete();
|
||||
});
|
||||
}
|
||||
private void RpfSearchComplete()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => { RpfSearchComplete(); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
RpfSearchTextBox.Enabled = true;
|
||||
RpfSearchHexRadioButton.Enabled = true;
|
||||
RpfSearchTextRadioButton.Enabled = true;
|
||||
RpfSearchCaseSensitiveCheckBox.Enabled = RpfSearchTextRadioButton.Checked;
|
||||
RpfSearchBothDirectionsCheckBox.Enabled = true;
|
||||
RpfSearchIgnoreCheckBox.Enabled = true;
|
||||
RpfSearchIgnoreTextBox.Enabled = RpfSearchIgnoreCheckBox.Checked;
|
||||
RpfSearchButton.Enabled = true;
|
||||
RpfSearchSaveResultsButton.Enabled = true;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void RpfSearchButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
RpfSearch();
|
||||
}
|
||||
|
||||
private void RpfSearchAbortButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
AbortOperation = true;
|
||||
}
|
||||
|
||||
private void RpfSearchSaveResultsButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
SaveFileDialog.FileName = "SearchResults.txt";
|
||||
if (SaveFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
string fpath = SaveFileDialog.FileName;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("CodeWalker Search Results for \"" + RpfSearchTextBox.Text + "\"");
|
||||
sb.AppendLine("[File path], [Byte offset]");
|
||||
if (RpfSearchResults != null)
|
||||
{
|
||||
foreach (var r in RpfSearchResults)
|
||||
{
|
||||
sb.AppendLine(r.FileEntry.Path + ", " + r.Offset.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(fpath, sb.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void RpfSearchIgnoreCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
RpfSearchIgnoreTextBox.Enabled = RpfSearchIgnoreCheckBox.Checked;
|
||||
if (RpfSearchIgnoreCheckBox.Checked)
|
||||
{
|
||||
RpfSearchOnlyCheckBox.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void RpfSearchOnlyCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
RpfSearchOnlyTextBox.Enabled = RpfSearchOnlyCheckBox.Checked;
|
||||
if (RpfSearchOnlyCheckBox.Checked)
|
||||
{
|
||||
RpfSearchIgnoreCheckBox.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void RpfSearchTextRadioButton_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
RpfSearchCaseSensitiveCheckBox.Enabled = RpfSearchTextRadioButton.Checked;
|
||||
}
|
||||
|
||||
private void RpfSearchResultsListView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (RpfSearchResultsListView.SelectedIndices.Count == 1)
|
||||
{
|
||||
var i = RpfSearchResultsListView.SelectedIndices[0];
|
||||
if ((i >= 0) && (i < RpfSearchResults.Count))
|
||||
{
|
||||
var r = RpfSearchResults[i];
|
||||
SelectFile(r.FileEntry, r.Offset + 1, r.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectFile(null, -1, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectFile(null, -1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void RpfSearchResultsListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
|
||||
{
|
||||
var item = new ListViewItem();
|
||||
if (e.ItemIndex < RpfSearchResults.Count)
|
||||
{
|
||||
RpfSearchResult r = RpfSearchResults[e.ItemIndex];
|
||||
item.Text = r.FileEntry.Name;
|
||||
item.SubItems.Add(r.Offset.ToString());
|
||||
item.Tag = r;
|
||||
}
|
||||
e.Item = item;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void SelectFile()
|
||||
{
|
||||
SelectFile(RpfSelectedEntry, RpfSelectedOffset, RpfSelectedLength);
|
||||
}
|
||||
private void SelectFile(RpfEntry entry, int offset, int length)
|
||||
{
|
||||
RpfSelectedEntry = entry;
|
||||
RpfSelectedOffset = offset;
|
||||
RpfSelectedLength = length;
|
||||
|
||||
RpfFileEntry rfe = entry as RpfFileEntry;
|
||||
if (rfe == null)
|
||||
{
|
||||
RpfDirectoryEntry rde = entry as RpfDirectoryEntry;
|
||||
if (rde != null)
|
||||
{
|
||||
FileInfoLabel.Text = rde.Path + " (Directory)";
|
||||
DataTextBox.Text = "[Please select a data file]";
|
||||
}
|
||||
else
|
||||
{
|
||||
FileInfoLabel.Text = "[Nothing selected]";
|
||||
DataTextBox.Text = "[Please select a search result]";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Cursor = Cursors.WaitCursor;
|
||||
|
||||
string typestr = "Resource";
|
||||
if (rfe is RpfBinaryFileEntry)
|
||||
{
|
||||
typestr = "Binary";
|
||||
}
|
||||
|
||||
byte[] data = rfe.File.ExtractFile(rfe);
|
||||
|
||||
int datalen = (data != null) ? data.Length : 0;
|
||||
FileInfoLabel.Text = rfe.Path + " (" + typestr + " file) - " + TextUtil.GetBytesReadable(datalen);
|
||||
|
||||
|
||||
if (ShowLargeFileContentsCheckBox.Checked || (datalen < 524287)) //512K
|
||||
{
|
||||
DisplayFileContentsText(rfe, data, length, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
DataTextBox.Text = "[Filesize >512KB. Select the Show large files option to view its contents]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
//bool istexdict = false;
|
||||
//if (rfe.NameLower.EndsWith(".ymap"))
|
||||
//{
|
||||
// YmapFile ymap = new YmapFile(rfe);
|
||||
// ymap.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ymap;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ytyp"))
|
||||
//{
|
||||
// YtypFile ytyp = new YtypFile();
|
||||
// ytyp.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ytyp;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ymf"))
|
||||
//{
|
||||
// YmfFile ymf = new YmfFile();
|
||||
// ymf.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ymf;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ymt"))
|
||||
//{
|
||||
// YmtFile ymt = new YmtFile();
|
||||
// ymt.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ymt;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ybn"))
|
||||
//{
|
||||
// YbnFile ybn = new YbnFile();
|
||||
// ybn.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ybn;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".fxc"))
|
||||
//{
|
||||
// FxcFile fxc = new FxcFile();
|
||||
// fxc.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = fxc;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".yft"))
|
||||
//{
|
||||
// YftFile yft = new YftFile();
|
||||
// yft.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = yft;
|
||||
// if ((yft.Fragment != null) && (yft.Fragment.Drawable != null) && (yft.Fragment.Drawable.ShaderGroup != null) && (yft.Fragment.Drawable.ShaderGroup.TextureDictionary != null))
|
||||
// {
|
||||
// ShowTextures(yft.Fragment.Drawable.ShaderGroup.TextureDictionary);
|
||||
// istexdict = true;
|
||||
// }
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ydr"))
|
||||
//{
|
||||
// YdrFile ydr = new YdrFile();
|
||||
// ydr.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ydr;
|
||||
// if ((ydr.Drawable != null) && (ydr.Drawable.ShaderGroup != null) && (ydr.Drawable.ShaderGroup.TextureDictionary != null))
|
||||
// {
|
||||
// ShowTextures(ydr.Drawable.ShaderGroup.TextureDictionary);
|
||||
// istexdict = true;
|
||||
// }
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ydd"))
|
||||
//{
|
||||
// YddFile ydd = new YddFile();
|
||||
// ydd.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ydd;
|
||||
// //todo: show embedded texdicts in ydd's? is this possible?
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ytd"))
|
||||
//{
|
||||
// YtdFile ytd = new YtdFile();
|
||||
// ytd.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ytd;
|
||||
// ShowTextures(ytd.TextureDict);
|
||||
// istexdict = true;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ycd"))
|
||||
//{
|
||||
// YcdFile ycd = new YcdFile();
|
||||
// ycd.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ycd;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ynd"))
|
||||
//{
|
||||
// YndFile ynd = new YndFile();
|
||||
// ynd.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ynd;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".ynv"))
|
||||
//{
|
||||
// YnvFile ynv = new YnvFile();
|
||||
// ynv.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = ynv;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith("_cache_y.dat"))
|
||||
//{
|
||||
// CacheDatFile cdf = new CacheDatFile();
|
||||
// cdf.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = cdf;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".rel"))
|
||||
//{
|
||||
// RelFile rel = new RelFile(rfe);
|
||||
// rel.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = rel;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".gxt2"))
|
||||
//{
|
||||
// Gxt2File gxt2 = new Gxt2File();
|
||||
// gxt2.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = gxt2;
|
||||
//}
|
||||
//else if (rfe.NameLower.EndsWith(".pso"))
|
||||
//{
|
||||
// JPsoFile pso = new JPsoFile();
|
||||
// pso.Load(data, rfe);
|
||||
// DetailsPropertyGrid.SelectedObject = pso;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// DetailsPropertyGrid.SelectedObject = null;
|
||||
//}
|
||||
|
||||
|
||||
//if (!istexdict)
|
||||
//{
|
||||
// ShowTextures(null);
|
||||
//}
|
||||
|
||||
|
||||
Cursor = Cursors.Default;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void DisplayFileContentsText(RpfFileEntry rfe, byte[] data, int length, int offset)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
Cursor = Cursors.Default;
|
||||
DataTextBox.Text = "[Error extracting file! " + rfe.File.LastError + "]";
|
||||
return;
|
||||
}
|
||||
|
||||
int selline = -1;
|
||||
int selstartc = -1;
|
||||
int selendc = -1;
|
||||
|
||||
if (DataHexRadio.Checked)
|
||||
{
|
||||
int charsperln = int.Parse(DataHexLineCombo.Text);
|
||||
int lines = (data.Length / charsperln) + (((data.Length % charsperln) > 0) ? 1 : 0);
|
||||
StringBuilder hexb = new StringBuilder();
|
||||
StringBuilder texb = new StringBuilder();
|
||||
StringBuilder finb = new StringBuilder();
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
selline = offset / charsperln;
|
||||
}
|
||||
for (int i = 0; i < lines; i++)
|
||||
{
|
||||
int pos = i * charsperln;
|
||||
int poslim = pos + charsperln;
|
||||
hexb.Clear();
|
||||
texb.Clear();
|
||||
hexb.AppendFormat("{0:X4}: ", pos);
|
||||
for (int c = pos; c < poslim; c++)
|
||||
{
|
||||
if (c < data.Length)
|
||||
{
|
||||
byte b = data[c];
|
||||
hexb.AppendFormat("{0:X2} ", b);
|
||||
if (char.IsControl((char)b))
|
||||
{
|
||||
texb.Append(".");
|
||||
}
|
||||
else
|
||||
{
|
||||
texb.Append(Encoding.ASCII.GetString(data, c, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hexb.Append(" ");
|
||||
texb.Append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
if (i == selline) selstartc = finb.Length;
|
||||
|
||||
finb.AppendLine(hexb.ToString() + "| " + texb.ToString());
|
||||
|
||||
if (i == selline) selendc = finb.Length - 1;
|
||||
}
|
||||
|
||||
DataTextBox.Text = finb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
string text = Encoding.UTF8.GetString(data);
|
||||
|
||||
|
||||
DataTextBox.Text = text;
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
selstartc = offset;
|
||||
selendc = offset + length;
|
||||
}
|
||||
}
|
||||
|
||||
if ((selstartc > 0) && (selendc > 0))
|
||||
{
|
||||
DataTextBox.SelectionStart = selstartc;
|
||||
DataTextBox.SelectionLength = selendc - selstartc;
|
||||
DataTextBox.ScrollToCaret();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ExportButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (InProgress) return;
|
||||
if (!(RpfMan?.IsInited ?? false))
|
||||
{
|
||||
MessageBox.Show("Please wait for the scan to complete.");
|
||||
return;
|
||||
}
|
||||
|
||||
RpfFileEntry rfe = RpfSelectedEntry as RpfFileEntry;
|
||||
if (rfe == null)
|
||||
{
|
||||
MessageBox.Show("Please select a file to export.");
|
||||
return;
|
||||
}
|
||||
|
||||
SaveFileDialog.FileName = rfe.Name;
|
||||
if (SaveFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
string fpath = SaveFileDialog.FileName;
|
||||
|
||||
byte[] data = rfe.File.ExtractFile(rfe);
|
||||
|
||||
|
||||
if (ExportCompressCheckBox.Checked)
|
||||
{
|
||||
data = ResourceBuilder.Compress(data);
|
||||
}
|
||||
|
||||
|
||||
RpfResourceFileEntry rrfe = rfe as RpfResourceFileEntry;
|
||||
if (rrfe != null) //add resource header if this is a resource file.
|
||||
{
|
||||
data = ResourceBuilder.AddResourceHeader(rrfe, data);
|
||||
}
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
MessageBox.Show("Error extracting file! " + rfe.File.LastError);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
File.WriteAllBytes(fpath, data);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Error saving file! " + ex.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void DataHexRadio_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
SelectFile();
|
||||
}
|
||||
|
||||
private void DataHexLineCombo_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
SelectFile();
|
||||
}
|
||||
|
||||
private void ShowLargeFileContentsCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
SelectFile();
|
||||
}
|
||||
}
|
||||
}
|
418
BinarySearchForm.resx
Normal file
418
BinarySearchForm.resx
Normal file
@ -0,0 +1,418 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="FolderBrowserDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="MainStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>182, 17</value>
|
||||
</metadata>
|
||||
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>317, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v//
|
||||
/////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO
|
||||
6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f//
|
||||
/wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA
|
||||
AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc
|
||||
skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU
|
||||
0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq
|
||||
+ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz
|
||||
/eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR
|
||||
p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm
|
||||
+P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB
|
||||
AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/
|
||||
/f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/
|
||||
+fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd
|
||||
4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
|
||||
1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2OL+NjZ7AAArX2Ok
|
||||
4uz/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
|
||||
2eP/LjJ1DAxKfYTE4Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//v7//f7//f7//v7//v//
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
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
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/
|
||||
/P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/
|
||||
/f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
|
||||
///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB///////
|
||||
//AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA
|
||||
H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A
|
||||
A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA
|
||||
/f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A
|
||||
AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf
|
||||
AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4
|
||||
AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A//
|
||||
///////gD/////////Af//////////////8=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
846
BrowseForm.Designer.cs
generated
Normal file
846
BrowseForm.Designer.cs
generated
Normal file
@ -0,0 +1,846 @@
|
||||
namespace CodeWalker
|
||||
{
|
||||
partial class BrowseForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BrowseForm));
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.FolderBrowseButton = new System.Windows.Forms.Button();
|
||||
this.FolderTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ScanButton = new System.Windows.Forms.Button();
|
||||
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.FlattenStructureCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.FindButton = new System.Windows.Forms.Button();
|
||||
this.MainTreeView = new System.Windows.Forms.TreeView();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.FindTextBox = new System.Windows.Forms.TextBox();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.SearchSaveResultsButton = new System.Windows.Forms.Button();
|
||||
this.SearchIgnoreTextBox = new System.Windows.Forms.TextBox();
|
||||
this.SearchIgnoreCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.SearchBothDirectionsCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.SearchCaseSensitiveCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.SearchHexRadioButton = new System.Windows.Forms.RadioButton();
|
||||
this.SearchTextRadioButton = new System.Windows.Forms.RadioButton();
|
||||
this.SearchResultsListView = new System.Windows.Forms.ListView();
|
||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.SearchAbortButton = new System.Windows.Forms.Button();
|
||||
this.SearchButton = new System.Windows.Forms.Button();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.SearchTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ExportCompressCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ExportButton = new System.Windows.Forms.Button();
|
||||
this.FileInfoLabel = new System.Windows.Forms.Label();
|
||||
this.SelectionTabControl = new System.Windows.Forms.TabControl();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.ShowLargeFileContentsCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.DataHexLineCombo = new System.Windows.Forms.ComboBox();
|
||||
this.DataTextRadio = new System.Windows.Forms.RadioButton();
|
||||
this.DataHexRadio = new System.Windows.Forms.RadioButton();
|
||||
this.DataTextBox = new System.Windows.Forms.TextBox();
|
||||
this.tabPage4 = new System.Windows.Forms.TabPage();
|
||||
this.DetailsPropertyGrid = new CodeWalker.WinForms.PropertyGridFix();
|
||||
this.TexturesTabPage = new System.Windows.Forms.TabPage();
|
||||
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
|
||||
this.SelTexturesListView = new System.Windows.Forms.ListView();
|
||||
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.SelTextureMipLabel = new System.Windows.Forms.Label();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.SelTextureDimensionsLabel = new System.Windows.Forms.Label();
|
||||
this.SelTextureMipTrackBar = new System.Windows.Forms.TrackBar();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.SelTextureNameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.SelTexturePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.MainStatusStrip = new System.Windows.Forms.StatusStrip();
|
||||
this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.TestAllButton = new System.Windows.Forms.Button();
|
||||
this.AbortButton = new System.Windows.Forms.Button();
|
||||
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.SelectionTabControl.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.tabPage4.SuspendLayout();
|
||||
this.TexturesTabPage.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
|
||||
this.splitContainer2.Panel1.SuspendLayout();
|
||||
this.splitContainer2.Panel2.SuspendLayout();
|
||||
this.splitContainer2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SelTexturePictureBox)).BeginInit();
|
||||
this.MainStatusStrip.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(12, 9);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(68, 13);
|
||||
this.label1.TabIndex = 47;
|
||||
this.label1.Text = "GTAV folder:";
|
||||
//
|
||||
// FolderBrowseButton
|
||||
//
|
||||
this.FolderBrowseButton.Location = new System.Drawing.Point(347, 4);
|
||||
this.FolderBrowseButton.Name = "FolderBrowseButton";
|
||||
this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23);
|
||||
this.FolderBrowseButton.TabIndex = 2;
|
||||
this.FolderBrowseButton.Text = "...";
|
||||
this.FolderBrowseButton.UseVisualStyleBackColor = true;
|
||||
this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click);
|
||||
//
|
||||
// FolderTextBox
|
||||
//
|
||||
this.FolderTextBox.Location = new System.Drawing.Point(90, 6);
|
||||
this.FolderTextBox.Name = "FolderTextBox";
|
||||
this.FolderTextBox.ReadOnly = true;
|
||||
this.FolderTextBox.Size = new System.Drawing.Size(251, 20);
|
||||
this.FolderTextBox.TabIndex = 1;
|
||||
//
|
||||
// ScanButton
|
||||
//
|
||||
this.ScanButton.Location = new System.Drawing.Point(380, 4);
|
||||
this.ScanButton.Name = "ScanButton";
|
||||
this.ScanButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.ScanButton.TabIndex = 0;
|
||||
this.ScanButton.Text = "Scan";
|
||||
this.ScanButton.UseVisualStyleBackColor = true;
|
||||
this.ScanButton.Click += new System.EventHandler(this.ScanButton_Click);
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 32);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.tabControl1);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.ExportCompressCheckBox);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.ExportButton);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.FileInfoLabel);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.SelectionTabControl);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(855, 492);
|
||||
this.splitContainer1.SplitterDistance = 281;
|
||||
this.splitContainer1.TabIndex = 5;
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Location = new System.Drawing.Point(0, 3);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(278, 489);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.FlattenStructureCheckBox);
|
||||
this.tabPage1.Controls.Add(this.FindButton);
|
||||
this.tabPage1.Controls.Add(this.MainTreeView);
|
||||
this.tabPage1.Controls.Add(this.label2);
|
||||
this.tabPage1.Controls.Add(this.FindTextBox);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(270, 463);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Browse";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// FlattenStructureCheckBox
|
||||
//
|
||||
this.FlattenStructureCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.FlattenStructureCheckBox.AutoSize = true;
|
||||
this.FlattenStructureCheckBox.Location = new System.Drawing.Point(3, 443);
|
||||
this.FlattenStructureCheckBox.Name = "FlattenStructureCheckBox";
|
||||
this.FlattenStructureCheckBox.Size = new System.Drawing.Size(128, 17);
|
||||
this.FlattenStructureCheckBox.TabIndex = 50;
|
||||
this.FlattenStructureCheckBox.Text = "Flatten RPF Structure";
|
||||
this.FlattenStructureCheckBox.UseVisualStyleBackColor = true;
|
||||
this.FlattenStructureCheckBox.CheckedChanged += new System.EventHandler(this.FlattenStructureCheckBox_CheckedChanged);
|
||||
//
|
||||
// FindButton
|
||||
//
|
||||
this.FindButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.FindButton.Location = new System.Drawing.Point(240, 4);
|
||||
this.FindButton.Name = "FindButton";
|
||||
this.FindButton.Size = new System.Drawing.Size(27, 22);
|
||||
this.FindButton.TabIndex = 11;
|
||||
this.FindButton.Text = ">";
|
||||
this.FindButton.UseVisualStyleBackColor = true;
|
||||
this.FindButton.Click += new System.EventHandler(this.FindButton_Click);
|
||||
//
|
||||
// MainTreeView
|
||||
//
|
||||
this.MainTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.MainTreeView.HideSelection = false;
|
||||
this.MainTreeView.Location = new System.Drawing.Point(0, 32);
|
||||
this.MainTreeView.Name = "MainTreeView";
|
||||
this.MainTreeView.Size = new System.Drawing.Size(267, 408);
|
||||
this.MainTreeView.TabIndex = 12;
|
||||
this.MainTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.MainTreeView_AfterSelect);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(4, 8);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(30, 13);
|
||||
this.label2.TabIndex = 49;
|
||||
this.label2.Text = "Find:";
|
||||
//
|
||||
// FindTextBox
|
||||
//
|
||||
this.FindTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.FindTextBox.Location = new System.Drawing.Point(38, 5);
|
||||
this.FindTextBox.Name = "FindTextBox";
|
||||
this.FindTextBox.Size = new System.Drawing.Size(199, 20);
|
||||
this.FindTextBox.TabIndex = 10;
|
||||
this.FindTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.FindTextBox_KeyPress);
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.SearchSaveResultsButton);
|
||||
this.tabPage2.Controls.Add(this.SearchIgnoreTextBox);
|
||||
this.tabPage2.Controls.Add(this.SearchIgnoreCheckBox);
|
||||
this.tabPage2.Controls.Add(this.SearchBothDirectionsCheckBox);
|
||||
this.tabPage2.Controls.Add(this.SearchCaseSensitiveCheckBox);
|
||||
this.tabPage2.Controls.Add(this.SearchHexRadioButton);
|
||||
this.tabPage2.Controls.Add(this.SearchTextRadioButton);
|
||||
this.tabPage2.Controls.Add(this.SearchResultsListView);
|
||||
this.tabPage2.Controls.Add(this.SearchAbortButton);
|
||||
this.tabPage2.Controls.Add(this.SearchButton);
|
||||
this.tabPage2.Controls.Add(this.label3);
|
||||
this.tabPage2.Controls.Add(this.SearchTextBox);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(270, 463);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Search";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// SearchSaveResultsButton
|
||||
//
|
||||
this.SearchSaveResultsButton.Enabled = false;
|
||||
this.SearchSaveResultsButton.Location = new System.Drawing.Point(178, 95);
|
||||
this.SearchSaveResultsButton.Name = "SearchSaveResultsButton";
|
||||
this.SearchSaveResultsButton.Size = new System.Drawing.Size(86, 22);
|
||||
this.SearchSaveResultsButton.TabIndex = 19;
|
||||
this.SearchSaveResultsButton.Text = "Save results...";
|
||||
this.SearchSaveResultsButton.UseVisualStyleBackColor = true;
|
||||
this.SearchSaveResultsButton.Click += new System.EventHandler(this.SearchSaveResultsButton_Click);
|
||||
//
|
||||
// SearchIgnoreTextBox
|
||||
//
|
||||
this.SearchIgnoreTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SearchIgnoreTextBox.Location = new System.Drawing.Point(65, 70);
|
||||
this.SearchIgnoreTextBox.Name = "SearchIgnoreTextBox";
|
||||
this.SearchIgnoreTextBox.Size = new System.Drawing.Size(202, 20);
|
||||
this.SearchIgnoreTextBox.TabIndex = 16;
|
||||
this.SearchIgnoreTextBox.Text = ".ydr, .ydd, .ytd, .yft, .ybn, .ycd, .awc, .bik";
|
||||
//
|
||||
// SearchIgnoreCheckBox
|
||||
//
|
||||
this.SearchIgnoreCheckBox.AutoSize = true;
|
||||
this.SearchIgnoreCheckBox.Checked = true;
|
||||
this.SearchIgnoreCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.SearchIgnoreCheckBox.Location = new System.Drawing.Point(6, 72);
|
||||
this.SearchIgnoreCheckBox.Name = "SearchIgnoreCheckBox";
|
||||
this.SearchIgnoreCheckBox.Size = new System.Drawing.Size(59, 17);
|
||||
this.SearchIgnoreCheckBox.TabIndex = 15;
|
||||
this.SearchIgnoreCheckBox.Text = "Ignore:";
|
||||
this.SearchIgnoreCheckBox.UseVisualStyleBackColor = true;
|
||||
this.SearchIgnoreCheckBox.CheckedChanged += new System.EventHandler(this.SearchIgnoreCheckBox_CheckedChanged);
|
||||
//
|
||||
// SearchBothDirectionsCheckBox
|
||||
//
|
||||
this.SearchBothDirectionsCheckBox.AutoSize = true;
|
||||
this.SearchBothDirectionsCheckBox.Checked = true;
|
||||
this.SearchBothDirectionsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.SearchBothDirectionsCheckBox.Location = new System.Drawing.Point(106, 50);
|
||||
this.SearchBothDirectionsCheckBox.Name = "SearchBothDirectionsCheckBox";
|
||||
this.SearchBothDirectionsCheckBox.Size = new System.Drawing.Size(96, 17);
|
||||
this.SearchBothDirectionsCheckBox.TabIndex = 14;
|
||||
this.SearchBothDirectionsCheckBox.Text = "Both directions";
|
||||
this.SearchBothDirectionsCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// SearchCaseSensitiveCheckBox
|
||||
//
|
||||
this.SearchCaseSensitiveCheckBox.AutoSize = true;
|
||||
this.SearchCaseSensitiveCheckBox.Location = new System.Drawing.Point(6, 50);
|
||||
this.SearchCaseSensitiveCheckBox.Name = "SearchCaseSensitiveCheckBox";
|
||||
this.SearchCaseSensitiveCheckBox.Size = new System.Drawing.Size(94, 17);
|
||||
this.SearchCaseSensitiveCheckBox.TabIndex = 13;
|
||||
this.SearchCaseSensitiveCheckBox.Text = "Case-sensitive";
|
||||
this.SearchCaseSensitiveCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// SearchHexRadioButton
|
||||
//
|
||||
this.SearchHexRadioButton.AutoSize = true;
|
||||
this.SearchHexRadioButton.Location = new System.Drawing.Point(155, 7);
|
||||
this.SearchHexRadioButton.Name = "SearchHexRadioButton";
|
||||
this.SearchHexRadioButton.Size = new System.Drawing.Size(44, 17);
|
||||
this.SearchHexRadioButton.TabIndex = 12;
|
||||
this.SearchHexRadioButton.Text = "Hex";
|
||||
this.SearchHexRadioButton.UseVisualStyleBackColor = true;
|
||||
this.SearchHexRadioButton.CheckedChanged += new System.EventHandler(this.SearchHexRadioButton_CheckedChanged);
|
||||
//
|
||||
// SearchTextRadioButton
|
||||
//
|
||||
this.SearchTextRadioButton.AutoSize = true;
|
||||
this.SearchTextRadioButton.Checked = true;
|
||||
this.SearchTextRadioButton.Location = new System.Drawing.Point(103, 7);
|
||||
this.SearchTextRadioButton.Name = "SearchTextRadioButton";
|
||||
this.SearchTextRadioButton.Size = new System.Drawing.Size(46, 17);
|
||||
this.SearchTextRadioButton.TabIndex = 11;
|
||||
this.SearchTextRadioButton.TabStop = true;
|
||||
this.SearchTextRadioButton.Text = "Text";
|
||||
this.SearchTextRadioButton.UseVisualStyleBackColor = true;
|
||||
this.SearchTextRadioButton.CheckedChanged += new System.EventHandler(this.SearchTextRadioButton_CheckedChanged);
|
||||
//
|
||||
// SearchResultsListView
|
||||
//
|
||||
this.SearchResultsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SearchResultsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader1,
|
||||
this.columnHeader2});
|
||||
this.SearchResultsListView.FullRowSelect = true;
|
||||
this.SearchResultsListView.HideSelection = false;
|
||||
this.SearchResultsListView.Location = new System.Drawing.Point(0, 123);
|
||||
this.SearchResultsListView.MultiSelect = false;
|
||||
this.SearchResultsListView.Name = "SearchResultsListView";
|
||||
this.SearchResultsListView.Size = new System.Drawing.Size(267, 340);
|
||||
this.SearchResultsListView.TabIndex = 20;
|
||||
this.SearchResultsListView.UseCompatibleStateImageBehavior = false;
|
||||
this.SearchResultsListView.View = System.Windows.Forms.View.Details;
|
||||
this.SearchResultsListView.VirtualMode = true;
|
||||
this.SearchResultsListView.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.SearchResultsListView_RetrieveVirtualItem);
|
||||
this.SearchResultsListView.SelectedIndexChanged += new System.EventHandler(this.SearchResultsListView_SelectedIndexChanged);
|
||||
//
|
||||
// columnHeader1
|
||||
//
|
||||
this.columnHeader1.Text = "File";
|
||||
this.columnHeader1.Width = 176;
|
||||
//
|
||||
// columnHeader2
|
||||
//
|
||||
this.columnHeader2.Text = "Offset";
|
||||
//
|
||||
// SearchAbortButton
|
||||
//
|
||||
this.SearchAbortButton.Location = new System.Drawing.Point(87, 95);
|
||||
this.SearchAbortButton.Name = "SearchAbortButton";
|
||||
this.SearchAbortButton.Size = new System.Drawing.Size(75, 22);
|
||||
this.SearchAbortButton.TabIndex = 18;
|
||||
this.SearchAbortButton.Text = "Abort";
|
||||
this.SearchAbortButton.UseVisualStyleBackColor = true;
|
||||
this.SearchAbortButton.Click += new System.EventHandler(this.SearchAbortButton_Click);
|
||||
//
|
||||
// SearchButton
|
||||
//
|
||||
this.SearchButton.Location = new System.Drawing.Point(6, 95);
|
||||
this.SearchButton.Name = "SearchButton";
|
||||
this.SearchButton.Size = new System.Drawing.Size(75, 22);
|
||||
this.SearchButton.TabIndex = 17;
|
||||
this.SearchButton.Text = "Search";
|
||||
this.SearchButton.UseVisualStyleBackColor = true;
|
||||
this.SearchButton.Click += new System.EventHandler(this.SearchButton_Click);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(4, 9);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(91, 13);
|
||||
this.label3.TabIndex = 52;
|
||||
this.label3.Text = "Search in files for:";
|
||||
//
|
||||
// SearchTextBox
|
||||
//
|
||||
this.SearchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SearchTextBox.Location = new System.Drawing.Point(3, 27);
|
||||
this.SearchTextBox.Name = "SearchTextBox";
|
||||
this.SearchTextBox.Size = new System.Drawing.Size(264, 20);
|
||||
this.SearchTextBox.TabIndex = 10;
|
||||
//
|
||||
// ExportCompressCheckBox
|
||||
//
|
||||
this.ExportCompressCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ExportCompressCheckBox.AutoSize = true;
|
||||
this.ExportCompressCheckBox.Location = new System.Drawing.Point(414, 5);
|
||||
this.ExportCompressCheckBox.Name = "ExportCompressCheckBox";
|
||||
this.ExportCompressCheckBox.Size = new System.Drawing.Size(72, 17);
|
||||
this.ExportCompressCheckBox.TabIndex = 105;
|
||||
this.ExportCompressCheckBox.Text = "Compress";
|
||||
this.ExportCompressCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ExportButton
|
||||
//
|
||||
this.ExportButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ExportButton.Location = new System.Drawing.Point(488, 2);
|
||||
this.ExportButton.Name = "ExportButton";
|
||||
this.ExportButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.ExportButton.TabIndex = 104;
|
||||
this.ExportButton.Text = "Export...";
|
||||
this.ExportButton.UseVisualStyleBackColor = true;
|
||||
this.ExportButton.Click += new System.EventHandler(this.ExportButton_Click);
|
||||
//
|
||||
// FileInfoLabel
|
||||
//
|
||||
this.FileInfoLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.FileInfoLabel.AutoEllipsis = true;
|
||||
this.FileInfoLabel.Location = new System.Drawing.Point(7, 6);
|
||||
this.FileInfoLabel.Name = "FileInfoLabel";
|
||||
this.FileInfoLabel.Size = new System.Drawing.Size(401, 16);
|
||||
this.FileInfoLabel.TabIndex = 51;
|
||||
this.FileInfoLabel.Text = "[Nothing selected]";
|
||||
//
|
||||
// SelectionTabControl
|
||||
//
|
||||
this.SelectionTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SelectionTabControl.Controls.Add(this.tabPage3);
|
||||
this.SelectionTabControl.Controls.Add(this.tabPage4);
|
||||
this.SelectionTabControl.Controls.Add(this.TexturesTabPage);
|
||||
this.SelectionTabControl.Location = new System.Drawing.Point(3, 30);
|
||||
this.SelectionTabControl.Name = "SelectionTabControl";
|
||||
this.SelectionTabControl.SelectedIndex = 0;
|
||||
this.SelectionTabControl.Size = new System.Drawing.Size(564, 462);
|
||||
this.SelectionTabControl.TabIndex = 0;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.ShowLargeFileContentsCheckBox);
|
||||
this.tabPage3.Controls.Add(this.DataHexLineCombo);
|
||||
this.tabPage3.Controls.Add(this.DataTextRadio);
|
||||
this.tabPage3.Controls.Add(this.DataHexRadio);
|
||||
this.tabPage3.Controls.Add(this.DataTextBox);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage3.Name = "tabPage3";
|
||||
this.tabPage3.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage3.Size = new System.Drawing.Size(556, 436);
|
||||
this.tabPage3.TabIndex = 0;
|
||||
this.tabPage3.Text = "Data";
|
||||
this.tabPage3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ShowLargeFileContentsCheckBox
|
||||
//
|
||||
this.ShowLargeFileContentsCheckBox.AutoSize = true;
|
||||
this.ShowLargeFileContentsCheckBox.Location = new System.Drawing.Point(395, 7);
|
||||
this.ShowLargeFileContentsCheckBox.Name = "ShowLargeFileContentsCheckBox";
|
||||
this.ShowLargeFileContentsCheckBox.Size = new System.Drawing.Size(139, 17);
|
||||
this.ShowLargeFileContentsCheckBox.TabIndex = 104;
|
||||
this.ShowLargeFileContentsCheckBox.Text = "Show large file contents";
|
||||
this.ShowLargeFileContentsCheckBox.UseVisualStyleBackColor = true;
|
||||
this.ShowLargeFileContentsCheckBox.CheckedChanged += new System.EventHandler(this.ShowLargeFileContentsCheckBox_CheckedChanged);
|
||||
//
|
||||
// DataHexLineCombo
|
||||
//
|
||||
this.DataHexLineCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.DataHexLineCombo.FormattingEnabled = true;
|
||||
this.DataHexLineCombo.Items.AddRange(new object[] {
|
||||
"8",
|
||||
"16",
|
||||
"32"});
|
||||
this.DataHexLineCombo.Location = new System.Drawing.Point(56, 5);
|
||||
this.DataHexLineCombo.Name = "DataHexLineCombo";
|
||||
this.DataHexLineCombo.Size = new System.Drawing.Size(49, 21);
|
||||
this.DataHexLineCombo.TabIndex = 101;
|
||||
this.DataHexLineCombo.SelectedIndexChanged += new System.EventHandler(this.DataHexLineCombo_SelectedIndexChanged);
|
||||
//
|
||||
// DataTextRadio
|
||||
//
|
||||
this.DataTextRadio.AutoSize = true;
|
||||
this.DataTextRadio.Location = new System.Drawing.Point(176, 6);
|
||||
this.DataTextRadio.Name = "DataTextRadio";
|
||||
this.DataTextRadio.Size = new System.Drawing.Size(46, 17);
|
||||
this.DataTextRadio.TabIndex = 102;
|
||||
this.DataTextRadio.Text = "Text";
|
||||
this.DataTextRadio.UseVisualStyleBackColor = true;
|
||||
this.DataTextRadio.CheckedChanged += new System.EventHandler(this.DataTextRadio_CheckedChanged);
|
||||
//
|
||||
// DataHexRadio
|
||||
//
|
||||
this.DataHexRadio.AutoSize = true;
|
||||
this.DataHexRadio.Checked = true;
|
||||
this.DataHexRadio.Location = new System.Drawing.Point(6, 6);
|
||||
this.DataHexRadio.Name = "DataHexRadio";
|
||||
this.DataHexRadio.Size = new System.Drawing.Size(44, 17);
|
||||
this.DataHexRadio.TabIndex = 100;
|
||||
this.DataHexRadio.TabStop = true;
|
||||
this.DataHexRadio.Text = "Hex";
|
||||
this.DataHexRadio.UseVisualStyleBackColor = true;
|
||||
this.DataHexRadio.CheckedChanged += new System.EventHandler(this.DataHexRadio_CheckedChanged);
|
||||
//
|
||||
// DataTextBox
|
||||
//
|
||||
this.DataTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.DataTextBox.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.DataTextBox.HideSelection = false;
|
||||
this.DataTextBox.Location = new System.Drawing.Point(6, 29);
|
||||
this.DataTextBox.Multiline = true;
|
||||
this.DataTextBox.Name = "DataTextBox";
|
||||
this.DataTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.DataTextBox.Size = new System.Drawing.Size(544, 401);
|
||||
this.DataTextBox.TabIndex = 103;
|
||||
this.DataTextBox.Text = "[Please select a data file]";
|
||||
this.DataTextBox.WordWrap = false;
|
||||
//
|
||||
// tabPage4
|
||||
//
|
||||
this.tabPage4.Controls.Add(this.DetailsPropertyGrid);
|
||||
this.tabPage4.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage4.Name = "tabPage4";
|
||||
this.tabPage4.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage4.Size = new System.Drawing.Size(556, 436);
|
||||
this.tabPage4.TabIndex = 1;
|
||||
this.tabPage4.Text = "Details";
|
||||
this.tabPage4.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// DetailsPropertyGrid
|
||||
//
|
||||
this.DetailsPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.DetailsPropertyGrid.Location = new System.Drawing.Point(6, 6);
|
||||
this.DetailsPropertyGrid.Name = "DetailsPropertyGrid";
|
||||
this.DetailsPropertyGrid.Size = new System.Drawing.Size(544, 424);
|
||||
this.DetailsPropertyGrid.TabIndex = 104;
|
||||
//
|
||||
// TexturesTabPage
|
||||
//
|
||||
this.TexturesTabPage.Controls.Add(this.splitContainer2);
|
||||
this.TexturesTabPage.Location = new System.Drawing.Point(4, 22);
|
||||
this.TexturesTabPage.Name = "TexturesTabPage";
|
||||
this.TexturesTabPage.Size = new System.Drawing.Size(556, 436);
|
||||
this.TexturesTabPage.TabIndex = 2;
|
||||
this.TexturesTabPage.Text = "Textures";
|
||||
this.TexturesTabPage.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// splitContainer2
|
||||
//
|
||||
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer2.Name = "splitContainer2";
|
||||
//
|
||||
// splitContainer2.Panel1
|
||||
//
|
||||
this.splitContainer2.Panel1.Controls.Add(this.SelTexturesListView);
|
||||
//
|
||||
// splitContainer2.Panel2
|
||||
//
|
||||
this.splitContainer2.Panel2.Controls.Add(this.SelTextureMipLabel);
|
||||
this.splitContainer2.Panel2.Controls.Add(this.label5);
|
||||
this.splitContainer2.Panel2.Controls.Add(this.SelTextureDimensionsLabel);
|
||||
this.splitContainer2.Panel2.Controls.Add(this.SelTextureMipTrackBar);
|
||||
this.splitContainer2.Panel2.Controls.Add(this.label4);
|
||||
this.splitContainer2.Panel2.Controls.Add(this.SelTextureNameTextBox);
|
||||
this.splitContainer2.Panel2.Controls.Add(this.SelTexturePictureBox);
|
||||
this.splitContainer2.Size = new System.Drawing.Size(556, 436);
|
||||
this.splitContainer2.SplitterDistance = 177;
|
||||
this.splitContainer2.TabIndex = 0;
|
||||
//
|
||||
// SelTexturesListView
|
||||
//
|
||||
this.SelTexturesListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SelTexturesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader5});
|
||||
this.SelTexturesListView.FullRowSelect = true;
|
||||
this.SelTexturesListView.HideSelection = false;
|
||||
this.SelTexturesListView.Location = new System.Drawing.Point(3, 3);
|
||||
this.SelTexturesListView.MultiSelect = false;
|
||||
this.SelTexturesListView.Name = "SelTexturesListView";
|
||||
this.SelTexturesListView.Size = new System.Drawing.Size(171, 430);
|
||||
this.SelTexturesListView.TabIndex = 21;
|
||||
this.SelTexturesListView.UseCompatibleStateImageBehavior = false;
|
||||
this.SelTexturesListView.View = System.Windows.Forms.View.Details;
|
||||
this.SelTexturesListView.SelectedIndexChanged += new System.EventHandler(this.SelTexturesListView_SelectedIndexChanged);
|
||||
//
|
||||
// columnHeader5
|
||||
//
|
||||
this.columnHeader5.Text = "Texture";
|
||||
this.columnHeader5.Width = 146;
|
||||
//
|
||||
// SelTextureMipLabel
|
||||
//
|
||||
this.SelTextureMipLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.SelTextureMipLabel.AutoSize = true;
|
||||
this.SelTextureMipLabel.Location = new System.Drawing.Point(41, 401);
|
||||
this.SelTextureMipLabel.Name = "SelTextureMipLabel";
|
||||
this.SelTextureMipLabel.Size = new System.Drawing.Size(13, 13);
|
||||
this.SelTextureMipLabel.TabIndex = 44;
|
||||
this.SelTextureMipLabel.Text = "0";
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(10, 10);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(38, 13);
|
||||
this.label5.TabIndex = 43;
|
||||
this.label5.Text = "Name:";
|
||||
//
|
||||
// SelTextureDimensionsLabel
|
||||
//
|
||||
this.SelTextureDimensionsLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SelTextureDimensionsLabel.AutoSize = true;
|
||||
this.SelTextureDimensionsLabel.Location = new System.Drawing.Point(301, 401);
|
||||
this.SelTextureDimensionsLabel.Name = "SelTextureDimensionsLabel";
|
||||
this.SelTextureDimensionsLabel.Size = new System.Drawing.Size(10, 13);
|
||||
this.SelTextureDimensionsLabel.TabIndex = 42;
|
||||
this.SelTextureDimensionsLabel.Text = "-";
|
||||
//
|
||||
// SelTextureMipTrackBar
|
||||
//
|
||||
this.SelTextureMipTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SelTextureMipTrackBar.AutoSize = false;
|
||||
this.SelTextureMipTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.SelTextureMipTrackBar.LargeChange = 1;
|
||||
this.SelTextureMipTrackBar.Location = new System.Drawing.Point(60, 395);
|
||||
this.SelTextureMipTrackBar.Maximum = 0;
|
||||
this.SelTextureMipTrackBar.Name = "SelTextureMipTrackBar";
|
||||
this.SelTextureMipTrackBar.Size = new System.Drawing.Size(234, 31);
|
||||
this.SelTextureMipTrackBar.TabIndex = 41;
|
||||
this.SelTextureMipTrackBar.Scroll += new System.EventHandler(this.SelTextureMipTrackBar_Scroll);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(10, 401);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(27, 13);
|
||||
this.label4.TabIndex = 40;
|
||||
this.label4.Text = "Mip:";
|
||||
//
|
||||
// SelTextureNameTextBox
|
||||
//
|
||||
this.SelTextureNameTextBox.Location = new System.Drawing.Point(60, 7);
|
||||
this.SelTextureNameTextBox.Name = "SelTextureNameTextBox";
|
||||
this.SelTextureNameTextBox.Size = new System.Drawing.Size(192, 20);
|
||||
this.SelTextureNameTextBox.TabIndex = 39;
|
||||
//
|
||||
// SelTexturePictureBox
|
||||
//
|
||||
this.SelTexturePictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.SelTexturePictureBox.BackColor = System.Drawing.Color.DarkGray;
|
||||
this.SelTexturePictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.SelTexturePictureBox.Location = new System.Drawing.Point(3, 33);
|
||||
this.SelTexturePictureBox.Name = "SelTexturePictureBox";
|
||||
this.SelTexturePictureBox.Size = new System.Drawing.Size(369, 351);
|
||||
this.SelTexturePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.SelTexturePictureBox.TabIndex = 38;
|
||||
this.SelTexturePictureBox.TabStop = false;
|
||||
//
|
||||
// MainStatusStrip
|
||||
//
|
||||
this.MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.StatusLabel});
|
||||
this.MainStatusStrip.Location = new System.Drawing.Point(0, 527);
|
||||
this.MainStatusStrip.Name = "MainStatusStrip";
|
||||
this.MainStatusStrip.Size = new System.Drawing.Size(855, 22);
|
||||
this.MainStatusStrip.TabIndex = 50;
|
||||
this.MainStatusStrip.Text = "statusStrip1";
|
||||
//
|
||||
// StatusLabel
|
||||
//
|
||||
this.StatusLabel.Name = "StatusLabel";
|
||||
this.StatusLabel.Size = new System.Drawing.Size(840, 17);
|
||||
this.StatusLabel.Spring = true;
|
||||
this.StatusLabel.Text = "Scan the GTAV folder to begin.";
|
||||
this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// TestAllButton
|
||||
//
|
||||
this.TestAllButton.Location = new System.Drawing.Point(537, 4);
|
||||
this.TestAllButton.Name = "TestAllButton";
|
||||
this.TestAllButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.TestAllButton.TabIndex = 3;
|
||||
this.TestAllButton.Text = "Test all files";
|
||||
this.TestAllButton.UseVisualStyleBackColor = true;
|
||||
this.TestAllButton.Click += new System.EventHandler(this.TestAllButton_Click);
|
||||
//
|
||||
// AbortButton
|
||||
//
|
||||
this.AbortButton.Location = new System.Drawing.Point(618, 4);
|
||||
this.AbortButton.Name = "AbortButton";
|
||||
this.AbortButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.AbortButton.TabIndex = 4;
|
||||
this.AbortButton.Text = "Abort";
|
||||
this.AbortButton.UseVisualStyleBackColor = true;
|
||||
this.AbortButton.Click += new System.EventHandler(this.AbortButton_Click);
|
||||
//
|
||||
// SaveFileDialog
|
||||
//
|
||||
this.SaveFileDialog.AddExtension = false;
|
||||
//
|
||||
// BrowseForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(855, 549);
|
||||
this.Controls.Add(this.AbortButton);
|
||||
this.Controls.Add(this.TestAllButton);
|
||||
this.Controls.Add(this.MainStatusStrip);
|
||||
this.Controls.Add(this.splitContainer1);
|
||||
this.Controls.Add(this.ScanButton);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.FolderBrowseButton);
|
||||
this.Controls.Add(this.FolderTextBox);
|
||||
this.DoubleBuffered = true;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Name = "BrowseForm";
|
||||
this.Text = "RPF Browser - CodeWalker by dexyfex";
|
||||
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.BrowseForm_FormClosed);
|
||||
this.Load += new System.EventHandler(this.BrowseForm_Load);
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage1.PerformLayout();
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage2.PerformLayout();
|
||||
this.SelectionTabControl.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.tabPage3.PerformLayout();
|
||||
this.tabPage4.ResumeLayout(false);
|
||||
this.TexturesTabPage.ResumeLayout(false);
|
||||
this.splitContainer2.Panel1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel2.ResumeLayout(false);
|
||||
this.splitContainer2.Panel2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
|
||||
this.splitContainer2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SelTexturePictureBox)).EndInit();
|
||||
this.MainStatusStrip.ResumeLayout(false);
|
||||
this.MainStatusStrip.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Button FolderBrowseButton;
|
||||
private System.Windows.Forms.TextBox FolderTextBox;
|
||||
private System.Windows.Forms.Button ScanButton;
|
||||
private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog;
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private System.Windows.Forms.TreeView MainTreeView;
|
||||
private System.Windows.Forms.StatusStrip MainStatusStrip;
|
||||
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private System.Windows.Forms.TabControl SelectionTabControl;
|
||||
private System.Windows.Forms.TabPage tabPage3;
|
||||
private System.Windows.Forms.TabPage tabPage4;
|
||||
private System.Windows.Forms.RadioButton DataTextRadio;
|
||||
private System.Windows.Forms.RadioButton DataHexRadio;
|
||||
private System.Windows.Forms.TextBox DataTextBox;
|
||||
private System.Windows.Forms.ComboBox DataHexLineCombo;
|
||||
private System.Windows.Forms.Label FileInfoLabel;
|
||||
private System.Windows.Forms.Button TestAllButton;
|
||||
private System.Windows.Forms.Button AbortButton;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox FindTextBox;
|
||||
private System.Windows.Forms.Button FindButton;
|
||||
private System.Windows.Forms.Button ExportButton;
|
||||
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
|
||||
private CodeWalker.WinForms.PropertyGridFix DetailsPropertyGrid;
|
||||
private System.Windows.Forms.Button SearchAbortButton;
|
||||
private System.Windows.Forms.Button SearchButton;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox SearchTextBox;
|
||||
private System.Windows.Forms.RadioButton SearchHexRadioButton;
|
||||
private System.Windows.Forms.RadioButton SearchTextRadioButton;
|
||||
private System.Windows.Forms.ListView SearchResultsListView;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
||||
private System.Windows.Forms.CheckBox SearchBothDirectionsCheckBox;
|
||||
private System.Windows.Forms.CheckBox SearchCaseSensitiveCheckBox;
|
||||
private System.Windows.Forms.TextBox SearchIgnoreTextBox;
|
||||
private System.Windows.Forms.CheckBox SearchIgnoreCheckBox;
|
||||
private System.Windows.Forms.TabPage TexturesTabPage;
|
||||
private System.Windows.Forms.SplitContainer splitContainer2;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.Label SelTextureDimensionsLabel;
|
||||
private System.Windows.Forms.TrackBar SelTextureMipTrackBar;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.TextBox SelTextureNameTextBox;
|
||||
private System.Windows.Forms.PictureBox SelTexturePictureBox;
|
||||
private System.Windows.Forms.ListView SelTexturesListView;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader5;
|
||||
private System.Windows.Forms.Label SelTextureMipLabel;
|
||||
private System.Windows.Forms.CheckBox ShowLargeFileContentsCheckBox;
|
||||
private System.Windows.Forms.CheckBox ExportCompressCheckBox;
|
||||
private System.Windows.Forms.CheckBox FlattenStructureCheckBox;
|
||||
private System.Windows.Forms.Button SearchSaveResultsButton;
|
||||
}
|
||||
}
|
1288
BrowseForm.cs
Normal file
1288
BrowseForm.cs
Normal file
File diff suppressed because it is too large
Load Diff
418
BrowseForm.resx
Normal file
418
BrowseForm.resx
Normal file
@ -0,0 +1,418 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="FolderBrowserDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="MainStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>182, 17</value>
|
||||
</metadata>
|
||||
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>320, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v//
|
||||
/////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO
|
||||
6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f//
|
||||
/wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA
|
||||
AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc
|
||||
skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU
|
||||
0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq
|
||||
+ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz
|
||||
/eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR
|
||||
p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm
|
||||
+P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB
|
||||
AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/
|
||||
/f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/
|
||||
+fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd
|
||||
4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
|
||||
1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2OL+NjZ7AAArX2Ok
|
||||
4uz/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
|
||||
2eP/LjJ1DAxKfYTE4Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//v7//f7//f7//v7//v//
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
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
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/
|
||||
/P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/
|
||||
/f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
|
||||
///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB///////
|
||||
//AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA
|
||||
H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A
|
||||
A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA
|
||||
/f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A
|
||||
AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf
|
||||
AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4
|
||||
AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A//
|
||||
///////gD/////////Af//////////////8=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
1
CodeWalker Explorer.cmd
Normal file
1
CodeWalker Explorer.cmd
Normal file
@ -0,0 +1 @@
|
||||
start codewalker explorer
|
1
CodeWalker Menu.cmd
Normal file
1
CodeWalker Menu.cmd
Normal file
@ -0,0 +1 @@
|
||||
start codewalker menu
|
145
CodeWalker.Core/CodeWalker.Core.csproj
Normal file
145
CodeWalker.Core/CodeWalker.Core.csproj
Normal file
@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{DE50D3A6-B49E-47A0-ABE6-101473A00759}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CodeWalker.Core</RootNamespace>
|
||||
<AssemblyName>CodeWalker.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="SharpDX, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpDX.4.0.1\lib\net45\SharpDX.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SharpDX.Mathematics, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpDX.Mathematics.4.0.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="GameFiles\FileTypes\AwcFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\CacheDatFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\CutFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\DlcContentFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\DlcSetupFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\FxcFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\GtxdFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\Gxt2File.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\JPsoFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\RelFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\Stats.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YbnFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YcdFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YddFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YdrFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YftFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YmapFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YmfFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YmtFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YndFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YnvFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YptFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YtdFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YtypFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YvrFile.cs" />
|
||||
<Compile Include="GameFiles\FileTypes\YwrFile.cs" />
|
||||
<Compile Include="GameFiles\GameFile.cs" />
|
||||
<Compile Include="GameFiles\GameFileCache.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\Archetype.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\Meta.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\MetaBuilder.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\MetaNames.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\MetaTypes.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\MetaXml.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\Pso.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\PsoTypes.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\Rbf.cs" />
|
||||
<Compile Include="GameFiles\MetaTypes\XmlMeta.cs" />
|
||||
<Compile Include="GameFiles\Resources\Bounds.cs" />
|
||||
<Compile Include="GameFiles\Resources\Clip.cs" />
|
||||
<Compile Include="GameFiles\Resources\Drawable.cs" />
|
||||
<Compile Include="GameFiles\Resources\Frag.cs" />
|
||||
<Compile Include="GameFiles\Resources\Nav.cs" />
|
||||
<Compile Include="GameFiles\Resources\Node.cs" />
|
||||
<Compile Include="GameFiles\Resources\Particle.cs" />
|
||||
<Compile Include="GameFiles\Resources\ResourceBaseTypes.cs" />
|
||||
<Compile Include="GameFiles\Resources\ResourceBuilder.cs" />
|
||||
<Compile Include="GameFiles\Resources\ResourceData.cs" />
|
||||
<Compile Include="GameFiles\Resources\ResourceFile.cs" />
|
||||
<Compile Include="GameFiles\Resources\Texture.cs" />
|
||||
<Compile Include="GameFiles\Resources\VehicleRecord.cs" />
|
||||
<Compile Include="GameFiles\Resources\VertexType.cs" />
|
||||
<Compile Include="GameFiles\Resources\WaypointRecord.cs" />
|
||||
<Compile Include="GameFiles\RpfFile.cs" />
|
||||
<Compile Include="GameFiles\RpfManager.cs" />
|
||||
<Compile Include="GameFiles\Utils\Data.cs" />
|
||||
<Compile Include="GameFiles\Utils\GTACrypto.cs" />
|
||||
<Compile Include="GameFiles\Utils\GTAKeys.cs" />
|
||||
<Compile Include="GameFiles\Utils\Jenk.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Utils\Cache.cs" />
|
||||
<Compile Include="Utils\Matrices.cs" />
|
||||
<Compile Include="Utils\Quaternions.cs" />
|
||||
<Compile Include="Utils\Utils.cs" />
|
||||
<Compile Include="Utils\Vectors.cs" />
|
||||
<Compile Include="Utils\Xml.cs" />
|
||||
<Compile Include="World\AudioZones.cs" />
|
||||
<Compile Include="World\Camera.cs" />
|
||||
<Compile Include="World\Clouds.cs" />
|
||||
<Compile Include="World\Entity.cs" />
|
||||
<Compile Include="World\PopZones.cs" />
|
||||
<Compile Include="World\Scenarios.cs" />
|
||||
<Compile Include="World\Space.cs" />
|
||||
<Compile Include="World\Timecycle.cs" />
|
||||
<Compile Include="World\TimecycleMods.cs" />
|
||||
<Compile Include="World\Trains.cs" />
|
||||
<Compile Include="World\Water.cs" />
|
||||
<Compile Include="World\Weather.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Resources\magic.dat" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
792
CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs
Normal file
792
CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs
Normal file
@ -0,0 +1,792 @@
|
||||
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; }
|
||||
|
||||
static public void Decrypt_RSXXTEA(byte[] data, uint[] key)
|
||||
{
|
||||
// Rockstar's modified version of XXTEA
|
||||
uint[] blocks = new uint[data.Length / 4];
|
||||
Buffer.BlockCopy(data, 0, blocks, 0, data.Length);
|
||||
|
||||
int block_count = blocks.Length;
|
||||
uint a, b = blocks[0], i;
|
||||
|
||||
i = (uint)(0x9E3779B9 * (6 + 52 / block_count));
|
||||
do
|
||||
{
|
||||
for (int block_index = block_count - 1; block_index >= 0; --block_index)
|
||||
{
|
||||
a = blocks[(block_index > 0 ? block_index : block_count) - 1];
|
||||
b = blocks[block_index] -= (a >> 5 ^ b << 2) + (b >> 3 ^ a << 4) ^ (i ^ b) + (key[block_index & 3 ^ (i >> 2 & 3)] ^ a ^ 0x7B3A207F);
|
||||
}
|
||||
i -= 0x9E3779B9;
|
||||
} while (i != 0);
|
||||
|
||||
Buffer.BlockCopy(blocks, 0, data, 0, data.Length);
|
||||
}
|
||||
|
||||
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...
|
||||
}
|
||||
|
||||
Endianess endianess = Endianess.LittleEndian;
|
||||
|
||||
Magic = BitConverter.ToUInt32(data, 0);
|
||||
if (Magic != 0x54414441 && Magic != 0x41444154)
|
||||
{
|
||||
if (data.Length % 4 == 0)
|
||||
{
|
||||
Decrypt_RSXXTEA(data, GTA5Keys.PC_AWC_KEY);
|
||||
Magic = BitConverter.ToUInt32(data, 0);
|
||||
} else
|
||||
ErrorMessage = "Corrupted data!";
|
||||
}
|
||||
|
||||
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 LoopPoint { get; set; }
|
||||
public ushort SamplesPerSecond { get; set; }
|
||||
public short Headroom { get; set; }
|
||||
public ushort LoopBegin { get; set; }
|
||||
public ushort LoopEnd { get; set; }
|
||||
public ushort PlayEnd { get; set; }
|
||||
public byte PlayBegin { get; set; }
|
||||
|
||||
public enum CodecFormat {
|
||||
PCM = 0,
|
||||
ADPCM = 4
|
||||
}
|
||||
public CodecFormat Codec { get; set; }
|
||||
|
||||
public AwcFormatChunk(DataReader r)
|
||||
{
|
||||
Samples = r.ReadUInt32();
|
||||
LoopPoint = r.ReadInt32();
|
||||
SamplesPerSecond = r.ReadUInt16();
|
||||
Headroom = r.ReadInt16();
|
||||
LoopBegin = r.ReadUInt16();
|
||||
LoopEnd = r.ReadUInt16();
|
||||
PlayEnd = r.ReadUInt16();
|
||||
PlayBegin = r.ReadByte();
|
||||
Codec = (CodecFormat)r.ReadByte();
|
||||
|
||||
//Apparently sometimes this struct is longer? TODO: fix??
|
||||
//r.ReadUInt16();
|
||||
//r.ReadUInt16();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Headroom.ToString() + ", " + Codec.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 = 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 codec;
|
||||
switch (Format.Codec)
|
||||
{
|
||||
case AwcFormatChunk.CodecFormat.PCM:
|
||||
codec = "PCM";
|
||||
break;
|
||||
case AwcFormatChunk.CodecFormat.ADPCM:
|
||||
codec = "ADPCM";
|
||||
break;
|
||||
default:
|
||||
codec = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
var hz = Format.SamplesPerSecond;
|
||||
|
||||
return codec + ((hz > 0) ? (", " + hz.ToString() + " Hz") : "");
|
||||
}
|
||||
}
|
||||
|
||||
public float Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return Format == null ? 0 : (float)Format.Samples / Format.SamplesPerSecond;
|
||||
}
|
||||
}
|
||||
|
||||
public string LengthStr
|
||||
{
|
||||
get
|
||||
{
|
||||
return TimeSpan.FromSeconds(Length).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 byte[] DecodeADPCM(byte[] data, int sampleCount)
|
||||
{
|
||||
byte[] dataPCM = new byte[data.Length * 4];
|
||||
int predictor = 0, step_index = 0, step = 0;
|
||||
int readingOffset = 0, writingOffset = 0, bytesInBlock = 0;
|
||||
|
||||
int[] ima_index_table = {
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
-1, -1, -1, -1, 2, 4, 6, 8
|
||||
};
|
||||
|
||||
short[] ima_step_table = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
||||
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
||||
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
|
||||
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
|
||||
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
|
||||
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
|
||||
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
|
||||
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
|
||||
};
|
||||
|
||||
int clip(int value, int min, int max)
|
||||
{
|
||||
if (value < min)
|
||||
return min;
|
||||
if (value > max)
|
||||
return max;
|
||||
return value;
|
||||
}
|
||||
|
||||
void parseNibble(byte nibble)
|
||||
{
|
||||
step_index = clip(step_index + ima_index_table[nibble], 0, 88);
|
||||
|
||||
int diff = step >> 3;
|
||||
if ((nibble & 4) > 0) diff += step;
|
||||
if ((nibble & 2) > 0) diff += step >> 1;
|
||||
if ((nibble & 1) > 0) diff += step >> 2;
|
||||
if ((nibble & 8) > 0) predictor -= diff;
|
||||
else predictor += diff;
|
||||
|
||||
step = ima_step_table[step_index];
|
||||
|
||||
int samplePCM = clip(predictor, -32768, 32767);
|
||||
dataPCM[writingOffset] = (byte)(samplePCM & 0xFF);
|
||||
dataPCM[writingOffset + 1] = (byte)((samplePCM >> 8) & 0xFF);
|
||||
writingOffset += 2;
|
||||
}
|
||||
|
||||
while ((readingOffset < data.Length) && (sampleCount > 0))
|
||||
{
|
||||
if (bytesInBlock == 0)
|
||||
{
|
||||
step_index = clip(data[readingOffset], 0, 88);
|
||||
predictor = BitConverter.ToInt16(data, readingOffset + 2);
|
||||
step = ima_step_table[step_index];
|
||||
bytesInBlock = 2044;
|
||||
readingOffset += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
parseNibble((byte)(data[readingOffset] & 0x0F));
|
||||
parseNibble((byte)((data[readingOffset] >> 4) & 0x0F));
|
||||
bytesInBlock--;
|
||||
sampleCount -= 2;
|
||||
readingOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
return dataPCM;
|
||||
}
|
||||
|
||||
public Stream GetWavStream()
|
||||
{
|
||||
byte[] dataPCM = null;
|
||||
int bitsPerSample = BitsPerSample;
|
||||
|
||||
switch (Format.Codec)
|
||||
{
|
||||
case AwcFormatChunk.CodecFormat.PCM:
|
||||
dataPCM = Data;
|
||||
break;
|
||||
case AwcFormatChunk.CodecFormat.ADPCM:
|
||||
dataPCM = new byte[Data.Length];
|
||||
Buffer.BlockCopy(Data, 0, dataPCM, 0, Data.Length);
|
||||
AwcFile.Decrypt_RSXXTEA(dataPCM, GTA5Keys.PC_AWC_KEY);
|
||||
dataPCM = DecodeADPCM(dataPCM, SampleCount);
|
||||
bitsPerSample = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
int byteRate = SamplesPerSecond * Channels * bitsPerSample / 8;
|
||||
short blockAlign = (short)(Channels * bitsPerSample / 8);
|
||||
|
||||
MemoryStream stream = new MemoryStream();
|
||||
BinaryWriter w = new BinaryWriter(stream);
|
||||
int wavLength = 12 + 24 + 8 + Data.Length;
|
||||
|
||||
// RIFF chunk
|
||||
w.Write("RIFF".ToCharArray());
|
||||
w.Write((int)(wavLength - 8));
|
||||
w.Write("WAVE".ToCharArray());
|
||||
|
||||
// fmt sub-chunk
|
||||
w.Write("fmt ".ToCharArray());
|
||||
w.Write((int)16); // fmt size
|
||||
w.Write((short)1); // 1 = WAVE_FORMAT_PCM
|
||||
w.Write((short)Channels);
|
||||
w.Write((int)SamplesPerSecond);
|
||||
w.Write((int)byteRate);
|
||||
w.Write((short)blockAlign);
|
||||
w.Write((short)bitsPerSample);
|
||||
|
||||
// data sub-chunk
|
||||
w.Write("data".ToCharArray());
|
||||
w.Write((int)dataPCM.Length);
|
||||
w.Write(dataPCM);
|
||||
|
||||
w.Flush();
|
||||
stream.Position = 0;
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
[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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
700
CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs
Normal file
700
CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs
Normal file
@ -0,0 +1,700 @@
|
||||
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 string Version { 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);
|
||||
}
|
||||
Version = sb.ToString().Replace("[VERSION]", "").Replace("\r", "").Replace("\n", "");
|
||||
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 void LoadXml(string xml)
|
||||
{
|
||||
}
|
||||
|
||||
public string GetXml()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine(MetaXmlBase.XmlHeader);
|
||||
sb.AppendLine(string.Format("<CacheDatFile version=\"{0}\">", Version));
|
||||
sb.AppendLine(" <fileDates>");
|
||||
if (FileDates != null)
|
||||
{
|
||||
foreach (var date in FileDates)
|
||||
{
|
||||
sb.AppendLine(string.Format(" <fileDate>{0}</fileDate>", date.ToCacheFileString()));
|
||||
}
|
||||
}
|
||||
sb.AppendLine(" </fileDates>");
|
||||
sb.AppendLine(" <module type=\"fwMapDataStore\">");
|
||||
if (AllMapNodes != null)
|
||||
{
|
||||
foreach (var mapnode in AllMapNodes)
|
||||
{
|
||||
sb.AppendLine(" <Item>");
|
||||
sb.AppendLine(string.Format(" <name>{0}</name>", mapnode.Name.ToCleanString()));
|
||||
sb.AppendLine(string.Format(" <parent>{0}</parent>", mapnode.ParentName.ToCleanString()));
|
||||
sb.AppendLine(string.Format(" <contentFlags value=\"{0}\" />", mapnode.ContentFlags.ToString()));
|
||||
sb.AppendLine(string.Format(" <streamingExtentsMin {0} />", FloatUtil.GetVector3XmlString(mapnode.streamingExtentsMin)));
|
||||
sb.AppendLine(string.Format(" <streamingExtentsMax {0} />", FloatUtil.GetVector3XmlString(mapnode.streamingExtentsMax)));
|
||||
sb.AppendLine(string.Format(" <entitiesExtentsMin {0} />", FloatUtil.GetVector3XmlString(mapnode.entitiesExtentsMin)));
|
||||
sb.AppendLine(string.Format(" <entitiesExtentsMax {0} />", FloatUtil.GetVector3XmlString(mapnode.entitiesExtentsMax)));
|
||||
sb.AppendLine(string.Format(" <flags unk1=\"{0}\" unk2=\"{1}\" unk3=\"{2}\" />", mapnode.Unk1, mapnode.Unk2, mapnode.Unk3));
|
||||
sb.AppendLine(" </Item>");
|
||||
}
|
||||
}
|
||||
sb.AppendLine(" </module>");
|
||||
sb.AppendLine(" <module type=\"CInteriorProxy\">");
|
||||
if (AllCInteriorProxies != null)
|
||||
{
|
||||
foreach (var intprox in AllCInteriorProxies)
|
||||
{
|
||||
sb.AppendLine(" <Item>");
|
||||
sb.AppendLine(string.Format(" <name>{0}</name>", intprox.Name.ToCleanString()));
|
||||
sb.AppendLine(string.Format(" <parent>{0}</parent>", intprox.Parent.ToCleanString()));
|
||||
sb.AppendLine(string.Format(" <position {0} />", FloatUtil.GetVector3XmlString(intprox.Position)));
|
||||
sb.AppendLine(string.Format(" <rotation {0} />", FloatUtil.GetQuaternionXmlString(intprox.Orientation)));
|
||||
sb.AppendLine(string.Format(" <aabbMin {0} />", FloatUtil.GetVector3XmlString(intprox.BBMin)));
|
||||
sb.AppendLine(string.Format(" <aabbMax {0} />", FloatUtil.GetVector3XmlString(intprox.BBMax)));
|
||||
sb.AppendLine(string.Format(" <unknowns1 unk01=\"{0}\" unk03=\"{1}\" />", intprox.Unk01, intprox.Unk03));
|
||||
sb.AppendLine(string.Format(" <unknowns2 unk11=\"{0}\" unk12=\"{1}\" unk13=\"{1}\" unk14=\"{1}\" />", intprox.Unk11, intprox.Unk12, intprox.Unk13, intprox.Unk14));
|
||||
sb.AppendLine(string.Format(" <unknowns3 unk15=\"{0}\" unk16=\"{1}\" unk17=\"{1}\" unk18=\"{1}\" />", intprox.Unk15, intprox.Unk16, intprox.Unk17, intprox.Unk18));
|
||||
sb.AppendLine(" </Item>");
|
||||
}
|
||||
}
|
||||
sb.AppendLine(" </module>");
|
||||
sb.AppendLine(" <module type=\"BoundsStore\">");
|
||||
if (AllBoundsStoreItems != null)
|
||||
{
|
||||
foreach (var bndstore in AllBoundsStoreItems)
|
||||
{
|
||||
sb.AppendLine(" <Item>");
|
||||
sb.AppendLine(string.Format(" <name>{0}</name>", bndstore.Name.ToCleanString()));
|
||||
sb.AppendLine(string.Format(" <aabbMin {0} />", FloatUtil.GetVector3XmlString(bndstore.Min)));
|
||||
sb.AppendLine(string.Format(" <aabbMax {0} />", FloatUtil.GetVector3XmlString(bndstore.Max)));
|
||||
sb.AppendLine(string.Format(" <layer value=\"{0}\" />", bndstore.Layer));
|
||||
sb.AppendLine(" </Item>");
|
||||
}
|
||||
}
|
||||
sb.AppendLine(" </module>");
|
||||
sb.AppendLine("</CacheDatFile>");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (FileEntry != null)
|
||||
{
|
||||
return FileEntry.ToString();
|
||||
}
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class CacheFileDate
|
||||
{
|
||||
public MetaHash FileName { get; set; } //"resource_surrogate:/%s.rpf"
|
||||
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 string ToCacheFileString()
|
||||
{
|
||||
return FileName.Hash.ToString() + " " + TimeStamp.ToFileTimeUtc().ToString() + " " + FileID.ToString();
|
||||
}
|
||||
|
||||
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();//could be float
|
||||
Unk18 = br.ReadUInt32();
|
||||
|
||||
|
||||
|
||||
switch (Unk01)
|
||||
{
|
||||
case 0: //v_cashdepot
|
||||
case 19: //dt1_02_carpark
|
||||
case 20: //dt1_03_carpark
|
||||
case 21: //dt1_05_carpark
|
||||
case 4: //dt1_rd1_tun
|
||||
case 14: //id1_11_tunnel1_int
|
||||
case 24: //v_firedept
|
||||
case 3: //id2_21_a_tun1
|
||||
case 22: //po1_08_warehouseint1
|
||||
case 11: //sc1_rd_inttun1
|
||||
case 10: //sc1_rd_inttun2b_end
|
||||
case 18: //bt1_04_carpark
|
||||
case 16: //v_hanger
|
||||
case 1: //ap1_03_lisapark_subway
|
||||
case 13: //kt1_03_carpark_int
|
||||
case 5: //sm20_tun1
|
||||
case 2: //vbca_tunnel1
|
||||
case 15: //cs1_12_tunnel01_int
|
||||
case 6: //cs1_14brailway1
|
||||
case 9: //cs2_roadsb_tunnel_01
|
||||
case 7: //cs3_03railtunnel_int1
|
||||
case 8: //cs4_rwayb_tunnelint
|
||||
case 12: //ch1_roadsdint_tun1
|
||||
case 100: //hei_int_mph_carrierhang3
|
||||
case 47: //xm_x17dlc_int_base_ent
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Unk02 != 0)
|
||||
{ }
|
||||
|
||||
switch (Unk03)
|
||||
{
|
||||
case 6: //v_cashdepot
|
||||
case 2: //dt1_02_carpark
|
||||
case 8: //v_fib01
|
||||
case 4: //v_fib03
|
||||
case 0: //v_fib04
|
||||
case 7: //v_clotheslo
|
||||
case 1: //v_gun
|
||||
case 3: //v_genbank
|
||||
case 11: //v_hospital
|
||||
case 5: //v_shop_247
|
||||
case 32: //v_abattoir
|
||||
case 13: //v_franklins
|
||||
case 15: //v_michael
|
||||
case 18: //v_faceoffice
|
||||
case 29: //v_recycle
|
||||
case 9: //v_stadium
|
||||
case 54: //v_farmhouse
|
||||
case 12: //v_ranch
|
||||
case 26: //hei_gta_milo_bar
|
||||
case 17: //hei_gta_milo_bedrm
|
||||
case 14: //hei_gta_milo_bridge
|
||||
case 48: //apa_mpapa_yacht
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ((Unk12 == 0) || (Unk12 > 0xFFFFFF))
|
||||
{ }
|
||||
|
||||
switch (Unk14)
|
||||
{
|
||||
case 1:
|
||||
case 0:
|
||||
case 580:
|
||||
case 355: //sm_smugdlc_int_01
|
||||
case 579: //xm_x17dlc_int_01
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (Unk16)
|
||||
{
|
||||
case 1:
|
||||
case 32758: //0x7FF6
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (Unk17) //could be a float..!
|
||||
{
|
||||
case 9:
|
||||
break;
|
||||
case 0x415CBC04: //13.7959f
|
||||
case 0x7B81AC94:
|
||||
case 0x40FE3224: //7.94362f v_gun
|
||||
case 0x41515774: //13.0839f v_gun
|
||||
case 0x414E7B34: //12.9051f bkr_biker_dlc_int_03
|
||||
case 0x41389C14: //11.5381f imp_impexp_int_01
|
||||
case 0x4177B664: //15.482f gr_grdlc_int_01
|
||||
case 0xCE0404F4: // sm_smugdlc_int_01
|
||||
break;
|
||||
default:
|
||||
//string str = JenkIndex.GetString(Unk17);
|
||||
break;
|
||||
}
|
||||
switch(Unk18)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 32758: //0x7FF6
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 Unk1 { get; set; }
|
||||
public byte Unk2 { get; set; }
|
||||
public byte Unk3 { get; set; }
|
||||
public byte Unk4 { 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());
|
||||
Unk1 = br.ReadByte(); //HD flag? (critical, long, strm)
|
||||
Unk2 = br.ReadByte(); //lod flag? - primary map files
|
||||
Unk3 = br.ReadByte(); //slod flag?
|
||||
Unk4 = br.ReadByte();
|
||||
|
||||
if (Unk1 != 0)
|
||||
{ }
|
||||
if (Unk2 != 0)
|
||||
{ }
|
||||
if (Unk3 != 0)
|
||||
{ }
|
||||
if (Unk4 != 0)
|
||||
{ } //no hits here now..
|
||||
|
||||
if (Unk4 == 0xFE)
|
||||
{
|
||||
//this seems to never be hit anymore...
|
||||
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
CodeWalker.Core/GameFiles/FileTypes/CutFile.cs
Normal file
48
CodeWalker.Core/GameFiles/FileTypes/CutFile.cs
Normal 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
CodeWalker.Core/GameFiles/FileTypes/DlcContentFile.cs
Normal file
431
CodeWalker.Core/GameFiles/FileTypes/DlcContentFile.cs
Normal 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).ToLowerInvariant();
|
||||
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
CodeWalker.Core/GameFiles/FileTypes/DlcSetupFile.cs
Normal file
82
CodeWalker.Core/GameFiles/FileTypes/DlcSetupFile.cs
Normal 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)";
|
||||
}
|
||||
}
|
||||
}
|
1079
CodeWalker.Core/GameFiles/FileTypes/FxcFile.cs
Normal file
1079
CodeWalker.Core/GameFiles/FileTypes/FxcFile.cs
Normal file
File diff suppressed because it is too large
Load Diff
166
CodeWalker.Core/GameFiles/FileTypes/GtxdFile.cs
Normal file
166
CodeWalker.Core/GameFiles/FileTypes/GtxdFile.cs
Normal file
@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class GtxdFile : GameFile, PackedFile
|
||||
{
|
||||
|
||||
public RbfFile Rbf { get; set; }
|
||||
|
||||
|
||||
public Dictionary<string, string> CMapParentTxds { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
public GtxdFile() : base(null, GameFileType.Gtxd)
|
||||
{
|
||||
}
|
||||
public GtxdFile(RpfFileEntry entry) : base(entry, GameFileType.Gtxd)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Load(byte[] data, RpfFileEntry entry)
|
||||
{
|
||||
RpfFileEntry = entry;
|
||||
Name = entry.Name;
|
||||
FilePath = Name;
|
||||
|
||||
|
||||
if (entry.NameLower.EndsWith(".ymt"))
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
//not an RBF file...
|
||||
}
|
||||
}
|
||||
else if (entry.NameLower.EndsWith(".meta"))
|
||||
{
|
||||
//required for update\x64\dlcpacks\mpheist\dlc.rpf\common\data\gtxd.meta and update\x64\dlcpacks\mpluxe\dlc.rpf\common\data\gtxd.meta
|
||||
string bom = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
|
||||
string xml = Encoding.UTF8.GetString(data);
|
||||
|
||||
if (xml.StartsWith(bom, StringComparison.Ordinal))
|
||||
{
|
||||
xml = xml.Remove(0, bom.Length);
|
||||
}
|
||||
|
||||
LoadMapParentTxds(xml);
|
||||
Loaded = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void LoadMapParentTxds(RbfStructure rbfstruct)
|
||||
{
|
||||
|
||||
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 LoadMapParentTxds(string xml)
|
||||
{
|
||||
XmlDocument xmldoc = new XmlDocument();
|
||||
xmldoc.LoadXml(xml); //maybe better load xml.ToLower() and use "cmapparenttxds/txdrelationships/item" as xpath?
|
||||
XmlNodeList items = xmldoc.SelectNodes("CMapParentTxds/txdRelationships/Item | CMapParentTxds/txdRelationships/item");
|
||||
|
||||
CMapParentTxds = new Dictionary<string, string>();
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
string parentstr = Xml.GetChildInnerText(items[i], "parent");
|
||||
string childstr = Xml.GetChildInnerText(items[i], "child");
|
||||
|
||||
if ((!string.IsNullOrEmpty(parentstr)) && (!string.IsNullOrEmpty(childstr)))
|
||||
{
|
||||
if (!CMapParentTxds.ContainsKey(childstr))
|
||||
{
|
||||
CMapParentTxds.Add(childstr, parentstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
164
CodeWalker.Core/GameFiles/FileTypes/Gxt2File.cs
Normal file
164
CodeWalker.Core/GameFiles/FileTypes/Gxt2File.cs
Normal 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
CodeWalker.Core/GameFiles/FileTypes/JPsoFile.cs
Normal file
48
CodeWalker.Core/GameFiles/FileTypes/JPsoFile.cs
Normal 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
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
3034
CodeWalker.Core/GameFiles/FileTypes/RelFile.cs
Normal file
3034
CodeWalker.Core/GameFiles/FileTypes/RelFile.cs
Normal file
File diff suppressed because it is too large
Load Diff
84
CodeWalker.Core/GameFiles/FileTypes/Stats.cs
Normal file
84
CodeWalker.Core/GameFiles/FileTypes/Stats.cs
Normal 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
CodeWalker.Core/GameFiles/FileTypes/YbnFile.cs
Normal file
44
CodeWalker.Core/GameFiles/FileTypes/YbnFile.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
130
CodeWalker.Core/GameFiles/FileTypes/YcdFile.cs
Normal file
130
CodeWalker.Core/GameFiles/FileTypes/YcdFile.cs
Normal file
@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public class YcdFile : GameFile, PackedFile
|
||||
{
|
||||
public ClipDictionary ClipDictionary { get; set; }
|
||||
|
||||
public Dictionary<MetaHash, ClipMapEntry> ClipMap { get; set; }
|
||||
public Dictionary<MetaHash, AnimationMapEntry> AnimMap { get; set; }
|
||||
|
||||
public ClipMapEntry[] ClipMapEntries { get; set; }
|
||||
public AnimationMapEntry[] AnimMapEntries { 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;
|
||||
RpfFileEntry = entry;
|
||||
//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>();
|
||||
AnimMap = new Dictionary<MetaHash, AnimationMapEntry>();
|
||||
if (ClipDictionary != null)
|
||||
{
|
||||
if ((ClipDictionary.Clips != null) && (ClipDictionary.Clips.data_items != null))
|
||||
{
|
||||
foreach (var cme in ClipDictionary.Clips.data_items)
|
||||
{
|
||||
if (cme != null)
|
||||
{
|
||||
ClipMap[cme.Hash] = cme;
|
||||
var nxt = cme.Next;
|
||||
while (nxt != null)
|
||||
{
|
||||
ClipMap[nxt.Hash] = nxt;
|
||||
nxt = nxt.Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ClipDictionary.Animations != null) && (ClipDictionary.Animations.Animations != null) && (ClipDictionary.Animations.Animations.data_items != null))
|
||||
{
|
||||
foreach (var ame in ClipDictionary.Animations.Animations.data_items)
|
||||
{
|
||||
if (ame != null)
|
||||
{
|
||||
AnimMap[ame.Hash] = ame;
|
||||
var nxt = ame.NextEntry;
|
||||
while (nxt != null)
|
||||
{
|
||||
AnimMap[nxt.Hash] = nxt;
|
||||
nxt = nxt.NextEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var cme in ClipMap.Values)
|
||||
{
|
||||
var clip = cme.Clip;
|
||||
if (clip == null) continue;
|
||||
clip.Ycd = this;
|
||||
if (string.IsNullOrEmpty(clip.Name)) continue;
|
||||
string name = clip.Name.Replace('\\', '/');
|
||||
var slidx = name.LastIndexOf('/');
|
||||
if ((slidx >= 0) && (slidx < name.Length - 1))
|
||||
{
|
||||
name = name.Substring(slidx + 1);
|
||||
}
|
||||
var didx = name.LastIndexOf('.');
|
||||
if ((didx > 0) && (didx < name.Length))
|
||||
{
|
||||
name = name.Substring(0, didx);
|
||||
}
|
||||
clip.ShortName = name;
|
||||
name = name.ToLowerInvariant();
|
||||
JenkIndex.Ensure(name);
|
||||
|
||||
|
||||
//if (name.EndsWith("_uv_0")) //hash for these entries match string with this removed, +1
|
||||
//{
|
||||
//}
|
||||
//if (name.EndsWith("_uv_1")) //same as above, but +2
|
||||
//{
|
||||
//}
|
||||
|
||||
}
|
||||
foreach (var ame in AnimMap.Values)
|
||||
{
|
||||
var anim = ame.Animation;
|
||||
if (anim == null) continue;
|
||||
anim.Ycd = this;
|
||||
}
|
||||
|
||||
|
||||
ClipMapEntries = ClipMap.Values.ToArray();
|
||||
AnimMapEntries = AnimMap.Values.ToArray();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
89
CodeWalker.Core/GameFiles/FileTypes/YddFile.cs
Normal file
89
CodeWalker.Core/GameFiles/FileTypes/YddFile.cs
Normal 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);
|
||||
|
||||
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
CodeWalker.Core/GameFiles/FileTypes/YdrFile.cs
Normal file
59
CodeWalker.Core/GameFiles/FileTypes/YdrFile.cs
Normal 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
CodeWalker.Core/GameFiles/FileTypes/YftFile.cs
Normal file
50
CodeWalker.Core/GameFiles/FileTypes/YftFile.cs
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
1681
CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs
Normal file
1681
CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs
Normal file
File diff suppressed because it is too large
Load Diff
187
CodeWalker.Core/GameFiles/FileTypes/YmfFile.cs
Normal file
187
CodeWalker.Core/GameFiles/FileTypes/YmfFile.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
324
CodeWalker.Core/GameFiles/FileTypes/YmtFile.cs
Normal file
324
CodeWalker.Core/GameFiles/FileTypes/YmtFile.cs
Normal file
@ -0,0 +1,324 @@
|
||||
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 Load(byte[] data)
|
||||
{
|
||||
//direct load from a raw, compressed ymt resource file (openIV-compatible format)
|
||||
|
||||
RpfFile.LoadResourceFile(this, data, 2);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
1309
CodeWalker.Core/GameFiles/FileTypes/YndFile.cs
Normal file
1309
CodeWalker.Core/GameFiles/FileTypes/YndFile.cs
Normal file
File diff suppressed because it is too large
Load Diff
689
CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs
Normal file
689
CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs
Normal file
@ -0,0 +1,689 @@
|
||||
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<NavMeshAdjPoly> AdjPolys { get; set; }
|
||||
public List<YnvPoly> Polys { get; set; }
|
||||
public List<YnvPortal> Portals { get; set; }
|
||||
public List<YnvPoint> Points { get; set; }
|
||||
|
||||
|
||||
public EditorVertex[] PathVertices { get; set; }
|
||||
public EditorVertex[] 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 PathBVH BVH { get; set; }
|
||||
|
||||
|
||||
public int AreaID
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)(Nav?.AreaID ?? 0);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Nav != null) Nav.AreaID = (uint)value;
|
||||
}
|
||||
}
|
||||
public int CellX { get { return AreaID % 100; } set { AreaID = (CellY * 100) + value; } }
|
||||
public int CellY { get { return AreaID / 100; } set { AreaID = (value * 100) + CellX; } }
|
||||
|
||||
|
||||
|
||||
|
||||
public YnvFile() : base(null, GameFileType.Ynv)
|
||||
{
|
||||
}
|
||||
public YnvFile(RpfFileEntry entry) : base(entry, GameFileType.Ynv)
|
||||
{
|
||||
}
|
||||
|
||||
public void Load(byte[] data)
|
||||
{
|
||||
//direct load from a raw, compressed ynv file (openIV-compatible format)
|
||||
|
||||
RpfFile.LoadResourceFile(this, data, 2);
|
||||
|
||||
Loaded = true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Vector3 posoffset = Nav.SectorTree?.AABBMin.XYZ() ?? Vector3.Zero;
|
||||
Vector3 aabbsize = Nav.AABBSize;
|
||||
|
||||
if (Nav.Vertices != null)
|
||||
{
|
||||
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.AdjPolys != null)
|
||||
{
|
||||
AdjPolys = Nav.AdjPolys.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;
|
||||
poly.CalculatePosition(); //calc poly center for display purposes..
|
||||
Polys.Add(poly);
|
||||
}
|
||||
}
|
||||
if (Nav.Portals != null)
|
||||
{
|
||||
var portals = Nav.Portals;
|
||||
Portals = new List<YnvPortal>(portals.Length);
|
||||
for (int i = 0; i < portals.Length; i++)
|
||||
{
|
||||
YnvPortal portal = new YnvPortal();
|
||||
portal.Init(this, portals[i]);
|
||||
portal.Index = i;
|
||||
portal.Position1 = posoffset + portal._RawData.Position1.ToVector3() * aabbsize;
|
||||
portal.Position2 = posoffset + portal._RawData.Position2.ToVector3() * aabbsize;
|
||||
Portals.Add(portal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////### add points to the list and calculate positions...
|
||||
var treestack = new Stack<NavMeshSector>();
|
||||
var pointi = 0;
|
||||
if (Nav.SectorTree != null)
|
||||
{
|
||||
treestack.Push(Nav.SectorTree);
|
||||
}
|
||||
while (treestack.Count > 0)
|
||||
{
|
||||
var sector = treestack.Pop();
|
||||
if (sector.Data != null)
|
||||
{
|
||||
var points = sector.Data.Points;
|
||||
if (points != null)
|
||||
{
|
||||
if (Points == null)
|
||||
{
|
||||
Points = new List<YnvPoint>();
|
||||
}
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
YnvPoint point = new YnvPoint();
|
||||
point.Init(this, points[i]);
|
||||
point.Index = pointi; pointi++;
|
||||
point.Position = posoffset + point._RawData.Position * aabbsize;
|
||||
Points.Add(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sector.SubTree1 != null) treestack.Push(sector.SubTree1);
|
||||
if (sector.SubTree2 != null) treestack.Push(sector.SubTree2);
|
||||
if (sector.SubTree3 != null) treestack.Push(sector.SubTree3);
|
||||
if (sector.SubTree4 != null) treestack.Push(sector.SubTree4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
UpdateAllNodePositions();
|
||||
|
||||
UpdateTriangleVertices();
|
||||
|
||||
BuildBVH();
|
||||
|
||||
|
||||
Loaded = true;
|
||||
LoadQueued = true;
|
||||
}
|
||||
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
BuildStructs();
|
||||
|
||||
byte[] data = ResourceBuilder.Build(Nav, 2); //ynv is version 2...
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public void BuildStructs()
|
||||
{
|
||||
Vector3 posoffset = Nav.SectorTree?.AABBMin.XYZ() ?? Vector3.Zero;
|
||||
Vector3 aabbsize = Nav.AABBSize;
|
||||
Vector3 aabbsizeinv = 1.0f / aabbsize;
|
||||
|
||||
var vertlist = new List<NavMeshVertex>();
|
||||
if (Vertices != null)
|
||||
{
|
||||
for (int i = 0; i < Vertices.Count; i++)
|
||||
{
|
||||
vertlist.Add(NavMeshVertex.Create((Vertices[i] - posoffset) * aabbsizeinv));
|
||||
}
|
||||
}
|
||||
var polylist = new List<NavMeshPoly>();
|
||||
if (Polys != null)
|
||||
{
|
||||
for (int i = 0; i < Polys.Count; i++)
|
||||
{
|
||||
polylist.Add(Polys[i].RawData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Nav.Vertices == null)
|
||||
{
|
||||
Nav.Vertices = new NavMeshList<NavMeshVertex>();
|
||||
Nav.Vertices.VFT = 1080158456;
|
||||
}
|
||||
if (Nav.Indices == null)
|
||||
{
|
||||
Nav.Indices = new NavMeshList<ushort>();
|
||||
Nav.Indices.VFT = 1080158424;
|
||||
}
|
||||
if (Nav.AdjPolys == null)
|
||||
{
|
||||
Nav.AdjPolys = new NavMeshList<NavMeshAdjPoly>();
|
||||
Nav.AdjPolys.VFT = 1080158440;
|
||||
}
|
||||
if (Nav.Polys == null)
|
||||
{
|
||||
Nav.Polys = new NavMeshList<NavMeshPoly>();
|
||||
Nav.Polys.VFT = 1080158408;
|
||||
}
|
||||
|
||||
|
||||
Nav.Vertices.RebuildList(vertlist);
|
||||
|
||||
Nav.Indices.RebuildList(Indices);
|
||||
|
||||
Nav.AdjPolys.RebuildList(AdjPolys);
|
||||
|
||||
Nav.Polys.RebuildList(polylist);
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < Nav.Polys.ListParts.Count; i++) //reassign part id's on all the polys...
|
||||
{
|
||||
var listpart = Nav.Polys.ListParts[i];
|
||||
var partitems = listpart?.Items;
|
||||
if (partitems == null) continue;
|
||||
ushort iu = (ushort)i;
|
||||
for (int j = 0; j < partitems.Length; j++)
|
||||
{
|
||||
partitems[j].PartID = iu;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public bool RemovePoly(YnvPoly poly)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void UpdateAllNodePositions()
|
||||
{
|
||||
if (Nav == null) return;
|
||||
|
||||
|
||||
Vector3 posoffset = Nav.SectorTree.AABBMin.XYZ();
|
||||
Vector3 aabbsize = Nav.AABBSize;
|
||||
|
||||
EditorVertex v = new EditorVertex();
|
||||
v.Colour = 0xFF0000FF;
|
||||
var lv = new List<EditorVertex>();
|
||||
var nv = new List<Vector4>();
|
||||
|
||||
|
||||
////### add portal positions to the node list, also add links to the link vertex array
|
||||
int cnt = Portals?.Count ?? 0;
|
||||
if (cnt > 0)
|
||||
{
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
var portal = Portals[i];
|
||||
nv.Add(new Vector4(portal.Position1, 1.0f));
|
||||
v.Position = portal.Position1; lv.Add(v);
|
||||
v.Position = portal.Position2; lv.Add(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////### add point positions to the node list
|
||||
cnt = Points?.Count ?? 0;
|
||||
if (cnt >= 0)
|
||||
{
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
var point = Points[i];
|
||||
nv.Add(new Vector4(point.Position, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NodePositions = (nv.Count > 0) ? nv.ToArray() : null;
|
||||
PathVertices = (lv.Count > 0) ? lv.ToArray() : null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void UpdateTriangleVertices()
|
||||
{
|
||||
//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<EditorVertex> rverts = new List<EditorVertex>();
|
||||
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)
|
||||
{ }
|
||||
|
||||
|
||||
EditorVertex p0 = new EditorVertex();
|
||||
EditorVertex p1 = new EditorVertex();
|
||||
EditorVertex p2 = new EditorVertex();
|
||||
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 void BuildBVH()
|
||||
{
|
||||
var nodes = new List<BasePathNode>();
|
||||
if (Portals != null) nodes.AddRange(Portals);
|
||||
if (Points != null) nodes.AddRange(Points);
|
||||
BVH = new PathBVH(nodes, 10, 10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public EditorVertex[] GetPathVertices()
|
||||
{
|
||||
return PathVertices;
|
||||
}
|
||||
public EditorVertex[] 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; } set { _RawData.AreaID = value; } }
|
||||
public ushort PartID { get { return _RawData.PartID; } set { _RawData.PartID = value; } }
|
||||
public ushort PortalID { get { return _RawData.PortalID; } set { _RawData.PortalID = value; } }
|
||||
public byte PortalUnk { get { return _RawData.PortalUnk; } set { _RawData.PortalUnk = value; } }
|
||||
public byte Flags1 { get { return (byte)(_RawData.Unknown_00h & 0xFF); } set { _RawData.Unknown_00h = (ushort)((_RawData.Unknown_00h & 0xFF00) | (value & 0xFF)); } }
|
||||
public byte Flags2 { get { return (byte)((_RawData.Unknown_24h.Value >> 0) & 0xFF); } set { _RawData.Unknown_24h = ((_RawData.Unknown_24h.Value & 0xFFFFFF00u) | ((value & 0xFFu) << 0)); } }
|
||||
public byte Flags3 { get { return (byte)((_RawData.Unknown_24h.Value >> 9) & 0xFF); } set { _RawData.Unknown_24h = ((_RawData.Unknown_24h.Value & 0xFFFE01FFu) | ((value & 0xFFu) << 9)); } }
|
||||
public byte Flags4 { get { return (byte)((_RawData.Unknown_28h.Value >> 16) & 0xFF); } set { _RawData.Unknown_28h = ((_RawData.Unknown_28h.Value & 0x0000FFFFu) | ((value & 0xFFu) << 16)); } }
|
||||
public bool B00_AvoidUnk { get { return (_RawData.Unknown_00h & 1) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 0, value); } }
|
||||
public bool B01_AvoidUnk { get { return (_RawData.Unknown_00h & 2) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 1, value); } }
|
||||
public bool B02_IsFootpath { get { return (_RawData.Unknown_00h & 4) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 2, value); } }
|
||||
public bool B03_IsUnderground { get { return (_RawData.Unknown_00h & 8) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 3, value); } }
|
||||
//public bool B04_Unused { get { return (_RawData.Unknown_00h & 16) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 4, value); } }
|
||||
//public bool B05_Unused { get { return (_RawData.Unknown_00h & 32) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 5, value); } }
|
||||
public bool B06_SteepSlope { get { return (_RawData.Unknown_00h & 64) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 6, value); } }
|
||||
public bool B07_IsWater { get { return (_RawData.Unknown_00h & 128) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 7, value); } }
|
||||
public bool B08_UndergroundUnk0 { get { return (_RawData.Unknown_24h.Value & 1) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 0, value); } }
|
||||
public bool B09_UndergroundUnk1 { get { return (_RawData.Unknown_24h.Value & 2) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 1, value); } }
|
||||
public bool B10_UndergroundUnk2 { get { return (_RawData.Unknown_24h.Value & 4) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 2, value); } }
|
||||
public bool B11_UndergroundUnk3 { get { return (_RawData.Unknown_24h.Value & 8) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 3, value); } }
|
||||
//public bool B12_Unused { get { return (_RawData.Unknown_24h.Value & 16) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 4, value); } }
|
||||
public bool B13_HasPathNode { get { return (_RawData.Unknown_24h.Value & 32) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 5, value); } }
|
||||
public bool B14_IsInterior { get { return (_RawData.Unknown_24h.Value & 64) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 6, value); } }
|
||||
public bool B15_InteractionUnk { get { return (_RawData.Unknown_24h.Value & 128) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 7, value); } }
|
||||
//public bool B16_Unused { get { return (_RawData.Unknown_24h.Value & 256) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 8, value); } }
|
||||
public bool B17_IsFlatGround { get { return (_RawData.Unknown_24h.Value & 512) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 9, value); } }
|
||||
public bool B18_IsRoad { get { return (_RawData.Unknown_24h.Value & 1024) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 10, value); } }
|
||||
public bool B19_IsCellEdge { get { return (_RawData.Unknown_24h.Value & 2048) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 11, value); } }
|
||||
public bool B20_IsTrainTrack { get { return (_RawData.Unknown_24h.Value & 4096) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 12, value); } }
|
||||
public bool B21_IsShallowWater { get { return (_RawData.Unknown_24h.Value & 8192) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 13, value); } }
|
||||
public bool B22_FootpathUnk1 { get { return (_RawData.Unknown_24h.Value & 16384) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 14, value); } }
|
||||
public bool B23_FootpathUnk2 { get { return (_RawData.Unknown_24h.Value & 32768) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 15, value); } }
|
||||
public bool B24_FootpathMall { get { return (_RawData.Unknown_24h.Value & 65536) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 16, value); } }
|
||||
public bool B25_SlopeSouth { get { return (_RawData.Unknown_28h.Value & 65536) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 16, value); } }
|
||||
public bool B26_SlopeSouthEast { get { return (_RawData.Unknown_28h.Value & 131072) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 17, value); } }
|
||||
public bool B27_SlopeEast { get { return (_RawData.Unknown_28h.Value & 262144) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 18, value); } }
|
||||
public bool B28_SlopeNorthEast { get { return (_RawData.Unknown_28h.Value & 524288) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 19, value); } }
|
||||
public bool B29_SlopeNorth { get { return (_RawData.Unknown_28h.Value & 1048576) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 20, value); } }
|
||||
public bool B30_SlopeNorthWest { get { return (_RawData.Unknown_28h.Value & 2097152) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 21, value); } }
|
||||
public bool B31_SlopeWest { get { return (_RawData.Unknown_28h.Value & 4194304) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 22, value); } }
|
||||
public bool B32_SlopeSouthWest { get { return (_RawData.Unknown_28h.Value & 8388608) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 23, value); } }
|
||||
//public bool B33_PortalUnk1 { get { return (_RawData.PortalUnk & 1) > 0; } }
|
||||
//public bool B34_PortalUnk2 { get { return (_RawData.PortalUnk & 2) > 0; } }
|
||||
//public bool B35_PortalUnk3 { get { return (_RawData.PortalUnk & 4) > 0; } }
|
||||
//public bool B36_PortalUnk4 { get { return (_RawData.PortalUnk & 8) > 0; } }
|
||||
public byte UnkX { get { return _RawData.Unknown_28h_8a; } set { _RawData.Unknown_28h_8a = value; } }
|
||||
public byte UnkY { get { return _RawData.Unknown_28h_8b; } set { _RawData.Unknown_28h_8b = value; } }
|
||||
|
||||
|
||||
public Vector3 Position { get; set; }
|
||||
public int Index { get; set; }
|
||||
|
||||
|
||||
public void Init(YnvFile ynv, NavMeshPoly poly)
|
||||
{
|
||||
Ynv = ynv;
|
||||
RawData = poly;
|
||||
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3 pos)
|
||||
{
|
||||
Vector3 delta = pos - Position;
|
||||
Position = pos;
|
||||
//TODO: update vertex positions!!!
|
||||
}
|
||||
|
||||
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
|
||||
//if (u0 >= 256) colour.Green += 1.0f;//other bits unused...
|
||||
|
||||
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.PortalUnk;
|
||||
//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 void CalculatePosition()
|
||||
{
|
||||
//calc poly center for display purposes.
|
||||
var indices = Ynv.Indices;
|
||||
var vertices = Ynv.Vertices;
|
||||
if ((indices == null) || (vertices == null))
|
||||
{ return; }
|
||||
var vc = vertices.Count;
|
||||
var ic = _RawData.IndexCount;
|
||||
var startid = _RawData.IndexID;
|
||||
var endid = startid + ic;
|
||||
if (startid >= indices.Count)
|
||||
{ return; }
|
||||
if (endid > indices.Count)
|
||||
{ return; }
|
||||
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;
|
||||
}
|
||||
Position = pcenter * (1.0f / pcount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return AreaID.ToString() + ", " + Index.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPortal : BasePathNode
|
||||
{
|
||||
public NavMeshPortal _RawData;
|
||||
|
||||
public YnvFile Ynv { get; set; }
|
||||
public NavMeshPortal RawData { get { return _RawData; } set { _RawData = value; } }
|
||||
|
||||
public Vector3 Position { get { return Position1; } set { Position1 = value; } }
|
||||
public Vector3 Position1 { get; set; }
|
||||
public Vector3 Position2 { get; set; }
|
||||
public int Index { get; set; }
|
||||
|
||||
|
||||
public void Init(YnvFile ynv, NavMeshPortal portal)
|
||||
{
|
||||
Ynv = ynv;
|
||||
RawData = portal;
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3 pos)
|
||||
{
|
||||
Position = pos;
|
||||
//TODO: update _RawData positions!
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Index.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoint : BasePathNode
|
||||
{
|
||||
public NavMeshPoint _RawData;
|
||||
|
||||
public YnvFile Ynv { get; set; }
|
||||
public NavMeshPoint RawData { get { return _RawData; } set { _RawData = value; } }
|
||||
|
||||
public Vector3 Position { get; set; }
|
||||
public float Direction
|
||||
{
|
||||
get
|
||||
{
|
||||
return (float)Math.PI * 2.0f * _RawData.Angle / 255.0f;
|
||||
}
|
||||
set
|
||||
{
|
||||
_RawData.Angle = (byte)(value * 255.0f / ((float)Math.PI * 2.0f));
|
||||
}
|
||||
}
|
||||
public Quaternion Orientation
|
||||
{
|
||||
get { return Quaternion.RotationAxis(Vector3.UnitZ, Direction); }
|
||||
set
|
||||
{
|
||||
Vector3 dir = value.Multiply(Vector3.UnitX);
|
||||
float dira = (float)Math.Atan2(dir.Y, dir.X);
|
||||
Direction = dira;
|
||||
}
|
||||
}
|
||||
|
||||
public int Index { get; set; }
|
||||
public byte Flags { get { return _RawData.Flags; } set { _RawData.Flags = value; } }
|
||||
|
||||
public void Init(YnvFile ynv, NavMeshPoint point)
|
||||
{
|
||||
Ynv = ynv;
|
||||
RawData = point;
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3 pos)
|
||||
{
|
||||
Position = pos;
|
||||
//TODO! update _RawData.Position!!!
|
||||
}
|
||||
public void SetOrientation(Quaternion orientation)
|
||||
{
|
||||
Orientation = orientation;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Index.ToString() + ": " + Flags.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
106
CodeWalker.Core/GameFiles/FileTypes/YptFile.cs
Normal file
106
CodeWalker.Core/GameFiles/FileTypes/YptFile.cs
Normal 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
CodeWalker.Core/GameFiles/FileTypes/YtdFile.cs
Normal file
49
CodeWalker.Core/GameFiles/FileTypes/YtdFile.cs
Normal 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;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
253
CodeWalker.Core/GameFiles/FileTypes/YtypFile.cs
Normal file
253
CodeWalker.Core/GameFiles/FileTypes/YtypFile.cs
Normal file
@ -0,0 +1,253 @@
|
||||
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 : GameFile, PackedFile
|
||||
{
|
||||
|
||||
|
||||
public Meta Meta { get; set; }
|
||||
public PsoFile Pso { get; set; }
|
||||
public RbfFile Rbf { get; set; }
|
||||
|
||||
|
||||
public uint NameHash { get; set; }
|
||||
public string[] Strings { get; set; }
|
||||
|
||||
|
||||
public CMapTypes CMapTypes { get; set; }
|
||||
|
||||
public Archetype[] AllArchetypes { get; set; }
|
||||
|
||||
public MetaWrapper[] Extensions { get; set; }
|
||||
|
||||
public CCompositeEntityType[] CompositeEntityTypes { get; set; }
|
||||
|
||||
|
||||
//fields used by the editor:
|
||||
public bool HasChanged { get; set; } = false;
|
||||
public List<string> SaveWarnings = null;
|
||||
|
||||
|
||||
|
||||
public YtypFile() : base(null, GameFileType.Ytyp)
|
||||
{
|
||||
}
|
||||
public YtypFile(RpfFileEntry entry) : base(entry, GameFileType.Ytyp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return (RpfFileEntry != null) ? RpfFileEntry.Name : string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public void Load(byte[] data)
|
||||
{
|
||||
//direct load from a raw, compressed ytyp file (openIV-compatible format)
|
||||
|
||||
RpfFile.LoadResourceFile(this, data, 2);
|
||||
|
||||
Loaded = true;
|
||||
}
|
||||
|
||||
public void Load(byte[] data, RpfFileEntry entry)
|
||||
{
|
||||
Name = entry.Name;
|
||||
RpfFileEntry = 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];
|
||||
var offset = ptr.Offset;
|
||||
var block = Meta.GetBlock(ptr.BlockID);
|
||||
if (block == null)
|
||||
{ continue; }
|
||||
if ((offset < 0) || (block.Data == null) || (offset >= block.Data.Length))
|
||||
{ continue; }
|
||||
|
||||
Archetype a = null;
|
||||
switch (block.StructureNameHash)
|
||||
{
|
||||
case MetaName.CBaseArchetypeDef:
|
||||
var basearch = PsoTypes.ConvertDataRaw<CBaseArchetypeDef>(block.Data, offset);
|
||||
a = new Archetype();
|
||||
a.Init(this, ref basearch);
|
||||
a.Extensions = MetaTypes.GetExtensions(Meta, basearch.extensions);
|
||||
break;
|
||||
case MetaName.CTimeArchetypeDef:
|
||||
var timearch = PsoTypes.ConvertDataRaw<CTimeArchetypeDef>(block.Data, offset);
|
||||
var ta = new TimeArchetype();
|
||||
ta.Init(this, ref timearch);
|
||||
ta.Extensions = MetaTypes.GetExtensions(Meta, timearch._BaseArchetypeDef.extensions);
|
||||
a = ta;
|
||||
break;
|
||||
case MetaName.CMloArchetypeDef:
|
||||
var mloarch = PsoTypes.ConvertDataRaw<CMloArchetypeDef>(block.Data, offset);
|
||||
var ma = new MloArchetype();
|
||||
ma.Init(this, ref mloarch);
|
||||
ma.Extensions = MetaTypes.GetExtensions(Meta, mloarch._BaseArchetypeDef.extensions);
|
||||
|
||||
ma.LoadChildren(Meta);
|
||||
|
||||
a = ma;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a != null)
|
||||
{
|
||||
allarchs.Add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
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.POINTER:
|
||||
// case MetaName.UINT:
|
||||
// case MetaName.VECTOR4:
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
//MetaTypes.ParseMetaData(Meta);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
54
CodeWalker.Core/GameFiles/FileTypes/YvrFile.cs
Normal file
54
CodeWalker.Core/GameFiles/FileTypes/YvrFile.cs
Normal 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
CodeWalker.Core/GameFiles/FileTypes/YwrFile.cs
Normal file
54
CodeWalker.Core/GameFiles/FileTypes/YwrFile.cs
Normal 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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
93
CodeWalker.Core/GameFiles/GameFile.cs
Normal file
93
CodeWalker.Core/GameFiles/GameFile.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public abstract class GameFile : Cacheable<GameFileCacheKey>
|
||||
{
|
||||
public volatile bool Loaded = false;
|
||||
public volatile bool LoadQueued = false;
|
||||
public RpfFileEntry RpfFileEntry { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string FilePath { get; set; } //used by the project form.
|
||||
public GameFileType Type { get; set; }
|
||||
|
||||
|
||||
|
||||
public GameFile(RpfFileEntry entry, GameFileType type)
|
||||
{
|
||||
RpfFileEntry = entry;
|
||||
Type = type;
|
||||
MemoryUsage = (entry != null) ? entry.GetFileSize() : 0;
|
||||
if (entry is RpfResourceFileEntry)
|
||||
{
|
||||
var resent = entry as RpfResourceFileEntry;
|
||||
var newuse = resent.SystemSize + resent.GraphicsSize;
|
||||
MemoryUsage = newuse;
|
||||
}
|
||||
else if (entry is RpfBinaryFileEntry)
|
||||
{
|
||||
var binent = entry as RpfBinaryFileEntry;
|
||||
var newuse = binent.FileUncompressedSize;
|
||||
if (newuse > MemoryUsage)
|
||||
{
|
||||
MemoryUsage = newuse;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return (string.IsNullOrEmpty(Name)) ? JenkIndex.GetString(Key.Hash) : Name;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public enum GameFileType : int
|
||||
{
|
||||
Ydd = 0,
|
||||
Ydr = 1,
|
||||
Yft = 2,
|
||||
Ymap = 3,
|
||||
Ymf = 4,
|
||||
Ymt = 5,
|
||||
Ytd = 6,
|
||||
Ytyp = 7,
|
||||
Ybn = 8,
|
||||
Ycd = 9,
|
||||
Ypt = 10,
|
||||
Ynd = 11,
|
||||
Ynv = 12,
|
||||
Rel = 13,
|
||||
Ywr = 14,
|
||||
Yvr = 15,
|
||||
Gtxd = 16,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public struct GameFileCacheKey
|
||||
{
|
||||
public uint Hash { get; set; }
|
||||
public GameFileType Type { get; set; }
|
||||
|
||||
public GameFileCacheKey(uint hash, GameFileType type)
|
||||
{
|
||||
Hash = hash;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
2761
CodeWalker.Core/GameFiles/GameFileCache.cs
Normal file
2761
CodeWalker.Core/GameFiles/GameFileCache.cs
Normal file
File diff suppressed because it is too large
Load Diff
301
CodeWalker.Core/GameFiles/MetaTypes/Archetype.cs
Normal file
301
CodeWalker.Core/GameFiles/MetaTypes/Archetype.cs
Normal file
@ -0,0 +1,301 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public class Archetype
|
||||
{
|
||||
public virtual MetaName Type => MetaName.CBaseArchetypeDef;
|
||||
|
||||
public CBaseArchetypeDef _BaseArchetypeDef;
|
||||
public CBaseArchetypeDef BaseArchetypeDef { get { return _BaseArchetypeDef; } set { _BaseArchetypeDef = value; } }
|
||||
|
||||
public MetaHash Hash { get; set; }
|
||||
public YtypFile Ytyp { get; set; }
|
||||
public MetaHash DrawableDict { get; set; }
|
||||
public MetaHash TextureDict { get; set; }
|
||||
public MetaHash ClipDict { get; set; }
|
||||
public Vector3 BBMin { get; set; }
|
||||
public Vector3 BBMax { get; set; }
|
||||
public Vector3 BSCenter { get; set; }
|
||||
public float BSRadius { get; set; }
|
||||
public float LodDist { get; set; }
|
||||
public MetaWrapper[] Extensions { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _BaseArchetypeDef.name.ToString();
|
||||
}
|
||||
}
|
||||
public string AssetName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _BaseArchetypeDef.assetName.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void InitVars(ref CBaseArchetypeDef arch)
|
||||
{
|
||||
BaseArchetypeDef = arch;
|
||||
Hash = arch.assetName;
|
||||
if (Hash.Hash == 0) Hash = arch.name;
|
||||
DrawableDict = arch.drawableDictionary;
|
||||
TextureDict = arch.textureDictionary;
|
||||
ClipDict = arch.clipDictionary;
|
||||
BBMin = arch.bbMin;
|
||||
BBMax = arch.bbMax;
|
||||
BSCenter = arch.bsCentre;
|
||||
BSRadius = arch.bsRadius;
|
||||
LodDist = arch.lodDist;
|
||||
}
|
||||
|
||||
public void Init(YtypFile ytyp, ref CBaseArchetypeDef arch)
|
||||
{
|
||||
Ytyp = ytyp;
|
||||
InitVars(ref arch);
|
||||
}
|
||||
|
||||
public virtual bool IsActive(float hour)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _BaseArchetypeDef.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public class TimeArchetype : Archetype
|
||||
{
|
||||
public override MetaName Type => MetaName.CTimeArchetypeDef;
|
||||
|
||||
public CTimeArchetypeDefData _TimeArchetypeDef;
|
||||
public CTimeArchetypeDefData TimeArchetypeDef { get { return _TimeArchetypeDef; } set { _TimeArchetypeDef = value; } }
|
||||
|
||||
|
||||
public uint TimeFlags { get; set; }
|
||||
public bool[] ActiveHours { get; set; }
|
||||
public string[] ActiveHoursText { get; set; }
|
||||
public bool ExtraFlag { get; set; }
|
||||
|
||||
|
||||
public void Init(YtypFile ytyp, ref CTimeArchetypeDef arch)
|
||||
{
|
||||
Ytyp = ytyp;
|
||||
InitVars(ref arch._BaseArchetypeDef);
|
||||
TimeArchetypeDef = arch.TimeArchetypeDef;
|
||||
|
||||
TimeFlags = _TimeArchetypeDef.timeFlags;
|
||||
ActiveHours = new bool[24];
|
||||
ActiveHoursText = new string[24];
|
||||
for (int i = 0; i < 24; i++)
|
||||
{
|
||||
bool v = ((TimeFlags >> i) & 1) == 1;
|
||||
ActiveHours[i] = v;
|
||||
|
||||
int nxth = (i < 23) ? (i + 1) : 0;
|
||||
string hrs = string.Format("{0:00}:00 - {1:00}:00", i, nxth);
|
||||
ActiveHoursText[i] = (hrs + (v ? " - On" : " - Off"));
|
||||
}
|
||||
ExtraFlag = ((TimeFlags >> 24) & 1) == 1;
|
||||
}
|
||||
|
||||
public override bool IsActive(float hour)
|
||||
{
|
||||
if (ActiveHours == null) return true;
|
||||
int h = ((int)hour) % 24;
|
||||
if ((h < 0) || (h > 23)) return true;
|
||||
return ActiveHours[h];
|
||||
}
|
||||
}
|
||||
|
||||
public class MloArchetype : Archetype
|
||||
{
|
||||
public override MetaName Type => MetaName.CMloArchetypeDef;
|
||||
|
||||
public CMloArchetypeDefData _MloArchetypeDef;
|
||||
public CMloArchetypeDefData MloArchetypeDef { get { return _MloArchetypeDef; } set { _MloArchetypeDef = value; } }
|
||||
|
||||
public MCEntityDef[] entities { get; set; }
|
||||
public MCMloRoomDef[] rooms { get; set; }
|
||||
public MCMloPortalDef[] portals { get; set; }
|
||||
public MCMloEntitySet[] entitySets { get; set; }
|
||||
public CMloTimeCycleModifier[] timeCycleModifiers { get; set; }
|
||||
|
||||
public void Init(YtypFile ytyp, ref CMloArchetypeDef arch)
|
||||
{
|
||||
Ytyp = ytyp;
|
||||
InitVars(ref arch._BaseArchetypeDef);
|
||||
MloArchetypeDef = arch.MloArchetypeDef;
|
||||
}
|
||||
|
||||
public void LoadChildren(Meta meta)
|
||||
{
|
||||
var centities = MetaTypes.ConvertDataArray<CEntityDef>(meta, MetaName.CEntityDef, _MloArchetypeDef.entities);
|
||||
if (centities != null)
|
||||
{
|
||||
entities = new MCEntityDef[centities.Length];
|
||||
for (int i = 0; i < centities.Length; i++)
|
||||
{
|
||||
entities[i] = new MCEntityDef(meta, centities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var crooms = MetaTypes.ConvertDataArray<CMloRoomDef>(meta, MetaName.CMloRoomDef, _MloArchetypeDef.rooms);
|
||||
if (crooms != null)
|
||||
{
|
||||
rooms = new MCMloRoomDef[crooms.Length];
|
||||
for (int i = 0; i < crooms.Length; i++)
|
||||
{
|
||||
rooms[i] = new MCMloRoomDef(meta, crooms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var cportals = MetaTypes.ConvertDataArray<CMloPortalDef>(meta, MetaName.CMloPortalDef, _MloArchetypeDef.portals);
|
||||
if (cportals != null)
|
||||
{
|
||||
portals = new MCMloPortalDef[cportals.Length];
|
||||
for (int i = 0; i < cportals.Length; i++)
|
||||
{
|
||||
portals[i] = new MCMloPortalDef(meta, cportals[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var centitySets = MetaTypes.ConvertDataArray<CMloEntitySet>(meta, MetaName.CMloEntitySet, _MloArchetypeDef.entitySets);
|
||||
if (centitySets != null)
|
||||
{
|
||||
entitySets = new MCMloEntitySet[centitySets.Length];
|
||||
for (int i = 0; i < centitySets.Length; i++)
|
||||
{
|
||||
entitySets[i] = new MCMloEntitySet(meta, centitySets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
timeCycleModifiers = MetaTypes.ConvertDataArray<CMloTimeCycleModifier>(meta, MetaName.CMloTimeCycleModifier, _MloArchetypeDef.timeCycleModifiers);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public class MloInstanceData
|
||||
{
|
||||
public YmapEntityDef Owner { get; set; }
|
||||
public CMloInstanceDef _Instance;
|
||||
public CMloInstanceDef Instance { get { return _Instance; } set { _Instance = value; } }
|
||||
public uint[] defaultEntitySets { get; set; }
|
||||
|
||||
public YmapEntityDef[] Entities { get; set; }
|
||||
|
||||
|
||||
public void CreateYmapEntities(YmapEntityDef owner, MloArchetype mloa)
|
||||
{
|
||||
Owner = owner;
|
||||
if (owner == null) return;
|
||||
if (mloa.entities == null) return;
|
||||
var ec = mloa.entities.Length;
|
||||
|
||||
var entlist = new List<YmapEntityDef>();
|
||||
for (int i = 0; i < ec; i++)
|
||||
{
|
||||
YmapEntityDef e = CreateYmapEntity(owner, mloa.entities[i], i);
|
||||
entlist.Add(e);
|
||||
}
|
||||
|
||||
int lasti = ec;
|
||||
|
||||
var entitySets = mloa.entitySets;
|
||||
if (entitySets != null)
|
||||
{
|
||||
for (int i = 0; i < entitySets.Length; i++)
|
||||
{
|
||||
var entitySet = entitySets[i];
|
||||
if (entitySet.Entities != null)
|
||||
{
|
||||
for (int j = 0; j < entitySet.Entities.Length; j++)
|
||||
{
|
||||
YmapEntityDef e = CreateYmapEntity(owner, entitySet.Entities[j], lasti);
|
||||
e.MloEntitySet = entitySet;
|
||||
entlist.Add(e);
|
||||
lasti++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultEntitySets != null)
|
||||
{
|
||||
}
|
||||
|
||||
Entities = entlist.ToArray();
|
||||
}
|
||||
|
||||
private YmapEntityDef CreateYmapEntity(YmapEntityDef owner, MCEntityDef ment, int i)
|
||||
{
|
||||
YmapEntityDef e = new YmapEntityDef(null, i, ref ment._Data);
|
||||
e.Extensions = ment.Extensions;
|
||||
e.MloRefPosition = e.Position;
|
||||
e.MloRefOrientation = e.Orientation;
|
||||
e.MloParent = owner;
|
||||
e.Position = owner.Position + owner.Orientation.Multiply(e.MloRefPosition);
|
||||
e.Orientation = Quaternion.Multiply(owner.Orientation, e.MloRefOrientation);
|
||||
e.UpdateWidgetPosition();
|
||||
e.UpdateWidgetOrientation();
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
public void SetPosition(Vector3 pos)
|
||||
{
|
||||
var cent = _Instance.CEntityDef;
|
||||
cent.position = pos;
|
||||
_Instance.CEntityDef = cent; //TODO: maybe find a better way of doing this...
|
||||
}
|
||||
|
||||
public void SetOrientation(Quaternion ori)
|
||||
{
|
||||
var cent = _Instance.CEntityDef;
|
||||
cent.rotation = new Vector4(ori.X, ori.Y, ori.Z, ori.W); //mlo instances have oppposite orientations to normal entities...
|
||||
_Instance.CEntityDef = cent; //TODO: maybe find a better way of doing this...
|
||||
}
|
||||
|
||||
public void UpdateEntities()
|
||||
{
|
||||
if (Entities == null) return;
|
||||
if (Owner == null) return;
|
||||
|
||||
for (int i = 0; i < Entities.Length; i++)
|
||||
{
|
||||
YmapEntityDef e = Entities[i];
|
||||
e.Position = Owner.Position + Owner.Orientation.Multiply(e.MloRefPosition);
|
||||
e.Orientation = Quaternion.Multiply(Owner.Orientation, e.MloRefOrientation);
|
||||
e.UpdateWidgetPosition();
|
||||
e.UpdateWidgetOrientation();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
1121
CodeWalker.Core/GameFiles/MetaTypes/Meta.cs
Normal file
1121
CodeWalker.Core/GameFiles/MetaTypes/Meta.cs
Normal file
File diff suppressed because it is too large
Load Diff
447
CodeWalker.Core/GameFiles/MetaTypes/MetaBuilder.cs
Normal file
447
CodeWalker.Core/GameFiles/MetaTypes/MetaBuilder.cs
Normal file
@ -0,0 +1,447 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpDX;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public class MetaBuilder
|
||||
{
|
||||
|
||||
List<MetaBuilderBlock> Blocks = new List<MetaBuilderBlock>();
|
||||
|
||||
int MaxBlockLength = 0x4000; //TODO: figure what this should be!
|
||||
|
||||
|
||||
public MetaBuilderBlock EnsureBlock(MetaName type)
|
||||
{
|
||||
foreach (var block in Blocks)
|
||||
{
|
||||
if (block.StructureNameHash == type)
|
||||
{
|
||||
if (block.TotalSize < MaxBlockLength)
|
||||
{
|
||||
return block;
|
||||
}
|
||||
}
|
||||
}
|
||||
MetaBuilderBlock b = new MetaBuilderBlock();
|
||||
b.StructureNameHash = type;
|
||||
b.Index = Blocks.Count;
|
||||
Blocks.Add(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
public MetaBuilderPointer AddItem<T>(MetaName type, T item) where T : struct
|
||||
{
|
||||
byte[] data = MetaTypes.ConvertToBytes(item);
|
||||
return AddItem(type, data);
|
||||
}
|
||||
|
||||
public MetaBuilderPointer AddItem(MetaName type, byte[] data)
|
||||
{
|
||||
MetaBuilderBlock block = EnsureBlock(type);
|
||||
int brem = data.Length % 16;
|
||||
if (brem > 0)
|
||||
{
|
||||
int newlen = data.Length - brem + 16;
|
||||
byte[] newdata = new byte[newlen];
|
||||
Buffer.BlockCopy(data, 0, newdata, 0, data.Length);
|
||||
data = newdata; //make sure item size is multiple of 16... so pointers don't need sub offsets!
|
||||
}
|
||||
int idx = block.AddItem(data);
|
||||
MetaBuilderPointer r = new MetaBuilderPointer();
|
||||
r.BlockID = block.Index + 1;
|
||||
r.Offset = (idx * data.Length);
|
||||
r.Length = data.Length;
|
||||
return r;
|
||||
}
|
||||
|
||||
public MetaBuilderPointer AddItemArray<T>(MetaName type, T[] items) where T : struct
|
||||
{
|
||||
byte[] data = MetaTypes.ConvertArrayToBytes(items);
|
||||
return AddItemArray(type, data, items.Length);
|
||||
}
|
||||
|
||||
public MetaBuilderPointer AddItemArray(MetaName type, byte[] data, int length)
|
||||
{
|
||||
MetaBuilderBlock block = EnsureBlock(type);
|
||||
int datalen = data.Length;
|
||||
int newlen = datalen;
|
||||
int lenrem = newlen % 16;
|
||||
if (lenrem != 0)
|
||||
{
|
||||
newlen += (16 - lenrem);
|
||||
}
|
||||
byte[] newdata = new byte[newlen];
|
||||
Buffer.BlockCopy(data, 0, newdata, 0, datalen);
|
||||
int offs = block.TotalSize;
|
||||
int idx = block.AddItem(newdata);
|
||||
MetaBuilderPointer r = new MetaBuilderPointer();
|
||||
r.BlockID = block.Index + 1;
|
||||
r.Offset = offs; //(idx * data.Length);;
|
||||
r.Length = length;
|
||||
return r;
|
||||
}
|
||||
|
||||
public MetaBuilderPointer AddString(string str)
|
||||
{
|
||||
MetaBuilderBlock block = EnsureBlock(MetaName.STRING);
|
||||
byte[] data = Encoding.ASCII.GetBytes(str);
|
||||
int datalen = data.Length;
|
||||
int newlen = datalen;
|
||||
int lenrem = newlen % 16;
|
||||
if (lenrem != 0) //need to pad the data length up to multiple of 16.
|
||||
{
|
||||
newlen += (16 - lenrem);
|
||||
}
|
||||
byte[] newdata = new byte[newlen];
|
||||
Buffer.BlockCopy(data, 0, newdata, 0, datalen);
|
||||
int offs = block.TotalSize;
|
||||
int idx = block.AddItem(newdata);
|
||||
MetaBuilderPointer r = new MetaBuilderPointer();
|
||||
r.BlockID = block.Index + 1;
|
||||
r.Offset = offs;// (idx * data.Length);
|
||||
r.Length = datalen; //actual length of string.
|
||||
return r;
|
||||
}
|
||||
|
||||
public MetaPOINTER AddItemPtr<T>(MetaName type, T item) where T : struct //helper method for AddItem<T>
|
||||
{
|
||||
var ptr = AddItem(type, item);
|
||||
return new MetaPOINTER(ptr.BlockID, ptr.Offset, 0);
|
||||
}
|
||||
|
||||
public MetaPOINTER AddItemPtr(MetaName type, byte[] data)//helper method for AddItem<T>
|
||||
{
|
||||
var ptr = AddItem(type, data);
|
||||
return new MetaPOINTER(ptr.BlockID, ptr.Offset, 0);
|
||||
}
|
||||
|
||||
public Array_Structure AddItemArrayPtr<T>(MetaName type, T[] items) where T : struct //helper method for AddItemArray<T>
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_Structure();
|
||||
var ptr = AddItemArray(type, items);
|
||||
return new Array_Structure(ptr);
|
||||
}
|
||||
|
||||
public Array_Structure AddItemArrayPtr(MetaName type, byte[][] data) //helper method for AddItemArray<T>
|
||||
{
|
||||
if ((data == null) || (data.Length == 0)) return new Array_Structure();
|
||||
|
||||
int len = 0;
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
len += data[i].Length;
|
||||
}
|
||||
|
||||
var newdata = new byte[len];
|
||||
|
||||
int offset = 0;
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
Buffer.BlockCopy(data[i], 0, newdata, offset, data[i].Length);
|
||||
offset += data[i].Length;
|
||||
}
|
||||
|
||||
var ptr = AddItemArray(type, newdata, data.Length);
|
||||
return new Array_Structure(ptr);
|
||||
}
|
||||
|
||||
public Array_Vector3 AddPaddedVector3ArrayPtr(Vector4[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_Vector3();
|
||||
var ptr = AddItemArray(MetaName.VECTOR4, items); //padded to vec4...
|
||||
return new Array_Vector3(ptr);
|
||||
}
|
||||
public Array_uint AddHashArrayPtr(MetaHash[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_uint();
|
||||
var ptr = AddItemArray(MetaName.HASH, items);
|
||||
return new Array_uint(ptr);
|
||||
}
|
||||
public Array_uint AddUintArrayPtr(uint[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_uint();
|
||||
var ptr = AddItemArray(MetaName.UINT, items);
|
||||
return new Array_uint(ptr);
|
||||
}
|
||||
public Array_ushort AddUshortArrayPtr(ushort[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_ushort();
|
||||
var ptr = AddItemArray(MetaName.USHORT, items);
|
||||
return new Array_ushort(ptr);
|
||||
}
|
||||
public Array_byte AddByteArrayPtr(byte[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_byte();
|
||||
var ptr = AddItemArray(MetaName.BYTE, items);
|
||||
return new Array_byte(ptr);
|
||||
}
|
||||
public Array_float AddFloatArrayPtr(float[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_float();
|
||||
var ptr = AddItemArray(MetaName.FLOAT, items);
|
||||
return new Array_float(ptr);
|
||||
}
|
||||
public CharPointer AddStringPtr(string str) //helper method for AddString
|
||||
{
|
||||
var ptr = AddString(str);
|
||||
return new CharPointer(ptr);
|
||||
}
|
||||
|
||||
|
||||
public Array_StructurePointer AddPointerArray(MetaPOINTER[] arr)
|
||||
{
|
||||
if ((arr == null) || (arr.Length == 0)) return new Array_StructurePointer();
|
||||
var ptr = AddItemArray(MetaName.POINTER, arr);
|
||||
Array_StructurePointer sp = new Array_StructurePointer();
|
||||
sp.Count1 = (ushort)arr.Length;
|
||||
sp.Count2 = sp.Count1;
|
||||
sp.Pointer = ptr.Pointer;
|
||||
return sp;
|
||||
}
|
||||
|
||||
public Array_StructurePointer AddItemPointerArrayPtr<T>(MetaName type, T[] items) where T : struct
|
||||
{
|
||||
//helper method for creating a pointer array
|
||||
if ((items == null) || (items.Length == 0)) return new Array_StructurePointer();
|
||||
|
||||
MetaPOINTER[] ptrs = new MetaPOINTER[items.Length];
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
ptrs[i] = AddItemPtr(type, items[i]);
|
||||
}
|
||||
return AddPointerArray(ptrs);
|
||||
|
||||
//Array_StructurePointer sp = new Array_StructurePointer();
|
||||
//sp.Count1 = (ushort)items.Length;
|
||||
//sp.Count2 = sp.Count1;
|
||||
//for (int i = 0; i < items.Length; i++)
|
||||
//{
|
||||
// var item = items[i];
|
||||
// var meptr = AddItemPtr(type, item);
|
||||
// var mptr = AddItem(MetaName.POINTER, meptr);
|
||||
// if (i == 0)
|
||||
// {
|
||||
// sp.Pointer = mptr.Pointer; //main pointer points to the first item.
|
||||
// }
|
||||
//}
|
||||
//return sp;
|
||||
}
|
||||
|
||||
|
||||
public Array_StructurePointer AddWrapperArrayPtr(MetaWrapper[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_StructurePointer();
|
||||
|
||||
|
||||
MetaPOINTER[] ptrs = new MetaPOINTER[items.Length];
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
ptrs[i] = items[i].Save(this);
|
||||
}
|
||||
return AddPointerArray(ptrs);
|
||||
|
||||
//Array_StructurePointer sp = new Array_StructurePointer();
|
||||
//sp.Count1 = (ushort)items.Length;
|
||||
//sp.Count2 = sp.Count1;
|
||||
//for (int i = 0; i < items.Length; i++)
|
||||
//{
|
||||
// var item = items[i];
|
||||
// var meptr = item.Save(this);
|
||||
// var mptr = AddItem(MetaName.POINTER, meptr);
|
||||
// if (i == 0)
|
||||
// {
|
||||
// sp.Pointer = mptr.Pointer; //main pointer points to the first item.
|
||||
// }
|
||||
//}
|
||||
//return sp;
|
||||
}
|
||||
|
||||
public Array_Structure AddWrapperArray(MetaWrapper[] items)
|
||||
{
|
||||
if ((items == null) || (items.Length == 0)) return new Array_Structure();
|
||||
|
||||
var sa = new Array_Structure();
|
||||
sa.Count1 = (ushort)items.Length;
|
||||
sa.Count2 = sa.Count1;
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
var item = items[i];
|
||||
var meptr = item.Save(this);
|
||||
if (i == 0)
|
||||
{
|
||||
MetaBuilderPointer mbp = new MetaBuilderPointer();
|
||||
mbp.BlockID = meptr.BlockID;
|
||||
mbp.Offset = meptr.Offset;
|
||||
sa.Pointer = mbp.Pointer;
|
||||
}
|
||||
}
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
public byte[] GetData()
|
||||
{
|
||||
int totlen = 0;
|
||||
for (int i = 0; i < Blocks.Count; i++)
|
||||
{
|
||||
totlen += Blocks[i].TotalSize;
|
||||
}
|
||||
byte[] data = new byte[totlen];
|
||||
int offset = 0;
|
||||
for (int i = 0; i < Blocks.Count; i++)
|
||||
{
|
||||
var block = Blocks[i];
|
||||
for (int j = 0; j < block.Items.Count; j++)
|
||||
{
|
||||
var bdata = block.Items[j];
|
||||
Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length);
|
||||
offset += bdata.Length;
|
||||
}
|
||||
}
|
||||
if (offset != data.Length)
|
||||
{ }
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Dictionary<MetaName, MetaStructureInfo> StructureInfos = new Dictionary<MetaName, MetaStructureInfo>();
|
||||
Dictionary<MetaName, MetaEnumInfo> EnumInfos = new Dictionary<MetaName, MetaEnumInfo>();
|
||||
|
||||
public void AddStructureInfo(MetaName name)
|
||||
{
|
||||
if (!StructureInfos.ContainsKey(name))
|
||||
{
|
||||
MetaStructureInfo si = MetaTypes.GetStructureInfo(name);
|
||||
if (si != null)
|
||||
{
|
||||
StructureInfos[name] = si;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void AddEnumInfo(MetaName name)
|
||||
{
|
||||
if (!EnumInfos.ContainsKey(name))
|
||||
{
|
||||
MetaEnumInfo ei = MetaTypes.GetEnumInfo(name);
|
||||
if (ei != null)
|
||||
{
|
||||
EnumInfos[name] = ei;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public Meta GetMeta()
|
||||
{
|
||||
Meta m = new Meta();
|
||||
m.FileVFT = 0x405bc808;
|
||||
m.FileUnknown = 1;
|
||||
m.Unknown_10h = 0x50524430;
|
||||
m.Unknown_14h = 0x0079;
|
||||
|
||||
m.RootBlockIndex = 1; //assume first block is root. todo: make adjustable?
|
||||
|
||||
m.StructureInfos = new ResourceSimpleArray<MetaStructureInfo>();
|
||||
foreach (var si in StructureInfos.Values)
|
||||
{
|
||||
m.StructureInfos.Add(si);
|
||||
}
|
||||
m.StructureInfosCount = (short)m.StructureInfos.Count;
|
||||
|
||||
m.EnumInfos = new ResourceSimpleArray<MetaEnumInfo>();
|
||||
foreach (var ei in EnumInfos.Values)
|
||||
{
|
||||
m.EnumInfos.Add(ei);
|
||||
}
|
||||
m.EnumInfosCount = (short)m.EnumInfos.Count;
|
||||
|
||||
m.DataBlocks = new ResourceSimpleArray<MetaDataBlock>();
|
||||
foreach (var bb in Blocks)
|
||||
{
|
||||
m.DataBlocks.Add(bb.GetMetaDataBlock());
|
||||
}
|
||||
m.DataBlocksCount = (short)m.DataBlocks.Count;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class MetaBuilderBlock
|
||||
{
|
||||
public MetaName StructureNameHash { get; set; }
|
||||
public List<byte[]> Items { get; set; } = new List<byte[]>();
|
||||
public int TotalSize { get; set; } = 0;
|
||||
public int Index { get; set; } = 0;
|
||||
|
||||
public int AddItem(byte[] item)
|
||||
{
|
||||
int idx = Items.Count;
|
||||
Items.Add(item);
|
||||
TotalSize += item.Length;
|
||||
return idx;
|
||||
}
|
||||
|
||||
public uint BasePointer
|
||||
{
|
||||
get
|
||||
{
|
||||
return (((uint)Index + 1) & 0xFFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MetaDataBlock GetMetaDataBlock()
|
||||
{
|
||||
if (TotalSize <= 0) return null;
|
||||
|
||||
byte[] data = new byte[TotalSize];
|
||||
int offset = 0;
|
||||
for (int j = 0; j < Items.Count; j++)
|
||||
{
|
||||
var bdata = Items[j];
|
||||
Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length);
|
||||
offset += bdata.Length;
|
||||
}
|
||||
|
||||
MetaDataBlock db = new MetaDataBlock();
|
||||
db.StructureNameHash = StructureNameHash;
|
||||
db.DataLength = TotalSize;
|
||||
db.Data = data;
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public struct MetaBuilderPointer
|
||||
{
|
||||
public int BlockID { get; set; } //1-based id
|
||||
public int Offset { get; set; } //byte offset
|
||||
public int Length { get; set; } //for temp use...
|
||||
public uint Pointer
|
||||
{
|
||||
get
|
||||
{
|
||||
uint bidx = (((uint)BlockID) & 0xFFF);
|
||||
uint offs = (((uint)Offset) & 0xFFFFF) << 12;
|
||||
return bidx + offs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
3773
CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs
Normal file
3773
CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs
Normal file
File diff suppressed because it is too large
Load Diff
6087
CodeWalker.Core/GameFiles/MetaTypes/MetaTypes.cs
Normal file
6087
CodeWalker.Core/GameFiles/MetaTypes/MetaTypes.cs
Normal file
File diff suppressed because it is too large
Load Diff
1761
CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs
Normal file
1761
CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs
Normal file
File diff suppressed because it is too large
Load Diff
858
CodeWalker.Core/GameFiles/MetaTypes/Pso.cs
Normal file
858
CodeWalker.Core/GameFiles/MetaTypes/Pso.cs
Normal file
@ -0,0 +1,858 @@
|
||||
/*
|
||||
Copyright(c) 2015 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//shamelessly stolen and mangled
|
||||
|
||||
|
||||
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 enum PsoSection : uint
|
||||
{
|
||||
PSIN = 0x5053494E,
|
||||
PMAP = 0x504D4150,
|
||||
PSCH = 0x50534348,
|
||||
PSIG = 0x50534947,
|
||||
STRF = 0x53545246,
|
||||
STRS = 0x53545253,
|
||||
STRE = 0x53545245,
|
||||
CHKS = 0x43484B53,
|
||||
}
|
||||
|
||||
public enum PsoDataType : byte
|
||||
{
|
||||
Bool = 0x00,
|
||||
SByte = 0x01,
|
||||
UByte = 0x02,
|
||||
SShort = 0x03,
|
||||
UShort = 0x04,
|
||||
SInt = 0x05,
|
||||
UInt = 0x06,
|
||||
Float = 0x07,
|
||||
Float2 = 0x08,
|
||||
Float3 = 0x09,
|
||||
Float4 = 0x0a,
|
||||
String = 0x0b,
|
||||
Structure = 0x0c,
|
||||
Array = 0x0d,
|
||||
Enum = 0x0e,
|
||||
Flags = 0x0f,
|
||||
Map = 0x10,
|
||||
Float3a = 0x14,
|
||||
Float4a = 0x15,
|
||||
HFloat = 0x1e,
|
||||
Long = 0x20,
|
||||
}
|
||||
public static class PsoDataTypes
|
||||
{
|
||||
public static string GetCSharpTypeName(PsoDataType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case PsoDataType.Bool: return "bool";
|
||||
case PsoDataType.SByte: return "sbyte";
|
||||
case PsoDataType.UByte: return "byte";
|
||||
case PsoDataType.SShort: return "short";
|
||||
case PsoDataType.UShort: return "ushort";
|
||||
case PsoDataType.SInt: return "int";
|
||||
case PsoDataType.UInt: return "int";
|
||||
case PsoDataType.Float: return "float";
|
||||
case PsoDataType.Float2: return "long";
|
||||
case PsoDataType.String: return "uint"; //hash? NEEDS WORK?
|
||||
case PsoDataType.Enum: return "byte";
|
||||
case PsoDataType.Flags: return "short";
|
||||
case PsoDataType.HFloat: return "short";
|
||||
case PsoDataType.Long: return "long";
|
||||
case PsoDataType.Float3:
|
||||
case PsoDataType.Float4:
|
||||
case PsoDataType.Map:
|
||||
case PsoDataType.Float3a:
|
||||
case PsoDataType.Float4a:
|
||||
case PsoDataType.Structure:
|
||||
case PsoDataType.Array:
|
||||
default:
|
||||
return t.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoFile
|
||||
{
|
||||
public PsoDataSection DataSection { get; set; }
|
||||
public PsoDataMapSection DataMapSection { get; set; }
|
||||
public PsoSchemaSection SchemaSection { get; set; }
|
||||
public PsoSTRFSection STRFSection { get; set; }
|
||||
public PsoSTRSSection STRSSection { get; set; }
|
||||
public PsoPSIGSection PSIGSection { get; set; }
|
||||
public PsoSTRESection STRESection { get; set; }
|
||||
public PsoCHKSSection CHKSSection { get; set; }
|
||||
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using (var stream = new FileStream(fileName, FileMode.Open))
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
public virtual void Load(Stream stream)
|
||||
{
|
||||
stream.Position = 0;
|
||||
|
||||
var reader = new DataReader(stream, Endianess.BigEndian);
|
||||
while (reader.Position < reader.Length)
|
||||
{
|
||||
var identInt = reader.ReadUInt32();
|
||||
var ident = (PsoSection)identInt;
|
||||
var length = reader.ReadInt32();
|
||||
|
||||
reader.Position -= 8;
|
||||
|
||||
var sectionData = reader.ReadBytes(length);
|
||||
var sectionStream = new MemoryStream(sectionData);
|
||||
var sectionReader = new DataReader(sectionStream, Endianess.BigEndian);
|
||||
|
||||
switch (ident)
|
||||
{
|
||||
case PsoSection.PSIN: //0x5053494E "PSIN" - ID / data section
|
||||
DataSection = new PsoDataSection();
|
||||
DataSection.Read(sectionReader);
|
||||
break;
|
||||
case PsoSection.PMAP: //0x504D4150 "PMAP" //data mapping
|
||||
DataMapSection = new PsoDataMapSection();
|
||||
DataMapSection.Read(sectionReader);
|
||||
break;
|
||||
case PsoSection.PSCH: //0x50534348 "PSCH" //schema
|
||||
SchemaSection = new PsoSchemaSection();
|
||||
SchemaSection.Read(sectionReader);
|
||||
break;
|
||||
case PsoSection.STRF: //0x53545246 "STRF" //paths/STRINGS (folder strings?)
|
||||
STRFSection = new PsoSTRFSection();
|
||||
STRFSection.Read(sectionReader);
|
||||
break;
|
||||
case PsoSection.STRS: //0x53545253 "STRS" //names/strings (DES_)
|
||||
STRSSection = new PsoSTRSSection();
|
||||
STRSSection.Read(sectionReader);
|
||||
break;
|
||||
case PsoSection.STRE: //0x53545245 "STRE" //probably encrypted strings.....
|
||||
STRESection = new PsoSTRESection();
|
||||
STRESection.Read(sectionReader);
|
||||
break;
|
||||
case PsoSection.PSIG: //0x50534947 "PSIG" //signature?
|
||||
PSIGSection = new PsoPSIGSection();
|
||||
PSIGSection.Read(sectionReader);
|
||||
break;
|
||||
case PsoSection.CHKS: //0x43484B53 "CHKS" //checksum?
|
||||
CHKSSection = new PsoCHKSSection();
|
||||
CHKSSection.Read(sectionReader);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using (var stream = new FileStream(fileName, FileMode.Create))
|
||||
Save(stream);
|
||||
}
|
||||
|
||||
public virtual void Save(Stream stream)
|
||||
{
|
||||
var writer = new DataWriter(stream, Endianess.BigEndian);
|
||||
if (DataSection != null) DataSection.Write(writer);
|
||||
if (DataMapSection != null) DataMapSection.Write(writer);
|
||||
if (SchemaSection != null) SchemaSection.Write(writer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public PsoDataMappingEntry GetBlock(int id)
|
||||
{
|
||||
if (DataMapSection == null) return null;
|
||||
if (DataMapSection.Entries == null) return null;
|
||||
PsoDataMappingEntry block = null;
|
||||
var ind = id - 1;
|
||||
var blocks = DataMapSection.Entries;
|
||||
if ((ind >= 0) && (ind < blocks.Length))
|
||||
{
|
||||
block = blocks[ind];
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static bool IsPSO(Stream stream)
|
||||
{
|
||||
//return !IsRBF(stream);
|
||||
|
||||
//1347635534
|
||||
var reader = new DataReader(stream, Endianess.BigEndian);
|
||||
var identInt = reader.ReadUInt32();
|
||||
stream.Position = 0;
|
||||
return ((identInt ) == 1347635534); //"PSIN"
|
||||
|
||||
}
|
||||
|
||||
public static bool IsRBF(Stream stream)
|
||||
{
|
||||
var reader = new DataReader(stream, Endianess.BigEndian);
|
||||
var identInt = reader.ReadUInt32();
|
||||
stream.Position = 0;
|
||||
return ((identInt & 0xFFFFFF00) == 0x52424600);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoDataSection
|
||||
{
|
||||
public uint Ident { get; set; } = 0x5053494E;
|
||||
public int Length { get; private set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadUInt32();
|
||||
Length = reader.ReadInt32();
|
||||
reader.Position -= 8;
|
||||
Data = reader.ReadBytes(Length);
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
writer.Write(Data);
|
||||
writer.Position -= Data.Length;
|
||||
writer.Write((uint)0x5053494E);
|
||||
writer.Write((uint)(Data.Length));
|
||||
writer.Position += Data.Length - 8;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + Length.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoDataMapSection
|
||||
{
|
||||
public int Ident { get; set; } = 0x504D4150;
|
||||
public int Length { get; private set; }
|
||||
public int RootId { get; set; }
|
||||
public short EntriesCount { get; private set; }
|
||||
public short Unknown_Eh { get; set; } = 0x7070;
|
||||
public PsoDataMappingEntry[] Entries { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadInt32();
|
||||
Length = reader.ReadInt32();
|
||||
RootId = reader.ReadInt32();
|
||||
EntriesCount = reader.ReadInt16();
|
||||
Unknown_Eh = reader.ReadInt16();
|
||||
Entries = new PsoDataMappingEntry[EntriesCount];
|
||||
for (int i = 0; i < EntriesCount; i++)
|
||||
{
|
||||
var entry = new PsoDataMappingEntry();
|
||||
entry.Read(reader);
|
||||
Entries[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
// update...
|
||||
EntriesCount = (short)Entries.Length;
|
||||
Length = 16 + EntriesCount * 16;
|
||||
|
||||
writer.Write(Ident);
|
||||
writer.Write(Length);
|
||||
writer.Write(RootId);
|
||||
writer.Write(EntriesCount);
|
||||
writer.Write(Unknown_Eh);
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
entry.Write(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + EntriesCount.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoDataMappingEntry
|
||||
{
|
||||
public MetaName NameHash { get; set; }
|
||||
public int Offset { get; set; }
|
||||
public int Unknown_8h { get; set; } = 0x00000000;
|
||||
public int Length { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
this.NameHash = (MetaName)reader.ReadUInt32();
|
||||
this.Offset = reader.ReadInt32();
|
||||
this.Unknown_8h = reader.ReadInt32();
|
||||
this.Length = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
writer.Write((uint)NameHash);
|
||||
writer.Write(Offset);
|
||||
writer.Write(Unknown_8h);
|
||||
writer.Write(Length);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return NameHash.ToString() + ": " + Offset.ToString() + ": " + Length.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSchemaSection
|
||||
{
|
||||
public int Ident { get; private set; } = 0x50534348;
|
||||
public int Length { get; set; }
|
||||
public uint Count { get; set; }
|
||||
|
||||
public PsoElementIndexInfo[] EntriesIdx { get; set; }
|
||||
public PsoElementInfo[] Entries { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadInt32();
|
||||
Length = reader.ReadInt32();
|
||||
Count = reader.ReadUInt32();
|
||||
|
||||
this.EntriesIdx = new PsoElementIndexInfo[Count];
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
var entry = new PsoElementIndexInfo();
|
||||
entry.Read(reader);
|
||||
EntriesIdx[i] = entry;
|
||||
}
|
||||
|
||||
this.Entries = new PsoElementInfo[Count];
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
reader.Position = EntriesIdx[i].Offset;
|
||||
var type = reader.ReadByte();
|
||||
|
||||
reader.Position = EntriesIdx[i].Offset;
|
||||
if (type == 0)
|
||||
{
|
||||
var entry = new PsoStructureInfo();
|
||||
entry.Read(reader);
|
||||
entry.IndexInfo = EntriesIdx[i];
|
||||
Entries[i] = entry;
|
||||
}
|
||||
else if (type == 1)
|
||||
{
|
||||
var entry = new PsoEnumInfo();
|
||||
entry.Read(reader);
|
||||
entry.IndexInfo = EntriesIdx[i];
|
||||
Entries[i] = entry;
|
||||
}
|
||||
else
|
||||
throw new Exception("unknown type!");
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
|
||||
var entriesStream = new MemoryStream();
|
||||
var entriesWriter = new DataWriter(entriesStream, Endianess.BigEndian);
|
||||
for (int i = 0; i < Entries.Length; i++)
|
||||
{
|
||||
EntriesIdx[i].Offset = 12 + 8 * Entries.Length + (int)entriesWriter.Position;
|
||||
Entries[i].Write(entriesWriter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var indexStream = new MemoryStream();
|
||||
var indexWriter = new DataWriter(indexStream, Endianess.BigEndian);
|
||||
foreach (var entry in EntriesIdx)
|
||||
entry.Write(indexWriter);
|
||||
|
||||
|
||||
|
||||
|
||||
writer.Write(Ident);
|
||||
writer.Write((int)(12 + entriesStream.Length + indexStream.Length));
|
||||
writer.Write((int)(Entries.Length));
|
||||
|
||||
// write entries index data
|
||||
var buf1 = new byte[indexStream.Length];
|
||||
indexStream.Position = 0;
|
||||
indexStream.Read(buf1, 0, buf1.Length);
|
||||
writer.Write(buf1);
|
||||
|
||||
// write entries data
|
||||
var buf2 = new byte[entriesStream.Length];
|
||||
entriesStream.Position = 0;
|
||||
entriesStream.Read(buf2, 0, buf2.Length);
|
||||
writer.Write(buf2);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + Count.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoElementIndexInfo
|
||||
{
|
||||
public MetaName NameHash { get; set; }
|
||||
public int Offset { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
this.NameHash = (MetaName)reader.ReadUInt32();
|
||||
this.Offset = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
writer.Write((uint)NameHash);
|
||||
writer.Write(Offset);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return NameHash.ToString() + ": " + Offset.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public abstract class PsoElementInfo
|
||||
{
|
||||
public PsoElementIndexInfo IndexInfo { get; set; }
|
||||
|
||||
public abstract void Read(DataReader reader);
|
||||
|
||||
public abstract void Write(DataWriter writer);
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoStructureInfo : PsoElementInfo
|
||||
{
|
||||
public byte Type { get; set; } = 0;
|
||||
public short EntriesCount { get; private set; }
|
||||
public byte Unk { get; set; }
|
||||
public int StructureLength { get; set; }
|
||||
public uint Unk_Ch { get; set; } = 0x00000000;
|
||||
public PsoStructureEntryInfo[] Entries { get; set; }
|
||||
|
||||
public override void Read(DataReader reader)
|
||||
{
|
||||
uint x = reader.ReadUInt32();
|
||||
this.Type = (byte)((x & 0xFF000000) >> 24);
|
||||
this.EntriesCount = (short)(x & 0xFFFF);
|
||||
this.Unk = (byte)((x & 0x00FF0000) >> 16);
|
||||
this.StructureLength = reader.ReadInt32();
|
||||
this.Unk_Ch = reader.ReadUInt32();
|
||||
|
||||
Entries = new PsoStructureEntryInfo[EntriesCount];
|
||||
for (int i = 0; i < EntriesCount; i++)
|
||||
{
|
||||
var entry = new PsoStructureEntryInfo();
|
||||
entry.Read(reader);
|
||||
Entries[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(DataWriter writer)
|
||||
{
|
||||
Type = 0;
|
||||
EntriesCount = (short)Entries.Length;
|
||||
|
||||
uint typeAndEntriesCount = (uint)(Type << 24) | (uint)(Unk << 16) | (ushort)EntriesCount;
|
||||
writer.Write(typeAndEntriesCount);
|
||||
writer.Write(StructureLength);
|
||||
writer.Write(Unk_Ch);
|
||||
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
entry.Write(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return IndexInfo.ToString() + " - " + Type.ToString() + ": " + EntriesCount.ToString();
|
||||
}
|
||||
|
||||
public PsoStructureEntryInfo FindEntry(MetaName name)
|
||||
{
|
||||
if (Entries != null)
|
||||
{
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
if (entry.EntryNameHash == name) return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public PsoStructureEntryInfo GetEntry(int id)
|
||||
{
|
||||
if ((Entries != null) && (id >= 0) && (id < Entries.Length))
|
||||
{
|
||||
return Entries[id];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoStructureEntryInfo
|
||||
{
|
||||
public MetaName EntryNameHash { get; set; }
|
||||
public PsoDataType Type { get; set; }
|
||||
public byte Unk_5h { get; set; }
|
||||
public ushort DataOffset { get; set; }
|
||||
public uint ReferenceKey { get; set; } // when array -> entry index with type
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
this.EntryNameHash = (MetaName)reader.ReadUInt32();
|
||||
this.Type = (PsoDataType)reader.ReadByte();
|
||||
this.Unk_5h = reader.ReadByte();
|
||||
this.DataOffset = reader.ReadUInt16();
|
||||
this.ReferenceKey = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
writer.Write((uint)EntryNameHash);
|
||||
writer.Write((byte)Type);
|
||||
writer.Write(Unk_5h);
|
||||
writer.Write(DataOffset);
|
||||
writer.Write(ReferenceKey);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if(ReferenceKey!=0)
|
||||
{
|
||||
return EntryNameHash.ToString() + ": " + Type.ToString() + ": " + DataOffset.ToString() + ": " + ((MetaName)ReferenceKey).ToString();
|
||||
}
|
||||
return EntryNameHash.ToString() + ": " + Type.ToString() + ": " + DataOffset.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoEnumInfo : PsoElementInfo
|
||||
{
|
||||
public byte Type { get; private set; } = 1;
|
||||
public int EntriesCount { get; private set; }
|
||||
public PsoEnumEntryInfo[] Entries { get; set; }
|
||||
|
||||
public override void Read(DataReader reader)
|
||||
{
|
||||
uint x = reader.ReadUInt32();
|
||||
this.Type = (byte)((x & 0xFF000000) >> 24);
|
||||
this.EntriesCount = (int)(x & 0x00FFFFFF);
|
||||
|
||||
Entries = new PsoEnumEntryInfo[EntriesCount];
|
||||
for (int i = 0; i < EntriesCount; i++)
|
||||
{
|
||||
var entry = new PsoEnumEntryInfo();
|
||||
entry.Read(reader);
|
||||
Entries[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(DataWriter writer)
|
||||
{
|
||||
// update...
|
||||
Type = 1;
|
||||
EntriesCount = Entries.Length;
|
||||
|
||||
uint typeAndEntriesCount = (uint)(Type << 24) | (uint)EntriesCount;
|
||||
writer.Write(typeAndEntriesCount);
|
||||
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
entry.Write(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public PsoEnumEntryInfo FindEntry(int val)
|
||||
{
|
||||
if (Entries == null) return null;
|
||||
for (int i = 0; i < Entries.Length; i++)
|
||||
{
|
||||
var entry = Entries[i];
|
||||
if (entry.EntryKey == val)
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return IndexInfo.ToString() + " - " + Type.ToString() + ": " + EntriesCount.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoEnumEntryInfo
|
||||
{
|
||||
public MetaName EntryNameHash { get; set; }
|
||||
public int EntryKey { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
this.EntryNameHash = (MetaName)reader.ReadUInt32();
|
||||
this.EntryKey = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
writer.Write((uint)EntryNameHash);
|
||||
writer.Write(EntryKey);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return EntryNameHash.ToString() + ": " + EntryKey.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSTRFSection
|
||||
{
|
||||
public int Ident { get; private set; } = 0x53545246;
|
||||
public int Length { get; set; }
|
||||
public string[] Strings { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadInt32();
|
||||
Length = reader.ReadInt32();
|
||||
List<string> strs = new List<string>();
|
||||
while (reader.Position < reader.Length)
|
||||
{
|
||||
strs.Add(reader.ReadString());
|
||||
}
|
||||
foreach (var str in strs)
|
||||
{
|
||||
JenkIndex.Ensure(str);
|
||||
JenkIndex.Ensure(str.ToLowerInvariant());
|
||||
}
|
||||
Strings = strs.ToArray();
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
|
||||
writer.Write(Ident);
|
||||
writer.Write(Length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + Length.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSTRSSection
|
||||
{
|
||||
public int Ident { get; private set; } = 0x53545253;
|
||||
public int Length { get; set; }
|
||||
public string[] Strings { get; set; }
|
||||
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadInt32();
|
||||
Length = reader.ReadInt32();
|
||||
|
||||
List<string> strs = new List<string>();
|
||||
while (reader.Position < reader.Length)
|
||||
{
|
||||
strs.Add(reader.ReadString());
|
||||
}
|
||||
foreach (var str in strs)
|
||||
{
|
||||
JenkIndex.Ensure(str);
|
||||
JenkIndex.Ensure(str.ToLowerInvariant());
|
||||
}
|
||||
Strings = strs.ToArray();
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
|
||||
writer.Write(Ident);
|
||||
writer.Write(Length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + Length.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSTRESection
|
||||
{
|
||||
public int Ident { get; private set; } = 0x53545245;
|
||||
public int Length { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
//public MetaHash[] Hashes { get; set; }
|
||||
//public byte[] Decr1 { get; set; }
|
||||
//public byte[] Decr2 { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadInt32();
|
||||
Length = reader.ReadInt32();
|
||||
|
||||
if (Length > 8)
|
||||
{
|
||||
Data = reader.ReadBytes(Length - 8);
|
||||
|
||||
//reader.Position = 8;
|
||||
//List<MetaHash> hashes = new List<MetaHash>();
|
||||
//while (reader.Position < reader.Length)
|
||||
//{
|
||||
// hashes.Add(reader.ReadUInt32());
|
||||
//}
|
||||
//Hashes = hashes.ToArray();
|
||||
|
||||
//Decr1 = GTACrypto.DecryptAES(Data);
|
||||
//Decr2 = GTACrypto.DecryptNG(Data, )
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
|
||||
writer.Write(Ident);
|
||||
writer.Write(Length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + Length.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoPSIGSection
|
||||
{
|
||||
public int Ident { get; private set; } = 0x50534947;
|
||||
public int Length { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadInt32();
|
||||
Length = reader.ReadInt32();
|
||||
|
||||
if (Length > 8)
|
||||
{
|
||||
Data = reader.ReadBytes(Length - 8);
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
|
||||
writer.Write(Ident);
|
||||
writer.Write(Length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + Length.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class PsoCHKSSection
|
||||
{
|
||||
public int Ident { get; private set; } = 0x43484B53;
|
||||
public int Length { get; set; }
|
||||
public uint FileSize { get; set; }
|
||||
public uint Checksum { get; set; }
|
||||
public uint Unk0 { get; set; } = 0x79707070; // "yppp"
|
||||
|
||||
public void Read(DataReader reader)
|
||||
{
|
||||
Ident = reader.ReadInt32();
|
||||
Length = reader.ReadInt32();
|
||||
|
||||
if (Length != 20)
|
||||
{ return; }
|
||||
|
||||
FileSize = reader.ReadUInt32();
|
||||
Checksum = reader.ReadUInt32();
|
||||
Unk0 = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
public void Write(DataWriter writer)
|
||||
{
|
||||
|
||||
writer.Write(Ident);
|
||||
writer.Write(Length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Ident.ToString() + ": " + Length.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
856
CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs
Normal file
856
CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs
Normal file
@ -0,0 +1,856 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using TC = System.ComponentModel.TypeConverterAttribute;
|
||||
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
||||
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public static class PsoTypes
|
||||
{
|
||||
//for parsing schema info in PSO files to generate structs for PSO parsing.
|
||||
//equivalent of MetaTypes but for PSO.
|
||||
|
||||
public static Dictionary<MetaName, PsoEnumInfo> EnumDict = new Dictionary<MetaName, PsoEnumInfo>();
|
||||
public static Dictionary<MetaName, PsoStructureInfo> StructDict = new Dictionary<MetaName, PsoStructureInfo>();
|
||||
|
||||
|
||||
|
||||
public static void Clear()
|
||||
{
|
||||
StructDict.Clear();
|
||||
}
|
||||
|
||||
public static void EnsurePsoTypes(PsoFile pso)
|
||||
{
|
||||
|
||||
if ((pso.SchemaSection == null) || (pso.SchemaSection.Entries == null) || (pso.SchemaSection.EntriesIdx == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < pso.SchemaSection.Entries.Length; i++)
|
||||
{
|
||||
var entry = pso.SchemaSection.Entries[i];
|
||||
var enuminfo = entry as PsoEnumInfo;
|
||||
var structinfo = entry as PsoStructureInfo;
|
||||
|
||||
if (enuminfo != null)
|
||||
{
|
||||
if (!EnumDict.ContainsKey(enuminfo.IndexInfo.NameHash))
|
||||
{
|
||||
EnumDict.Add(enuminfo.IndexInfo.NameHash, enuminfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
PsoEnumInfo oldei = EnumDict[enuminfo.IndexInfo.NameHash];
|
||||
if (!ComparePsoEnumInfos(oldei, enuminfo))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (structinfo != null)
|
||||
{
|
||||
if (!StructDict.ContainsKey(structinfo.IndexInfo.NameHash))
|
||||
{
|
||||
StructDict.Add(structinfo.IndexInfo.NameHash, structinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
PsoStructureInfo oldsi = StructDict[structinfo.IndexInfo.NameHash];
|
||||
if (!ComparePsoStructureInfos(oldsi, structinfo))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static bool ComparePsoEnumInfos(PsoEnumInfo a, PsoEnumInfo b)
|
||||
{
|
||||
//returns true if they are the same.
|
||||
|
||||
if (a.Entries.Length != b.Entries.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < a.Entries.Length; i++)
|
||||
{
|
||||
if ((a.Entries[i].EntryNameHash != b.Entries[i].EntryNameHash) ||
|
||||
(a.Entries[i].EntryKey != b.Entries[i].EntryKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static bool ComparePsoStructureInfos(PsoStructureInfo a, PsoStructureInfo b)
|
||||
{
|
||||
//returns true if they are the same.
|
||||
|
||||
if (a.Entries.Length != b.Entries.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < a.Entries.Length; i++)
|
||||
{
|
||||
if ((a.Entries[i].EntryNameHash != b.Entries[i].EntryNameHash) ||
|
||||
(a.Entries[i].DataOffset != b.Entries[i].DataOffset) ||
|
||||
(a.Entries[i].Type != b.Entries[i].Type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static string GetTypesString()
|
||||
{
|
||||
StringBuilder sbe = new StringBuilder();
|
||||
StringBuilder sbs = new StringBuilder();
|
||||
|
||||
sbe.AppendLine("//Enum infos");
|
||||
sbs.AppendLine("//Struct infos");
|
||||
|
||||
|
||||
foreach (var kvp in EnumDict)
|
||||
{
|
||||
var ei = kvp.Value;
|
||||
string name = GetSafeName(ei.IndexInfo.NameHash, ei.Type);
|
||||
sbe.AppendLine("public enum " + name + " //Type:" + ei.Type.ToString());
|
||||
sbe.AppendLine("{");
|
||||
foreach (var entry in ei.Entries)
|
||||
{
|
||||
string eename = GetSafeName(entry.EntryNameHash, (uint)entry.EntryKey);
|
||||
sbe.AppendFormat(" {0} = {1},", eename, entry.EntryKey);
|
||||
sbe.AppendLine();
|
||||
}
|
||||
sbe.AppendLine("}");
|
||||
sbe.AppendLine();
|
||||
}
|
||||
|
||||
foreach (var kvp in StructDict)
|
||||
{
|
||||
var si = kvp.Value;
|
||||
string name = GetSafeName(si.IndexInfo.NameHash, si.Type);
|
||||
sbs.AppendLine("public struct " + name + " //" + si.StructureLength.ToString() + " bytes, Type:" + si.Type.ToString());
|
||||
sbs.AppendLine("{");
|
||||
for (int i = 0; i < si.Entries.Length; i++)
|
||||
{
|
||||
var entry = si.Entries[i];
|
||||
|
||||
if ((entry.DataOffset == 0) && (entry.EntryNameHash == MetaName.ARRAYINFO)) //referred to by array
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
string sename = GetSafeName(entry.EntryNameHash, entry.ReferenceKey);
|
||||
string fmt = " public {0} {1}; //{2} {3}";
|
||||
|
||||
if (entry.Type == PsoDataType.Array)
|
||||
{
|
||||
if (entry.ReferenceKey >= si.Entries.Length)
|
||||
{
|
||||
sbs.AppendFormat(fmt, entry.Type.ToString(), sename, entry.DataOffset, entry.ToString() + " { unexpected key! " + entry.ReferenceKey.ToString() + "}");
|
||||
sbs.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
var structentry = si.Entries[(int)entry.ReferenceKey];
|
||||
var typename = "Array_" + PsoDataTypes.GetCSharpTypeName(structentry.Type);
|
||||
sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry.ToString() + " {" + structentry.ToString() + "}");
|
||||
sbs.AppendLine();
|
||||
}
|
||||
}
|
||||
else if (entry.Type == PsoDataType.Structure)
|
||||
{
|
||||
var typename = GetSafeName((MetaName)entry.ReferenceKey, entry.ReferenceKey);
|
||||
sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry.ToString());
|
||||
sbs.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
var typename = PsoDataTypes.GetCSharpTypeName(entry.Type);
|
||||
sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry);
|
||||
sbs.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
sbs.AppendLine("}");
|
||||
sbs.AppendLine();
|
||||
}
|
||||
|
||||
|
||||
sbe.AppendLine();
|
||||
sbe.AppendLine();
|
||||
sbe.AppendLine();
|
||||
sbe.AppendLine();
|
||||
sbe.AppendLine();
|
||||
sbe.Append(sbs.ToString());
|
||||
|
||||
string result = sbe.ToString();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static string GetSafeName(MetaName namehash, uint key)
|
||||
{
|
||||
string name = namehash.ToString();
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
name = "Unk_" + key;
|
||||
}
|
||||
if (!char.IsLetter(name[0]))
|
||||
{
|
||||
name = "Unk_" + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static T ConvertDataRaw<T>(byte[] data) where T : struct
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
var h = handle.AddrOfPinnedObject();
|
||||
var r = Marshal.PtrToStructure<T>(h);
|
||||
handle.Free();
|
||||
return r;
|
||||
}
|
||||
public static T ConvertDataRaw<T>(byte[] data, int offset) where T : struct
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
var h = handle.AddrOfPinnedObject();
|
||||
var r = Marshal.PtrToStructure<T>(h + offset);
|
||||
handle.Free();
|
||||
return r;
|
||||
}
|
||||
public static T ConvertData<T>(byte[] data, int offset) where T : struct, IPsoSwapEnd
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
var h = handle.AddrOfPinnedObject();
|
||||
var r = Marshal.PtrToStructure<T>(h + offset);
|
||||
handle.Free();
|
||||
r.SwapEnd();
|
||||
return r;
|
||||
}
|
||||
public static T[] ConvertDataArrayRaw<T>(byte[] data, int offset, int count) where T : struct
|
||||
{
|
||||
T[] items = new T[count];
|
||||
int itemsize = Marshal.SizeOf(typeof(T));
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int off = offset + i * itemsize;
|
||||
items[i] = ConvertDataRaw<T>(data, off);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
public static T GetItem<T>(PsoFile pso, int offset) where T : struct, IPsoSwapEnd
|
||||
{
|
||||
return ConvertData<T>(pso.DataSection.Data, offset);
|
||||
}
|
||||
public static T GetRootItem<T>(PsoFile pso) where T : struct, IPsoSwapEnd
|
||||
{
|
||||
var i = pso.DataMapSection.RootId - 1;
|
||||
var e = pso.DataMapSection.Entries[i];
|
||||
return GetItem<T>(pso, e.Offset);
|
||||
}
|
||||
public static PsoDataMappingEntry GetRootEntry(PsoFile pso)
|
||||
{
|
||||
var i = pso.DataMapSection.RootId - 1;
|
||||
var e = pso.DataMapSection.Entries[i];
|
||||
return e;
|
||||
}
|
||||
|
||||
public static T[] GetItemArrayRaw<T>(PsoFile pso, Array_Structure arr) where T : struct
|
||||
{
|
||||
if ((arr.Count1 > 0) && (arr.Pointer > 0))
|
||||
{
|
||||
var entry = pso.DataMapSection.Entries[(int)arr.PointerDataIndex];
|
||||
return ConvertDataArrayRaw<T>(pso.DataSection.Data, entry.Offset, arr.Count1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static T[] GetItemArray<T>(PsoFile pso, Array_Structure arr) where T : struct, IPsoSwapEnd
|
||||
{
|
||||
if ((arr.Count1 > 0) && (arr.Pointer > 0))
|
||||
{
|
||||
var entry = pso.DataMapSection.Entries[(int)arr.PointerDataIndex];
|
||||
var res = ConvertDataArrayRaw<T>(pso.DataSection.Data, entry.Offset, arr.Count1);
|
||||
if (res != null)
|
||||
{
|
||||
for (int i = 0; i < res.Length; i++)
|
||||
{
|
||||
res[i].SwapEnd();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static uint[] GetUintArrayRaw(PsoFile pso, Array_uint arr)
|
||||
{
|
||||
byte[] data = pso.DataSection.Data;
|
||||
var entryid = arr.Pointer & 0xFFF;
|
||||
if ((entryid == 0) || (entryid > pso.DataMapSection.EntriesCount))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var entryoffset = (arr.Pointer & 0xFFFFFF) >> 12;
|
||||
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
||||
int totoffset = arrentry.Offset + (int)entryoffset;
|
||||
uint[] readdata = ConvertDataArrayRaw<uint>(data, totoffset, arr.Count1);
|
||||
return readdata;
|
||||
}
|
||||
public static uint[] GetUintArray(PsoFile pso, Array_uint arr)
|
||||
{
|
||||
uint[] uints = GetUintArrayRaw(pso, arr);
|
||||
if (uints == null) return null;
|
||||
for (int i = 0; i < uints.Length; i++)
|
||||
{
|
||||
uints[i] = MetaTypes.SwapBytes(uints[i]);
|
||||
}
|
||||
return uints;
|
||||
}
|
||||
|
||||
public static MetaHash[] GetHashArray(PsoFile pso, Array_uint arr)
|
||||
{
|
||||
uint[] uints = GetUintArrayRaw(pso, arr);
|
||||
if (uints == null) return null;
|
||||
MetaHash[] hashes = new MetaHash[uints.Length];
|
||||
for (int n = 0; n < uints.Length; n++)
|
||||
{
|
||||
hashes[n].Hash = MetaTypes.SwapBytes(uints[n]);
|
||||
}
|
||||
return hashes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static float[] GetFloatArrayRaw(PsoFile pso, Array_float arr)
|
||||
{
|
||||
byte[] data = pso.DataSection.Data;
|
||||
var entryid = arr.Pointer & 0xFFF;
|
||||
if ((entryid == 0) || (entryid > pso.DataMapSection.EntriesCount))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var entryoffset = (arr.Pointer & 0xFFFFFF) >> 12;
|
||||
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
||||
int totoffset = arrentry.Offset + (int)entryoffset;
|
||||
float[] readdata = ConvertDataArrayRaw<float>(data, totoffset, arr.Count1);
|
||||
return readdata;
|
||||
}
|
||||
public static float[] GetFloatArray(PsoFile pso, Array_float arr)
|
||||
{
|
||||
float[] floats = GetFloatArrayRaw(pso, arr);
|
||||
if (floats == null) return null;
|
||||
for (int i = 0; i < floats.Length; i++)
|
||||
{
|
||||
floats[i] = MetaTypes.SwapBytes(floats[i]);
|
||||
}
|
||||
return floats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static ushort[] GetUShortArrayRaw(PsoFile pso, Array_Structure arr)
|
||||
{
|
||||
byte[] data = pso.DataSection.Data;
|
||||
var entryid = arr.Pointer & 0xFFF;
|
||||
if ((entryid == 0) || (entryid > pso.DataMapSection.EntriesCount))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var entryoffset = (arr.Pointer & 0xFFFFFF) >> 12;
|
||||
var arrentry = pso.DataMapSection.Entries[(int)entryid - 1];
|
||||
int totoffset = arrentry.Offset + (int)entryoffset;
|
||||
ushort[] readdata = ConvertDataArrayRaw<ushort>(data, totoffset, arr.Count1);
|
||||
return readdata;
|
||||
}
|
||||
public static ushort[] GetUShortArray(PsoFile pso, Array_Structure arr)
|
||||
{
|
||||
ushort[] ushorts = GetUShortArrayRaw(pso, arr);
|
||||
if (ushorts == null) return null;
|
||||
for (int i = 0; i < ushorts.Length; i++)
|
||||
{
|
||||
ushorts[i] = MetaTypes.SwapBytes(ushorts[i]);
|
||||
}
|
||||
return ushorts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static T[] GetObjectArray<T, U>(PsoFile pso, Array_Structure arr) where U : struct, IPsoSwapEnd where T : PsoClass<U>, new()
|
||||
{
|
||||
U[] items = GetItemArray<U>(pso, arr);
|
||||
if (items == null) return null;
|
||||
if (items.Length == 0) return null;
|
||||
T[] result = new T[items.Length];
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
T newitem = new T();
|
||||
newitem.Init(pso, ref items[i]);
|
||||
result[i] = newitem;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] GetByteArray(PsoFile pso, PsoStructureEntryInfo entry, int offset)
|
||||
{
|
||||
var aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
||||
var aBlockId = (int)entry.ReferenceKey & 0x0000FFFF;
|
||||
var block = pso.GetBlock(aBlockId);
|
||||
if (block == null) return null;
|
||||
|
||||
//block.Offset
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static PsoPOINTER[] GetPointerArray(PsoFile pso, Array_StructurePointer array)
|
||||
{
|
||||
uint count = array.Count1;
|
||||
if (count == 0) return null;
|
||||
|
||||
int ptrsize = Marshal.SizeOf(typeof(MetaPOINTER));
|
||||
int itemsleft = (int)count; //large arrays get split into chunks...
|
||||
uint ptr = array.Pointer;
|
||||
int ptrindex = (int)(ptr & 0xFFF) - 1;
|
||||
int ptroffset = (int)((ptr >> 12) & 0xFFFFF);
|
||||
var ptrblock = (ptrindex < pso.DataMapSection.EntriesCount) ? pso.DataMapSection.Entries[ptrindex] : null;
|
||||
if ((ptrblock == null) || (ptrblock.NameHash != MetaName.PsoPOINTER))
|
||||
{ return null; }
|
||||
|
||||
var offset = ptrblock.Offset;
|
||||
int boffset = offset + ptroffset;
|
||||
|
||||
var ptrs = ConvertDataArrayRaw<PsoPOINTER>(pso.DataSection.Data, boffset, (int)count);
|
||||
if (ptrs != null)
|
||||
{
|
||||
for (int i = 0; i < ptrs.Length; i++)
|
||||
{
|
||||
ptrs[i].SwapEnd();
|
||||
}
|
||||
}
|
||||
|
||||
return ptrs;
|
||||
}
|
||||
|
||||
|
||||
public static T[] ConvertDataArray<T>(PsoFile pso, Array_StructurePointer array) where T : struct, IPsoSwapEnd
|
||||
{
|
||||
uint count = array.Count1;
|
||||
if (count == 0) return null;
|
||||
PsoPOINTER[] ptrs = GetPointerArray(pso, array);
|
||||
if (ptrs == null) return null;
|
||||
if (ptrs.Length < count)
|
||||
{ return null; }
|
||||
|
||||
T[] items = new T[count];
|
||||
int itemsize = Marshal.SizeOf(typeof(T));
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var sptr = ptrs[i];
|
||||
int blocki = sptr.BlockID - 1;
|
||||
int offset = (int)sptr.ItemOffset;// * 16;//block data size...
|
||||
if (blocki >= pso.DataMapSection.EntriesCount)
|
||||
{ continue; }
|
||||
var block = pso.DataMapSection.Entries[blocki];
|
||||
|
||||
if ((offset < 0) || (offset >= block.Length))
|
||||
{ continue; }
|
||||
|
||||
int boffset = block.Offset + offset;
|
||||
|
||||
items[i] = ConvertData<T>(pso.DataSection.Data, boffset);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static string GetString(PsoFile pso, CharPointer ptr)
|
||||
{
|
||||
if (ptr.Count1 == 0) return null;
|
||||
|
||||
var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1;
|
||||
var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF;
|
||||
|
||||
var block = pso.GetBlock(blocki);
|
||||
if (block == null)
|
||||
{ return null; }
|
||||
|
||||
var length = ptr.Count1;
|
||||
var lastbyte = offset + length;
|
||||
if (lastbyte >= block.Length)
|
||||
{ return null; }
|
||||
|
||||
var data = pso.DataSection?.Data;
|
||||
if (data == null)
|
||||
{ return null; }
|
||||
|
||||
var doffset = block.Offset + offset;
|
||||
|
||||
string s = Encoding.ASCII.GetString(data, doffset, length);
|
||||
|
||||
//if (meta.Strings == null) return null;
|
||||
//if (offset < 0) return null;
|
||||
//if (offset >= meta.Strings.Length) return null;
|
||||
//string s = meta.Strings[offset];
|
||||
|
||||
return s;
|
||||
}
|
||||
public static string GetString(PsoFile pso, DataBlockPointer ptr)
|
||||
{
|
||||
var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1;
|
||||
var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF;
|
||||
|
||||
var block = pso.GetBlock(blocki);
|
||||
if (block == null)
|
||||
{ return null; }
|
||||
|
||||
//var length = ptr.Count1;
|
||||
//var lastbyte = offset + length;
|
||||
//if (lastbyte >= block.Length)
|
||||
//{ return null; }
|
||||
|
||||
var data = pso.DataSection?.Data;
|
||||
if (data == null)
|
||||
{ return null; }
|
||||
|
||||
//var doffset = block.Offset + offset;
|
||||
|
||||
//string s = Encoding.ASCII.GetString(data, doffset, length);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var o = block.Offset + offset;
|
||||
char c = (char)data[o];
|
||||
while (c != 0)
|
||||
{
|
||||
sb.Append(c);
|
||||
o++;
|
||||
c = (char)data[o];
|
||||
}
|
||||
var s = sb.ToString();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public interface IPsoSwapEnd
|
||||
{
|
||||
void SwapEnd();
|
||||
}
|
||||
|
||||
public abstract class PsoClass<T> where T : struct, IPsoSwapEnd
|
||||
{
|
||||
public abstract void Init(PsoFile pso, ref T v);
|
||||
}
|
||||
|
||||
|
||||
public struct PsoChar64
|
||||
{
|
||||
public byte b00, b01, b02, b03, b04, b05, b06, b07, b08, b09,
|
||||
b10, b11, b12, b13, b14, b15, b16, b17, b18, b19,
|
||||
b20, b21, b22, b23, b24, b25, b26, b27, b28, b29,
|
||||
b30, b31, b32, b33, b34, b35, b36, b37, b38, b39,
|
||||
b40, b41, b42, b43, b44, b45, b46, b47, b48, b49,
|
||||
b50, b51, b52, b53, b54, b55, b56, b57, b58, b59,
|
||||
b60, b61, b62, b63;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
byte[] bytes = new byte[]
|
||||
{
|
||||
b00, b01, b02, b03, b04, b05, b06, b07, b08, b09,
|
||||
b10, b11, b12, b13, b14, b15, b16, b17, b18, b19,
|
||||
b20, b21, b22, b23, b24, b25, b26, b27, b28, b29,
|
||||
b30, b31, b32, b33, b34, b35, b36, b37, b38, b39,
|
||||
b40, b41, b42, b43, b44, b45, b46, b47, b48, b49,
|
||||
b50, b51, b52, b53, b54, b55, b56, b57, b58, b59,
|
||||
b60, b61, b62, b63
|
||||
};
|
||||
return Encoding.ASCII.GetString(bytes).Replace("\0", string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[TC(typeof(EXP))] public struct PsoPOINTER : IPsoSwapEnd //8 bytes - pointer to data item
|
||||
{
|
||||
public uint Pointer { get; set; }
|
||||
public uint Unk2 { get; set; }
|
||||
|
||||
public ushort BlockID { get { return (ushort)(Pointer & 0xFFF); } } //1-based ID
|
||||
public uint ItemOffset { get { return ((Pointer>>12) & 0xFFFFF); } } //byte offset
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return BlockID.ToString() + ", " + ItemOffset.ToString() + ", " + Unk2.ToString();
|
||||
}
|
||||
|
||||
public void SwapEnd()
|
||||
{
|
||||
Pointer = MetaTypes.SwapBytes(Pointer);
|
||||
Unk2 = MetaTypes.SwapBytes(Unk2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Struct infos
|
||||
[TC(typeof(EXP))] public struct CPackFileMetaData : IPsoSwapEnd //96 bytes, Type:0
|
||||
{
|
||||
public Array_Structure MapDataGroups; //0 MapDataGroups: Array: 0 {256: Structure: 0: 3260758307}
|
||||
public Array_Structure HDTxdBindingArray; //16 HDTxdBindingArray: Array: 16: 2 {256: Structure: 0: CHDTxdAssetBinding}
|
||||
public Array_Structure imapDependencies; //32 imapDependencies: Array: 32: 4 {256: Structure: 0: 3501026914}
|
||||
public Array_Structure imapDependencies_2; //48 imapDependencies_2: Array: 48: 6 {256: Structure: 0: 3240050401}
|
||||
public Array_Structure itypDependencies_2; //64 itypDependencies_2: Array: 64: 8 {256: Structure: 0: 1515605584}
|
||||
public Array_Structure Interiors; //80 Interiors: Array: 80: 10 {256: Structure: 0: 741495440}
|
||||
|
||||
public void SwapEnd()
|
||||
{
|
||||
MapDataGroups.SwapEnd();
|
||||
HDTxdBindingArray.SwapEnd();
|
||||
imapDependencies.SwapEnd();
|
||||
imapDependencies_2.SwapEnd();
|
||||
itypDependencies_2.SwapEnd();
|
||||
Interiors.SwapEnd();
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct CMapDataGroup : IPsoSwapEnd //56 bytes, Type:0
|
||||
{
|
||||
public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0
|
||||
public uint Unused0 { get; set; } //4
|
||||
public Array_uint Bounds { get; set; } //8 Bounds//3298223272: Array: 8: 1 {256: INT_0Bh: 0}
|
||||
public ushort Flags { get; set; } //24 Flags: SHORT_0Fh: 24: 2097155
|
||||
public ushort Unused1 { get; set; }//26
|
||||
public uint Unused2 { get; set; }//28
|
||||
public Array_uint WeatherTypes { get; set; } //32 WeatherTypes: Array: 32: 5 {256: INT_0Bh: 0}
|
||||
public uint HoursOnOff { get; set; } //48 HoursOnOff//4190815249: INT_06h: 48
|
||||
public uint Unused3 { get; set; }//52
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name.ToString() + ": ybn:" + Bounds.Count1.ToString() + ", wt:" + WeatherTypes.Count1.ToString() + ", flags:" + Flags.ToString() + ", hours:" + HoursOnOff.ToString();
|
||||
}
|
||||
|
||||
public void SwapEnd()
|
||||
{
|
||||
Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash));
|
||||
var b = Bounds; b.SwapEnd(); Bounds = b;
|
||||
var w = WeatherTypes; w.SwapEnd(); WeatherTypes = w;
|
||||
HoursOnOff = MetaTypes.SwapBytes(HoursOnOff);
|
||||
Flags = MetaTypes.SwapBytes(Flags);
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct CHDTxdAssetBinding : IPsoSwapEnd //132 bytes, Type:0
|
||||
{
|
||||
public byte assetType { get; set; } //0 assetType: BYTE_ENUM_VALUE: 0: 3387532954
|
||||
public byte Unused01 { get; set; }//1
|
||||
public ushort Unused02 { get; set; }//2
|
||||
public PsoChar64 targetAsset { get; set; } //4 targetAsset: INT_0Bh: 4: 4194304
|
||||
public PsoChar64 HDTxd { get; set; } //68 HDTxd: INT_0Bh: 68: 4194304
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return assetType.ToString() + ": " + targetAsset.ToString() + ": " + HDTxd.ToString();
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
//targetAsset.Hash = MetaTypes.SwapBytes(targetAsset.Hash);
|
||||
//HDTxd.Hash = MetaTypes.SwapBytes(HDTxd.Hash);
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct CImapDependency : IPsoSwapEnd //12 bytes, Type:0 // CImapDependency//3501026914
|
||||
{
|
||||
public MetaHash imapName { get; set; } //0 imapName: INT_0Bh: 0
|
||||
public MetaHash itypName { get; set; } //4 itypName//2890158180: INT_0Bh: 4
|
||||
public MetaHash packFileName { get; set; } //8 packFileName//4216494073: INT_0Bh: 8
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return imapName.ToString() + ", " + itypName.ToString() + ", " + packFileName.ToString();
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
imapName = new MetaHash(MetaTypes.SwapBytes(imapName.Hash));
|
||||
itypName = new MetaHash(MetaTypes.SwapBytes(itypName.Hash));
|
||||
packFileName = new MetaHash(MetaTypes.SwapBytes(packFileName.Hash));
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct CImapDependencies : IPsoSwapEnd //24 bytes, Type:0 // CImapDependencies//3240050401 imapDependencies_2
|
||||
{
|
||||
public MetaHash imapName { get; set; } //0 imapName: INT_0Bh: 0 //name hash
|
||||
public ushort manifestFlags { get; set; } //4 manifestFlags//1683136603: SHORT_0Fh: 4: 2097153
|
||||
public ushort Unused0 { get; set; } //6
|
||||
public Array_uint itypDepArray { get; set; } //8 itypDepArray//2410949350: Array: 8: 3 {256: INT_0Bh: 0} //children...
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return imapName.ToString() + ": " + manifestFlags.ToString() + ": " + itypDepArray.ToString();
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
imapName = new MetaHash(MetaTypes.SwapBytes(imapName.Hash));
|
||||
manifestFlags = MetaTypes.SwapBytes(manifestFlags);
|
||||
var d = itypDepArray; d.SwapEnd(); itypDepArray = d;
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct CItypDependencies : IPsoSwapEnd //24 bytes, Type:0 // CItypDependencies//1515605584 itypDependencies_2
|
||||
{
|
||||
public MetaHash itypName { get; set; } //0 itypName//2890158180: INT_0Bh: 0
|
||||
public ushort manifestFlags { get; set; } //4 manifestFlags//1683136603: SHORT_0Fh: 4: 2097153
|
||||
public ushort Unused0 { get; set; } //6
|
||||
public Array_uint itypDepArray { get; set; } //8 itypDepArray//2410949350: Array: 8: 3 {256: INT_0Bh: 0}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return itypName.ToString() + ": " + manifestFlags.ToString() + ": " + itypDepArray.ToString();
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
itypName = new MetaHash(MetaTypes.SwapBytes(itypName.Hash));
|
||||
manifestFlags = MetaTypes.SwapBytes(manifestFlags);
|
||||
var d = itypDepArray; d.SwapEnd(); itypDepArray = d;
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct Unk_741495440 : IPsoSwapEnd //24 bytes, Type:0 // Interiors
|
||||
{
|
||||
public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0
|
||||
public uint Unused0 { get; set; } //4
|
||||
public Array_uint Bounds { get; set; } //8 Bounds//3298223272: Array: 8: 1 {256: INT_0Bh: 0}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return JenkIndex.GetString(Name);
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash));
|
||||
var b = Bounds; b.SwapEnd(); Bounds = b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[TC(typeof(EXP))] public struct CScenarioPointManifest : IPsoSwapEnd //56 bytes, Type:0
|
||||
{
|
||||
public int VersionNumber { get; set; } //0 VersionNumber: INT_05h: 0
|
||||
public uint Unused0 { get; set; } //4
|
||||
public Array_StructurePointer RegionDefs { get; set; } //8 RegionDefs: Array: 8: 1 {ARRAYINFO: Structure: 0}
|
||||
public Array_StructurePointer Groups { get; set; } //24 Groups: Array: 24: 3 {ARRAYINFO: Structure: 0}
|
||||
public Array_uint InteriorNames { get; set; } //40 InteriorNames: Array: 40: 5 {ARRAYINFO: INT_0Bh: 0}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return VersionNumber.ToString();
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
VersionNumber = MetaTypes.SwapBytes(VersionNumber);
|
||||
var r = RegionDefs; r.SwapEnd(); RegionDefs = r;
|
||||
var g = Groups; g.SwapEnd(); Groups = g;
|
||||
var i = InteriorNames; i.SwapEnd(); InteriorNames = i;
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct CScenarioPointRegionDef : IPsoSwapEnd //64 bytes, Type:0
|
||||
{
|
||||
public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0
|
||||
public uint Unused0 { get; set; } //4
|
||||
public uint Unused1 { get; set; } //8
|
||||
public uint Unused2 { get; set; } //12
|
||||
public rage__spdAABB AABB { get; set; } //16 AABB: Structure: 16: rage__spdAABB
|
||||
public uint Unused3 { get; set; } //48
|
||||
public uint Unused4 { get; set; } //52
|
||||
public uint Unused5 { get; set; } //56
|
||||
public uint Unused6 { get; set; } //60
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name.ToString() + ", " + AABB.ToString();
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash));
|
||||
var aabb = AABB; aabb.SwapEnd(); AABB = aabb;
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))] public struct CScenarioPointGroup : IPsoSwapEnd //8 bytes, Type:0
|
||||
{
|
||||
public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0
|
||||
public byte EnabledByDefault { get; set; } //4 EnabledByDefault: BYTE_00h: 4
|
||||
public byte Unused0 { get; set; } //5
|
||||
public ushort Unused1 { get; set; } //6
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name.ToString();
|
||||
}
|
||||
public void SwapEnd()
|
||||
{
|
||||
Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
295
CodeWalker.Core/GameFiles/MetaTypes/Rbf.cs
Normal file
295
CodeWalker.Core/GameFiles/MetaTypes/Rbf.cs
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
Copyright(c) 2015 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//shamelessly stolen and mangled
|
||||
|
||||
|
||||
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 RbfFile
|
||||
{
|
||||
private const int RBF_IDENT = 0x30464252;
|
||||
|
||||
public RbfStructure current { get; set; }
|
||||
public Stack<RbfStructure> stack { get; set; }
|
||||
public List<RbfEntryDescription> descriptors { get; set; }
|
||||
|
||||
public RbfStructure Load(string fileName)
|
||||
{
|
||||
using (var fileStream = new FileStream(fileName, FileMode.Open))
|
||||
{
|
||||
return Load(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
public RbfStructure Load(Stream stream)
|
||||
{
|
||||
stack = new Stack<RbfStructure>();
|
||||
descriptors = new List<RbfEntryDescription>();
|
||||
|
||||
var reader = new DataReader(stream);
|
||||
var ident = reader.ReadInt32();
|
||||
if (ident != RBF_IDENT)
|
||||
throw new Exception("The file identifier does not match.");
|
||||
|
||||
while (reader.Position < reader.Length)
|
||||
{
|
||||
var descriptorIndex = reader.ReadByte();
|
||||
if (descriptorIndex == 0xFF) // close tag
|
||||
{
|
||||
var b = reader.ReadByte();
|
||||
if (b != 0xFF)
|
||||
throw new Exception("Expected 0xFF but was " + b.ToString("X2"));
|
||||
|
||||
if (stack.Count > 0)
|
||||
{
|
||||
current = stack.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reader.Position != reader.Length)
|
||||
throw new Exception("Expected end of stream but was not.");
|
||||
return current;
|
||||
}
|
||||
}
|
||||
else if (descriptorIndex == 0xFD) // bytes
|
||||
{
|
||||
var b = reader.ReadByte();
|
||||
if (b != 0xFF)
|
||||
throw new Exception("Expected 0xFF but was " + b.ToString("X2"));
|
||||
|
||||
var dataLength = reader.ReadInt32();
|
||||
var data = reader.ReadBytes(dataLength);
|
||||
|
||||
var bytesValue = new RbfBytes();
|
||||
bytesValue.Value = data;
|
||||
current.Children.Add(bytesValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dataType = reader.ReadByte();
|
||||
if (descriptorIndex == descriptors.Count) // new descriptor + data
|
||||
{
|
||||
var nameLength = reader.ReadInt16();
|
||||
var nameBytes = reader.ReadBytes(nameLength);
|
||||
var name = Encoding.ASCII.GetString(nameBytes);
|
||||
|
||||
var descriptor = new RbfEntryDescription();
|
||||
descriptor.Name = name;
|
||||
descriptor.Type = dataType;
|
||||
descriptors.Add(descriptor);
|
||||
|
||||
ParseElement(reader, descriptors.Count - 1, dataType);
|
||||
}
|
||||
else // existing descriptor + data
|
||||
{
|
||||
if (dataType != descriptors[descriptorIndex].Type)
|
||||
{
|
||||
//throw new Exception("Data type does not match. Expected "
|
||||
// + descriptors[descriptorIndex].Type.ToString() + " but found "
|
||||
// + dataType.ToString() + ". Descriptor: " + descriptors[descriptorIndex].Name);
|
||||
}
|
||||
|
||||
ParseElement(reader, descriptorIndex, dataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Unexpected end of stream.");
|
||||
}
|
||||
|
||||
private void ParseElement(DataReader reader, int descriptorIndex, byte dataType)
|
||||
{
|
||||
var descriptor = descriptors[descriptorIndex];
|
||||
switch (dataType) //(descriptor.Type)
|
||||
{
|
||||
case 0: // open element...
|
||||
{
|
||||
var structureValue = new RbfStructure();
|
||||
structureValue.Name = descriptor.Name;
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
current.Children.Add(structureValue);
|
||||
stack.Push(current);
|
||||
}
|
||||
|
||||
current = structureValue;
|
||||
|
||||
// 6 bytes
|
||||
var x1 = reader.ReadInt16();
|
||||
var x2 = reader.ReadInt16();
|
||||
var x3 = reader.ReadInt16();
|
||||
//if (x1 != 0)
|
||||
// throw new Exception("unexpected");
|
||||
//if (x2 != 0)
|
||||
// throw new Exception("unexpected");
|
||||
//if (x3 != 0)
|
||||
// throw new Exception("unexpected");
|
||||
break;
|
||||
}
|
||||
case 0x10:
|
||||
{
|
||||
var intValue = new RbfUint32();
|
||||
intValue.Name = descriptor.Name;
|
||||
intValue.Value = reader.ReadUInt32();
|
||||
current.Children.Add(intValue);
|
||||
break;
|
||||
}
|
||||
case 0x20:
|
||||
{
|
||||
var booleanValue = new RbfBoolean();
|
||||
booleanValue.Name = descriptor.Name;
|
||||
booleanValue.Value = true;
|
||||
current.Children.Add(booleanValue);
|
||||
break;
|
||||
}
|
||||
case 0x30:
|
||||
{
|
||||
var booleanValue = new RbfBoolean();
|
||||
booleanValue.Name = descriptor.Name;
|
||||
booleanValue.Value = false;
|
||||
current.Children.Add(booleanValue);
|
||||
break;
|
||||
}
|
||||
case 0x40:
|
||||
{
|
||||
var floatValue = new RbfFloat();
|
||||
floatValue.Name = descriptor.Name;
|
||||
floatValue.Value = reader.ReadSingle();
|
||||
current.Children.Add(floatValue);
|
||||
break;
|
||||
}
|
||||
case 0x50:
|
||||
{
|
||||
var floatVectorValue = new RbfFloat3();
|
||||
floatVectorValue.Name = descriptor.Name;
|
||||
floatVectorValue.X = reader.ReadSingle();
|
||||
floatVectorValue.Y = reader.ReadSingle();
|
||||
floatVectorValue.Z = reader.ReadSingle();
|
||||
current.Children.Add(floatVectorValue);
|
||||
break;
|
||||
}
|
||||
case 0x60:
|
||||
{
|
||||
var valueLength = reader.ReadInt16();
|
||||
var valueBytes = reader.ReadBytes(valueLength);
|
||||
var value = Encoding.ASCII.GetString(valueBytes);
|
||||
var stringValue = new RbfString();
|
||||
stringValue.Name = descriptor.Name;
|
||||
stringValue.Value = value;
|
||||
current.Children.Add(stringValue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Exception("Unsupported data type.");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsRBF(Stream stream)
|
||||
{
|
||||
var reader = new DataReader(stream);
|
||||
var origpos = stream.Position;
|
||||
var ident = reader.ReadInt32();
|
||||
var isrbf = (ident == RBF_IDENT);
|
||||
stream.Position = origpos;
|
||||
return isrbf;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfEntryDescription
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Type { get; set; }
|
||||
public override string ToString() { return Name + ": " + Type.ToString(); }
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public interface IRbfType
|
||||
{
|
||||
string Name { get; set; }
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfBoolean : IRbfType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool Value { get; set; }
|
||||
public override string ToString() { return Name + ": " + Value.ToString(); }
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfBytes : IRbfType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public byte[] Value { get; set; }
|
||||
public override string ToString() { return Name + ": " + Value.ToString(); }
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfFloat : IRbfType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public float Value { get; set; }
|
||||
public override string ToString() { return Name + ": " + Value.ToString(); }
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfFloat3 : IRbfType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float Z { get; set; }
|
||||
public override string ToString() { return string.Format("{0}: X:{1}, Y:{2}, Z:{3}", Name, X, Y, Z); }
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfString : IRbfType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
public override string ToString() { return Name + ": " + Value.ToString(); }
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfStructure : IRbfType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<IRbfType> Children { get; set; } = new List<IRbfType>();
|
||||
public override string ToString() { return Name + ": {" + Children.Count.ToString() + "}"; }
|
||||
public IRbfType FindChild(string name)
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (child == null) continue;
|
||||
if (child.Name == name) return child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class RbfUint32 : IRbfType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public uint Value { get; set; }
|
||||
public override string ToString() { return Name + ": " + Value.ToString(); }
|
||||
}
|
||||
|
||||
|
||||
}
|
774
CodeWalker.Core/GameFiles/MetaTypes/XmlMeta.cs
Normal file
774
CodeWalker.Core/GameFiles/MetaTypes/XmlMeta.cs
Normal file
@ -0,0 +1,774 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using SharpDX;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public class XmlMeta
|
||||
{
|
||||
public static Meta GetMeta(XmlDocument doc)
|
||||
{
|
||||
MetaBuilder mb = new MetaBuilder();
|
||||
|
||||
Traverse(doc.DocumentElement, mb, 0, true);
|
||||
|
||||
var meta = mb.GetMeta();
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
private static byte[] Traverse(XmlNode node, MetaBuilder mb, MetaName type = 0, bool isRoot = false)
|
||||
{
|
||||
if(type == 0)
|
||||
{
|
||||
type = (MetaName)(uint)GetHash(node.Name);
|
||||
}
|
||||
|
||||
var infos = MetaTypes.GetStructureInfo(type);
|
||||
|
||||
if (infos != null)
|
||||
{
|
||||
byte[] data = new byte[infos.StructureSize];
|
||||
var arrayResults = new ArrayResults();
|
||||
|
||||
arrayResults.Structures = new Dictionary<int, Array_Structure>();
|
||||
arrayResults.StructurePointers = new Dictionary<int, Array_StructurePointer>();
|
||||
arrayResults.UInts = new Dictionary<int, Array_uint>();
|
||||
arrayResults.UShorts = new Dictionary<int, Array_ushort>();
|
||||
arrayResults.UBytes = new Dictionary<int, Array_byte>();
|
||||
arrayResults.Floats = new Dictionary<int, Array_float>();
|
||||
arrayResults.Float_XYZs = new Dictionary<int, Array_Vector3>();
|
||||
arrayResults.Hashes = new Dictionary<int, Array_uint>();
|
||||
|
||||
Array.Clear(data, 0, infos.StructureSize);
|
||||
|
||||
MetaStructureEntryInfo_s arrEntry = new MetaStructureEntryInfo_s();
|
||||
|
||||
if (isRoot)
|
||||
{
|
||||
mb.EnsureBlock(type);
|
||||
}
|
||||
|
||||
for (int i = 0; i < infos.Entries.Length; i++)
|
||||
{
|
||||
var entry = infos.Entries[i];
|
||||
|
||||
var cnode = GetEntryNode(node.ChildNodes, entry);
|
||||
|
||||
if (entry.EntryNameHash == MetaName.ARRAYINFO)
|
||||
{
|
||||
arrEntry = entry;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cnode == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (entry.DataType)
|
||||
{
|
||||
case MetaStructureEntryDataType.Array:
|
||||
{
|
||||
TraverseArray(cnode, mb, arrEntry, entry.DataOffset, arrayResults);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.ArrayOfBytes:
|
||||
{
|
||||
GetParsedArrayOfBytes(cnode, data, entry, arrEntry);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.ArrayOfChars:
|
||||
{
|
||||
int offset = entry.DataOffset;
|
||||
var split = Split(cnode.InnerText, 2);
|
||||
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
byte val = Convert.ToByte(split[j], 16);
|
||||
data[offset] = val;
|
||||
offset += sizeof(byte);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.Boolean:
|
||||
{
|
||||
byte val = (cnode.Attributes["value"].Value == "false") ? (byte)0 : (byte)1;
|
||||
data[entry.DataOffset] = val;
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.ByteEnum:
|
||||
{
|
||||
byte val = Convert.ToByte(cnode.Attributes["value"].Value);
|
||||
data[entry.DataOffset] = val;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case MetaStructureEntryDataType.CharPointer:
|
||||
{
|
||||
if (!string.IsNullOrEmpty(cnode.InnerText))
|
||||
{
|
||||
var ptr = mb.AddStringPtr(cnode.InnerText);
|
||||
var val = MetaTypes.ConvertToBytes(ptr);
|
||||
|
||||
Buffer.BlockCopy(val, 0, data, entry.DataOffset, val.Length);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.DataBlockPointer:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.Float:
|
||||
{
|
||||
float val = FloatUtil.Parse(cnode.Attributes["value"].Value);
|
||||
Write(val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.Float_XYZ:
|
||||
{
|
||||
float x = FloatUtil.Parse(cnode.Attributes["x"].Value);
|
||||
float y = FloatUtil.Parse(cnode.Attributes["y"].Value);
|
||||
float z = FloatUtil.Parse(cnode.Attributes["z"].Value);
|
||||
|
||||
Write(x, data, entry.DataOffset);
|
||||
Write(y, data, entry.DataOffset + sizeof(float));
|
||||
Write(z, data, entry.DataOffset + sizeof(float) * 2);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case MetaStructureEntryDataType.Float_XYZW:
|
||||
{
|
||||
float x = FloatUtil.Parse(cnode.Attributes["x"].Value);
|
||||
float y = FloatUtil.Parse(cnode.Attributes["y"].Value);
|
||||
float z = FloatUtil.Parse(cnode.Attributes["z"].Value);
|
||||
float w = FloatUtil.Parse(cnode.Attributes["w"].Value);
|
||||
|
||||
Write(x, data, entry.DataOffset);
|
||||
Write(y, data, entry.DataOffset + sizeof(float));
|
||||
Write(z, data, entry.DataOffset + sizeof(float) * 2);
|
||||
Write(w, data, entry.DataOffset + sizeof(float) * 3);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.Hash:
|
||||
{
|
||||
var hash = GetHash(cnode.InnerText);
|
||||
Write(hash, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.IntEnum:
|
||||
case MetaStructureEntryDataType.IntFlags1:
|
||||
case MetaStructureEntryDataType.IntFlags2:
|
||||
{
|
||||
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
|
||||
|
||||
mb.AddEnumInfo(_infos.EnumNameHash);
|
||||
|
||||
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText);
|
||||
Write(val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.ShortFlags:
|
||||
{
|
||||
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
|
||||
|
||||
mb.AddEnumInfo(_infos.EnumNameHash);
|
||||
|
||||
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText);
|
||||
Write((short)val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.SignedByte:
|
||||
{
|
||||
var val = Convert.ToSByte(cnode.Attributes["value"].Value);
|
||||
data[entry.DataOffset] = (byte)val;
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.SignedInt:
|
||||
{
|
||||
var val = Convert.ToInt32(cnode.Attributes["value"].Value);
|
||||
Write(val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.SignedShort:
|
||||
{
|
||||
var val = Convert.ToInt16(cnode.Attributes["value"].Value);
|
||||
Write(val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.Structure:
|
||||
{
|
||||
var struc = Traverse(cnode, mb, entry.ReferenceKey);
|
||||
|
||||
if(struc != null)
|
||||
{
|
||||
Buffer.BlockCopy(struc, 0, data, entry.DataOffset, struc.Length);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.StructurePointer:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.UnsignedByte:
|
||||
{
|
||||
var val = Convert.ToByte(cnode.Attributes["value"].Value);
|
||||
data[entry.DataOffset] = val;
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.UnsignedInt:
|
||||
{
|
||||
switch (entry.EntryNameHash)
|
||||
{
|
||||
case MetaName.color:
|
||||
{
|
||||
var val = Convert.ToUInt32(cnode.Attributes["value"].Value, 16);
|
||||
Write(val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
var val = Convert.ToUInt32(cnode.Attributes["value"].Value);
|
||||
Write(val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.UnsignedShort:
|
||||
{
|
||||
var val = Convert.ToUInt16(cnode.Attributes["value"].Value);
|
||||
Write(val, data, entry.DataOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
arrayResults.WriteArrays(data);
|
||||
|
||||
mb.AddStructureInfo(infos.StructureNameHash);
|
||||
|
||||
if (isRoot)
|
||||
{
|
||||
mb.AddItem(type, data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void GetParsedArrayOfBytes(XmlNode node, byte[] data, MetaStructureEntryInfo_s entry, MetaStructureEntryInfo_s arrEntry)
|
||||
{
|
||||
int offset = entry.DataOffset;
|
||||
string[] split;
|
||||
|
||||
switch (arrEntry.DataType)
|
||||
{
|
||||
default:
|
||||
split = Split(node.InnerText, 2);
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
byte val = Convert.ToByte(split[j], 16);
|
||||
data[offset] = val;
|
||||
offset += sizeof(byte);
|
||||
}
|
||||
break;
|
||||
case MetaStructureEntryDataType.SignedByte:
|
||||
split = node.InnerText.Split(); //split = Split(node.InnerText, 2); to read as unsplitted HEX
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
sbyte val = Convert.ToSByte(split[j], 10);
|
||||
data[offset] = (byte)val;
|
||||
offset += sizeof(sbyte);
|
||||
}
|
||||
break;
|
||||
case MetaStructureEntryDataType.UnsignedByte:
|
||||
split = node.InnerText.Split();
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
byte val = Convert.ToByte(split[j], 10);
|
||||
data[offset] = val;
|
||||
offset += sizeof(byte);
|
||||
}
|
||||
break;
|
||||
case MetaStructureEntryDataType.SignedShort:
|
||||
split = node.InnerText.Split();
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
short val = Convert.ToInt16(split[j], 10);
|
||||
Write(val, data, offset);
|
||||
offset += sizeof(short);
|
||||
}
|
||||
break;
|
||||
case MetaStructureEntryDataType.UnsignedShort:
|
||||
split = node.InnerText.Split();
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
ushort val = Convert.ToUInt16(split[j], 10);
|
||||
Write(val, data, offset);
|
||||
offset += sizeof(ushort);
|
||||
}
|
||||
break;
|
||||
case MetaStructureEntryDataType.SignedInt:
|
||||
split = node.InnerText.Split();
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
int val = Convert.ToInt32(split[j], 10);
|
||||
Write(val, data, offset);
|
||||
offset += sizeof(int);
|
||||
}
|
||||
break;
|
||||
case MetaStructureEntryDataType.UnsignedInt:
|
||||
split = node.InnerText.Split();
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
uint val = Convert.ToUInt32(split[j], 10);
|
||||
Write(val, data, offset);
|
||||
offset += sizeof(uint);
|
||||
}
|
||||
break;
|
||||
case MetaStructureEntryDataType.Float:
|
||||
split = node.InnerText.Split();
|
||||
for (int j = 0; j < split.Length; j++)
|
||||
{
|
||||
float val = FloatUtil.Parse(split[j]);
|
||||
Write(val, data, offset);
|
||||
offset += sizeof(float);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseArray(XmlNode node, MetaBuilder mb, MetaStructureEntryInfo_s arrEntry, int offset, ArrayResults results)
|
||||
{
|
||||
switch (arrEntry.DataType)
|
||||
{
|
||||
case MetaStructureEntryDataType.Structure:
|
||||
{
|
||||
results.Structures[offset] = TraverseArrayStructure(node, mb, arrEntry.ReferenceKey);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.StructurePointer:
|
||||
{
|
||||
results.StructurePointers[offset] = TraverseArrayStructurePointer(node, mb);
|
||||
break;
|
||||
}
|
||||
|
||||
case MetaStructureEntryDataType.UnsignedInt:
|
||||
{
|
||||
results.UInts[offset] = TraverseRawUIntArray(node, mb);
|
||||
break;
|
||||
}
|
||||
case MetaStructureEntryDataType.UnsignedShort:
|
||||
{
|
||||
results.UShorts[offset] = TraverseRawUShortArray(node, mb);
|
||||
break;
|
||||
}
|
||||
case MetaStructureEntryDataType.UnsignedByte:
|
||||
{
|
||||
results.UBytes[offset] = TraverseRawUByteArray(node, mb);
|
||||
break;
|
||||
}
|
||||
case MetaStructureEntryDataType.Float:
|
||||
{
|
||||
results.Floats[offset] = TraverseRawFloatArray(node, mb);
|
||||
break;
|
||||
}
|
||||
case MetaStructureEntryDataType.Float_XYZ:
|
||||
{
|
||||
results.Float_XYZs[offset] = TraverseRawVector3Array(node, mb);
|
||||
break;
|
||||
}
|
||||
case MetaStructureEntryDataType.Hash:
|
||||
{
|
||||
results.Hashes[offset] = TraverseHashArray(node, mb);
|
||||
break;
|
||||
}
|
||||
case MetaStructureEntryDataType.CharPointer:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
case MetaStructureEntryDataType.DataBlockPointer:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Array_Structure TraverseArrayStructure(XmlNode node, MetaBuilder mb, MetaName type)
|
||||
{
|
||||
var strucs = new List<byte[]>();
|
||||
|
||||
foreach (XmlNode cnode in node.ChildNodes)
|
||||
{
|
||||
var struc = Traverse(cnode, mb, type);
|
||||
|
||||
if (struc != null)
|
||||
{
|
||||
strucs.Add(struc);
|
||||
}
|
||||
}
|
||||
|
||||
return mb.AddItemArrayPtr(type, strucs.ToArray());
|
||||
}
|
||||
|
||||
private static Array_StructurePointer TraverseArrayStructurePointer(XmlNode node, MetaBuilder mb)
|
||||
{
|
||||
var ptrs = new List<MetaPOINTER>();
|
||||
|
||||
foreach (XmlNode cnode in node.ChildNodes)
|
||||
{
|
||||
var type = (MetaName)(uint)GetHash(cnode.Attributes["type"].Value);
|
||||
var struc = Traverse(cnode, mb, type);
|
||||
|
||||
if(struc != null)
|
||||
{
|
||||
var ptr = mb.AddItemPtr(type, struc);
|
||||
ptrs.Add(ptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mb.AddPointerArray(ptrs.ToArray());
|
||||
|
||||
}
|
||||
|
||||
private static Array_uint TraverseRawUIntArray(XmlNode node, MetaBuilder mb)
|
||||
{
|
||||
var data = new List<uint>();
|
||||
|
||||
if (node.InnerText != "")
|
||||
{
|
||||
var split = Regex.Split(node.InnerText, @"[\s\r\n\t]");
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(split[i]))
|
||||
{
|
||||
var val = Convert.ToUInt32(split[i]);
|
||||
data.Add(val);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return mb.AddUintArrayPtr(data.ToArray());
|
||||
}
|
||||
|
||||
private static Array_ushort TraverseRawUShortArray(XmlNode node, MetaBuilder mb)
|
||||
{
|
||||
var data = new List<ushort>();
|
||||
|
||||
if (node.InnerText != "")
|
||||
{
|
||||
var split = Regex.Split(node.InnerText, @"[\s\r\n\t]");
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(split[i]))
|
||||
{
|
||||
var val = Convert.ToUInt16(split[i]);
|
||||
data.Add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mb.AddUshortArrayPtr(data.ToArray());
|
||||
}
|
||||
|
||||
private static Array_byte TraverseRawUByteArray(XmlNode node, MetaBuilder mb)
|
||||
{
|
||||
var data = new List<byte>();
|
||||
|
||||
if (node.InnerText != "")
|
||||
{
|
||||
var split = Regex.Split(node.InnerText, @"[\s\r\n\t]");
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(split[i]))
|
||||
{
|
||||
var val = Convert.ToByte(split[i]);
|
||||
data.Add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mb.AddByteArrayPtr(data.ToArray());
|
||||
}
|
||||
|
||||
private static Array_float TraverseRawFloatArray(XmlNode node, MetaBuilder mb)
|
||||
{
|
||||
var data = new List<float>();
|
||||
|
||||
if(node.InnerText != "")
|
||||
{
|
||||
var split = Regex.Split(node.InnerText, @"[\s\r\n\t]");
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
var ts = split[i]?.Trim();
|
||||
if (!string.IsNullOrEmpty(ts))
|
||||
{
|
||||
var val = FloatUtil.Parse(ts);// Convert.ToSingle(split[i]);
|
||||
data.Add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mb.AddFloatArrayPtr(data.ToArray());
|
||||
}
|
||||
|
||||
private static Array_Vector3 TraverseRawVector3Array(XmlNode node, MetaBuilder mb)
|
||||
{
|
||||
var items = new List<Vector4>();
|
||||
|
||||
|
||||
var split = node.InnerText.Split('\n');// Regex.Split(node.InnerText, @"[\s\r\n\t]");
|
||||
|
||||
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float z = 0f;
|
||||
float w = 0f;
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
var s = split[i]?.Trim();
|
||||
if (string.IsNullOrEmpty(s)) continue;
|
||||
var split2 = Regex.Split(s, @"[\s\t]");
|
||||
int c = 0;
|
||||
x = 0f; y = 0f; z = 0f;
|
||||
for (int n = 0; n < split2.Length; n++)
|
||||
{
|
||||
var ts = split2[n]?.Trim();
|
||||
if (string.IsNullOrEmpty(ts)) continue;
|
||||
var f = FloatUtil.Parse(ts);
|
||||
switch (c)
|
||||
{
|
||||
case 0: x = f; break;
|
||||
case 1: y = f; break;
|
||||
case 2: z = f; break;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
if (c >= 3)
|
||||
{
|
||||
var val = new Vector4(x, y, z, w);
|
||||
items.Add(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return mb.AddPaddedVector3ArrayPtr(items.ToArray());
|
||||
}
|
||||
|
||||
private static Array_uint TraverseHashArray(XmlNode node, MetaBuilder mb)
|
||||
{
|
||||
var items = new List<MetaHash>();
|
||||
|
||||
foreach (XmlNode cnode in node.ChildNodes)
|
||||
{
|
||||
var val = GetHash(cnode.InnerText);
|
||||
items.Add(val);
|
||||
}
|
||||
|
||||
return mb.AddHashArrayPtr(items.ToArray());
|
||||
}
|
||||
|
||||
private static void Write(int val, byte[] data, int offset)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(val);
|
||||
Buffer.BlockCopy(bytes, 0, data, offset, sizeof(int));
|
||||
}
|
||||
|
||||
private static void Write(uint val, byte[] data, int offset)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(val);
|
||||
Buffer.BlockCopy(bytes, 0, data, offset, sizeof(uint));
|
||||
}
|
||||
|
||||
private static void Write(short val, byte[] data, int offset)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(val);
|
||||
Buffer.BlockCopy(bytes, 0, data, offset, sizeof(short));
|
||||
}
|
||||
|
||||
private static void Write(ushort val, byte[] data, int offset)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(val);
|
||||
Buffer.BlockCopy(bytes, 0, data, offset, sizeof(ushort));
|
||||
}
|
||||
|
||||
private static void Write(float val, byte[] data, int offset)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(val);
|
||||
Buffer.BlockCopy(bytes, 0, data, offset, sizeof(float));
|
||||
}
|
||||
|
||||
private static MetaHash GetHash(string str)
|
||||
{
|
||||
if (str.StartsWith("hash_"))
|
||||
{
|
||||
return (MetaHash) Convert.ToUInt32(str.Substring(5), 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
return JenkHash.GenHash(str);
|
||||
}
|
||||
}
|
||||
|
||||
private static XmlNode GetEntryNode(XmlNodeList nodes, MetaStructureEntryInfo_s entry)
|
||||
{
|
||||
foreach (XmlNode node in nodes)
|
||||
{
|
||||
if (GetHash(node.Name) == (uint)entry.EntryNameHash)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string[] Split(string str, int maxChunkSize)
|
||||
{
|
||||
var chunks = new List<String>();
|
||||
|
||||
for (int i = 0; i < str.Length; i += maxChunkSize)
|
||||
{
|
||||
chunks.Add(str.Substring(i, Math.Min(maxChunkSize, str.Length - i)));
|
||||
}
|
||||
|
||||
return chunks.ToArray();
|
||||
}
|
||||
|
||||
private static int GetEnumInt(MetaName type, string enumString)
|
||||
{
|
||||
var enumName = (MetaName)(uint)GetHash(enumString);
|
||||
var infos = MetaTypes.GetEnumInfo(type);
|
||||
|
||||
if (infos == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int j = 0; j < infos.Entries.Length; j++)
|
||||
{
|
||||
var entry = infos.Entries[j];
|
||||
|
||||
if (entry.EntryNameHash == enumName)
|
||||
{
|
||||
return entry.EntryValue;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct ArrayResults
|
||||
{
|
||||
public Dictionary<int, Array_Structure> Structures;
|
||||
public Dictionary<int, Array_StructurePointer> StructurePointers;
|
||||
public Dictionary<int, Array_uint> UInts;
|
||||
public Dictionary<int, Array_ushort> UShorts;
|
||||
public Dictionary<int, Array_byte> UBytes;
|
||||
public Dictionary<int, Array_float> Floats;
|
||||
public Dictionary<int, Array_Vector3> Float_XYZs;
|
||||
public Dictionary<int, Array_uint> Hashes;
|
||||
|
||||
public void WriteArrays(byte[] data)
|
||||
{
|
||||
foreach (KeyValuePair<int, Array_Structure> ptr in Structures)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, Array_StructurePointer> ptr in StructurePointers)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, Array_uint> ptr in UInts)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, Array_ushort> ptr in UShorts)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, Array_byte> ptr in UBytes)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, Array_float> ptr in Floats)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, Array_Vector3> ptr in Float_XYZs)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, Array_uint> ptr in Hashes)
|
||||
{
|
||||
var _data = MetaTypes.ConvertToBytes(ptr.Value);
|
||||
Buffer.BlockCopy(_data, 0, data, ptr.Key, _data.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1435
CodeWalker.Core/GameFiles/Resources/Bounds.cs
Normal file
1435
CodeWalker.Core/GameFiles/Resources/Bounds.cs
Normal file
File diff suppressed because it is too large
Load Diff
1673
CodeWalker.Core/GameFiles/Resources/Clip.cs
Normal file
1673
CodeWalker.Core/GameFiles/Resources/Clip.cs
Normal file
File diff suppressed because it is too large
Load Diff
2672
CodeWalker.Core/GameFiles/Resources/Drawable.cs
Normal file
2672
CodeWalker.Core/GameFiles/Resources/Drawable.cs
Normal file
File diff suppressed because it is too large
Load Diff
3759
CodeWalker.Core/GameFiles/Resources/Frag.cs
Normal file
3759
CodeWalker.Core/GameFiles/Resources/Frag.cs
Normal file
File diff suppressed because it is too large
Load Diff
907
CodeWalker.Core/GameFiles/Resources/Nav.cs
Normal file
907
CodeWalker.Core/GameFiles/Resources/Nav.cs
Normal file
@ -0,0 +1,907 @@
|
||||
/*
|
||||
Copyright(c) 2016 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//now with enhanced uglification for codewalker
|
||||
|
||||
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class NavMesh : ResourceFileBase
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 368; }
|
||||
}
|
||||
|
||||
|
||||
public NavMeshFlags ContentFlags { get; set; }
|
||||
public uint VersionUnk1 { get; set; } // 0x00010011
|
||||
public uint Unused_018h { get; set; } // 0x00000000
|
||||
public uint Unused_01Ch { get; set; } // 0x00000000
|
||||
public Matrix Transform { get; set; } //(1,0,0,NaN),(0,1,0,NaN),(0,0,1,NaN),(0,0,0,NaN)
|
||||
public Vector3 AABBSize { get; set; }
|
||||
public float AABBUnk { get; set; } // 0x7F800001 //NaN
|
||||
public ulong VerticesPointer { get; set; }
|
||||
public uint Unused_078h { get; set; } // 0x00000000
|
||||
public uint Unused_07Ch { get; set; } // 0x00000000
|
||||
public ulong IndicesPointer { get; set; }
|
||||
public ulong AdjPolysPointer { get; set; }
|
||||
public uint AdjPolysIndicesCount { get; set; }
|
||||
public NavMeshUintArray AdjAreaIDs { get; set; }
|
||||
public ulong PolysPointer { get; set; }
|
||||
public ulong SectorTreePointer { get; set; }
|
||||
public ulong PortalsPointer { get; set; }
|
||||
public ulong PortalLinksPointer { get; set; }
|
||||
public uint VerticesCount { get; set; }
|
||||
public uint PolysCount { get; set; }
|
||||
public uint AreaID { get; set; } // X + Y*100
|
||||
public uint TotalBytes { get; set; }
|
||||
public uint SectorUnkCount { get; set; }
|
||||
public uint PortalsCount { get; set; }
|
||||
public uint PortalLinksCount { get; set; }
|
||||
public uint Unused_154h { get; set; } // 0x00000000
|
||||
public uint Unused_158h { get; set; } // 0x00000000
|
||||
public uint Unused_15Ch { get; set; } // 0x00000000
|
||||
public uint VersionUnk2 { get; set; } //2244687201 (0x85CB3561) for grid ynv's
|
||||
public uint Unused_164h { get; set; } // 0x00000000
|
||||
public uint Unused_168h { get; set; } // 0x00000000
|
||||
public uint Unused_16Ch { get; set; } // 0x00000000
|
||||
|
||||
|
||||
public NavMeshList<NavMeshVertex> Vertices { get; set; }
|
||||
public NavMeshList<ushort> Indices { get; set; }
|
||||
public NavMeshList<NavMeshAdjPoly> AdjPolys { get; set; }
|
||||
public NavMeshList<NavMeshPoly> Polys { get; set; }
|
||||
public NavMeshSector SectorTree { get; set; }
|
||||
public NavMeshPortal[] Portals { get; set; }
|
||||
public ushort[] PortalLinks { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
private ResourceSystemStructBlock<NavMeshPortal> PortalsBlock = null;
|
||||
private ResourceSystemStructBlock<ushort> PortalLinksBlock = null;
|
||||
|
||||
|
||||
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
base.Read(reader, parameters);
|
||||
|
||||
ContentFlags = (NavMeshFlags)reader.ReadUInt32();
|
||||
VersionUnk1 = reader.ReadUInt32();
|
||||
Unused_018h = reader.ReadUInt32();
|
||||
Unused_01Ch = reader.ReadUInt32();
|
||||
Transform = reader.ReadMatrix();
|
||||
AABBSize = reader.ReadVector3();
|
||||
AABBUnk = reader.ReadSingle();
|
||||
VerticesPointer = reader.ReadUInt64();
|
||||
Unused_078h = reader.ReadUInt32();
|
||||
Unused_07Ch = reader.ReadUInt32();
|
||||
IndicesPointer = reader.ReadUInt64();
|
||||
AdjPolysPointer = reader.ReadUInt64();
|
||||
AdjPolysIndicesCount = reader.ReadUInt32();
|
||||
AdjAreaIDs = reader.ReadStruct<NavMeshUintArray>();
|
||||
PolysPointer = reader.ReadUInt64();
|
||||
SectorTreePointer = reader.ReadUInt64();
|
||||
PortalsPointer = reader.ReadUInt64();
|
||||
PortalLinksPointer = reader.ReadUInt64();
|
||||
VerticesCount = reader.ReadUInt32();
|
||||
PolysCount = reader.ReadUInt32();
|
||||
AreaID = reader.ReadUInt32();
|
||||
TotalBytes = reader.ReadUInt32();
|
||||
SectorUnkCount = reader.ReadUInt32();
|
||||
PortalsCount = reader.ReadUInt32();
|
||||
PortalLinksCount = reader.ReadUInt32();
|
||||
Unused_154h = reader.ReadUInt32();
|
||||
Unused_158h = reader.ReadUInt32();
|
||||
Unused_15Ch = reader.ReadUInt32();
|
||||
VersionUnk2 = reader.ReadUInt32();
|
||||
Unused_164h = reader.ReadUInt32();
|
||||
Unused_168h = reader.ReadUInt32();
|
||||
Unused_16Ch = reader.ReadUInt32();
|
||||
|
||||
|
||||
|
||||
Vertices = reader.ReadBlockAt<NavMeshList<NavMeshVertex>>(VerticesPointer);
|
||||
Indices = reader.ReadBlockAt<NavMeshList<ushort>>(IndicesPointer);
|
||||
AdjPolys = reader.ReadBlockAt<NavMeshList<NavMeshAdjPoly>>(AdjPolysPointer);
|
||||
Polys = reader.ReadBlockAt<NavMeshList<NavMeshPoly>>(PolysPointer);
|
||||
SectorTree = reader.ReadBlockAt<NavMeshSector>(SectorTreePointer);
|
||||
Portals = reader.ReadStructsAt<NavMeshPortal>(PortalsPointer, PortalsCount);
|
||||
PortalLinks = reader.ReadUshortsAt(PortalLinksPointer, PortalLinksCount);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
base.Write(writer, parameters);
|
||||
|
||||
VerticesPointer = (ulong)(Vertices != null ? Vertices.FilePosition : 0);
|
||||
IndicesPointer = (ulong)(Indices != null ? Indices.FilePosition : 0);
|
||||
AdjPolysPointer = (ulong)(AdjPolys != null ? AdjPolys.FilePosition : 0);
|
||||
PolysPointer = (ulong)(Polys != null ? Polys.FilePosition : 0);
|
||||
SectorTreePointer = (ulong)(SectorTree != null ? SectorTree.FilePosition : 0);
|
||||
PortalsPointer = (ulong)(PortalsBlock?.FilePosition ?? 0);
|
||||
PortalLinksPointer = (ulong)(PortalLinksBlock?.FilePosition ?? 0);
|
||||
|
||||
|
||||
|
||||
writer.Write((uint)ContentFlags);
|
||||
writer.Write(VersionUnk1);
|
||||
writer.Write(Unused_018h);
|
||||
writer.Write(Unused_01Ch);
|
||||
writer.Write(Transform);
|
||||
writer.Write(AABBSize);
|
||||
writer.Write(AABBUnk);
|
||||
writer.Write(VerticesPointer);
|
||||
writer.Write(Unused_078h);
|
||||
writer.Write(Unused_07Ch);
|
||||
writer.Write(IndicesPointer);
|
||||
writer.Write(AdjPolysPointer);
|
||||
writer.Write(AdjPolysIndicesCount);
|
||||
writer.WriteStruct(AdjAreaIDs);
|
||||
writer.Write(PolysPointer);
|
||||
writer.Write(SectorTreePointer);
|
||||
writer.Write(PortalsPointer);
|
||||
writer.Write(PortalLinksPointer);
|
||||
writer.Write(VerticesCount);
|
||||
writer.Write(PolysCount);
|
||||
writer.Write(AreaID);
|
||||
writer.Write(TotalBytes);
|
||||
writer.Write(SectorUnkCount);
|
||||
writer.Write(PortalsCount);
|
||||
writer.Write(PortalLinksCount);
|
||||
writer.Write(Unused_154h);
|
||||
writer.Write(Unused_158h);
|
||||
writer.Write(Unused_15Ch);
|
||||
writer.Write(VersionUnk2);
|
||||
writer.Write(Unused_164h);
|
||||
writer.Write(Unused_168h);
|
||||
writer.Write(Unused_16Ch);
|
||||
}
|
||||
|
||||
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>(base.GetReferences());
|
||||
if (Vertices != null) list.Add(Vertices);
|
||||
if (Indices != null) list.Add(Indices);
|
||||
if (AdjPolys != null) list.Add(AdjPolys);
|
||||
if (Polys != null) list.Add(Polys);
|
||||
if (SectorTree != null) list.Add(SectorTree);
|
||||
|
||||
if ((Portals != null) && (Portals.Length > 0))
|
||||
{
|
||||
PortalsBlock = new ResourceSystemStructBlock<NavMeshPortal>(Portals);
|
||||
list.Add(PortalsBlock);
|
||||
}
|
||||
|
||||
if ((PortalLinks != null) && (PortalLinks.Length > 0))
|
||||
{
|
||||
PortalLinksBlock = new ResourceSystemStructBlock<ushort>(PortalLinks);
|
||||
list.Add(PortalLinksBlock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "(Size: " + FloatUtil.GetVector3String(AABBSize) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshUintArray
|
||||
{
|
||||
public uint Count { get; set; }
|
||||
public uint v00;
|
||||
public uint v01;
|
||||
public uint v02;
|
||||
public uint v03;
|
||||
public uint v04;
|
||||
public uint v05;
|
||||
public uint v06; // 0x00000000
|
||||
public uint v07; // 0x00000000
|
||||
public uint v08; // 0x00000000
|
||||
public uint v09; // 0x00000000
|
||||
public uint v10; // 0x00000000
|
||||
public uint v11; // 0x00000000
|
||||
public uint v12; // 0x00000000
|
||||
public uint v13; // 0x00000000
|
||||
public uint v14; // 0x00000000
|
||||
public uint v15; // 0x00000000
|
||||
public uint v16; // 0x00000000
|
||||
public uint v17; // 0x00000000
|
||||
public uint v18; // 0x00000000
|
||||
public uint v19; // 0x00000000
|
||||
public uint v20; // 0x00000000
|
||||
public uint v21; // 0x00000000
|
||||
public uint v22; // 0x00000000
|
||||
public uint v23; // 0x00000000
|
||||
public uint v24; // 0x00000000
|
||||
public uint v25; // 0x00000000
|
||||
public uint v26; // 0x00000000
|
||||
public uint v27; // 0x00000000
|
||||
public uint v28; // 0x00000000
|
||||
public uint v29; // 0x00000000
|
||||
public uint v30; // 0x00000000
|
||||
public uint v31; // 0x00000000
|
||||
|
||||
public uint[] RawValues
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[]{ v00,v01,v02,v03,v04,v05,v06,v07,v08,v09,
|
||||
v10,v11,v12,v13,v14,v15,v16,v17,v18,v19,
|
||||
v20,v21,v22,v23,v24,v25,v26,v27,v28,v29,
|
||||
v30,v31 };
|
||||
}
|
||||
}
|
||||
|
||||
public uint[] Values
|
||||
{
|
||||
get
|
||||
{
|
||||
uint[] vals = new uint[Count];
|
||||
uint[] rvals = RawValues;
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
vals[i] = rvals[i];
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
set
|
||||
{
|
||||
Count = (uint)value.Length;
|
||||
v00 = (Count > 0) ? value[0] : 0;
|
||||
v01 = (Count > 1) ? value[1] : 0;
|
||||
v02 = (Count > 2) ? value[2] : 0;
|
||||
v03 = (Count > 3) ? value[3] : 0;
|
||||
v04 = (Count > 4) ? value[4] : 0;
|
||||
v05 = (Count > 5) ? value[5] : 0;
|
||||
v06 = (Count > 6) ? value[6] : 0;
|
||||
v07 = (Count > 7) ? value[7] : 0;
|
||||
v08 = (Count > 8) ? value[8] : 0;
|
||||
v09 = (Count > 9) ? value[9] : 0;
|
||||
v10 = (Count > 10) ? value[10] : 0;
|
||||
v11 = (Count > 11) ? value[11] : 0;
|
||||
v12 = (Count > 12) ? value[12] : 0;
|
||||
v13 = (Count > 13) ? value[13] : 0;
|
||||
v14 = (Count > 14) ? value[14] : 0;
|
||||
v15 = (Count > 15) ? value[15] : 0;
|
||||
v16 = (Count > 16) ? value[16] : 0;
|
||||
v17 = (Count > 17) ? value[17] : 0;
|
||||
v18 = (Count > 18) ? value[18] : 0;
|
||||
v19 = (Count > 19) ? value[19] : 0;
|
||||
v20 = (Count > 20) ? value[20] : 0;
|
||||
v21 = (Count > 21) ? value[21] : 0;
|
||||
v22 = (Count > 22) ? value[22] : 0;
|
||||
v23 = (Count > 23) ? value[23] : 0;
|
||||
v24 = (Count > 24) ? value[24] : 0;
|
||||
v25 = (Count > 25) ? value[25] : 0;
|
||||
v26 = (Count > 26) ? value[26] : 0;
|
||||
v27 = (Count > 27) ? value[27] : 0;
|
||||
v28 = (Count > 28) ? value[28] : 0;
|
||||
v29 = (Count > 29) ? value[29] : 0;
|
||||
v30 = (Count > 30) ? value[30] : 0;
|
||||
v31 = (Count > 31) ? value[31] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "(Count: " + Count.ToString() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshList<T> : ResourceSystemBlock where T : struct
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 48; }
|
||||
}
|
||||
|
||||
public uint VFT { get; set; }
|
||||
public uint Unknown_04h { get; set; } // 0x00000001
|
||||
public uint ItemCount { get; set; }
|
||||
public uint Unknown_0Ch { get; set; } // 0x00000000
|
||||
public ulong ListPartsPointer { get; set; }
|
||||
public ulong ListOffsetsPointer { get; set; }
|
||||
public uint ListPartsCount { get; set; }
|
||||
public uint Unknown_24h { get; set; } // 0x00000000
|
||||
public uint Unknown_28h { get; set; } // 0x00000000
|
||||
public uint Unknown_2Ch { get; set; } // 0x00000000
|
||||
|
||||
public ResourceSimpleArray<NavMeshListPart<T>> ListParts { get; set; }
|
||||
public uint[] ListOffsets { get; set; }
|
||||
|
||||
private ResourceSystemStructBlock<uint> ListOffsetsBlock = null;
|
||||
public int ItemSize { get { return System.Runtime.InteropServices.Marshal.SizeOf<T>(); } }
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
VFT = reader.ReadUInt32();
|
||||
Unknown_04h = reader.ReadUInt32();
|
||||
ItemCount = reader.ReadUInt32();
|
||||
Unknown_0Ch = reader.ReadUInt32();
|
||||
ListPartsPointer = reader.ReadUInt64();
|
||||
ListOffsetsPointer = reader.ReadUInt64();
|
||||
ListPartsCount = reader.ReadUInt32();
|
||||
Unknown_24h = reader.ReadUInt32();
|
||||
Unknown_28h = reader.ReadUInt32();
|
||||
Unknown_2Ch = reader.ReadUInt32();
|
||||
|
||||
ListParts = reader.ReadBlockAt<ResourceSimpleArray<NavMeshListPart<T>>>(ListPartsPointer, ListPartsCount);
|
||||
ListOffsets = reader.ReadUintsAt(ListOffsetsPointer, ListPartsCount);
|
||||
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
ListPartsPointer = (ulong)(ListParts != null ? ListParts.FilePosition : 0);
|
||||
ListOffsetsPointer = (ulong)(ListOffsetsBlock?.FilePosition ?? 0);
|
||||
ListPartsCount = (uint)(ListParts != null ? ListParts.Count : 0);
|
||||
|
||||
writer.Write(VFT);
|
||||
writer.Write(Unknown_04h);
|
||||
writer.Write(ItemCount);
|
||||
writer.Write(Unknown_0Ch);
|
||||
writer.Write(ListPartsPointer);
|
||||
writer.Write(ListOffsetsPointer);
|
||||
writer.Write(ListPartsCount);
|
||||
writer.Write(Unknown_24h);
|
||||
writer.Write(Unknown_28h);
|
||||
writer.Write(Unknown_2Ch);
|
||||
}
|
||||
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>();
|
||||
if (ListParts != null) list.Add(ListParts);
|
||||
|
||||
if ((ListOffsets != null) && (ListOffsets.Length > 0))
|
||||
{
|
||||
ListOffsetsBlock = new ResourceSystemStructBlock<uint>(ListOffsets);
|
||||
list.Add(ListOffsetsBlock);
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<T> GetFullList()
|
||||
{
|
||||
List<T> list = new List<T>((int)ItemCount);
|
||||
|
||||
if (ListParts != null)
|
||||
{
|
||||
foreach (var part in ListParts)
|
||||
{
|
||||
if (part.Items != null)
|
||||
{
|
||||
list.AddRange(part.Items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public void RebuildList(List<T> items)
|
||||
{
|
||||
|
||||
//max bytes per part: 16384
|
||||
int maxpartbytes = 16384; //0x4000
|
||||
int itembytes = ItemSize;
|
||||
int itemsperpart = maxpartbytes / itembytes;
|
||||
int currentitem = 0;
|
||||
|
||||
var parts = new ResourceSimpleArray<NavMeshListPart<T>>();
|
||||
var partitems = new List<T>();
|
||||
var offsets = new List<uint>();
|
||||
|
||||
while (currentitem < items.Count)
|
||||
{
|
||||
partitems.Clear();
|
||||
int lastitem = currentitem + itemsperpart;
|
||||
if (lastitem > items.Count) lastitem = items.Count;
|
||||
for (int i = currentitem; i < lastitem; i++)
|
||||
{
|
||||
partitems.Add(items[i]);
|
||||
}
|
||||
var part = new NavMeshListPart<T>();
|
||||
part.Items = partitems.ToArray();
|
||||
part.Unknown_0Ch = 0;
|
||||
parts.Add(part);
|
||||
offsets.Add((uint)currentitem);
|
||||
currentitem = lastitem;
|
||||
}
|
||||
ListParts = parts;
|
||||
ListOffsets = offsets.ToArray();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "(" + ItemCount.ToString() + " total items, " + ListPartsCount.ToString() + " parts)";
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshListPart<T> : ResourceSystemBlock where T : struct
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 16; }
|
||||
}
|
||||
|
||||
public ulong Pointer { get; set; }
|
||||
public uint Count { get; set; }
|
||||
public uint Unknown_0Ch { get; set; } // 0x00000000
|
||||
|
||||
public T[] Items { get; set; }
|
||||
|
||||
private ResourceSystemStructBlock<T> ItemsBlock = null;
|
||||
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
Pointer = reader.ReadUInt64();
|
||||
Count = reader.ReadUInt32();
|
||||
Unknown_0Ch = reader.ReadUInt32();
|
||||
|
||||
Items = reader.ReadStructsAt<T>(Pointer, Count);
|
||||
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
Pointer = (ulong)(ItemsBlock?.FilePosition ?? 0);
|
||||
Count = (uint)(Items?.Length ?? 0);
|
||||
|
||||
writer.Write(Pointer);
|
||||
writer.Write(Count);
|
||||
writer.Write(Unknown_0Ch);
|
||||
}
|
||||
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>();
|
||||
|
||||
if ((Items != null) && (Items.Length > 0))
|
||||
{
|
||||
ItemsBlock = new ResourceSystemStructBlock<T>(Items);
|
||||
list.Add(ItemsBlock);
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "(" + Count.ToString() + " items)";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshVertex
|
||||
{
|
||||
public ushort X { get; set; }
|
||||
public ushort Y { get; set; }
|
||||
public ushort Z { get; set; }
|
||||
|
||||
|
||||
public Vector3 Position { get { return ToVector3(); } set { FromVector3(value); } }
|
||||
|
||||
public Vector3 ToVector3()
|
||||
{
|
||||
const float usmax = ushort.MaxValue;
|
||||
return new Vector3(X / usmax, Y / usmax, Z / usmax);
|
||||
}
|
||||
public void FromVector3(Vector3 v)
|
||||
{
|
||||
const float usmax = ushort.MaxValue;
|
||||
X = (ushort)(v.X * usmax);
|
||||
Y = (ushort)(v.Y * usmax);
|
||||
Z = (ushort)(v.Z * usmax);
|
||||
}
|
||||
|
||||
public static NavMeshVertex Create(Vector3 v)
|
||||
{
|
||||
var nmv = new NavMeshVertex();
|
||||
nmv.FromVector3(v);
|
||||
return nmv;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return X.ToString() + ", " + Y.ToString() + ", " + Z.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAABB
|
||||
{
|
||||
public short MinX { get; set; }
|
||||
public short MaxX { get; set; }
|
||||
public short MinY { get; set; }
|
||||
public short MaxY { get; set; }
|
||||
public short MinZ { get; set; }
|
||||
public short MaxZ { get; set; }
|
||||
|
||||
public Vector3 Min { get { return new Vector3(MinX / 4.0f, MinY / 4.0f, MinZ / 4.0f); } }
|
||||
public Vector3 Max { get { return new Vector3(MaxX / 4.0f, MaxY / 4.0f, MaxZ / 4.0f); } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
Vector3 min = Min;
|
||||
Vector3 max = Max;
|
||||
return string.Format("({0}, {1}, {2}) | ({3}, {4}, {5})", min.X, min.Y, min.Z, max.X, max.Y, max.Z);
|
||||
//return string.Format("({0}, {1}, {2}) | ({3}, {4}, {5})", MinX, MinY, MinZ, MaxX, MaxY, MaxZ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPoly
|
||||
{
|
||||
public NavMeshAdjPolyPart Unknown_0h { get; set; }
|
||||
public NavMeshAdjPolyPart Unknown_4h { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return //Unknown_0h.Bin + " | " + Unknown_4h.Bin + " | " +
|
||||
Unknown_0h.ToString() + " | " + Unknown_4h.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPolyPart
|
||||
{
|
||||
public uint Value { get; set; }
|
||||
|
||||
public string Bin
|
||||
{
|
||||
get
|
||||
{
|
||||
return Convert.ToString(Value, 2).PadLeft(32, '0');
|
||||
}
|
||||
}
|
||||
|
||||
public uint AreaIDInd { get { return (Value >> 0) & 0x1F; } }
|
||||
public uint PolyID { get { return (Value >> 5) & 0x3FFF; } }
|
||||
public uint Unk2 { get { return (Value >> 19) & 0x3; } }
|
||||
public uint Unk3 { get { return (Value >> 21) & 0x7FF; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return AreaIDInd.ToString() + ", " + PolyID.ToString() + ", " + Unk2.ToString() + ", " + Unk3.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPoly
|
||||
{
|
||||
public ushort Unknown_00h { get; set; }
|
||||
public ushort IndexFlags { get; set; }
|
||||
public ushort IndexID { get; set; }
|
||||
public ushort AreaID { get; set; }
|
||||
public uint Unused_08h { get; set; } // 0x00000000
|
||||
public uint Unused_0Ch { get; set; } // 0x00000000
|
||||
public uint Unused_10h { get; set; } // 0x00000000
|
||||
public uint Unused_14h { get; set; } // 0x00000000
|
||||
public NavMeshAABB CellAABB { get; set; }
|
||||
public FlagsUint Unknown_24h { get; set; }
|
||||
public FlagsUint Unknown_28h { get; set; }
|
||||
public ushort PartFlags { get; set; }
|
||||
public ushort PortalID { get; set; }
|
||||
|
||||
|
||||
//public int IndexUnk { get { return (IndexFlags >> 0) & 31; } } //always 0
|
||||
public int IndexCount { get { return (IndexFlags >> 5); } }
|
||||
|
||||
//public int PartUnk1 { get { return (PartFlags >> 0) & 0xF; } } //always 0
|
||||
public ushort PartID { get { return (ushort)((PartFlags >> 4) & 0xFF); } set { PartFlags = (ushort)((PartFlags & 0xF00F) | ((value & 0xFF) << 4)); } }
|
||||
public byte PortalUnk { get { return (byte)((PartFlags >> 12) & 0xF); } set { PartFlags = (ushort)((PartFlags & 0x0FFF) | ((value & 0xF) << 12)); } }
|
||||
|
||||
|
||||
public ushort Unknown_28h_16 { get { return (ushort)((Unknown_28h.Value & 0xFFFF)); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFF0000) | (value & 0xFFFFu); } }
|
||||
public byte Unknown_28h_8a { get { return (byte)((Unknown_28h.Value >> 0) & 0xFF); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFFFF00) | ((value & 0xFFu)<<0); } }
|
||||
public byte Unknown_28h_8b { get { return (byte)((Unknown_28h.Value >> 8) & 0xFF); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFF00FF) | ((value & 0xFFu)<<8); } }
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
//Unknown_28h.Bin + ", (" + Unknown_28h_8a.ToString() + ", " + Unknown_28h_8b.ToString() + "), " +
|
||||
Unknown_00h.ToString() + ", " +
|
||||
//IndexFlags.ToString() + ", " +
|
||||
IndexCount.ToString() + ", " + //IndexUnk.ToString() + ", " +
|
||||
IndexID.ToString() + ", " + AreaID.ToString() + ", " +
|
||||
CellAABB.ToString() + ", " +
|
||||
Unknown_24h.Hex + ", " +
|
||||
Unknown_28h.Hex + ", " +
|
||||
//PartFlags.ToString() + ", " + //PartUnk1.ToString() + ", " +
|
||||
PartID.ToString() + ", " +
|
||||
PortalUnk.ToString() + ", " +
|
||||
PortalID.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshSector : ResourceSystemBlock
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 96; }
|
||||
}
|
||||
|
||||
public Vector4 AABBMin { get; set; } //W==NaN
|
||||
public Vector4 AABBMax { get; set; } //W==NaN
|
||||
public NavMeshAABB CellAABB { get; set; }
|
||||
public ulong DataPointer { get; set; }
|
||||
public ulong SubTree1Pointer { get; set; }
|
||||
public ulong SubTree2Pointer { get; set; }
|
||||
public ulong SubTree3Pointer { get; set; }
|
||||
public ulong SubTree4Pointer { get; set; }
|
||||
public uint Unused_54h { get; set; } // 0x00000000
|
||||
public uint Unused_58h { get; set; } // 0x00000000
|
||||
public uint Unused_5Ch { get; set; } // 0x00000000
|
||||
|
||||
public NavMeshSectorData Data { get; set; }
|
||||
public NavMeshSector SubTree1 { get; set; }
|
||||
public NavMeshSector SubTree2 { get; set; }
|
||||
public NavMeshSector SubTree3 { get; set; }
|
||||
public NavMeshSector SubTree4 { get; set; }
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
AABBMin = reader.ReadVector4();
|
||||
AABBMax = reader.ReadVector4();
|
||||
CellAABB = reader.ReadStruct<NavMeshAABB>();
|
||||
DataPointer = reader.ReadUInt64();
|
||||
SubTree1Pointer = reader.ReadUInt64();
|
||||
SubTree2Pointer = reader.ReadUInt64();
|
||||
SubTree3Pointer = reader.ReadUInt64();
|
||||
SubTree4Pointer = reader.ReadUInt64();
|
||||
Unused_54h = reader.ReadUInt32();
|
||||
Unused_58h = reader.ReadUInt32();
|
||||
Unused_5Ch = reader.ReadUInt32();
|
||||
|
||||
Data = reader.ReadBlockAt<NavMeshSectorData>(DataPointer);
|
||||
SubTree1 = reader.ReadBlockAt<NavMeshSector>(SubTree1Pointer);
|
||||
SubTree2 = reader.ReadBlockAt<NavMeshSector>(SubTree2Pointer);
|
||||
SubTree3 = reader.ReadBlockAt<NavMeshSector>(SubTree3Pointer);
|
||||
SubTree4 = reader.ReadBlockAt<NavMeshSector>(SubTree4Pointer);
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
DataPointer = (ulong)(Data != null ? Data.FilePosition : 0);
|
||||
SubTree1Pointer = (ulong)(SubTree1 != null ? SubTree1.FilePosition : 0);
|
||||
SubTree2Pointer = (ulong)(SubTree2 != null ? SubTree2.FilePosition : 0);
|
||||
SubTree3Pointer = (ulong)(SubTree3 != null ? SubTree3.FilePosition : 0);
|
||||
SubTree4Pointer = (ulong)(SubTree4 != null ? SubTree4.FilePosition : 0);
|
||||
|
||||
writer.Write(AABBMin);
|
||||
writer.Write(AABBMax);
|
||||
writer.WriteStruct(CellAABB);
|
||||
writer.Write(DataPointer);
|
||||
writer.Write(SubTree1Pointer);
|
||||
writer.Write(SubTree2Pointer);
|
||||
writer.Write(SubTree3Pointer);
|
||||
writer.Write(SubTree4Pointer);
|
||||
writer.Write(Unused_54h);
|
||||
writer.Write(Unused_58h);
|
||||
writer.Write(Unused_5Ch);
|
||||
}
|
||||
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>();
|
||||
if (Data != null) list.Add(Data);
|
||||
if (SubTree1 != null) list.Add(SubTree1);
|
||||
if (SubTree2 != null) list.Add(SubTree2);
|
||||
if (SubTree3 != null) list.Add(SubTree3);
|
||||
if (SubTree4 != null) list.Add(SubTree4);
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "[Min: "+AABBMin.ToString() + "], [Max:" + AABBMax.ToString() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshSectorData : ResourceSystemBlock
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 32; }
|
||||
}
|
||||
|
||||
public uint UnkDataStartID { get; set; }
|
||||
public uint Unused_04h { get; set; } // 0x00000000
|
||||
public ulong PolyIDsPointer { get; set; }
|
||||
public ulong PointsPointer { get; set; }
|
||||
public ushort PolyIDsCount { get; set; }
|
||||
public ushort PointsCount { get; set; }
|
||||
public uint Unused_1Ch { get; set; } // 0x00000000
|
||||
|
||||
public ushort[] PolyIDs { get; set; }
|
||||
public NavMeshPoint[] Points { get; set; }
|
||||
|
||||
private ResourceSystemStructBlock<ushort> PolyIDsBlock = null;
|
||||
private ResourceSystemStructBlock<NavMeshPoint> PointsBlock = null;
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
UnkDataStartID = reader.ReadUInt32();
|
||||
Unused_04h = reader.ReadUInt32();
|
||||
PolyIDsPointer = reader.ReadUInt64();
|
||||
PointsPointer = reader.ReadUInt64();
|
||||
PolyIDsCount = reader.ReadUInt16();
|
||||
PointsCount = reader.ReadUInt16();
|
||||
Unused_1Ch = reader.ReadUInt32();
|
||||
|
||||
PolyIDs = reader.ReadUshortsAt(PolyIDsPointer, PolyIDsCount);
|
||||
Points = reader.ReadStructsAt<NavMeshPoint>(PointsPointer, PointsCount);
|
||||
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
PolyIDsPointer = (ulong)(PolyIDsBlock?.FilePosition ?? 0);
|
||||
PolyIDsCount = (ushort)(PolyIDs?.Length ?? 0);
|
||||
PointsPointer = (ulong)(PointsBlock?.FilePosition ?? 0);
|
||||
PointsCount = (ushort)(Points?.Length ?? 0);
|
||||
|
||||
|
||||
writer.Write(UnkDataStartID);
|
||||
writer.Write(Unused_04h);
|
||||
writer.Write(PolyIDsPointer);
|
||||
writer.Write(PointsPointer);
|
||||
writer.Write(PolyIDsCount);
|
||||
writer.Write(PointsCount);
|
||||
writer.Write(Unused_1Ch);
|
||||
}
|
||||
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>();
|
||||
|
||||
if ((PolyIDs != null) && (PolyIDs.Length > 0))
|
||||
{
|
||||
PolyIDsBlock = new ResourceSystemStructBlock<ushort>(PolyIDs);
|
||||
list.Add(PolyIDsBlock);
|
||||
}
|
||||
if ((Points != null) && (Points.Length > 0))
|
||||
{
|
||||
PointsBlock = new ResourceSystemStructBlock<NavMeshPoint>(Points);
|
||||
list.Add(PointsBlock);
|
||||
}
|
||||
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "(Polys: " + PolyIDsCount.ToString() + ", UnkOffset: " + UnkDataStartID.ToString() + ", UnkCount: " + PointsCount.ToString() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPoint
|
||||
{
|
||||
public ushort X { get; set; }
|
||||
public ushort Y { get; set; }
|
||||
public ushort Z { get; set; }
|
||||
public byte Angle { get; set; }
|
||||
public byte Flags { get; set; }
|
||||
|
||||
|
||||
public Vector3 Position { get { return ToVector3(); } }
|
||||
|
||||
public Vector3 ToVector3()
|
||||
{
|
||||
const float usmax = ushort.MaxValue;
|
||||
return new Vector3(X / usmax, Y / usmax, Z / usmax);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Flags.ToString() + ": " + Angle.ToString() + ", " + Position.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPortal
|
||||
{
|
||||
public uint TypeFlags { get; set; }
|
||||
public NavMeshVertex Position1 { get; set; }
|
||||
public NavMeshVertex Position2 { get; set; }
|
||||
public ushort PolyID1a { get; set; }
|
||||
public ushort PolyID1b { get; set; }
|
||||
public ushort PolyID2a { get; set; }
|
||||
public ushort PolyID2b { get; set; }
|
||||
public uint AreaFlags { get; set; }
|
||||
|
||||
public uint Type1 { get { return TypeFlags & 0xFF; } }
|
||||
public uint Type2 { get { return (TypeFlags >> 8) & 0xF; } }
|
||||
public uint Type3 { get { return (TypeFlags >> 12) & 0xF; } }
|
||||
public uint Type4 { get { return (TypeFlags >> 16) & 0xFFFF; } }
|
||||
|
||||
public ushort AreaID1 { get { return (ushort)(AreaFlags & 0x3FFF); } }
|
||||
public ushort AreaID2 { get { return (ushort)((AreaFlags >> 14) & 0x3FFF); } }
|
||||
public byte AreaUnk { get { return (byte)((AreaFlags >> 28) & 0xF); } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return AreaID1.ToString() + ", " + AreaID2.ToString() + ", " + AreaUnk.ToString() + ", " +
|
||||
PolyID1a.ToString() + ", " + PolyID1b.ToString() + ", " +
|
||||
PolyID2a.ToString() + ", " + PolyID2b.ToString() + ", " +
|
||||
Type1.ToString() + ", " + Type2.ToString() + ", " + Type3.ToString() + ", " + Type4.ToString() + ", " +
|
||||
"(" + Position1.ToString() + " | " + Position2.ToString() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[Flags] public enum NavMeshFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
Vertices = 1,
|
||||
Portals = 2,
|
||||
Vehicle = 4,
|
||||
Unknown8 = 8,
|
||||
}
|
||||
|
||||
|
||||
}
|
280
CodeWalker.Core/GameFiles/Resources/Node.cs
Normal file
280
CodeWalker.Core/GameFiles/Resources/Node.cs
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
Copyright(c) 2016 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//mangled to fit
|
||||
|
||||
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class NodeDictionary : ResourceFileBase
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 112; }
|
||||
}
|
||||
|
||||
public ulong NodesPointer { get; set; }
|
||||
public uint NodesCount { get; set; }
|
||||
public uint NodesCountVehicle { get; set; }
|
||||
public uint NodesCountPed { get; set; }
|
||||
public uint Unk24 { get; set; } // 0x00000000
|
||||
public ulong LinksPtr { get; set; }
|
||||
public uint LinksCount { get; set; }
|
||||
public uint Unk34 { get; set; } // 0x00000000
|
||||
public ulong JunctionsPtr { get; set; }
|
||||
public ulong JunctionHeightmapBytesPtr { get; set; }
|
||||
public uint Unk48 { get; set; } = 1; // 0x00000001
|
||||
public uint Unk4C { get; set; } // 0x00000000
|
||||
public ulong JunctionRefsPtr { get; set; }
|
||||
public ushort JunctionRefsCount0 { get; set; }
|
||||
public ushort JunctionRefsCount1 { get; set; } // same as JunctionRefsCount0
|
||||
public uint Unk5C { get; set; } // 0x00000000
|
||||
public uint JunctionsCount { get; set; } // same as JunctionRefsCount0
|
||||
public uint JunctionHeightmapBytesCount { get; set; }
|
||||
public uint Unk68 { get; set; } // 0x00000000
|
||||
public uint Unk6C { get; set; } // 0x00000000
|
||||
|
||||
public Node[] Nodes { get; set; }
|
||||
public NodeLink[] Links { get; set; }
|
||||
public NodeJunction[] Junctions { get; set; }
|
||||
public byte[] JunctionHeightmapBytes { get; set; }
|
||||
public NodeJunctionRef[] JunctionRefs { get; set; }
|
||||
|
||||
|
||||
private ResourceSystemStructBlock<Node> NodesBlock = null;
|
||||
private ResourceSystemStructBlock<NodeLink> LinksBlock = null;
|
||||
private ResourceSystemStructBlock<NodeJunction> JunctionsBlock = null;
|
||||
private ResourceSystemStructBlock<byte> JunctionHeightmapBytesBlock = null;
|
||||
private ResourceSystemStructBlock<NodeJunctionRef> JunctionRefsBlock = null;
|
||||
|
||||
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
base.Read(reader, parameters);
|
||||
|
||||
this.NodesPointer = reader.ReadUInt64();
|
||||
this.NodesCount = reader.ReadUInt32();
|
||||
this.NodesCountVehicle = reader.ReadUInt32();
|
||||
this.NodesCountPed = reader.ReadUInt32();
|
||||
this.Unk24 = reader.ReadUInt32();
|
||||
this.LinksPtr = reader.ReadUInt64();
|
||||
this.LinksCount = reader.ReadUInt32();
|
||||
this.Unk34 = reader.ReadUInt32();
|
||||
this.JunctionsPtr = reader.ReadUInt64();
|
||||
this.JunctionHeightmapBytesPtr = reader.ReadUInt64();
|
||||
this.Unk48 = reader.ReadUInt32();
|
||||
this.Unk4C = reader.ReadUInt32();
|
||||
this.JunctionRefsPtr = reader.ReadUInt64();
|
||||
this.JunctionRefsCount0 = reader.ReadUInt16();
|
||||
this.JunctionRefsCount1 = reader.ReadUInt16();
|
||||
this.Unk5C = reader.ReadUInt32();
|
||||
this.JunctionsCount = reader.ReadUInt32();
|
||||
this.JunctionHeightmapBytesCount = reader.ReadUInt32();
|
||||
this.Unk68 = reader.ReadUInt32();
|
||||
this.Unk6C = reader.ReadUInt32();
|
||||
|
||||
this.Nodes = reader.ReadStructsAt<Node>(this.NodesPointer, this.NodesCount);
|
||||
this.Links = reader.ReadStructsAt<NodeLink>(this.LinksPtr, this.LinksCount);
|
||||
this.Junctions = reader.ReadStructsAt<NodeJunction>(this.JunctionsPtr, this.JunctionsCount);
|
||||
this.JunctionHeightmapBytes = reader.ReadBytesAt(this.JunctionHeightmapBytesPtr, this.JunctionHeightmapBytesCount);
|
||||
this.JunctionRefs = reader.ReadStructsAt<NodeJunctionRef>(this.JunctionRefsPtr, this.JunctionRefsCount1);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
base.Write(writer, parameters);
|
||||
|
||||
// update structure data
|
||||
NodesPointer = (ulong)(NodesBlock?.FilePosition ?? 0);
|
||||
NodesCount = (uint)(Nodes?.Length ?? 0); //assume NodesCountVehicle and Ped already updated..
|
||||
LinksPtr = (ulong)(LinksBlock?.FilePosition ?? 0);
|
||||
LinksCount = (uint)(Links?.Length ?? 0);
|
||||
JunctionsPtr = (ulong)(JunctionsBlock?.FilePosition ?? 0);
|
||||
JunctionHeightmapBytesPtr = (ulong)(JunctionHeightmapBytesBlock?.FilePosition ?? 0);
|
||||
JunctionRefsPtr = (ulong)(JunctionRefsBlock?.FilePosition ?? 0);
|
||||
JunctionRefsCount0 = (ushort)(JunctionRefs?.Length ?? 0);
|
||||
JunctionRefsCount1 = JunctionRefsCount1;
|
||||
JunctionsCount = (uint)(Junctions?.Length ?? 0);
|
||||
JunctionHeightmapBytesCount = (uint)(JunctionHeightmapBytes?.Length ?? 0);
|
||||
|
||||
|
||||
// write structure data
|
||||
writer.Write(this.NodesPointer);
|
||||
writer.Write(this.NodesCount);
|
||||
writer.Write(this.NodesCountVehicle);
|
||||
writer.Write(this.NodesCountPed);
|
||||
writer.Write(this.Unk24);
|
||||
writer.Write(this.LinksPtr);
|
||||
writer.Write(this.LinksCount);
|
||||
writer.Write(this.Unk34);
|
||||
writer.Write(this.JunctionsPtr);
|
||||
writer.Write(this.JunctionHeightmapBytesPtr);
|
||||
writer.Write(this.Unk48);
|
||||
writer.Write(this.Unk4C);
|
||||
writer.Write(this.JunctionRefsPtr);
|
||||
writer.Write(this.JunctionRefsCount0);
|
||||
writer.Write(this.JunctionRefsCount1);
|
||||
writer.Write(this.Unk5C);
|
||||
writer.Write(this.JunctionsCount);
|
||||
writer.Write(this.JunctionHeightmapBytesCount);
|
||||
writer.Write(this.Unk68);
|
||||
writer.Write(this.Unk6C);
|
||||
}
|
||||
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>(base.GetReferences());
|
||||
|
||||
if ((JunctionRefs != null) && (JunctionRefs.Length > 0))
|
||||
{
|
||||
JunctionRefsBlock = new ResourceSystemStructBlock<NodeJunctionRef>(JunctionRefs);
|
||||
list.Add(JunctionRefsBlock);
|
||||
}
|
||||
if ((JunctionHeightmapBytes != null) && (JunctionHeightmapBytes.Length > 0))
|
||||
{
|
||||
JunctionHeightmapBytesBlock = new ResourceSystemStructBlock<byte>(JunctionHeightmapBytes);
|
||||
list.Add(JunctionHeightmapBytesBlock);
|
||||
}
|
||||
if ((Junctions != null) && (Junctions.Length > 0))
|
||||
{
|
||||
JunctionsBlock = new ResourceSystemStructBlock<NodeJunction>(Junctions);
|
||||
list.Add(JunctionsBlock);
|
||||
}
|
||||
if ((Links != null) && (Links.Length > 0))
|
||||
{
|
||||
LinksBlock = new ResourceSystemStructBlock<NodeLink>(Links);
|
||||
list.Add(LinksBlock);
|
||||
}
|
||||
if ((Nodes != null) && (Nodes.Length > 0))
|
||||
{
|
||||
NodesBlock = new ResourceSystemStructBlock<Node>(Nodes);
|
||||
list.Add(NodesBlock);
|
||||
}
|
||||
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct Node
|
||||
{
|
||||
public uint Unused0 { get; set; } // 0x00000000
|
||||
public uint Unused1 { get; set; } // 0x00000000
|
||||
public uint Unused2 { get; set; } // 0x00000000
|
||||
public uint Unused3 { get; set; } // 0x00000000
|
||||
public ushort AreaID { get; set; }
|
||||
public ushort NodeID { get; set; }
|
||||
public TextHash StreetName { get; set; }
|
||||
public ushort Unused4 { get; set; }
|
||||
public ushort LinkID { get; set; }
|
||||
public short PositionX { get; set; }
|
||||
public short PositionY { get; set; }
|
||||
public FlagsByte Flags0 { get; set; }
|
||||
public FlagsByte Flags1 { get; set; }
|
||||
public short PositionZ { get; set; }
|
||||
public FlagsByte Flags2 { get; set; }
|
||||
public FlagsByte LinkCountFlags { get; set; }
|
||||
public FlagsByte Flags3 { get; set; }
|
||||
public FlagsByte Flags4 { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
//return Unused0.ToString() + ", " + Unused1.ToString() + ", " + Unused2.ToString() + ", " +
|
||||
// Unused3.ToString() + ", " + AreaID.ToString() + ", " + NodeID.ToString() + ", " +
|
||||
// UnknownInterp.ToString() + ", " + HeuristicCost.ToString() + ", " + LinkID.ToString() + ", " +
|
||||
// PositionX.ToString() + ", " + PositionY.ToString() + ", " + Unk20.ToString() + ", " + Unk21.ToString() + ", " +
|
||||
// Unk22.ToString() + ", " + Unk24.ToString() + ", " + Unk26.ToString();
|
||||
|
||||
return AreaID.ToString() + ", " + NodeID.ToString() + ", " + StreetName.ToString();// + ", X:" +
|
||||
//PositionX.ToString() + ", Y:" + PositionY.ToString() + ", " + PositionZ.ToString();// + ", " +
|
||||
//Flags0.ToString() + ", " + Flags1.ToString() + ", Z:" +
|
||||
//Flags2.ToString() + ", " + LinkCountFlags.ToString() + ", " +
|
||||
//Flags3.ToString() + ", " + Flags4.ToString();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NodeLink
|
||||
{
|
||||
public ushort AreaID { get; set; }
|
||||
public ushort NodeID { get; set; }
|
||||
public FlagsByte Flags0 { get; set; }
|
||||
public FlagsByte Flags1 { get; set; }
|
||||
public FlagsByte Flags2 { get; set; }
|
||||
public FlagsByte LinkLength { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return AreaID.ToString() + ", " + NodeID.ToString() + ", " + Flags0.Value.ToString() + ", " + Flags1.Value.ToString() + ", " + Flags2.Value.ToString() + ", " + LinkLength.Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NodeJunction
|
||||
{
|
||||
public short MaxZ { get; set; }
|
||||
public short PositionX { get; set; }
|
||||
public short PositionY { get; set; }
|
||||
public short MinZ { get; set; }
|
||||
public ushort HeightmapPtr { get; set; }
|
||||
public byte HeightmapDimX { get; set; }
|
||||
public byte HeightmapDimY { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return PositionX.ToString() + ", " + PositionY.ToString() + ": " + MinZ.ToString() + ", " + MaxZ.ToString() + ": " + HeightmapDimX.ToString() + " x " + HeightmapDimY.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NodeJunctionRef
|
||||
{
|
||||
public ushort AreaID { get; set; }
|
||||
public ushort NodeID { get; set; }
|
||||
public ushort JunctionID { get; set; }
|
||||
public ushort Unk0 { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return AreaID.ToString() + ", " + NodeID.ToString() + ", " + JunctionID.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
4303
CodeWalker.Core/GameFiles/Resources/Particle.cs
Normal file
4303
CodeWalker.Core/GameFiles/Resources/Particle.cs
Normal file
File diff suppressed because it is too large
Load Diff
1454
CodeWalker.Core/GameFiles/Resources/ResourceBaseTypes.cs
Normal file
1454
CodeWalker.Core/GameFiles/Resources/ResourceBaseTypes.cs
Normal file
File diff suppressed because it is too large
Load Diff
340
CodeWalker.Core/GameFiles/Resources/ResourceBuilder.cs
Normal file
340
CodeWalker.Core/GameFiles/Resources/ResourceBuilder.cs
Normal file
@ -0,0 +1,340 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public class ResourceBuilder
|
||||
{
|
||||
protected const int RESOURCE_IDENT = 0x37435352;
|
||||
protected const int BASE_SIZE = 0x2000;
|
||||
private const int SKIP_SIZE = 512;//256;//64;
|
||||
private const int ALIGN_SIZE = 512;//64;
|
||||
|
||||
|
||||
public static void GetBlocks(IResourceBlock rootBlock, out IList<IResourceBlock> sys, out IList<IResourceBlock> gfx)
|
||||
{
|
||||
var systemBlocks = new HashSet<IResourceBlock>();
|
||||
var graphicBlocks = new HashSet<IResourceBlock>();
|
||||
var protectedBlocks = new List<IResourceBlock>();
|
||||
|
||||
var stack = new Stack<IResourceBlock>();
|
||||
stack.Push(rootBlock);
|
||||
|
||||
var processed = new HashSet<IResourceBlock>();
|
||||
processed.Add(rootBlock);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var block = stack.Pop();
|
||||
if (block == null)
|
||||
continue;
|
||||
|
||||
if (block is IResourceSystemBlock)
|
||||
{
|
||||
if (!systemBlocks.Contains(block))
|
||||
systemBlocks.Add(block);
|
||||
|
||||
// for system blocks, also process references...
|
||||
|
||||
var references = ((IResourceSystemBlock)block).GetReferences();
|
||||
//Array.Reverse(references);
|
||||
foreach (var reference in references)
|
||||
if (!processed.Contains(reference))
|
||||
{
|
||||
stack.Push(reference);
|
||||
processed.Add(reference);
|
||||
}
|
||||
var subs = new Stack<IResourceSystemBlock>();
|
||||
foreach (var part in ((IResourceSystemBlock)block).GetParts())
|
||||
subs.Push((IResourceSystemBlock)part.Item2);
|
||||
while (subs.Count > 0)
|
||||
{
|
||||
var sub = subs.Pop();
|
||||
|
||||
foreach (var x in sub.GetReferences())
|
||||
if (!processed.Contains(x))
|
||||
{
|
||||
stack.Push(x);
|
||||
processed.Add(x);
|
||||
}
|
||||
foreach (var x in sub.GetParts())
|
||||
subs.Push((IResourceSystemBlock)x.Item2);
|
||||
|
||||
protectedBlocks.Add(sub);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!graphicBlocks.Contains(block))
|
||||
graphicBlocks.Add(block);
|
||||
}
|
||||
}
|
||||
|
||||
//var result = new List<IResourceBlock>();
|
||||
//result.AddRange(systemBlocks);
|
||||
//result.AddRange(graphicBlocks);
|
||||
//return result;
|
||||
|
||||
// there are now sys-blocks in the list that actually
|
||||
// only substructures and therefore must not get
|
||||
// a new position!
|
||||
// -> remove them from the list
|
||||
foreach (var q in protectedBlocks)
|
||||
if (systemBlocks.Contains(q))
|
||||
systemBlocks.Remove(q);
|
||||
|
||||
|
||||
sys = new List<IResourceBlock>();
|
||||
foreach (var s in systemBlocks)
|
||||
sys.Add(s);
|
||||
gfx = new List<IResourceBlock>();
|
||||
foreach (var s in graphicBlocks)
|
||||
gfx.Add(s);
|
||||
}
|
||||
|
||||
public static void AssignPositions(IList<IResourceBlock> blocks, uint basePosition, ref int pageSize, out int pageCount)
|
||||
{
|
||||
// find largest structure
|
||||
long largestBlockSize = 0;
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
if (largestBlockSize < block.BlockLength)
|
||||
largestBlockSize = block.BlockLength;
|
||||
}
|
||||
|
||||
// find minimum page size
|
||||
long currentPageSize = pageSize;// 0x2000;
|
||||
while (currentPageSize < largestBlockSize)
|
||||
currentPageSize *= 2;
|
||||
|
||||
long currentPageCount;
|
||||
long currentPosition;
|
||||
while (true)
|
||||
{
|
||||
currentPageCount = 0;
|
||||
currentPosition = 0;
|
||||
|
||||
// reset all positions
|
||||
foreach (var block in blocks)
|
||||
block.FilePosition = -1;
|
||||
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
if (block.FilePosition != -1)
|
||||
throw new Exception("A position of -1 is not possible!");
|
||||
//if (block.Length == 0)
|
||||
// throw new Exception("A length of 0 is not allowed!");
|
||||
|
||||
// check if new page is necessary...
|
||||
// if yes, add a new page and align to it
|
||||
long maxSpace = currentPageCount * currentPageSize - currentPosition;
|
||||
if (maxSpace < (block.BlockLength + SKIP_SIZE))
|
||||
{
|
||||
currentPageCount++;
|
||||
currentPosition = currentPageSize * (currentPageCount - 1);
|
||||
}
|
||||
|
||||
// set position
|
||||
block.FilePosition = basePosition + currentPosition;
|
||||
currentPosition += block.BlockLength + SKIP_SIZE;
|
||||
|
||||
// align...
|
||||
if ((currentPosition % ALIGN_SIZE) != 0)
|
||||
currentPosition += (ALIGN_SIZE - (currentPosition % ALIGN_SIZE));
|
||||
}
|
||||
|
||||
// break if everything fits...
|
||||
if (currentPageCount < 128)
|
||||
break;
|
||||
|
||||
currentPageSize *= 2;
|
||||
}
|
||||
|
||||
pageSize = (int)currentPageSize;
|
||||
pageCount = (int)currentPageCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] Build(ResourceFileBase fileBase, int version)
|
||||
{
|
||||
|
||||
fileBase.FilePagesInfo = new ResourcePagesInfo();
|
||||
|
||||
IList<IResourceBlock> systemBlocks;
|
||||
IList<IResourceBlock> graphicBlocks;
|
||||
GetBlocks(fileBase, out systemBlocks, out graphicBlocks);
|
||||
|
||||
int systemPageSize = BASE_SIZE;// *4;
|
||||
int systemPageCount;
|
||||
AssignPositions(systemBlocks, 0x50000000, ref systemPageSize, out systemPageCount);
|
||||
|
||||
int graphicsPageSize = BASE_SIZE;
|
||||
int graphicsPageCount;
|
||||
AssignPositions(graphicBlocks, 0x60000000, ref graphicsPageSize, out graphicsPageCount);
|
||||
|
||||
|
||||
|
||||
|
||||
fileBase.FilePagesInfo.SystemPagesCount = 0;
|
||||
if (systemPageCount > 0)
|
||||
fileBase.FilePagesInfo.SystemPagesCount = 1; // (byte)systemPageCount; //1
|
||||
fileBase.FilePagesInfo.GraphicsPagesCount = (byte)graphicsPageCount;
|
||||
|
||||
|
||||
|
||||
var systemStream = new MemoryStream();
|
||||
var graphicsStream = new MemoryStream();
|
||||
var resourceWriter = new ResourceDataWriter(systemStream, graphicsStream);
|
||||
|
||||
resourceWriter.Position = 0x50000000;
|
||||
foreach (var block in systemBlocks)
|
||||
{
|
||||
resourceWriter.Position = block.FilePosition;
|
||||
|
||||
var pos_before = resourceWriter.Position;
|
||||
block.Write(resourceWriter);
|
||||
var pos_after = resourceWriter.Position;
|
||||
|
||||
if ((pos_after - pos_before) != block.BlockLength)
|
||||
{
|
||||
throw new Exception("error in system length");
|
||||
}
|
||||
}
|
||||
|
||||
resourceWriter.Position = 0x60000000;
|
||||
foreach (var block in graphicBlocks)
|
||||
{
|
||||
resourceWriter.Position = block.FilePosition;
|
||||
|
||||
var pos_before = resourceWriter.Position;
|
||||
block.Write(resourceWriter);
|
||||
var pos_after = resourceWriter.Position;
|
||||
|
||||
if ((pos_after - pos_before) != block.BlockLength)
|
||||
{
|
||||
throw new Exception("error in graphics length");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var sysDataSize = 0x2000;
|
||||
while (sysDataSize < systemStream.Length)
|
||||
{
|
||||
sysDataSize *= 2;
|
||||
}
|
||||
var sysData = new byte[sysDataSize];
|
||||
systemStream.Flush();
|
||||
systemStream.Position = 0;
|
||||
systemStream.Read(sysData, 0, (int)systemStream.Length);
|
||||
|
||||
|
||||
var gfxPageSize = 0x2000;
|
||||
while (gfxPageSize != graphicsPageSize)
|
||||
{
|
||||
gfxPageSize *= 2;
|
||||
}
|
||||
var gfxDataSize = graphicsPageCount * gfxPageSize;
|
||||
var gfxData = new byte[gfxDataSize];
|
||||
graphicsStream.Flush();
|
||||
graphicsStream.Position = 0;
|
||||
graphicsStream.Read(gfxData, 0, (int)graphicsStream.Length);
|
||||
|
||||
|
||||
|
||||
uint uv = (uint)version;
|
||||
uint sv = (uv >> 4) & 0xF;
|
||||
uint gv = (uv >> 0) & 0xF;
|
||||
|
||||
//uint sf = RpfResourceFileEntry.GetFlagsFromSize(sysDataSize, sv);
|
||||
//uint gf = RpfResourceFileEntry.GetFlagsFromSize(gfxDataSize, gv); //TODO: might be broken...
|
||||
|
||||
uint sf = RpfResourceFileEntry.GetFlagsFromBlocks((uint)systemPageCount, (uint)systemPageSize, sv);
|
||||
uint gf = RpfResourceFileEntry.GetFlagsFromBlocks((uint)graphicsPageCount, (uint)graphicsPageSize, gv);
|
||||
|
||||
var tdatasize = sysDataSize + gfxDataSize;
|
||||
var tdata = new byte[tdatasize];
|
||||
Buffer.BlockCopy(sysData, 0, tdata, 0, sysDataSize);
|
||||
Buffer.BlockCopy(gfxData, 0, tdata, sysDataSize, gfxDataSize);
|
||||
|
||||
|
||||
var cdata = Compress(tdata);
|
||||
|
||||
|
||||
var dataSize = 16 + cdata.Length;// sysDataSize + gfxDataSize;
|
||||
var data = new byte[dataSize];
|
||||
|
||||
byte[] h1 = BitConverter.GetBytes((uint)0x37435352);
|
||||
byte[] h2 = BitConverter.GetBytes((int)version);
|
||||
byte[] h3 = BitConverter.GetBytes(sf);
|
||||
byte[] h4 = BitConverter.GetBytes(gf);
|
||||
Buffer.BlockCopy(h1, 0, data, 0, 4);
|
||||
Buffer.BlockCopy(h2, 0, data, 4, 4);
|
||||
Buffer.BlockCopy(h3, 0, data, 8, 4);
|
||||
Buffer.BlockCopy(h4, 0, data, 12, 4);
|
||||
Buffer.BlockCopy(cdata, 0, data, 16, cdata.Length);
|
||||
//Buffer.BlockCopy(sysData, 0, data, 16, sysDataSize);
|
||||
//Buffer.BlockCopy(gfxData, 0, data, 16 + sysDataSize, gfxDataSize);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte[] AddResourceHeader(RpfResourceFileEntry entry, byte[] data)
|
||||
{
|
||||
if (data == null) return null;
|
||||
byte[] newdata = new byte[data.Length + 16];
|
||||
byte[] h1 = BitConverter.GetBytes((uint)0x37435352);
|
||||
byte[] h2 = BitConverter.GetBytes(entry.Version);
|
||||
byte[] h3 = BitConverter.GetBytes(entry.SystemFlags);
|
||||
byte[] h4 = BitConverter.GetBytes(entry.GraphicsFlags);
|
||||
Buffer.BlockCopy(h1, 0, newdata, 0, 4);
|
||||
Buffer.BlockCopy(h2, 0, newdata, 4, 4);
|
||||
Buffer.BlockCopy(h3, 0, newdata, 8, 4);
|
||||
Buffer.BlockCopy(h4, 0, newdata, 12, 4);
|
||||
Buffer.BlockCopy(data, 0, newdata, 16, data.Length);
|
||||
return newdata;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] Compress(byte[] data)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress, true);
|
||||
ds.Write(data, 0, data.Length);
|
||||
ds.Close();
|
||||
byte[] deflated = ms.GetBuffer();
|
||||
byte[] outbuf = new byte[ms.Length]; //need to copy to the right size buffer...
|
||||
Array.Copy(deflated, outbuf, outbuf.Length);
|
||||
return outbuf;
|
||||
}
|
||||
}
|
||||
public static byte[] Decompress(byte[] data)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream(data))
|
||||
{
|
||||
DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress);
|
||||
MemoryStream outstr = new MemoryStream();
|
||||
ds.CopyTo(outstr);
|
||||
byte[] deflated = outstr.GetBuffer();
|
||||
byte[] outbuf = new byte[outstr.Length]; //need to copy to the right size buffer...
|
||||
Array.Copy(deflated, outbuf, outbuf.Length);
|
||||
return outbuf;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
750
CodeWalker.Core/GameFiles/Resources/ResourceData.cs
Normal file
750
CodeWalker.Core/GameFiles/Resources/ResourceData.cs
Normal file
@ -0,0 +1,750 @@
|
||||
/*
|
||||
Copyright(c) 2015 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//shamelessly stolen and mangled
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents a resource data reader.
|
||||
/// </summary>
|
||||
public class ResourceDataReader : DataReader
|
||||
{
|
||||
private const long SYSTEM_BASE = 0x50000000;
|
||||
private const long GRAPHICS_BASE = 0x60000000;
|
||||
|
||||
private Stream systemStream;
|
||||
private Stream graphicsStream;
|
||||
|
||||
// this is a dictionary that contains all the resource blocks
|
||||
// which were read from this resource reader
|
||||
private Dictionary<long, List<IResourceBlock>> blockPool;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the underlying stream.
|
||||
/// </summary>
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position within the underlying stream.
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new resource data reader for the specified system- and graphics-stream.
|
||||
/// </summary>
|
||||
public ResourceDataReader(Stream systemStream, Stream graphicsStream, Endianess endianess = Endianess.LittleEndian)
|
||||
: base((Stream)null, endianess)
|
||||
{
|
||||
this.systemStream = systemStream;
|
||||
this.graphicsStream = graphicsStream;
|
||||
this.blockPool = new Dictionary<long, List<IResourceBlock>>();
|
||||
}
|
||||
|
||||
public ResourceDataReader(RpfResourceFileEntry resentry, byte[] data, Endianess endianess = Endianess.LittleEndian)
|
||||
: base((Stream)null, endianess)
|
||||
{
|
||||
var systemSize = resentry.SystemSize;
|
||||
var graphicsSize = resentry.GraphicsSize;
|
||||
|
||||
this.systemStream = new MemoryStream(data, 0, systemSize);
|
||||
this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize);
|
||||
this.blockPool = new Dictionary<long, List<IResourceBlock>>();
|
||||
Position = 0x50000000;
|
||||
}
|
||||
|
||||
public ResourceDataReader(int systemSize, int graphicsSize, byte[] data, Endianess endianess = Endianess.LittleEndian)
|
||||
: base((Stream)null, endianess)
|
||||
{
|
||||
this.systemStream = new MemoryStream(data, 0, systemSize);
|
||||
this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize);
|
||||
this.blockPool = new Dictionary<long, List<IResourceBlock>>();
|
||||
Position = 0x50000000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from the underlying stream. This is the only method that directly accesses
|
||||
/// the data in the underlying stream.
|
||||
/// </summary>
|
||||
protected override byte[] ReadFromStream(int count, bool ignoreEndianess = false)
|
||||
{
|
||||
if ((Position & SYSTEM_BASE) == SYSTEM_BASE)
|
||||
{
|
||||
// read from system stream...
|
||||
|
||||
systemStream.Position = Position & ~0x50000000;
|
||||
|
||||
var buffer = new byte[count];
|
||||
systemStream.Read(buffer, 0, count);
|
||||
|
||||
// handle endianess
|
||||
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
||||
{
|
||||
Array.Reverse(buffer);
|
||||
}
|
||||
|
||||
Position = systemStream.Position | 0x50000000;
|
||||
return buffer;
|
||||
|
||||
}
|
||||
if ((Position & GRAPHICS_BASE) == GRAPHICS_BASE)
|
||||
{
|
||||
// read from graphic stream...
|
||||
|
||||
graphicsStream.Position = Position & ~0x60000000;
|
||||
|
||||
var buffer = new byte[count];
|
||||
graphicsStream.Read(buffer, 0, count);
|
||||
|
||||
// handle endianess
|
||||
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
||||
{
|
||||
Array.Reverse(buffer);
|
||||
}
|
||||
|
||||
Position = graphicsStream.Position | 0x60000000;
|
||||
return buffer;
|
||||
}
|
||||
throw new Exception("illegal position!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a block.
|
||||
/// </summary>
|
||||
public T ReadBlock<T>(params object[] parameters) where T : IResourceBlock, new()
|
||||
{
|
||||
// make sure to return the same object if the same
|
||||
// block is read again...
|
||||
if (blockPool.ContainsKey(Position))
|
||||
{
|
||||
var blocks = blockPool[Position];
|
||||
foreach (var block in blocks)
|
||||
if (block is T)
|
||||
{
|
||||
Position += block.BlockLength;
|
||||
|
||||
// since a resource block of the same type
|
||||
// has been found at the same address, return it
|
||||
return (T)block;
|
||||
}
|
||||
}
|
||||
|
||||
var result = new T();
|
||||
|
||||
|
||||
// replace with correct type...
|
||||
if (result is IResourceXXSystemBlock)
|
||||
result = (T)((IResourceXXSystemBlock)result).GetType(this, parameters);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
|
||||
// add block to the block pool...
|
||||
if (blockPool.ContainsKey(Position))
|
||||
{
|
||||
blockPool[Position].Add(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
var blocks = new List<IResourceBlock>();
|
||||
blocks.Add(result);
|
||||
blockPool.Add(Position, blocks);
|
||||
}
|
||||
|
||||
var classPosition = Position;
|
||||
result.Read(this, parameters);
|
||||
//result.Position = classPosition; //TODO: need this if writing stuff!
|
||||
return (T)result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a block at a specified position.
|
||||
/// </summary>
|
||||
public T ReadBlockAt<T>(ulong position, params object[] parameters) where T : IResourceBlock, new()
|
||||
{
|
||||
if (position != 0)
|
||||
{
|
||||
var positionBackup = Position;
|
||||
|
||||
Position = (long)position;
|
||||
var result = ReadBlock<T>(parameters);
|
||||
Position = positionBackup;
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte[] ReadBytesAt(ulong position, uint count)
|
||||
{
|
||||
long pos = (long)position;
|
||||
if ((pos <= 0) || (count == 0)) return null;
|
||||
var posbackup = Position;
|
||||
Position = pos;
|
||||
var result = ReadBytes((int)count);
|
||||
Position = posbackup;
|
||||
return result;
|
||||
}
|
||||
public ushort[] ReadUshortsAt(ulong position, uint count)
|
||||
{
|
||||
if ((position <= 0) || (count == 0)) return null;
|
||||
|
||||
var result = new ushort[count];
|
||||
var length = count * 2;
|
||||
byte[] data = ReadBytesAt(position, length);
|
||||
Buffer.BlockCopy(data, 0, result, 0, (int)length);
|
||||
|
||||
//var posbackup = Position;
|
||||
//Position = position;
|
||||
//var result2 = new ushort[count];
|
||||
//for (uint i = 0; i < count; i++)
|
||||
//{
|
||||
// result2[i] = ReadUInt16();
|
||||
//}
|
||||
//Position = posbackup;
|
||||
return result;
|
||||
}
|
||||
public uint[] ReadUintsAt(ulong position, uint count)
|
||||
{
|
||||
if ((position <= 0) || (count == 0)) return null;
|
||||
|
||||
var result = new uint[count];
|
||||
var length = count * 4;
|
||||
byte[] data = ReadBytesAt(position, length);
|
||||
Buffer.BlockCopy(data, 0, result, 0, (int)length);
|
||||
|
||||
//var posbackup = Position;
|
||||
//Position = position;
|
||||
//var result = new uint[count];
|
||||
//for (uint i = 0; i < count; i++)
|
||||
//{
|
||||
// result[i] = ReadUInt32();
|
||||
//}
|
||||
//Position = posbackup;
|
||||
return result;
|
||||
}
|
||||
public ulong[] ReadUlongsAt(ulong position, uint count)
|
||||
{
|
||||
if ((position <= 0) || (count == 0)) return null;
|
||||
|
||||
var result = new ulong[count];
|
||||
var length = count * 8;
|
||||
byte[] data = ReadBytesAt(position, length);
|
||||
Buffer.BlockCopy(data, 0, result, 0, (int)length);
|
||||
|
||||
//var posbackup = Position;
|
||||
//Position = position;
|
||||
//var result = new ulong[count];
|
||||
//for (uint i = 0; i < count; i++)
|
||||
//{
|
||||
// result[i] = ReadUInt64();
|
||||
//}
|
||||
//Position = posbackup;
|
||||
return result;
|
||||
}
|
||||
public float[] ReadFloatsAt(ulong position, uint count)
|
||||
{
|
||||
if ((position <= 0) || (count == 0)) return null;
|
||||
|
||||
var result = new float[count];
|
||||
var length = count * 4;
|
||||
byte[] data = ReadBytesAt(position, length);
|
||||
Buffer.BlockCopy(data, 0, result, 0, (int)length);
|
||||
|
||||
//var posbackup = Position;
|
||||
//Position = position;
|
||||
//var result = new float[count];
|
||||
//for (uint i = 0; i < count; i++)
|
||||
//{
|
||||
// result[i] = ReadSingle();
|
||||
//}
|
||||
//Position = posbackup;
|
||||
return result;
|
||||
}
|
||||
public T[] ReadStructsAt<T>(ulong position, uint count)//, uint structsize)
|
||||
{
|
||||
if ((position <= 0) || (count == 0)) return null;
|
||||
|
||||
uint structsize = (uint)Marshal.SizeOf(typeof(T));
|
||||
var length = count * structsize;
|
||||
byte[] data = ReadBytesAt(position, length);
|
||||
|
||||
//var result2 = new T[count];
|
||||
//Buffer.BlockCopy(data, 0, result2, 0, (int)length); //error: "object must be an array of primitives" :(
|
||||
|
||||
var result = new T[count];
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
var h = handle.AddrOfPinnedObject();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
result[i] = Marshal.PtrToStructure<T>(h + (int)(i * structsize));
|
||||
}
|
||||
handle.Free();
|
||||
|
||||
return result;
|
||||
}
|
||||
public T[] ReadStructs<T>(uint count)
|
||||
{
|
||||
uint structsize = (uint)Marshal.SizeOf(typeof(T));
|
||||
var result = new T[count];
|
||||
var length = count * structsize;
|
||||
byte[] data = ReadBytes((int)length);
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
var h = handle.AddrOfPinnedObject();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
result[i] = Marshal.PtrToStructure<T>(h + (int)(i * structsize));
|
||||
}
|
||||
handle.Free();
|
||||
return result;
|
||||
}
|
||||
|
||||
public T ReadStruct<T>() where T : struct
|
||||
{
|
||||
uint structsize = (uint)Marshal.SizeOf(typeof(T));
|
||||
var length = structsize;
|
||||
byte[] data = ReadBytes((int)length);
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
var h = handle.AddrOfPinnedObject();
|
||||
var result = Marshal.PtrToStructure<T>(h);
|
||||
handle.Free();
|
||||
return result;
|
||||
}
|
||||
|
||||
public T ReadStructAt<T>(long position) where T : struct
|
||||
{
|
||||
if ((position <= 0)) return default(T);
|
||||
var posbackup = Position;
|
||||
Position = (long)position;
|
||||
var result = ReadStruct<T>();
|
||||
Position = posbackup;
|
||||
return result;
|
||||
}
|
||||
|
||||
public string ReadStringAt(ulong position)
|
||||
{
|
||||
long newpos = (long)position;
|
||||
if ((newpos <= 0)) return null;
|
||||
var lastpos = Position;
|
||||
Position = newpos;
|
||||
var result = ReadString();
|
||||
Position = lastpos;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a resource data writer.
|
||||
/// </summary>
|
||||
public class ResourceDataWriter : DataWriter
|
||||
{
|
||||
private const long SYSTEM_BASE = 0x50000000;
|
||||
private const long GRAPHICS_BASE = 0x60000000;
|
||||
|
||||
private Stream systemStream;
|
||||
private Stream graphicsStream;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the underlying stream.
|
||||
/// </summary>
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position within the underlying stream.
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new resource data reader for the specified system- and graphics-stream.
|
||||
/// </summary>
|
||||
public ResourceDataWriter(Stream systemStream, Stream graphicsStream, Endianess endianess = Endianess.LittleEndian)
|
||||
: base((Stream)null, endianess)
|
||||
{
|
||||
this.systemStream = systemStream;
|
||||
this.graphicsStream = graphicsStream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to the underlying stream. This is the only method that directly accesses
|
||||
/// the data in the underlying stream.
|
||||
/// </summary>
|
||||
protected override void WriteToStream(byte[] value, bool ignoreEndianess = true)
|
||||
{
|
||||
if ((Position & SYSTEM_BASE) == SYSTEM_BASE)
|
||||
{
|
||||
// write to system stream...
|
||||
|
||||
systemStream.Position = Position & ~SYSTEM_BASE;
|
||||
|
||||
// handle endianess
|
||||
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
||||
{
|
||||
var buf = (byte[])value.Clone();
|
||||
Array.Reverse(buf);
|
||||
systemStream.Write(buf, 0, buf.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
systemStream.Write(value, 0, value.Length);
|
||||
}
|
||||
|
||||
Position = systemStream.Position | 0x50000000;
|
||||
return;
|
||||
|
||||
}
|
||||
if ((Position & GRAPHICS_BASE) == GRAPHICS_BASE)
|
||||
{
|
||||
// write to graphic stream...
|
||||
|
||||
graphicsStream.Position = Position & ~GRAPHICS_BASE;
|
||||
|
||||
// handle endianess
|
||||
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
||||
{
|
||||
var buf = (byte[])value.Clone();
|
||||
Array.Reverse(buf);
|
||||
graphicsStream.Write(buf, 0, buf.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphicsStream.Write(value, 0, value.Length);
|
||||
}
|
||||
|
||||
Position = graphicsStream.Position | 0x60000000;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Exception("illegal position!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a block.
|
||||
/// </summary>
|
||||
public void WriteBlock(IResourceBlock value)
|
||||
{
|
||||
value.Write(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void WriteStruct<T>(T val) where T : struct
|
||||
{
|
||||
int size = Marshal.SizeOf(typeof(T));
|
||||
byte[] arr = new byte[size];
|
||||
IntPtr ptr = Marshal.AllocHGlobal(size);
|
||||
Marshal.StructureToPtr(val, ptr, true);
|
||||
Marshal.Copy(ptr, arr, 0, size);
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
Write(arr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data block in a resource file.
|
||||
/// </summary>
|
||||
public interface IResourceBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the position of the data block.
|
||||
/// </summary>
|
||||
long FilePosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the data block.
|
||||
/// </summary>
|
||||
long BlockLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data block.
|
||||
/// </summary>
|
||||
void Read(ResourceDataReader reader, params object[] parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data block.
|
||||
/// </summary>
|
||||
void Write(ResourceDataWriter writer, params object[] parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data block of the system segement in a resource file.
|
||||
/// </summary>
|
||||
public interface IResourceSystemBlock : IResourceBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of data blocks that are part of this block.
|
||||
/// </summary>
|
||||
Tuple<long, IResourceBlock>[] GetParts();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of data blocks that are referenced by this block.
|
||||
/// </summary>
|
||||
IResourceBlock[] GetReferences();
|
||||
}
|
||||
|
||||
public interface IResourceXXSystemBlock : IResourceSystemBlock
|
||||
{
|
||||
IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data block of the graphics segmenet in a resource file.
|
||||
/// </summary>
|
||||
public interface IResourceGraphicsBlock : IResourceBlock
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data block of the system segement in a resource file.
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public abstract class ResourceSystemBlock : IResourceSystemBlock
|
||||
{
|
||||
private long position;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position of the data block.
|
||||
/// </summary>
|
||||
public virtual long FilePosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return position;
|
||||
}
|
||||
set
|
||||
{
|
||||
position = value;
|
||||
foreach (var part in GetParts())
|
||||
{
|
||||
part.Item2.FilePosition = value + part.Item1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the data block.
|
||||
/// </summary>
|
||||
public abstract long BlockLength
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data block.
|
||||
/// </summary>
|
||||
public abstract void Read(ResourceDataReader reader, params object[] parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data block.
|
||||
/// </summary>
|
||||
public abstract void Write(ResourceDataWriter writer, params object[] parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of data blocks that are part of this block.
|
||||
/// </summary>
|
||||
public virtual Tuple<long, IResourceBlock>[] GetParts()
|
||||
{
|
||||
return new Tuple<long, IResourceBlock>[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of data blocks that are referenced by this block.
|
||||
/// </summary>
|
||||
public virtual IResourceBlock[] GetReferences()
|
||||
{
|
||||
return new IResourceBlock[0];
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ResourecTypedSystemBlock : ResourceSystemBlock, IResourceXXSystemBlock
|
||||
{
|
||||
public abstract IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data block of the graphics segmenet in a resource file.
|
||||
/// </summary>
|
||||
public abstract class ResourceGraphicsBlock : IResourceGraphicsBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the position of the data block.
|
||||
/// </summary>
|
||||
public virtual long FilePosition
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the data block.
|
||||
/// </summary>
|
||||
public abstract long BlockLength
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data block.
|
||||
/// </summary>
|
||||
public abstract void Read(ResourceDataReader reader, params object[] parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data block.
|
||||
/// </summary>
|
||||
public abstract void Write(ResourceDataWriter writer, params object[] parameters);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class ResourceSystemDataBlock : ResourceSystemBlock //used for writing resources.
|
||||
{
|
||||
public byte[] Data { get; set; }
|
||||
public int DataLength { get; set; }
|
||||
|
||||
public override long BlockLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Data != null) ? Data.Length : DataLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ResourceSystemDataBlock(byte[] data)
|
||||
{
|
||||
Data = data;
|
||||
DataLength = (Data != null) ? Data.Length : 0;
|
||||
}
|
||||
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
Data = reader.ReadBytes(DataLength);
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
writer.Write(Data);
|
||||
}
|
||||
}
|
||||
|
||||
public class ResourceSystemStructBlock<T> : ResourceSystemBlock where T : struct //used for writing resources.
|
||||
{
|
||||
public T[] Items { get; set; }
|
||||
public int ItemCount { get; set; }
|
||||
public int StructureSize { get; set; }
|
||||
|
||||
public override long BlockLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((Items != null) ? Items.Length : ItemCount) * StructureSize;
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceSystemStructBlock(T[] items)
|
||||
{
|
||||
Items = items;
|
||||
ItemCount = (Items != null) ? Items.Length : 0;
|
||||
StructureSize = Marshal.SizeOf(typeof(T));
|
||||
}
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
int datalength = ItemCount * StructureSize;
|
||||
byte[] data = reader.ReadBytes(datalength);
|
||||
Items = MetaTypes.ConvertDataArray<T>(data, 0, ItemCount);
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
byte[] data = MetaTypes.ConvertArrayToBytes(Items);
|
||||
writer.Write(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//public interface ResourceDataStruct
|
||||
//{
|
||||
// void Read(ResourceDataReader reader);
|
||||
// void Write(ResourceDataWriter writer);
|
||||
//}
|
||||
|
||||
}
|
148
CodeWalker.Core/GameFiles/Resources/ResourceFile.cs
Normal file
148
CodeWalker.Core/GameFiles/Resources/ResourceFile.cs
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright(c) 2015 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//shamelessly stolen and mangled
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceFileBase : ResourceSystemBlock
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 16; }
|
||||
}
|
||||
|
||||
// structure data
|
||||
public uint FileVFT { get; set; }
|
||||
public uint FileUnknown { get; set; }
|
||||
public ulong FilePagesInfoPointer { get; set; }
|
||||
|
||||
// reference data
|
||||
public ResourcePagesInfo FilePagesInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
// read structure data
|
||||
this.FileVFT = reader.ReadUInt32();
|
||||
this.FileUnknown = reader.ReadUInt32();
|
||||
this.FilePagesInfoPointer = reader.ReadUInt64();
|
||||
|
||||
// read reference data
|
||||
this.FilePagesInfo = reader.ReadBlockAt<ResourcePagesInfo>(
|
||||
this.FilePagesInfoPointer // offset
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data-block to a stream.
|
||||
/// </summary>
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
// update structure data
|
||||
this.FilePagesInfoPointer = (ulong)(this.FilePagesInfo != null ? this.FilePagesInfo.FilePosition : 0);
|
||||
|
||||
// write structure data
|
||||
writer.Write(this.FileVFT);
|
||||
writer.Write(this.FileUnknown);
|
||||
writer.Write(this.FilePagesInfoPointer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of data blocks which are referenced by this block.
|
||||
/// </summary>
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>();
|
||||
if (FilePagesInfo != null) list.Add(FilePagesInfo);
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourcePagesInfo : ResourceSystemBlock
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 20; }
|
||||
}
|
||||
|
||||
// structure data
|
||||
public uint Unknown_0h { get; set; }
|
||||
public uint Unknown_4h { get; set; }
|
||||
public byte SystemPagesCount { get; set; }
|
||||
public byte GraphicsPagesCount { get; set; }
|
||||
public ushort Unknown_Ah { get; set; }
|
||||
public uint Unknown_Ch { get; set; }
|
||||
public uint Unknown_10h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
// read structure data
|
||||
this.Unknown_0h = reader.ReadUInt32();
|
||||
this.Unknown_4h = reader.ReadUInt32();
|
||||
this.SystemPagesCount = reader.ReadByte();
|
||||
this.GraphicsPagesCount = reader.ReadByte();
|
||||
this.Unknown_Ah = reader.ReadUInt16();
|
||||
this.Unknown_Ch = reader.ReadUInt32();
|
||||
this.Unknown_10h = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data-block to a stream.
|
||||
/// </summary>
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
// write structure data
|
||||
writer.Write(this.Unknown_0h);
|
||||
writer.Write(this.Unknown_4h);
|
||||
writer.Write(this.SystemPagesCount);
|
||||
writer.Write(this.GraphicsPagesCount);
|
||||
writer.Write(this.Unknown_Ah);
|
||||
writer.Write(this.Unknown_Ch);
|
||||
writer.Write(this.Unknown_10h);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return SystemPagesCount.ToString() + ", " + GraphicsPagesCount.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
445
CodeWalker.Core/GameFiles/Resources/Texture.cs
Normal file
445
CodeWalker.Core/GameFiles/Resources/Texture.cs
Normal file
@ -0,0 +1,445 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class TextureDictionary : ResourceFileBase
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
// structure data
|
||||
public uint Unknown_10h { get; set; } // 0x00000000
|
||||
public uint Unknown_14h { get; set; } // 0x00000000
|
||||
public uint Unknown_18h { get; set; } // 0x00000001
|
||||
public uint Unknown_1Ch { get; set; } // 0x00000000
|
||||
public ResourceSimpleList64Ptr TextureNameHashesPtr { get; set; }
|
||||
public uint[] TextureNameHashes { get; set; }
|
||||
public ResourcePointerList64<Texture> Textures { get; set; }
|
||||
|
||||
public Dictionary<uint, Texture> Dict { get; set; }
|
||||
public long MemoryUsage
|
||||
{
|
||||
get
|
||||
{
|
||||
long val = 0;
|
||||
if ((Textures != null) && (Textures.data_items != null))
|
||||
{
|
||||
foreach (var tex in Textures.data_items)
|
||||
{
|
||||
if (tex != null)
|
||||
{
|
||||
val += tex.MemoryUsage;
|
||||
}
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
public TextureDictionary()
|
||||
{
|
||||
//this.TextureNameHashes = new ResourceSimpleList64<uint_r>();
|
||||
this.Textures = new ResourcePointerList64<Texture>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
base.Read(reader, parameters);
|
||||
|
||||
// read structure data
|
||||
this.Unknown_10h = reader.ReadUInt32();
|
||||
this.Unknown_14h = reader.ReadUInt32();
|
||||
this.Unknown_18h = reader.ReadUInt32();
|
||||
this.Unknown_1Ch = reader.ReadUInt32();
|
||||
this.TextureNameHashesPtr = reader.ReadStruct<ResourceSimpleList64Ptr>();
|
||||
this.TextureNameHashes = reader.ReadUintsAt(this.TextureNameHashesPtr.EntriesPointer, this.TextureNameHashesPtr.EntriesCount);
|
||||
//this.TextureNameHashes = reader.ReadBlock<ResourceSimpleList64<uint_r>>();
|
||||
this.Textures = reader.ReadBlock<ResourcePointerList64<Texture>>();
|
||||
|
||||
var dict = new Dictionary<uint, Texture>();
|
||||
if ((Textures != null) && (Textures.data_items != null) && (TextureNameHashes != null))
|
||||
{
|
||||
for (int i = 0; (i < Textures.data_items.Length) && (i < TextureNameHashes.Length); i++)
|
||||
{
|
||||
var tex = Textures.data_items[i];
|
||||
var hash = TextureNameHashes[i];
|
||||
dict[hash] = tex;
|
||||
}
|
||||
}
|
||||
Dict = new Dictionary<uint, Texture>(dict);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data-block to a stream.
|
||||
/// </summary>
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
base.Write(writer, parameters);
|
||||
|
||||
// write structure data
|
||||
writer.Write(this.Unknown_10h);
|
||||
writer.Write(this.Unknown_14h);
|
||||
writer.Write(this.Unknown_18h);
|
||||
writer.Write(this.Unknown_1Ch);
|
||||
//writer.WriteBlock(this.TextureNameHashes); //TODO: fix!
|
||||
//writer.WriteBlock(this.Textures);
|
||||
}
|
||||
|
||||
public override Tuple<long, IResourceBlock>[] GetParts()
|
||||
{
|
||||
return new Tuple<long, IResourceBlock>[] {
|
||||
//new Tuple<long, IResourceBlock>(0x20, TextureNameHashes), //TODO: fix!
|
||||
new Tuple<long, IResourceBlock>(0x30, Textures)
|
||||
};
|
||||
}
|
||||
|
||||
public Dictionary<uint, Texture> GetDictionary()
|
||||
{
|
||||
Dictionary<uint, Texture> td = new Dictionary<uint, Texture>();
|
||||
if ((Textures != null) && (Textures.data_items != null))
|
||||
{
|
||||
var texs = Textures.data_items;
|
||||
var hashes = TextureNameHashes;
|
||||
for (int i = 0; (i < texs.Length) && (i < hashes.Length); i++)
|
||||
{
|
||||
td.Add(hashes[i], texs[i]);
|
||||
}
|
||||
}
|
||||
return td;
|
||||
}
|
||||
|
||||
public Texture Lookup(uint hash)
|
||||
{
|
||||
Texture tex = null;
|
||||
if (Dict != null)
|
||||
{
|
||||
Dict.TryGetValue(hash, out tex);
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class TextureBase : ResourceSystemBlock
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 64; }
|
||||
}
|
||||
|
||||
// structure data
|
||||
public uint VFT { get; set; }
|
||||
public uint Unknown_4h { get; set; } // 0x00000001
|
||||
public uint Unknown_8h { get; set; } // 0x00000000
|
||||
public uint Unknown_Ch { get; set; } // 0x00000000
|
||||
public uint Unknown_10h { get; set; } // 0x00000000
|
||||
public uint Unknown_14h { get; set; } // 0x00000000
|
||||
public uint Unknown_18h { get; set; } // 0x00000000
|
||||
public uint Unknown_1Ch { get; set; } // 0x00000000
|
||||
public uint Unknown_20h { get; set; } // 0x00000000
|
||||
public uint Unknown_24h { get; set; } // 0x00000000
|
||||
public ulong NamePointer { get; set; }
|
||||
public uint Unknown_30h { get; set; }
|
||||
public uint Unknown_34h { get; set; } // 0x00000000
|
||||
public uint Unknown_38h { get; set; } // 0x00000000
|
||||
public uint Unknown_3Ch { get; set; } // 0x00000000
|
||||
|
||||
// reference data
|
||||
public string Name { get; set; }
|
||||
public uint NameHash { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
// read structure data
|
||||
this.VFT = reader.ReadUInt32();
|
||||
this.Unknown_4h = reader.ReadUInt32();
|
||||
this.Unknown_8h = reader.ReadUInt32();
|
||||
this.Unknown_Ch = reader.ReadUInt32();
|
||||
this.Unknown_10h = reader.ReadUInt32();
|
||||
this.Unknown_14h = reader.ReadUInt32();
|
||||
this.Unknown_18h = reader.ReadUInt32();
|
||||
this.Unknown_1Ch = reader.ReadUInt32();
|
||||
this.Unknown_20h = reader.ReadUInt32();
|
||||
this.Unknown_24h = reader.ReadUInt32();
|
||||
this.NamePointer = reader.ReadUInt64();
|
||||
this.Unknown_30h = reader.ReadUInt32();
|
||||
this.Unknown_34h = reader.ReadUInt32();
|
||||
this.Unknown_38h = reader.ReadUInt32();
|
||||
this.Unknown_3Ch = reader.ReadUInt32();
|
||||
|
||||
// read reference data
|
||||
this.Name = reader.ReadStringAt( //BlockAt<string_r>(
|
||||
this.NamePointer // offset
|
||||
);
|
||||
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
NameHash = JenkHash.GenHash(Name.ToLowerInvariant());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data-block to a stream.
|
||||
/// </summary>
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
// update structure data
|
||||
//this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO: fix
|
||||
|
||||
// write structure data
|
||||
writer.Write(this.VFT);
|
||||
writer.Write(this.Unknown_4h);
|
||||
writer.Write(this.Unknown_8h);
|
||||
writer.Write(this.Unknown_Ch);
|
||||
writer.Write(this.Unknown_10h);
|
||||
writer.Write(this.Unknown_14h);
|
||||
writer.Write(this.Unknown_18h);
|
||||
writer.Write(this.Unknown_1Ch);
|
||||
writer.Write(this.Unknown_20h);
|
||||
writer.Write(this.Unknown_24h);
|
||||
writer.Write(this.NamePointer);
|
||||
writer.Write(this.Unknown_30h);
|
||||
writer.Write(this.Unknown_34h);
|
||||
writer.Write(this.Unknown_38h);
|
||||
writer.Write(this.Unknown_3Ch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of data blocks which are referenced by this block.
|
||||
/// </summary>
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>();
|
||||
//if (Name != null) list.Add(Name); //TODO: fix
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "TextureBase: " + Name;
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class Texture : TextureBase
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get { return 144; }
|
||||
}
|
||||
|
||||
// structure data
|
||||
public uint Unknown_40h { get; set; }
|
||||
public uint Unknown_44h { get; set; } // 0x00000000
|
||||
public uint Unknown_48h { get; set; }
|
||||
public uint Unknown_4Ch { get; set; } // 0x00000000
|
||||
public ushort Width { get; set; }
|
||||
public ushort Height { get; set; }
|
||||
public ushort Unknown_54h { get; set; } // 0x0001
|
||||
public ushort Stride { get; set; }
|
||||
public TextureFormat Format { get; set; }
|
||||
public byte Unknown_5Ch { get; set; } // 0x00
|
||||
public byte Levels { get; set; }
|
||||
public ushort Unknown_5Eh { get; set; } // 0x0000
|
||||
public uint Unknown_60h { get; set; } // 0x00000000
|
||||
public uint Unknown_64h { get; set; } // 0x00000000
|
||||
public uint Unknown_68h { get; set; } // 0x00000000
|
||||
public uint Unknown_6Ch { get; set; } // 0x00000000
|
||||
public ulong DataPointer { get; set; }
|
||||
public uint Unknown_78h { get; set; } // 0x00000000
|
||||
public uint Unknown_7Ch { get; set; } // 0x00000000
|
||||
public uint Unknown_80h { get; set; } // 0x00000000
|
||||
public uint Unknown_84h { get; set; } // 0x00000000
|
||||
public uint Unknown_88h { get; set; } // 0x00000000
|
||||
public uint Unknown_8Ch { get; set; } // 0x00000000
|
||||
|
||||
// reference data
|
||||
public TextureData Data { get; set; }
|
||||
|
||||
public long MemoryUsage
|
||||
{
|
||||
get
|
||||
{
|
||||
long val = 0;
|
||||
if (Data != null)
|
||||
{
|
||||
val += Data.FullData.LongLength;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
base.Read(reader, parameters);
|
||||
|
||||
// read structure data
|
||||
this.Unknown_40h = reader.ReadUInt32();
|
||||
this.Unknown_44h = reader.ReadUInt32();
|
||||
this.Unknown_48h = reader.ReadUInt32();
|
||||
this.Unknown_4Ch = reader.ReadUInt32();
|
||||
this.Width = reader.ReadUInt16();
|
||||
this.Height = reader.ReadUInt16();
|
||||
this.Unknown_54h = reader.ReadUInt16();
|
||||
this.Stride = reader.ReadUInt16();
|
||||
this.Format = (TextureFormat)reader.ReadUInt32();
|
||||
this.Unknown_5Ch = reader.ReadByte();
|
||||
this.Levels = reader.ReadByte();
|
||||
this.Unknown_5Eh = reader.ReadUInt16();
|
||||
this.Unknown_60h = reader.ReadUInt32();
|
||||
this.Unknown_64h = reader.ReadUInt32();
|
||||
this.Unknown_68h = reader.ReadUInt32();
|
||||
this.Unknown_6Ch = reader.ReadUInt32();
|
||||
this.DataPointer = reader.ReadUInt64();
|
||||
this.Unknown_78h = reader.ReadUInt32();
|
||||
this.Unknown_7Ch = reader.ReadUInt32();
|
||||
this.Unknown_80h = reader.ReadUInt32();
|
||||
this.Unknown_84h = reader.ReadUInt32();
|
||||
this.Unknown_88h = reader.ReadUInt32();
|
||||
this.Unknown_8Ch = reader.ReadUInt32();
|
||||
|
||||
// read reference data
|
||||
this.Data = reader.ReadBlockAt<TextureData>(
|
||||
this.DataPointer, // offset
|
||||
this.Format,
|
||||
this.Width,
|
||||
this.Height,
|
||||
this.Levels,
|
||||
this.Stride
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data-block to a stream.
|
||||
/// </summary>
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
base.Write(writer, parameters);
|
||||
|
||||
this.DataPointer = (ulong)this.Data.FilePosition;
|
||||
|
||||
// write structure data
|
||||
writer.Write(this.Unknown_40h);
|
||||
writer.Write(this.Unknown_44h);
|
||||
writer.Write(this.Unknown_48h);
|
||||
writer.Write(this.Unknown_4Ch);
|
||||
writer.Write(this.Width);
|
||||
writer.Write(this.Height);
|
||||
writer.Write(this.Unknown_54h);
|
||||
writer.Write(this.Stride);
|
||||
writer.Write((uint)this.Format);
|
||||
writer.Write(this.Unknown_5Ch);
|
||||
writer.Write(this.Levels);
|
||||
writer.Write(this.Unknown_5Eh);
|
||||
writer.Write(this.Unknown_60h);
|
||||
writer.Write(this.Unknown_64h);
|
||||
writer.Write(this.Unknown_68h);
|
||||
writer.Write(this.Unknown_6Ch);
|
||||
writer.Write(this.DataPointer);
|
||||
writer.Write(this.Unknown_78h);
|
||||
writer.Write(this.Unknown_7Ch);
|
||||
writer.Write(this.Unknown_80h);
|
||||
writer.Write(this.Unknown_84h);
|
||||
writer.Write(this.Unknown_88h);
|
||||
writer.Write(this.Unknown_8Ch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of data blocks which are referenced by this block.
|
||||
/// </summary>
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>(base.GetReferences());
|
||||
list.Add(Data);
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Texture: " + Width.ToString() + "x" + Height.ToString() + ": " + Name;
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class TextureData : ResourceGraphicsBlock
|
||||
{
|
||||
public override long BlockLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return FullData.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] FullData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
uint format = Convert.ToUInt32(parameters[0]);
|
||||
int Width = Convert.ToInt32(parameters[1]);
|
||||
int Height = Convert.ToInt32(parameters[2]);
|
||||
int Levels = Convert.ToInt32(parameters[3]);
|
||||
int Stride = Convert.ToInt32(parameters[4]);
|
||||
|
||||
int fullLength = 0;
|
||||
int length = Stride * Height;
|
||||
for (int i = 0; i < Levels; i++)
|
||||
{
|
||||
fullLength += length;
|
||||
length /= 4;
|
||||
}
|
||||
|
||||
FullData = reader.ReadBytes(fullLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data-block to a stream.
|
||||
/// </summary>
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
writer.Write(FullData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum TextureFormat : uint
|
||||
{
|
||||
D3DFMT_A8R8G8B8 = 21,
|
||||
D3DFMT_A1R5G5B5 = 25,
|
||||
D3DFMT_A8 = 28,
|
||||
D3DFMT_A8B8G8R8 = 32,
|
||||
D3DFMT_L8 = 50,
|
||||
|
||||
// fourCC
|
||||
D3DFMT_DXT1 = 0x31545844,
|
||||
D3DFMT_DXT3 = 0x33545844,
|
||||
D3DFMT_DXT5 = 0x35545844,
|
||||
D3DFMT_ATI1 = 0x31495441,
|
||||
D3DFMT_ATI2 = 0x32495441,
|
||||
D3DFMT_BC7 = 0x20374342,
|
||||
|
||||
//UNKNOWN
|
||||
}
|
||||
|
||||
}
|
116
CodeWalker.Core/GameFiles/Resources/VehicleRecord.cs
Normal file
116
CodeWalker.Core/GameFiles/Resources/VehicleRecord.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
|
||||
public class VehicleRecordList : ResourceFileBase
|
||||
{
|
||||
public override long BlockLength => 0x20;
|
||||
|
||||
public ResourceSimpleList64<VehicleRecordEntry> Entries;
|
||||
|
||||
public VehicleRecordList()
|
||||
{
|
||||
this.Entries = new ResourceSimpleList64<VehicleRecordEntry>();
|
||||
}
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
base.Read(reader, parameters);
|
||||
|
||||
this.Entries = reader.ReadBlock<ResourceSimpleList64<VehicleRecordEntry>>();
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
base.Write(writer, parameters);
|
||||
|
||||
writer.WriteBlock(this.Entries);
|
||||
}
|
||||
|
||||
public override Tuple<long, IResourceBlock>[] GetParts()
|
||||
{
|
||||
return new Tuple<long, IResourceBlock>[] {
|
||||
new Tuple<long, IResourceBlock>(16, Entries)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class VehicleRecordEntry : ResourceSystemBlock
|
||||
{
|
||||
// this looks exactly like an rrr entry:
|
||||
// -> http://www.gtamodding.com/wiki/Carrec
|
||||
|
||||
public override long BlockLength => 0x20;
|
||||
|
||||
// structure data
|
||||
public uint Time;
|
||||
public short VelocityX;
|
||||
public short VelocityY;
|
||||
public short VelocityZ;
|
||||
public sbyte RightX;
|
||||
public sbyte RightY;
|
||||
public sbyte RightZ;
|
||||
public sbyte TopX;
|
||||
public sbyte TopY;
|
||||
public sbyte TopZ;
|
||||
public byte SteeringAngle;
|
||||
public byte GasPedalPower;
|
||||
public byte BrakePedalPower;
|
||||
public byte HandbrakeUsed;
|
||||
public float PositionX;
|
||||
public float PositionY;
|
||||
public float PositionZ;
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
// read structure data
|
||||
this.Time = reader.ReadUInt32();
|
||||
this.VelocityX = reader.ReadInt16();
|
||||
this.VelocityY = reader.ReadInt16();
|
||||
this.VelocityZ = reader.ReadInt16();
|
||||
this.RightX = (sbyte)reader.ReadByte();
|
||||
this.RightY = (sbyte)reader.ReadByte();
|
||||
this.RightZ = (sbyte)reader.ReadByte();
|
||||
this.TopX = (sbyte)reader.ReadByte();
|
||||
this.TopY = (sbyte)reader.ReadByte();
|
||||
this.TopZ = (sbyte)reader.ReadByte();
|
||||
this.SteeringAngle = reader.ReadByte();
|
||||
this.GasPedalPower = reader.ReadByte();
|
||||
this.BrakePedalPower = reader.ReadByte();
|
||||
this.HandbrakeUsed = reader.ReadByte();
|
||||
this.PositionX = reader.ReadSingle();
|
||||
this.PositionY = reader.ReadSingle();
|
||||
this.PositionZ = reader.ReadSingle();
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
// write structure data
|
||||
writer.Write(this.Time);
|
||||
writer.Write(this.VelocityX);
|
||||
writer.Write(this.VelocityY);
|
||||
writer.Write(this.VelocityZ);
|
||||
writer.Write(this.RightX);
|
||||
writer.Write(this.RightY);
|
||||
writer.Write(this.RightZ);
|
||||
writer.Write(this.TopX);
|
||||
writer.Write(this.TopY);
|
||||
writer.Write(this.TopZ);
|
||||
writer.Write(this.SteeringAngle);
|
||||
writer.Write(this.GasPedalPower);
|
||||
writer.Write(this.BrakePedalPower);
|
||||
writer.Write(this.HandbrakeUsed);
|
||||
writer.Write(this.PositionX);
|
||||
writer.Write(this.PositionY);
|
||||
writer.Write(this.PositionZ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
62
CodeWalker.Core/GameFiles/Resources/VertexType.cs
Normal file
62
CodeWalker.Core/GameFiles/Resources/VertexType.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
|
||||
|
||||
public enum VertexType : uint
|
||||
{
|
||||
Default = 89, //PNCT
|
||||
DefaultEx = 16473, //PNCTX
|
||||
PNCCT = 121,
|
||||
PNCCTTTT = 1017,
|
||||
PCCNCCTTX = 16639,
|
||||
PCCNCCT = 127,
|
||||
PNCTTTX = 16857,
|
||||
PNCTTX = 16601,
|
||||
PNCTTTX_2 = 19545,
|
||||
PNCTTTX_3 = 17113,
|
||||
PNCCTTX = 16633,
|
||||
PNCCTTX_2 = 17017,
|
||||
PNCCTTTX = 17145,
|
||||
PCCNCCTX = 16511,
|
||||
PCCNCTX = 16479,
|
||||
PCCNCT = 95,
|
||||
PNCCTT = 249,
|
||||
PNCCTX = 16505,
|
||||
PCT = 81,
|
||||
PT = 65,
|
||||
PTT = 193,
|
||||
PNC = 25,
|
||||
PC = 17,
|
||||
PCC = 7,
|
||||
PCCH2H4 = 2147500121, //0x80004059 (16473 + 0x80000000) DefaultEx Cloth?
|
||||
PNCH2 = 2147483737, //0x80000059 (89 + 0x80000000) Default Cloth?
|
||||
PNCTTTTX = 19673, //normal_spec_detail_dpm_vertdecal_tnt
|
||||
PNCTTTT = 985,
|
||||
PCCNCCTT = 255,
|
||||
PCTT = 209,
|
||||
PCCCCT = 119,
|
||||
PCCNC = 31,
|
||||
PCCNCTT = 223,
|
||||
PCCNCTTX = 16607,
|
||||
PCCNCTTT = 479,
|
||||
PNCTT = 217,
|
||||
PNCTTT = 473,
|
||||
}
|
||||
|
||||
|
||||
//vertex data to be used by the editor. TODO: maybe move somewhere else.
|
||||
public struct EditorVertex
|
||||
{
|
||||
public Vector3 Position;
|
||||
public uint Colour;
|
||||
}
|
||||
|
||||
|
||||
}
|
107
CodeWalker.Core/GameFiles/Resources/WaypointRecord.cs
Normal file
107
CodeWalker.Core/GameFiles/Resources/WaypointRecord.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
|
||||
public class WaypointRecordList : ResourceFileBase
|
||||
{
|
||||
public override long BlockLength => 0x30;
|
||||
|
||||
public uint Unknown_10h; // 0x00000000
|
||||
public uint Unknown_14h; // 0x00000000
|
||||
public ulong EntriesPointer;
|
||||
public uint EntriesCount;
|
||||
public uint Unknown_24h; // 0x00000000
|
||||
public uint Unknown_28h; // 0x00000000
|
||||
public uint Unknown_2Ch; // 0x00000000
|
||||
|
||||
public ResourceSimpleArray<WaypointRecordEntry> Entries;
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
base.Read(reader, parameters);
|
||||
|
||||
this.Unknown_10h = reader.ReadUInt32();
|
||||
this.Unknown_14h = reader.ReadUInt32();
|
||||
this.EntriesPointer = reader.ReadUInt64();
|
||||
this.EntriesCount = reader.ReadUInt32();
|
||||
this.Unknown_24h = reader.ReadUInt32();
|
||||
this.Unknown_28h = reader.ReadUInt32();
|
||||
this.Unknown_2Ch = reader.ReadUInt32();
|
||||
|
||||
this.Entries = reader.ReadBlockAt<ResourceSimpleArray<WaypointRecordEntry>>(
|
||||
this.EntriesPointer, // offset
|
||||
this.EntriesCount
|
||||
);
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
base.Write(writer, parameters);
|
||||
|
||||
//// update structure data
|
||||
//this.EntriesPointer = (ulong)(this.Entries?.Position ?? 0);
|
||||
//this.EntriesCount = (uint)(this.Entries?.Count ?? 0);
|
||||
|
||||
// write structure data
|
||||
writer.Write(this.Unknown_10h);
|
||||
writer.Write(this.Unknown_14h);
|
||||
writer.Write(this.EntriesPointer);
|
||||
writer.Write(this.EntriesCount);
|
||||
writer.Write(this.Unknown_24h);
|
||||
writer.Write(this.Unknown_28h);
|
||||
writer.Write(this.Unknown_2Ch);
|
||||
}
|
||||
|
||||
public override IResourceBlock[] GetReferences()
|
||||
{
|
||||
var list = new List<IResourceBlock>(base.GetReferences());
|
||||
if (Entries != null) list.Add(Entries);
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class WaypointRecordEntry : ResourceSystemBlock
|
||||
{
|
||||
public override long BlockLength => 20;
|
||||
|
||||
public float PositionX;
|
||||
public float PositionY;
|
||||
public float PositionZ;
|
||||
public ushort Unk0;
|
||||
public ushort Unk1;
|
||||
public ushort Unk2;
|
||||
public ushort Unk3;
|
||||
|
||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||
{
|
||||
// read structure data
|
||||
this.PositionX = reader.ReadSingle();
|
||||
this.PositionY = reader.ReadSingle();
|
||||
this.PositionZ = reader.ReadSingle();
|
||||
this.Unk0 = reader.ReadUInt16();
|
||||
this.Unk1 = reader.ReadUInt16();
|
||||
this.Unk2 = reader.ReadUInt16();
|
||||
this.Unk3 = reader.ReadUInt16();
|
||||
}
|
||||
|
||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||
{
|
||||
// write structure data
|
||||
writer.Write(this.PositionX);
|
||||
writer.Write(this.PositionY);
|
||||
writer.Write(this.PositionZ);
|
||||
writer.Write(this.Unk0);
|
||||
writer.Write(this.Unk1);
|
||||
writer.Write(this.Unk2);
|
||||
writer.Write(this.Unk3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
2562
CodeWalker.Core/GameFiles/RpfFile.cs
Normal file
2562
CodeWalker.Core/GameFiles/RpfFile.cs
Normal file
File diff suppressed because it is too large
Load Diff
492
CodeWalker.Core/GameFiles/RpfManager.cs
Normal file
492
CodeWalker.Core/GameFiles/RpfManager.cs
Normal file
@ -0,0 +1,492 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public class RpfManager
|
||||
{
|
||||
//for caching and management of RPF file data.
|
||||
|
||||
public string Folder { get; private set; }
|
||||
public string[] ExcludePaths { get; set; }
|
||||
public bool EnableMods { get; set; }
|
||||
public Action<string> UpdateStatus { get; private set; }
|
||||
public Action<string> ErrorLog { get; private set; }
|
||||
|
||||
public List<RpfFile> BaseRpfs { get; private set; }
|
||||
public List<RpfFile> ModRpfs { get; private set; }
|
||||
public List<RpfFile> DlcRpfs { get; private set; }
|
||||
public List<RpfFile> AllRpfs { get; private set; }
|
||||
public List<RpfFile> DlcNoModRpfs { get; private set; }
|
||||
public List<RpfFile> AllNoModRpfs { get; private set; }
|
||||
public Dictionary<string, RpfFile> RpfDict { get; private set; }
|
||||
public Dictionary<string, RpfEntry> EntryDict { get; private set; }
|
||||
public Dictionary<string, RpfFile> ModRpfDict { get; private set; }
|
||||
public Dictionary<string, RpfEntry> ModEntryDict { get; private set; }
|
||||
|
||||
public volatile bool IsInited = false;
|
||||
|
||||
public void Init(string folder, Action<string> updateStatus, Action<string> errorLog, bool rootOnly = false, bool buildIndex = true)
|
||||
{
|
||||
UpdateStatus = updateStatus;
|
||||
ErrorLog = errorLog;
|
||||
|
||||
string replpath = folder + "\\";
|
||||
var sopt = rootOnly ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories;
|
||||
string[] allfiles = Directory.GetFiles(folder, "*.rpf", sopt);
|
||||
|
||||
BaseRpfs = new List<RpfFile>();
|
||||
ModRpfs = new List<RpfFile>();
|
||||
DlcRpfs = new List<RpfFile>();
|
||||
AllRpfs = new List<RpfFile>();
|
||||
DlcNoModRpfs = new List<RpfFile>();
|
||||
AllNoModRpfs = new List<RpfFile>();
|
||||
RpfDict = new Dictionary<string, RpfFile>();
|
||||
EntryDict = new Dictionary<string, RpfEntry>();
|
||||
ModRpfDict = new Dictionary<string, RpfFile>();
|
||||
ModEntryDict = new Dictionary<string, RpfEntry>();
|
||||
|
||||
foreach (string rpfpath in allfiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
RpfFile rf = new RpfFile(rpfpath, rpfpath.Replace(replpath, ""));
|
||||
|
||||
if (ExcludePaths != null)
|
||||
{
|
||||
bool excl = false;
|
||||
for (int i = 0; i < ExcludePaths.Length; i++)
|
||||
{
|
||||
if (rf.Path.StartsWith(ExcludePaths[i]))
|
||||
{
|
||||
excl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (excl) continue; //skip files in exclude paths.
|
||||
}
|
||||
|
||||
rf.ScanStructure(updateStatus, errorLog);
|
||||
|
||||
AddRpfFile(rf, false, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorLog(rpfpath + ": " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
if (buildIndex)
|
||||
{
|
||||
updateStatus("Building jenkindex...");
|
||||
BuildBaseJenkIndex();
|
||||
}
|
||||
|
||||
updateStatus("Scan complete");
|
||||
|
||||
IsInited = true;
|
||||
}
|
||||
|
||||
public void Init(List<RpfFile> allRpfs)
|
||||
{
|
||||
//fast init used by RPF explorer's File cache
|
||||
AllRpfs = allRpfs;
|
||||
|
||||
BaseRpfs = new List<RpfFile>();
|
||||
ModRpfs = new List<RpfFile>();
|
||||
DlcRpfs = new List<RpfFile>();
|
||||
DlcNoModRpfs = new List<RpfFile>();
|
||||
AllNoModRpfs = new List<RpfFile>();
|
||||
RpfDict = new Dictionary<string, RpfFile>();
|
||||
EntryDict = new Dictionary<string, RpfEntry>();
|
||||
ModRpfDict = new Dictionary<string, RpfFile>();
|
||||
ModEntryDict = new Dictionary<string, RpfEntry>();
|
||||
foreach (var rpf in allRpfs)
|
||||
{
|
||||
RpfDict[rpf.Path] = rpf;
|
||||
if (rpf.AllEntries == null) continue;
|
||||
foreach (var entry in rpf.AllEntries)
|
||||
{
|
||||
EntryDict[entry.Path] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
BuildBaseJenkIndex();
|
||||
|
||||
IsInited = true;
|
||||
}
|
||||
|
||||
|
||||
private void AddRpfFile(RpfFile file, bool isdlc, bool ismod)
|
||||
{
|
||||
isdlc = isdlc || (file.NameLower == "dlc.rpf") || (file.NameLower == "update.rpf");
|
||||
ismod = ismod || (file.Path.StartsWith("mods\\"));
|
||||
|
||||
if (file.AllEntries != null)
|
||||
{
|
||||
AllRpfs.Add(file);
|
||||
if (!ismod)
|
||||
{
|
||||
AllNoModRpfs.Add(file);
|
||||
}
|
||||
if (isdlc)
|
||||
{
|
||||
DlcRpfs.Add(file);
|
||||
if (!ismod)
|
||||
{
|
||||
DlcNoModRpfs.Add(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ismod)
|
||||
{
|
||||
ModRpfs.Add(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseRpfs.Add(file);
|
||||
}
|
||||
}
|
||||
if (ismod)
|
||||
{
|
||||
ModRpfDict[file.Path.Substring(5)] = file;
|
||||
}
|
||||
|
||||
RpfDict[file.Path] = file;
|
||||
|
||||
foreach (RpfEntry entry in file.AllEntries)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(entry.Name))
|
||||
{
|
||||
if (ismod)
|
||||
{
|
||||
ModEntryDict[entry.Path] = entry;
|
||||
ModEntryDict[entry.Path.Substring(5)] = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
EntryDict[entry.Path] = entry;
|
||||
}
|
||||
|
||||
if (entry is RpfFileEntry)
|
||||
{
|
||||
RpfFileEntry fentry = entry as RpfFileEntry;
|
||||
entry.NameHash = JenkHash.GenHash(entry.NameLower);
|
||||
int ind = entry.NameLower.LastIndexOf('.');
|
||||
entry.ShortNameHash = (ind > 0) ? JenkHash.GenHash(entry.NameLower.Substring(0, ind)) : entry.NameHash;
|
||||
if (entry.ShortNameHash != 0)
|
||||
{
|
||||
//EntryHashDict[entry.ShortNameHash] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
file.LastError = ex.ToString();
|
||||
file.LastException = ex;
|
||||
ErrorLog(entry.Path + ": " + ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file.Children != null)
|
||||
{
|
||||
foreach (RpfFile cfile in file.Children)
|
||||
{
|
||||
AddRpfFile(cfile, isdlc, ismod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public RpfFile FindRpfFile(string path)
|
||||
{
|
||||
RpfFile file = null; //check the dictionary
|
||||
|
||||
if (EnableMods && ModRpfDict.TryGetValue(path, out file))
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
if (RpfDict.TryGetValue(path, out file))
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
string lpath = path.ToLowerInvariant(); //try look at names etc
|
||||
foreach (RpfFile tfile in AllRpfs)
|
||||
{
|
||||
if (tfile.NameLower == lpath)
|
||||
{
|
||||
return tfile;
|
||||
}
|
||||
if (tfile.Path == lpath)
|
||||
{
|
||||
return tfile;
|
||||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
public RpfEntry GetEntry(string path)
|
||||
{
|
||||
RpfEntry entry;
|
||||
string pathl = path.ToLowerInvariant();
|
||||
if (EnableMods && ModEntryDict.TryGetValue(pathl, out entry))
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
EntryDict.TryGetValue(pathl, out entry);
|
||||
if (entry == null)
|
||||
{
|
||||
pathl = pathl.Replace("/", "\\");
|
||||
pathl = pathl.Replace("common:", "common.rpf");
|
||||
if (EnableMods && ModEntryDict.TryGetValue(pathl, out entry))
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
EntryDict.TryGetValue(pathl, out entry);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
public byte[] GetFileData(string path)
|
||||
{
|
||||
byte[] data = null;
|
||||
RpfFileEntry entry = GetEntry(path) as RpfFileEntry;
|
||||
if (entry != null)
|
||||
{
|
||||
data = entry.File.ExtractFile(entry);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
public string GetFileUTF8Text(string path)
|
||||
{
|
||||
byte[] bytes = GetFileData(path);
|
||||
if (bytes == null)
|
||||
{ return string.Empty; } //file not found..
|
||||
if ((bytes.Length > 3) && (bytes[0] == 0xEF) && (bytes[1] == 0xBB) && (bytes[2] == 0xBF))
|
||||
{
|
||||
byte[] newb = new byte[bytes.Length - 3];
|
||||
for (int i = 3; i < bytes.Length; i++)
|
||||
{
|
||||
newb[i - 3] = bytes[i];
|
||||
}
|
||||
bytes = newb; //trim starting 3 "magic" bytes?
|
||||
}
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
public XmlDocument GetFileXml(string path)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
string text = GetFileUTF8Text(path);
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
doc.LoadXml(text);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
public T GetFile<T>(string path) where T : class, PackedFile, new()
|
||||
{
|
||||
T file = null;
|
||||
byte[] data = null;
|
||||
RpfFileEntry entry = GetEntry(path) as RpfFileEntry;
|
||||
if (entry != null)
|
||||
{
|
||||
data = entry.File.ExtractFile(entry);
|
||||
}
|
||||
if (data != null)
|
||||
{
|
||||
file = new T();
|
||||
file.Load(data, entry);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
public T GetFile<T>(RpfEntry e) where T : class, PackedFile, new()
|
||||
{
|
||||
T file = null;
|
||||
byte[] data = null;
|
||||
RpfFileEntry entry = e as RpfFileEntry;
|
||||
if (entry != null)
|
||||
{
|
||||
data = entry.File.ExtractFile(entry);
|
||||
}
|
||||
if (data != null)
|
||||
{
|
||||
file = new T();
|
||||
file.Load(data, entry);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
public bool LoadFile<T>(T file, RpfEntry e) where T : class, PackedFile
|
||||
{
|
||||
byte[] data = null;
|
||||
RpfFileEntry entry = e as RpfFileEntry;
|
||||
if (entry != null)
|
||||
{
|
||||
data = entry.File.ExtractFile(entry);
|
||||
}
|
||||
if (data != null)
|
||||
{
|
||||
file.Load(data, entry);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void BuildBaseJenkIndex()
|
||||
{
|
||||
JenkIndex.Clear();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (RpfFile file in AllRpfs)
|
||||
{
|
||||
try
|
||||
{
|
||||
JenkIndex.Ensure(file.Name);
|
||||
foreach (RpfEntry entry in file.AllEntries)
|
||||
{
|
||||
var nlow = entry.NameLower;
|
||||
if (string.IsNullOrEmpty(nlow)) continue;
|
||||
//JenkIndex.Ensure(entry.Name);
|
||||
//JenkIndex.Ensure(nlow);
|
||||
int ind = nlow.LastIndexOf('.');
|
||||
if (ind > 0)
|
||||
{
|
||||
JenkIndex.Ensure(entry.Name.Substring(0, ind));
|
||||
JenkIndex.Ensure(nlow.Substring(0, ind));
|
||||
|
||||
//if (ind < entry.Name.Length - 2)
|
||||
//{
|
||||
// JenkIndex.Ensure(entry.Name.Substring(0, ind) + ".#" + entry.Name.Substring(ind + 2));
|
||||
// JenkIndex.Ensure(entry.NameLower.Substring(0, ind) + ".#" + entry.NameLower.Substring(ind + 2));
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
JenkIndex.Ensure(entry.Name);
|
||||
JenkIndex.Ensure(nlow);
|
||||
}
|
||||
if (nlow.EndsWith(".ydr") || nlow.EndsWith(".yft"))
|
||||
{
|
||||
var sname = nlow.Substring(0, nlow.Length - 4);
|
||||
JenkIndex.Ensure(sname + "_lod");
|
||||
JenkIndex.Ensure(sname + "_loda");
|
||||
JenkIndex.Ensure(sname + "_lodb");
|
||||
}
|
||||
if (nlow.EndsWith(".ydd"))
|
||||
{
|
||||
if (nlow.EndsWith("_children.ydd"))
|
||||
{
|
||||
var strn = nlow.Substring(0, nlow.Length - 13);
|
||||
JenkIndex.Ensure(strn);
|
||||
JenkIndex.Ensure(strn + "_lod");
|
||||
JenkIndex.Ensure(strn + "_loda");
|
||||
JenkIndex.Ensure(strn + "_lodb");
|
||||
}
|
||||
var idx = nlow.LastIndexOf('_');
|
||||
if (idx > 0)
|
||||
{
|
||||
var str1 = nlow.Substring(0, idx);
|
||||
var idx2 = str1.LastIndexOf('_');
|
||||
if (idx2 > 0)
|
||||
{
|
||||
var str2 = str1.Substring(0, idx2);
|
||||
JenkIndex.Ensure(str2 + "_lod");
|
||||
var maxi = 100;
|
||||
for (int i = 1; i <= maxi; i++)
|
||||
{
|
||||
var str3 = str2 + "_" + i.ToString().PadLeft(2, '0');
|
||||
//JenkIndex.Ensure(str3);
|
||||
JenkIndex.Ensure(str3 + "_lod");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nlow.EndsWith(".awc")) //create audio container path hashes...
|
||||
{
|
||||
string[] parts = entry.Path.Split('\\');
|
||||
int pl = parts.Length;
|
||||
if (pl > 2)
|
||||
{
|
||||
string fn = parts[pl - 1];
|
||||
string fd = parts[pl - 2];
|
||||
string hpath = fn.Substring(0, fn.Length - 4);
|
||||
if (fd.EndsWith(".rpf"))
|
||||
{
|
||||
fd = fd.Substring(0, fd.Length - 4);
|
||||
}
|
||||
hpath = fd + "/" + hpath;
|
||||
if (parts[pl - 3] != "sfx")
|
||||
{ }//no hit
|
||||
|
||||
JenkIndex.Ensure(hpath);
|
||||
}
|
||||
}
|
||||
if (nlow.EndsWith(".nametable"))
|
||||
{
|
||||
RpfBinaryFileEntry binfe = entry as RpfBinaryFileEntry;
|
||||
if (binfe != null)
|
||||
{
|
||||
byte[] data = file.ExtractFile(binfe);
|
||||
if (data != null)
|
||||
{
|
||||
sb.Clear();
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
byte c = data[i];
|
||||
if (c == 0)
|
||||
{
|
||||
string str = sb.ToString();
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
{
|
||||
string strl = str.ToLowerInvariant();
|
||||
//JenkIndex.Ensure(str);
|
||||
JenkIndex.Ensure(strl);
|
||||
|
||||
////DirMod_Sounds_ entries apparently can be used to infer SP audio strings
|
||||
////no luck here yet though
|
||||
//if (strl.StartsWith("dirmod_sounds_") && (strl.Length > 14))
|
||||
//{
|
||||
// strl = strl.Substring(14);
|
||||
// JenkIndex.Ensure(strl);
|
||||
//}
|
||||
}
|
||||
sb.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
//failing silently!! not so good really
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
483
CodeWalker.Core/GameFiles/Utils/Data.cs
Normal file
483
CodeWalker.Core/GameFiles/Utils/Data.cs
Normal file
@ -0,0 +1,483 @@
|
||||
/*
|
||||
Copyright(c) 2015 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//shamelessly stolen
|
||||
|
||||
|
||||
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public enum Endianess
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
|
||||
public enum DataType
|
||||
{
|
||||
Byte = 0,
|
||||
Int16 = 1,
|
||||
Int32 = 2,
|
||||
Int64 = 3,
|
||||
Uint16 = 4,
|
||||
Uint32 = 5,
|
||||
Uint64 = 6,
|
||||
Float = 7,
|
||||
Double = 8,
|
||||
String = 9,
|
||||
}
|
||||
|
||||
public class DataReader
|
||||
{
|
||||
private Stream baseStream;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the endianess of the underlying stream.
|
||||
/// </summary>
|
||||
public Endianess Endianess
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the underlying stream.
|
||||
/// </summary>
|
||||
public virtual long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position within the underlying stream.
|
||||
/// </summary>
|
||||
public virtual long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
baseStream.Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new data reader for the specified stream.
|
||||
/// </summary>
|
||||
public DataReader(Stream stream, Endianess endianess = Endianess.LittleEndian)
|
||||
{
|
||||
this.baseStream = stream;
|
||||
this.Endianess = endianess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from the underlying stream. This is the only method that directly accesses
|
||||
/// the data in the underlying stream.
|
||||
/// </summary>
|
||||
protected virtual byte[] ReadFromStream(int count, bool ignoreEndianess = false)
|
||||
{
|
||||
var buffer = new byte[count];
|
||||
baseStream.Read(buffer, 0, count);
|
||||
|
||||
// handle endianess
|
||||
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
||||
{
|
||||
Array.Reverse(buffer);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte.
|
||||
/// </summary>
|
||||
public byte ReadByte()
|
||||
{
|
||||
return ReadFromStream(1)[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sequence of bytes.
|
||||
/// </summary>
|
||||
public byte[] ReadBytes(int count)
|
||||
{
|
||||
return ReadFromStream(count, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a signed 16-bit value.
|
||||
/// </summary>
|
||||
public short ReadInt16()
|
||||
{
|
||||
return BitConverter.ToInt16(ReadFromStream(2), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a signed 32-bit value.
|
||||
/// </summary>
|
||||
public int ReadInt32()
|
||||
{
|
||||
return BitConverter.ToInt32(ReadFromStream(4), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a signed 64-bit value.
|
||||
/// </summary>
|
||||
public long ReadInt64()
|
||||
{
|
||||
return BitConverter.ToInt64(ReadFromStream(8), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an unsigned 16-bit value.
|
||||
/// </summary>
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
return BitConverter.ToUInt16(ReadFromStream(2), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an unsigned 32-bit value.
|
||||
/// </summary>
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
return BitConverter.ToUInt32(ReadFromStream(4), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an unsigned 64-bit value.
|
||||
/// </summary>
|
||||
public ulong ReadUInt64()
|
||||
{
|
||||
return BitConverter.ToUInt64(ReadFromStream(8), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a single precision floating point value.
|
||||
/// </summary>
|
||||
public float ReadSingle()
|
||||
{
|
||||
return BitConverter.ToSingle(ReadFromStream(4), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a double precision floating point value.
|
||||
/// </summary>
|
||||
public double ReadDouble()
|
||||
{
|
||||
return BitConverter.ToDouble(ReadFromStream(8), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a string.
|
||||
/// </summary>
|
||||
public string ReadString()
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
var temp = ReadFromStream(1)[0];
|
||||
while (temp != 0)
|
||||
{
|
||||
bytes.Add(temp);
|
||||
temp = ReadFromStream(1)[0];
|
||||
}
|
||||
|
||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
||||
}
|
||||
|
||||
|
||||
public Vector3 ReadVector3()
|
||||
{
|
||||
Vector3 v = new Vector3();
|
||||
v.X = ReadSingle();
|
||||
v.Y = ReadSingle();
|
||||
v.Z = ReadSingle();
|
||||
return v;
|
||||
}
|
||||
public Vector4 ReadVector4()
|
||||
{
|
||||
Vector4 v = new Vector4();
|
||||
v.X = ReadSingle();
|
||||
v.Y = ReadSingle();
|
||||
v.Z = ReadSingle();
|
||||
v.W = ReadSingle();
|
||||
return v;
|
||||
}
|
||||
|
||||
public Matrix ReadMatrix()
|
||||
{
|
||||
Matrix m = new Matrix();
|
||||
m.M11 = ReadSingle();
|
||||
m.M21 = ReadSingle();
|
||||
m.M31 = ReadSingle();
|
||||
m.M41 = ReadSingle();
|
||||
m.M12 = ReadSingle();
|
||||
m.M22 = ReadSingle();
|
||||
m.M32 = ReadSingle();
|
||||
m.M42 = ReadSingle();
|
||||
m.M13 = ReadSingle();
|
||||
m.M23 = ReadSingle();
|
||||
m.M33 = ReadSingle();
|
||||
m.M43 = ReadSingle();
|
||||
m.M14 = ReadSingle();
|
||||
m.M24 = ReadSingle();
|
||||
m.M34 = ReadSingle();
|
||||
m.M44 = ReadSingle();
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//TODO: put this somewhere else...
|
||||
public static uint SizeOf(DataType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case DataType.Byte: return 1;
|
||||
case DataType.Int16: return 2;
|
||||
case DataType.Int32: return 4;
|
||||
case DataType.Int64: return 8;
|
||||
case DataType.Uint16: return 2;
|
||||
case DataType.Uint32: return 4;
|
||||
case DataType.Uint64: return 8;
|
||||
case DataType.Float: return 4;
|
||||
case DataType.Double: return 8;
|
||||
case DataType.String: return 0; //how long is a string..?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class DataWriter
|
||||
{
|
||||
private Stream baseStream;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the endianess of the underlying stream.
|
||||
/// </summary>
|
||||
public Endianess Endianess
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the underlying stream.
|
||||
/// </summary>
|
||||
public virtual long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position within the underlying stream.
|
||||
/// </summary>
|
||||
public virtual long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
baseStream.Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new data writer for the specified stream.
|
||||
/// </summary>
|
||||
public DataWriter(Stream stream, Endianess endianess = Endianess.LittleEndian)
|
||||
{
|
||||
this.baseStream = stream;
|
||||
this.Endianess = endianess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to the underlying stream. This is the only method that directly accesses
|
||||
/// the data in the underlying stream.
|
||||
/// </summary>
|
||||
protected virtual void WriteToStream(byte[] value, bool ignoreEndianess = false)
|
||||
{
|
||||
if (!ignoreEndianess && (Endianess == Endianess.BigEndian))
|
||||
{
|
||||
var buffer = (byte[])value.Clone();
|
||||
Array.Reverse(buffer);
|
||||
baseStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
baseStream.Write(value, 0, value.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a byte.
|
||||
/// </summary>
|
||||
public void Write(byte value)
|
||||
{
|
||||
WriteToStream(new byte[] { value });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a sequence of bytes.
|
||||
/// </summary>
|
||||
public void Write(byte[] value)
|
||||
{
|
||||
WriteToStream(value, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a signed 16-bit value.
|
||||
/// </summary>
|
||||
public void Write(short value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a signed 32-bit value.
|
||||
/// </summary>
|
||||
public void Write(int value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a signed 64-bit value.
|
||||
/// </summary>
|
||||
public void Write(long value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an unsigned 16-bit value.
|
||||
/// </summary>
|
||||
public void Write(ushort value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an unsigned 32-bit value.
|
||||
/// </summary>
|
||||
public void Write(uint value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an unsigned 64-bit value.
|
||||
/// </summary>
|
||||
public void Write(ulong value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a single precision floating point value.
|
||||
/// </summary>
|
||||
public void Write(float value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a double precision floating point value.
|
||||
/// </summary>
|
||||
public void Write(double value)
|
||||
{
|
||||
WriteToStream(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a string.
|
||||
/// </summary>
|
||||
public void Write(string value)
|
||||
{
|
||||
foreach (var c in value)
|
||||
Write((byte)c);
|
||||
Write((byte)0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Write(Vector3 value)
|
||||
{
|
||||
Write(value.X);
|
||||
Write(value.Y);
|
||||
Write(value.Z);
|
||||
}
|
||||
public void Write(Vector4 value)
|
||||
{
|
||||
Write(value.X);
|
||||
Write(value.Y);
|
||||
Write(value.Z);
|
||||
Write(value.W);
|
||||
}
|
||||
|
||||
public void Write(Matrix value)
|
||||
{
|
||||
Write(value.M11);
|
||||
Write(value.M21);
|
||||
Write(value.M31);
|
||||
Write(value.M41);
|
||||
Write(value.M12);
|
||||
Write(value.M22);
|
||||
Write(value.M32);
|
||||
Write(value.M42);
|
||||
Write(value.M13);
|
||||
Write(value.M23);
|
||||
Write(value.M33);
|
||||
Write(value.M43);
|
||||
Write(value.M14);
|
||||
Write(value.M24);
|
||||
Write(value.M34);
|
||||
Write(value.M44);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
429
CodeWalker.Core/GameFiles/Utils/GTACrypto.cs
Normal file
429
CodeWalker.Core/GameFiles/Utils/GTACrypto.cs
Normal file
@ -0,0 +1,429 @@
|
||||
/*
|
||||
Copyright(c) 2015 Neodymium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//shamelessly stolen
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
public class GTACrypto
|
||||
{
|
||||
|
||||
|
||||
public static byte[] DecryptAES(byte[] data)
|
||||
{
|
||||
return DecryptAESData(data, GTA5Keys.PC_AES_KEY);
|
||||
}
|
||||
public static byte[] EncryptAES(byte[] data)
|
||||
{
|
||||
return EncryptAESData(data, GTA5Keys.PC_AES_KEY);
|
||||
}
|
||||
|
||||
public static byte[] DecryptAESData(byte[] data, byte[] key, int rounds = 1)
|
||||
{
|
||||
var rijndael = Rijndael.Create();
|
||||
rijndael.KeySize = 256;
|
||||
rijndael.Key = key;
|
||||
rijndael.BlockSize = 128;
|
||||
rijndael.Mode = CipherMode.ECB;
|
||||
rijndael.Padding = PaddingMode.None;
|
||||
|
||||
var buffer = (byte[])data.Clone();
|
||||
var length = data.Length - data.Length % 16;
|
||||
|
||||
// decrypt...
|
||||
if (length > 0)
|
||||
{
|
||||
var decryptor = rijndael.CreateDecryptor();
|
||||
for (var roundIndex = 0; roundIndex < rounds; roundIndex++)
|
||||
decryptor.TransformBlock(buffer, 0, length, buffer, 0);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
public static byte[] EncryptAESData(byte[] data, byte[] key, int rounds = 1)
|
||||
{
|
||||
var rijndael = Rijndael.Create();
|
||||
rijndael.KeySize = 256;
|
||||
rijndael.Key = key;
|
||||
rijndael.BlockSize = 128;
|
||||
rijndael.Mode = CipherMode.ECB;
|
||||
rijndael.Padding = PaddingMode.None;
|
||||
|
||||
var buffer = (byte[])data.Clone();
|
||||
var length = data.Length - data.Length % 16;
|
||||
|
||||
// encrypt...
|
||||
if (length > 0)
|
||||
{
|
||||
var encryptor = rijndael.CreateEncryptor();
|
||||
for (var roundIndex = 0; roundIndex < rounds; roundIndex++)
|
||||
encryptor.TransformBlock(buffer, 0, length, buffer, 0);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte[] GetNGKey(string name, uint length)
|
||||
{
|
||||
uint hash = GTA5Hash.CalculateHash(name);
|
||||
uint keyidx = (hash + length + (101 - 40)) % 0x65;
|
||||
return GTA5Keys.PC_NG_KEYS[keyidx];
|
||||
}
|
||||
|
||||
|
||||
public static byte[] DecryptNG(byte[] data, string name, uint length)
|
||||
{
|
||||
byte[] key = GetNGKey(name, length);
|
||||
return DecryptNG(data, key);
|
||||
}
|
||||
|
||||
public static byte[] DecryptNG(byte[] data, byte[] key)
|
||||
{
|
||||
var decryptedData = new byte[data.Length];
|
||||
|
||||
var keyuints = new uint[key.Length / 4];
|
||||
Buffer.BlockCopy(key, 0, keyuints, 0, key.Length);
|
||||
|
||||
for (int blockIndex = 0; blockIndex < data.Length / 16; blockIndex++)
|
||||
{
|
||||
var encryptedBlock = new byte[16];
|
||||
Array.Copy(data, 16 * blockIndex, encryptedBlock, 0, 16);
|
||||
var decryptedBlock = DecryptNGBlock(encryptedBlock, keyuints);
|
||||
Array.Copy(decryptedBlock, 0, decryptedData, 16 * blockIndex, 16);
|
||||
}
|
||||
|
||||
if (data.Length % 16 != 0)
|
||||
{
|
||||
var left = data.Length % 16;
|
||||
Buffer.BlockCopy(data, data.Length - left, decryptedData, data.Length - left, left);
|
||||
}
|
||||
|
||||
return decryptedData;
|
||||
}
|
||||
|
||||
public static byte[] DecryptNGBlock(byte[] data, uint[] key)
|
||||
{
|
||||
var buffer = data;
|
||||
|
||||
// prepare key...
|
||||
var subKeys = new uint[17][];
|
||||
for (int i = 0; i < 17; i++)
|
||||
{
|
||||
subKeys[i] = new uint[4];
|
||||
subKeys[i][0] = key[4 * i + 0];
|
||||
subKeys[i][1] = key[4 * i + 1];
|
||||
subKeys[i][2] = key[4 * i + 2];
|
||||
subKeys[i][3] = key[4 * i + 3];
|
||||
}
|
||||
|
||||
buffer = DecryptNGRoundA(buffer, subKeys[0], GTA5Keys.PC_NG_DECRYPT_TABLES[0]);
|
||||
buffer = DecryptNGRoundA(buffer, subKeys[1], GTA5Keys.PC_NG_DECRYPT_TABLES[1]);
|
||||
for (int k = 2; k <= 15; k++)
|
||||
buffer = DecryptNGRoundB(buffer, subKeys[k], GTA5Keys.PC_NG_DECRYPT_TABLES[k]);
|
||||
buffer = DecryptNGRoundA(buffer, subKeys[16], GTA5Keys.PC_NG_DECRYPT_TABLES[16]);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
// round 1,2,16
|
||||
public static byte[] DecryptNGRoundA(byte[] data, uint[] key, uint[][] table)
|
||||
{
|
||||
var x1 =
|
||||
table[0][data[0]] ^
|
||||
table[1][data[1]] ^
|
||||
table[2][data[2]] ^
|
||||
table[3][data[3]] ^
|
||||
key[0];
|
||||
var x2 =
|
||||
table[4][data[4]] ^
|
||||
table[5][data[5]] ^
|
||||
table[6][data[6]] ^
|
||||
table[7][data[7]] ^
|
||||
key[1];
|
||||
var x3 =
|
||||
table[8][data[8]] ^
|
||||
table[9][data[9]] ^
|
||||
table[10][data[10]] ^
|
||||
table[11][data[11]] ^
|
||||
key[2];
|
||||
var x4 =
|
||||
table[12][data[12]] ^
|
||||
table[13][data[13]] ^
|
||||
table[14][data[14]] ^
|
||||
table[15][data[15]] ^
|
||||
key[3];
|
||||
|
||||
var result = new byte[16];
|
||||
Array.Copy(BitConverter.GetBytes(x1), 0, result, 0, 4);
|
||||
Array.Copy(BitConverter.GetBytes(x2), 0, result, 4, 4);
|
||||
Array.Copy(BitConverter.GetBytes(x3), 0, result, 8, 4);
|
||||
Array.Copy(BitConverter.GetBytes(x4), 0, result, 12, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// round 3-15
|
||||
public static byte[] DecryptNGRoundB(byte[] data, uint[] key, uint[][] table)
|
||||
{
|
||||
var x1 =
|
||||
table[0][data[0]] ^
|
||||
table[7][data[7]] ^
|
||||
table[10][data[10]] ^
|
||||
table[13][data[13]] ^
|
||||
key[0];
|
||||
var x2 =
|
||||
table[1][data[1]] ^
|
||||
table[4][data[4]] ^
|
||||
table[11][data[11]] ^
|
||||
table[14][data[14]] ^
|
||||
key[1];
|
||||
var x3 =
|
||||
table[2][data[2]] ^
|
||||
table[5][data[5]] ^
|
||||
table[8][data[8]] ^
|
||||
table[15][data[15]] ^
|
||||
key[2];
|
||||
var x4 =
|
||||
table[3][data[3]] ^
|
||||
table[6][data[6]] ^
|
||||
table[9][data[9]] ^
|
||||
table[12][data[12]] ^
|
||||
key[3];
|
||||
|
||||
//var result = new byte[16];
|
||||
//Array.Copy(BitConverter.GetBytes(x1), 0, result, 0, 4);
|
||||
//Array.Copy(BitConverter.GetBytes(x2), 0, result, 4, 4);
|
||||
//Array.Copy(BitConverter.GetBytes(x3), 0, result, 8, 4);
|
||||
//Array.Copy(BitConverter.GetBytes(x4), 0, result, 12, 4);
|
||||
//return result;
|
||||
|
||||
var result = new byte[16];
|
||||
result[0] = (byte)((x1 >> 0) & 0xFF);
|
||||
result[1] = (byte)((x1 >> 8) & 0xFF);
|
||||
result[2] = (byte)((x1 >> 16) & 0xFF);
|
||||
result[3] = (byte)((x1 >> 24) & 0xFF);
|
||||
result[4] = (byte)((x2 >> 0) & 0xFF);
|
||||
result[5] = (byte)((x2 >> 8) & 0xFF);
|
||||
result[6] = (byte)((x2 >> 16) & 0xFF);
|
||||
result[7] = (byte)((x2 >> 24) & 0xFF);
|
||||
result[8] = (byte)((x3 >> 0) & 0xFF);
|
||||
result[9] = (byte)((x3 >> 8) & 0xFF);
|
||||
result[10] = (byte)((x3 >> 16) & 0xFF);
|
||||
result[11] = (byte)((x3 >> 24) & 0xFF);
|
||||
result[12] = (byte)((x4 >> 0) & 0xFF);
|
||||
result[13] = (byte)((x4 >> 8) & 0xFF);
|
||||
result[14] = (byte)((x4 >> 16) & 0xFF);
|
||||
result[15] = (byte)((x4 >> 24) & 0xFF);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte[] EncryptNG(byte[] data, string name, uint length)
|
||||
{
|
||||
byte[] key = GetNGKey(name, length);
|
||||
return EncryptNG(data, key);
|
||||
}
|
||||
|
||||
public static byte[] EncryptNG(byte[] data, byte[] key)
|
||||
{
|
||||
if ((GTA5Keys.PC_NG_ENCRYPT_TABLES == null) || (GTA5Keys.PC_NG_ENCRYPT_LUTs == null))
|
||||
{
|
||||
throw new Exception("Unable to encrypt - tables not loaded.");
|
||||
}
|
||||
|
||||
var encryptedData = new byte[data.Length];
|
||||
|
||||
var keyuints = new uint[key.Length / 4];
|
||||
Buffer.BlockCopy(key, 0, keyuints, 0, key.Length);
|
||||
|
||||
for (int blockIndex = 0; blockIndex < data.Length / 16; blockIndex++)
|
||||
{
|
||||
byte[] decryptedBlock = new byte[16];
|
||||
Array.Copy(data, 16 * blockIndex, decryptedBlock, 0, 16);
|
||||
byte[] encryptedBlock = EncryptBlock(decryptedBlock, keyuints);
|
||||
Array.Copy(encryptedBlock, 0, encryptedData, 16 * blockIndex, 16);
|
||||
}
|
||||
|
||||
if (data.Length % 16 != 0)
|
||||
{
|
||||
var left = data.Length % 16;
|
||||
Buffer.BlockCopy(data, data.Length - left, encryptedData, data.Length - left, left);
|
||||
}
|
||||
|
||||
return encryptedData;
|
||||
}
|
||||
|
||||
public static byte[] EncryptBlock(byte[] data, uint[] key)
|
||||
{
|
||||
var buffer = data;
|
||||
|
||||
// prepare key...
|
||||
var subKeys = new uint[17][];
|
||||
for (int i = 0; i < 17; i++)
|
||||
{
|
||||
subKeys[i] = new uint[4];
|
||||
subKeys[i][0] = key[4 * i + 0];
|
||||
subKeys[i][1] = key[4 * i + 1];
|
||||
subKeys[i][2] = key[4 * i + 2];
|
||||
subKeys[i][3] = key[4 * i + 3];
|
||||
}
|
||||
|
||||
buffer = EncryptRoundA(buffer, subKeys[16], GTA5Keys.PC_NG_ENCRYPT_TABLES[16]);
|
||||
for (int k = 15; k >= 2; k--)
|
||||
buffer = EncryptRoundB_LUT(buffer, subKeys[k], GTA5Keys.PC_NG_ENCRYPT_LUTs[k]);
|
||||
buffer = EncryptRoundA(buffer, subKeys[1], GTA5Keys.PC_NG_ENCRYPT_TABLES[1]);
|
||||
buffer = EncryptRoundA(buffer, subKeys[0], GTA5Keys.PC_NG_ENCRYPT_TABLES[0]);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static byte[] EncryptRoundA(byte[] data, uint[] key, uint[][] table)
|
||||
{
|
||||
// apply xor to data first...
|
||||
var xorbuf = new byte[16];
|
||||
Buffer.BlockCopy(key, 0, xorbuf, 0, 16);
|
||||
|
||||
var x1 =
|
||||
table[0][data[0] ^ xorbuf[0]] ^
|
||||
table[1][data[1] ^ xorbuf[1]] ^
|
||||
table[2][data[2] ^ xorbuf[2]] ^
|
||||
table[3][data[3] ^ xorbuf[3]];
|
||||
var x2 =
|
||||
table[4][data[4] ^ xorbuf[4]] ^
|
||||
table[5][data[5] ^ xorbuf[5]] ^
|
||||
table[6][data[6] ^ xorbuf[6]] ^
|
||||
table[7][data[7] ^ xorbuf[7]];
|
||||
var x3 =
|
||||
table[8][data[8] ^ xorbuf[8]] ^
|
||||
table[9][data[9] ^ xorbuf[9]] ^
|
||||
table[10][data[10] ^ xorbuf[10]] ^
|
||||
table[11][data[11] ^ xorbuf[11]];
|
||||
var x4 =
|
||||
table[12][data[12] ^ xorbuf[12]] ^
|
||||
table[13][data[13] ^ xorbuf[13]] ^
|
||||
table[14][data[14] ^ xorbuf[14]] ^
|
||||
table[15][data[15] ^ xorbuf[15]];
|
||||
|
||||
var buf = new byte[16];
|
||||
Array.Copy(BitConverter.GetBytes(x1), 0, buf, 0, 4);
|
||||
Array.Copy(BitConverter.GetBytes(x2), 0, buf, 4, 4);
|
||||
Array.Copy(BitConverter.GetBytes(x3), 0, buf, 8, 4);
|
||||
Array.Copy(BitConverter.GetBytes(x4), 0, buf, 12, 4);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static byte[] EncryptRoundA_LUT(byte[] dataOld, uint[] key, GTA5NGLUT[] lut)
|
||||
{
|
||||
var data = (byte[])dataOld.Clone();
|
||||
|
||||
// apply xor to data first...
|
||||
var xorbuf = new byte[16];
|
||||
Buffer.BlockCopy(key, 0, xorbuf, 0, 16);
|
||||
for (int y = 0; y < 16; y++)
|
||||
{
|
||||
data[y] ^= xorbuf[y];
|
||||
}
|
||||
|
||||
return new byte[] {
|
||||
lut[0].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[1].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[2].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[3].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[4].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[5].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[6].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[7].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[8].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)),
|
||||
lut[9].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)),
|
||||
lut[10].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)),
|
||||
lut[11].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)),
|
||||
lut[12].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)),
|
||||
lut[13].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)),
|
||||
lut[14].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)),
|
||||
lut[15].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0))
|
||||
};
|
||||
}
|
||||
|
||||
public static byte[] EncryptRoundB_LUT(byte[] dataOld, uint[] key, GTA5NGLUT[] lut)
|
||||
{
|
||||
var data = (byte[])dataOld.Clone();
|
||||
|
||||
// apply xor to data first...
|
||||
var xorbuf = new byte[16];
|
||||
Buffer.BlockCopy(key, 0, xorbuf, 0, 16);
|
||||
for (int y = 0; y < 16; y++)
|
||||
{
|
||||
data[y] ^= xorbuf[y];
|
||||
}
|
||||
|
||||
return new byte[] {
|
||||
lut[0].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[1].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[2].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)),
|
||||
lut[3].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)),
|
||||
lut[4].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[5].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)),
|
||||
lut[6].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)),
|
||||
lut[7].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[8].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)),
|
||||
lut[9].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)),
|
||||
lut[10].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[11].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[12].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)),
|
||||
lut[13].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)),
|
||||
lut[14].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)),
|
||||
lut[15].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0))};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
1470
CodeWalker.Core/GameFiles/Utils/GTAKeys.cs
Normal file
1470
CodeWalker.Core/GameFiles/Utils/GTAKeys.cs
Normal file
File diff suppressed because it is too large
Load Diff
264
CodeWalker.Core/GameFiles/Utils/Jenk.cs
Normal file
264
CodeWalker.Core/GameFiles/Utils/Jenk.cs
Normal file
@ -0,0 +1,264 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
|
||||
public class JenkHash
|
||||
{
|
||||
public JenkHashInputEncoding Encoding { get; set; }
|
||||
public string Text { get; set; }
|
||||
public int HashInt { get; set; }
|
||||
public uint HashUint { get; set; }
|
||||
public string HashHex { get; set; }
|
||||
|
||||
public JenkHash(string text, JenkHashInputEncoding encoding)
|
||||
{
|
||||
Encoding = encoding;
|
||||
Text = text;
|
||||
HashUint = GenHash(text, encoding);
|
||||
HashInt = (int)HashUint;
|
||||
HashHex = "0x" + HashUint.ToString("X");
|
||||
}
|
||||
|
||||
|
||||
public static uint GenHash(string text, JenkHashInputEncoding encoding)
|
||||
{
|
||||
uint h = 0;
|
||||
byte[] chars;
|
||||
|
||||
switch (encoding)
|
||||
{
|
||||
default:
|
||||
case JenkHashInputEncoding.UTF8:
|
||||
chars = UTF8Encoding.UTF8.GetBytes(text);
|
||||
break;
|
||||
case JenkHashInputEncoding.ASCII:
|
||||
chars = ASCIIEncoding.ASCII.GetBytes(text);
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < chars.Length; i++)
|
||||
{
|
||||
h += chars[i];
|
||||
h += (h << 10);
|
||||
h ^= (h >> 6);
|
||||
}
|
||||
h += (h << 3);
|
||||
h ^= (h >> 11);
|
||||
h += (h << 15);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
public static uint GenHash(string text)
|
||||
{
|
||||
uint h = 0;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
h += (byte)text[i];
|
||||
h += (h << 10);
|
||||
h ^= (h >> 6);
|
||||
}
|
||||
h += (h << 3);
|
||||
h ^= (h >> 11);
|
||||
h += (h << 15);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
public static uint GenHash(byte[] data)
|
||||
{
|
||||
uint h = 0;
|
||||
for (uint i = 0; i < data.Length; i++)
|
||||
{
|
||||
h += data[i];
|
||||
h += (h << 10);
|
||||
h ^= (h >> 6);
|
||||
}
|
||||
h += (h << 3);
|
||||
h ^= (h >> 11);
|
||||
h += (h << 15);
|
||||
return h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum JenkHashInputEncoding
|
||||
{
|
||||
UTF8 = 0,
|
||||
ASCII = 1,
|
||||
}
|
||||
|
||||
|
||||
public class JenkIndMatch
|
||||
{
|
||||
public string Hash { get; set; }
|
||||
public string Value { get; set; }
|
||||
public double Score { get; set; }
|
||||
|
||||
public JenkIndMatch(string hash, string val)
|
||||
{
|
||||
Hash = hash;
|
||||
Value = val;
|
||||
CalculateScore();
|
||||
}
|
||||
|
||||
public void CalculateScore()
|
||||
{
|
||||
|
||||
int wordlength = 0;
|
||||
int wordrank = 0;
|
||||
|
||||
string okwordsymbs = " _-.";
|
||||
string goodwordsymbs = "_";
|
||||
|
||||
for (int i = 0; i < Value.Length; i++)
|
||||
{
|
||||
char c = Value[i];
|
||||
|
||||
bool wordchar = (char.IsLetter(c) || char.IsDigit(c) || goodwordsymbs.Contains(c));
|
||||
|
||||
if (wordchar)
|
||||
{
|
||||
wordlength++;
|
||||
}
|
||||
else if (okwordsymbs.Contains(c))
|
||||
{
|
||||
//wordlength++; //don't add this to the score, but allow it to continue the chain
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wordlength > 2)
|
||||
{
|
||||
wordrank += wordlength; //linear word increment, ignoring 1-2char matches
|
||||
}
|
||||
wordlength = 0;
|
||||
}
|
||||
|
||||
//wordrank += wordlength; //each sequential letter in a word contributes more to the rank, ie. 1+2+3+4+...
|
||||
}
|
||||
if (wordlength > 2)
|
||||
{
|
||||
wordrank += wordlength; //linear word increment, ignoring 1-2char matches
|
||||
}
|
||||
|
||||
|
||||
if (Value.Length > 0)
|
||||
{
|
||||
//the max value for a given length when 1+2+3+4+5+..n = n(n+1)/2
|
||||
//double n = (double)Value.Length;
|
||||
//double maxscore = n * (n + 1.0) * 0.5;
|
||||
|
||||
double n = (double)Value.Length;
|
||||
Score = (((double)wordrank) / n);
|
||||
//Score = (((double)wordrank));
|
||||
}
|
||||
else
|
||||
{
|
||||
Score = 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} -> {1} ({2:0.##})", Hash, Value, Score);
|
||||
}
|
||||
}
|
||||
|
||||
public class JenkIndProblem
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public string Excuse { get; set; }
|
||||
public int Line { get; set; }
|
||||
|
||||
public JenkIndProblem(string filepath, string excuse, int line)
|
||||
{
|
||||
Filename = Path.GetFileName(filepath);
|
||||
Excuse = excuse;
|
||||
Line = line;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} : {1} at line {2}", Filename, Excuse, Line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static class JenkIndex
|
||||
{
|
||||
public static Dictionary<uint, string> Index = new Dictionary<uint, string>();
|
||||
private static object syncRoot = new object();
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
public static string[] GetAllStrings()
|
||||
{
|
||||
string[] res = null;
|
||||
lock (syncRoot)
|
||||
{
|
||||
res = Index.Values.ToArray();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
36
CodeWalker.Core/Properties/AssemblyInfo.cs
Normal file
36
CodeWalker.Core/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CodeWalker.Core")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CodeWalker.Core")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("de50d3a6-b49e-47a0-abe6-101473a00759")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
73
CodeWalker.Core/Properties/Resources.Designer.cs
generated
Normal file
73
CodeWalker.Core/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace CodeWalker.Core.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeWalker.Core.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] magic {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("magic", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
CodeWalker.Core/Properties/Resources.resx
Normal file
124
CodeWalker.Core/Properties/Resources.resx
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="magic" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\magic.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
BIN
CodeWalker.Core/Resources/magic.dat
Normal file
BIN
CodeWalker.Core/Resources/magic.dat
Normal file
Binary file not shown.
121
CodeWalker.Core/Utils/Cache.cs
Normal file
121
CodeWalker.Core/Utils/Cache.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
public class Cache<TKey, TVal> where TVal : Cacheable<TKey>
|
||||
{
|
||||
public long MaxMemoryUsage = 536870912; //512mb
|
||||
public long CurrentMemoryUsage = 0;
|
||||
public double CacheTime = 5.0; //seconds to keep something that's not used
|
||||
|
||||
private LinkedList<TVal> loadedList = new LinkedList<TVal>();
|
||||
private Dictionary<TKey, LinkedListNode<TVal>> loadedListDict = new Dictionary<TKey, LinkedListNode<TVal>>();
|
||||
|
||||
public Cache()
|
||||
{
|
||||
}
|
||||
public Cache(long maxMemoryUsage, double cacheTime)
|
||||
{
|
||||
MaxMemoryUsage = maxMemoryUsage;
|
||||
CacheTime = cacheTime;
|
||||
}
|
||||
|
||||
public TVal TryGet(TKey key)
|
||||
{
|
||||
LinkedListNode<TVal> lln = null;
|
||||
if (loadedListDict.TryGetValue(key, out lln))
|
||||
{
|
||||
loadedList.Remove(lln);
|
||||
loadedList.AddLast(lln);
|
||||
lln.Value.LastUseTime = DateTime.Now;
|
||||
}
|
||||
return (lln != null) ? lln.Value : null;
|
||||
}
|
||||
public bool TryAdd(TKey key, TVal item)
|
||||
{
|
||||
if (item.MemoryUsage == 0)
|
||||
{
|
||||
}
|
||||
item.Key = key;
|
||||
if (CanAdd())
|
||||
{
|
||||
var lln = loadedList.AddLast(item);
|
||||
loadedListDict.Add(key, lln);
|
||||
Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//cache full, check the front of the list for oldest..
|
||||
var oldlln = loadedList.First;
|
||||
var cachetime = CacheTime;
|
||||
int iter = 0, maxiter = 2;
|
||||
while (!CanAdd() && (iter<maxiter))
|
||||
{
|
||||
while ((!CanAdd()) && (oldlln != null) && ((DateTime.Now - oldlln.Value.LastUseTime).TotalSeconds > cachetime))
|
||||
{
|
||||
Interlocked.Add(ref CurrentMemoryUsage, -oldlln.Value.MemoryUsage);
|
||||
loadedListDict.Remove(oldlln.Value.Key);
|
||||
loadedList.Remove(oldlln); //gc should free up memory later..
|
||||
oldlln.Value = null;
|
||||
oldlln = null;
|
||||
//GC.Collect();
|
||||
oldlln = loadedList.First;
|
||||
}
|
||||
cachetime *= 0.5;
|
||||
iter++;
|
||||
}
|
||||
if (CanAdd()) //see if there's enough memory now...
|
||||
{
|
||||
var newlln = loadedList.AddLast(item);
|
||||
loadedListDict.Add(key, newlln);
|
||||
Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//really shouldn't get here, but it's possible under stress.
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanAdd()
|
||||
{
|
||||
return Interlocked.Read(ref CurrentMemoryUsage) < MaxMemoryUsage;
|
||||
}
|
||||
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
loadedList.Clear();
|
||||
loadedListDict.Clear();
|
||||
CurrentMemoryUsage = 0;
|
||||
}
|
||||
|
||||
public void Remove(TKey key)
|
||||
{
|
||||
LinkedListNode<TVal> n;
|
||||
if (loadedListDict.TryGetValue(key, out n))
|
||||
{
|
||||
loadedListDict.Remove(key);
|
||||
loadedList.Remove(n);
|
||||
CurrentMemoryUsage -= n.Value.MemoryUsage;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract class Cacheable<TKey>
|
||||
{
|
||||
public TKey Key;
|
||||
public DateTime LastUseTime = DateTime.Now;
|
||||
public long MemoryUsage;
|
||||
}
|
||||
|
||||
}
|
42
CodeWalker.Core/Utils/Matrices.cs
Normal file
42
CodeWalker.Core/Utils/Matrices.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
public static class MatrixExtensions
|
||||
{
|
||||
|
||||
public static Vector3 MultiplyW(this Matrix m, Vector3 v)
|
||||
{
|
||||
float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41;
|
||||
float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42;
|
||||
float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43;
|
||||
float w = (((m.M14 * v.X) + (m.M24 * v.Y)) + (m.M34 * v.Z)) + m.M44;
|
||||
float iw = 1.0f / Math.Abs(w);
|
||||
return new Vector3(x * iw, y * iw, z * iw);
|
||||
}
|
||||
public static Vector3 Multiply(this Matrix m, Vector3 v)
|
||||
{
|
||||
float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41;
|
||||
float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42;
|
||||
float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43;
|
||||
return new Vector3(x, y, z);
|
||||
//this quick mul ignores W...
|
||||
}
|
||||
|
||||
public static Vector4 Multiply(this Matrix m, Vector4 v)
|
||||
{
|
||||
float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41;
|
||||
float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42;
|
||||
float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43;
|
||||
float w = (((m.M14 * v.X) + (m.M24 * v.Y)) + (m.M34 * v.Z)) + m.M44;
|
||||
return new Vector4(x, y, z, w);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
74
CodeWalker.Core/Utils/Quaternions.cs
Normal file
74
CodeWalker.Core/Utils/Quaternions.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
|
||||
|
||||
|
||||
public static class QuaternionExtension
|
||||
{
|
||||
public static Vector3 Multiply(this Quaternion a, Vector3 b)
|
||||
{
|
||||
float axx = a.X * 2.0f;
|
||||
float ayy = a.Y * 2.0f;
|
||||
float azz = a.Z * 2.0f;
|
||||
float awxx = a.W * axx;
|
||||
float awyy = a.W * ayy;
|
||||
float awzz = a.W * azz;
|
||||
float axxx = a.X * axx;
|
||||
float axyy = a.X * ayy;
|
||||
float axzz = a.X * azz;
|
||||
float ayyy = a.Y * ayy;
|
||||
float ayzz = a.Y * azz;
|
||||
float azzz = a.Z * azz;
|
||||
return new Vector3(((b.X * ((1.0f - ayyy) - azzz)) + (b.Y * (axyy - awzz))) + (b.Z * (axzz + awyy)),
|
||||
((b.X * (axyy + awzz)) + (b.Y * ((1.0f - axxx) - azzz))) + (b.Z * (ayzz - awxx)),
|
||||
((b.X * (axzz - awyy)) + (b.Y * (ayzz + awxx))) + (b.Z * ((1.0f - axxx) - ayyy)));
|
||||
}
|
||||
|
||||
public static Matrix ToMatrix(this Quaternion q)
|
||||
{
|
||||
float xx = q.X * q.X;
|
||||
float yy = q.Y * q.Y;
|
||||
float zz = q.Z * q.Z;
|
||||
float xy = q.X * q.Y;
|
||||
float zw = q.Z * q.W;
|
||||
float zx = q.Z * q.X;
|
||||
float yw = q.Y * q.W;
|
||||
float yz = q.Y * q.Z;
|
||||
float xw = q.X * q.W;
|
||||
Matrix result = new Matrix();
|
||||
result.M11 = 1.0f - (2.0f * (yy + zz));
|
||||
result.M12 = 2.0f * (xy + zw);
|
||||
result.M13 = 2.0f * (zx - yw);
|
||||
result.M14 = 0.0f;
|
||||
result.M21 = 2.0f * (xy - zw);
|
||||
result.M22 = 1.0f - (2.0f * (zz + xx));
|
||||
result.M23 = 2.0f * (yz + xw);
|
||||
result.M24 = 0.0f;
|
||||
result.M31 = 2.0f * (zx + yw);
|
||||
result.M32 = 2.0f * (yz - xw);
|
||||
result.M33 = 1.0f - (2.0f * (yy + xx));
|
||||
result.M34 = 0.0f;
|
||||
result.M41 = 0.0f;
|
||||
result.M42 = 0.0f;
|
||||
result.M43 = 0.0f;
|
||||
result.M44 = 1.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Vector4 ToVector4(this Quaternion q)
|
||||
{
|
||||
return new Vector4(q.X, q.Y, q.Z, q.W);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
221
CodeWalker.Core/Utils/Utils.cs
Normal file
221
CodeWalker.Core/Utils/Utils.cs
Normal file
@ -0,0 +1,221 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
|
||||
|
||||
public static class TextUtil
|
||||
{
|
||||
|
||||
public static string GetBytesReadable(long i)
|
||||
{
|
||||
//shamelessly stolen from stackoverflow, and a bit mangled
|
||||
|
||||
// Returns the human-readable file size for an arbitrary, 64-bit file size
|
||||
// The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
|
||||
// Get absolute value
|
||||
long absolute_i = (i < 0 ? -i : i);
|
||||
// Determine the suffix and readable value
|
||||
string suffix;
|
||||
double readable;
|
||||
if (absolute_i >= 0x1000000000000000) // Exabyte
|
||||
{
|
||||
suffix = "EB";
|
||||
readable = (i >> 50);
|
||||
}
|
||||
else if (absolute_i >= 0x4000000000000) // Petabyte
|
||||
{
|
||||
suffix = "PB";
|
||||
readable = (i >> 40);
|
||||
}
|
||||
else if (absolute_i >= 0x10000000000) // Terabyte
|
||||
{
|
||||
suffix = "TB";
|
||||
readable = (i >> 30);
|
||||
}
|
||||
else if (absolute_i >= 0x40000000) // Gigabyte
|
||||
{
|
||||
suffix = "GB";
|
||||
readable = (i >> 20);
|
||||
}
|
||||
else if (absolute_i >= 0x100000) // Megabyte
|
||||
{
|
||||
suffix = "MB";
|
||||
readable = (i >> 10);
|
||||
}
|
||||
else if (absolute_i >= 0x400) // Kilobyte
|
||||
{
|
||||
suffix = "KB";
|
||||
readable = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
return i.ToString("0 bytes"); // Byte
|
||||
}
|
||||
// Divide by 1024 to get fractional value
|
||||
readable = (readable / 1024);
|
||||
|
||||
string fmt = "0.### ";
|
||||
if (readable > 1000)
|
||||
{
|
||||
fmt = "0";
|
||||
}
|
||||
else if (readable > 100)
|
||||
{
|
||||
fmt = "0.#";
|
||||
}
|
||||
else if (readable > 10)
|
||||
{
|
||||
fmt = "0.##";
|
||||
}
|
||||
|
||||
// Return formatted number with suffix
|
||||
return readable.ToString(fmt) + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class FloatUtil
|
||||
{
|
||||
public static bool TryParse(string s, out float f)
|
||||
{
|
||||
f = 0.0f;
|
||||
if (float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out f))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static float Parse(string s)
|
||||
{
|
||||
float f;
|
||||
TryParse(s, out f);
|
||||
return f;
|
||||
}
|
||||
public static string ToString(float f)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return f.ToString(c);
|
||||
}
|
||||
|
||||
|
||||
public static string GetVector2String(Vector2 v)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return v.X.ToString(c) + ", " + v.Y.ToString(c);
|
||||
}
|
||||
public static string GetVector3String(Vector3 v)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return v.X.ToString(c) + ", " + v.Y.ToString(c) + ", " + v.Z.ToString(c);
|
||||
}
|
||||
public static string GetVector3String(Vector3 v, string format)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return v.X.ToString(format, c) + ", " + v.Y.ToString(format, c) + ", " + v.Z.ToString(format, c);
|
||||
}
|
||||
public static string GetVector3XmlString(Vector3 v)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return string.Format("x=\"{0}\" y=\"{1}\" z=\"{2}\"", v.X.ToString(c), v.Y.ToString(c), v.Z.ToString(c));
|
||||
}
|
||||
public static string GetVector4XmlString(Vector4 v)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return string.Format("x=\"{0}\" y=\"{1}\" z=\"{2}\" w=\"{3}\"", v.X.ToString(c), v.Y.ToString(c), v.Z.ToString(c), v.W.ToString(c));
|
||||
}
|
||||
public static string GetQuaternionXmlString(Quaternion q)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return string.Format("x=\"{0}\" y=\"{1}\" z=\"{2}\" w=\"{3}\"", q.X.ToString(c), q.Y.ToString(c), q.Z.ToString(c), q.W.ToString(c));
|
||||
}
|
||||
|
||||
public static Vector3 ParseVector3String(string s)
|
||||
{
|
||||
Vector3 p = new Vector3(0.0f);
|
||||
string[] ss = s.Split(',');
|
||||
if (ss.Length > 0)
|
||||
{
|
||||
FloatUtil.TryParse(ss[0].Trim(), out p.X);
|
||||
}
|
||||
if (ss.Length > 1)
|
||||
{
|
||||
FloatUtil.TryParse(ss[1].Trim(), out p.Y);
|
||||
}
|
||||
if (ss.Length > 2)
|
||||
{
|
||||
FloatUtil.TryParse(ss[2].Trim(), out p.Z);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static string GetVector4String(Vector4 v)
|
||||
{
|
||||
var c = CultureInfo.InvariantCulture;
|
||||
return v.X.ToString(c) + ", " + v.Y.ToString(c) + ", " + v.Z.ToString(c) + ", " + v.W.ToString(c);
|
||||
}
|
||||
public static Vector4 ParseVector4String(string s)
|
||||
{
|
||||
Vector4 p = new Vector4(0.0f);
|
||||
string[] ss = s.Split(',');
|
||||
if (ss.Length > 0)
|
||||
{
|
||||
FloatUtil.TryParse(ss[0].Trim(), out p.X);
|
||||
}
|
||||
if (ss.Length > 1)
|
||||
{
|
||||
FloatUtil.TryParse(ss[1].Trim(), out p.Y);
|
||||
}
|
||||
if (ss.Length > 2)
|
||||
{
|
||||
FloatUtil.TryParse(ss[2].Trim(), out p.Z);
|
||||
}
|
||||
if (ss.Length > 3)
|
||||
{
|
||||
FloatUtil.TryParse(ss[3].Trim(), out p.W);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static class BitUtil
|
||||
{
|
||||
public static bool IsBitSet(uint value, int bit)
|
||||
{
|
||||
return (((value >> bit) & 1) > 0);
|
||||
}
|
||||
public static uint SetBit(uint value, int bit)
|
||||
{
|
||||
return (value | (1u << bit));
|
||||
}
|
||||
public static uint ClearBit(uint value, int bit)
|
||||
{
|
||||
return (value & (~(1u << bit)));
|
||||
}
|
||||
public static uint UpdateBit(uint value, int bit, bool flag)
|
||||
{
|
||||
if (flag) return SetBit(value, bit);
|
||||
else return ClearBit(value, bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
65
CodeWalker.Core/Utils/Vectors.cs
Normal file
65
CodeWalker.Core/Utils/Vectors.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
public static class Vectors
|
||||
{
|
||||
|
||||
public static Vector3 XYZ(this Vector4 v)
|
||||
{
|
||||
return new Vector3(v.X, v.Y, v.Z);
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 Round(this Vector3 v)
|
||||
{
|
||||
return new Vector3((float)Math.Round(v.X), (float)Math.Round(v.Y), (float)Math.Round(v.Z));
|
||||
}
|
||||
|
||||
public static Vector4 Floor(this Vector4 v)
|
||||
{
|
||||
return new Vector4((float)Math.Floor(v.X), (float)Math.Floor(v.Y), (float)Math.Floor(v.Z), (float)Math.Floor(v.W));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public struct Vector2I
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
|
||||
public Vector2I(int x, int y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
public Vector2I(Vector2 v)
|
||||
{
|
||||
X = (int)Math.Floor(v.X);
|
||||
Y = (int)Math.Floor(v.Y);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return X.ToString() + ", " + Y.ToString();
|
||||
}
|
||||
|
||||
|
||||
public static Vector2I operator +(Vector2I a, Vector2I b)
|
||||
{
|
||||
return new Vector2I(a.X + b.X, a.Y + b.Y);
|
||||
}
|
||||
|
||||
public static Vector2I operator -(Vector2I a, Vector2I b)
|
||||
{
|
||||
return new Vector2I(a.X - b.X, a.Y - b.Y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
137
CodeWalker.Core/Utils/Xml.cs
Normal file
137
CodeWalker.Core/Utils/Xml.cs
Normal file
@ -0,0 +1,137 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
public static class Xml
|
||||
{
|
||||
|
||||
public static string GetStringAttribute(XmlNode node, string attribute)
|
||||
{
|
||||
if (node == null) return null;
|
||||
return node.Attributes[attribute]?.InnerText;
|
||||
}
|
||||
public static bool GetBoolAttribute(XmlNode node, string attribute)
|
||||
{
|
||||
if (node == null) return false;
|
||||
string val = node.Attributes[attribute]?.InnerText;
|
||||
bool b;
|
||||
bool.TryParse(val, out b);
|
||||
return b;
|
||||
}
|
||||
public static int GetIntAttribute(XmlNode node, string attribute)
|
||||
{
|
||||
if (node == null) return 0;
|
||||
string val = node.Attributes[attribute]?.InnerText;
|
||||
int i;
|
||||
int.TryParse(val, out i);
|
||||
return i;
|
||||
}
|
||||
public static float GetFloatAttribute(XmlNode node, string attribute)
|
||||
{
|
||||
if (node == null) return 0;
|
||||
string val = node.Attributes[attribute]?.InnerText;
|
||||
float f;
|
||||
FloatUtil.TryParse(val, out f);
|
||||
return f;
|
||||
}
|
||||
|
||||
public static string GetChildInnerText(XmlNode node, string name)
|
||||
{
|
||||
if (node == null) return null;
|
||||
return node.SelectSingleNode(name)?.InnerText;
|
||||
}
|
||||
public static bool GetChildBoolInnerText(XmlNode node, string name)
|
||||
{
|
||||
if (node == null) return false;
|
||||
string val = node.SelectSingleNode(name)?.InnerText;
|
||||
bool b;
|
||||
bool.TryParse(val, out b);
|
||||
return b;
|
||||
}
|
||||
public static int GetChildIntInnerText(XmlNode node, string name)
|
||||
{
|
||||
if (node == null) return 0;
|
||||
string val = node.SelectSingleNode(name)?.InnerText;
|
||||
int i;
|
||||
int.TryParse(val, out i);
|
||||
return i;
|
||||
}
|
||||
public static float GetChildFloatInnerText(XmlNode node, string name)
|
||||
{
|
||||
if (node == null) return 0;
|
||||
string val = node.SelectSingleNode(name)?.InnerText;
|
||||
float f;
|
||||
FloatUtil.TryParse(val, out f);
|
||||
return f;
|
||||
}
|
||||
|
||||
public static bool GetChildBoolAttribute(XmlNode node, string name, string attribute)
|
||||
{
|
||||
if (node == null) return false;
|
||||
string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText;
|
||||
bool b;
|
||||
bool.TryParse(val, out b);
|
||||
return b;
|
||||
}
|
||||
public static int GetChildIntAttribute(XmlNode node, string name, string attribute)
|
||||
{
|
||||
if (node == null) return 0;
|
||||
string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText;
|
||||
int i;
|
||||
int.TryParse(val, out i);
|
||||
return i;
|
||||
}
|
||||
public static float GetChildFloatAttribute(XmlNode node, string name, string attribute)
|
||||
{
|
||||
if (node == null) return 0;
|
||||
string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText;
|
||||
float f;
|
||||
FloatUtil.TryParse(val, out f);
|
||||
return f;
|
||||
}
|
||||
public static string GetChildStringAttribute(XmlNode node, string name, string attribute)
|
||||
{
|
||||
if (node == null) return string.Empty;
|
||||
string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText;
|
||||
return val;
|
||||
}
|
||||
public static Vector3 GetChildVector3Attributes(XmlNode node, string name, string x, string y, string z)
|
||||
{
|
||||
float fx = GetChildFloatAttribute(node, name, x);
|
||||
float fy = GetChildFloatAttribute(node, name, y);
|
||||
float fz = GetChildFloatAttribute(node, name, z);
|
||||
return new Vector3(fx, fy, fz);
|
||||
}
|
||||
|
||||
public static XmlElement GetChild(XmlElement element, string name)
|
||||
{
|
||||
return element.SelectSingleNode(name) as XmlElement;
|
||||
}
|
||||
|
||||
public static XmlElement AddChild(XmlDocument doc, XmlNode node, string name)
|
||||
{
|
||||
XmlElement child = doc.CreateElement(name);
|
||||
node.AppendChild(child);
|
||||
return child;
|
||||
}
|
||||
public static XmlElement AddChildWithInnerText(XmlDocument doc, XmlNode node, string name, string innerText)
|
||||
{
|
||||
XmlElement child = AddChild(doc, node, name);
|
||||
child.InnerText = innerText;
|
||||
return child;
|
||||
}
|
||||
public static XmlElement AddChildWithAttribute(XmlDocument doc, XmlNode node, string name, string attributeName, string attributeValue)
|
||||
{
|
||||
XmlElement child = AddChild(doc, node, name);
|
||||
child.SetAttribute(attributeName, attributeValue);
|
||||
return child;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
279
CodeWalker.Core/World/AudioZones.cs
Normal file
279
CodeWalker.Core/World/AudioZones.cs
Normal file
@ -0,0 +1,279 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class AudioZones // : BasePathData
|
||||
{
|
||||
public volatile bool Inited = false;
|
||||
public GameFileCache GameFileCache;
|
||||
|
||||
//public Vector4[] GetNodePositions()
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
//public EditorVertex[] GetPathVertices()
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
//public EditorVertex[] GetTriangleVertices()
|
||||
//{
|
||||
// return TriangleVerts;
|
||||
//}
|
||||
//public EditorVertex[] TriangleVerts;
|
||||
|
||||
public List<AudioPlacement> Zones = new List<AudioPlacement>();
|
||||
public List<AudioPlacement> Emitters = new List<AudioPlacement>();
|
||||
public List<AudioPlacement> AllItems = new List<AudioPlacement>();
|
||||
|
||||
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||
{
|
||||
Inited = false;
|
||||
|
||||
GameFileCache = gameFileCache;
|
||||
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
|
||||
Zones.Clear();
|
||||
Emitters.Clear();
|
||||
AllItems.Clear();
|
||||
|
||||
|
||||
Dictionary<uint, RpfFileEntry> datrelentries = new Dictionary<uint, RpfFileEntry>();
|
||||
var audrpf = rpfman.FindRpfFile("x64\\audio\\audio_rel.rpf");
|
||||
if (audrpf != null)
|
||||
{
|
||||
AddRpfDatRels(audrpf, datrelentries);
|
||||
}
|
||||
|
||||
if (gameFileCache.EnableDlc)
|
||||
{
|
||||
var updrpf = rpfman.FindRpfFile("update\\update.rpf");
|
||||
if (updrpf != null)
|
||||
{
|
||||
AddRpfDatRels(updrpf, datrelentries);
|
||||
}
|
||||
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load from current dlc rpfs
|
||||
{
|
||||
AddRpfDatRels(dlcrpf, datrelentries);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var dat151entry in datrelentries.Values)
|
||||
{
|
||||
var relfile = rpfman.GetFile<RelFile>(dat151entry);
|
||||
if (relfile != null)
|
||||
{
|
||||
foreach (var reldata in relfile.RelDatas)
|
||||
{
|
||||
if (reldata is Dat151AmbientZone)
|
||||
{
|
||||
Zones.Add(new AudioPlacement(relfile, reldata as Dat151AmbientZone));
|
||||
}
|
||||
else if (reldata is Dat151AmbientEmitter)
|
||||
{
|
||||
Emitters.Add(new AudioPlacement(relfile, reldata as Dat151AmbientEmitter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AllItems.AddRange(Zones);
|
||||
AllItems.AddRange(Emitters);
|
||||
|
||||
Inited = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void AddRpfDatRels(RpfFile rpffile, Dictionary<uint, RpfFileEntry> datrelentries)
|
||||
{
|
||||
if (rpffile.AllEntries == null) return;
|
||||
foreach (var entry in rpffile.AllEntries)
|
||||
{
|
||||
if (entry is RpfFileEntry)
|
||||
{
|
||||
RpfFileEntry fentry = entry as RpfFileEntry;
|
||||
//if (entry.NameLower.EndsWith(".rel"))
|
||||
//{
|
||||
// datrelentries[entry.NameHash] = fentry;
|
||||
//}
|
||||
if (entry.NameLower.EndsWith(".dat54.rel"))
|
||||
{
|
||||
datrelentries[entry.NameHash] = fentry;
|
||||
}
|
||||
if (entry.NameLower.EndsWith(".dat151.rel"))
|
||||
{
|
||||
datrelentries[entry.NameHash] = fentry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class AudioPlacement
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public MetaHash NameHash { get; set; }
|
||||
public RelFile RelFile { get; set; }
|
||||
public Dat151AmbientZone AudioZone { get; set; }
|
||||
public Dat151AmbientEmitter AudioEmitter { get; set; }
|
||||
public Dat151ZoneShape Shape { get; set; }
|
||||
public string ShortTypeName { get; set; }
|
||||
public string FullTypeName { get; set; }
|
||||
public Vector3 InnerPos { get; set; }
|
||||
public Vector3 InnerMin { get; set; }
|
||||
public Vector3 InnerMax { get; set; }
|
||||
public float InnerRad { get; set; }
|
||||
public Quaternion InnerOri { get; set; }
|
||||
public Vector3 OuterPos { get; set; }
|
||||
public Vector3 OuterMin { get; set; }
|
||||
public Vector3 OuterMax { get; set; }
|
||||
public float OuterRad { get; set; }
|
||||
public Quaternion OuterOri { get; set; }
|
||||
public Vector3 Position { get; set; }
|
||||
public Vector3 HitboxMin { get; set; }
|
||||
public Vector3 HitboxMax { get; set; }
|
||||
public Quaternion Orientation { get; set; }
|
||||
public Quaternion OrientationInv { get; set; }
|
||||
public float HitSphereRad { get; set; }
|
||||
|
||||
|
||||
public AudioPlacement(RelFile rel, Dat151AmbientZone zone)
|
||||
{
|
||||
RelFile = rel;
|
||||
AudioZone = zone;
|
||||
Shape = zone.Shape;
|
||||
ShortTypeName = "AudioZone";
|
||||
FullTypeName = "Audio Zone";
|
||||
Name = zone.Name;
|
||||
NameHash = zone.NameHash;
|
||||
|
||||
float deg2rad = (float)(Math.PI / 180.0);
|
||||
|
||||
switch (zone.Shape)
|
||||
{
|
||||
case Dat151ZoneShape.Box:
|
||||
InnerPos = zone.InnerPos;
|
||||
InnerMax = zone.InnerSize * 0.5f;
|
||||
InnerMin = -InnerMax;
|
||||
InnerOri = Quaternion.RotationAxis(Vector3.UnitZ, zone.InnerAngle * deg2rad);
|
||||
break;
|
||||
case Dat151ZoneShape.Sphere:
|
||||
InnerPos = zone.InnerPos;
|
||||
InnerOri = Quaternion.Identity;
|
||||
InnerRad = zone.InnerSize.X;
|
||||
OuterRad = zone.OuterSize.X;
|
||||
break;
|
||||
case Dat151ZoneShape.Line:
|
||||
InnerPos = zone.InnerPos;
|
||||
InnerMin = new Vector3(-1.0f, -1.0f, 0.0f);
|
||||
InnerMax = new Vector3(1.0f, 1.0f, (zone.InnerSize - zone.InnerPos).Length());
|
||||
InnerOri = Quaternion.Invert(Quaternion.LookAtLH(zone.InnerPos, zone.InnerSize, Vector3.UnitZ));
|
||||
break;
|
||||
}
|
||||
|
||||
OuterPos = zone.OuterPos;
|
||||
OuterMax = zone.OuterSize * 0.5f;
|
||||
OuterMin = -OuterMax;
|
||||
OuterOri = Quaternion.RotationAxis(Vector3.UnitZ, zone.OuterAngle * deg2rad);
|
||||
|
||||
bool useouter = ((InnerMax.X == 0) || (InnerMax.Y == 0) || (InnerMax.Z == 0));
|
||||
if (useouter && (zone.Shape != Dat151ZoneShape.Sphere))
|
||||
{ } //not sure what these are yet!
|
||||
Position = useouter ? OuterPos : InnerPos;
|
||||
HitboxMax = useouter ? OuterMax : InnerMax;
|
||||
HitboxMin = useouter ? OuterMin : InnerMin;
|
||||
Orientation = useouter ? OuterOri : InnerOri;
|
||||
OrientationInv = Quaternion.Invert(Orientation);
|
||||
HitSphereRad = InnerRad;
|
||||
if (zone.Shape == Dat151ZoneShape.Sphere)
|
||||
{
|
||||
Position = InnerPos;
|
||||
}
|
||||
}
|
||||
public AudioPlacement(RelFile rel, Dat151AmbientEmitter emitter)
|
||||
{
|
||||
RelFile = rel;
|
||||
AudioEmitter = emitter;
|
||||
Shape = Dat151ZoneShape.Sphere;
|
||||
ShortTypeName = "AudioEmitter";
|
||||
FullTypeName = "Audio Emitter";
|
||||
Name = emitter.Name;
|
||||
NameHash = emitter.NameHash;
|
||||
|
||||
Orientation = Quaternion.Identity;
|
||||
OrientationInv = Quaternion.Identity;
|
||||
InnerPos = emitter.Position;
|
||||
OuterPos = InnerPos;
|
||||
InnerRad = emitter.InnerRad;
|
||||
OuterRad = emitter.OuterRad;
|
||||
|
||||
bool useouter = (InnerRad == 0);
|
||||
if (useouter)
|
||||
{
|
||||
InnerRad = 1;
|
||||
}
|
||||
Position = InnerPos;
|
||||
HitSphereRad = InnerRad;// useouter ? OuterRad : InnerRad;
|
||||
}
|
||||
|
||||
|
||||
public void SetPosition(Vector3 pos)
|
||||
{
|
||||
bool useouter = ((InnerMax.X == 0) || (InnerMax.Y == 0) || (InnerMax.Z == 0));
|
||||
Vector3 delta = pos - InnerPos;
|
||||
InnerPos = pos;
|
||||
OuterPos += delta;
|
||||
Position = useouter ? OuterPos : InnerPos;
|
||||
}
|
||||
public void SetOrientation(Quaternion ori)
|
||||
{
|
||||
Orientation = ori;
|
||||
OrientationInv = Quaternion.Invert(ori);
|
||||
|
||||
if (InnerOri == OuterOri)
|
||||
{
|
||||
InnerOri = Orientation;
|
||||
OuterOri = Orientation;
|
||||
}
|
||||
else
|
||||
{
|
||||
//not sure yet how to allow independent rotation of inner & outer boxes...
|
||||
//maybe only in project window?
|
||||
bool useouter = ((InnerMax.X == 0) || (InnerMax.Y == 0) || (InnerMax.Z == 0));
|
||||
if (useouter)
|
||||
{
|
||||
OuterOri = Orientation;
|
||||
}
|
||||
else
|
||||
{
|
||||
InnerOri = Orientation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string GetNameString()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Name)) return Name;
|
||||
return NameHash.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
338
CodeWalker.Core/World/Camera.cs
Normal file
338
CodeWalker.Core/World/Camera.cs
Normal file
@ -0,0 +1,338 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class Camera
|
||||
{
|
||||
public Vector3 TargetRotation = Vector3.Zero;
|
||||
public Vector3 CurrentRotation = Vector3.Zero;
|
||||
public float Smoothness;// 10.0f;//0.15f;
|
||||
public float Sensitivity;// 0.005f;
|
||||
public float TargetDistance = 1.0f;
|
||||
public float CurrentDistance = 1.0f;
|
||||
public float ZoomCurrentTime = 0.0f;
|
||||
public float ZoomTargetTime = 2.0f;
|
||||
public float ZoomVelocity = 0.0f;
|
||||
public float ZoomSpeed = 0.1f;
|
||||
public float Width = 1920.0f;
|
||||
public float Height = 1080.0f;
|
||||
public float FieldOfView;// 1.0f;
|
||||
public float FieldOfViewFactor = 0.5f / (float)Math.Tan(/*FieldOfView*/ 1.0f * 0.5f);
|
||||
public float AspectRatio = 1920.0f / 1080.0f;
|
||||
public float ZNear = 0.5f;
|
||||
public float ZFar = 12000.0f;
|
||||
public Entity FollowEntity = null;
|
||||
public Vector3 LocalLookAt = Vector3.ForwardLH;
|
||||
public float VOffset = 0.0f;
|
||||
public bool UpdateProj = true;
|
||||
public bool IsMapView = false;
|
||||
public bool IsOrthographic = false;
|
||||
public float OrthographicSize = 20.0f;
|
||||
public float OrthographicTargetSize = 20.0f;
|
||||
public Matrix ProjMatrix = Matrix.Identity;
|
||||
public Vector3 Position = Vector3.Zero;
|
||||
public Vector3 UpDirection = Vector3.Up;
|
||||
public Vector3 ViewDirection = Vector3.ForwardLH;
|
||||
public Quaternion ViewQuaternion = Quaternion.Identity;
|
||||
public Quaternion ViewInvQuaternion = Quaternion.Identity;
|
||||
public Matrix ViewMatrix = Matrix.Identity;
|
||||
public Matrix ViewInvMatrix = Matrix.Identity;
|
||||
public Matrix ViewProjMatrix = Matrix.Identity;
|
||||
public Matrix ViewProjInvMatrix = Matrix.Identity;
|
||||
public Frustum ViewFrustum = new Frustum();
|
||||
public Vector3 MouseRayNear = Vector3.Zero;
|
||||
public Vector3 MouseRayFar = Vector3.Zero;
|
||||
public Ray MouseRay;
|
||||
private float MouseX = 0;
|
||||
private float MouseY = 0;
|
||||
private object syncRoot = new object();
|
||||
|
||||
|
||||
public Camera(float smoothness, float sensitivity, float fov)
|
||||
{
|
||||
Smoothness = smoothness;
|
||||
Sensitivity = sensitivity;
|
||||
FieldOfView = fov;
|
||||
FieldOfViewFactor = 0.5f / (float)Math.Tan(FieldOfView * 0.5f);
|
||||
}
|
||||
|
||||
|
||||
public void SetMousePosition(int x, int y)
|
||||
{
|
||||
MouseX = (x / Width) * 2.0f - 1.0f;
|
||||
MouseY = (y / Height) * -2.0f + 1.0f;
|
||||
}
|
||||
|
||||
public void SetFollowEntity(Entity e)
|
||||
{
|
||||
FollowEntity = e;
|
||||
}
|
||||
|
||||
public void Update(float elapsed)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
UpdateFollow(elapsed);
|
||||
if (UpdateProj) UpdateProjMatrix();
|
||||
|
||||
//float mx = (LastMouseX / Width) * 2.0f;
|
||||
//float my = (LastMouseY / Height) * -2.0f;
|
||||
|
||||
////MousedItem = nullptr;
|
||||
////MousedThing = nullptr;
|
||||
////MousedItemSpace = nullptr;
|
||||
|
||||
UpdateProjection();//, mx, my);
|
||||
}
|
||||
}
|
||||
private void UpdateFollow(float elapsed)
|
||||
{
|
||||
const float ythresh = 1.55f;
|
||||
const float nythresh = -1.55f;
|
||||
Vector3 up = Vector3.Up;// new Vector3(0.0f, 1.0f, 0.0f);
|
||||
if (TargetRotation.Y > ythresh) TargetRotation.Y = ythresh;
|
||||
if (TargetRotation.Y < nythresh) TargetRotation.Y = nythresh;
|
||||
float sv = Math.Min(Smoothness * elapsed, 1.0f);
|
||||
CurrentRotation = CurrentRotation + ((TargetRotation - CurrentRotation) * sv);
|
||||
|
||||
if (TargetDistance > 11000.0f) TargetDistance = 11000.0f; //11km max zoom dist
|
||||
if (TargetDistance < 0.0001f) TargetDistance = 0.0001f; //0.1mm min zoom dist...
|
||||
ZoomCurrentTime += elapsed;
|
||||
if (ZoomCurrentTime > ZoomTargetTime) ZoomCurrentTime = ZoomTargetTime;
|
||||
float currentTime = ZoomCurrentTime / ZoomTargetTime;
|
||||
float deltaDist = TargetDistance - CurrentDistance;
|
||||
if (currentTime < 1.0f && deltaDist > 0.0f)
|
||||
{
|
||||
//TODO: when to properly reset ZoomCurrentTime?
|
||||
float y = currentTime*currentTime*currentTime; //powf(currentTime, 3.0f);
|
||||
deltaDist *= y;
|
||||
}
|
||||
CurrentDistance = CurrentDistance + deltaDist * ZoomSpeed;
|
||||
|
||||
if (IsOrthographic || IsMapView)
|
||||
{
|
||||
if (OrthographicTargetSize > 20000.0f) OrthographicTargetSize = 20000.0f;
|
||||
if (OrthographicTargetSize < 1.0f) OrthographicTargetSize = 1.0f;
|
||||
OrthographicSize = OrthographicSize + ((OrthographicTargetSize - OrthographicSize) * sv);
|
||||
UpdateProj = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (IsMapView)
|
||||
{
|
||||
//in map view, need a constant view matrix aligned to XY.
|
||||
|
||||
Vector3 cpos = new Vector3();
|
||||
if (FollowEntity != null)
|
||||
{
|
||||
cpos = FollowEntity.Position;
|
||||
}
|
||||
LocalLookAt = Vector3.Zero;
|
||||
Position = cpos;
|
||||
//Position.Z = 1000.0f;
|
||||
ViewDirection = -Vector3.UnitZ;
|
||||
UpDirection = Vector3.UnitY;
|
||||
}
|
||||
else
|
||||
{
|
||||
//normal view mode
|
||||
|
||||
Vector3 rdir = new Vector3();
|
||||
float cryd = (float)Math.Cos(CurrentRotation.Y);
|
||||
rdir.X = -(float)Math.Sin(-CurrentRotation.X) * cryd;
|
||||
rdir.Z = -(float)Math.Cos(-CurrentRotation.X) * cryd;
|
||||
rdir.Y = (float)Math.Sin(CurrentRotation.Y);
|
||||
Vector3 lookat = new Vector3(0.0f, VOffset, 0.0f);
|
||||
Vector3 cpos = new Vector3();
|
||||
if (FollowEntity != null)
|
||||
{
|
||||
up = FollowEntity.Orientation.Multiply(up);
|
||||
lookat = FollowEntity.Orientation.Multiply(lookat);
|
||||
rdir = FollowEntity.Orientation.Multiply(rdir);
|
||||
cpos = FollowEntity.Position;
|
||||
}
|
||||
LocalLookAt = (rdir * CurrentDistance) + lookat;
|
||||
Position = cpos + LocalLookAt;
|
||||
ViewDirection = Vector3.Normalize(-rdir);
|
||||
UpDirection = up;
|
||||
}
|
||||
|
||||
|
||||
//M16FLookAt(LocalProjection.ViewMatrix, V3F(0.0f, 0.0f, 0.0f), LocalProjection.ViewDirection, LocalProjection.UpDirection);
|
||||
ViewQuaternion = Quaternion.LookAtRH(Vector3.Zero, ViewDirection, UpDirection);
|
||||
ViewInvQuaternion = Quaternion.Invert(ViewQuaternion);
|
||||
ViewMatrix = ViewQuaternion.ToMatrix();
|
||||
ViewInvMatrix = Matrix.Invert(ViewMatrix);
|
||||
|
||||
}
|
||||
private void UpdateProjMatrix()
|
||||
{
|
||||
if (IsMapView)
|
||||
{
|
||||
ProjMatrix = Matrix.OrthoRH(AspectRatio * OrthographicSize, OrthographicSize, 1.0f, 3000.0f);
|
||||
}
|
||||
else if (IsOrthographic)
|
||||
{
|
||||
ProjMatrix = Matrix.OrthoRH(AspectRatio * OrthographicSize, OrthographicSize, ZNear, ZFar);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProjMatrix = Matrix.PerspectiveFovRH(FieldOfView, AspectRatio, ZNear, ZFar);
|
||||
}
|
||||
//ProjMatrix._33/=ZFar;
|
||||
//ProjMatrix._43/=ZFar;
|
||||
UpdateProj = false;
|
||||
}
|
||||
private void UpdateProjection() //CameraSpaceProjection& p, float mx, float my)
|
||||
{
|
||||
float mx = MouseX;
|
||||
float my = MouseY;
|
||||
ViewProjMatrix = Matrix.Multiply(ViewMatrix, ProjMatrix);
|
||||
ViewProjInvMatrix = Matrix.Invert(ViewProjMatrix);
|
||||
MouseRayNear = ViewProjInvMatrix.MultiplyW(new Vector3(mx, my, 0.0f));
|
||||
MouseRayFar = ViewProjInvMatrix.MultiplyW(new Vector3(mx, my, 1.0f));
|
||||
MouseRay.Position = Vector3.Zero;
|
||||
MouseRay.Direction = Vector3.Normalize(MouseRayFar - MouseRayNear);
|
||||
if (IsMapView || IsOrthographic)
|
||||
{
|
||||
MouseRay.Position = MouseRayNear;
|
||||
}
|
||||
ViewFrustum.Update(ref ViewProjMatrix);
|
||||
ViewFrustum.Position = Position;
|
||||
}
|
||||
private void UpdateMousedItem()
|
||||
{
|
||||
//////MousedItem = nullptr;
|
||||
//////MousedThing = nullptr;
|
||||
//////MousedItemSpace = nullptr;
|
||||
////int i = 0;
|
||||
//////var cp = &SpaceProjections[i++];
|
||||
//////auto item = cp->MousedItem;
|
||||
//////auto thing = cp->MousedThing;
|
||||
////auto count = cp->MouseTestedItems;
|
||||
//////while((item==nullptr) && (thing==nullptr) && (i<SpaceProjections.size()))
|
||||
////Moused.Clear();
|
||||
////if (cp->Moused.HasValue) Moused.Set(cp->Moused);
|
||||
////while (!Moused.HasValue && (i < SpaceProjections.size()))
|
||||
////{
|
||||
//// cp = &SpaceProjections[i++];
|
||||
//// //item = cp->MousedItem;
|
||||
//// //thing = cp->MousedThing;
|
||||
//// if (cp->Moused.HasValue)
|
||||
//// {
|
||||
//// Moused.Set(cp->Moused);
|
||||
//// }
|
||||
//// count += cp->MouseTestedItems;
|
||||
////}
|
||||
//////if((item!=nullptr) || (thing!=nullptr))
|
||||
//////{
|
||||
////// MousedItem = item;
|
||||
////// MousedThing = thing;
|
||||
////// MousedItemSpace = cp->MousedItemSpace;
|
||||
//////}
|
||||
}
|
||||
public void OnWindowResize(int w, int h)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
Width = (float)w;
|
||||
Height = (float)h;
|
||||
AspectRatio = Width / Height;
|
||||
UpdateProj = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ControllerRotate(float x, float y)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
TargetRotation.X += x;
|
||||
TargetRotation.Y += y;
|
||||
}
|
||||
}
|
||||
|
||||
public void ControllerZoom(float z)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
float v = (z < 0) ? (1.0f - z) : (z > 0) ? (1.0f / (1.0f + z)) : 1.0f;
|
||||
TargetDistance *= v;
|
||||
OrthographicTargetSize *= v;
|
||||
}
|
||||
}
|
||||
|
||||
public void MouseRotate(int x, int y)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
TargetRotation.X += x * Sensitivity;
|
||||
TargetRotation.Y += y * Sensitivity;
|
||||
}
|
||||
}
|
||||
|
||||
public void MouseZoom(int z)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
float v = (z < 0) ? 1.1f : (z > 0) ? 1.0f / 1.1f : 1.0f;
|
||||
TargetDistance *= v;
|
||||
OrthographicTargetSize *= v;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Frustum
|
||||
{
|
||||
public Plane[] Planes = new Plane[6];
|
||||
public Vector3 Position;
|
||||
|
||||
public void Update(ref Matrix vp)
|
||||
{
|
||||
//left, right, top, bottom, near, far
|
||||
Planes[0] = Plane.Normalize(new Plane((vp.M14 + vp.M11), (vp.M24 + vp.M21), (vp.M34 + vp.M31), (vp.M44 + vp.M41)));
|
||||
Planes[1] = Plane.Normalize(new Plane((vp.M14 - vp.M11), (vp.M24 - vp.M21), (vp.M34 - vp.M31), (vp.M44 - vp.M41)));
|
||||
Planes[2] = Plane.Normalize(new Plane((vp.M14 - vp.M12), (vp.M24 - vp.M22), (vp.M34 - vp.M32), (vp.M44 - vp.M42)));
|
||||
Planes[3] = Plane.Normalize(new Plane((vp.M14 + vp.M12), (vp.M24 + vp.M22), (vp.M34 + vp.M32), (vp.M44 + vp.M42)));
|
||||
Planes[4] = Plane.Normalize(new Plane((vp.M13), (vp.M23), (vp.M33), 0.0f));//(vp.M43));
|
||||
Planes[5] = Plane.Normalize(new Plane((vp.M14 - vp.M13), (vp.M24 - vp.M23), (vp.M34 - vp.M33), (vp.M44 - vp.M43)));
|
||||
}
|
||||
|
||||
//public bool ContainsSphere(ref Vector3 c, float cls, float r)
|
||||
//{
|
||||
// //cls = c length squared, for optimization
|
||||
// if (cls < (r * r))
|
||||
// {
|
||||
// return true; //frustrum center is in the sphere
|
||||
// }
|
||||
// float nr = -r;
|
||||
// for (int i = 0; i < 6; i++)
|
||||
// {
|
||||
// if (Plane.DotCoordinate(Planes[i], c) < nr)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
public bool ContainsSphereNoClipNoOpt(ref Vector3 c, float r)
|
||||
{
|
||||
float nr = -r;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (Plane.DotCoordinate(Planes[i], c) < nr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
459
CodeWalker.Core/World/Clouds.cs
Normal file
459
CodeWalker.Core/World/Clouds.cs
Normal file
@ -0,0 +1,459 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class Clouds
|
||||
{
|
||||
public volatile bool Inited = false;
|
||||
|
||||
public Weather Weather;
|
||||
public Timecycle Timecycle;
|
||||
public Dictionary<string, CloudAnimSetting> AnimSettings { get; set; }
|
||||
public CloudAnimOverrides AnimOverrides = new CloudAnimOverrides();
|
||||
|
||||
public CloudHatManager HatManager;
|
||||
public CloudSettingsMap SettingsMap;
|
||||
|
||||
|
||||
public Clouds()
|
||||
{
|
||||
AnimSettings = new Dictionary<string, CloudAnimSetting>();
|
||||
AddAnimSetting(new CloudAnimSetting("UVOffset1.X", "UV Offset 1 X", -1.0f, 1.0f, 0.0f));
|
||||
AddAnimSetting(new CloudAnimSetting("UVOffset1.Y", "UV Offset 1 Y", -1.0f, 1.0f, 0.0f));
|
||||
AddAnimSetting(new CloudAnimSetting("UVOffset2.X", "UV Offset 2 X", -1.0f, 1.0f, 0.0f));
|
||||
AddAnimSetting(new CloudAnimSetting("UVOffset2.Y", "UV Offset 2 Y", -1.0f, 1.0f, 0.0f));
|
||||
AddAnimSetting(new CloudAnimSetting("UVOffset3.X", "UV Offset 3 X", -1.0f, 1.0f, 0.0f));
|
||||
AddAnimSetting(new CloudAnimSetting("UVOffset3.Y", "UV Offset 3 Y", -1.0f, 1.0f, 0.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("RescaleUV1.X", "Rescale UV 1 X", 0.0f, 50.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("RescaleUV1.Y", "Rescale UV 1 Y", 0.0f, 50.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("RescaleUV2.X", "Rescale UV 2 X", 0.0f, 50.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("RescaleUV2.Y", "Rescale UV 2 Y", 0.0f, 50.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("RescaleUV3.X", "Rescale UV 3 X", 0.0f, 50.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("RescaleUV3.Y", "Rescale UV 3 Y", 0.0f, 50.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale1.X", "Anim Scale 1 X", 0.0f, 8.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale1.Y", "Anim Scale 1 Y", 0.0f, 8.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale2.X", "Anim Scale 2 X", 0.0f, 8.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale2.Y", "Anim Scale 2 Y", 0.0f, 8.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale3.X", "Anim Scale 3 X", 0.0f, 8.0f, 1.0f));
|
||||
//AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale3.Y", "Anim Scale 3 Y", 0.0f, 8.0f, 1.0f));
|
||||
}
|
||||
private void AddAnimSetting(CloudAnimSetting setting)
|
||||
{
|
||||
AnimSettings[setting.Name] = setting;
|
||||
}
|
||||
private void UpdateAnimOverrides()
|
||||
{
|
||||
AnimOverrides.UVOffset1.X = AnimSettings["UVOffset1.X"].CurrentValue;
|
||||
AnimOverrides.UVOffset1.Y = AnimSettings["UVOffset1.Y"].CurrentValue;
|
||||
AnimOverrides.UVOffset2.X = AnimSettings["UVOffset2.X"].CurrentValue;
|
||||
AnimOverrides.UVOffset2.Y = AnimSettings["UVOffset2.Y"].CurrentValue;
|
||||
AnimOverrides.UVOffset3.X = AnimSettings["UVOffset3.X"].CurrentValue;
|
||||
AnimOverrides.UVOffset3.Y = AnimSettings["UVOffset3.Y"].CurrentValue;
|
||||
//AnimOverrides.RescaleUV1.X = AnimSettings["RescaleUV1.X"].CurrentValue;
|
||||
//AnimOverrides.RescaleUV1.Y = AnimSettings["RescaleUV1.Y"].CurrentValue;
|
||||
//AnimOverrides.RescaleUV2.X = AnimSettings["RescaleUV2.X"].CurrentValue;
|
||||
//AnimOverrides.RescaleUV2.Y = AnimSettings["RescaleUV2.Y"].CurrentValue;
|
||||
//AnimOverrides.RescaleUV3.X = AnimSettings["RescaleUV3.X"].CurrentValue;
|
||||
//AnimOverrides.RescaleUV3.Y = AnimSettings["RescaleUV3.Y"].CurrentValue;
|
||||
//AnimOverrides.cloudLayerAnimScale1.X = AnimSettings["cloudLayerAnimScale1.X"].CurrentValue;
|
||||
//AnimOverrides.cloudLayerAnimScale1.Y = AnimSettings["cloudLayerAnimScale1.Y"].CurrentValue;
|
||||
//AnimOverrides.cloudLayerAnimScale2.X = AnimSettings["cloudLayerAnimScale2.X"].CurrentValue;
|
||||
//AnimOverrides.cloudLayerAnimScale2.Y = AnimSettings["cloudLayerAnimScale2.Y"].CurrentValue;
|
||||
//AnimOverrides.cloudLayerAnimScale3.X = AnimSettings["cloudLayerAnimScale3.X"].CurrentValue;
|
||||
//AnimOverrides.cloudLayerAnimScale3.Y = AnimSettings["cloudLayerAnimScale3.Y"].CurrentValue;
|
||||
}
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus, Weather weather)
|
||||
{
|
||||
Weather = weather;
|
||||
Timecycle = weather.Timecycle;
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
string filename = "common.rpf\\data\\clouds.xml";
|
||||
|
||||
//TODO: RpfMan should be able to get the right version? or maybe let gameFileCache do it!
|
||||
string kffilename = "common.rpf\\data\\cloudkeyframes.xml";
|
||||
if (gameFileCache.EnableDlc)
|
||||
{
|
||||
kffilename = "update\\update.rpf\\common\\data\\cloudkeyframes.xml";
|
||||
}
|
||||
|
||||
XmlDocument cloudsxml = rpfman.GetFileXml(filename);
|
||||
XmlDocument cloudskfxml = rpfman.GetFileXml(kffilename);
|
||||
|
||||
HatManager = new CloudHatManager();
|
||||
HatManager.Init(cloudsxml.DocumentElement); //CloudHatManager
|
||||
|
||||
SettingsMap = new CloudSettingsMap();
|
||||
SettingsMap.Init(cloudskfxml.DocumentElement); //CloudSettingsMap
|
||||
|
||||
Inited = true;
|
||||
}
|
||||
|
||||
|
||||
public void Update(float elapsed)
|
||||
{
|
||||
UpdateAnimOverrides();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class CloudHatManager
|
||||
{
|
||||
public CloudHatFrag[] CloudHatFrags { get; set; }
|
||||
public float DesiredTransitionTimeSec { get; set; }
|
||||
public Vector3 CamPositionScaler { get; set; }
|
||||
public float AltitudeScrollScaler { get; set; }
|
||||
|
||||
public void Init(XmlElement xml)
|
||||
{
|
||||
List<CloudHatFrag> fraglist = new List<CloudHatFrag>();
|
||||
XmlNodeList frags = xml.SelectNodes("mCloudHatFrags/Item");
|
||||
foreach (XmlNode node in frags)
|
||||
{
|
||||
XmlElement fragel = node as XmlElement;
|
||||
if (fragel != null)
|
||||
{
|
||||
CloudHatFrag frag = new CloudHatFrag();
|
||||
frag.Init(fragel);
|
||||
fraglist.Add(frag);
|
||||
}
|
||||
}
|
||||
CloudHatFrags = fraglist.ToArray();
|
||||
|
||||
DesiredTransitionTimeSec = Xml.GetChildFloatAttribute(xml, "mDesiredTransitionTimeSec", "value");
|
||||
CamPositionScaler = Xml.GetChildVector3Attributes(xml, "mCamPositionScaler", "x", "y", "z");
|
||||
AltitudeScrollScaler = Xml.GetChildFloatAttribute(xml, "mAltitudeScrollScaler", "value");
|
||||
}
|
||||
|
||||
public CloudHatFrag FindFrag(string name)
|
||||
{
|
||||
for (int i = 0; i < CloudHatFrags.Length; i++)
|
||||
{
|
||||
CloudHatFrag f = CloudHatFrags[i];
|
||||
if (f.Name == name)
|
||||
{
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CloudHatFrag
|
||||
{
|
||||
public Vector3 Position { get; set; }
|
||||
public Vector3 Rotation { get; set; }
|
||||
public Vector3 Scale { get; set; }
|
||||
public string Name { get; set; }
|
||||
public CloudHatFragLayer[] Layers { get; set; }
|
||||
public float TransitionAlphaRange { get; set; }
|
||||
public float TransitionMidPoint { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public Vector3 AngularVelocity { get; set; }
|
||||
public Vector3 AnimBlendWeights { get; set; }
|
||||
public Vector2[] UVVelocity { get; set; }
|
||||
public byte[] AnimMode { get; set; }
|
||||
public bool[] ShowLayer { get; set; }
|
||||
public bool EnableAnimations { get; set; }
|
||||
|
||||
public void Init(XmlElement xml)
|
||||
{
|
||||
Position = Xml.GetChildVector3Attributes(xml, "mPosition", "x", "y", "z");
|
||||
Rotation = Xml.GetChildVector3Attributes(xml, "mRotation", "x", "y", "z");
|
||||
Scale = Xml.GetChildVector3Attributes(xml, "mScale", "x", "y", "z");
|
||||
Name = Xml.GetChildInnerText(xml, "mName");
|
||||
|
||||
List<CloudHatFragLayer> layerlist = new List<CloudHatFragLayer>();
|
||||
XmlNodeList layersxml = xml.SelectNodes("mLayers/Item");
|
||||
foreach (XmlNode node in layersxml)
|
||||
{
|
||||
XmlElement layerel = node as XmlElement;
|
||||
if (layerel != null)
|
||||
{
|
||||
CloudHatFragLayer layer = new CloudHatFragLayer();
|
||||
layer.Init(layerel);
|
||||
layerlist.Add(layer);
|
||||
}
|
||||
}
|
||||
Layers = layerlist.ToArray();
|
||||
|
||||
TransitionAlphaRange = Xml.GetChildFloatAttribute(xml, "mTransitionAlphaRange", "value");
|
||||
TransitionMidPoint = Xml.GetChildFloatAttribute(xml, "mTransitionMidPoint", "value");
|
||||
Enabled = Xml.GetChildBoolAttribute(xml, "mEnabled", "value");
|
||||
AngularVelocity = Xml.GetChildVector3Attributes(xml, "mAngularVelocity", "x", "y", "z");
|
||||
AnimBlendWeights = Xml.GetChildVector3Attributes(xml, "mAnimBlendWeights", "x", "y", "z");
|
||||
|
||||
string uvvelocitystr = Xml.GetChildInnerText(xml, "mUVVelocity").Trim();
|
||||
string[] uvvelocities = uvvelocitystr.Split('\n');
|
||||
UVVelocity = new Vector2[uvvelocities.Length];
|
||||
for (int i = 0; i < uvvelocities.Length; i++)
|
||||
{
|
||||
Vector2 vel = Vector2.Zero;
|
||||
string uvvel = uvvelocities[i].Trim();
|
||||
string[] uvvelc = uvvel.Split('\t');
|
||||
if (uvvelc.Length == 2)
|
||||
{
|
||||
FloatUtil.TryParse(uvvelc[0].Trim(), out vel.X);
|
||||
FloatUtil.TryParse(uvvelc[1].Trim(), out vel.Y);
|
||||
}
|
||||
UVVelocity[i] = vel;
|
||||
}
|
||||
|
||||
string animmodestr = Xml.GetChildInnerText(xml, "mAnimMode").Trim();
|
||||
string[] animmodes = animmodestr.Split('\n');
|
||||
AnimMode = new byte[animmodes.Length];
|
||||
for (int i = 0; i < animmodes.Length; i++)
|
||||
{
|
||||
byte.TryParse(animmodes[i].Trim(), out AnimMode[i]);
|
||||
}
|
||||
|
||||
|
||||
//string showlayerstr = Xml.GetChildInnerText(xml, "mShowLayer").Trim();
|
||||
XmlNodeList showlayersxml = xml.SelectNodes("mShowLayer/Item");
|
||||
ShowLayer = new bool[showlayersxml.Count];
|
||||
for (int i = 0; i < showlayersxml.Count; i++)
|
||||
{
|
||||
XmlNode slnode = showlayersxml[i];
|
||||
if (slnode is XmlElement)
|
||||
{
|
||||
ShowLayer[i] = Xml.GetBoolAttribute(slnode, "value");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EnableAnimations = Xml.GetChildBoolAttribute(xml, "mEnableAnimations", "value");
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
public class CloudHatFragLayer
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public float CostFactor { get; set; }
|
||||
public float RotationScale { get; set; }
|
||||
public float CamPositionScalerAdjust { get; set; }
|
||||
public float TransitionInTimePercent { get; set; }
|
||||
public float TransitionOutTimePercent { get; set; }
|
||||
public float TransitionInDelayPercent { get; set; }
|
||||
public float TransitionOutDelayPercent { get; set; }
|
||||
public float HeightTigger { get; set; }
|
||||
public float HeightFadeRange { get; set; }
|
||||
|
||||
public void Init(XmlElement xml)
|
||||
{
|
||||
Filename = Xml.GetChildInnerText(xml, "mFilename");
|
||||
CostFactor = Xml.GetChildFloatAttribute(xml, "mCostFactor", "value");
|
||||
RotationScale = Xml.GetChildFloatAttribute(xml, "mRotationScale", "value");
|
||||
CamPositionScalerAdjust = Xml.GetChildFloatAttribute(xml, "mCamPositionScalerAdjust", "value");
|
||||
TransitionInTimePercent = Xml.GetChildFloatAttribute(xml, "mTransitionInTimePercent", "value");
|
||||
TransitionOutTimePercent = Xml.GetChildFloatAttribute(xml, "mTransitionOutTimePercent", "value");
|
||||
TransitionInDelayPercent = Xml.GetChildFloatAttribute(xml, "mTransitionInDelayPercent", "value");
|
||||
TransitionOutDelayPercent = Xml.GetChildFloatAttribute(xml, "mTransitionOutDelayPercent", "value");
|
||||
HeightTigger = Xml.GetChildFloatAttribute(xml, "mHeightTigger", "value");
|
||||
HeightFadeRange = Xml.GetChildFloatAttribute(xml, "mHeightFadeRange", "value");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class CloudSettingsMap
|
||||
{
|
||||
public float[] KeyframeTimes { get; set; }
|
||||
public Dictionary<string, CloudSettingsMapItem> SettingsMap { get; set; }
|
||||
|
||||
public void Init(XmlElement xml)
|
||||
{
|
||||
|
||||
string kftstr = Xml.GetChildInnerText(xml, "KeyframeTimes").Trim();
|
||||
string[] kftarr = kftstr.Split('\n');
|
||||
KeyframeTimes = new float[kftarr.Length];
|
||||
for (int i = 0; i < kftarr.Length; i++)
|
||||
{
|
||||
FloatUtil.TryParse(kftarr[i].Trim(), out KeyframeTimes[i]);
|
||||
}
|
||||
|
||||
|
||||
SettingsMap = new Dictionary<string, CloudSettingsMapItem>();
|
||||
XmlNodeList mapxml = xml.SelectNodes("SettingsMap/Item");
|
||||
foreach (XmlNode node in mapxml)
|
||||
{
|
||||
XmlElement itemel = node as XmlElement;
|
||||
if (itemel != null)
|
||||
{
|
||||
CloudSettingsMapItem item = new CloudSettingsMapItem();
|
||||
item.Init(itemel);
|
||||
SettingsMap[item.Name] = item;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class CloudSettingsMapItem
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public CloudSettingsMapCloudList CloudList { get; set; } = new CloudSettingsMapCloudList();
|
||||
public CloudSettingsMapKeyData CloudColor { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudLightColor { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudAmbientColor { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudSkyColor { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudBounceColor { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudEastColor { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudWestColor { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudScaleFillColors { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudDensityShift_Scale_ScatteringConst_Scale { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudPiercingLightPower_Strength_NormalStrength_Thickness { get; set; } = new CloudSettingsMapKeyData();
|
||||
public CloudSettingsMapKeyData CloudScaleDiffuseFillAmbient_WrapAmount { get; set; } = new CloudSettingsMapKeyData();
|
||||
|
||||
public void Init(XmlNode xml)
|
||||
{
|
||||
Name = Xml.GetChildInnerText(xml, "Name");
|
||||
var snode = xml.SelectSingleNode("Settings");
|
||||
CloudList.Init(snode.SelectSingleNode("CloudList"));
|
||||
CloudColor.Init(snode.SelectSingleNode("CloudColor"));
|
||||
CloudLightColor.Init(snode.SelectSingleNode("CloudLightColor"));
|
||||
CloudAmbientColor.Init(snode.SelectSingleNode("CloudAmbientColor"));
|
||||
CloudSkyColor.Init(snode.SelectSingleNode("CloudSkyColor"));
|
||||
CloudBounceColor.Init(snode.SelectSingleNode("CloudBounceColor"));
|
||||
CloudEastColor.Init(snode.SelectSingleNode("CloudEastColor"));
|
||||
CloudWestColor.Init(snode.SelectSingleNode("CloudWestColor"));
|
||||
CloudScaleFillColors.Init(snode.SelectSingleNode("CloudScaleFillColors"));
|
||||
CloudDensityShift_Scale_ScatteringConst_Scale.Init(snode.SelectSingleNode("CloudDensityShift_Scale_ScatteringConst_Scale"));
|
||||
CloudPiercingLightPower_Strength_NormalStrength_Thickness.Init(snode.SelectSingleNode("CloudPiercingLightPower_Strength_NormalStrength_Thickness"));
|
||||
CloudScaleDiffuseFillAmbient_WrapAmount.Init(snode.SelectSingleNode("CloudScaleDiffuseFillAmbient_WrapAmount"));
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
public class CloudSettingsMapCloudList
|
||||
{
|
||||
public int[] Probability { get; set; }
|
||||
public int[] Bits { get; set; } //one bit for each cloud hat frag
|
||||
|
||||
public void Init(XmlNode xml)
|
||||
{
|
||||
string pstr = Xml.GetChildInnerText(xml, "mProbability").Trim();
|
||||
string bstr = Xml.GetChildInnerText(xml, "mBits").Trim();
|
||||
|
||||
string[] parr = pstr.Split('\n');
|
||||
string[] barr = bstr.Split('\n');
|
||||
|
||||
Probability = new int[parr.Length];
|
||||
Bits = new int[barr.Length];
|
||||
|
||||
for (int i = 0; i < parr.Length; i++)
|
||||
{
|
||||
int.TryParse(parr[i].Trim(), out Probability[i]);
|
||||
}
|
||||
for (int i = 0; i < barr.Length; i++)
|
||||
{
|
||||
Bits[i] = Convert.ToInt32(barr[i].Trim(), 16);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CloudSettingsMapKeyData
|
||||
{
|
||||
public int numKeyEntries { get; set; }
|
||||
public Dictionary<float, Vector4> keyEntryData { get; set; }
|
||||
|
||||
public void Init(XmlNode xml)
|
||||
{
|
||||
var kdxml = xml.SelectSingleNode("keyData");
|
||||
|
||||
numKeyEntries = Xml.GetChildIntAttribute(kdxml, "numKeyEntries", "value");
|
||||
|
||||
string kestr = Xml.GetChildInnerText(kdxml, "keyEntryData").Trim();
|
||||
string[] kearr = kestr.Split('\n');
|
||||
keyEntryData = new Dictionary<float, Vector4>();
|
||||
for (int i = 0; i < kearr.Length; i++)
|
||||
{
|
||||
string kvstr = kearr[i].Trim();
|
||||
string[] kvarr = kvstr.Split('\t');
|
||||
float key = 0.0f;
|
||||
Vector4 val = Vector4.Zero;
|
||||
if (kvarr.Length >= 5)
|
||||
{
|
||||
FloatUtil.TryParse(kvarr[0].Trim(), out key);
|
||||
FloatUtil.TryParse(kvarr[1].Trim(), out val.X);
|
||||
FloatUtil.TryParse(kvarr[2].Trim(), out val.Y);
|
||||
FloatUtil.TryParse(kvarr[3].Trim(), out val.Z);
|
||||
FloatUtil.TryParse(kvarr[4].Trim(), out val.W);
|
||||
}
|
||||
else
|
||||
{ }
|
||||
keyEntryData[key] = val;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class CloudAnimSetting
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public float MinValue { get; set; }
|
||||
public float MaxValue { get; set; }
|
||||
public float DefaultValue { get; set; }
|
||||
public float CurrentValue { get; set; }
|
||||
|
||||
|
||||
public CloudAnimSetting(string name, string displayname, float minval, float maxval, float defaultval)
|
||||
{
|
||||
Name = name;
|
||||
DisplayName = displayname;
|
||||
MinValue = minval;
|
||||
MaxValue = maxval;
|
||||
DefaultValue = defaultval;
|
||||
CurrentValue = defaultval;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return DisplayName;
|
||||
}
|
||||
}
|
||||
|
||||
public class CloudAnimOverrides
|
||||
{
|
||||
public Vector2 UVOffset1 = Vector2.Zero;
|
||||
public Vector2 UVOffset2 = Vector2.Zero;
|
||||
public Vector2 UVOffset3 = Vector2.Zero;
|
||||
public Vector2 RescaleUV1 = Vector2.One;
|
||||
public Vector2 RescaleUV2 = Vector2.One;
|
||||
public Vector2 RescaleUV3 = Vector2.One;
|
||||
public Vector2 cloudLayerAnimScale1 = Vector2.One;
|
||||
public Vector2 cloudLayerAnimScale2 = Vector2.One;
|
||||
public Vector2 cloudLayerAnimScale3 = Vector2.One;
|
||||
}
|
||||
|
||||
}
|
179
CodeWalker.Core/World/Entity.cs
Normal file
179
CodeWalker.Core/World/Entity.cs
Normal file
@ -0,0 +1,179 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class Entity
|
||||
{
|
||||
public Space Space;
|
||||
public YmapEntityDef EntityDef;
|
||||
|
||||
public float Radius;
|
||||
public Vector3 Center;
|
||||
public Vector3 Position;
|
||||
public Quaternion Orientation = Quaternion.Identity;
|
||||
public Quaternion OrientationInv = Quaternion.Identity;
|
||||
|
||||
public float Mass;
|
||||
public Matrix MomentOfInertia;
|
||||
public Vector3 Momentum;
|
||||
public Vector3 Velocity;
|
||||
public Vector3 AngularMomentum;
|
||||
public Vector3 AngularVelocity;
|
||||
|
||||
public bool WasColliding;
|
||||
|
||||
public bool EnableCollisions;
|
||||
public bool Enabled;
|
||||
|
||||
|
||||
//public CollisionShape ..
|
||||
|
||||
public virtual void PreUpdate(float elapsed)
|
||||
{ }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class PedEntity : Entity
|
||||
{
|
||||
|
||||
public Vector2 ControlMovement;
|
||||
public bool ControlJump;
|
||||
public bool ControlBoost;
|
||||
|
||||
public Vector3 ForwardVec;
|
||||
|
||||
public Quaternion CameraOrientation = Quaternion.LookAtLH(Vector3.Zero, Vector3.Up, Vector3.ForwardLH);
|
||||
public Entity CameraEntity = new Entity();
|
||||
|
||||
public bool OnGround = false;
|
||||
|
||||
|
||||
public PedEntity()
|
||||
{
|
||||
Radius = 0.5f;
|
||||
Center = new Vector3(0.0f, 0.0f, -1.2f); //base collision point is 1.7m below center... for camera offset
|
||||
|
||||
Mass = 80.0f;
|
||||
|
||||
ForwardVec = Vector3.UnitY;
|
||||
CameraEntity.Orientation = CameraOrientation;
|
||||
CameraEntity.OrientationInv = Quaternion.Invert(Orientation);
|
||||
}
|
||||
|
||||
public override void PreUpdate(float elapsed)
|
||||
{
|
||||
|
||||
//float rotspd = 0.5f;
|
||||
float movspd = 10.0f;
|
||||
float velspd = 10.0f;
|
||||
float jmpvel = 3.0f;
|
||||
float boostmult = 10.0f;
|
||||
if (ControlBoost) movspd *= boostmult;
|
||||
|
||||
Quaternion rot = Quaternion.Identity;// .RotationAxis(Vector3.UnitZ, -ControlMovement.X * rotspd * elapsed);
|
||||
Quaternion ori = Quaternion.Multiply(Orientation, rot);
|
||||
SetOrientation(ori);
|
||||
|
||||
|
||||
float jmpamt = (ControlJump ? jmpvel : 0);
|
||||
Vector3 curvel = Velocity;
|
||||
Vector3 controlvel = new Vector3(ControlMovement * movspd, jmpamt);
|
||||
Vector3 targetvel = controlvel + new Vector3(0, 0, curvel.Z);
|
||||
Vector3 newvel = curvel + (targetvel - curvel) * velspd * elapsed;
|
||||
Velocity = newvel;
|
||||
var coll = Space.FindFirstCollision(this, elapsed);
|
||||
if (coll.Hit)
|
||||
{
|
||||
Vector3 collpos = coll.PrePos; //last known ok position
|
||||
Vector3 disp = Velocity * elapsed;
|
||||
Vector3 oldpos = Position;
|
||||
Vector3 targetpos = Position + disp;
|
||||
float displ = disp.Length();
|
||||
|
||||
//////BoundingSphere sph = new BoundingSphere(targetpos + Center, Radius);
|
||||
//////r.SphereHit = SphereIntersect(sph);
|
||||
|
||||
if ((disp.Z > -0.25f))/* && (displ < Radius * 2.0f)*/
|
||||
{
|
||||
Vector3 raydir = new Vector3(0.0f, 0.0f, -1.0f);
|
||||
Vector3 rayoff = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
Ray ray = new Ray(targetpos + Center + rayoff, raydir);
|
||||
var rayhit = Space.RayIntersect(ray, 1.0f);
|
||||
if (rayhit.Hit)
|
||||
{
|
||||
if (rayhit.HitDist > 0)
|
||||
{
|
||||
Position = rayhit.Position - Center + new Vector3(0, 0, Radius);
|
||||
//collpos = Position;//targetpos;//
|
||||
}
|
||||
else
|
||||
{
|
||||
//the start of the ray was a collision... can't move here
|
||||
Position = collpos;
|
||||
}
|
||||
}
|
||||
else //might happen when about to go off a big drop?
|
||||
{
|
||||
Position = targetpos;// collpos;
|
||||
//collpos = targetpos;
|
||||
}
|
||||
}
|
||||
else //moving fast...
|
||||
{
|
||||
Position = collpos; //last known ok position
|
||||
}
|
||||
//Position = collpos; //last known ok position
|
||||
|
||||
|
||||
|
||||
bool wasOnGround = OnGround;
|
||||
OnGround = (Vector3.Dot(coll.SphereHit.Normal, Vector3.UnitZ) > 0.8f);
|
||||
if (OnGround)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Vector3 findisp = Position - oldpos;
|
||||
float findispl = findisp.Length();
|
||||
float fdisp = Math.Min(displ, findispl);
|
||||
Vector3 dispdir = findisp / Math.Max(findispl, 0.0001f);
|
||||
float absvel = fdisp / Math.Max(elapsed, 0.0001f);
|
||||
Velocity = dispdir * absvel;
|
||||
|
||||
//Vector3 veldir = Vector3.Normalize(Position - oldpos);
|
||||
//float vellen = (collpos - oldpos).Length() / Math.Max(elapsed, 0.0001f);
|
||||
//Velocity = veldir * vellen;
|
||||
|
||||
//Velocity = (Position - oldpos) / Math.Max(elapsed, 0.0001f);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Position = coll.HitPos; //hitpos is the end pos if not hit
|
||||
OnGround = false;
|
||||
}
|
||||
|
||||
CameraEntity.Position = Position;
|
||||
}
|
||||
|
||||
|
||||
private void SetOrientation(Quaternion ori)
|
||||
{
|
||||
Orientation = ori;
|
||||
OrientationInv = Quaternion.Invert(Orientation);
|
||||
CameraEntity.Orientation = Quaternion.Multiply(Orientation, CameraOrientation);
|
||||
CameraEntity.OrientationInv = Quaternion.Invert(Orientation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
206
CodeWalker.Core/World/PopZones.cs
Normal file
206
CodeWalker.Core/World/PopZones.cs
Normal file
@ -0,0 +1,206 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class PopZones : BasePathData
|
||||
{
|
||||
public volatile bool Inited = false;
|
||||
public GameFileCache GameFileCache;
|
||||
|
||||
public Dictionary<string, PopZone> Groups = new Dictionary<string, PopZone>();
|
||||
|
||||
public Vector4[] GetNodePositions()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public EditorVertex[] GetPathVertices()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public EditorVertex[] GetTriangleVertices()
|
||||
{
|
||||
return TriangleVerts;
|
||||
}
|
||||
|
||||
public EditorVertex[] TriangleVerts;
|
||||
|
||||
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||
{
|
||||
Inited = false;
|
||||
|
||||
GameFileCache = gameFileCache;
|
||||
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
string filename = "common.rpf\\data\\levels\\gta5\\popzone.ipl";
|
||||
if (gameFileCache.EnableDlc)
|
||||
{
|
||||
filename = "update\\update.rpf\\common\\data\\levels\\gta5\\popzone.ipl";
|
||||
}
|
||||
|
||||
string ipltext = rpfman.GetFileUTF8Text(filename);
|
||||
|
||||
if (string.IsNullOrEmpty(ipltext))
|
||||
{
|
||||
ipltext = "";
|
||||
}
|
||||
|
||||
Groups.Clear();
|
||||
|
||||
var ipllines = ipltext.Split('\n');
|
||||
bool inzone = false;
|
||||
foreach (var iplline in ipllines)
|
||||
{
|
||||
var linet = iplline.Trim();
|
||||
if (linet == "zone")
|
||||
{
|
||||
inzone = true;
|
||||
}
|
||||
else if (linet == "end")
|
||||
{
|
||||
inzone = false;
|
||||
}
|
||||
else if (inzone)
|
||||
{
|
||||
PopZoneBox box = new PopZoneBox();
|
||||
box.Init(linet);
|
||||
|
||||
PopZone group;
|
||||
if (!Groups.TryGetValue(box.NameLabel, out group))
|
||||
{
|
||||
group = new PopZone();
|
||||
group.NameLabel = box.NameLabel;
|
||||
Groups[box.NameLabel] = group;
|
||||
}
|
||||
|
||||
group.Boxes.Add(box);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var group in Groups.Values)
|
||||
{
|
||||
var hash = JenkHash.GenHash(group.NameLabel.ToLowerInvariant());
|
||||
group.Name = GlobalText.TryGetString(hash);
|
||||
}
|
||||
|
||||
|
||||
BuildVertices();
|
||||
|
||||
Inited = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void BuildVertices()
|
||||
{
|
||||
|
||||
var vlist = new List<EditorVertex>();
|
||||
var v1 = new EditorVertex();
|
||||
var v2 = new EditorVertex();
|
||||
var v3 = new EditorVertex();
|
||||
var v4 = new EditorVertex();
|
||||
|
||||
foreach (var group in Groups.Values)
|
||||
{
|
||||
var hash = JenkHash.GenHash(group.NameLabel.ToLowerInvariant());
|
||||
byte cr = (byte)((hash >> 8) & 0xFF);
|
||||
byte cg = (byte)((hash >> 16) & 0xFF);
|
||||
byte cb = (byte)((hash >> 24) & 0xFF);
|
||||
byte ca = 60;
|
||||
uint cv = (uint)new Color(cr, cg, cb, ca).ToRgba();
|
||||
v1.Colour = cv;
|
||||
v2.Colour = cv;
|
||||
v3.Colour = cv;
|
||||
v4.Colour = cv;
|
||||
|
||||
foreach (var box in group.Boxes)
|
||||
{
|
||||
var min = box.Box.Minimum;
|
||||
var max = box.Box.Maximum;
|
||||
|
||||
v1.Position = new Vector3(min.X, min.Y, 0);
|
||||
v2.Position = new Vector3(max.X, min.Y, 0);
|
||||
v3.Position = new Vector3(min.X, max.Y, 0);
|
||||
v4.Position = new Vector3(max.X, max.Y, 0);
|
||||
|
||||
vlist.Add(v1);
|
||||
vlist.Add(v2);
|
||||
vlist.Add(v3);
|
||||
vlist.Add(v3);
|
||||
vlist.Add(v2);
|
||||
vlist.Add(v4);
|
||||
}
|
||||
}
|
||||
|
||||
if (vlist.Count > 0)
|
||||
{
|
||||
TriangleVerts = vlist.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
TriangleVerts = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class PopZone
|
||||
{
|
||||
public string NameLabel { get; set; }
|
||||
public string Name { get; set; } //lookup from gxt2 with label..?
|
||||
public List<PopZoneBox> Boxes { get; set; } = new List<PopZoneBox>();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return NameLabel + ": " + Name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class PopZoneBox
|
||||
{
|
||||
public string ID { get; set; }
|
||||
public BoundingBox Box { get; set; }
|
||||
public string NameLabel { get; set; }
|
||||
public float UnkVal { get; set; }
|
||||
|
||||
|
||||
public void Init(string iplline)
|
||||
{
|
||||
var parts = iplline.Split(',');
|
||||
if (parts.Length >= 9)
|
||||
{
|
||||
ID = parts[0].Trim();
|
||||
BoundingBox b = new BoundingBox();
|
||||
b.Minimum.X = FloatUtil.Parse(parts[1].Trim());
|
||||
b.Minimum.Y = FloatUtil.Parse(parts[2].Trim());
|
||||
b.Minimum.Z = FloatUtil.Parse(parts[3].Trim());
|
||||
b.Maximum.X = FloatUtil.Parse(parts[4].Trim());
|
||||
b.Maximum.Y = FloatUtil.Parse(parts[5].Trim());
|
||||
b.Maximum.Z = FloatUtil.Parse(parts[6].Trim());
|
||||
Box = b;
|
||||
NameLabel = parts[7].Trim();
|
||||
UnkVal = FloatUtil.Parse(parts[8].Trim());
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ID + ": " + NameLabel + ": " + Box.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1898
CodeWalker.Core/World/Scenarios.cs
Normal file
1898
CodeWalker.Core/World/Scenarios.cs
Normal file
File diff suppressed because it is too large
Load Diff
2139
CodeWalker.Core/World/Space.cs
Normal file
2139
CodeWalker.Core/World/Space.cs
Normal file
File diff suppressed because it is too large
Load Diff
124
CodeWalker.Core/World/Timecycle.cs
Normal file
124
CodeWalker.Core/World/Timecycle.cs
Normal file
@ -0,0 +1,124 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class Timecycle
|
||||
{
|
||||
public volatile bool Inited = false;
|
||||
|
||||
public float sun_roll { get; set; }
|
||||
public float sun_yaw { get; set; }
|
||||
public float moon_roll { get; set; }
|
||||
public float moon_wobble_freq { get; set; }
|
||||
public float moon_wobble_amp { get; set; }
|
||||
public float moon_wobble_offset { get; set; }
|
||||
public List<TimecycleSample> Samples { get; set; } = new List<TimecycleSample>();
|
||||
public List<string> Regions { get; set; } = new List<string>();
|
||||
|
||||
public float CurrentHour { get; set; } = 0;
|
||||
public int CurrentSampleIndex { get; set; } = 0;
|
||||
public float CurrentSampleBlend { get; set; } = 1.0f;
|
||||
public float NextSampleBlend { get; set; } = 0.0f;
|
||||
public Vector3 CurrentSunDirection { get; set; } = new Vector3(0, 0, 1);
|
||||
public Vector3 CurrentMoonDirection { get; set; } = new Vector3(0, 0, -1);
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||
{
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
string filename = "common.rpf\\data\\levels\\gta5\\time.xml";
|
||||
|
||||
XmlDocument timexml = rpfman.GetFileXml(filename);
|
||||
|
||||
XmlElement time = timexml.DocumentElement;
|
||||
XmlNode suninfo = time.SelectSingleNode("suninfo");
|
||||
XmlNode mooninfo = time.SelectSingleNode("mooninfo");
|
||||
XmlNodeList samples = time.SelectNodes("sample");
|
||||
XmlNodeList regions = time.SelectNodes("region");
|
||||
|
||||
sun_roll = Xml.GetFloatAttribute(suninfo, "sun_roll");
|
||||
sun_yaw = Xml.GetFloatAttribute(suninfo, "sun_yaw");
|
||||
moon_roll = Xml.GetFloatAttribute(mooninfo, "moon_roll");
|
||||
moon_wobble_freq = Xml.GetFloatAttribute(mooninfo, "moon_wobble_freq");
|
||||
moon_wobble_amp = Xml.GetFloatAttribute(mooninfo, "moon_wobble_amp");
|
||||
moon_wobble_offset = Xml.GetFloatAttribute(mooninfo, "moon_wobble_offset");
|
||||
|
||||
Samples.Clear();
|
||||
for (int i = 0; i < samples.Count; i++)
|
||||
{
|
||||
TimecycleSample tcs = new TimecycleSample();
|
||||
tcs.Init(samples[i]);
|
||||
Samples.Add(tcs);
|
||||
}
|
||||
|
||||
Regions.Clear();
|
||||
for (int i = 0; i < regions.Count; i++)
|
||||
{
|
||||
Regions.Add(Xml.GetStringAttribute(regions[i], "name"));
|
||||
}
|
||||
|
||||
Inited = true;
|
||||
}
|
||||
|
||||
|
||||
public void SetTime(float hour)
|
||||
{
|
||||
float day = Math.Max(hour / 24.0f, 0.0f);
|
||||
float h = hour - ((float)Math.Floor(day) * 24.0f);
|
||||
CurrentHour = h;
|
||||
|
||||
for (int i = 0; i < Samples.Count; i++)
|
||||
{
|
||||
bool lasti = (i >= Samples.Count - 1);
|
||||
var cur = Samples[i];
|
||||
var nxt = Samples[lasti ? 0 : i+1];
|
||||
var nxth = lasti ? nxt.hour + 24.0f : nxt.hour;
|
||||
if (((h >= cur.hour) && (h < nxth)) || lasti)
|
||||
{
|
||||
float blendrange = (nxth - cur.hour) - cur.duration;
|
||||
float blendstart = cur.hour + cur.duration;
|
||||
float blendrel = h - blendstart;
|
||||
float blendval = blendrel / blendrange;
|
||||
float blend = Math.Min(Math.Max(blendval, 0.0f), 1.0f);
|
||||
NextSampleBlend = blend;
|
||||
CurrentSampleBlend = 1.0f - blend;
|
||||
CurrentSampleIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsNightTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (CurrentHour < 6.0f) || (CurrentHour > 20.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TimecycleSample
|
||||
{
|
||||
public string name { get; set; }
|
||||
public float hour { get; set; }
|
||||
public float duration { get; set; }
|
||||
public string uw_tc_mod { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
name = Xml.GetStringAttribute(node, "name");
|
||||
hour = Xml.GetFloatAttribute(node, "hour");
|
||||
duration = Xml.GetFloatAttribute(node, "duration");
|
||||
uw_tc_mod = Xml.GetStringAttribute(node, "uw_tc_mod");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
148
CodeWalker.Core/World/TimecycleMods.cs
Normal file
148
CodeWalker.Core/World/TimecycleMods.cs
Normal file
@ -0,0 +1,148 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class TimecycleMods
|
||||
{
|
||||
|
||||
public Dictionary<uint, TimecycleMod> Dict = new Dictionary<uint, TimecycleMod>();
|
||||
|
||||
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||
{
|
||||
Dict.Clear();
|
||||
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_1.xml"));
|
||||
LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_2.xml"));
|
||||
LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_3.xml"));
|
||||
LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_4.xml"));
|
||||
|
||||
LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_1.xml"));
|
||||
LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_2.xml"));//doesn't exist, but try anyway
|
||||
LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_3.xml"));
|
||||
LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_4.xml"));
|
||||
|
||||
if (gameFileCache.EnableDlc)
|
||||
{
|
||||
foreach (var dlcrpf in gameFileCache.DlcActiveRpfs)
|
||||
{
|
||||
foreach (var file in dlcrpf.AllEntries)
|
||||
{
|
||||
if (file.NameLower.EndsWith(".xml") && file.NameLower.StartsWith("timecycle_mods_"))
|
||||
{
|
||||
LoadXml(rpfman.GetFileXml(file.Path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gameFileCache.TimeCycleModsDict = Dict;
|
||||
}
|
||||
|
||||
private void LoadXml(XmlDocument doc)
|
||||
{
|
||||
var root = doc.DocumentElement;
|
||||
if (root == null)
|
||||
{ return; }
|
||||
|
||||
float version = Xml.GetFloatAttribute(root, "version");
|
||||
|
||||
var modnodes = root.SelectNodes("modifier");
|
||||
foreach (XmlNode modnode in modnodes)
|
||||
{
|
||||
if (!(modnode is XmlElement)) continue;
|
||||
TimecycleMod mod = new TimecycleMod();
|
||||
mod.Init(modnode);
|
||||
Dict[mod.nameHash] = mod;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public class TimecycleMod
|
||||
{
|
||||
public string name { get; set; }
|
||||
public uint nameHash { get; set; }
|
||||
public int numMods { get; set; }
|
||||
public int userFlags { get; set; }
|
||||
|
||||
public TimecycleModValue[] Values { get; set; }
|
||||
public Dictionary<string, TimecycleModValue> Dict { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
Dict = new Dictionary<string, TimecycleModValue>();
|
||||
|
||||
name = Xml.GetStringAttribute(node, "name");
|
||||
numMods = Xml.GetIntAttribute(node, "numMods");
|
||||
userFlags = Xml.GetIntAttribute(node, "userFlags");
|
||||
|
||||
string namel = name.ToLowerInvariant();
|
||||
JenkIndex.Ensure(namel);
|
||||
nameHash = JenkHash.GenHash(namel);
|
||||
|
||||
List<TimecycleModValue> vals = new List<TimecycleModValue>();
|
||||
foreach (XmlNode valnode in node.ChildNodes)
|
||||
{
|
||||
if (!(valnode is XmlElement)) continue;
|
||||
|
||||
TimecycleModValue val = new TimecycleModValue();
|
||||
val.Init(valnode);
|
||||
|
||||
vals.Add(val);
|
||||
Dict[val.name] = val;
|
||||
}
|
||||
Values = vals.ToArray();
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return name + " (" + numMods.ToString() + " mods, userFlags: " + userFlags.ToString() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public class TimecycleModValue
|
||||
{
|
||||
public string name { get; set; }
|
||||
public float value1 { get; set; }
|
||||
public float value2 { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
name = node.Name;
|
||||
|
||||
string valstr = node.InnerText;
|
||||
string[] valstrs = valstr.Split(' ');
|
||||
if (valstrs.Length == 2)
|
||||
{
|
||||
value1 = FloatUtil.Parse(valstrs[0]);
|
||||
value2 = FloatUtil.Parse(valstrs[1]);
|
||||
}
|
||||
else
|
||||
{ }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return name + ": " + FloatUtil.ToString(value1) + ", " + FloatUtil.ToString(value2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
433
CodeWalker.Core/World/Trains.cs
Normal file
433
CodeWalker.Core/World/Trains.cs
Normal file
@ -0,0 +1,433 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using SharpDX;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class Trains
|
||||
{
|
||||
public volatile bool Inited = false;
|
||||
public GameFileCache GameFileCache;
|
||||
|
||||
public List<TrainTrack> TrainTracks { get; set; } = new List<TrainTrack>();
|
||||
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||
{
|
||||
GameFileCache = gameFileCache;
|
||||
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
string trainsfilename = "common.rpf\\data\\levels\\gta5\\trains.xml";
|
||||
XmlDocument trainsxml = rpfman.GetFileXml(trainsfilename);
|
||||
XmlElement trainsdata = trainsxml.DocumentElement;
|
||||
//TODO: parse train_configs
|
||||
|
||||
|
||||
string tracksfilename = "common.rpf\\data\\levels\\gta5\\traintracks.xml";
|
||||
XmlDocument tracksxml = rpfman.GetFileXml(tracksfilename);
|
||||
XmlElement tracksdata = tracksxml.DocumentElement;
|
||||
XmlNodeList tracks = tracksdata.SelectNodes("train_track");
|
||||
|
||||
TrainTracks.Clear();
|
||||
for (int i = 0; i < tracks.Count; i++)
|
||||
{
|
||||
var trackxml = tracks[i];
|
||||
TrainTrack tt = new TrainTrack();
|
||||
tt.Load(gameFileCache, trackxml);
|
||||
TrainTracks.Add(tt);
|
||||
}
|
||||
|
||||
|
||||
Inited = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TrainTrack : BasePathData
|
||||
{
|
||||
public string filename { get; set; }
|
||||
public string trainConfigName { get; set; }
|
||||
public bool isPingPongTrack { get; set; }
|
||||
public bool stopsAtStations { get; set; }
|
||||
public bool MPstopsAtStations { get; set; }
|
||||
public float speed { get; set; }
|
||||
public float brakingDist { get; set; }
|
||||
|
||||
|
||||
public List<TrainTrackNode> Nodes { get; set; }
|
||||
public int NodeCount { get; set; }
|
||||
|
||||
|
||||
public int StationCount
|
||||
{
|
||||
get
|
||||
{
|
||||
int sc = 0;
|
||||
foreach (var node in Nodes)
|
||||
{
|
||||
if ((node.NodeType == 1) || (node.NodeType == 2) || (node.NodeType == 5))
|
||||
{
|
||||
sc++;
|
||||
}
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public EditorVertex[] LinkedVerts { get; set; }
|
||||
public Vector4[] NodePositions { get; set; }
|
||||
|
||||
public EditorVertex[] GetPathVertices()
|
||||
{
|
||||
return LinkedVerts;
|
||||
}
|
||||
public EditorVertex[] GetTriangleVertices()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public Vector4[] GetNodePositions()
|
||||
{
|
||||
return NodePositions;
|
||||
}
|
||||
|
||||
public PathBVH BVH { get; set; }
|
||||
|
||||
public string NodesString { get; set; }
|
||||
public RpfFileEntry RpfFileEntry { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public bool HasChanged { get; set; }
|
||||
public bool Loaded { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
public void Load(GameFileCache gameFileCache, XmlNode node)
|
||||
{
|
||||
//load from game file cache
|
||||
|
||||
filename = Xml.GetStringAttribute(node, "filename");
|
||||
trainConfigName = Xml.GetStringAttribute(node, "trainConfigName");
|
||||
isPingPongTrack = Xml.GetBoolAttribute(node, "isPingPongTrack");
|
||||
stopsAtStations = Xml.GetBoolAttribute(node, "stopsAtStations");
|
||||
MPstopsAtStations = Xml.GetBoolAttribute(node, "MPstopsAtStations");
|
||||
speed = Xml.GetFloatAttribute(node, "speed");
|
||||
brakingDist = Xml.GetFloatAttribute(node, "brakingDist");
|
||||
|
||||
RpfFileEntry = gameFileCache.RpfMan.GetEntry(filename) as RpfFileEntry;
|
||||
NodesString = gameFileCache.RpfMan.GetFileUTF8Text(filename);
|
||||
SetNameFromFilename();
|
||||
FilePath = Name;
|
||||
|
||||
Load(NodesString);
|
||||
|
||||
BuildVertices();
|
||||
|
||||
BuildBVH();
|
||||
|
||||
Loaded = true;
|
||||
}
|
||||
|
||||
public void Load(byte[] data)
|
||||
{
|
||||
filename = string.Empty;
|
||||
trainConfigName = string.Empty;
|
||||
RpfFileEntry = new RpfBinaryFileEntry();
|
||||
|
||||
|
||||
string str = Encoding.UTF8.GetString(data);
|
||||
Load(str);
|
||||
|
||||
BuildVertices();
|
||||
|
||||
BuildBVH();
|
||||
|
||||
Loaded = true;
|
||||
}
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
NodeCount = Nodes.Count;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine(Nodes.Count.ToString());
|
||||
foreach (var node in Nodes)
|
||||
{
|
||||
var nstr = FloatUtil.GetVector3String(node.Position).Replace(",","") + " " + node.NodeType.ToString();
|
||||
sb.AppendLine(nstr);
|
||||
}
|
||||
string str = sb.ToString();
|
||||
return Encoding.UTF8.GetBytes(str);
|
||||
}
|
||||
|
||||
|
||||
public void SetNameFromFilename()
|
||||
{
|
||||
string[] fparts = filename.Replace('\\', '/').Split('/');
|
||||
if ((fparts == null) || (fparts.Length == 0))
|
||||
{
|
||||
Name = filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
Name = fparts[fparts.Length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Load(string trackstr)
|
||||
{
|
||||
//load nodes from a text string...
|
||||
NodesString = trackstr;
|
||||
|
||||
if (!string.IsNullOrEmpty(trackstr))
|
||||
{
|
||||
string[] trackstrs = trackstr.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (trackstrs.Length > 1)
|
||||
{
|
||||
int nodecount;
|
||||
int.TryParse(trackstrs[0], out nodecount);
|
||||
NodeCount = nodecount;
|
||||
List<TrainTrackNode> nodes = new List<TrainTrackNode>();
|
||||
for (int i = 1; i < trackstrs.Length; i++)
|
||||
{
|
||||
var nodestr = trackstrs[i].Trim();
|
||||
var nodevals = nodestr.Split(' ');
|
||||
if (nodevals.Length == 4)
|
||||
{
|
||||
TrainTrackNode ttnode = new TrainTrackNode();
|
||||
var x = FloatUtil.Parse(nodevals[0]);
|
||||
var y = FloatUtil.Parse(nodevals[1]);
|
||||
var z = FloatUtil.Parse(nodevals[2]);
|
||||
int nodetype;
|
||||
int.TryParse(nodevals[3], out nodetype);
|
||||
ttnode.Position = new Vector3(x, y, z);
|
||||
ttnode.NodeType = nodetype;
|
||||
ttnode.Track = this;
|
||||
ttnode.Index = nodes.Count;
|
||||
ttnode.Links[0] = (nodes.Count > 0) ? nodes[nodes.Count - 1] : null;
|
||||
if (ttnode.Links[0] != null)
|
||||
{
|
||||
ttnode.Links[0].Links[1] = ttnode;
|
||||
}
|
||||
nodes.Add(ttnode);
|
||||
}
|
||||
else
|
||||
{ }
|
||||
}
|
||||
Nodes = nodes;
|
||||
}
|
||||
else
|
||||
{ }
|
||||
}
|
||||
else
|
||||
{ }
|
||||
|
||||
if (Nodes == null)
|
||||
{
|
||||
Nodes = new List<TrainTrackNode>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void BuildVertices()
|
||||
{
|
||||
if ((Nodes != null) && (Nodes.Count > 0))
|
||||
{
|
||||
var nc = Nodes.Count;
|
||||
var lc = nc - 1;
|
||||
var lvc = lc * 2;
|
||||
var np = new Vector4[nc];
|
||||
var lv = new EditorVertex[lvc];
|
||||
for (int i = 0; i < nc; i++)
|
||||
{
|
||||
np[i] = new Vector4(Nodes[i].Position, 1.0f);
|
||||
if (i > 0)
|
||||
{
|
||||
var l = i - 1;
|
||||
var li = l * 2;
|
||||
var ni = li + 1;
|
||||
lv[li].Position = Nodes[l].Position;
|
||||
lv[ni].Position = Nodes[i].Position;
|
||||
lv[li].Colour = (uint)Nodes[l].GetColour();
|
||||
lv[ni].Colour = (uint)Nodes[i].GetColour();
|
||||
}
|
||||
}
|
||||
NodePositions = np;
|
||||
LinkedVerts = lv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void UpdateBvhForNode(TrainTrackNode node)
|
||||
{
|
||||
//this needs to be called when a node's position changes...
|
||||
//need to recalc the BVH for mouse intersection optimisation purposes.
|
||||
|
||||
//if (BVH == null) return;
|
||||
//BVH.UpdateForNode(node);
|
||||
|
||||
BuildBVH();
|
||||
|
||||
//also updates the NodePositions for the visible vertex
|
||||
if (Nodes != null)
|
||||
{
|
||||
for (int i = 0; i < Nodes.Count; i++)
|
||||
{
|
||||
if (Nodes[i] == node)
|
||||
{
|
||||
NodePositions[i] = new Vector4(node.Position, 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void BuildBVH()
|
||||
{
|
||||
BVH = new PathBVH(Nodes, 10, 10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public TrainTrackNode AddNode(TrainTrackNode afternode = null)
|
||||
{
|
||||
int cnt = Nodes?.Count ?? 0;
|
||||
TrainTrackNode tn = new TrainTrackNode();
|
||||
tn.Track = this;
|
||||
tn.Index = (afternode != null) ? afternode.Index + 1 : cnt;
|
||||
|
||||
if (Nodes == null)
|
||||
{
|
||||
Nodes = new List<TrainTrackNode>();
|
||||
}
|
||||
|
||||
if (afternode != null)
|
||||
{
|
||||
TrainTrackNode aln = afternode.Links[1];
|
||||
if (aln != null) aln.Links[0] = tn;
|
||||
afternode.Links[1] = tn;
|
||||
tn.Links[0] = afternode;
|
||||
tn.Links[1] = aln;
|
||||
|
||||
int idx = tn.Index;
|
||||
Nodes.Insert(idx, tn);
|
||||
|
||||
for (int i = 0; i < Nodes.Count; i++)
|
||||
{
|
||||
Nodes[i].Index = i;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cnt > 0)
|
||||
{
|
||||
TrainTrackNode ln = Nodes[cnt - 1];
|
||||
tn.Links[0] = ln;
|
||||
ln.Links[1] = tn;
|
||||
}
|
||||
|
||||
Nodes.Add(tn);
|
||||
}
|
||||
|
||||
|
||||
NodeCount = Nodes.Count;
|
||||
|
||||
return tn;
|
||||
}
|
||||
|
||||
public bool RemoveNode(TrainTrackNode node)
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
r = Nodes.Remove(node);
|
||||
|
||||
NodeCount = Nodes.Count;
|
||||
|
||||
if (r)
|
||||
{
|
||||
var l0 = node.Links[0];
|
||||
var l1 = node.Links[1];
|
||||
|
||||
if (l0 != null)
|
||||
{
|
||||
l0.Links[1] = l1;
|
||||
}
|
||||
if (l1 != null)
|
||||
{
|
||||
l1.Links[0] = l0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Nodes.Count; i++)
|
||||
{
|
||||
Nodes[i].Index = i;
|
||||
}
|
||||
|
||||
BuildVertices();
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name + ": " + filename + " (" + NodeCount.ToString() + " nodes)";
|
||||
}
|
||||
}
|
||||
|
||||
public class TrainTrackNode : BasePathNode
|
||||
{
|
||||
public Vector3 Position { get; set; }
|
||||
public int NodeType { get; set; }
|
||||
|
||||
public TrainTrack Track { get; set; }
|
||||
public int Index { get; set; }
|
||||
public TrainTrackNode[] Links { get; set; } = new TrainTrackNode[2];
|
||||
|
||||
public int GetColour()
|
||||
{
|
||||
switch (NodeType)
|
||||
{
|
||||
case 0: return new Color4(1.0f, 0.0f, 0.0f, 1.0f).ToRgba();
|
||||
case 1: return new Color4(1.0f, 1.0f, 0.0f, 1.0f).ToRgba();
|
||||
case 2: return new Color4(0.0f, 1.0f, 0.0f, 1.0f).ToRgba();
|
||||
case 3: return new Color4(0.0f, 1.0f, 1.0f, 1.0f).ToRgba();
|
||||
case 4: return new Color4(0.0f, 0.0f, 1.0f, 1.0f).ToRgba();
|
||||
case 5: return new Color4(1.0f, 0.0f, 1.0f, 1.0f).ToRgba();
|
||||
default: return new Color4(1.0f, 1.0f, 1.0f, 1.0f).ToRgba();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetPosition(Vector3 pos)
|
||||
{
|
||||
Position = pos;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Index.ToString() + ": " + NodeType.ToString();// + ": " + FloatUtil.GetVector3String(Position);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
213
CodeWalker.Core/World/Water.cs
Normal file
213
CodeWalker.Core/World/Water.cs
Normal file
@ -0,0 +1,213 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class Water
|
||||
{
|
||||
public volatile bool Inited = false;
|
||||
public GameFileCache GameFileCache;
|
||||
public List<WaterQuad> WaterQuads = new List<WaterQuad>();
|
||||
public List<WaterCalmingQuad> CalmingQuads = new List<WaterCalmingQuad>();
|
||||
public List<WaterWaveQuad> WaveQuads = new List<WaterWaveQuad>();
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||
{
|
||||
GameFileCache = gameFileCache;
|
||||
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
string filename = "common.rpf\\data\\levels\\gta5\\water.xml";
|
||||
|
||||
XmlDocument waterxml = rpfman.GetFileXml(filename);
|
||||
|
||||
XmlElement waterdata = waterxml.DocumentElement;
|
||||
|
||||
XmlNodeList waterquads = waterdata.SelectNodes("WaterQuads/Item");
|
||||
WaterQuads.Clear();
|
||||
for (int i = 0; i < waterquads.Count; i++)
|
||||
{
|
||||
var waterquad = new WaterQuad();
|
||||
waterquad.Init(waterquads[i]);
|
||||
WaterQuads.Add(waterquad);
|
||||
}
|
||||
|
||||
XmlNodeList calmingquads = waterdata.SelectNodes("CalmingQuads/Item");
|
||||
CalmingQuads.Clear();
|
||||
for (int i = 0; i < calmingquads.Count; i++)
|
||||
{
|
||||
var calmingquad = new WaterCalmingQuad();
|
||||
calmingquad.Init(calmingquads[i]);
|
||||
CalmingQuads.Add(calmingquad);
|
||||
}
|
||||
|
||||
XmlNodeList wavequads = waterdata.SelectNodes("WaveQuads/Item");
|
||||
WaveQuads.Clear();
|
||||
for (int i = 0; i < wavequads.Count; i++)
|
||||
{
|
||||
var wavequad = new WaterWaveQuad();
|
||||
wavequad.Init(wavequads[i]);
|
||||
WaveQuads.Add(wavequad);
|
||||
}
|
||||
|
||||
Inited = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void GetVisibleQuads(Camera camera, List<WaterQuad> quads)
|
||||
{
|
||||
if (!Inited) return;
|
||||
|
||||
var vf = camera.ViewFrustum;
|
||||
for (int i = 0; i < WaterQuads.Count; i++)
|
||||
{
|
||||
var quad = WaterQuads[i];
|
||||
|
||||
Vector3 camrel = quad.BSCenter - camera.Position;
|
||||
if (vf.ContainsSphereNoClipNoOpt(ref camrel, quad.BSRadius))
|
||||
{
|
||||
quads.Add(quad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class WaterQuad
|
||||
{
|
||||
public float minX { get; set; }
|
||||
public float maxX { get; set; }
|
||||
public float minY { get; set; }
|
||||
public float maxY { get; set; }
|
||||
public int Type { get; set; }
|
||||
public bool IsInvisible { get; set; }
|
||||
public bool HasLimitedDepth { get; set; }
|
||||
public float z { get; set; }
|
||||
public float a1 { get; set; }
|
||||
public float a2 { get; set; }
|
||||
public float a3 { get; set; }
|
||||
public float a4 { get; set; }
|
||||
public bool NoStencil { get; set; }
|
||||
|
||||
public Vector3 BSCenter;
|
||||
public float BSRadius;
|
||||
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
minX = Xml.GetChildFloatAttribute(node, "minX", "value");
|
||||
maxX = Xml.GetChildFloatAttribute(node, "maxX", "value");
|
||||
minY = Xml.GetChildFloatAttribute(node, "minY", "value");
|
||||
maxY = Xml.GetChildFloatAttribute(node, "maxY", "value");
|
||||
Type = Xml.GetChildIntAttribute(node, "Type", "value");
|
||||
IsInvisible = Xml.GetChildBoolAttribute(node, "IsInvisible", "value");
|
||||
HasLimitedDepth = Xml.GetChildBoolAttribute(node, "HasLimitedDepth", "value");
|
||||
z = Xml.GetChildFloatAttribute(node, "z", "value");
|
||||
a1 = Xml.GetChildFloatAttribute(node, "a1", "value");
|
||||
a2 = Xml.GetChildFloatAttribute(node, "a2", "value");
|
||||
a3 = Xml.GetChildFloatAttribute(node, "a3", "value");
|
||||
a4 = Xml.GetChildFloatAttribute(node, "a4", "value");
|
||||
NoStencil = Xml.GetChildBoolAttribute(node, "NoStencil", "value");
|
||||
|
||||
/*
|
||||
<minX value="-1592" />
|
||||
<maxX value="-1304" />
|
||||
<minY value="-1744" />
|
||||
<maxY value="-1624" />
|
||||
<Type value="0" />
|
||||
<IsInvisible value="false" />
|
||||
<HasLimitedDepth value="false" />
|
||||
<z value="0.0" />
|
||||
<a1 value="26" />
|
||||
<a2 value="26" />
|
||||
<a3 value="26" />
|
||||
<a4 value="26" />
|
||||
<NoStencil value="false" />
|
||||
*/
|
||||
|
||||
|
||||
BSCenter = new Vector3((minX + maxX) * 0.5f, (minY + maxY) * 0.5f, z);
|
||||
BSRadius = new Vector2(maxX - minX, maxY - minY).Length() * 0.5f;
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}, {1}, {2}", FloatUtil.ToString(minX), FloatUtil.ToString(minY), FloatUtil.ToString(z), FloatUtil.ToString(maxX), FloatUtil.ToString(maxY));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class WaterCalmingQuad
|
||||
{
|
||||
public float minX { get; set; }
|
||||
public float maxX { get; set; }
|
||||
public float minY { get; set; }
|
||||
public float maxY { get; set; }
|
||||
public float fDampening { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
minX = Xml.GetChildFloatAttribute(node, "minX", "value");
|
||||
maxX = Xml.GetChildFloatAttribute(node, "maxX", "value");
|
||||
minY = Xml.GetChildFloatAttribute(node, "minY", "value");
|
||||
maxY = Xml.GetChildFloatAttribute(node, "maxY", "value");
|
||||
fDampening = Xml.GetChildFloatAttribute(node, "fDampening", "value");
|
||||
|
||||
/*
|
||||
<minX value="1752" />
|
||||
<maxX value="2076" />
|
||||
<minY value="216" />
|
||||
<maxY value="800" />
|
||||
<fDampening value="0.05" />
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class WaterWaveQuad
|
||||
{
|
||||
public float minX { get; set; }
|
||||
public float maxX { get; set; }
|
||||
public float minY { get; set; }
|
||||
public float maxY { get; set; }
|
||||
public float Amplitude { get; set; }
|
||||
public float XDirection { get; set; }
|
||||
public float YDirection { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
minX = Xml.GetChildFloatAttribute(node, "minX", "value");
|
||||
maxX = Xml.GetChildFloatAttribute(node, "maxX", "value");
|
||||
minY = Xml.GetChildFloatAttribute(node, "minY", "value");
|
||||
maxY = Xml.GetChildFloatAttribute(node, "maxY", "value");
|
||||
Amplitude = Xml.GetChildFloatAttribute(node, "Amplitude", "value");
|
||||
XDirection = Xml.GetChildFloatAttribute(node, "XDirection", "value");
|
||||
YDirection = Xml.GetChildFloatAttribute(node, "YDirection", "value");
|
||||
|
||||
/*
|
||||
<minX value="1664" />
|
||||
<maxX value="1988" />
|
||||
<minY value="-120" />
|
||||
<maxY value="132" />
|
||||
<Amplitude value="0.1" />
|
||||
<XDirection value="-0.603208" />
|
||||
<YDirection value="-0.797584" />
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
569
CodeWalker.Core/World/Weather.cs
Normal file
569
CodeWalker.Core/World/Weather.cs
Normal file
@ -0,0 +1,569 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.World
|
||||
{
|
||||
public class Weather
|
||||
{
|
||||
|
||||
public Dictionary<string, WeatherGpuFx> WeatherGpuFx { get; set; } = new Dictionary<string, WeatherGpuFx>();
|
||||
public Dictionary<string, WeatherType> WeatherTypes { get; set; } = new Dictionary<string, WeatherType>();
|
||||
public List<WeatherCycle> WeatherCycles { get; set; } = new List<WeatherCycle>();
|
||||
public WeatherValues CurrentValues;
|
||||
|
||||
public volatile bool Inited = false;
|
||||
public WeatherType CurrentWeatherType;
|
||||
public WeatherType NextWeatherType;
|
||||
public float WeatherChangeTime = 0.33f;
|
||||
public float CurrentWeatherChangeTime = 0.0f;
|
||||
public float CurrentWeatherChangeBlend = 0.0f;
|
||||
public string Region = "GLOBAL"; //URBAN or GLOBAL..
|
||||
public WeatherCycleKeyframeRegion CurrentWeatherRegion;
|
||||
public WeatherCycleKeyframeRegion NextWeatherRegion;
|
||||
|
||||
public Timecycle Timecycle;
|
||||
public TimecycleMods TimecycleMods;
|
||||
|
||||
public void Init(GameFileCache gameFileCache, Action<string> updateStatus, Timecycle timecycle)
|
||||
{
|
||||
Timecycle = timecycle;
|
||||
var rpfman = gameFileCache.RpfMan;
|
||||
|
||||
//TODO: RpfMan should be able to get the right version? or maybe let gameFileCache do it!
|
||||
string filename = "common.rpf\\data\\levels\\gta5\\weather.xml";
|
||||
if (gameFileCache.EnableDlc)
|
||||
{
|
||||
filename = "update\\update.rpf\\common\\data\\levels\\gta5\\weather.xml";
|
||||
}
|
||||
|
||||
XmlDocument weatherxml = rpfman.GetFileXml(filename);
|
||||
|
||||
XmlElement weather = weatherxml.DocumentElement;
|
||||
|
||||
XmlNodeList weathergpufx = weather.SelectNodes("WeatherGpuFx/Item");
|
||||
WeatherGpuFx.Clear();
|
||||
for (int i = 0; i < weathergpufx.Count; i++)
|
||||
{
|
||||
var weathergpufxi = new WeatherGpuFx();
|
||||
weathergpufxi.Init(weathergpufx[i]);
|
||||
WeatherGpuFx[weathergpufxi.Name] = weathergpufxi;
|
||||
}
|
||||
|
||||
XmlNodeList weathertypes = weather.SelectNodes("WeatherTypes/Item");
|
||||
WeatherTypes.Clear();
|
||||
for (int i = 0; i < weathertypes.Count; i++)
|
||||
{
|
||||
var weathertype = new WeatherType();
|
||||
weathertype.Init(gameFileCache, weathertypes[i]);
|
||||
WeatherTypes[weathertype.Name] = weathertype;
|
||||
}
|
||||
|
||||
XmlNodeList weathercycles = weather.SelectNodes("WeatherCycles/Item");
|
||||
WeatherCycles.Clear();
|
||||
for (int i = 0; i < weathercycles.Count; i++)
|
||||
{
|
||||
var weathercycle = new WeatherCycle();
|
||||
weathercycle.Init(weathercycles[i]);
|
||||
WeatherCycles.Add(weathercycle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (WeatherTypes.Count > 0)
|
||||
{
|
||||
CurrentWeatherType = WeatherTypes.Values.First();
|
||||
CurrentWeatherRegion = CurrentWeatherType.GetRegion(Region);
|
||||
NextWeatherType = CurrentWeatherType;
|
||||
NextWeatherRegion = NextWeatherType.GetRegion(Region);
|
||||
}
|
||||
|
||||
|
||||
TimecycleMods = new TimecycleMods();
|
||||
TimecycleMods.Init(gameFileCache, updateStatus);
|
||||
|
||||
|
||||
Inited = true;
|
||||
}
|
||||
|
||||
public void Update(float elapsed)
|
||||
{
|
||||
if (!Inited) return;
|
||||
|
||||
if (CurrentWeatherType != NextWeatherType)
|
||||
{
|
||||
CurrentWeatherChangeTime += elapsed;
|
||||
if (CurrentWeatherChangeTime >= WeatherChangeTime)
|
||||
{
|
||||
CurrentWeatherType = NextWeatherType;
|
||||
CurrentWeatherChangeTime = 0.0f;
|
||||
}
|
||||
CurrentWeatherChangeBlend = Math.Min(CurrentWeatherChangeTime / WeatherChangeTime, 1.0f);
|
||||
}
|
||||
if (CurrentWeatherType != null)
|
||||
{
|
||||
CurrentWeatherRegion = CurrentWeatherType.GetRegion(Region);
|
||||
}
|
||||
if (NextWeatherType != null)
|
||||
{
|
||||
NextWeatherRegion = NextWeatherType.GetRegion(Region);
|
||||
}
|
||||
|
||||
CurrentValues.Update(this);
|
||||
}
|
||||
|
||||
public void SetNextWeather(string name)
|
||||
{
|
||||
WeatherTypes.TryGetValue(name, out NextWeatherType);
|
||||
if (NextWeatherType == null)
|
||||
{
|
||||
NextWeatherType = CurrentWeatherType;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentWeatherChangeTime = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetDynamicValue(string name)
|
||||
{
|
||||
int csi = Timecycle.CurrentSampleIndex;
|
||||
float csb = Timecycle.CurrentSampleBlend;
|
||||
if ((CurrentWeatherRegion != null) && (NextWeatherRegion != null))
|
||||
{
|
||||
float cv = CurrentWeatherRegion.GetCurrentValue(name, csi, csb);
|
||||
float nv = NextWeatherRegion.GetCurrentValue(name, csi, csb);
|
||||
return cv * (1.0f - CurrentWeatherChangeBlend) + nv * CurrentWeatherChangeBlend;
|
||||
}
|
||||
else if (CurrentWeatherRegion != null)
|
||||
{
|
||||
return CurrentWeatherRegion.GetCurrentValue(name, csi, csb);
|
||||
}
|
||||
//throw new Exception("CurrentWeatherRegion was null.");
|
||||
return 0.0f;
|
||||
}
|
||||
public Vector3 GetDynamicRGB(string rname, string gname, string bname)
|
||||
{
|
||||
int csi = Timecycle.CurrentSampleIndex;
|
||||
float csb = Timecycle.CurrentSampleBlend;
|
||||
if ((CurrentWeatherRegion != null) && (NextWeatherRegion != null))
|
||||
{
|
||||
float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb);
|
||||
float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb);
|
||||
float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb);
|
||||
float nvr = NextWeatherRegion.GetCurrentValue(rname, csi, csb);
|
||||
float nvg = NextWeatherRegion.GetCurrentValue(gname, csi, csb);
|
||||
float nvb = NextWeatherRegion.GetCurrentValue(bname, csi, csb);
|
||||
Vector3 cv = new Vector3(cvr, cvg, cvb);
|
||||
Vector3 nv = new Vector3(nvr, nvg, nvb);
|
||||
return cv * (1.0f - CurrentWeatherChangeBlend) + nv * CurrentWeatherChangeBlend;
|
||||
}
|
||||
else if (CurrentWeatherRegion != null)
|
||||
{
|
||||
float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb);
|
||||
float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb);
|
||||
float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb);
|
||||
return new Vector3(cvr, cvg, cvb);
|
||||
}
|
||||
//throw new Exception("CurrentWeatherRegion was null.");
|
||||
return Vector3.Zero;
|
||||
}
|
||||
public Vector4 GetDynamicRGBA(string rname, string gname, string bname, string aname)
|
||||
{
|
||||
int csi = Timecycle.CurrentSampleIndex;
|
||||
float csb = Timecycle.CurrentSampleBlend;
|
||||
if ((CurrentWeatherRegion != null) && (NextWeatherRegion != null))
|
||||
{
|
||||
float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb);
|
||||
float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb);
|
||||
float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb);
|
||||
float cva = CurrentWeatherRegion.GetCurrentValue(aname, csi, csb);
|
||||
float nvr = NextWeatherRegion.GetCurrentValue(rname, csi, csb);
|
||||
float nvg = NextWeatherRegion.GetCurrentValue(gname, csi, csb);
|
||||
float nvb = NextWeatherRegion.GetCurrentValue(bname, csi, csb);
|
||||
float nva = NextWeatherRegion.GetCurrentValue(aname, csi, csb);
|
||||
Vector4 cv = new Vector4(cvr, cvg, cvb, cva);
|
||||
Vector4 nv = new Vector4(nvr, nvg, nvb, nva);
|
||||
return cv * (1.0f - CurrentWeatherChangeBlend) + nv * CurrentWeatherChangeBlend;
|
||||
}
|
||||
else if (CurrentWeatherRegion != null)
|
||||
{
|
||||
float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb);
|
||||
float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb);
|
||||
float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb);
|
||||
float cva = CurrentWeatherRegion.GetCurrentValue(aname, csi, csb);
|
||||
return new Vector4(cvr, cvg, cvb, cva);
|
||||
}
|
||||
//throw new Exception("CurrentWeatherRegion was null.");
|
||||
return Vector4.Zero;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class WeatherGpuFx
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string SystemType { get; set; }
|
||||
public string diffuseName { get; set; }
|
||||
public string distortionTexture { get; set; }
|
||||
public string diffuseSplashName { get; set; }
|
||||
public string driveType { get; set; }
|
||||
public float windInfluence { get; set; }
|
||||
public float gravity { get; set; }
|
||||
public string emitterSettingsName { get; set; }
|
||||
public string renderSettingsName { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
Name = Xml.GetChildInnerText(node, "Name");
|
||||
SystemType = Xml.GetChildInnerText(node, "SystemType");
|
||||
diffuseName = Xml.GetChildInnerText(node, "diffuseName");
|
||||
distortionTexture = Xml.GetChildInnerText(node, "distortionTexture");
|
||||
diffuseSplashName = Xml.GetChildInnerText(node, "diffuseSplashName");
|
||||
driveType = Xml.GetChildInnerText(node, "driveType");
|
||||
windInfluence = Xml.GetChildFloatAttribute(node, "windInfluence", "value");
|
||||
gravity = Xml.GetChildFloatAttribute(node, "gravity", "value");
|
||||
emitterSettingsName = Xml.GetChildInnerText(node, "emitterSettingsName");
|
||||
renderSettingsName = Xml.GetChildInnerText(node, "renderSettingsName");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
public class WeatherType
|
||||
{
|
||||
public MetaHash NameHash { get; set; }
|
||||
public string Name { get; set; }
|
||||
public float Sun { get; set; }
|
||||
public float Cloud { get; set; }
|
||||
public float WindMin { get; set; }
|
||||
public float WindMax { get; set; }
|
||||
public float Rain { get; set; }
|
||||
public float Snow { get; set; }
|
||||
public float SnowMist { get; set; }
|
||||
public float Fog { get; set; }
|
||||
public float RippleBumpiness { get; set; }
|
||||
public float RippleMinBumpiness { get; set; }
|
||||
public float RippleMaxBumpiness { get; set; }
|
||||
public float RippleBumpinessWindScale { get; set; }
|
||||
public float RippleScale { get; set; }
|
||||
public float RippleSpeed { get; set; }
|
||||
public float RippleVelocityTransfer { get; set; }
|
||||
public float OceanBumpiness { get; set; }
|
||||
public float DeepOceanScale { get; set; }
|
||||
public float OceanNoiseMinAmplitude { get; set; }
|
||||
public float OceanWaveAmplitude { get; set; }
|
||||
public float ShoreWaveAmplitude { get; set; }
|
||||
public float OceanWaveWindScale { get; set; }
|
||||
public float ShoreWaveWindScale { get; set; }
|
||||
public float OceanWaveMinAmplitude { get; set; }
|
||||
public float ShoreWaveMinAmplitude { get; set; }
|
||||
public float OceanWaveMaxAmplitude { get; set; }
|
||||
public float ShoreWaveMaxAmplitude { get; set; }
|
||||
public float OceanFoamIntensity { get; set; }
|
||||
public float OceanFoamScale { get; set; }
|
||||
public float RippleDisturb { get; set; }
|
||||
public float Lightning { get; set; }
|
||||
public float Sandstorm { get; set; }
|
||||
public string OldSettingName { get; set; }
|
||||
public string DropSettingName { get; set; }
|
||||
public string MistSettingName { get; set; }
|
||||
public string GroundSettingName { get; set; }
|
||||
public string TimeCycleFilename { get; set; }
|
||||
public string CloudSettingsName { get; set; }
|
||||
|
||||
public WeatherCycleKeyframeData TimeCycleData;
|
||||
|
||||
public void Init(GameFileCache gameFileCache, XmlNode node)
|
||||
{
|
||||
Name = Xml.GetChildInnerText(node, "Name");
|
||||
NameHash = new MetaHash(JenkHash.GenHash(Name.ToLowerInvariant()));
|
||||
Sun = Xml.GetChildFloatAttribute(node, "Sun", "value");
|
||||
Cloud = Xml.GetChildFloatAttribute(node, "Cloud", "value");
|
||||
WindMin = Xml.GetChildFloatAttribute(node, "WindMin", "value");
|
||||
WindMax = Xml.GetChildFloatAttribute(node, "WindMax", "value");
|
||||
Rain = Xml.GetChildFloatAttribute(node, "Rain", "value");
|
||||
Snow = Xml.GetChildFloatAttribute(node, "Snow", "value");
|
||||
SnowMist = Xml.GetChildFloatAttribute(node, "SnowMist", "value");
|
||||
Fog = Xml.GetChildFloatAttribute(node, "Fog", "value");
|
||||
RippleBumpiness = Xml.GetChildFloatAttribute(node, "RippleBumpiness", "value");
|
||||
RippleMinBumpiness = Xml.GetChildFloatAttribute(node, "RippleMinBumpiness", "value");
|
||||
RippleMaxBumpiness = Xml.GetChildFloatAttribute(node, "RippleMaxBumpiness", "value");
|
||||
RippleBumpinessWindScale = Xml.GetChildFloatAttribute(node, "RippleBumpinessWindScale", "value");
|
||||
RippleScale = Xml.GetChildFloatAttribute(node, "RippleScale", "value");
|
||||
RippleSpeed = Xml.GetChildFloatAttribute(node, "RippleSpeed", "value");
|
||||
RippleVelocityTransfer = Xml.GetChildFloatAttribute(node, "RippleVelocityTransfer", "value");
|
||||
OceanBumpiness = Xml.GetChildFloatAttribute(node, "OceanBumpiness", "value");
|
||||
DeepOceanScale = Xml.GetChildFloatAttribute(node, "DeepOceanScale", "value");
|
||||
OceanNoiseMinAmplitude = Xml.GetChildFloatAttribute(node, "OceanNoiseMinAmplitude", "value");
|
||||
OceanWaveAmplitude = Xml.GetChildFloatAttribute(node, "OceanWaveAmplitude", "value");
|
||||
ShoreWaveAmplitude = Xml.GetChildFloatAttribute(node, "ShoreWaveAmplitude", "value");
|
||||
OceanWaveWindScale = Xml.GetChildFloatAttribute(node, "OceanWaveWindScale", "value");
|
||||
ShoreWaveWindScale = Xml.GetChildFloatAttribute(node, "ShoreWaveWindScale", "value");
|
||||
OceanWaveMinAmplitude = Xml.GetChildFloatAttribute(node, "OceanWaveMinAmplitude", "value");
|
||||
ShoreWaveMinAmplitude = Xml.GetChildFloatAttribute(node, "ShoreWaveMinAmplitude", "value");
|
||||
OceanWaveMaxAmplitude = Xml.GetChildFloatAttribute(node, "OceanWaveMaxAmplitude", "value");
|
||||
ShoreWaveMaxAmplitude = Xml.GetChildFloatAttribute(node, "ShoreWaveMaxAmplitude", "value");
|
||||
OceanFoamIntensity = Xml.GetChildFloatAttribute(node, "OceanFoamIntensity", "value");
|
||||
OceanFoamScale = Xml.GetChildFloatAttribute(node, "OceanFoamScale", "value");
|
||||
RippleDisturb = Xml.GetChildFloatAttribute(node, "RippleDisturb", "value");
|
||||
Lightning = Xml.GetChildFloatAttribute(node, "Lightning", "value");
|
||||
Sandstorm = Xml.GetChildFloatAttribute(node, "Sandstorm", "value");
|
||||
OldSettingName = Xml.GetChildInnerText(node, "OldSettingName");
|
||||
DropSettingName = Xml.GetChildInnerText(node, "DropSettingName");
|
||||
MistSettingName = Xml.GetChildInnerText(node, "MistSettingName");
|
||||
GroundSettingName = Xml.GetChildInnerText(node, "GroundSettingName");
|
||||
TimeCycleFilename = Xml.GetChildInnerText(node, "TimeCycleFilename");
|
||||
CloudSettingsName = Xml.GetChildInnerText(node, "CloudSettingsName");
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(TimeCycleFilename))
|
||||
{
|
||||
|
||||
//TODO: RpfMan should be able to get the right version? or maybe let gameFileCache do it!
|
||||
string fname = TimeCycleFilename.ToLowerInvariant();
|
||||
bool useupd = gameFileCache.EnableDlc;
|
||||
if (useupd)
|
||||
{
|
||||
fname = fname.Replace("common:", "update/update.rpf/common");
|
||||
}
|
||||
XmlDocument tcxml = gameFileCache.RpfMan.GetFileXml(fname);
|
||||
if (useupd && !tcxml.HasChildNodes)
|
||||
{
|
||||
fname = TimeCycleFilename.ToLowerInvariant();
|
||||
tcxml = gameFileCache.RpfMan.GetFileXml(fname);
|
||||
}
|
||||
|
||||
foreach (XmlNode cycle in tcxml.DocumentElement.ChildNodes)
|
||||
{
|
||||
TimeCycleData = new WeatherCycleKeyframeData();
|
||||
TimeCycleData.Init(cycle);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public WeatherCycleKeyframeRegion GetRegion(string name)
|
||||
{
|
||||
if ((TimeCycleData != null) && (TimeCycleData.Regions != null))
|
||||
{
|
||||
WeatherCycleKeyframeRegion r;
|
||||
if (TimeCycleData.Regions.TryGetValue(name, out r))
|
||||
{
|
||||
return r;
|
||||
}
|
||||
return TimeCycleData.Regions.Values.FirstOrDefault();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
public class WeatherCycle
|
||||
{
|
||||
public string CycleName { get; set; }
|
||||
public float TimeMult { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
CycleName = Xml.GetChildInnerText(node, "CycleName");
|
||||
TimeMult = Xml.GetChildFloatAttribute(node, "TimeMult", "value");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return CycleName + ", " + TimeMult.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class WeatherCycleKeyframeData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int RegionCount { get; set; }
|
||||
public Dictionary<string, WeatherCycleKeyframeRegion> Regions { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
//read cycle node
|
||||
Name = Xml.GetStringAttribute(node, "name");
|
||||
RegionCount = Xml.GetIntAttribute(node, "regions");
|
||||
Regions = new Dictionary<string, WeatherCycleKeyframeRegion>();
|
||||
foreach (XmlNode child in node.ChildNodes)
|
||||
{
|
||||
WeatherCycleKeyframeRegion r = new WeatherCycleKeyframeRegion();
|
||||
r.Init(child);
|
||||
Regions[r.Name] = r;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
public class WeatherCycleKeyframeRegion
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Dictionary<string, WeatherCycleKeyframeDataEntry> Data { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
//read region node
|
||||
Name = Xml.GetStringAttribute(node, "name");
|
||||
Data = new Dictionary<string, WeatherCycleKeyframeDataEntry>();
|
||||
foreach (XmlNode child in node.ChildNodes)
|
||||
{
|
||||
if (child != null)
|
||||
{
|
||||
WeatherCycleKeyframeDataEntry d = new WeatherCycleKeyframeDataEntry();
|
||||
d.Init(child);
|
||||
Data[d.Name] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float GetCurrentValue(string name, int sample, float curblend)
|
||||
{
|
||||
WeatherCycleKeyframeDataEntry e;
|
||||
if (Data.TryGetValue(name, out e))
|
||||
{
|
||||
if (sample >= e.Values.Length)
|
||||
{
|
||||
//System.Windows.Forms.MessageBox.Show("Sample index was out of range: " + sample.ToString());
|
||||
sample = e.Values.Length - 1;
|
||||
}
|
||||
int nxtsample = (sample < e.Values.Length - 1) ? sample + 1 : 0;
|
||||
float cv = e.Values[sample];
|
||||
float nv = e.Values[nxtsample];
|
||||
return cv * curblend + nv * (1.0f - curblend);
|
||||
}
|
||||
//throw new Exception("WeatherCycleKeyframeDataEntry " + name + " not found in region " + Name + ".");
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
public class WeatherCycleKeyframeDataEntry
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public float[] Values { get; set; }
|
||||
|
||||
public void Init(XmlNode node)
|
||||
{
|
||||
//read data node
|
||||
Name = node.Name;
|
||||
string[] strvals = node.InnerText.Trim().Split(' ');
|
||||
Values = new float[strvals.Length];
|
||||
for (int i = 0; i < strvals.Length; i++)
|
||||
{
|
||||
if (!FloatUtil.TryParse(strvals[i], out Values[i]))
|
||||
{
|
||||
//System.Windows.Forms.MessageBox.Show("Error parsing float value: " + strvals[i] + "\n" +
|
||||
// "Node: " + node.OuterXml.ToString());
|
||||
//throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct WeatherValues
|
||||
{
|
||||
public Vector3 sunDirection;
|
||||
public Vector3 moonDirection;
|
||||
public Vector4 skyZenithCol;
|
||||
public Vector4 skyZenithTransitionCol;
|
||||
public Vector4 skyZenithTransition;
|
||||
public Vector4 skyAzimuthEastCol;
|
||||
public Vector4 skyAzimuthWestCol;
|
||||
public Vector4 skyAzimuthTransitionCol;
|
||||
public float skyAzimuthTransition;
|
||||
public float skyHdr;
|
||||
public Vector4 skyPlane;
|
||||
public Vector3 skySunCol;
|
||||
public Vector3 skySunDiscCol;
|
||||
public float skySunDiscSize;
|
||||
public float skySunHdr;
|
||||
public Vector3 skySunMie;
|
||||
public float skySunInfluenceRadius;
|
||||
public float skySunScatterInten;
|
||||
public Vector3 skyMoonCol;
|
||||
public float skyMoonDiscSize;
|
||||
public float skyMoonIten;
|
||||
public float skyMoonInfluenceRadius;
|
||||
public float skyMoonScatterInten;
|
||||
public float skyStarsIten;
|
||||
public Vector4 lightDirCol;
|
||||
public Vector4 lightDirAmbCol;
|
||||
public float lightDirAmbIntensityMult;
|
||||
public float lightDirAmbBounce;
|
||||
public Vector4 lightNaturalAmbDown;
|
||||
public Vector4 lightNaturalAmbUp;
|
||||
public float lightNaturalAmbUpIntensityMult;
|
||||
public Vector4 lightArtificialIntDown;
|
||||
public Vector4 lightArtificialIntUp;
|
||||
public Vector4 lightArtificialExtDown;
|
||||
public Vector4 lightArtificialExtUp;
|
||||
|
||||
public void Update(Weather w)
|
||||
{
|
||||
sunDirection = w.GetDynamicRGB("sun_direction_x", "sun_direction_y", "sun_direction_z");
|
||||
moonDirection = w.GetDynamicRGB("moon_direction_x", "moon_direction_y", "moon_direction_z");
|
||||
skyZenithCol = w.GetDynamicRGBA("sky_zenith_col_r", "sky_zenith_col_g", "sky_zenith_col_b", "sky_zenith_col_inten");
|
||||
skyZenithTransitionCol = w.GetDynamicRGBA("sky_zenith_transition_col_r", "sky_zenith_transition_col_g", "sky_zenith_transition_col_b", "sky_zenith_transition_col_inten");
|
||||
//skyZenithTransition = w.GetDynamicRGBA("sky_zenith_transition_position", "sky_zenith_transition_east_blend", "sky_zenith_transition_west_blend", "sky_zenith_blend_start");
|
||||
skyZenithTransition = w.GetDynamicRGBA("sky_zenith_blend_start", "sky_zenith_transition_east_blend", "sky_zenith_transition_west_blend", "sky_zenith_transition_position");
|
||||
skyAzimuthEastCol = w.GetDynamicRGBA("sky_azimuth_east_col_r", "sky_azimuth_east_col_g", "sky_azimuth_east_col_b", "sky_azimuth_east_col_inten");
|
||||
skyAzimuthWestCol = w.GetDynamicRGBA("sky_azimuth_west_col_r", "sky_azimuth_west_col_g", "sky_azimuth_west_col_b", "sky_azimuth_west_col_inten");
|
||||
skyAzimuthTransitionCol = w.GetDynamicRGBA("sky_azimuth_transition_col_r", "sky_azimuth_transition_col_g", "sky_azimuth_transition_col_b", "sky_azimuth_transition_col_inten");
|
||||
skyAzimuthTransition = w.GetDynamicValue("sky_azimuth_transition_position");
|
||||
skyHdr = w.GetDynamicValue("sky_hdr");
|
||||
skyPlane = w.GetDynamicRGBA("sky_plane_r", "sky_plane_g", "sky_plane_b", "sky_plane_inten");
|
||||
skySunCol = w.GetDynamicRGB("sky_sun_col_r", "sky_sun_col_g", "sky_sun_col_b");
|
||||
skySunDiscCol = w.GetDynamicRGB("sky_sun_disc_col_r", "sky_sun_disc_col_g", "sky_sun_disc_col_b");
|
||||
skySunDiscSize = w.GetDynamicValue("sky_sun_disc_size");
|
||||
skySunHdr = w.GetDynamicValue("sky_sun_hdr");
|
||||
skySunMie = w.GetDynamicRGB("sky_sun_miephase", "sky_sun_miescatter", "sky_sun_mie_intensity_mult");
|
||||
skySunInfluenceRadius = w.GetDynamicValue("sky_sun_influence_radius");
|
||||
skySunScatterInten = w.GetDynamicValue("sky_sun_scatter_inten");
|
||||
skyMoonCol = w.GetDynamicRGB("sky_moon_col_r", "sky_moon_col_g", "sky_moon_col_b");
|
||||
skyMoonDiscSize = w.GetDynamicValue("sky_moon_disc_size");
|
||||
skyMoonIten = w.GetDynamicValue("sky_moon_iten");
|
||||
skyMoonInfluenceRadius = w.GetDynamicValue("sky_moon_influence_radius");
|
||||
skyMoonScatterInten = w.GetDynamicValue("sky_moon_scatter_inten");
|
||||
skyStarsIten = w.GetDynamicValue("sky_stars_iten");
|
||||
lightDirCol = w.GetDynamicRGBA("light_dir_col_r", "light_dir_col_g", "light_dir_col_b", "light_dir_mult");
|
||||
lightDirAmbCol = w.GetDynamicRGBA("light_directional_amb_col_r", "light_directional_amb_col_g", "light_directional_amb_col_b", "light_directional_amb_intensity");
|
||||
lightDirAmbIntensityMult = w.GetDynamicValue("light_directional_amb_intensity_mult");
|
||||
lightDirAmbBounce = w.GetDynamicValue("light_directional_amb_bounce_enabled");
|
||||
lightNaturalAmbDown = w.GetDynamicRGBA("light_natural_amb_down_col_r", "light_natural_amb_down_col_g", "light_natural_amb_down_col_b", "light_natural_amb_down_intensity");
|
||||
lightNaturalAmbUp = w.GetDynamicRGBA("light_natural_amb_up_col_r", "light_natural_amb_up_col_g", "light_natural_amb_up_col_b", "light_natural_amb_up_intensity");
|
||||
lightNaturalAmbUpIntensityMult = w.GetDynamicValue("light_natural_amb_up_intensity_mult");
|
||||
lightArtificialIntDown = w.GetDynamicRGBA("light_artificial_int_down_col_r", "light_artificial_int_down_col_g", "light_artificial_int_down_col_b", "light_artificial_int_down_intensity");
|
||||
lightArtificialIntUp = w.GetDynamicRGBA("light_artificial_int_up_col_r", "light_artificial_int_up_col_g", "light_artificial_int_up_col_b", "light_artificial_int_up_intensity");
|
||||
lightArtificialExtDown = w.GetDynamicRGBA("light_artificial_ext_down_col_r", "light_artificial_ext_down_col_g", "light_artificial_ext_down_col_b", "light_artificial_ext_down_intensity");
|
||||
lightArtificialExtUp = w.GetDynamicRGBA("light_artificial_ext_up_col_r", "light_artificial_ext_up_col_g", "light_artificial_ext_up_col_b", "light_artificial_ext_up_intensity");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
5
CodeWalker.Core/packages.config
Normal file
5
CodeWalker.Core/packages.config
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="SharpDX" version="4.0.1" targetFramework="net461" />
|
||||
<package id="SharpDX.Mathematics" version="4.0.1" targetFramework="net461" />
|
||||
</packages>
|
122
CodeWalker.WinForms/CodeWalker.WinForms.csproj
Normal file
122
CodeWalker.WinForms/CodeWalker.WinForms.csproj
Normal file
@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{9702C58D-F52F-45CF-9456-9CE5AF40F5C3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CodeWalker.WinForms</RootNamespace>
|
||||
<AssemblyName>CodeWalker.WinForms</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WeifenLuo.WinFormsUI.Docking, Version=3.0.4.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DockPanelSuite.3.0.4\lib\net40\WeifenLuo.WinFormsUI.Docking.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WeifenLuo.WinFormsUI.Docking.ThemeVS2015, Version=3.0.4.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DockPanelSuite.ThemeVS2015.3.0.4\lib\net40\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MenuStripFix.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MenuStripFix.Designer.cs">
|
||||
<DependentUpon>MenuStripFix.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ProjectPanel.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PropertyGridFix.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PropertyGridFix.Designer.cs">
|
||||
<DependentUpon>PropertyGridFix.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ReadOnlyPropertyGrid.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ReadOnlyPropertyGrid.Designer.cs">
|
||||
<DependentUpon>ReadOnlyPropertyGrid.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TextBoxFix.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TextBoxFix.Designer.cs">
|
||||
<DependentUpon>TextBoxFix.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TextBoxScrollSyncFix.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TextBoxScrollSyncFix.Designer.cs">
|
||||
<DependentUpon>TextBoxScrollSyncFix.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ToolStripFix.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ToolStripFix.Designer.cs">
|
||||
<DependentUpon>ToolStripFix.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ToolStripSplitButtonFix.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ToolStripSplitButtonFix.Designer.cs">
|
||||
<DependentUpon>ToolStripSplitButtonFix.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ToolStripSpringTextBox.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ToolStripSpringTextBox.Designer.cs">
|
||||
<DependentUpon>ToolStripSpringTextBox.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TreeViewFix.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TreeViewFix.Designer.cs">
|
||||
<DependentUpon>TreeViewFix.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="FormUtils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
459
CodeWalker.WinForms/FormUtils.cs
Normal file
459
CodeWalker.WinForms/FormUtils.cs
Normal file
@ -0,0 +1,459 @@
|
||||
using CodeWalker.WinForms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using Point = System.Drawing.Point;
|
||||
|
||||
namespace CodeWalker
|
||||
{
|
||||
////public static class Utils
|
||||
////{
|
||||
//// //unused
|
||||
//// //public static Bitmap ResizeImage(Image image, int width, int height)
|
||||
//// //{
|
||||
//// // var destRect = new Rectangle(0, 0, width, height);
|
||||
//// // var destImage = new Bitmap(width, height);
|
||||
//// // destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
|
||||
//// // using (var graphics = Graphics.FromImage(destImage))
|
||||
//// // {
|
||||
//// // graphics.CompositingMode = CompositingMode.SourceCopy;
|
||||
//// // graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
//// // graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
//// // graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
//// // graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
//// // using (var wrapMode = new ImageAttributes())
|
||||
//// // {
|
||||
//// // wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
||||
//// // graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
|
||||
//// // }
|
||||
//// // }
|
||||
//// // return destImage;
|
||||
//// //}
|
||||
////}
|
||||
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static class ListViewExtensions
|
||||
{
|
||||
//from stackoverflow:
|
||||
//https://stackoverflow.com/questions/254129/how-to-i-display-a-sort-arrow-in-the-header-of-a-list-view-column-using-c
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct HDITEM
|
||||
{
|
||||
public Mask mask;
|
||||
public int cxy;
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public string pszText;
|
||||
public IntPtr hbm;
|
||||
public int cchTextMax;
|
||||
public Format fmt;
|
||||
public IntPtr lParam;
|
||||
// _WIN32_IE >= 0x0300
|
||||
public int iImage;
|
||||
public int iOrder;
|
||||
// _WIN32_IE >= 0x0500
|
||||
public uint type;
|
||||
public IntPtr pvFilter;
|
||||
// _WIN32_WINNT >= 0x0600
|
||||
public uint state;
|
||||
|
||||
[Flags]
|
||||
public enum Mask
|
||||
{
|
||||
Format = 0x4, // HDI_FORMAT
|
||||
};
|
||||
|
||||
[Flags]
|
||||
public enum Format
|
||||
{
|
||||
SortDown = 0x200, // HDF_SORTDOWN
|
||||
SortUp = 0x400, // HDF_SORTUP
|
||||
};
|
||||
};
|
||||
|
||||
public const int LVM_FIRST = 0x1000;
|
||||
public const int LVM_GETHEADER = LVM_FIRST + 31;
|
||||
|
||||
public const int HDM_FIRST = 0x1200;
|
||||
public const int HDM_GETITEM = HDM_FIRST + 11;
|
||||
public const int HDM_SETITEM = HDM_FIRST + 12;
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref HDITEM lParam);
|
||||
|
||||
public static void SetSortIcon(this ListView listViewControl, int columnIndex, SortOrder order)
|
||||
{
|
||||
IntPtr columnHeader = SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
|
||||
for (int columnNumber = 0; columnNumber <= listViewControl.Columns.Count - 1; columnNumber++)
|
||||
{
|
||||
var columnPtr = new IntPtr(columnNumber);
|
||||
var item = new HDITEM
|
||||
{
|
||||
mask = HDITEM.Mask.Format
|
||||
};
|
||||
|
||||
if (SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero)
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
if (order != SortOrder.None && columnNumber == columnIndex)
|
||||
{
|
||||
switch (order)
|
||||
{
|
||||
case SortOrder.Ascending:
|
||||
item.fmt &= ~HDITEM.Format.SortDown;
|
||||
item.fmt |= HDITEM.Format.SortUp;
|
||||
break;
|
||||
case SortOrder.Descending:
|
||||
item.fmt &= ~HDITEM.Format.SortUp;
|
||||
item.fmt |= HDITEM.Format.SortDown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.fmt &= ~HDITEM.Format.SortDown & ~HDITEM.Format.SortUp;
|
||||
}
|
||||
|
||||
if (SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero)
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//private const int LVM_FIRST = 0x1000;
|
||||
private const int LVM_SETITEMSTATE = LVM_FIRST + 43;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct LVITEM
|
||||
{
|
||||
public int mask;
|
||||
public int iItem;
|
||||
public int iSubItem;
|
||||
public int state;
|
||||
public int stateMask;
|
||||
[MarshalAs(UnmanagedType.LPTStr)]
|
||||
public string pszText;
|
||||
public int cchTextMax;
|
||||
public int iImage;
|
||||
public IntPtr lParam;
|
||||
public int iIndent;
|
||||
public int iGroupId;
|
||||
public int cColumns;
|
||||
public IntPtr puColumns;
|
||||
};
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr SendMessageLVItem(IntPtr hWnd, int msg, int wParam, ref LVITEM lvi);
|
||||
|
||||
/// <summary>
|
||||
/// Select all rows on the given listview
|
||||
/// </summary>
|
||||
/// <param name="list">The listview whose items are to be selected</param>
|
||||
public static void SelectAllItems(this ListView list)
|
||||
{
|
||||
SetItemState(list, -1, 2, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect all rows on the given listview
|
||||
/// </summary>
|
||||
/// <param name="list">The listview whose items are to be deselected</param>
|
||||
public static void DeselectAllItems(this ListView list)
|
||||
{
|
||||
SetItemState(list, -1, 2, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the item state on the given item
|
||||
/// </summary>
|
||||
/// <param name="list">The listview whose item's state is to be changed</param>
|
||||
/// <param name="itemIndex">The index of the item to be changed</param>
|
||||
/// <param name="mask">Which bits of the value are to be set?</param>
|
||||
/// <param name="value">The value to be set</param>
|
||||
public static void SetItemState(ListView list, int itemIndex, int mask, int value)
|
||||
{
|
||||
LVITEM lvItem = new LVITEM();
|
||||
lvItem.stateMask = mask;
|
||||
lvItem.state = value;
|
||||
SendMessageLVItem(list.Handle, LVM_SETITEMSTATE, itemIndex, ref lvItem);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class TextBoxExtension
|
||||
{
|
||||
private const int EM_SETTABSTOPS = 0x00CB;
|
||||
|
||||
[DllImport("User32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, int[] lParam);
|
||||
|
||||
public static Point GetCaretPosition(this TextBox textBox)
|
||||
{
|
||||
Point point = new Point(0, 0);
|
||||
|
||||
if (textBox.Focused)
|
||||
{
|
||||
point.X = textBox.SelectionStart - textBox.GetFirstCharIndexOfCurrentLine() + 1;
|
||||
point.Y = textBox.GetLineFromCharIndex(textBox.SelectionStart) + 1;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
public static void SetTabStopWidth(this TextBox textbox, int width)
|
||||
{
|
||||
SendMessage(textbox.Handle, EM_SETTABSTOPS, 1, new int[] { width * 4 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class Prompt
|
||||
{
|
||||
//handy utility to get a string from the user...
|
||||
public static string ShowDialog(IWin32Window owner, string text, string caption, ThemeBase theme, string defaultvalue = "")
|
||||
{
|
||||
Form prompt = new Form()
|
||||
{
|
||||
Width = 450,
|
||||
Height = 150,
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog,
|
||||
Text = caption,
|
||||
StartPosition = FormStartPosition.CenterParent,
|
||||
MaximizeBox = false,
|
||||
MinimizeBox = false
|
||||
};
|
||||
FormTheme.SetTheme(prompt, theme);
|
||||
var textLabel = new Label() { Left = 30, Top = 20, Width = 370, Height = 20, Text = text, };
|
||||
var textBox = new TextBox() { Left = 30, Top = 40, Width = 370, Text = defaultvalue };
|
||||
var cancel = new Button() { Text = "Cancel", Left = 230, Width = 80, Top = 70, DialogResult = DialogResult.Cancel };
|
||||
var confirmation = new Button() { Text = "Ok", Left = 320, Width = 80, Top = 70, DialogResult = DialogResult.OK };
|
||||
cancel.Click += (sender, e) => { prompt.Close(); };
|
||||
confirmation.Click += (sender, e) => { prompt.Close(); };
|
||||
prompt.Controls.Add(textBox);
|
||||
prompt.Controls.Add(confirmation);
|
||||
prompt.Controls.Add(cancel);
|
||||
prompt.Controls.Add(textLabel);
|
||||
prompt.AcceptButton = confirmation;
|
||||
|
||||
return prompt.ShowDialog(owner) == DialogResult.OK ? textBox.Text : "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class FormTheme
|
||||
{
|
||||
public static void SetTheme(Control form, ThemeBase theme)
|
||||
{
|
||||
form.BackColor = SystemColors.Control;
|
||||
form.ForeColor = SystemColors.ControlText;
|
||||
var txtback = SystemColors.Window;
|
||||
var wndback = SystemColors.Window;
|
||||
var disback = SystemColors.Control;
|
||||
var disfore = form.ForeColor;
|
||||
var btnback = Color.Transparent;
|
||||
var fStyle = FlatStyle.System;
|
||||
var panelC = SystemColors.Control;
|
||||
var dropdwn = SystemColors.Control;
|
||||
var dropdwntxt = form.ForeColor;
|
||||
|
||||
if (theme is VS2015DarkTheme)
|
||||
{
|
||||
form.BackColor = theme.ColorPalette.MainWindowActive.Background;
|
||||
form.ForeColor = Color.White;
|
||||
txtback = Color.FromArgb(72, 75, 82);// form.BackColor;
|
||||
wndback = theme.ColorPalette.MainWindowActive.Background;
|
||||
disback = form.BackColor;// Color.FromArgb(32,32,32);
|
||||
disfore = Color.DarkGray;
|
||||
btnback = form.BackColor;
|
||||
fStyle = FlatStyle.Flat;
|
||||
panelC = form.BackColor;
|
||||
dropdwn = form.BackColor;
|
||||
dropdwntxt = form.ForeColor;
|
||||
}
|
||||
|
||||
if (theme is VS2015BlueTheme)
|
||||
{
|
||||
panelC = theme.ColorPalette.MainWindowActive.Background;
|
||||
dropdwn = panelC;
|
||||
dropdwntxt = Color.White;
|
||||
}
|
||||
|
||||
var allcontrols = new List<Control>();
|
||||
RecurseControls(form, allcontrols);
|
||||
|
||||
foreach (var c in allcontrols)
|
||||
{
|
||||
if (c is TabPage)
|
||||
{
|
||||
c.ForeColor = form.ForeColor;
|
||||
c.BackColor = wndback;
|
||||
}
|
||||
else if ((c is CheckedListBox) || (c is ListBox))
|
||||
{
|
||||
c.ForeColor = form.ForeColor;
|
||||
c.BackColor = txtback;
|
||||
}
|
||||
else if ((c is ListView))
|
||||
{
|
||||
c.ForeColor = form.ForeColor;
|
||||
c.BackColor = wndback;
|
||||
}
|
||||
else if ((c is TextBox))
|
||||
{
|
||||
var txtbox = c as TextBox;
|
||||
c.ForeColor = txtbox.ReadOnly ? disfore : form.ForeColor;
|
||||
c.BackColor = txtbox.ReadOnly ? disback : txtback;
|
||||
}
|
||||
else if ((c is Button) || (c is GroupBox))
|
||||
{
|
||||
c.ForeColor = form.ForeColor;
|
||||
c.BackColor = btnback;
|
||||
}
|
||||
else if (c is TreeView)
|
||||
{
|
||||
c.ForeColor = form.ForeColor;
|
||||
c.BackColor = wndback;
|
||||
(c as TreeView).LineColor = form.ForeColor;
|
||||
}
|
||||
else if (c is Panel)
|
||||
{
|
||||
c.BackColor = panelC;
|
||||
}
|
||||
else if (c is TrackBar)
|
||||
{
|
||||
c.BackColor = form.BackColor;
|
||||
}
|
||||
else if (c is ReadOnlyPropertyGrid)
|
||||
{
|
||||
var rpd = (ReadOnlyPropertyGrid)c;
|
||||
rpd.ViewBackColor = txtback;
|
||||
rpd.ViewForeColor = form.ForeColor;
|
||||
}
|
||||
else if (c is PropertyGridFix)
|
||||
{
|
||||
var rpd = (PropertyGridFix)c;
|
||||
rpd.ViewBackColor = form.BackColor;
|
||||
rpd.ViewForeColor = form.ForeColor;
|
||||
}
|
||||
else if (c is ComboBox)
|
||||
{
|
||||
var cb = (ComboBox)c;
|
||||
|
||||
cb.BackColor = dropdwn;
|
||||
cb.FlatStyle = fStyle;
|
||||
cb.ForeColor = dropdwntxt;
|
||||
}
|
||||
else if (c is ContextMenuStrip)
|
||||
{
|
||||
c.BackColor = form.BackColor;
|
||||
c.ForeColor = form.ForeColor;
|
||||
}
|
||||
else if (c is StatusStrip)
|
||||
{
|
||||
var ss = (StatusStrip)c;
|
||||
VisualStudioToolStripExtender ve = new VisualStudioToolStripExtender();
|
||||
var version = VisualStudioToolStripExtender.VsVersion.Vs2015;
|
||||
ve.SetStyle(ss, version, theme);
|
||||
}
|
||||
else if (c is MenuStrip)
|
||||
{
|
||||
var ms = (MenuStrip)c;
|
||||
VisualStudioToolStripExtender ve = new VisualStudioToolStripExtender();
|
||||
var version = VisualStudioToolStripExtender.VsVersion.Vs2015;
|
||||
ve.SetStyle(ms, version, theme);
|
||||
}
|
||||
else if (c is ToolStrip)
|
||||
{
|
||||
var ts = (ToolStrip)c;
|
||||
VisualStudioToolStripExtender ve = new VisualStudioToolStripExtender();
|
||||
var version = VisualStudioToolStripExtender.VsVersion.Vs2015;
|
||||
ve.SetStyle(ts, version, theme);
|
||||
}
|
||||
else if (c is ToolStripFix)
|
||||
{
|
||||
var tsf = (ToolStripFix)c;
|
||||
VisualStudioToolStripExtender ve = new VisualStudioToolStripExtender();
|
||||
var version = VisualStudioToolStripExtender.VsVersion.Vs2015;
|
||||
ve.SetStyle(tsf, version, theme);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private static void RecurseControls(Control c, List<Control> l)
|
||||
{
|
||||
foreach (Control cc in c.Controls)
|
||||
{
|
||||
l.Add(cc);
|
||||
RecurseControls(cc, l);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//unused
|
||||
//public class AccurateTimer
|
||||
//{
|
||||
// private delegate void TimerEventDel(int id, int msg, IntPtr user, int dw1, int dw2);
|
||||
// private const int TIME_PERIODIC = 1;
|
||||
// private const int EVENT_TYPE = TIME_PERIODIC;// + 0x100; // TIME_KILL_SYNCHRONOUS causes a hang ?!
|
||||
// [DllImport("winmm.dll")]
|
||||
// private static extern int timeBeginPeriod(int msec);
|
||||
// [DllImport("winmm.dll")]
|
||||
// private static extern int timeEndPeriod(int msec);
|
||||
// [DllImport("winmm.dll")]
|
||||
// private static extern int timeSetEvent(int delay, int resolution, TimerEventDel handler, IntPtr user, int eventType);
|
||||
// [DllImport("winmm.dll")]
|
||||
// private static extern int timeKillEvent(int id);
|
||||
// Action mAction;
|
||||
// Form mForm;
|
||||
// private int mTimerId;
|
||||
// private TimerEventDel mHandler; // NOTE: declare at class scope so garbage collector doesn't release it!!!
|
||||
// public AccurateTimer(Form form, Action action, int delay)
|
||||
// {
|
||||
// mAction = action;
|
||||
// mForm = form;
|
||||
// timeBeginPeriod(1);
|
||||
// mHandler = new TimerEventDel(TimerCallback);
|
||||
// mTimerId = timeSetEvent(delay, 0, mHandler, IntPtr.Zero, EVENT_TYPE);
|
||||
// }
|
||||
// public void Stop()
|
||||
// {
|
||||
// int err = timeKillEvent(mTimerId);
|
||||
// timeEndPeriod(1);
|
||||
// System.Threading.Thread.Sleep(100);// Ensure callbacks are drained
|
||||
// }
|
||||
// private void TimerCallback(int id, int msg, IntPtr user, int dw1, int dw2)
|
||||
// {
|
||||
// if (mTimerId != 0) mForm.BeginInvoke(mAction);
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
36
CodeWalker.WinForms/MenuStripFix.Designer.cs
generated
Normal file
36
CodeWalker.WinForms/MenuStripFix.Designer.cs
generated
Normal file
@ -0,0 +1,36 @@
|
||||
namespace CodeWalker.WinForms
|
||||
{
|
||||
partial class MenuStripFix
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
49
CodeWalker.WinForms/MenuStripFix.cs
Normal file
49
CodeWalker.WinForms/MenuStripFix.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CodeWalker.WinForms
|
||||
{
|
||||
public partial class MenuStripFix : MenuStrip
|
||||
{
|
||||
public MenuStripFix()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
base.OnPaint(pe);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const uint WM_LBUTTONDOWN = 0x201;
|
||||
const uint WM_LBUTTONUP = 0x202;
|
||||
|
||||
static private bool down = false;
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
//fix to properly handle the mouse down event when the form isn't currently focused...
|
||||
if (m.Msg == WM_LBUTTONUP && !down)
|
||||
{
|
||||
m.Msg = (int)WM_LBUTTONDOWN;
|
||||
base.WndProc(ref m);
|
||||
m.Msg = (int)WM_LBUTTONUP;
|
||||
}
|
||||
|
||||
if (m.Msg == WM_LBUTTONDOWN) down = true;
|
||||
if (m.Msg == WM_LBUTTONUP) down = false;
|
||||
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
}
|
||||
}
|
69
CodeWalker.WinForms/ProjectPanel.cs
Normal file
69
CodeWalker.WinForms/ProjectPanel.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
namespace CodeWalker.Project
|
||||
{
|
||||
public class ProjectPanel : DockContent
|
||||
{
|
||||
|
||||
public virtual void SetTheme(ThemeBase theme)
|
||||
{
|
||||
FormTheme.SetTheme(this, theme);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class ProjectFloatWindow : FloatWindow
|
||||
{
|
||||
public ProjectFloatWindow(DockPanel dockPanel, DockPane pane)
|
||||
: base(dockPanel, pane)
|
||||
{
|
||||
Init(dockPanel, pane);
|
||||
}
|
||||
|
||||
public ProjectFloatWindow(DockPanel dockPanel, DockPane pane, Rectangle bounds)
|
||||
: base(dockPanel, pane, bounds)
|
||||
{
|
||||
Init(dockPanel, pane);
|
||||
}
|
||||
|
||||
private void Init(DockPanel dockPanel, DockPane pane)
|
||||
{
|
||||
FormBorderStyle = FormBorderStyle.Sizable;
|
||||
|
||||
//trying to set float window tab strip location to the top... for some reason it defaults to bottom!
|
||||
//var t = this;
|
||||
//if (pane != null)
|
||||
//{
|
||||
// pane.DockState = DockState.Document;
|
||||
//}
|
||||
//if (dockPanel != null)
|
||||
//{
|
||||
// dockPanel.DocumentTabStripLocation = DocumentTabStripLocation.Top;
|
||||
//}
|
||||
//if (DockPanel != null)
|
||||
//{
|
||||
// DockPanel.DocumentTabStripLocation = DocumentTabStripLocation.Top;
|
||||
//}
|
||||
}
|
||||
}
|
||||
public class ProjectFloatWindowFactory : DockPanelExtender.IFloatWindowFactory
|
||||
{
|
||||
public FloatWindow CreateFloatWindow(DockPanel dockPanel, DockPane pane, Rectangle bounds)
|
||||
{
|
||||
return new ProjectFloatWindow(dockPanel, pane, bounds);
|
||||
}
|
||||
|
||||
public FloatWindow CreateFloatWindow(DockPanel dockPanel, DockPane pane)
|
||||
{
|
||||
return new ProjectFloatWindow(dockPanel, pane);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user