fix(script): preserve scheduler counter increment
This commit is contained in:
3 files changed
+146
-6
No files matched your search
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
internal static class Handler2NativeOracle {
|
||||
private const uint LoadWithAlteredSearchPath = 0x00000008;
|
||||
private const int RefreshRecordRva = 0x5070;
|
||||
private const string ExpectedSha256 = "c19cd6cd31cd2896f8c4ba0f0e700dd3408aec8182daaf4863d98a7d233a2abc";
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern IntPtr LoadLibraryEx(string fileName, IntPtr file, uint flags);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool FreeLibrary(IntPtr module);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate void RefreshRecord(IntPtr record);
|
||||
|
||||
private static int Main() {
|
||||
if (IntPtr.Size != 4) {
|
||||
Console.Error.WriteLine("Build this oracle with an x86 target; ai.dll is 32-bit.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
string dllPath = Environment.GetEnvironmentVariable("FPARKAN_ORIGINAL_AI_DLL");
|
||||
if (String.IsNullOrEmpty(dllPath) || !File.Exists(dllPath)) {
|
||||
Console.Error.WriteLine("Set FPARKAN_ORIGINAL_AI_DLL to the original GOG ai.dll.");
|
||||
return 3;
|
||||
}
|
||||
|
||||
string actualSha256;
|
||||
using (SHA256 sha256 = SHA256.Create())
|
||||
using (FileStream input = File.OpenRead(dllPath)) {
|
||||
byte[] digest = sha256.ComputeHash(input);
|
||||
StringBuilder hex = new StringBuilder(digest.Length * 2);
|
||||
foreach (byte value in digest) hex.Append(value.ToString("x2"));
|
||||
actualSha256 = hex.ToString();
|
||||
}
|
||||
if (actualSha256 != ExpectedSha256) {
|
||||
Console.Error.WriteLine("Unexpected ai.dll SHA-256: " + actualSha256);
|
||||
return 4;
|
||||
}
|
||||
|
||||
IntPtr module = LoadLibraryEx(dllPath, IntPtr.Zero, LoadWithAlteredSearchPath);
|
||||
if (module == IntPtr.Zero) {
|
||||
Console.Error.WriteLine("LoadLibraryEx failed: " + Marshal.GetLastWin32Error());
|
||||
return 5;
|
||||
}
|
||||
|
||||
try {
|
||||
var refresh = (RefreshRecord)Marshal.GetDelegateForFunctionPointer(
|
||||
IntPtr.Add(module, RefreshRecordRva), typeof(RefreshRecord));
|
||||
IntPtr record = Marshal.AllocHGlobal(100);
|
||||
try {
|
||||
for (int offset = 0; offset < 100; offset += 4) Marshal.WriteInt32(record, offset, 0);
|
||||
Marshal.WriteInt32(record, 0x24, 4);
|
||||
Marshal.WriteInt32(record, 0x28, 4);
|
||||
AssertRefresh(refresh, record, 8);
|
||||
AssertRefresh(refresh, record, 12);
|
||||
|
||||
Marshal.WriteInt32(record, 0x24, unchecked((int)UInt32.MaxValue));
|
||||
Marshal.WriteInt32(record, 0x28, unchecked((int)UInt32.MaxValue));
|
||||
AssertRefresh(refresh, record, UInt32.MaxValue - 1);
|
||||
AssertRefresh(refresh, record, UInt32.MaxValue - 2);
|
||||
}
|
||||
finally { Marshal.FreeHGlobal(record); }
|
||||
}
|
||||
finally { FreeLibrary(module); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void AssertRefresh(RefreshRecord refresh, IntPtr record, uint expectedCounter) {
|
||||
uint savedIncrement = unchecked((uint)Marshal.ReadInt32(record, 0x28));
|
||||
refresh(record);
|
||||
uint actualCounter = unchecked((uint)Marshal.ReadInt32(record, 0x24));
|
||||
uint actualIncrement = unchecked((uint)Marshal.ReadInt32(record, 0x28));
|
||||
Console.WriteLine("record[+0x24]=0x{0:X8} record[+0x28]=0x{1:X8}",
|
||||
actualCounter, actualIncrement);
|
||||
if (actualCounter != expectedCounter || actualIncrement != savedIncrement) {
|
||||
throw new InvalidOperationException(String.Format(
|
||||
"Expected +0x24=0x{0:X8}, +0x28 unchanged at 0x{1:X8}.",
|
||||
expectedCounter, savedIncrement));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user