Merge branch 'main' into main

This commit is contained in:
Apache 2023-02-18 12:03:54 -06:00 committed by GitHub
commit dcab42e5b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 349 additions and 294 deletions

View file

@ -1,6 +1,6 @@
[*.{cs,vb,lua}] [*.{cs,vb,lua}]
#### Top of file license comment #### Top of file license comment
file_header_template = This file is part of Capy64 - https://github.com/Capy64/Capy64\nCopyright 2023 Alessandro "AlexDevs" Proto\n\nLicensed under the Apache License, Version 2.0 (the "License").\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License. file_header_template = This file is part of Capy64 - https://github.com/Ale32bit/Capy64\nCopyright 2023 Alessandro "AlexDevs" Proto\n\nLicensed under the Apache License, Version 2.0 (the "License").\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.
[*.cs] [*.cs]
#### Stili di denominazione #### #### Stili di denominazione ####

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -18,7 +18,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace Capy64.API; namespace Capy64.API;
public interface IPlugin public interface IComponent
{ {
void ConfigureServices(IServiceCollection services) { } void ConfigureServices(IServiceCollection services) { }
void LuaInit(Lua L) { } void LuaInit(Lua L) { }

View file

@ -23,8 +23,8 @@ local http = require("http")
local event = require("event") local event = require("event")
local INDEX_URL = "https://raw.github.com/Capy64/CapyOS/deploy/index.json" local INDEX_URL = "https://raw.github.com/Ale32bit/CapyOS/deploy/index.json"
local JSON_URL = "https://raw.github.com/Capy64/CapyOS/main/lib/json.lua" local JSON_URL = "https://raw.github.com/Ale32bit/CapyOS/main/lib/json.lua"
local bootSleep = 2000 local bootSleep = 2000
local bg = 0x0 local bg = 0x0
@ -264,4 +264,4 @@ end
bootScreen() bootScreen()
term.clear() term.clear()

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -17,8 +17,9 @@ using Capy64.API;
using Capy64.Core; using Capy64.Core;
using Capy64.Eventing; using Capy64.Eventing;
using Capy64.Extensions; using Capy64.Extensions;
using Capy64.Runtime; using Capy64.Integrations;
using Capy64.PluginManager; using Capy64.PluginManager;
using Capy64.Runtime;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@ -27,7 +28,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using static Capy64.Utils; using static Capy64.Utils;
using Capy64.Integrations;
namespace Capy64; namespace Capy64;
@ -41,8 +41,8 @@ public class Capy64 : Game, IGame
"Capy64"); "Capy64");
public static Capy64 Instance { get; private set; } public static Capy64 Instance { get; private set; }
public Capy64 Game => this; public Capy64 Game => this;
public IList<IPlugin> NativePlugins { get; private set; } public IList<IComponent> NativePlugins { get; private set; }
public IList<IPlugin> Plugins { get; private set; } public IList<IComponent> Plugins { get; private set; }
public int Width { get; set; } = 400; public int Width { get; set; } = 400;
public int Height { get; set; } = 300; public int Height { get; set; } = 300;
public float Scale { get; set; } = 2f; public float Scale { get; set; } = 2f;
@ -121,8 +121,8 @@ public class Capy64 : Game, IGame
if (Window.IsMaximized()) if (Window.IsMaximized())
{ {
var vertical = bounds.Height - Height * Scale; var vertical = bounds.Height - (Height * Scale);
var horizontal = bounds.Width - Width * Scale; var horizontal = bounds.Width - (Width * Scale);
Borders.Top = (int)Math.Floor(vertical / 2d); Borders.Top = (int)Math.Floor(vertical / 2d);
Borders.Bottom = (int)Math.Ceiling(vertical / 2d); Borders.Bottom = (int)Math.Ceiling(vertical / 2d);
@ -159,18 +159,18 @@ public class Capy64 : Game, IGame
base.Initialize(); base.Initialize();
} }
private List<IPlugin> GetNativePlugins() private List<IComponent> GetNativePlugins()
{ {
var iType = typeof(IPlugin); var iType = typeof(IComponent);
var types = AppDomain.CurrentDomain.GetAssemblies() var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes()) .SelectMany(s => s.GetTypes())
.Where(p => iType.IsAssignableFrom(p) && !p.IsInterface); .Where(p => iType.IsAssignableFrom(p) && !p.IsInterface);
var plugins = new List<IPlugin>(); var plugins = new List<IComponent>();
foreach (var type in types) foreach (var type in types)
{ {
var instance = (IPlugin)ActivatorUtilities.CreateInstance(_serviceProvider, type)!; var instance = (IComponent)ActivatorUtilities.CreateInstance(_serviceProvider, type)!;
plugins.Add(instance); plugins.Add(instance);
} }
return plugins; return plugins;

View file

@ -35,7 +35,6 @@
<Pack>True</Pack> <Pack>True</Pack>
<PackagePath>\</PackagePath> <PackagePath>\</PackagePath>
</None> </None>
<None Include="C:\Users\Alex\source\repos\Capy64\Capy64\Capy64\.editorconfig" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DiscordRichPresence" Version="1.1.3.18" /> <PackageReference Include="DiscordRichPresence" Version="1.1.3.18" />

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -14,16 +14,7 @@
// limitations under the License. // limitations under the License.
using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Core; namespace Capy64.Core;
@ -38,25 +29,111 @@ public class Audio : IDisposable
Noise Noise
} }
public const int SampleRate = 48000; public const int SampleRate = 16000;
public const AudioChannels Channels = AudioChannels.Mono; public const int HQSampleRate = 48000;
public readonly DynamicSoundEffectInstance Sound; public const AudioChannels AudioChannel = AudioChannels.Mono;
public const int ChannelsCount = 5;
public readonly DynamicSoundEffectInstance[] Channels = new DynamicSoundEffectInstance[ChannelsCount];
private bool[] freeChannels = new bool[ChannelsCount];
public readonly DynamicSoundEffectInstance HQChannel = new(HQSampleRate, AudioChannel);
private static readonly Random rng = new(); private static readonly Random rng = new();
public Audio() public Audio()
{ {
Sound = new DynamicSoundEffectInstance(SampleRate, Channels); for (int i = 0; i < ChannelsCount; i++)
{
Channels[i] = new DynamicSoundEffectInstance(SampleRate, AudioChannel);
freeChannels[i] = true;
Channels[i].BufferNeeded += Audio_BufferNeeded;
}
HQChannel.BufferNeeded += HQChannel_BufferNeeded;
} }
public TimeSpan Submit(byte[] buffer) private void HQChannel_BufferNeeded(object sender, EventArgs e)
{ {
Sound.SubmitBuffer(buffer); var pending = HQChannel.PendingBufferCount;
return Sound.GetSampleDuration(buffer.Length); Capy64.Instance.LuaRuntime.QueueEvent("audio_need", LK =>
{
LK.PushInteger(-1);
LK.PushInteger(pending);
return 2;
});
} }
public byte[] GenerateWave(Waveform form, double frequency, TimeSpan time) private void Audio_BufferNeeded(object sender, EventArgs e)
{ {
var size = Sound.GetSampleSizeInBytes(time); for (int i = 0; i < ChannelsCount; i++)
{
if (Channels[i] == sender)
{
freeChannels[i] = true;
var pending = Channels[i].PendingBufferCount;
Capy64.Instance.LuaRuntime.QueueEvent("audio_need", LK =>
{
LK.PushInteger(i);
LK.PushInteger(pending);
return 2;
});
}
}
}
public int GetChannelId(int inp)
{
if (inp >= 0)
return inp;
if (inp == -1)
return -1;
if (inp == -2)
{
for (int i = 0; i < ChannelsCount; i++)
{
if (freeChannels[i])
return i;
}
}
return -3;
}
public bool TryGetChannel(int id, out DynamicSoundEffectInstance channel, out int resolvedId)
{
resolvedId = GetChannelId(id);
if (resolvedId >= 0)
channel = Channels[resolvedId];
else if (resolvedId == -1)
channel = HQChannel;
else
channel = null;
return channel != null;
}
public TimeSpan Submit(int id, byte[] buffer)
{
if (!TryGetChannel(id, out var channel, out var rId))
return TimeSpan.Zero;
channel.SubmitBuffer(buffer);
freeChannels[rId] = false;
return channel.GetSampleDuration(buffer.Length);
}
public TimeSpan SubmitHQ(byte[] buffer)
{
HQChannel.SubmitBuffer(buffer);
return HQChannel.GetSampleDuration(buffer.Length);
}
public static byte[] GenerateWave(DynamicSoundEffectInstance channel, Waveform form, double frequency, TimeSpan time, float volume = 1f)
{
var size = channel.GetSampleSizeInBytes(time);
var buffer = new byte[size]; var buffer = new byte[size];
var step = 1d / SampleRate; var step = 1d / SampleRate;
@ -69,12 +146,12 @@ public class Audio : IDisposable
Waveform.Square => GetSquarePoint(frequency, x), Waveform.Square => GetSquarePoint(frequency, x),
Waveform.Triangle => GetTrianglePoint(frequency, x), Waveform.Triangle => GetTrianglePoint(frequency, x),
Waveform.Sawtooth => GetSawtoothPoint(frequency, x), Waveform.Sawtooth => GetSawtoothPoint(frequency, x),
Waveform.Noise => rng.NextDouble() * 2 - 1, Waveform.Noise => (rng.NextDouble() * 2) - 1,
_ => throw new NotImplementedException(), _ => throw new NotImplementedException(),
}; };
Console.WriteLine(value);
value = Math.Clamp(value, -1, 1); value = Math.Clamp(value, -1, 1);
var sample = (short)(value >= 0.0f ? value * short.MaxValue : value * short.MinValue * -1); var sample = (short)((value >= 0.0f ? value * short.MaxValue : value * short.MinValue * -1) * volume);
if (!BitConverter.IsLittleEndian) if (!BitConverter.IsLittleEndian)
{ {
buffer[i] = (byte)(sample >> 8); buffer[i] = (byte)(sample >> 8);
@ -107,8 +184,8 @@ public class Audio : IDisposable
double v = 0; double v = 0;
for (int k = 1; k <= 25; k++) for (int k = 1; k <= 25; k++)
{ {
v += (Math.Pow(-1, k) / Math.Pow(2 * k - 1, 2)) v += Math.Pow(-1, k) / Math.Pow((2 * k) - 1, 2)
* Math.Sin(frequency * 2 * Math.PI * (2 * k - 1) * x); * Math.Sin(frequency * 2 * Math.PI * ((2 * k) - 1) * x);
} }
return -(8 / Math.Pow(Math.PI, 2)) * v; return -(8 / Math.Pow(Math.PI, 2)) * v;
} }
@ -118,7 +195,7 @@ public class Audio : IDisposable
double v = 0; double v = 0;
for (int k = 1; k <= 50; k++) for (int k = 1; k <= 50; k++)
{ {
v += (Math.Pow(-1, k) / k) * Math.Sin(frequency * 2 * Math.PI * k * x); v += Math.Pow(-1, k) / k * Math.Sin(frequency * 2 * Math.PI * k * x);
} }
return -(2 / Math.PI) * v; return -(2 / Math.PI) * v;
} }
@ -126,6 +203,9 @@ public class Audio : IDisposable
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
Sound.Dispose(); for (int i = 0; i < ChannelsCount; i++)
{
Channels[i]?.Dispose();
}
} }
} }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -154,9 +154,10 @@ public class Drawing : IDisposable
_spriteBatch.DrawPoint(point, color, size); _spriteBatch.DrawPoint(point, color, size);
} }
public void DrawCircle(Vector2 pos, int radius, Color color, int thickness = 1) public void DrawCircle(Vector2 pos, int radius, Color color, int thickness = 1, int sides = -1)
{ {
_spriteBatch.DrawCircle(pos, radius, radius * 4, color, thickness); sides = sides < 0 ? radius * 4 : sides;
_spriteBatch.DrawCircle(pos, radius, sides, color, thickness);
} }
public void DrawLine(Vector2 start, Vector2 end, Color color, float thickness = 1) public void DrawLine(Vector2 start, Vector2 end, Color color, float thickness = 1)
@ -199,17 +200,22 @@ public class Drawing : IDisposable
_spriteBatch.Draw(_whitePixel, position3, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth); _spriteBatch.Draw(_whitePixel, position3, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
} }
public void DrawTexture(Texture2D texture, Vector2 pos) public void DrawBuffer(uint[] buffer, Rectangle rect, Rectangle? source = null, Color? color = null, float rotation = 0f, Vector2? origin = null, float scale = 1f, SpriteEffects spriteEffects = 0)
{
_spriteBatch.Draw(texture, pos, null, Color.White, 0f, Vector2.Zero, 1, SpriteEffects.None, 0f);
}
public void DrawBuffer(uint[] buffer, Rectangle rect)
{ {
var texture = new Texture2D(_graphicsDevice, rect.Width, rect.Height, false, SurfaceFormat.Color); var texture = new Texture2D(_graphicsDevice, rect.Width, rect.Height, false, SurfaceFormat.Color);
texture.SetData(buffer); texture.SetData(buffer);
DrawTexture(texture, new(rect.X, rect.Y)); _spriteBatch.Draw(
texture, // Texture
rect.Location.ToVector2(), // Position
source, // source
color ?? Color.White, // Color
rotation, // Rotation
origin ?? Vector2.Zero, // Origin
scale, // Scale
spriteEffects, // Flip effects
0f // layer depth
);
_disposeTextures.Add(texture); _disposeTextures.Add(texture);
} }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -14,11 +14,6 @@
// limitations under the License. // limitations under the License.
using Capy64.Extensions.Bindings; using Capy64.Extensions.Bindings;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Core; namespace Capy64.Core;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -163,7 +163,8 @@ public class EventEmitter
public void RaiseOverlay(OverlayEvent ev) public void RaiseOverlay(OverlayEvent ev)
{ {
if(OnOverlay is not null) { if (OnOverlay is not null)
{
OnOverlay(this, ev); OnOverlay(this, ev);
} }
} }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -14,7 +14,6 @@
// limitations under the License. // limitations under the License.
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System; using System;
namespace Capy64.Eventing.Events; namespace Capy64.Eventing.Events;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -13,7 +13,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using Microsoft.Xna.Framework.Input;
using System; using System;
namespace Capy64.Eventing.Events; namespace Capy64.Eventing.Events;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -14,7 +14,6 @@
// limitations under the License. // limitations under the License.
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System; using System;
namespace Capy64.Eventing.Events; namespace Capy64.Eventing.Events;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -423,7 +423,7 @@ public class InputManager
// D-PAD // D-PAD
var od = oldGamePadState.DPad; var od = oldGamePadState.DPad;
var d = state.DPad; var d = state.DPad;
if (od.Left != d.Left) if (od.Left != d.Left)
{ {
_eventEmitter.RaiseGamePadButton(new() _eventEmitter.RaiseGamePadButton(new()
@ -466,7 +466,7 @@ public class InputManager
if (ot.Left != t.Left) if (ot.Left != t.Left)
{ {
_eventEmitter.RaiseGamePadTrigger(new() _eventEmitter.RaiseGamePadTrigger(new()
{ {
Trigger = 1, // left Trigger = 1, // left

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -14,11 +14,7 @@
// limitations under the License. // limitations under the License.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Extensions.Bindings; namespace Capy64.Extensions.Bindings;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -15,7 +15,6 @@
using Capy64.API; using Capy64.API;
using Capy64.Core; using Capy64.Core;
using Capy64.Eventing;
using Capy64.Integrations; using Capy64.Integrations;
using Capy64.Runtime; using Capy64.Runtime;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
@ -27,8 +26,8 @@ namespace Capy64;
public interface IGame public interface IGame
{ {
Capy64 Game { get; } Capy64 Game { get; }
IList<IPlugin> NativePlugins { get; } IList<IComponent> NativePlugins { get; }
IList<IPlugin> Plugins { get; } IList<IComponent> Plugins { get; }
GameWindow Window { get; } GameWindow Window { get; }
Drawing Drawing { get; } Drawing Drawing { get; }
Audio Audio { get; } Audio Audio { get; }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -18,16 +18,11 @@ using DiscordRPC;
using DiscordRPC.Logging; using DiscordRPC.Logging;
using DiscordRPC.Message; using DiscordRPC.Message;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Integrations; namespace Capy64.Integrations;
public class DiscordIntegration : IPlugin public class DiscordIntegration : IComponent
{ {
public DiscordRpcClient Client { get; private set; } public DiscordRpcClient Client { get; private set; }
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -33,21 +33,21 @@ internal class PluginLoader
return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(path))); return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(path)));
} }
public static List<IPlugin> LoadAllPlugins(string pluginsPath, IServiceProvider provider) public static List<IComponent> LoadAllPlugins(string pluginsPath, IServiceProvider provider)
{ {
if (!Directory.Exists(pluginsPath)) if (!Directory.Exists(pluginsPath))
Directory.CreateDirectory(pluginsPath); Directory.CreateDirectory(pluginsPath);
var plugins = new List<IPlugin>(); var plugins = new List<IComponent>();
foreach (var fileName in Directory.GetFiles(pluginsPath).Where(q => q.EndsWith(".dll"))) foreach (var fileName in Directory.GetFiles(pluginsPath).Where(q => q.EndsWith(".dll")))
{ {
var assembly = LoadPlugin(fileName); var assembly = LoadPlugin(fileName);
foreach (Type type in assembly.GetTypes()) foreach (Type type in assembly.GetTypes())
{ {
if (typeof(IPlugin).IsAssignableFrom(type)) if (typeof(IComponent).IsAssignableFrom(type))
{ {
IPlugin result = ActivatorUtilities.CreateInstance(provider, type) as IPlugin; IComponent result = ActivatorUtilities.CreateInstance(provider, type) as IComponent;
plugins.Add(result); plugins.Add(result);
} }
} }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -24,7 +24,7 @@ using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, c) => .ConfigureAppConfiguration((context, c) =>
{ {
var settingsPath = Path.Combine(Capy64.Capy64.AppDataPath, "settings.json"); var settingsPath = Path.Combine(Capy64.Capy64.AppDataPath, "settings.json");
if(!Directory.Exists(Capy64.Capy64.AppDataPath)) if (!Directory.Exists(Capy64.Capy64.AppDataPath))
{ {
Directory.CreateDirectory(Capy64.Capy64.AppDataPath); Directory.CreateDirectory(Capy64.Capy64.AppDataPath);
} }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -15,12 +15,10 @@
using Capy64.Core; using Capy64.Core;
using Capy64.Eventing.Events; using Capy64.Eventing.Events;
using Capy64.Eventing;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using System; using System;
using System.Linq; using System.Linq;
using static Capy64.Eventing.InputManager; using static Capy64.Eventing.InputManager;
using Capy64.Runtime.Extensions;
namespace Capy64.Runtime; namespace Capy64.Runtime;
@ -187,7 +185,8 @@ internal class EventEmitter
if (SDL.HasClipboardText()) if (SDL.HasClipboardText())
{ {
var text = SDL.GetClipboardText(); var text = SDL.GetClipboardText();
_runtime.QueueEvent("paste", LK => { _runtime.QueueEvent("paste", LK =>
{
LK.PushString(text); LK.PushString(text);
return 1; return 1;
@ -199,7 +198,8 @@ internal class EventEmitter
private void OnChar(object sender, CharEvent e) private void OnChar(object sender, CharEvent e)
{ {
_runtime.QueueEvent("char", LK => { _runtime.QueueEvent("char", LK =>
{
LK.PushString(e.Character.ToString()); LK.PushString(e.Character.ToString());
return 1; return 1;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -17,12 +17,11 @@ using Capy64.API;
using KeraLua; using KeraLua;
using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Audio;
using System; using System;
using System.Threading.Tasks;
using static Capy64.Core.Audio; using static Capy64.Core.Audio;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
public class Audio : IPlugin public class Audio : IComponent
{ {
private const int queueLimit = 8; private const int queueLimit = 8;
@ -90,19 +89,6 @@ public class Audio : IPlugin
return 1; return 1;
} }
private static async Task DelayEmit(TimeSpan time)
{
var waitTime = time - TimeSpan.FromMilliseconds(1000 / 60);
if (waitTime.TotalMilliseconds < 0)
waitTime = time;
await Task.Delay(waitTime);
_game.LuaRuntime.QueueEvent("audio_end", LK =>
{
LK.PushInteger(_game.Audio.Sound.PendingBufferCount);
return 1;
});
}
private static int L_Play(IntPtr state) private static int L_Play(IntPtr state)
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
@ -127,7 +113,7 @@ public class Audio : IPlugin
} }
} }
if (_game.Audio.Sound.PendingBufferCount > queueLimit) if (_game.Audio.HQChannel.PendingBufferCount > queueLimit)
{ {
L.PushBoolean(false); L.PushBoolean(false);
L.PushString("queue is full"); L.PushString("queue is full");
@ -137,11 +123,10 @@ public class Audio : IPlugin
try try
{ {
var ts = _game.Audio.Submit(buffer); var ts = _game.Audio.SubmitHQ(buffer);
DelayEmit(ts);
if (_game.Audio.Sound.State != SoundState.Playing) if (_game.Audio.HQChannel.State != SoundState.Playing)
_game.Audio.Sound.Play(); _game.Audio.HQChannel.Play();
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -157,11 +142,11 @@ public class Audio : IPlugin
var freq = L.OptNumber(1, 440); var freq = L.OptNumber(1, 440);
var time = L.OptNumber(2, 1); var time = L.OptNumber(2, 1);
var volume = L.OptNumber(3, 1);
volume = Math.Clamp(volume, 0, 1);
var timespan = TimeSpan.FromSeconds(time); var timespan = TimeSpan.FromSeconds(time);
var volume = (float)L.OptNumber(3, 1);
volume = Math.Clamp(volume, 0, 1);
var form = L.CheckOption(4, "sine", new string[] var form = L.CheckOption(4, "sine", new string[]
{ {
"sine", "sine",
@ -172,37 +157,70 @@ public class Audio : IPlugin
null, null,
}); });
var buffer = _game.Audio.GenerateWave((Waveform)form, freq, timespan); var id = (int)L.OptInteger(5, -2);
if (!_game.Audio.TryGetChannel(id, out var channel, out var rid))
{
L.PushBoolean(false);
return 1;
}
var buffer = GenerateWave(channel, (Waveform)form, freq, timespan, volume);
try try
{ {
var ts = _game.Audio.Submit(buffer); var ts = _game.Audio.Submit(rid, buffer);
DelayEmit(ts);
if (_game.Audio.Sound.State != SoundState.Playing) if (channel.State != SoundState.Playing)
_game.Audio.Sound.Play(); channel.Play();
L.PushBoolean(true);
} }
catch (Exception ex) catch (Exception ex)
{ {
L.Error(ex.Message); L.Error(ex.Message);
} }
return 0; return 1;
} }
private static int L_Resume(IntPtr state) private static int L_Resume(IntPtr state)
{ {
_game.Audio.Sound.Resume(); var L = Lua.FromIntPtr(state);
var id = (int)L.CheckInteger(1);
if (!_game.Audio.TryGetChannel(id, out var channel, out var rid))
{
L.ArgumentError(1, "channel id not found");
return 0;
}
channel.Resume();
return 0; return 0;
} }
private static int L_Pause(IntPtr state) private static int L_Pause(IntPtr state)
{ {
_game.Audio.Sound.Pause(); var L = Lua.FromIntPtr(state);
var id = (int)L.CheckInteger(1);
if (!_game.Audio.TryGetChannel(id, out var channel, out var rid))
{
L.ArgumentError(1, "channel id not found");
return 0;
}
channel.Pause();
return 0; return 0;
} }
private static int L_Stop(IntPtr state) private static int L_Stop(IntPtr state)
{ {
_game.Audio.Sound.Stop(); var L = Lua.FromIntPtr(state);
var id = (int)L.CheckInteger(1);
if (!_game.Audio.TryGetChannel(id, out var channel, out var rid))
{
L.ArgumentError(1, "channel id not found");
return 0;
}
channel.Stop();
return 0; return 0;
} }
@ -211,7 +229,14 @@ public class Audio : IPlugin
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
L.PushNumber(_game.Audio.Sound.Volume); var id = (int)L.CheckInteger(1);
if (!_game.Audio.TryGetChannel(id, out var channel, out var rid))
{
L.ArgumentError(1, "channel id not found");
return 0;
}
L.PushNumber(channel.Volume);
return 1; return 1;
} }
@ -219,10 +244,17 @@ public class Audio : IPlugin
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
var volume = (float)L.CheckNumber(1); var id = (int)L.CheckInteger(1);
if (!_game.Audio.TryGetChannel(id, out var channel, out var rid))
{
L.ArgumentError(1, "channel id not found");
return 0;
}
var volume = (float)L.CheckNumber(2);
volume = Math.Clamp(volume, 0, 1); volume = Math.Clamp(volume, 0, 1);
_game.Audio.Sound.Volume = volume; channel.Volume = volume;
return 0; return 0;
} }
@ -231,7 +263,14 @@ public class Audio : IPlugin
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
var status = _game.Audio.Sound.State switch var id = (int)L.CheckInteger(1);
if (!_game.Audio.TryGetChannel(id, out var channel, out var rid))
{
L.ArgumentError(1, "channel id not found");
return 0;
}
var status = channel.State switch
{ {
SoundState.Playing => "playing", SoundState.Playing => "playing",
SoundState.Paused => "paused", SoundState.Paused => "paused",
@ -246,6 +285,9 @@ public class Audio : IPlugin
private void OnClose(object sender, EventArgs e) private void OnClose(object sender, EventArgs e)
{ {
_game.Audio.Sound.Stop(true); foreach (var channel in _game.Audio.Channels)
{
channel.Stop();
}
} }
} }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -16,14 +16,10 @@
using Capy64.API; using Capy64.API;
using KeraLua; using KeraLua;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
public class Event : IPlugin public class Event : IComponent
{ {
private static IGame _game; private static IGame _game;
public Event(IGame game) public Event(IGame game)

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -15,17 +15,16 @@
using Capy64.API; using Capy64.API;
using Capy64.Runtime.Extensions; using Capy64.Runtime.Extensions;
using Capy64.Runtime.Objects;
using KeraLua; using KeraLua;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using Capy64.Runtime.Objects;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
public class FileSystem : IPlugin public class FileSystem : IComponent
{ {
public static string DataPath = Path.Combine(Capy64.AppDataPath, "data"); public static string DataPath = Path.Combine(Capy64.AppDataPath, "data");
@ -430,7 +429,7 @@ public class FileSystem : IPlugin
var attr = File.GetAttributes(path); var attr = File.GetAttributes(path);
if (attr.HasFlag(FileAttributes.Directory)) if (attr.HasFlag(FileAttributes.Directory))
{ {
if(!recursive && Directory.GetFileSystemEntries(path).Any()) if (!recursive && Directory.GetFileSystemEntries(path).Any())
{ {
L.Error("directory not empty"); L.Error("directory not empty");
return 0; return 0;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -24,7 +24,7 @@ using System.IO;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
public class GPU : IPlugin public class GPU : IComponent
{ {
private static IGame _game; private static IGame _game;
@ -281,10 +281,11 @@ public class GPU : IPlugin
var y = (int)L.CheckNumber(2) - 1; var y = (int)L.CheckNumber(2) - 1;
var rad = (int)L.CheckNumber(3); var rad = (int)L.CheckNumber(3);
var c = L.CheckInteger(4); var c = L.CheckInteger(4);
var s = (int)L.OptNumber(5, 1); var t = (int)L.OptNumber(5, 1);
var s = (int)L.OptInteger(6, -1);
Utils.UnpackRGB((uint)c, out var r, out var g, out var b); Utils.UnpackRGB((uint)c, out var r, out var g, out var b);
_game.Drawing.DrawCircle(new(x, y), rad, new Color(r, g, b), s); _game.Drawing.DrawCircle(new(x, y), rad, new Color(r, g, b), t, s);
return 0; return 0;
} }
@ -386,7 +387,14 @@ public class GPU : IPlugin
var t = L.CheckString(4); var t = L.CheckString(4);
Utils.UnpackRGB((uint)c, out var r, out var g, out var b); Utils.UnpackRGB((uint)c, out var r, out var g, out var b);
_game.Drawing.DrawString(new Vector2(x, y), t, new Color(r, g, b)); try
{
_game.Drawing.DrawString(new Vector2(x, y), t, new Color(r, g, b));
}
catch (ArgumentException ex) // UTF-16 fuckery
{
L.Error(ex.Message);
}
return 0; return 0;
} }
@ -456,7 +464,7 @@ public class GPU : IPlugin
var w = (int)L.CheckInteger(4); var w = (int)L.CheckInteger(4);
var h = (int)L.CheckInteger(5); var h = (int)L.CheckInteger(5);
if(w * h != buffer.Length) if (w * h != buffer.Length)
{ {
L.Error("width and height do not match buffer size"); L.Error("width and height do not match buffer size");
} }

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -28,7 +28,7 @@ using System.Threading;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
#nullable enable #nullable enable
public class HTTP : IPlugin public class HTTP : IComponent
{ {
private static IGame _game; private static IGame _game;
private static HttpClient _httpClient; private static HttpClient _httpClient;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -19,14 +19,10 @@ using KeraLua;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
public class Machine : IPlugin public class Machine : IComponent
{ {
private static IGame _game; private static IGame _game;
public Machine(IGame game) public Machine(IGame game)

View file

@ -1,34 +0,0 @@
// This file is part of Capy64 - https://github.com/Capy64/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 KeraLua;
using System;
namespace Capy64.Runtime.Libraries;
public class OS : IPlugin
{
private static IGame _game;
public OS(IGame game)
{
_game = game;
}
public void LuaInit(Lua state)
{
state.GetGlobal("os");
}
}

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -18,15 +18,12 @@ using Capy64.Eventing.Events;
using KeraLua; using KeraLua;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended;
using Newtonsoft.Json.Linq;
using System; using System;
using static Capy64.Utils; using static Capy64.Utils;
using static System.Formats.Asn1.AsnWriter;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
internal class Term : IPlugin internal class Term : IComponent
{ {
private struct Char private struct Char
{ {
@ -292,7 +289,7 @@ internal class Term : IPlugin
if (cursorState) if (cursorState)
{ {
var realpos = ToRealPos(CursorPosition - Vector2.One); var realpos = ToRealPos(CursorPosition - Vector2.One);
var charpos = realpos * _game.Scale + CharOffset; var charpos = (realpos * _game.Scale) + CharOffset;
_game.Game.SpriteBatch.Draw(cursorTexture, charpos, null, ForegroundColor, 0f, Vector2.Zero, _game.Scale, SpriteEffects.None, 0); _game.Game.SpriteBatch.Draw(cursorTexture, charpos, null, ForegroundColor, 0f, Vector2.Zero, _game.Scale, SpriteEffects.None, 0);
} }
} }
@ -319,7 +316,14 @@ internal class Term : IPlugin
if (!L.IsNone(1)) if (!L.IsNone(1))
str = L.ToString(1); str = L.ToString(1);
Write(str); try
{
Write(str);
}
catch (ArgumentException ex) // UTF-16 fuckery
{
L.Error(ex.Message);
}
return 0; return 0;
} }
@ -623,15 +627,15 @@ internal class Term : IPlugin
// RGB to ABGR // RGB to ABGR
fgv = fgv =
(fgv & 0x00_FF_00_00U) >> 16 | // move R ((fgv & 0x00_FF_00_00U) >> 16) | // move R
(fgv & 0x00_00_FF_00U) | // move G (fgv & 0x00_00_FF_00U) | // move G
(fgv & 0x00_00_00_FFU) << 16 | // move B ((fgv & 0x00_00_00_FFU) << 16) | // move B
0xFF_00_00_00U; 0xFF_00_00_00U;
bgv = bgv =
(bgv & 0x00_FF_00_00U) >> 16 | // move R ((bgv & 0x00_FF_00_00U) >> 16) | // move R
(bgv & 0x00_00_FF_00U) | // move G (bgv & 0x00_00_FF_00U) | // move G
(bgv & 0x00_00_00_FFU) << 16 | // move B ((bgv & 0x00_00_00_FFU) << 16) | // move B
0xFF_00_00_00U; 0xFF_00_00_00U;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -17,11 +17,10 @@ using Capy64.API;
using KeraLua; using KeraLua;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
class Timer : IPlugin class Timer : IComponent
{ {
private LuaRegister[] TimerLib = new LuaRegister[] private LuaRegister[] TimerLib = new LuaRegister[]
{ {

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -15,10 +15,6 @@
using KeraLua; using KeraLua;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime; namespace Capy64.Runtime;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -19,9 +19,7 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime; namespace Capy64.Runtime;
@ -43,9 +41,6 @@ public class LuaState : IDisposable
Encoding = Encoding.UTF8, Encoding = Encoding.UTF8,
}; };
_parent.PushString("Capy64 " + Capy64.Version);
_parent.SetGlobal("_HOST");
Sandbox.OpenLibraries(_parent); Sandbox.OpenLibraries(_parent);
Sandbox.Patch(_parent); Sandbox.Patch(_parent);
@ -75,7 +70,7 @@ public class LuaState : IDisposable
private void InitPlugins() private void InitPlugins()
{ {
var allPlugins = new List<IPlugin>(Capy64.Instance.NativePlugins); var allPlugins = new List<IComponent>(Capy64.Instance.NativePlugins);
allPlugins.AddRange(Capy64.Instance.Plugins); allPlugins.AddRange(Capy64.Instance.Plugins);
foreach (var plugin in allPlugins) foreach (var plugin in allPlugins)
{ {

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -18,15 +18,10 @@ using KeraLua;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime; namespace Capy64.Runtime;
public class ObjectManager : IPlugin public class ObjectManager : IComponent
{ {
private static ConcurrentDictionary<nint, object> _objects = new(); private static ConcurrentDictionary<nint, object> _objects = new();

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -16,15 +16,11 @@
using Capy64.API; using Capy64.API;
using KeraLua; using KeraLua;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime.Objects; namespace Capy64.Runtime.Objects;
public class FileHandle : IPlugin public class FileHandle : IComponent
{ {
public const string ObjectType = "file"; public const string ObjectType = "file";
@ -107,12 +103,13 @@ public class FileHandle : IPlugin
{ {
var modes = "nlLa"; var modes = "nlLa";
mode = mode.TrimStart('*'); mode = mode.TrimStart('*');
if(string.IsNullOrEmpty(mode)) { if (string.IsNullOrEmpty(mode))
{
return '\0'; return '\0';
} }
var i = modes.IndexOf(mode[0]); var i = modes.IndexOf(mode[0]);
if(i == -1) if (i == -1)
return '\0'; return '\0';
return modes[i]; return modes[i];
@ -274,7 +271,7 @@ public class FileHandle : IPlugin
var n = L.GetTop() - 1; var n = L.GetTop() - 1;
var stream = CheckStream(L, false); var stream = CheckStream(L, false);
L.ArgumentCheck(n <= maxargn, maxargn + 2, "too many arguments"); L.ArgumentCheck(n <= maxargn, maxargn + 2, "too many arguments");
L.PushCopy(1); L.PushCopy(1);
L.PushInteger(n); L.PushInteger(n);
L.PushBoolean(false); L.PushBoolean(false);
L.Rotate(2, 3); L.Rotate(2, 3);

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -16,11 +16,10 @@
using Capy64.API; using Capy64.API;
using KeraLua; using KeraLua;
using System; using System;
using System.IO;
namespace Capy64.Runtime.Objects; namespace Capy64.Runtime.Objects;
public class GPUBuffer : IPlugin public class GPUBuffer : IComponent
{ {
public const string ObjectType = "GPUBuffer"; public const string ObjectType = "GPUBuffer";
@ -111,9 +110,9 @@ public class GPUBuffer : IPlugin
// ABGR to RGB // ABGR to RGB
value = value =
(value & 0x00_00_00_FFU) << 16 | // move R ((value & 0x00_00_00_FFU) << 16) | // move R
(value & 0x00_00_FF_00U) | // move G (value & 0x00_00_FF_00U) | // move G
(value & 0x00_FF_00_00U) >> 16; // move B ((value & 0x00_FF_00_00U) >> 16); // move B
L.PushInteger(value); L.PushInteger(value);
@ -146,11 +145,11 @@ public class GPUBuffer : IPlugin
// RGB to ABGR // RGB to ABGR
value = value =
(value & 0x00_FF_00_00U) >> 16 | // move R ((value & 0x00_FF_00_00U) >> 16) | // move R
(value & 0x00_00_FF_00U) | // move G (value & 0x00_00_FF_00U) | // move G
(value & 0x00_00_00_FFU) << 16 | // move B ((value & 0x00_00_00_FFU) << 16) | // move B
0xFF_00_00_00U; 0xFF_00_00_00U;
buffer[key] = value; buffer[key] = value;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -23,7 +23,7 @@ using System.Threading;
namespace Capy64.Runtime.Objects; namespace Capy64.Runtime.Objects;
public class WebSocketClient : IPlugin public class WebSocketClient : IComponent
{ {
public const string ObjectType = "WebSocketClient"; public const string ObjectType = "WebSocketClient";

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -13,14 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using Capy64.Core;
using Capy64.Runtime.Libraries; using Capy64.Runtime.Libraries;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime; namespace Capy64.Runtime;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -19,18 +19,12 @@ using Capy64.Extensions;
using Capy64.Runtime.Libraries; using Capy64.Runtime.Libraries;
using KeraLua; using KeraLua;
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Capy64.Runtime; namespace Capy64.Runtime;
internal class RuntimeManager : IPlugin internal class RuntimeManager : IComponent
{ {
private LuaState luaState; private LuaState luaState;
private EventEmitter emitter; private EventEmitter emitter;

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -37,6 +37,8 @@ internal class Sandbox
L.OpenOS(); L.OpenOS();
L.OpenPackage(); L.OpenPackage();
L.SetTop(0);
} }
internal static void Patch(Lua L) internal static void Patch(Lua L)
{ {
@ -70,10 +72,11 @@ internal class Sandbox
L.PushString("config"); L.PushString("config");
L.PushString(packageConfig); L.PushString(packageConfig);
L.SetTable(-4); L.SetTable(-4);
L.Pop(1);
// delete 3 and 4 searchers // delete 3 and 4 searchers
L.PushString("searchers"); L.PushString("searchers");
L.GetTable(-3); L.GetTable(-2);
L.PushNil(); L.PushNil();
L.SetInteger(-2, 3); L.SetInteger(-2, 3);
@ -84,7 +87,7 @@ internal class Sandbox
L.PushCFunction(L_Searcher); L.PushCFunction(L_Searcher);
L.SetInteger(-2, 2); L.SetInteger(-2, 2);
L.Pop(L.GetTop()); L.Pop(2);
// Replace loadfile with sandboxed one // Replace loadfile with sandboxed one
L.PushCFunction(L_Loadfile); L.PushCFunction(L_Loadfile);
@ -94,8 +97,6 @@ internal class Sandbox
L.PushCFunction(L_Dofile); L.PushCFunction(L_Dofile);
L.SetGlobal("dofile"); L.SetGlobal("dofile");
L.Pop(L.GetTop());
// yeet dangerous os functions // yeet dangerous os functions
L.GetGlobal("os"); L.GetGlobal("os");
@ -118,6 +119,8 @@ internal class Sandbox
L.PushString("getenv"); L.PushString("getenv");
L.PushNil(); L.PushNil();
L.SetTable(-3); L.SetTable(-3);
L.Pop(1);
} }
internal static int L_Searcher(IntPtr state) internal static int L_Searcher(IntPtr state)

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
@ -33,7 +33,7 @@ public static class Utils
return return
(color.R << 16) + (color.R << 16) +
(color.G << 8) + (color.G << 8) +
(color.B); color.B;
} }
public static void UnpackRGB(uint packed, out byte r, out byte g, out byte b) public static void UnpackRGB(uint packed, out byte r, out byte g, out byte b)

View file

@ -1,4 +1,4 @@
// This file is part of Capy64 - https://github.com/Capy64/Capy64 // This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto // Copyright 2023 Alessandro "AlexDevs" Proto
// //
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").

View file

@ -4,7 +4,7 @@ using KeraLua;
namespace ExamplePlugin; namespace ExamplePlugin;
public class MyPlugin : IPlugin public class MyPlugin : IComponent
{ {
private static IGame _game; private static IGame _game;
public MyPlugin(IGame game) public MyPlugin(IGame game)

View file

@ -1,19 +1,23 @@
<a href="https://capy64.github.io"> <a href="https://capy64.alexdevs.me">
<img src="https://raw.githubusercontent.com/Capy64/capy64.github.io/main/docs/assets/logo.png" alt="Capy64 Logo" title="Capy64" align="right" height="60" /> <img src="https://raw.githubusercontent.com/Ale32bit/Capy64-docs/main/docs/assets/logo.png" alt="Capy64 Logo" title="Capy64" align="right" height="60" />
</a> </a>
# Capy64 # Capy64
[![.NET](https://github.com/Capy64/Capy64/actions/workflows/dotnet.yml/badge.svg)](https://github.com/Capy64/Capy64/actions/workflows/dotnet.yml) [![.NET](https://github.com/Ale32bit/Capy64/actions/workflows/dotnet.yml/badge.svg)](https://github.com/Ale32bit/Capy64/actions/workflows/dotnet.yml)
[![License](https://img.shields.io/github/license/Capy64/Capy64)](https://github.com/Capy64/Capy64/blob/main/LICENSE) [![License](https://img.shields.io/github/license/Ale32bit/Capy64)](https://github.com/Ale32bit/Capy64/blob/main/LICENSE)
[![Release](https://img.shields.io/github/v/release/Capy64/Capy64?include_prereleases)](https://github.com/Capy64/Capy64/releases) [![Release](https://img.shields.io/github/v/release/Ale32bit/Capy64?include_prereleases)](https://github.com/Ale32bit/Capy64/releases)
## About Capy64 ## About Capy64
Capy64 is a fantasy console that runs sandbox Lua 5.4. Capy64 is a fantasy console that runs sandbox Lua 5.4.
Create anything, from Hello Worlds to games! Create anything, from Hello Worlds to games!
## Requirements
* [.NET 7 Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)
## Building ## Building
### Requirements ### Requirements
@ -26,6 +30,6 @@ Create anything, from Hello Worlds to games!
### Steps ### Steps
1. Clone the repository with `git clone https://github.com/Capy64/Capy64.git`. 1. Clone the repository with `git clone https://github.com/Ale32bit/Capy64.git`.
2. Open the file Capy64.sln with the .NET IDE. 2. Open the file Capy64.sln with the .NET IDE.
3. Build project 3. Build project