Refactor Bink class, Rename Bink.cs -> Binka.cs

This commit is contained in:
miku-666
2023-01-08 00:53:43 +01:00
parent 07bcde39dc
commit bbaf7b965a
4 changed files with 158 additions and 191 deletions

View File

@@ -1,179 +0,0 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
namespace PckStudio.Classes
{
internal class Bink
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr FreeLibrary(IntPtr library);
public int temp_error_code;
string binka_enc_loc;
string mss32_loc;
string binkawin_loc;
public string working = null;
public async void WavToBinka(string infile, string outFile, int compression)
{
var process = Process.Start(new ProcessStartInfo
{
FileName = binka_enc_loc,
Arguments = $"\"{infile}\" \"{outFile}\" -s -b{compression}",
UseShellExecute = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
});
process.WaitForExit();
temp_error_code = process.ExitCode;
}
public unsafe void BinkaToWav(string infile, string outFile)
{
string[] array2 = createArg(infile, outFile);
byte[] array3 = File.ReadAllBytes(array2[0]);
Console.WriteLine(array3.Length);
uint num = 0U;
AIL_set_redist_directory(".");
AIL_startup();
IntPtr intPtr;
// crash happens in AIL_decompress_ASI
if (AIL_decompress_ASI(array3, (uint)array3.Length, ".binka", &intPtr, &num, 0U) == 0)
throw new Exception("AIL ERROR");
byte[] array4 = new byte[num];
Marshal.Copy(intPtr, array4, 0, array4.Length);
AIL_mem_free_lock(intPtr);
AIL_shutdown();
File.WriteAllBytes(array2[1], array4);
}
public void SetUpBinka()
{
if (working == null)
{
working = (Path.GetTempPath() + "PCKStudio").Replace("\\","/");
Directory.CreateDirectory(working);
binka_enc_loc = ExtractResource("binka_encode.exe", working);
mss32_loc = ExtractResource("mss32.dll", working);
binkawin_loc = ExtractResource("binkawin.asi", working);
library = LoadLibrary(mss32_loc);
}
else
{
binka_enc_loc = working + "\\binka_encode.exe";
mss32_loc = working + "\\mss32.dll";
binkawin_loc = working + "\\binkawin.asi";
}
}
public void CleanUpBinka()
{
File.Delete(binka_enc_loc);
File.Delete(binkawin_loc);
while (File.Exists(mss32_loc))
{
try
{
File.Delete(mss32_loc);
}
catch
{
FreeLibrary(library);
}
}
Directory.Delete(working);
}
private static string getType(string loc)
{
string a = Path.GetExtension(loc).ToLower();
bool flag = a == ".binka";
string result;
if (flag)
{
result = "BINKA";
}
else
{
bool flag2 = !(a == ".wav");
if (flag2)
{
throw new Exception("File type not valid. To use MP3 or other audio formats, convert to wav format before using this tool");
}
result = "WAV";
}
return result;
}
private static string[] createArg(string inFile, string outdir = null)
{
string[] array = new string[2];
array[0] = inFile;
string[] array2 = array;
string type = getType(inFile);
bool flag = type == "BINKA";
if (flag)
{
array2[1] = ((outdir.Length <= 3) ? Path.GetFullPath(inFile.Replace(".binka", ".wav")) : (outdir + "\\" + Path.GetFileName(inFile.Replace(".binka", ".wav"))));
}
else
{
bool flag2 = type == "WAV";
if (flag2)
{
array2[1] = ((outdir.Length <= 3) ? Path.GetFullPath(inFile.Replace(".wav", ".binka")) : (outdir + "\\" + Path.GetFileName(inFile.Replace(".wav", ".binka"))));
}
}
bool flag3 = !Directory.Exists(Path.GetDirectoryName(array2[1]));
if (flag3)
{
Directory.CreateDirectory(Path.GetDirectoryName(array2[1]));
}
return array2;
}
internal static string ExtractResource(string resource, string working)
{
object ob = Properties.Resources.ResourceManager.GetObject(Path.GetFileNameWithoutExtension(resource));
byte[] myResBytes = (byte[])ob;
if(File.Exists(Path.Combine(working, resource))) File.Delete(Path.Combine(working, resource));
using (FileStream fsDst = new FileStream(Path.Combine(working, resource), FileMode.CreateNew, FileAccess.Write))
{
fsDst.Write(myResBytes, 0, myResBytes.Length);
fsDst.Close();
fsDst.Dispose();
}
return "\"" + working + "/" + resource + "\"";
}
[DllImport("mss32.dll", EntryPoint = "_AIL_decompress_ASI@24")]
private unsafe static extern int AIL_decompress_ASI([MarshalAs(UnmanagedType.LPArray)] byte[] indata, uint insize, [MarshalAs(UnmanagedType.LPStr)] string ext, IntPtr* result, uint* resultsize, uint zero);
[DllImport("mss32.dll", EntryPoint = "_AIL_last_error@0")]
private static extern IntPtr AIL_last_error();
[DllImport("mss32.dll", EntryPoint = "_AIL_set_redist_directory@4")]
private static extern IntPtr AIL_set_redist_directory([MarshalAs(UnmanagedType.LPStr)] string redistDir);
[DllImport("mss32.dll", EntryPoint = "_AIL_mem_free_lock@4")]
private static extern void AIL_mem_free_lock(IntPtr ptr);
[DllImport("mss32.dll", EntryPoint = "_AIL_startup@0")]
private static extern int AIL_startup();
[DllImport("mss32.dll", EntryPoint = "_AIL_shutdown@0")]
private static extern int AIL_shutdown();
public Bink()
{
}
private static IntPtr library;
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace PckStudio.Classes
{
internal static class Binka
{
private class LibHandle
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
public static extern int FreeLibrary(IntPtr library);
private IntPtr libHandle;
public IntPtr Handle => libHandle;
public LibHandle(string libraryPath)
{
libHandle = LoadLibrary(libraryPath);
}
~LibHandle()
{
FreeLibrary(libHandle);
}
}
private static string dataCache = Program.AppDataCache;
public static uint LastAILErrorCode = 0xffffffff;
public static int FromWav(string inputFilepath, string outputFilepath, int compressionLevel)
{
var process = Process.Start(new ProcessStartInfo
{
FileName = GetAndCacheResource("binka_encode.exe"),
Arguments = $"\"{inputFilepath}\" \"{outputFilepath}\" -s -b{compressionLevel}",
UseShellExecute = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
});
process.WaitForExit();
return process.ExitCode;
}
public static unsafe void ToWav(string inputFilename, string outputFilepath)
{
// handle should be closed when function gets out of scope
LibHandle mss32LibHandle = new LibHandle(GetAndCacheResource("mss32.dll"));
string ext = Path.GetExtension(inputFilename).ToLower();
switch (ext)
{
case ".binka":
inputFilename = inputFilename.Replace(".binka", ".wav");
break;
case ".wav":
inputFilename = inputFilename.Replace(".wav", ".binka");
break;
default:
throw new NotSupportedException(nameof(ext)+":"+ext);
}
string outputDirectory = Path.GetDirectoryName(outputFilepath);
Directory.CreateDirectory(outputDirectory);
string destinationFilepath = Path.Combine(outputDirectory, Path.GetFileName(inputFilename));
byte[] inputFiledata = File.ReadAllBytes(inputFilename);
Debug.WriteLine($"{nameof(inputFiledata)}: {inputFiledata.Length}");
AILInternalCalls.SetRedistDirectory(".");
AILInternalCalls.Startup(); // __fastcall
int resultBufferSize = 0;
IntPtr resultBuffer = new IntPtr();
// crash happens in AIL_decompress_ASI
LastAILErrorCode = (uint)AILInternalCalls.DecompressASI(inputFiledata, inputFiledata.Length, ".binka", resultBuffer, &resultBufferSize);
Debug.WriteLine("AIL Error Code: " + LastAILErrorCode.ToString());
byte[] buffer = new byte[resultBufferSize];
Marshal.Copy(resultBuffer, buffer, 0, resultBufferSize);
AILInternalCalls.MemFreeLock(resultBuffer);
AILInternalCalls.Shutdown();
File.WriteAllBytes(destinationFilepath, buffer);
}
// Move to a cache class ?
private static string GetAndCacheResource(string resourceName)
{
_ = resourceName ?? throw new ArgumentNullException(nameof(resourceName));
string destinationFilepath = Path.Combine(dataCache, resourceName);
if (!File.Exists(destinationFilepath))
{
byte[] resourceData = ExtractResource(resourceName);
using (FileStream fsDst = File.OpenWrite(destinationFilepath))
{
fsDst.Write(resourceData, 0, resourceData.Length);
}
}
return destinationFilepath;
}
internal static byte[] ExtractResource(string resourceName)
{
byte[] resourceData = (byte[])Properties.Resources.ResourceManager.GetObject(Path.GetFileNameWithoutExtension(resourceName));
return resourceData;
}
private class AILInternalCalls
{
public delegate int AIL_decomp_func();
[DllImport("mss32.dll", EntryPoint = "_AIL_decompress_ASI@24")]
public unsafe static extern int DecompressASI(
[MarshalAs(UnmanagedType.LPArray)] byte[] indata,
int insize,
[MarshalAs(UnmanagedType.LPStr)] string ext,
IntPtr result,
int *resultSize,
[MarshalAs(UnmanagedType.FunctionPtr)] AIL_decomp_func func = null);
[DllImport("mss32.dll", EntryPoint = "_AIL_last_error@0")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string LastError();
[DllImport("mss32.dll", EntryPoint = "_AIL_set_redist_directory@4")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string SetRedistDirectory([MarshalAs(UnmanagedType.LPStr)] string redistDir);
[DllImport("mss32.dll", EntryPoint = "_AIL_mem_free_lock@4")]
public static extern void MemFreeLock(IntPtr ptr);
[DllImport("mss32.dll", EntryPoint = "_AIL_startup@0")]
public static extern int Startup();
[DllImport("mss32.dll", EntryPoint = "_AIL_shutdown@0")]
public static extern int Shutdown();
}
}
}

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using MetroFramework.Forms;
using PckStudio.Classes;
using PckStudio.Classes.FileTypes;
using PckStudio.Classes.IO.PCK;
using PckStudio.Forms.Additional_Popups.Audio;
@@ -18,7 +19,6 @@ namespace PckStudio.Forms.Editor
public partial class AudioEditor : MetroForm
{
public string defaultType = "yes";
Classes.Bink BINK = new Classes.Bink();
PCKAudioFile audioFile = null;
PCKFile.FileData audioPCK;
LOCFile loc;
@@ -55,8 +55,6 @@ namespace PckStudio.Forms.Editor
loc = locFile;
_isLittleEndian = isLittleEndian;
BINK.SetUpBinka();
audioPCK = file;
using (var stream = new MemoryStream(file.data))
{
@@ -185,7 +183,8 @@ namespace PckStudio.Forms.Editor
async void ProcessEntries(string[] FileList)
{
foreach (string file in FileList)
int exitCode = 0;
foreach (string file in FileList)
{
if (Path.GetExtension(file) == ".binka" || Path.GetExtension(file) == ".wav")
{
@@ -214,14 +213,14 @@ namespace PckStudio.Forms.Editor
await Task.Run(() =>
{
BINK.WavToBinka(file, new_loc, (int)compressionUpDown.Value);
exitCode = Binka.FromWav(file, new_loc, (int)compressionUpDown.Value);
});
waitDiag.Close();
waitDiag.Dispose();
Cursor.Current = Cursors.Default;
if (BINK.temp_error_code != 0) continue;
if (exitCode != 0) continue;
}
else if (!duplicate_song)
{
@@ -404,7 +403,10 @@ namespace PckStudio.Forms.Editor
{
if (!parent.CreateDataFolder()) return;
OpenFileDialog ofn = new OpenFileDialog();
int exitCode = 0;
OpenFileDialog ofn = new OpenFileDialog();
ofn.Multiselect = true;
ofn.Filter = "Supported audio files (*.binka,*.wav)|*.binka;*.wav";
ofn.Title = "Please choose WAV or BINKA files to replace existing track files";
@@ -436,16 +438,16 @@ namespace PckStudio.Forms.Editor
await Task.Run(() =>
{
BINK.WavToBinka(file, new_loc, (int)compressionUpDown.Value);
exitCode = Binka.FromWav(file, new_loc, (int)compressionUpDown.Value);
});
waitDiag.Close();
waitDiag.Dispose();
Cursor.Current = Cursors.Default;
if (BINK.temp_error_code != 0) continue;
if (exitCode != 0) continue;
}
else if(file_ext == ".binka") File.Copy(file, Path.Combine(parent.GetDataPath(), Path.GetFileName(file)));
else if(file_ext == ".binka") File.Copy(file, Path.Combine(parent.GetDataPath(), Path.GetFileName(file)));
}
}
@@ -453,7 +455,7 @@ namespace PckStudio.Forms.Editor
{
if (treeView2.SelectedNode != null && treeView1.SelectedNode.Tag is PCKAudioFile.AudioCategory)
{
BINK.BinkaToWav(Path.Combine(parent.GetDataPath(), treeView2.SelectedNode.Text + ".binka"), Path.Combine(parent.GetDataPath()));
Binka.ToWav(Path.Combine(parent.GetDataPath(), treeView2.SelectedNode.Text + ".binka"), Path.Combine(parent.GetDataPath()));
}
}
}

View File

@@ -141,7 +141,7 @@
<Compile Include="Classes\FileTypes\CSMBFile.cs" />
<Compile Include="Classes\FileTypes\ModelFile.cs" />
<Compile Include="Classes\FileTypes\PCKAudioFile.cs" />
<Compile Include="Classes\FileTypes\Bink.cs" />
<Compile Include="Classes\FileTypes\Binka.cs" />
<Compile Include="Classes\FileTypes\COLFile.cs" />
<Compile Include="Classes\FileTypes\CSM.cs" />
<Compile Include="Classes\FileTypes\GRFFile.cs" />