using System; using System.Runtime.InteropServices; using System.Text; namespace BSO { /// Was der Loader (dinput8.dll) mitgibt - Gegenstueck zu HostApi in BSO.Loader\dinput8.cpp. [StructLayout(LayoutKind.Sequential)] public unsafe struct HostApi { public delegate* unmanaged Log; public char* GameDir; public char* BsoDir; } /// /// Einstieg: der Loader startet .NET beim ersten DirectInput8Create und ruft Start auf, danach OnFrame einmal pro /// Bild im Hauptthread des Spiels. Protokoll: <Spiel>\BSO\BSO_Loader.txt. /// public static unsafe class Bootstrap { public const string ModVersion = "0.5.0"; static HostApi* host; static int frameErrors; /// Ordner von BSO.dll (<Spiel>\BSO). public static string Folder { get; private set; } /// Ordner der Spiel-EXE (Bin_High_Win64). public static string GameFolder { get; private set; } [UnmanagedCallersOnly] public static void Start(HostApi* api) { try { host = api; Folder = new string(api->BsoDir); GameFolder = new string(api->GameDir); Log("BSO " + ModVersion + " gestartet (.NET " + Environment.Version + ")"); Log("Kommandozeile: " + Environment.CommandLine); Config.Load(); } catch (Exception e) { Log("Start fehlgeschlagen: " + e); } } [UnmanagedCallersOnly] public static void OnFrame() { try { Mem.NewFrame(); if (!Vision.Init()) return; if (Vision.TimerAdvanced()) { Input.Update(); BorderlessWindow.Update(); LocalPlayer.Update(); Multiplayer.Update(); RemotePlayers.Update(); PositionHud.Update(); } RemotePlayers.Draw(); PositionHud.Draw(); } catch (Exception e) { // Nicht jedes Bild ins Protokoll schreiben if (frameErrors++ < 5) Log("Fehler im Bild-Takt: " + e); } } public static void Log(string line) { if (host == null) return; byte[] bytes = Encoding.UTF8.GetBytes(line + "\0"); fixed (byte* p = bytes) host->Log(p); } } }