mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-01-18 18:46:43 +00:00
Adapting InputManager to SDL
This commit is contained in:
parent
0d358b09b9
commit
110afd1ca4
26 changed files with 579 additions and 495 deletions
406
Capy64/Capy64.cs
406
Capy64/Capy64.cs
|
@ -1,4 +1,4 @@
|
|||
// This file is part of Capy64 - https://github.com/Ale32bit/Capy64
|
||||
// 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").
|
||||
|
@ -13,37 +13,56 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Capy64.API;
|
||||
using Capy64.Core;
|
||||
using Capy64.Eventing;
|
||||
using Capy64.Extensions;
|
||||
using Capy64.Integrations;
|
||||
using Capy64.PluginManager;
|
||||
using Capy64.Runtime;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using MonoGame.Extended;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Capy64.Utils;
|
||||
|
||||
namespace Capy64;
|
||||
|
||||
public enum EngineMode
|
||||
{
|
||||
Classic,
|
||||
Free
|
||||
}
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Utils;
|
||||
using static SDL2.SDL;
|
||||
|
||||
public class Capy64 : Game
|
||||
public class Capy64 : IDisposable
|
||||
{
|
||||
public const string Version = "1.1.0-beta";
|
||||
public nint Window { get; private set; } = 0;
|
||||
public nint Renderer { get; private set; } = 0;
|
||||
public nint VideoSurface { get; private set; } = 0;
|
||||
public nint SurfaceRenderer { get; private set; } = 0;
|
||||
public int WindowWidth { get; private set; }
|
||||
public int WindowHeight { get; private set; }
|
||||
public int Width { get; set; } = DefaultParameters.Width;
|
||||
public int Height { get; set; } = DefaultParameters.Height;
|
||||
public float Scale { get; set; } = DefaultParameters.Scale;
|
||||
public int Tickrate { get; set; } = DefaultParameters.ClassicTickrate;
|
||||
public int Framerate { get; set; } = 60;
|
||||
|
||||
public float Ticktime => 1000f / Tickrate;
|
||||
public float Frametime => 1000f / Framerate;
|
||||
|
||||
public Color BorderColor { get; set; } = Color.Blue;
|
||||
|
||||
public Borders Borders {
|
||||
get => _borders;
|
||||
set {
|
||||
_borders = value;
|
||||
_outputRect = new() {
|
||||
x = value.Left,
|
||||
y = value.Top,
|
||||
w = (int)(Width * Scale),
|
||||
h = (int)(Height * Scale),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private SDL_Rect _outputRect;
|
||||
private Borders _borders;
|
||||
|
||||
public static readonly string AssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
public static readonly string AssetsPath = Path.Combine(AssemblyPath, "Assets");
|
||||
|
||||
public static class DefaultParameters
|
||||
{
|
||||
|
@ -57,165 +76,41 @@ public class Capy64 : Game
|
|||
public const int FreeTickrate = 60;
|
||||
}
|
||||
|
||||
public static readonly string AssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
public static readonly string AssetsPath = Path.Combine(AssemblyPath, "Assets");
|
||||
|
||||
public static string AppDataPath
|
||||
{
|
||||
get
|
||||
{
|
||||
public static string AppDataPath {
|
||||
get {
|
||||
string baseDir =
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Environment.GetFolderPath(
|
||||
Environment.SpecialFolder.ApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? Environment.GetFolderPath(
|
||||
Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? Environment.GetFolderPath(
|
||||
Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
"./";
|
||||
|
||||
return Path.Combine(baseDir, "Capy64");
|
||||
}
|
||||
}
|
||||
|
||||
public static Capy64 Instance { get; private set; }
|
||||
public Capy64 Game => this;
|
||||
public EngineMode EngineMode { get; private set; } = EngineMode.Classic;
|
||||
public IList<IComponent> NativePlugins { get; private set; }
|
||||
public IList<IComponent> Plugins { get; private set; }
|
||||
public int Width { get; set; } = DefaultParameters.Width;
|
||||
public int Height { get; set; } = DefaultParameters.Height;
|
||||
public float Scale { get; set; } = DefaultParameters.Scale;
|
||||
public Drawing Drawing { get; private set; }
|
||||
public Audio Audio { get; private set; }
|
||||
public LuaState LuaRuntime { get; set; }
|
||||
public Eventing.EventEmitter EventEmitter { get; private set; }
|
||||
public DiscordIntegration Discord { get; set; }
|
||||
public int TickRate => tickrate;
|
||||
public IConfiguration Configuration { get; private set; }
|
||||
|
||||
public Color BorderColor { get; set; } = Color.Black;
|
||||
|
||||
public Borders Borders = new()
|
||||
{
|
||||
Top = 0,
|
||||
Bottom = 0,
|
||||
Left = 0,
|
||||
Right = 0,
|
||||
};
|
||||
|
||||
public SpriteBatch SpriteBatch;
|
||||
|
||||
|
||||
private readonly InputManager _inputManager;
|
||||
private RenderTarget2D renderTarget;
|
||||
private readonly GraphicsDeviceManager _graphics;
|
||||
private ulong _totalTicks = 0;
|
||||
private int tickrate = 0;
|
||||
private int everyTick => 60 / tickrate;
|
||||
private bool _running = false;
|
||||
private InputManager _inputManager;
|
||||
public EventEmitter EventEmitter = new();
|
||||
|
||||
public Capy64()
|
||||
{
|
||||
Instance = this;
|
||||
ResetBorder();
|
||||
WindowWidth = (int)(Width * Scale) + Borders.Left + Borders.Right;
|
||||
WindowHeight = (int)(Height * Scale) + Borders.Top + Borders.Bottom;
|
||||
|
||||
_graphics = new GraphicsDeviceManager(this);
|
||||
//Content.RootDirectory = "Content";
|
||||
IsMouseVisible = true;
|
||||
|
||||
EventEmitter = new();
|
||||
_inputManager = new(this, EventEmitter);
|
||||
|
||||
Drawing = new();
|
||||
}
|
||||
|
||||
public void SetEngineMode(EngineMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case EngineMode.Classic:
|
||||
tickrate = DefaultParameters.ClassicTickrate;
|
||||
Width = DefaultParameters.Width;
|
||||
Height = DefaultParameters.Height;
|
||||
Window.AllowUserResizing = false;
|
||||
ResetBorder();
|
||||
|
||||
break;
|
||||
|
||||
case EngineMode.Free:
|
||||
tickrate = DefaultParameters.FreeTickrate;
|
||||
Window.AllowUserResizing = true;
|
||||
break;
|
||||
}
|
||||
|
||||
EngineMode = mode;
|
||||
|
||||
UpdateSize(true);
|
||||
}
|
||||
|
||||
public void UpdateSize(bool resize = true)
|
||||
{
|
||||
if (resize)
|
||||
{
|
||||
_graphics.PreferredBackBufferWidth = (int)(Width * Scale) + Borders.Left + Borders.Right;
|
||||
_graphics.PreferredBackBufferHeight = (int)(Height * Scale) + Borders.Top + Borders.Bottom;
|
||||
_graphics.ApplyChanges();
|
||||
}
|
||||
|
||||
renderTarget = new RenderTarget2D(
|
||||
GraphicsDevice,
|
||||
Width,
|
||||
Height,
|
||||
false,
|
||||
GraphicsDevice.PresentationParameters.BackBufferFormat,
|
||||
DepthFormat.Depth24, 0, RenderTargetUsage.PreserveContents);
|
||||
|
||||
Drawing.Canvas = renderTarget;
|
||||
|
||||
_inputManager.Texture = renderTarget;
|
||||
|
||||
EventEmitter.RaiseScreenSizeChange();
|
||||
}
|
||||
|
||||
private void OnWindowSizeChange(object sender, EventArgs e)
|
||||
{
|
||||
if (EngineMode == EngineMode.Classic)
|
||||
{
|
||||
UpdateSize(true);
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = Window.ClientBounds;
|
||||
|
||||
Width = (int)(bounds.Width / Scale);
|
||||
Height = (int)(bounds.Height / Scale);
|
||||
|
||||
if (Window.IsMaximized())
|
||||
{
|
||||
var vertical = bounds.Height - (Height * Scale);
|
||||
var horizontal = bounds.Width - (Width * Scale);
|
||||
|
||||
Borders.Top = (int)Math.Floor(vertical / 2d);
|
||||
Borders.Bottom = (int)Math.Ceiling(vertical / 2d);
|
||||
|
||||
Borders.Left = (int)Math.Floor(horizontal / 2d);
|
||||
Borders.Right = (int)Math.Ceiling(horizontal / 2d);
|
||||
|
||||
UpdateSize(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetBorder();
|
||||
UpdateSize();
|
||||
}
|
||||
_inputManager = new(null, EventEmitter);
|
||||
}
|
||||
|
||||
private void ResetBorder()
|
||||
{
|
||||
var size = (int)(Scale * DefaultParameters.BorderMultiplier);
|
||||
Borders = new Borders
|
||||
{
|
||||
Borders = new Borders {
|
||||
Top = size,
|
||||
Bottom = size,
|
||||
Left = size,
|
||||
|
@ -223,116 +118,113 @@ public class Capy64 : Game
|
|||
};
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
public void Run()
|
||||
{
|
||||
var configBuilder = new ConfigurationBuilder();
|
||||
#if DEBUG
|
||||
SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
|
||||
#endif
|
||||
|
||||
var settingsPath = Path.Combine(AppDataPath, "settings.json");
|
||||
if (!Directory.Exists(AppDataPath))
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||
{
|
||||
Directory.CreateDirectory(AppDataPath);
|
||||
}
|
||||
if (!File.Exists(settingsPath))
|
||||
{
|
||||
File.Copy(Path.Combine(AssetsPath, "default.json"), settingsPath);
|
||||
Console.WriteLine(SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
configBuilder.AddJsonFile(Path.Combine(AssetsPath, "default.json"), false);
|
||||
configBuilder.AddJsonFile(settingsPath, false);
|
||||
Window = SDL_CreateWindow("Capy64 " + Version,
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
WindowWidth, WindowHeight,
|
||||
SDL_WindowFlags.SDL_WINDOW_OPENGL);
|
||||
|
||||
Configuration = configBuilder.Build();
|
||||
|
||||
Window.Title = "Capy64 " + Version;
|
||||
|
||||
Scale = Configuration.GetValue("Window:Scale", DefaultParameters.Scale);
|
||||
|
||||
ResetBorder();
|
||||
UpdateSize();
|
||||
|
||||
Window.AllowUserResizing = true;
|
||||
Window.ClientSizeChanged += OnWindowSizeChange;
|
||||
|
||||
InactiveSleepTime = new TimeSpan(0);
|
||||
|
||||
SetEngineMode(Configuration.GetValue<EngineMode>("EngineMode", DefaultParameters.EngineMode));
|
||||
|
||||
Audio = new Audio();
|
||||
|
||||
NativePlugins = GetNativePlugins();
|
||||
var safeMode = Configuration.GetValue("SafeMode", false);
|
||||
if (!safeMode)
|
||||
Plugins = PluginLoader.LoadAllPlugins(Path.Combine(AppDataPath, "plugins"));
|
||||
|
||||
EventEmitter.RaiseInit();
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
private List<IComponent> GetNativePlugins()
|
||||
{
|
||||
var iType = typeof(IComponent);
|
||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(s => s.GetTypes())
|
||||
.Where(p => iType.IsAssignableFrom(p) && !p.IsInterface);
|
||||
|
||||
var plugins = new List<IComponent>();
|
||||
|
||||
foreach (var type in types)
|
||||
if (Window == nint.Zero)
|
||||
{
|
||||
var instance = (IComponent)Activator.CreateInstance(type, this);
|
||||
plugins.Add(instance);
|
||||
Console.WriteLine(SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
var icon = SDL_LoadBMP("./Icon.bmp");
|
||||
if(icon != 0)
|
||||
SDL_SetWindowIcon(Window, icon);
|
||||
|
||||
Renderer = SDL_CreateRenderer(Window,
|
||||
0,
|
||||
SDL_RendererFlags.SDL_RENDERER_ACCELERATED | SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC);
|
||||
|
||||
protected override void LoadContent()
|
||||
{
|
||||
SpriteBatch = new SpriteBatch(GraphicsDevice);
|
||||
}
|
||||
|
||||
protected override void Update(GameTime gameTime)
|
||||
{
|
||||
Drawing.Begin();
|
||||
|
||||
// Register user input
|
||||
_inputManager.Update(IsActive);
|
||||
|
||||
EventEmitter.RaiseTick(new()
|
||||
if (Renderer == nint.Zero)
|
||||
{
|
||||
GameTime = gameTime,
|
||||
TotalTicks = _totalTicks,
|
||||
IsActiveTick = (int)_totalTicks % everyTick == 0,
|
||||
});
|
||||
Console.WriteLine(SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
Drawing.End();
|
||||
VideoSurface = SDL_CreateRGBSurfaceWithFormat(0, Width, Height, 32, SDL_PIXELFORMAT_ARGB8888);
|
||||
SurfaceRenderer = SDL_CreateSoftwareRenderer(VideoSurface);
|
||||
|
||||
_totalTicks++;
|
||||
SDL_SetRenderDrawColor(SurfaceRenderer, 255, 255, 255, 255);
|
||||
SDL_RenderClear(SurfaceRenderer);
|
||||
|
||||
base.Update(gameTime);
|
||||
_running = true;
|
||||
ulong deltaEnd = 0;
|
||||
var perfFreq = SDL_GetPerformanceFrequency();
|
||||
while (_running)
|
||||
{
|
||||
var deltaStart = SDL_GetPerformanceCounter();
|
||||
var delta = deltaStart - deltaEnd;
|
||||
|
||||
while (SDL_PollEvent(out var ev) != 0)
|
||||
{
|
||||
ProcessEvent(ev);
|
||||
}
|
||||
|
||||
if ((uint)(perfFreq / delta) >= Framerate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
deltaEnd = deltaStart;
|
||||
|
||||
SDL_SetRenderDrawColor(Renderer, BorderColor.R, BorderColor.G, BorderColor.B, 255);
|
||||
SDL_RenderClear(Renderer);
|
||||
|
||||
SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 255);
|
||||
var texture = SDL_CreateTextureFromSurface(Renderer, VideoSurface);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(Renderer, SDL_BlendMode.SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_RenderCopy(Renderer, texture, 0, ref _outputRect);
|
||||
SDL_DestroyTexture(texture);
|
||||
SDL_RenderPresent(Renderer);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Draw(GameTime gameTime)
|
||||
private void ProcessEvent(SDL_Event ev)
|
||||
{
|
||||
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp);
|
||||
GraphicsDevice.Clear(BorderColor);
|
||||
|
||||
SpriteBatch.DrawRectangle(renderTarget.Bounds.Location.ToVector2() + new Vector2(Borders.Left, Borders.Top),
|
||||
new Size2(renderTarget.Bounds.Width * Scale, renderTarget.Bounds.Height * Scale), Color.Black,
|
||||
Math.Min(renderTarget.Bounds.Width, renderTarget.Bounds.Height), 0);
|
||||
|
||||
SpriteBatch.Draw(renderTarget, new(Borders.Left, Borders.Top), null, Color.White, 0f, Vector2.Zero, Scale,
|
||||
SpriteEffects.None, 0);
|
||||
|
||||
EventEmitter.RaiseOverlay(new()
|
||||
switch (ev.type)
|
||||
{
|
||||
GameTime = gameTime,
|
||||
TotalTicks = _totalTicks,
|
||||
});
|
||||
case SDL_EventType.SDL_QUIT:
|
||||
_running = false;
|
||||
break;
|
||||
|
||||
SpriteBatch.End();
|
||||
case SDL_EventType.SDL_KEYDOWN:
|
||||
break;
|
||||
|
||||
base.Draw(gameTime);
|
||||
case SDL_EventType.SDL_MOUSEBUTTONUP:
|
||||
case SDL_EventType.SDL_MOUSEBUTTONDOWN:
|
||||
|
||||
unsafe
|
||||
{
|
||||
var pitch = ((SDL_Surface*)VideoSurface)->pitch;
|
||||
((uint*)((SDL_Surface*)VideoSurface)->pixels)[x + y * pitch / 4] = 0xFFFF00FF;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SDL_DestroyRenderer(SurfaceRenderer);
|
||||
SDL_FreeSurface(VideoSurface);
|
||||
SDL_DestroyRenderer(Renderer);
|
||||
SDL_DestroyWindow(Window);
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
}
|
|
@ -53,7 +53,7 @@ public class Audio : IDisposable
|
|||
|
||||
private static void EnqueueAudioNeedEvent(int i, int pending)
|
||||
{
|
||||
Capy64.Instance.LuaRuntime.QueueEvent("audio_need", LK =>
|
||||
LegacyEntry.Instance.LuaRuntime.QueueEvent("audio_need", LK =>
|
||||
{
|
||||
LK.PushInteger(i);
|
||||
LK.PushInteger(pending);
|
||||
|
|
|
@ -54,7 +54,7 @@ public class Drawing : IDisposable
|
|||
public Drawing()
|
||||
{
|
||||
_fontSystem = new FontSystem();
|
||||
_fontSystem.AddFont(File.ReadAllBytes(Path.Combine(Capy64.AssetsPath, "font.ttf")));
|
||||
_fontSystem.AddFont(File.ReadAllBytes(Path.Combine(LegacyEntry.AssetsPath, "font.ttf")));
|
||||
}
|
||||
|
||||
public void Begin()
|
||||
|
@ -184,7 +184,7 @@ public class Drawing : IDisposable
|
|||
public void Clear(Color? color = default)
|
||||
{
|
||||
Color finalColor = color ?? Color.Black;
|
||||
Capy64.Instance.BorderColor = finalColor;
|
||||
LegacyEntry.Instance.BorderColor = finalColor;
|
||||
_graphicsDevice.Clear(finalColor);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ using Microsoft.Xna.Framework.Input;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SDL2;
|
||||
|
||||
namespace Capy64.Eventing;
|
||||
|
||||
|
@ -74,7 +75,7 @@ public class InputManager
|
|||
};
|
||||
|
||||
public Texture2D Texture { get; set; }
|
||||
public static float WindowScale => Capy64.Instance.Scale;
|
||||
public static float WindowScale => LegacyEntry.Instance.Scale;
|
||||
public const int MouseScrollDelta = 120;
|
||||
|
||||
private Point mousePosition;
|
||||
|
@ -84,17 +85,17 @@ public class InputManager
|
|||
private Modifiers keyboardMods = 0;
|
||||
private readonly HashSet<Keys> pressedKeys = new();
|
||||
|
||||
private readonly Game _game;
|
||||
private readonly Capy64 _game;
|
||||
private readonly EventEmitter _eventEmitter;
|
||||
public InputManager(Game game, EventEmitter eventManager)
|
||||
public InputManager(Capy64 game, EventEmitter eventManager)
|
||||
|
||||
{
|
||||
_game = game;
|
||||
_eventEmitter = eventManager;
|
||||
|
||||
_game.Window.KeyDown += OnKeyDown;
|
||||
/*_game.Window.KeyDown += OnKeyDown;
|
||||
_game.Window.KeyUp += OnKeyUp;
|
||||
_game.Window.TextInput += OnTextInput;
|
||||
_game.Window.TextInput += OnTextInput;*/
|
||||
|
||||
var mouseState = Mouse.GetState();
|
||||
vMouseScroll = mouseState.ScrollWheelValue;
|
||||
|
@ -108,12 +109,36 @@ public class InputManager
|
|||
UpdateGamePad(GamePad.GetState(PlayerIndex.One), IsActive);
|
||||
}
|
||||
|
||||
public void UpdateMouse(MouseState state, bool isActive)
|
||||
public void UpdateMouseSDL(SDL.SDL_Event ev)
|
||||
{
|
||||
var position = new Point(ev.button.x, ev.button.y);
|
||||
var rawPosition = position - new Point(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top);
|
||||
var pos = new Point((int)(rawPosition.X / WindowScale), (int)(rawPosition.Y / WindowScale)) + new Point(1, 1);
|
||||
|
||||
if (pos.X < 1 || pos.Y < 1 || pos.X > (_game.Width) || pos.Y > _game.Height)
|
||||
return;
|
||||
|
||||
if (pos != mousePosition)
|
||||
{
|
||||
mousePosition = pos;
|
||||
_eventEmitter.RaiseMouseMove(new()
|
||||
{
|
||||
Position = mousePosition,
|
||||
PressedButtons = mouseButtonStates
|
||||
.Where(q => q.Value == ButtonState.Pressed)
|
||||
.Select(q => (int)q.Key)
|
||||
.ToArray()
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void UpdateMouse(MouseState state, bool isActive)
|
||||
{
|
||||
if (!isActive)
|
||||
return;
|
||||
|
||||
var rawPosition = state.Position - new Point(Capy64.Instance.Borders.Left, Capy64.Instance.Borders.Top);
|
||||
var rawPosition = state.Position - new Point(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top);
|
||||
var pos = new Point((int)(rawPosition.X / WindowScale), (int)(rawPosition.Y / WindowScale)) + new Point(1, 1);
|
||||
|
||||
if (pos.X < 1 || pos.Y < 1 || pos.X > Texture.Width || pos.Y > Texture.Height)
|
||||
|
|
|
@ -28,7 +28,7 @@ public class DiscordIntegration : IComponent
|
|||
public readonly bool Enabled;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public DiscordIntegration(Capy64 game)
|
||||
public DiscordIntegration(LegacyEntry game)
|
||||
{
|
||||
_configuration = game.Configuration;
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class DiscordIntegration : IComponent
|
|||
|
||||
Client.OnReady += OnReady;
|
||||
|
||||
Capy64.Instance.Discord = this;
|
||||
LegacyEntry.Instance.Discord = this;
|
||||
|
||||
if (Enabled)
|
||||
Client.Initialize();
|
||||
|
@ -62,7 +62,7 @@ public class DiscordIntegration : IComponent
|
|||
Assets = new Assets()
|
||||
{
|
||||
LargeImageKey = "image_large",
|
||||
LargeImageText = "Capy64 " + Capy64.Version,
|
||||
LargeImageText = "Capy64 " + LegacyEntry.Version,
|
||||
SmallImageKey = "image_small"
|
||||
}
|
||||
});
|
||||
|
|
338
Capy64/LegacyEntry.cs
Normal file
338
Capy64/LegacyEntry.cs
Normal file
|
@ -0,0 +1,338 @@
|
|||
// 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.Core;
|
||||
using Capy64.Eventing;
|
||||
using Capy64.Extensions;
|
||||
using Capy64.Integrations;
|
||||
using Capy64.PluginManager;
|
||||
using Capy64.Runtime;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using MonoGame.Extended;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Capy64.Utils;
|
||||
|
||||
namespace Capy64;
|
||||
|
||||
public enum EngineMode
|
||||
{
|
||||
Classic,
|
||||
Free
|
||||
}
|
||||
|
||||
public class LegacyEntry : Game
|
||||
{
|
||||
public const string Version = "1.1.0-beta";
|
||||
|
||||
public static class DefaultParameters
|
||||
{
|
||||
public const int Width = 318;
|
||||
public const int Height = 240;
|
||||
public const float Scale = 2f;
|
||||
public const float BorderMultiplier = 1.5f;
|
||||
public static readonly EngineMode EngineMode = EngineMode.Classic;
|
||||
|
||||
public const int ClassicTickrate = 30;
|
||||
public const int FreeTickrate = 60;
|
||||
}
|
||||
|
||||
public static readonly string AssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
public static readonly string AssetsPath = Path.Combine(AssemblyPath, "Assets");
|
||||
|
||||
public static string AppDataPath
|
||||
{
|
||||
get
|
||||
{
|
||||
string baseDir =
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
"./";
|
||||
|
||||
return Path.Combine(baseDir, "Capy64");
|
||||
}
|
||||
}
|
||||
|
||||
public static LegacyEntry Instance { get; private set; }
|
||||
public LegacyEntry Game => this;
|
||||
public EngineMode EngineMode { get; private set; } = EngineMode.Classic;
|
||||
public IList<IComponent> NativePlugins { get; private set; }
|
||||
public IList<IComponent> Plugins { get; private set; }
|
||||
public int Width { get; set; } = DefaultParameters.Width;
|
||||
public int Height { get; set; } = DefaultParameters.Height;
|
||||
public float Scale { get; set; } = DefaultParameters.Scale;
|
||||
public Drawing Drawing { get; private set; }
|
||||
public Audio Audio { get; private set; }
|
||||
public LuaState LuaRuntime { get; set; }
|
||||
public Eventing.EventEmitter EventEmitter { get; private set; }
|
||||
public DiscordIntegration Discord { get; set; }
|
||||
public int TickRate => tickrate;
|
||||
public IConfiguration Configuration { get; private set; }
|
||||
|
||||
public Color BorderColor { get; set; } = Color.Black;
|
||||
|
||||
public Borders Borders = new()
|
||||
{
|
||||
Top = 0,
|
||||
Bottom = 0,
|
||||
Left = 0,
|
||||
Right = 0,
|
||||
};
|
||||
|
||||
public SpriteBatch SpriteBatch;
|
||||
|
||||
|
||||
private readonly InputManager _inputManager;
|
||||
private RenderTarget2D renderTarget;
|
||||
private readonly GraphicsDeviceManager _graphics;
|
||||
private ulong _totalTicks = 0;
|
||||
private int tickrate = 0;
|
||||
private int everyTick => 60 / tickrate;
|
||||
|
||||
public LegacyEntry()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
_graphics = new GraphicsDeviceManager(this);
|
||||
//Content.RootDirectory = "Content";
|
||||
IsMouseVisible = true;
|
||||
|
||||
EventEmitter = new();
|
||||
_inputManager = new(null, EventEmitter);
|
||||
|
||||
Drawing = new();
|
||||
}
|
||||
|
||||
public void SetEngineMode(EngineMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case EngineMode.Classic:
|
||||
tickrate = DefaultParameters.ClassicTickrate;
|
||||
Width = DefaultParameters.Width;
|
||||
Height = DefaultParameters.Height;
|
||||
Window.AllowUserResizing = false;
|
||||
ResetBorder();
|
||||
|
||||
break;
|
||||
|
||||
case EngineMode.Free:
|
||||
tickrate = DefaultParameters.FreeTickrate;
|
||||
Window.AllowUserResizing = true;
|
||||
break;
|
||||
}
|
||||
|
||||
EngineMode = mode;
|
||||
|
||||
UpdateSize(true);
|
||||
}
|
||||
|
||||
public void UpdateSize(bool resize = true)
|
||||
{
|
||||
if (resize)
|
||||
{
|
||||
_graphics.PreferredBackBufferWidth = (int)(Width * Scale) + Borders.Left + Borders.Right;
|
||||
_graphics.PreferredBackBufferHeight = (int)(Height * Scale) + Borders.Top + Borders.Bottom;
|
||||
_graphics.ApplyChanges();
|
||||
}
|
||||
|
||||
renderTarget = new RenderTarget2D(
|
||||
GraphicsDevice,
|
||||
Width,
|
||||
Height,
|
||||
false,
|
||||
GraphicsDevice.PresentationParameters.BackBufferFormat,
|
||||
DepthFormat.Depth24, 0, RenderTargetUsage.PreserveContents);
|
||||
|
||||
Drawing.Canvas = renderTarget;
|
||||
|
||||
_inputManager.Texture = renderTarget;
|
||||
|
||||
EventEmitter.RaiseScreenSizeChange();
|
||||
}
|
||||
|
||||
private void OnWindowSizeChange(object sender, EventArgs e)
|
||||
{
|
||||
if (EngineMode == EngineMode.Classic)
|
||||
{
|
||||
UpdateSize(true);
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = Window.ClientBounds;
|
||||
|
||||
Width = (int)(bounds.Width / Scale);
|
||||
Height = (int)(bounds.Height / Scale);
|
||||
|
||||
if (Window.IsMaximized())
|
||||
{
|
||||
var vertical = bounds.Height - (Height * Scale);
|
||||
var horizontal = bounds.Width - (Width * Scale);
|
||||
|
||||
Borders.Top = (int)Math.Floor(vertical / 2d);
|
||||
Borders.Bottom = (int)Math.Ceiling(vertical / 2d);
|
||||
|
||||
Borders.Left = (int)Math.Floor(horizontal / 2d);
|
||||
Borders.Right = (int)Math.Ceiling(horizontal / 2d);
|
||||
|
||||
UpdateSize(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetBorder();
|
||||
UpdateSize();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetBorder()
|
||||
{
|
||||
var size = (int)(Scale * DefaultParameters.BorderMultiplier);
|
||||
Borders = new Borders
|
||||
{
|
||||
Top = size,
|
||||
Bottom = size,
|
||||
Left = size,
|
||||
Right = size
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
var configBuilder = new ConfigurationBuilder();
|
||||
|
||||
var settingsPath = Path.Combine(AppDataPath, "settings.json");
|
||||
if (!Directory.Exists(AppDataPath))
|
||||
{
|
||||
Directory.CreateDirectory(AppDataPath);
|
||||
}
|
||||
if (!File.Exists(settingsPath))
|
||||
{
|
||||
File.Copy(Path.Combine(AssetsPath, "default.json"), settingsPath);
|
||||
}
|
||||
|
||||
configBuilder.AddJsonFile(Path.Combine(AssetsPath, "default.json"), false);
|
||||
configBuilder.AddJsonFile(settingsPath, false);
|
||||
|
||||
Configuration = configBuilder.Build();
|
||||
|
||||
Window.Title = "Capy64 " + Version;
|
||||
|
||||
Scale = Configuration.GetValue("Window:Scale", DefaultParameters.Scale);
|
||||
|
||||
ResetBorder();
|
||||
UpdateSize();
|
||||
|
||||
Window.AllowUserResizing = true;
|
||||
Window.ClientSizeChanged += OnWindowSizeChange;
|
||||
|
||||
InactiveSleepTime = new TimeSpan(0);
|
||||
|
||||
SetEngineMode(Configuration.GetValue<EngineMode>("EngineMode", DefaultParameters.EngineMode));
|
||||
|
||||
Audio = new Audio();
|
||||
|
||||
NativePlugins = GetNativePlugins();
|
||||
var safeMode = Configuration.GetValue("SafeMode", false);
|
||||
if (!safeMode)
|
||||
Plugins = PluginLoader.LoadAllPlugins(Path.Combine(AppDataPath, "plugins"));
|
||||
|
||||
EventEmitter.RaiseInit();
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
private List<IComponent> GetNativePlugins()
|
||||
{
|
||||
var iType = typeof(IComponent);
|
||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(s => s.GetTypes())
|
||||
.Where(p => iType.IsAssignableFrom(p) && !p.IsInterface);
|
||||
|
||||
var plugins = new List<IComponent>();
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var instance = (IComponent)Activator.CreateInstance(type, this);
|
||||
plugins.Add(instance);
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
|
||||
protected override void LoadContent()
|
||||
{
|
||||
SpriteBatch = new SpriteBatch(GraphicsDevice);
|
||||
}
|
||||
|
||||
protected override void Update(GameTime gameTime)
|
||||
{
|
||||
Drawing.Begin();
|
||||
|
||||
// Register user input
|
||||
_inputManager.Update(IsActive);
|
||||
|
||||
EventEmitter.RaiseTick(new()
|
||||
{
|
||||
GameTime = gameTime,
|
||||
TotalTicks = _totalTicks,
|
||||
IsActiveTick = (int)_totalTicks % everyTick == 0,
|
||||
});
|
||||
|
||||
Drawing.End();
|
||||
|
||||
_totalTicks++;
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
protected override void Draw(GameTime gameTime)
|
||||
{
|
||||
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp);
|
||||
GraphicsDevice.Clear(BorderColor);
|
||||
|
||||
SpriteBatch.DrawRectangle(renderTarget.Bounds.Location.ToVector2() + new Vector2(Borders.Left, Borders.Top),
|
||||
new Size2(renderTarget.Bounds.Width * Scale, renderTarget.Bounds.Height * Scale), Color.Black,
|
||||
Math.Min(renderTarget.Bounds.Width, renderTarget.Bounds.Height), 0);
|
||||
|
||||
SpriteBatch.Draw(renderTarget, new(Borders.Left, Borders.Top), null, Color.White, 0f, Vector2.Zero, Scale,
|
||||
SpriteEffects.None, 0);
|
||||
|
||||
EventEmitter.RaiseOverlay(new()
|
||||
{
|
||||
GameTime = gameTime,
|
||||
TotalTicks = _totalTicks,
|
||||
});
|
||||
|
||||
SpriteBatch.End();
|
||||
|
||||
base.Draw(gameTime);
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ internal class PluginLoader
|
|||
{
|
||||
if (typeof(IComponent).IsAssignableFrom(type))
|
||||
{
|
||||
IComponent result = Activator.CreateInstance(type, Capy64.Instance) as IComponent;
|
||||
IComponent result = Activator.CreateInstance(type, LegacyEntry.Instance) as IComponent;
|
||||
plugins.Add(result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ using Capy64;
|
|||
|
||||
if (args.Length > 0 && args[0] == "sdl")
|
||||
{
|
||||
using var game = new SDLEntry();
|
||||
using var game = new Capy64.Capy64();
|
||||
|
||||
game.Run();
|
||||
}
|
||||
else
|
||||
{
|
||||
using var game = new Capy64.Capy64();
|
||||
using var game = new Capy64.LegacyEntry();
|
||||
|
||||
game.Run();
|
||||
}
|
|
@ -25,8 +25,8 @@ public class AudioLib : IComponent
|
|||
{
|
||||
private const int queueLimit = 8;
|
||||
|
||||
private static Capy64 _game;
|
||||
public AudioLib(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public AudioLib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
_game.EventEmitter.OnClose += OnClose;
|
||||
|
|
|
@ -29,8 +29,8 @@ public class EventLib : IComponent
|
|||
|
||||
private static bool FrozenTaskAwaiter = false;
|
||||
|
||||
private static Capy64 _game;
|
||||
public EventLib(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public EventLib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Capy64.Runtime.Libraries;
|
|||
|
||||
public class FileSystemLib : IComponent
|
||||
{
|
||||
public static string DataPath = Path.Combine(Capy64.AppDataPath, "data");
|
||||
public static string DataPath = Path.Combine(LegacyEntry.AppDataPath, "data");
|
||||
|
||||
public FileSystemLib()
|
||||
{
|
||||
|
@ -111,7 +111,7 @@ public class FileSystemLib : IComponent
|
|||
new(), // NULL
|
||||
};
|
||||
|
||||
public FileSystemLib(Capy64 _) { }
|
||||
public FileSystemLib(LegacyEntry _) { }
|
||||
|
||||
public void LuaInit(Lua state)
|
||||
{
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace Capy64.Runtime.Libraries;
|
|||
public class GPULib : IComponent
|
||||
{
|
||||
|
||||
private static Capy64 _game;
|
||||
public GPULib(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public GPULib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
}
|
||||
|
@ -657,7 +657,7 @@ public class GPULib : IComponent
|
|||
Texture2D texture;
|
||||
try
|
||||
{
|
||||
texture = Texture2D.FromFile(Capy64.Instance.Drawing.Canvas.GraphicsDevice, path);
|
||||
texture = Texture2D.FromFile(LegacyEntry.Instance.Drawing.Canvas.GraphicsDevice, path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -30,12 +30,12 @@ namespace Capy64.Runtime.Libraries;
|
|||
#nullable enable
|
||||
public class HTTPLib : IComponent
|
||||
{
|
||||
private static Capy64 _game = null!;
|
||||
private static LegacyEntry _game = null!;
|
||||
private static HttpClient _httpClient = null!;
|
||||
private static long _requestId;
|
||||
public static readonly HashSet<WebSocketClient.Client> WebSocketConnections = new();
|
||||
|
||||
public static readonly string UserAgent = $"Capy64/{Capy64.Version}";
|
||||
public static readonly string UserAgent = $"Capy64/{LegacyEntry.Version}";
|
||||
|
||||
private static IConfiguration _configuration = null!;
|
||||
private readonly LuaRegister[] Library = new LuaRegister[]
|
||||
|
@ -57,7 +57,7 @@ public class HTTPLib : IComponent
|
|||
},
|
||||
new(),
|
||||
};
|
||||
public HTTPLib(Capy64 game)
|
||||
public HTTPLib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
_requestId = 0;
|
||||
|
|
|
@ -24,8 +24,8 @@ namespace Capy64.Runtime.Libraries;
|
|||
|
||||
public class MachineLib : IComponent
|
||||
{
|
||||
private static Capy64 _game;
|
||||
public MachineLib(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public MachineLib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ public class MachineLib : IComponent
|
|||
{
|
||||
var L = Lua.FromIntPtr(state);
|
||||
|
||||
var currentTitle = Capy64.Instance.Window.Title;
|
||||
var currentTitle = LegacyEntry.Instance.Window.Title;
|
||||
|
||||
if (!L.IsNoneOrNil(1))
|
||||
{
|
||||
|
@ -117,12 +117,12 @@ public class MachineLib : IComponent
|
|||
|
||||
if (string.IsNullOrEmpty(newTitle))
|
||||
{
|
||||
newTitle = "Capy64 " + Capy64.Version;
|
||||
newTitle = "Capy64 " + LegacyEntry.Version;
|
||||
}
|
||||
|
||||
newTitle = newTitle[..Math.Min(newTitle.Length, 256)];
|
||||
|
||||
Capy64.Instance.Window.Title = newTitle;
|
||||
LegacyEntry.Instance.Window.Title = newTitle;
|
||||
}
|
||||
|
||||
L.PushString(currentTitle);
|
||||
|
@ -157,7 +157,7 @@ public class MachineLib : IComponent
|
|||
{
|
||||
var L = Lua.FromIntPtr(state);
|
||||
|
||||
L.PushString("Capy64 " + Capy64.Version);
|
||||
L.PushString("Capy64 " + LegacyEntry.Version);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ public class MachineLib : IComponent
|
|||
|
||||
try
|
||||
{
|
||||
Capy64.Instance.Discord.SetPresence(details, dstate);
|
||||
LegacyEntry.Instance.Discord.SetPresence(details, dstate);
|
||||
L.PushBoolean(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
|
@ -49,11 +49,11 @@ internal class TermLib : IComponent
|
|||
public static Color BackgroundColor { get; set; }
|
||||
private static Char?[] CharGrid;
|
||||
|
||||
private static Capy64 _game;
|
||||
private static LegacyEntry _game;
|
||||
private static bool cursorState = false;
|
||||
private static bool enableCursor = true;
|
||||
private static Texture2D cursorTexture;
|
||||
public TermLib(Capy64 game)
|
||||
public TermLib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
|
||||
|
@ -317,7 +317,7 @@ internal class TermLib : IComponent
|
|||
{
|
||||
var realpos = ToRealPos(CursorPosition - Vector2.One);
|
||||
var charpos = (realpos * _game.Scale) + ((CharOffset + new Vector2(0, 2)) * _game.Scale);
|
||||
charpos += new Vector2(Capy64.Instance.Borders.Left, Capy64.Instance.Borders.Top);
|
||||
charpos += new Vector2(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top);
|
||||
_game.Game.SpriteBatch.Draw(cursorTexture, charpos, null, ForegroundColor, 0f, Vector2.Zero, _game.Scale, SpriteEffects.None, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,11 @@ class TimerLib : IComponent
|
|||
new(),
|
||||
};
|
||||
|
||||
private static Capy64 _game;
|
||||
private static LegacyEntry _game;
|
||||
private static uint _timerId = 0;
|
||||
|
||||
private static readonly ConcurrentDictionary<uint, Timer> timers = new();
|
||||
public TimerLib(Capy64 game)
|
||||
public TimerLib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
|
||||
|
@ -122,7 +122,7 @@ class TimerLib : IComponent
|
|||
|
||||
timers[timerId] = new Timer
|
||||
{
|
||||
RemainingTicks = (int)(delay * Capy64.Instance.TickRate)
|
||||
RemainingTicks = (int)(delay * LegacyEntry.Instance.TickRate)
|
||||
};
|
||||
|
||||
L.PushInteger(timerId);
|
||||
|
@ -141,7 +141,7 @@ class TimerLib : IComponent
|
|||
|
||||
timers[timerId] = new Timer
|
||||
{
|
||||
RemainingTicks = (int)(delay * Capy64.Instance.TickRate),
|
||||
RemainingTicks = (int)(delay * LegacyEntry.Instance.TickRate),
|
||||
Task = task,
|
||||
};
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ public class LuaState : IDisposable
|
|||
|
||||
private void InitPlugins()
|
||||
{
|
||||
var allPlugins = new List<IComponent>(Capy64.Instance.NativePlugins);
|
||||
allPlugins.AddRange(Capy64.Instance.Plugins);
|
||||
var allPlugins = new List<IComponent>(LegacyEntry.Instance.NativePlugins);
|
||||
allPlugins.AddRange(LegacyEntry.Instance.Plugins);
|
||||
foreach (var plugin in allPlugins)
|
||||
{
|
||||
plugin.LuaInit(Thread);
|
||||
|
|
|
@ -25,8 +25,8 @@ public class ObjectManager : IComponent
|
|||
{
|
||||
private static readonly ConcurrentDictionary<nint, object> _objects = new();
|
||||
|
||||
private static Capy64 _game;
|
||||
public ObjectManager(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public ObjectManager(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
_game.EventEmitter.OnClose += OnClose;
|
||||
|
|
|
@ -88,7 +88,7 @@ public class FileHandle : IComponent
|
|||
new(),
|
||||
};
|
||||
|
||||
public FileHandle(Capy64 _) { }
|
||||
public FileHandle(LegacyEntry _) { }
|
||||
|
||||
public void LuaInit(Lua L)
|
||||
{
|
||||
|
|
|
@ -66,8 +66,8 @@ public class GPUBufferMeta : IComponent
|
|||
new(),
|
||||
};
|
||||
|
||||
private static Capy64 _game;
|
||||
public GPUBufferMeta(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public GPUBufferMeta(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ public class Socket : IDisposable
|
|||
|
||||
public class SocketLib : IComponent
|
||||
{
|
||||
private static Capy64 _game = null!;
|
||||
public SocketLib(Capy64 game)
|
||||
private static LegacyEntry _game = null!;
|
||||
public SocketLib(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ namespace Capy64.Runtime.Objects;
|
|||
|
||||
public class TaskMeta : IComponent
|
||||
{
|
||||
private static Capy64 _game;
|
||||
public TaskMeta(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public TaskMeta(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ public class WebSocketClient : IComponent
|
|||
new(),
|
||||
};
|
||||
|
||||
public WebSocketClient(Capy64 _) { }
|
||||
public WebSocketClient(LegacyEntry _) { }
|
||||
|
||||
public void LuaInit(Lua L)
|
||||
{
|
||||
|
@ -146,7 +146,7 @@ public class WebSocketClient : IComponent
|
|||
.ContinueWith(async task =>
|
||||
{
|
||||
await task;
|
||||
Capy64.Instance.LuaRuntime.QueueEvent("websocket_close", LK =>
|
||||
LegacyEntry.Instance.LuaRuntime.QueueEvent("websocket_close", LK =>
|
||||
{
|
||||
LK.PushInteger(client.RequestId);
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ internal class RuntimeManager : IComponent
|
|||
private static bool close = false;
|
||||
private static bool inPanic = false;
|
||||
|
||||
private static Capy64 _game;
|
||||
public RuntimeManager(Capy64 game)
|
||||
private static LegacyEntry _game;
|
||||
public RuntimeManager(LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
|
||||
|
@ -124,7 +124,7 @@ internal class RuntimeManager : IComponent
|
|||
luaState.Thread.PushCFunction(L_Exit);
|
||||
luaState.Thread.SetGlobal("exit");
|
||||
|
||||
var status = luaState.Thread.LoadFile(Path.Combine(Capy64.AssetsPath, "Lua/bios.lua"));
|
||||
var status = luaState.Thread.LoadFile(Path.Combine(LegacyEntry.AssetsPath, "Lua/bios.lua"));
|
||||
if (status != LuaStatus.OK)
|
||||
{
|
||||
throw new LuaException(luaState.Thread.ToString(-1));
|
||||
|
@ -185,7 +185,7 @@ internal class RuntimeManager : IComponent
|
|||
|
||||
private void LoadFirmware()
|
||||
{
|
||||
var firmwareContent = File.ReadAllText(Path.Combine(Capy64.AssetsPath, "Lua/firmware.lua"));
|
||||
var firmwareContent = File.ReadAllText(Path.Combine(LegacyEntry.AssetsPath, "Lua/firmware.lua"));
|
||||
var errored = luaState.Thread.DoString(firmwareContent);
|
||||
if (errored)
|
||||
{
|
||||
|
@ -212,10 +212,10 @@ internal class RuntimeManager : IComponent
|
|||
|
||||
public static void InstallOS(bool force = false)
|
||||
{
|
||||
var installedFilePath = Path.Combine(Capy64.AppDataPath, ".installed");
|
||||
var installedFilePath = Path.Combine(LegacyEntry.AppDataPath, ".installed");
|
||||
if (!File.Exists(installedFilePath) || force)
|
||||
{
|
||||
FileSystemLib.CopyDirectory(Path.Combine(Capy64.AssetsPath, "Lua/CapyOS"), FileSystemLib.DataPath, true, true);
|
||||
FileSystemLib.CopyDirectory(Path.Combine(LegacyEntry.AssetsPath, "Lua/CapyOS"), FileSystemLib.DataPath, true, true);
|
||||
File.Create(installedFilePath).Dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
// 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.
|
||||
|
||||
namespace Capy64;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using static global::Capy64.Utils;
|
||||
using static SDL2.SDL;
|
||||
|
||||
public class SDLEntry : IDisposable
|
||||
{
|
||||
public const string Version = "1.1.0-beta";
|
||||
public nint Window { get; private set; } = 0;
|
||||
public nint Renderer { get; private set; } = 0;
|
||||
public nint VideoSurface { get; private set; } = 0;
|
||||
public int WindowWidth { get; private set; }
|
||||
public int WindowHeight { get; private set; }
|
||||
public int Width { get; set; } = DefaultParameters.Width;
|
||||
public int Height { get; set; } = DefaultParameters.Height;
|
||||
public float Scale { get; set; } = DefaultParameters.Scale;
|
||||
public uint BorderColor { get; set; } = 0x0;
|
||||
|
||||
public Borders Borders
|
||||
{
|
||||
get => _borders;
|
||||
set
|
||||
{
|
||||
_borders = value;
|
||||
|
||||
}
|
||||
}
|
||||
private SDL_Rect _bordersRect;
|
||||
private Borders _borders;
|
||||
|
||||
public static readonly string AssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
public static readonly string AssetsPath = Path.Combine(AssemblyPath, "Assets");
|
||||
|
||||
public static class DefaultParameters
|
||||
{
|
||||
public const int Width = 318;
|
||||
public const int Height = 240;
|
||||
public const float Scale = 2f;
|
||||
public const float BorderMultiplier = 1.5f;
|
||||
public static readonly EngineMode EngineMode = EngineMode.Classic;
|
||||
|
||||
public const int ClassicTickrate = 30;
|
||||
public const int FreeTickrate = 60;
|
||||
}
|
||||
|
||||
public static string AppDataPath
|
||||
{
|
||||
get
|
||||
{
|
||||
string baseDir =
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData,
|
||||
Environment.SpecialFolderOption.Create) :
|
||||
"./";
|
||||
|
||||
return Path.Combine(baseDir, "Capy64");
|
||||
}
|
||||
}
|
||||
|
||||
public SDLEntry()
|
||||
{
|
||||
Borders = new()
|
||||
{
|
||||
Top = 0,
|
||||
Bottom = 0,
|
||||
Left = 0,
|
||||
Right = 0,
|
||||
};
|
||||
WindowWidth = (int)(Width * Scale) + Borders.Left + Borders.Right;
|
||||
WindowHeight = (int)(Height * Scale) + Borders.Top + Borders.Bottom;
|
||||
}
|
||||
public void Run()
|
||||
{
|
||||
#if DEBUG
|
||||
SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
|
||||
#endif
|
||||
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||
{
|
||||
Console.WriteLine(SDL_GetError());
|
||||
return;
|
||||
}
|
||||
Window = SDL_CreateWindow("Capy64 " + Version,
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
WindowWidth, WindowHeight,
|
||||
SDL_WindowFlags.SDL_WINDOW_OPENGL);
|
||||
|
||||
if (Window == nint.Zero)
|
||||
{
|
||||
Console.WriteLine(SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
Renderer = SDL_CreateRenderer(Window,
|
||||
0,
|
||||
SDL_RendererFlags.SDL_RENDERER_ACCELERATED | SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC);
|
||||
|
||||
if (Renderer == nint.Zero)
|
||||
{
|
||||
Console.WriteLine(SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
VideoSurface = SDL_CreateRGBSurfaceWithFormat(0, Width, Height, 32, SDL_PIXELFORMAT_ARGB8888);
|
||||
|
||||
var running = true;
|
||||
while (running)
|
||||
{
|
||||
while (SDL_PollEvent(out var ev) != 0)
|
||||
{
|
||||
switch (ev.type)
|
||||
{
|
||||
case SDL_EventType.SDL_QUIT:
|
||||
running = false;
|
||||
break;
|
||||
case SDL_EventType.SDL_KEYDOWN:
|
||||
if (ev.key.keysym.scancode == SDL_Scancode.SDL_SCANCODE_ESCAPE)
|
||||
running = false;
|
||||
|
||||
unsafe
|
||||
{
|
||||
var pitch = ((SDL_Surface*)VideoSurface)->pitch;
|
||||
((uint*)((SDL_Surface*)VideoSurface)->pixels)[10 + 10 * pitch / 4] = 0xFFFF00FF;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_RenderClear(Renderer);
|
||||
var texture = SDL_CreateTextureFromSurface(Renderer, VideoSurface);
|
||||
SDL_RenderCopy(Renderer, texture, 0, 0);
|
||||
SDL_DestroyTexture(texture);
|
||||
SDL_RenderPresent(Renderer);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SDL_DestroyRenderer(Renderer);
|
||||
SDL_DestroyWindow(Window);
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,8 @@ namespace ExamplePlugin;
|
|||
|
||||
public class MyPlugin : IComponent
|
||||
{
|
||||
private static Capy64.Capy64 _game;
|
||||
public MyPlugin(Capy64.Capy64 game)
|
||||
private static Capy64.LegacyEntry _game;
|
||||
public MyPlugin(Capy64.LegacyEntry game)
|
||||
{
|
||||
_game = game;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue