mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-12-14 18:15:44 +00:00
251 lines
5.9 KiB
C#
251 lines
5.9 KiB
C#
// This file is part of Capy64 - https://github.com/Ale32bit/Capy64
|
|
// Copyright 2023 Alessandro "AlexDevs" Proto
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License").
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
using Capy64.API;
|
|
using Capy64.Eventing.Events;
|
|
using Capy64.Extensions;
|
|
using Capy64.Runtime.Libraries;
|
|
using KeraLua;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
|
|
namespace Capy64.Runtime;
|
|
|
|
internal class RuntimeManager : IComponent
|
|
{
|
|
private LuaState luaState;
|
|
private EventEmitter emitter;
|
|
|
|
private static int step = 0;
|
|
private static bool close = false;
|
|
private static bool inPanic = false;
|
|
|
|
private static IGame _game;
|
|
public RuntimeManager(IGame game)
|
|
{
|
|
_game = game;
|
|
|
|
_game.EventEmitter.OnInit += OnInit;
|
|
_game.EventEmitter.OnTick += OnTick;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Start Capy64 state.
|
|
/// First BIOS, then OS
|
|
/// </summary>
|
|
private void Start()
|
|
{
|
|
emitter?.Unregister();
|
|
|
|
luaState?.Dispose();
|
|
luaState = null;
|
|
close = false;
|
|
|
|
switch (step++)
|
|
{
|
|
case 0:
|
|
InitBIOS();
|
|
break;
|
|
case 1:
|
|
InitOS();
|
|
break;
|
|
default:
|
|
step = 0;
|
|
Start();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void Resume()
|
|
{
|
|
if (inPanic) return;
|
|
try
|
|
{
|
|
if (close || !luaState.ProcessQueue())
|
|
{
|
|
_game.EventEmitter.RaiseClose();
|
|
Start();
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.Error.WriteLine(e);
|
|
inPanic = true;
|
|
close = true;
|
|
PanicScreen.Render(e.Message);
|
|
}
|
|
}
|
|
|
|
public static void ResetPanic()
|
|
{
|
|
inPanic = false;
|
|
}
|
|
|
|
private void InitBIOS()
|
|
{
|
|
_game.Discord.SetPresence("Booting up...");
|
|
|
|
luaState = new LuaState();
|
|
_game.LuaRuntime = luaState;
|
|
|
|
emitter = new(_game.EventEmitter, luaState);
|
|
|
|
luaState.QueueEvent("init", LK =>
|
|
{
|
|
LK.PushInteger(step);
|
|
return 1;
|
|
});
|
|
|
|
emitter.Register();
|
|
|
|
luaState.Thread.PushCFunction(L_OpenDataFolder);
|
|
luaState.Thread.SetGlobal("openDataFolder");
|
|
|
|
luaState.Thread.PushCFunction(L_ShouldInstallOS);
|
|
luaState.Thread.SetGlobal("shouldInstallOS");
|
|
|
|
luaState.Thread.PushCFunction(L_FlagInstalled);
|
|
luaState.Thread.SetGlobal("flagInstalled");
|
|
|
|
luaState.Thread.PushCFunction(L_Exit);
|
|
luaState.Thread.SetGlobal("exit");
|
|
|
|
luaState.Thread.PushCFunction(L_SetConsole);
|
|
luaState.Thread.SetGlobal("setConsole");
|
|
|
|
luaState.Thread.PushCFunction(L_GetConsole);
|
|
luaState.Thread.SetGlobal("getConsole");
|
|
|
|
var status = luaState.Thread.LoadFile("Assets/bios.lua");
|
|
if (status != LuaStatus.OK)
|
|
{
|
|
throw new LuaException(luaState.Thread.ToString(-1));
|
|
}
|
|
}
|
|
|
|
private void InitOS()
|
|
{
|
|
_game.Discord.SetPresence("On CapyOS");
|
|
|
|
luaState = new LuaState();
|
|
_game.LuaRuntime = luaState;
|
|
|
|
emitter = new(_game.EventEmitter, luaState);
|
|
|
|
luaState.QueueEvent("init", LK =>
|
|
{
|
|
LK.PushInteger(step);
|
|
return 1;
|
|
});
|
|
|
|
emitter.Register();
|
|
|
|
var initContent = File.ReadAllText(Path.Combine(FileSystem.DataPath, "init.lua"));
|
|
var status = luaState.Thread.LoadString(initContent, "=init.lua");
|
|
if (status != LuaStatus.OK)
|
|
{
|
|
throw new LuaException(luaState.Thread.ToString(-1));
|
|
}
|
|
}
|
|
|
|
public static void Reset()
|
|
{
|
|
close = true;
|
|
step = 0;
|
|
}
|
|
|
|
public static void Reboot()
|
|
{
|
|
close = true;
|
|
}
|
|
|
|
public static void Shutdown()
|
|
{
|
|
close = true;
|
|
_game.Exit();
|
|
}
|
|
|
|
private static int L_OpenDataFolder(IntPtr state)
|
|
{
|
|
var path = FileSystem.DataPath;
|
|
switch (Environment.OSVersion.Platform)
|
|
{
|
|
case PlatformID.Win32NT:
|
|
Process.Start("explorer.exe", path);
|
|
break;
|
|
case PlatformID.Unix:
|
|
Process.Start("xdg-open", path);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static int L_ShouldInstallOS(IntPtr state)
|
|
{
|
|
var L = Lua.FromIntPtr(state);
|
|
var installedFilePath = Path.Combine(Capy64.AppDataPath, ".installed");
|
|
|
|
L.PushBoolean(!File.Exists(installedFilePath));
|
|
|
|
return 1;
|
|
}
|
|
|
|
private static int L_FlagInstalled(IntPtr state)
|
|
{
|
|
var installedFilePath = Path.Combine(Capy64.AppDataPath, ".installed");
|
|
if (!File.Exists(installedFilePath))
|
|
File.Create(installedFilePath).Dispose();
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static int L_Exit(IntPtr state)
|
|
{
|
|
close = true;
|
|
return 0;
|
|
}
|
|
|
|
private static int L_SetConsole(IntPtr state)
|
|
{
|
|
var L = Lua.FromIntPtr(state);
|
|
|
|
var status = L.ToBoolean(1);
|
|
_game.Window.ToggleConsole(status);
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static int L_GetConsole(IntPtr state)
|
|
{
|
|
var L = Lua.FromIntPtr(state);
|
|
|
|
var status = _game.Window.IsConsoleVisible();
|
|
L.PushBoolean(status);
|
|
|
|
return 1;
|
|
}
|
|
|
|
private void OnInit(object sender, EventArgs e)
|
|
{
|
|
Start();
|
|
}
|
|
|
|
private void OnTick(object sender, TickEvent e)
|
|
{
|
|
Resume();
|
|
}
|
|
}
|