diff --git a/Capy64/Capy64.cs b/Capy64/Capy64.cs index 0b7e308..d20daf8 100644 --- a/Capy64/Capy64.cs +++ b/Capy64/Capy64.cs @@ -1,49 +1,68 @@ -// 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"). // 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 -} +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 NativePlugins { get; private set; } - public IList 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", 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 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(); - - 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(); } } \ No newline at end of file diff --git a/Capy64/Core/Audio.cs b/Capy64/Core/Audio.cs index 1409a83..01d4969 100644 --- a/Capy64/Core/Audio.cs +++ b/Capy64/Core/Audio.cs @@ -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); diff --git a/Capy64/Core/Drawing.cs b/Capy64/Core/Drawing.cs index 0f16450..a10cc0c 100644 --- a/Capy64/Core/Drawing.cs +++ b/Capy64/Core/Drawing.cs @@ -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); } diff --git a/Capy64/Eventing/InputManager.cs b/Capy64/Eventing/InputManager.cs index 2521b93..db0b832 100644 --- a/Capy64/Eventing/InputManager.cs +++ b/Capy64/Eventing/InputManager.cs @@ -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 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) diff --git a/Capy64/Integrations/DiscordIntegration.cs b/Capy64/Integrations/DiscordIntegration.cs index 0377653..1597cb4 100644 --- a/Capy64/Integrations/DiscordIntegration.cs +++ b/Capy64/Integrations/DiscordIntegration.cs @@ -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" } }); diff --git a/Capy64/LegacyEntry.cs b/Capy64/LegacyEntry.cs new file mode 100644 index 0000000..f67d148 --- /dev/null +++ b/Capy64/LegacyEntry.cs @@ -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 NativePlugins { get; private set; } + public IList 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", 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 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(); + + 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); + } +} \ No newline at end of file diff --git a/Capy64/PluginManager/PluginLoader.cs b/Capy64/PluginManager/PluginLoader.cs index 376c18a..3c9272b 100644 --- a/Capy64/PluginManager/PluginLoader.cs +++ b/Capy64/PluginManager/PluginLoader.cs @@ -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); } } diff --git a/Capy64/Program.cs b/Capy64/Program.cs index a9dae91..053a151 100644 --- a/Capy64/Program.cs +++ b/Capy64/Program.cs @@ -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(); } \ No newline at end of file diff --git a/Capy64/Runtime/Libraries/AudioLib.cs b/Capy64/Runtime/Libraries/AudioLib.cs index f68c2d6..8b25c1b 100644 --- a/Capy64/Runtime/Libraries/AudioLib.cs +++ b/Capy64/Runtime/Libraries/AudioLib.cs @@ -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; diff --git a/Capy64/Runtime/Libraries/EventLib.cs b/Capy64/Runtime/Libraries/EventLib.cs index bec39f4..6cad777 100644 --- a/Capy64/Runtime/Libraries/EventLib.cs +++ b/Capy64/Runtime/Libraries/EventLib.cs @@ -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; } diff --git a/Capy64/Runtime/Libraries/FileSystemLib.cs b/Capy64/Runtime/Libraries/FileSystemLib.cs index 2a98aad..6886a07 100644 --- a/Capy64/Runtime/Libraries/FileSystemLib.cs +++ b/Capy64/Runtime/Libraries/FileSystemLib.cs @@ -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) { diff --git a/Capy64/Runtime/Libraries/GPULib.cs b/Capy64/Runtime/Libraries/GPULib.cs index c2a1297..dabd363 100644 --- a/Capy64/Runtime/Libraries/GPULib.cs +++ b/Capy64/Runtime/Libraries/GPULib.cs @@ -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) { diff --git a/Capy64/Runtime/Libraries/HTTPLib.cs b/Capy64/Runtime/Libraries/HTTPLib.cs index aef6325..d78e8bb 100644 --- a/Capy64/Runtime/Libraries/HTTPLib.cs +++ b/Capy64/Runtime/Libraries/HTTPLib.cs @@ -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 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; diff --git a/Capy64/Runtime/Libraries/MachineLib.cs b/Capy64/Runtime/Libraries/MachineLib.cs index 185e29a..1caf92e 100644 --- a/Capy64/Runtime/Libraries/MachineLib.cs +++ b/Capy64/Runtime/Libraries/MachineLib.cs @@ -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) diff --git a/Capy64/Runtime/Libraries/TermLib.cs b/Capy64/Runtime/Libraries/TermLib.cs index 6336b0e..f4df3de 100644 --- a/Capy64/Runtime/Libraries/TermLib.cs +++ b/Capy64/Runtime/Libraries/TermLib.cs @@ -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); } } diff --git a/Capy64/Runtime/Libraries/TimerLib.cs b/Capy64/Runtime/Libraries/TimerLib.cs index 1b4f989..eedcd91 100644 --- a/Capy64/Runtime/Libraries/TimerLib.cs +++ b/Capy64/Runtime/Libraries/TimerLib.cs @@ -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 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, }; diff --git a/Capy64/Runtime/LuaState.cs b/Capy64/Runtime/LuaState.cs index f2845d0..d221ddb 100644 --- a/Capy64/Runtime/LuaState.cs +++ b/Capy64/Runtime/LuaState.cs @@ -72,8 +72,8 @@ public class LuaState : IDisposable private void InitPlugins() { - var allPlugins = new List(Capy64.Instance.NativePlugins); - allPlugins.AddRange(Capy64.Instance.Plugins); + var allPlugins = new List(LegacyEntry.Instance.NativePlugins); + allPlugins.AddRange(LegacyEntry.Instance.Plugins); foreach (var plugin in allPlugins) { plugin.LuaInit(Thread); diff --git a/Capy64/Runtime/ObjectManager.cs b/Capy64/Runtime/ObjectManager.cs index 5b524d9..e0c5bcf 100644 --- a/Capy64/Runtime/ObjectManager.cs +++ b/Capy64/Runtime/ObjectManager.cs @@ -25,8 +25,8 @@ public class ObjectManager : IComponent { private static readonly ConcurrentDictionary _objects = new(); - private static Capy64 _game; - public ObjectManager(Capy64 game) + private static LegacyEntry _game; + public ObjectManager(LegacyEntry game) { _game = game; _game.EventEmitter.OnClose += OnClose; diff --git a/Capy64/Runtime/Objects/FileHandle.cs b/Capy64/Runtime/Objects/FileHandle.cs index 82b7c50..5a3eddc 100644 --- a/Capy64/Runtime/Objects/FileHandle.cs +++ b/Capy64/Runtime/Objects/FileHandle.cs @@ -88,7 +88,7 @@ public class FileHandle : IComponent new(), }; - public FileHandle(Capy64 _) { } + public FileHandle(LegacyEntry _) { } public void LuaInit(Lua L) { diff --git a/Capy64/Runtime/Objects/GPUBufferMeta.cs b/Capy64/Runtime/Objects/GPUBufferMeta.cs index eb983d9..6d37afb 100644 --- a/Capy64/Runtime/Objects/GPUBufferMeta.cs +++ b/Capy64/Runtime/Objects/GPUBufferMeta.cs @@ -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; } diff --git a/Capy64/Runtime/Objects/Socket.cs b/Capy64/Runtime/Objects/Socket.cs index 0a7eab6..1037ccd 100644 --- a/Capy64/Runtime/Objects/Socket.cs +++ b/Capy64/Runtime/Objects/Socket.cs @@ -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; } diff --git a/Capy64/Runtime/Objects/Task.cs b/Capy64/Runtime/Objects/Task.cs index da7343e..25f1b06 100644 --- a/Capy64/Runtime/Objects/Task.cs +++ b/Capy64/Runtime/Objects/Task.cs @@ -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; } diff --git a/Capy64/Runtime/Objects/WebSocketClient.cs b/Capy64/Runtime/Objects/WebSocketClient.cs index 5152652..74307a4 100644 --- a/Capy64/Runtime/Objects/WebSocketClient.cs +++ b/Capy64/Runtime/Objects/WebSocketClient.cs @@ -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); diff --git a/Capy64/Runtime/RuntimeManager.cs b/Capy64/Runtime/RuntimeManager.cs index e077818..85147ec 100644 --- a/Capy64/Runtime/RuntimeManager.cs +++ b/Capy64/Runtime/RuntimeManager.cs @@ -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(); } } diff --git a/Capy64/SDLEntry.cs b/Capy64/SDLEntry.cs deleted file mode 100644 index c7144e4..0000000 --- a/Capy64/SDLEntry.cs +++ /dev/null @@ -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(); - } -} - diff --git a/ExamplePlugin/MyPlugin.cs b/ExamplePlugin/MyPlugin.cs index 9f43d1e..efed056 100644 --- a/ExamplePlugin/MyPlugin.cs +++ b/ExamplePlugin/MyPlugin.cs @@ -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; }