mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2026-05-15 00:54:47 +08:00
Moved tools forms into Tools folder, removed unused Materials.txt
This commit is contained in:
@@ -0,0 +1,984 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user