using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using FSO.Client;
using FSO.Client.UI.Panels;
using FSO.Common;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Formats.Png;
namespace FSO.Unix
{
public static class Program
{
///
/// The main entry point for the application.
///
public static void Main(string[] args)
{
InitUnix();
var mgAssembly = typeof(Microsoft.Xna.Framework.Game).Assembly;
var platform = mgAssembly.GetType("MonoGame.Framework.Utilities.PlatformInfo");
var backend = platform?.GetProperty("GraphicsBackend")?.GetValue(null);
Console.WriteLine($"[FreeSO] MonoGame: {mgAssembly.GetName().Version} | Backend: {backend ?? "Unknown"}");
FSOEnvironment.Enable3D = true;
if ((new FSOProgram()).InitWithArguments(args))
{
var startProxy = new GameStartProxy();
startProxy.Start(false);
}
Environment.Exit(0);
}
public static void InitUnix()
{
FSO.Files.ImageLoaderHelpers.BitmapFunction = BitmapReader;
FSO.Files.ImageLoaderHelpers.SavePNGFunc = SavePNG;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
FSOProgram.ShowDialog = ShowDialog;
}
public static void ShowDialog(string text)
{
ShowDialog(text, "FreeSO Message");
}
private static string Escape(string s) => s.Replace("\"", "\\\"");
private static void ShowDialog(string text, string title)
{
if (text.Length > 1500) text = text.Substring(0, 1500) + "...";
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
var psi = new ProcessStartInfo
{
FileName = "osascript",
Arguments = $"-e \"display alert \\\"{Escape(title)}\\\" message \\\"{Escape(text)}\\\" giving up after 15\"",
UseShellExecute = true
};
Process.Start(psi)?.WaitForExit();
}
else
{
try
{
var psi = new ProcessStartInfo
{
FileName = "zenity",
Arguments = $"--error --title=\"{Escape(title)}\" --text=\"{Escape(text)}\"",
UseShellExecute = false
};
Process.Start(psi)?.WaitForExit();
}
catch
{
Console.Error.WriteLine($"[{title}] {text}");
}
}
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
string title = e.ExceptionObject is OutOfMemoryException
? "Out of Memory! FreeSO needs to close."
: "A fatal error occured! Screenshot this dialog and post it on Discord.";
ShowDialog(e.ExceptionObject.ToString(), title);
Environment.Exit(1);
}
public static void SavePNG(byte[] data, int width, int height, Stream str)
{
using var image = new Image(width, height);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int i = (y * width + x) * 4;
image[x, y] = new Rgba32(data[i], data[i + 1], data[i + 2], data[i + 3]);
}
}
image.Save(str, new PngEncoder());
}
public static Tuple BitmapReader(Stream str)
{
using var image = Image.Load(str);
int width = image.Width;
int height = image.Height;
var data = new byte[width * height * 4];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int i = (y * width + x) * 4;
Rgba32 px = image[x, y];
data[i] = px.R;
data[i + 1] = px.G;
data[i + 2] = px.B;
data[i + 3] = px.A;
}
}
return new Tuple(data, width, height);
}
}
}