Offer to restart game from VEH exception handler (#936)

This commit is contained in:
kizer 2022-07-27 04:14:48 +09:00 committed by GitHub
parent 98e421a227
commit 58ceb1dc87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1279 additions and 616 deletions

View file

@ -7,7 +7,7 @@ using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Dalamud.Game;
using Newtonsoft.Json;
using Reloaded.Memory.Buffers;
@ -484,6 +484,7 @@ namespace Dalamud.Injector
var withoutDalamud = false;
var noFixAcl = false;
var waitForGameWindow = true;
var encryptArguments = false;
var parsingGameArgument = false;
for (var i = 2; i < args.Count; i++)
@ -520,6 +521,43 @@ namespace Dalamud.Injector
throw new CommandLineException($"\"{args[i]}\" is not a command line argument.");
}
var checksumTable = "fX1pGtdS5CAP4_VL";
var argDelimiterRegex = new Regex(" (?<!(?:^|[^ ])(?: )*)/");
var kvDelimiterRegex = new Regex(" (?<!(?:^|[^ ])(?: )*)=");
gameArguments = gameArguments.SelectMany(x =>
{
if (!x.StartsWith("//**sqex0003") || !x.EndsWith("**//"))
return new List<string>() { x };
var checksum = checksumTable.IndexOf(x[x.Length - 5]);
if (checksum == -1)
return new List<string>() { x };
var encData = Convert.FromBase64String(x.Substring(12, x.Length - 12 - 5).Replace('-', '+').Replace('_', '/').Replace('*', '='));
var rawData = new byte[encData.Length];
for (var i = (uint)checksum; i < 0x10000u; i += 0x10)
{
var bf = new LegacyBlowfish(Encoding.UTF8.GetBytes($"{i << 16:x08}"));
Buffer.BlockCopy(encData, 0, rawData, 0, rawData.Length);
bf.Decrypt(ref rawData);
var rawString = Encoding.UTF8.GetString(rawData).Split('\0', 2).First();
encryptArguments = true;
var args = argDelimiterRegex.Split(rawString).Skip(1).Select(y => string.Join('=', kvDelimiterRegex.Split(y, 2)).Replace(" ", " ")).ToList();
if (!args.Any())
continue;
if (!args.First().StartsWith("T="))
continue;
if (!uint.TryParse(args.First().Substring(2), out var tickCount))
continue;
if (tickCount >> 16 != i)
continue;
return args.Skip(1);
}
return new List<string>() { x };
}).ToList();
if (showHelp)
{
ProcessHelpCommand(args, "launch");
@ -603,7 +641,39 @@ namespace Dalamud.Injector
});
}
var gameArgumentString = string.Join(" ", gameArguments.Select(x => EncodeParameterArgument(x)));
string gameArgumentString;
if (encryptArguments)
{
var rawTickCount = (uint)Environment.TickCount;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
[System.Runtime.InteropServices.DllImport("c")]
static extern ulong clock_gettime_nsec_np(int clock_id);
const int CLOCK_MONOTONIC_RAW = 4;
var rawTickCountFixed = (clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) / 1000000);
Log.Information("ArgumentBuilder::DeriveKey() fixing up rawTickCount from {0} to {1} on macOS", rawTickCount, rawTickCountFixed);
rawTickCount = (uint)rawTickCountFixed;
}
var ticks = rawTickCount & 0xFFFF_FFFFu;
var key = ticks & 0xFFFF_0000u;
gameArguments.Insert(0, $"T={ticks}");
var escapeValue = (string x) => x.Replace(" ", " ");
gameArgumentString = gameArguments.Select(x => x.Split('=', 2)).Aggregate(new StringBuilder(), (whole, part) => whole.Append($" /{escapeValue(part[0])} ={escapeValue(part.Length > 1 ? part[1] : string.Empty)}")).ToString();
var bf = new LegacyBlowfish(Encoding.UTF8.GetBytes($"{key:x08}"));
var ciphertext = bf.Encrypt(Encoding.UTF8.GetBytes(gameArgumentString));
var base64Str = Convert.ToBase64String(ciphertext).Replace('+', '-').Replace('/', '_').Replace('=', '*');
var checksum = checksumTable[(int)(key >> 16) & 0xF];
gameArgumentString = $"//**sqex0003{base64Str}{checksum}**//";
}
else
{
gameArgumentString = string.Join(" ", gameArguments.Select(x => EncodeParameterArgument(x)));
}
var process = GameStart.LaunchGame(Path.GetDirectoryName(gamePath), gamePath, gameArgumentString, noFixAcl, (Process p) =>
{
if (!withoutDalamud && mode == "entrypoint")