diff --git a/AMNet.Server/Config.cs b/AMNet.Server/Config.cs index 7df4bb9..260df44 100644 --- a/AMNet.Server/Config.cs +++ b/AMNet.Server/Config.cs @@ -14,18 +14,24 @@ internal static class Config { GameId = ReadKey(IOSection, "gameId", 4); ServerName = ReadKey(IOSection, "serverName", 26, Environment.MachineName); + + EnableAimeTxt = PInvoke.GetPrivateProfileInt(IOSection, "enableKeyboardMode", 1, ConfigFileName) > 0; + AimeTxtPath = ReadKey("aime", "aimePath", PInvoke.MAX_PATH, @"DEVICE\aime.txt"); } public static string GameId { get; } public static string ServerName { get; } + public static bool EnableAimeTxt { get; } + public static string AimeTxtPath { get; } + internal static unsafe string ReadKey(string section, string key, uint maxLength, string @default = null) { + // +1 for null terminator var buffer = stackalloc char[(int)maxLength + 1]; var bufferStr = new PWSTR(buffer); - PInvoke.GetPrivateProfileString(section, key, @default ?? string.Empty, bufferStr, maxLength, ConfigFileName); - + PInvoke.GetPrivateProfileString(section, key, @default ?? string.Empty, bufferStr, maxLength + 1, ConfigFileName); return bufferStr.ToString(); } } \ No newline at end of file diff --git a/AMNet.Server/DllMain.cs b/AMNet.Server/DllMain.cs index 491325d..f3ef0a0 100644 --- a/AMNet.Server/DllMain.cs +++ b/AMNet.Server/DllMain.cs @@ -1,5 +1,6 @@ -using System.Linq; +using System.IO; using System.Runtime.InteropServices; +using System.Text; using System.Threading; using Windows.Win32; using Microsoft.AspNetCore.Builder; @@ -12,41 +13,72 @@ public static class DllMain { private const string WebAddress = "http://card.ppc.moe"; - private static WebApplication _app; - static DllMain() { PInvoke.AllocConsole(); + + App = WebServer.BuildServer(Config.ReadKey(Config.IOSection, "serverAddress", 1024, "http://+:6070").Split(';')); } + private static WebApplication App { get; } + [UnmanagedCallersOnly(EntryPoint = "aime_io_get_api_version")] public static ushort GetApiVersion() => 0x0100; [UnmanagedCallersOnly(EntryPoint = "aime_io_init")] public static int Init() { - var addresses = Config.ReadKey(Config.IOSection, "serverAddress", 1024, "http://+:6070").Split(';'); - - _app = WebServer.BuildServer(addresses); - CancellationTokenRegistration? cancellationRegistration = null; - cancellationRegistration = _app.Lifetime.ApplicationStarted.Register(() => + cancellationRegistration = App.Lifetime.ApplicationStarted.Register(() => { - _app.Logger.LogInformation("AMNet Server ({gameId}) started successfully.", Config.GameId); - _app.Logger.LogInformation("Visit {addr} from a mobile device on the same network to get started.", WebAddress); + App.Logger.LogInformation("AMNet Server ({gameId}) started successfully.", Config.GameId); + App.Logger.LogInformation("Visit {addr} from a mobile device on the same network to get started.", WebAddress); // ReSharper disable once AccessToModifiedClosure cancellationRegistration?.Dispose(); }); - _app.RunAsync(); + App.RunAsync(); return 0; } [UnmanagedCallersOnly(EntryPoint = "aime_io_nfc_poll")] public static int NfcPoll(byte unitNo) { - // there's no polling here (handled by the webserver) + if (!Config.EnableAimeTxt) + { + return 1; + } + + // check keyboard input for the enter key being held down (0x0D) + var enterPressed = (PInvoke.GetAsyncKeyState(0x0D) & 0x8000) != 0; + + if (!enterPressed) + { + return 0; + } + + try + { + using var aimeTxtReader = new StreamReader(File.OpenRead(Config.AimeTxtPath), Encoding.UTF8); + + var fileName = Path.GetFileName(Config.AimeTxtPath); + var cardResult = App.Services.GetRequiredService().SetCard(aimeTxtReader.ReadLine()); + + if (cardResult == null) + { + App.Logger.LogWarning("Failed to read card from {file}: invalid format", fileName); + } + else + { + App.Logger.LogInformation("Card loaded from {fileName}", fileName); + } + } + catch (IOException e) + { + App.Logger.LogWarning("Failed to read '{path}': {message}", Path.GetFullPath(Config.AimeTxtPath), e.Message); + } + return 0; } @@ -58,7 +90,7 @@ public static class DllMain return 1; } - var card = _app.Services.GetRequiredService().TakeActiveCard(); + var card = App.Services.GetRequiredService().TakeActiveCard(); if (card?.Expired != false) { return 1; @@ -71,7 +103,7 @@ public static class DllMain } finally { - _app.Logger.LogInformation("Card read in: {0}", string.Join(" ", Enumerable.Range(0, 5).Select(x => card.OriginalValue.Substring(x * 4, 4)))); + App.Logger.LogInformation("Card read in: {cardId}", card); } } diff --git a/AMNet.Server/NativeMethods.txt b/AMNet.Server/NativeMethods.txt index 3c5510e..7976195 100644 --- a/AMNet.Server/NativeMethods.txt +++ b/AMNet.Server/NativeMethods.txt @@ -1,3 +1,5 @@ GetPrivateProfileStringW GetPrivateProfileInt -AllocConsole \ No newline at end of file +GetAsyncKeyState +AllocConsole +MAX_PATH