Files
ppc_amnet/AMNet.Server/DllMain.cs
T
2025-01-21 19:08:32 +00:00

144 lines
4.4 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Windows.Win32;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace AMNet.Server;
public static class DllMain
{
private const string WebAddress = "http://card.ppc.moe";
// instance metrics
internal static long LastPollTime = -1;
internal static long ServerStartedAt;
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()
{
CancellationTokenRegistration? cancellationRegistration = null;
cancellationRegistration = App.Lifetime.ApplicationStarted.Register(() =>
{
App.Logger.LogInformation("AMNet Server v{version} ({gameId}) started.", Config.ServerVersion.ToString(Config.ServerVersion.Build > 0 ? 3 : 2), Config.GameId ?? "SXXX");
App.Logger.LogInformation("Visit {addr} from a mobile device on the same network to get started.", WebAddress);
// ReSharper disable once AccessToModifiedClosure
cancellationRegistration?.Dispose();
});
Volatile.Write(ref ServerStartedAt, Environment.TickCount64);
App.RunAsync();
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "aime_io_nfc_poll")]
public static int NfcPoll(byte unitNo)
{
Volatile.Write(ref LastPollTime, Environment.TickCount64);
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<CardPresenter>().SetCard(aimeTxtReader.ReadLine(), null);
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;
}
[UnmanagedCallersOnly(EntryPoint = "aime_io_nfc_get_aime_id")]
public static int GetAimeId(byte unitNo, IntPtr luid, nint luidSize)
{
if (unitNo != 0)
{
return 1;
}
// if physical cards are being directed to
var card = App.Services.GetRequiredService<CardPresenter>().TakeActiveCard(Config.PhysicalCardUseIDm ? false : null);
if (card?.Expired != false)
{
return 1;
}
Marshal.Copy(card.AccessCode, 0, luid, (int)luidSize);
App.Logger.LogInformation("Access Code read: {cardId}", CardPresenter.FormatHexCode(card.AccessCode));
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "aime_io_nfc_get_felica_id")]
public static unsafe int GetFelicaId(byte unitNo, ulong* idm)
{
if (!Config.PhysicalCardUseIDm || unitNo != 0)
{
return 1;
}
var card = App.Services.GetRequiredService<CardPresenter>().TakeActiveCard(true);
if (card?.Expired != false)
{
return 1;
}
ulong idmValue = 0;
for (var i = 0 ; i < 8 ; i++)
{
idmValue = (idmValue << 8) | card.IDm[i];
}
*idm = idmValue;
App.Logger.LogInformation("FeliCa IDm read: {idm}", CardPresenter.FormatHexCode(card.IDm));
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "aime_io_led_set_color")]
public static void SetLedColour(byte unitNo, byte r, byte g, byte b)
{
// do nothing
}
}