mirror of
https://github.com/4sval/FModel.git
synced 2026-08-22 09:24:32 -05:00
Criware decrypt key setting / HCA decoder
This commit is contained in:
Submodule CUE4Parse updated: afccc8919b...40813f382f
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Versions;
|
||||
@@ -24,7 +24,8 @@ public class DirectorySettings : ViewModel, ICloneable
|
||||
Endpoints = old?.Endpoints ?? EndpointSettings.Default(gameName),
|
||||
Directories = old?.Directories ?? CustomDirectory.Default(gameName),
|
||||
AesKeys = old?.AesKeys ?? new AesResponse { MainKey = aes, DynamicKeys = null },
|
||||
LastAesReload = old?.LastAesReload ?? DateTime.Today.AddDays(-1)
|
||||
LastAesReload = old?.LastAesReload ?? DateTime.Today.AddDays(-1),
|
||||
CriwareDecryptionKey = old?.CriwareDecryptionKey ?? 0
|
||||
};
|
||||
}
|
||||
|
||||
@@ -98,6 +99,13 @@ public class DirectorySettings : ViewModel, ICloneable
|
||||
set => SetProperty(ref _lastAesReload, value);
|
||||
}
|
||||
|
||||
private ulong _criwareDecryptionKey;
|
||||
public ulong CriwareDecryptionKey
|
||||
{
|
||||
get => _criwareDecryptionKey;
|
||||
set => SetProperty(ref _criwareDecryptionKey, value);
|
||||
}
|
||||
|
||||
private bool Equals(DirectorySettings other)
|
||||
{
|
||||
return GameDirectory == other.GameDirectory && UeVersion == other.UeVersion;
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
using CSCore;
|
||||
using CSCore.DSP;
|
||||
using CSCore.SoundOut;
|
||||
using CSCore.Streams;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -12,7 +8,12 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using CSCore;
|
||||
using CSCore.CoreAudioAPI;
|
||||
using CSCore.DSP;
|
||||
using CSCore.SoundOut;
|
||||
using CSCore.Streams;
|
||||
using CUE4Parse.UE4.CriWare.Decoders.HCA;
|
||||
using CUE4Parse.Utils;
|
||||
using FModel.Extensions;
|
||||
using FModel.Framework;
|
||||
@@ -569,7 +570,6 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable
|
||||
case "wem":
|
||||
case "at9":
|
||||
case "raw":
|
||||
case "hca":
|
||||
{
|
||||
if (TryConvert(out var wavFilePath))
|
||||
{
|
||||
@@ -580,6 +580,37 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable
|
||||
|
||||
return false;
|
||||
}
|
||||
case "hca":
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] wavData = HcaWaveStream.ConvertHcaToWav(SelectedAudioFile.Data, UserSettings.Default.CurrentDir.CriwareDecryptionKey);
|
||||
|
||||
string outputDir = Path.Combine(UserSettings.Default.OutputDirectory, ".data");
|
||||
Directory.CreateDirectory(outputDir);
|
||||
|
||||
string wavFilePath = Path.Combine(outputDir,
|
||||
Path.ChangeExtension(SelectedAudioFile.FileName, ".wav"));
|
||||
|
||||
File.WriteAllBytes(wavFilePath, wavData);
|
||||
|
||||
var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePath));
|
||||
Replace(newAudio);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (CriwareDecryptionException ex)
|
||||
{
|
||||
FLogger.Append(ELog.Error, () => FLogger.Text($"Failed to convert HCA: '{ex.Message}'", Constants.WHITE, true));
|
||||
Log.Error($"Failed to convert HCA: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Failed to convert HCA: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case "rada":
|
||||
case "binka":
|
||||
{
|
||||
|
||||
@@ -777,34 +777,33 @@ public class CUE4ParseViewModel : ViewModel
|
||||
break;
|
||||
}
|
||||
case "awb":
|
||||
{
|
||||
var archive = entry.CreateReader();
|
||||
var awbReader = new AwbReader(archive);
|
||||
|
||||
var extractedSounds = CriWareProvider.ExtractCriWareSounds(awbReader, archive.Name);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
var archive = entry.CreateReader();
|
||||
var awbReader = new AwbReader(archive);
|
||||
|
||||
var extractedSounds = CriWareProvider.ExtractCriWareSounds(awbReader, archive.Name);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine("/Criware/", sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
}
|
||||
|
||||
break;
|
||||
SaveAndPlaySound(Path.Combine("/Criware/", sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "acb":
|
||||
{
|
||||
var archive = entry.CreateReader();
|
||||
var acbReader = new AcbReader(archive);
|
||||
|
||||
TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(acbReader, Formatting.Indented), saveProperties, updateUi);
|
||||
|
||||
var extractedSounds = CriWareProvider.ExtractCriWareSounds(acbReader, archive.Name);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
var archive = entry.CreateReader();
|
||||
var acbReader = new AcbReader(archive);
|
||||
SaveAndPlaySound(Path.Combine("/Criware/", sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
}
|
||||
|
||||
TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(acbReader, Formatting.Indented), saveProperties, updateUi);
|
||||
|
||||
var extractedSounds = CriWareProvider.ExtractCriWareSounds(acbReader, archive.Name);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine("/Criware/", sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "xvag":
|
||||
case "flac":
|
||||
case "at9":
|
||||
|
||||
@@ -2,14 +2,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.Nanite;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.Serialization;
|
||||
using CUE4Parse.UE4.Versions;
|
||||
using CUE4Parse_Conversion.Meshes;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using CUE4Parse_Conversion.UEFormat.Enums;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.Nanite;
|
||||
using FModel.Framework;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
@@ -165,6 +165,13 @@ public class SettingsViewModel : ViewModel
|
||||
set => SetProperty(ref _selectedTextureExportFormat, value);
|
||||
}
|
||||
|
||||
private ulong _criwareDecryptionKey;
|
||||
public ulong CriwareDecryptionKey
|
||||
{
|
||||
get => _criwareDecryptionKey;
|
||||
set => SetProperty(ref _criwareDecryptionKey, value);
|
||||
}
|
||||
|
||||
public bool SocketSettingsEnabled => SelectedMeshExportFormat == EMeshFormat.ActorX;
|
||||
public bool CompressionSettingsEnabled => SelectedMeshExportFormat == EMeshFormat.UEFormat;
|
||||
|
||||
@@ -227,6 +234,7 @@ public class SettingsViewModel : ViewModel
|
||||
_customVersionsSnapshot = UserSettings.Default.CurrentDir.Versioning.CustomVersions;
|
||||
_optionsSnapshot = UserSettings.Default.CurrentDir.Versioning.Options;
|
||||
_mapStructTypesSnapshot = UserSettings.Default.CurrentDir.Versioning.MapStructTypes;
|
||||
_criwareDecryptionKey = UserSettings.Default.CurrentDir.CriwareDecryptionKey;
|
||||
|
||||
AesEndpoint = UserSettings.Default.CurrentDir.Endpoints[0];
|
||||
MappingEndpoint = UserSettings.Default.CurrentDir.Endpoints[1];
|
||||
@@ -262,6 +270,7 @@ public class SettingsViewModel : ViewModel
|
||||
SelectedNaniteMeshExportFormat = _naniteMeshExportFormatSnapshot;
|
||||
SelectedMaterialExportFormat = _materialExportFormatSnapshot;
|
||||
SelectedTextureExportFormat = _textureExportFormatSnapshot;
|
||||
CriwareDecryptionKey = _criwareDecryptionKey;
|
||||
SelectedAesReload = UserSettings.Default.AesReload;
|
||||
SelectedDiscordRpc = UserSettings.Default.DiscordRpc;
|
||||
|
||||
@@ -308,6 +317,7 @@ public class SettingsViewModel : ViewModel
|
||||
UserSettings.Default.CurrentDir.Versioning.CustomVersions = SelectedCustomVersions;
|
||||
UserSettings.Default.CurrentDir.Versioning.Options = SelectedOptions;
|
||||
UserSettings.Default.CurrentDir.Versioning.MapStructTypes = SelectedMapStructTypes;
|
||||
UserSettings.Default.CurrentDir.CriwareDecryptionKey = CriwareDecryptionKey;
|
||||
|
||||
UserSettings.Default.AssetLanguage = SelectedAssetLanguage;
|
||||
UserSettings.Default.CompressedAudioMode = SelectedCompressedAudio;
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -238,6 +239,26 @@
|
||||
<Slider Grid.Row="19" Grid.Column="2" Grid.ColumnSpan="5" TickPlacement="None" Minimum="0" Maximum="2048" Ticks="0,8,32,128,256,512,1024,2048"
|
||||
AutoToolTipPlacement="BottomRight" IsMoveToPointEnabled="True" IsSnapToTickEnabled="True" Margin="0 5 0 5"
|
||||
Value="{Binding WwiseMaxBnkPrefetch, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="20"
|
||||
Grid.Column="0"
|
||||
Text="CRIWARE Decryption Key"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 0 10" />
|
||||
|
||||
<TextBox x:Name="CriwareKeyBox"
|
||||
Grid.Row="20"
|
||||
Grid.Column="2"
|
||||
Grid.ColumnSpan="5"
|
||||
Margin="0 5 0 10"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
MaxLength="20"
|
||||
ToolTip="Enter decryption key in numeric or hexadecimal format (valid key is up to 20 digits or 8 bytes long)"
|
||||
TextAlignment="Right"
|
||||
TextChanged="CriwareKeyBox_TextChanged"
|
||||
Loaded="CriwareKeyBox_Loaded"/>
|
||||
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CreatorTemplate">
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using FModel.Services;
|
||||
@@ -190,4 +193,52 @@ public partial class SettingsView
|
||||
_applicationView.SettingsView.MappingEndpoint, "Endpoint Configuration (Mapping)", EEndpointType.Mapping);
|
||||
editor.ShowDialog();
|
||||
}
|
||||
|
||||
private void CriwareKeyBox_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not TextBox textBox)
|
||||
return;
|
||||
|
||||
textBox.Text = _applicationView.SettingsView.CriwareDecryptionKey.ToString();
|
||||
}
|
||||
|
||||
private void CriwareKeyBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (sender is not TextBox textBox)
|
||||
return;
|
||||
|
||||
string input = textBox.Text?.Trim() ?? string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return;
|
||||
|
||||
if (TryParseKey(input, out ulong parsed))
|
||||
_applicationView.SettingsView.CriwareDecryptionKey = parsed;
|
||||
}
|
||||
|
||||
private static bool TryParseKey(string text, out ulong value)
|
||||
{
|
||||
value = 0;
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return false;
|
||||
|
||||
bool isHex = false;
|
||||
if (text.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
isHex = true;
|
||||
text = text[2..];
|
||||
}
|
||||
else if (text.Any(char.IsLetter))
|
||||
{
|
||||
isHex = true;
|
||||
}
|
||||
|
||||
int numberBase = text.All(Uri.IsHexDigit) ? 16 : 10;
|
||||
return ulong.TryParse(
|
||||
text,
|
||||
isHex ? NumberStyles.HexNumber : NumberStyles.Integer,
|
||||
CultureInfo.InvariantCulture,
|
||||
out value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user