mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-12-14 18:15:44 +00:00
Merge branch 'main' into main
This commit is contained in:
commit
dcab42e5b2
56 changed files with 349 additions and 294 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[*.{cs,vb,lua}]
|
||||
#### 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]
|
||||
#### Stili di denominazione ####
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -18,7 +18,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
|
||||
namespace Capy64.API;
|
||||
|
||||
public interface IPlugin
|
||||
public interface IComponent
|
||||
{
|
||||
void ConfigureServices(IServiceCollection services) { }
|
||||
void LuaInit(Lua L) { }
|
||||
|
|
@ -23,8 +23,8 @@ local http = require("http")
|
|||
local event = require("event")
|
||||
|
||||
|
||||
local INDEX_URL = "https://raw.github.com/Capy64/CapyOS/deploy/index.json"
|
||||
local JSON_URL = "https://raw.github.com/Capy64/CapyOS/main/lib/json.lua"
|
||||
local INDEX_URL = "https://raw.github.com/Ale32bit/CapyOS/deploy/index.json"
|
||||
local JSON_URL = "https://raw.github.com/Ale32bit/CapyOS/main/lib/json.lua"
|
||||
|
||||
local bootSleep = 2000
|
||||
local bg = 0x0
|
||||
|
|
@ -264,4 +264,4 @@ end
|
|||
|
||||
bootScreen()
|
||||
|
||||
term.clear()
|
||||
term.clear()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -17,8 +17,9 @@ using Capy64.API;
|
|||
using Capy64.Core;
|
||||
using Capy64.Eventing;
|
||||
using Capy64.Extensions;
|
||||
using Capy64.Runtime;
|
||||
using Capy64.Integrations;
|
||||
using Capy64.PluginManager;
|
||||
using Capy64.Runtime;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
|
@ -27,7 +28,6 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using static Capy64.Utils;
|
||||
using Capy64.Integrations;
|
||||
|
||||
namespace Capy64;
|
||||
|
||||
|
|
@ -41,8 +41,8 @@ public class Capy64 : Game, IGame
|
|||
"Capy64");
|
||||
public static Capy64 Instance { get; private set; }
|
||||
public Capy64 Game => this;
|
||||
public IList<IPlugin> NativePlugins { get; private set; }
|
||||
public IList<IPlugin> Plugins { get; private set; }
|
||||
public IList<IComponent> NativePlugins { get; private set; }
|
||||
public IList<IComponent> Plugins { get; private set; }
|
||||
public int Width { get; set; } = 400;
|
||||
public int Height { get; set; } = 300;
|
||||
public float Scale { get; set; } = 2f;
|
||||
|
|
@ -121,8 +121,8 @@ public class Capy64 : Game, IGame
|
|||
|
||||
if (Window.IsMaximized())
|
||||
{
|
||||
var vertical = bounds.Height - Height * Scale;
|
||||
var horizontal = bounds.Width - Width * Scale;
|
||||
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);
|
||||
|
|
@ -159,18 +159,18 @@ public class Capy64 : Game, IGame
|
|||
base.Initialize();
|
||||
}
|
||||
|
||||
private List<IPlugin> GetNativePlugins()
|
||||
private List<IComponent> GetNativePlugins()
|
||||
{
|
||||
var iType = typeof(IPlugin);
|
||||
var iType = typeof(IComponent);
|
||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(s => s.GetTypes())
|
||||
.Where(p => iType.IsAssignableFrom(p) && !p.IsInterface);
|
||||
|
||||
var plugins = new List<IPlugin>();
|
||||
var plugins = new List<IComponent>();
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var instance = (IPlugin)ActivatorUtilities.CreateInstance(_serviceProvider, type)!;
|
||||
var instance = (IComponent)ActivatorUtilities.CreateInstance(_serviceProvider, type)!;
|
||||
plugins.Add(instance);
|
||||
}
|
||||
return plugins;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
<None Include="C:\Users\Alex\source\repos\Capy64\Capy64\Capy64\.editorconfig" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DiscordRichPresence" Version="1.1.3.18" />
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -14,16 +14,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
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;
|
||||
|
||||
|
|
@ -38,25 +29,111 @@ public class Audio : IDisposable
|
|||
Noise
|
||||
}
|
||||
|
||||
public const int SampleRate = 48000;
|
||||
public const AudioChannels Channels = AudioChannels.Mono;
|
||||
public readonly DynamicSoundEffectInstance Sound;
|
||||
public const int SampleRate = 16000;
|
||||
public const int HQSampleRate = 48000;
|
||||
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();
|
||||
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);
|
||||
return Sound.GetSampleDuration(buffer.Length);
|
||||
var pending = HQChannel.PendingBufferCount;
|
||||
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 step = 1d / SampleRate;
|
||||
|
|
@ -69,12 +146,12 @@ public class Audio : IDisposable
|
|||
Waveform.Square => GetSquarePoint(frequency, x),
|
||||
Waveform.Triangle => GetTrianglePoint(frequency, x),
|
||||
Waveform.Sawtooth => GetSawtoothPoint(frequency, x),
|
||||
Waveform.Noise => rng.NextDouble() * 2 - 1,
|
||||
Waveform.Noise => (rng.NextDouble() * 2) - 1,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
Console.WriteLine(value);
|
||||
|
||||
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)
|
||||
{
|
||||
buffer[i] = (byte)(sample >> 8);
|
||||
|
|
@ -107,8 +184,8 @@ public class Audio : IDisposable
|
|||
double v = 0;
|
||||
for (int k = 1; k <= 25; k++)
|
||||
{
|
||||
v += (Math.Pow(-1, k) / Math.Pow(2 * k - 1, 2))
|
||||
* Math.Sin(frequency * 2 * Math.PI * (2 * k - 1) * x);
|
||||
v += Math.Pow(-1, k) / Math.Pow((2 * k) - 1, 2)
|
||||
* Math.Sin(frequency * 2 * Math.PI * ((2 * k) - 1) * x);
|
||||
}
|
||||
return -(8 / Math.Pow(Math.PI, 2)) * v;
|
||||
}
|
||||
|
|
@ -118,7 +195,7 @@ public class Audio : IDisposable
|
|||
double v = 0;
|
||||
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;
|
||||
}
|
||||
|
|
@ -126,6 +203,9 @@ public class Audio : IDisposable
|
|||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
Sound.Dispose();
|
||||
for (int i = 0; i < ChannelsCount; i++)
|
||||
{
|
||||
Channels[i]?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -154,9 +154,10 @@ public class Drawing : IDisposable
|
|||
_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)
|
||||
|
|
@ -199,17 +200,22 @@ public class Drawing : IDisposable
|
|||
_spriteBatch.Draw(_whitePixel, position3, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
|
||||
}
|
||||
|
||||
public void DrawTexture(Texture2D texture, Vector2 pos)
|
||||
{
|
||||
_spriteBatch.Draw(texture, pos, null, Color.White, 0f, Vector2.Zero, 1, SpriteEffects.None, 0f);
|
||||
}
|
||||
|
||||
public void DrawBuffer(uint[] buffer, Rectangle rect)
|
||||
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)
|
||||
{
|
||||
var texture = new Texture2D(_graphicsDevice, rect.Width, rect.Height, false, SurfaceFormat.Color);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -14,11 +14,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
using Capy64.Extensions.Bindings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Core;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -163,7 +163,8 @@ public class EventEmitter
|
|||
|
||||
public void RaiseOverlay(OverlayEvent ev)
|
||||
{
|
||||
if(OnOverlay is not null) {
|
||||
if (OnOverlay is not null)
|
||||
{
|
||||
OnOverlay(this, ev);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -14,7 +14,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
|
||||
namespace Capy64.Eventing.Events;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -13,7 +13,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
|
||||
namespace Capy64.Eventing.Events;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -14,7 +14,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
|
||||
namespace Capy64.Eventing.Events;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -423,7 +423,7 @@ public class InputManager
|
|||
// D-PAD
|
||||
var od = oldGamePadState.DPad;
|
||||
var d = state.DPad;
|
||||
|
||||
|
||||
if (od.Left != d.Left)
|
||||
{
|
||||
_eventEmitter.RaiseGamePadButton(new()
|
||||
|
|
@ -466,7 +466,7 @@ public class InputManager
|
|||
|
||||
if (ot.Left != t.Left)
|
||||
{
|
||||
|
||||
|
||||
_eventEmitter.RaiseGamePadTrigger(new()
|
||||
{
|
||||
Trigger = 1, // left
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -14,11 +14,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Extensions.Bindings;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
using Capy64.API;
|
||||
using Capy64.Core;
|
||||
using Capy64.Eventing;
|
||||
using Capy64.Integrations;
|
||||
using Capy64.Runtime;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
|
@ -27,8 +26,8 @@ namespace Capy64;
|
|||
public interface IGame
|
||||
{
|
||||
Capy64 Game { get; }
|
||||
IList<IPlugin> NativePlugins { get; }
|
||||
IList<IPlugin> Plugins { get; }
|
||||
IList<IComponent> NativePlugins { get; }
|
||||
IList<IComponent> Plugins { get; }
|
||||
GameWindow Window { get; }
|
||||
Drawing Drawing { get; }
|
||||
Audio Audio { get; }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -18,16 +18,11 @@ using DiscordRPC;
|
|||
using DiscordRPC.Logging;
|
||||
using DiscordRPC.Message;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Integrations;
|
||||
|
||||
public class DiscordIntegration : IPlugin
|
||||
public class DiscordIntegration : IComponent
|
||||
{
|
||||
public DiscordRpcClient Client { get; private set; }
|
||||
private readonly IConfiguration _configuration;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// 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)));
|
||||
}
|
||||
|
||||
public static List<IPlugin> LoadAllPlugins(string pluginsPath, IServiceProvider provider)
|
||||
public static List<IComponent> LoadAllPlugins(string pluginsPath, IServiceProvider provider)
|
||||
{
|
||||
if (!Directory.Exists(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")))
|
||||
{
|
||||
var assembly = LoadPlugin(fileName);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -24,7 +24,7 @@ using IHost host = Host.CreateDefaultBuilder(args)
|
|||
.ConfigureAppConfiguration((context, c) =>
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -15,12 +15,10 @@
|
|||
|
||||
using Capy64.Core;
|
||||
using Capy64.Eventing.Events;
|
||||
using Capy64.Eventing;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using static Capy64.Eventing.InputManager;
|
||||
using Capy64.Runtime.Extensions;
|
||||
|
||||
namespace Capy64.Runtime;
|
||||
|
||||
|
|
@ -187,7 +185,8 @@ internal class EventEmitter
|
|||
if (SDL.HasClipboardText())
|
||||
{
|
||||
var text = SDL.GetClipboardText();
|
||||
_runtime.QueueEvent("paste", LK => {
|
||||
_runtime.QueueEvent("paste", LK =>
|
||||
{
|
||||
LK.PushString(text);
|
||||
|
||||
return 1;
|
||||
|
|
@ -199,7 +198,8 @@ internal class EventEmitter
|
|||
|
||||
private void OnChar(object sender, CharEvent e)
|
||||
{
|
||||
_runtime.QueueEvent("char", LK => {
|
||||
_runtime.QueueEvent("char", LK =>
|
||||
{
|
||||
LK.PushString(e.Character.ToString());
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -17,12 +17,11 @@ using Capy64.API;
|
|||
using KeraLua;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using static Capy64.Core.Audio;
|
||||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
|
||||
public class Audio : IPlugin
|
||||
public class Audio : IComponent
|
||||
{
|
||||
private const int queueLimit = 8;
|
||||
|
||||
|
|
@ -90,19 +89,6 @@ public class Audio : IPlugin
|
|||
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)
|
||||
{
|
||||
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.PushString("queue is full");
|
||||
|
|
@ -137,11 +123,10 @@ public class Audio : IPlugin
|
|||
|
||||
try
|
||||
{
|
||||
var ts = _game.Audio.Submit(buffer);
|
||||
DelayEmit(ts);
|
||||
var ts = _game.Audio.SubmitHQ(buffer);
|
||||
|
||||
if (_game.Audio.Sound.State != SoundState.Playing)
|
||||
_game.Audio.Sound.Play();
|
||||
if (_game.Audio.HQChannel.State != SoundState.Playing)
|
||||
_game.Audio.HQChannel.Play();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -157,11 +142,11 @@ public class Audio : IPlugin
|
|||
|
||||
var freq = L.OptNumber(1, 440);
|
||||
var time = L.OptNumber(2, 1);
|
||||
var volume = L.OptNumber(3, 1);
|
||||
volume = Math.Clamp(volume, 0, 1);
|
||||
|
||||
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[]
|
||||
{
|
||||
"sine",
|
||||
|
|
@ -172,37 +157,70 @@ public class Audio : IPlugin
|
|||
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
|
||||
{
|
||||
var ts = _game.Audio.Submit(buffer);
|
||||
DelayEmit(ts);
|
||||
var ts = _game.Audio.Submit(rid, buffer);
|
||||
|
||||
if (_game.Audio.Sound.State != SoundState.Playing)
|
||||
_game.Audio.Sound.Play();
|
||||
if (channel.State != SoundState.Playing)
|
||||
channel.Play();
|
||||
|
||||
L.PushBoolean(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
L.Error(ex.Message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
@ -211,7 +229,14 @@ public class Audio : IPlugin
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -219,10 +244,17 @@ public class Audio : IPlugin
|
|||
{
|
||||
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);
|
||||
|
||||
_game.Audio.Sound.Volume = volume;
|
||||
channel.Volume = volume;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -231,7 +263,14 @@ public class Audio : IPlugin
|
|||
{
|
||||
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.Paused => "paused",
|
||||
|
|
@ -246,6 +285,9 @@ public class Audio : IPlugin
|
|||
|
||||
private void OnClose(object sender, EventArgs e)
|
||||
{
|
||||
_game.Audio.Sound.Stop(true);
|
||||
foreach (var channel in _game.Audio.Channels)
|
||||
{
|
||||
channel.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -16,14 +16,10 @@
|
|||
using Capy64.API;
|
||||
using KeraLua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
|
||||
public class Event : IPlugin
|
||||
public class Event : IComponent
|
||||
{
|
||||
private static IGame _game;
|
||||
public Event(IGame game)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -15,17 +15,16 @@
|
|||
|
||||
using Capy64.API;
|
||||
using Capy64.Runtime.Extensions;
|
||||
using Capy64.Runtime.Objects;
|
||||
using KeraLua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Capy64.Runtime.Objects;
|
||||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
|
||||
public class FileSystem : IPlugin
|
||||
public class FileSystem : IComponent
|
||||
{
|
||||
public static string DataPath = Path.Combine(Capy64.AppDataPath, "data");
|
||||
|
||||
|
|
@ -430,7 +429,7 @@ public class FileSystem : IPlugin
|
|||
var attr = File.GetAttributes(path);
|
||||
if (attr.HasFlag(FileAttributes.Directory))
|
||||
{
|
||||
if(!recursive && Directory.GetFileSystemEntries(path).Any())
|
||||
if (!recursive && Directory.GetFileSystemEntries(path).Any())
|
||||
{
|
||||
L.Error("directory not empty");
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -24,7 +24,7 @@ using System.IO;
|
|||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
|
||||
public class GPU : IPlugin
|
||||
public class GPU : IComponent
|
||||
{
|
||||
|
||||
private static IGame _game;
|
||||
|
|
@ -281,10 +281,11 @@ public class GPU : IPlugin
|
|||
var y = (int)L.CheckNumber(2) - 1;
|
||||
var rad = (int)L.CheckNumber(3);
|
||||
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);
|
||||
_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;
|
||||
}
|
||||
|
|
@ -386,7 +387,14 @@ public class GPU : IPlugin
|
|||
var t = L.CheckString(4);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -456,7 +464,7 @@ public class GPU : IPlugin
|
|||
var w = (int)L.CheckInteger(4);
|
||||
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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -28,7 +28,7 @@ using System.Threading;
|
|||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
#nullable enable
|
||||
public class HTTP : IPlugin
|
||||
public class HTTP : IComponent
|
||||
{
|
||||
private static IGame _game;
|
||||
private static HttpClient _httpClient;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -19,14 +19,10 @@ using KeraLua;
|
|||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
|
||||
public class Machine : IPlugin
|
||||
public class Machine : IComponent
|
||||
{
|
||||
private static IGame _game;
|
||||
public Machine(IGame game)
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -18,15 +18,12 @@ using Capy64.Eventing.Events;
|
|||
using KeraLua;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using MonoGame.Extended;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using static Capy64.Utils;
|
||||
using static System.Formats.Asn1.AsnWriter;
|
||||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
|
||||
internal class Term : IPlugin
|
||||
internal class Term : IComponent
|
||||
{
|
||||
private struct Char
|
||||
{
|
||||
|
|
@ -292,7 +289,7 @@ internal class Term : IPlugin
|
|||
if (cursorState)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -319,7 +316,14 @@ internal class Term : IPlugin
|
|||
if (!L.IsNone(1))
|
||||
str = L.ToString(1);
|
||||
|
||||
Write(str);
|
||||
try
|
||||
{
|
||||
Write(str);
|
||||
}
|
||||
catch (ArgumentException ex) // UTF-16 fuckery
|
||||
{
|
||||
L.Error(ex.Message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -623,15 +627,15 @@ internal class Term : IPlugin
|
|||
|
||||
// RGB to ABGR
|
||||
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_00_FFU) << 16 | // move B
|
||||
((fgv & 0x00_00_00_FFU) << 16) | // move B
|
||||
0xFF_00_00_00U;
|
||||
|
||||
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_00_FFU) << 16 | // move B
|
||||
((bgv & 0x00_00_00_FFU) << 16) | // move B
|
||||
0xFF_00_00_00U;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -17,11 +17,10 @@ using Capy64.API;
|
|||
using KeraLua;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Capy64.Runtime.Libraries;
|
||||
|
||||
class Timer : IPlugin
|
||||
class Timer : IComponent
|
||||
{
|
||||
private LuaRegister[] TimerLib = new LuaRegister[]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -15,10 +15,6 @@
|
|||
|
||||
using KeraLua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -19,9 +19,7 @@ using System;
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime;
|
||||
|
||||
|
|
@ -43,9 +41,6 @@ public class LuaState : IDisposable
|
|||
Encoding = Encoding.UTF8,
|
||||
};
|
||||
|
||||
_parent.PushString("Capy64 " + Capy64.Version);
|
||||
_parent.SetGlobal("_HOST");
|
||||
|
||||
Sandbox.OpenLibraries(_parent);
|
||||
Sandbox.Patch(_parent);
|
||||
|
||||
|
|
@ -75,7 +70,7 @@ public class LuaState : IDisposable
|
|||
|
||||
private void InitPlugins()
|
||||
{
|
||||
var allPlugins = new List<IPlugin>(Capy64.Instance.NativePlugins);
|
||||
var allPlugins = new List<IComponent>(Capy64.Instance.NativePlugins);
|
||||
allPlugins.AddRange(Capy64.Instance.Plugins);
|
||||
foreach (var plugin in allPlugins)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -18,15 +18,10 @@ using KeraLua;
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime;
|
||||
|
||||
public class ObjectManager : IPlugin
|
||||
public class ObjectManager : IComponent
|
||||
{
|
||||
private static ConcurrentDictionary<nint, object> _objects = new();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -16,15 +16,11 @@
|
|||
using Capy64.API;
|
||||
using KeraLua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime.Objects;
|
||||
|
||||
public class FileHandle : IPlugin
|
||||
public class FileHandle : IComponent
|
||||
{
|
||||
public const string ObjectType = "file";
|
||||
|
||||
|
|
@ -107,12 +103,13 @@ public class FileHandle : IPlugin
|
|||
{
|
||||
var modes = "nlLa";
|
||||
mode = mode.TrimStart('*');
|
||||
if(string.IsNullOrEmpty(mode)) {
|
||||
if (string.IsNullOrEmpty(mode))
|
||||
{
|
||||
return '\0';
|
||||
}
|
||||
|
||||
var i = modes.IndexOf(mode[0]);
|
||||
if(i == -1)
|
||||
if (i == -1)
|
||||
return '\0';
|
||||
|
||||
return modes[i];
|
||||
|
|
@ -274,7 +271,7 @@ public class FileHandle : IPlugin
|
|||
var n = L.GetTop() - 1;
|
||||
var stream = CheckStream(L, false);
|
||||
L.ArgumentCheck(n <= maxargn, maxargn + 2, "too many arguments");
|
||||
L.PushCopy(1);
|
||||
L.PushCopy(1);
|
||||
L.PushInteger(n);
|
||||
L.PushBoolean(false);
|
||||
L.Rotate(2, 3);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -16,11 +16,10 @@
|
|||
using Capy64.API;
|
||||
using KeraLua;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Capy64.Runtime.Objects;
|
||||
|
||||
public class GPUBuffer : IPlugin
|
||||
public class GPUBuffer : IComponent
|
||||
{
|
||||
public const string ObjectType = "GPUBuffer";
|
||||
|
||||
|
|
@ -111,9 +110,9 @@ public class GPUBuffer : IPlugin
|
|||
|
||||
// ABGR to RGB
|
||||
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_FF_00_00U) >> 16; // move B
|
||||
((value & 0x00_FF_00_00U) >> 16); // move B
|
||||
|
||||
L.PushInteger(value);
|
||||
|
||||
|
|
@ -146,11 +145,11 @@ public class GPUBuffer : IPlugin
|
|||
|
||||
// RGB to ABGR
|
||||
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_00_FFU) << 16 | // move B
|
||||
((value & 0x00_00_00_FFU) << 16) | // move B
|
||||
0xFF_00_00_00U;
|
||||
|
||||
|
||||
|
||||
buffer[key] = value;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -23,7 +23,7 @@ using System.Threading;
|
|||
|
||||
namespace Capy64.Runtime.Objects;
|
||||
|
||||
public class WebSocketClient : IPlugin
|
||||
public class WebSocketClient : IComponent
|
||||
{
|
||||
public const string ObjectType = "WebSocketClient";
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -13,14 +13,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using Capy64.Core;
|
||||
using Capy64.Runtime.Libraries;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -19,18 +19,12 @@ using Capy64.Extensions;
|
|||
using Capy64.Runtime.Libraries;
|
||||
using KeraLua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capy64.Runtime;
|
||||
|
||||
internal class RuntimeManager : IPlugin
|
||||
internal class RuntimeManager : IComponent
|
||||
{
|
||||
private LuaState luaState;
|
||||
private EventEmitter emitter;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -37,6 +37,8 @@ internal class Sandbox
|
|||
L.OpenOS();
|
||||
|
||||
L.OpenPackage();
|
||||
|
||||
L.SetTop(0);
|
||||
}
|
||||
internal static void Patch(Lua L)
|
||||
{
|
||||
|
|
@ -70,10 +72,11 @@ internal class Sandbox
|
|||
L.PushString("config");
|
||||
L.PushString(packageConfig);
|
||||
L.SetTable(-4);
|
||||
L.Pop(1);
|
||||
|
||||
// delete 3 and 4 searchers
|
||||
L.PushString("searchers");
|
||||
L.GetTable(-3);
|
||||
L.GetTable(-2);
|
||||
|
||||
L.PushNil();
|
||||
L.SetInteger(-2, 3);
|
||||
|
|
@ -84,7 +87,7 @@ internal class Sandbox
|
|||
L.PushCFunction(L_Searcher);
|
||||
L.SetInteger(-2, 2);
|
||||
|
||||
L.Pop(L.GetTop());
|
||||
L.Pop(2);
|
||||
|
||||
// Replace loadfile with sandboxed one
|
||||
L.PushCFunction(L_Loadfile);
|
||||
|
|
@ -94,8 +97,6 @@ internal class Sandbox
|
|||
L.PushCFunction(L_Dofile);
|
||||
L.SetGlobal("dofile");
|
||||
|
||||
L.Pop(L.GetTop());
|
||||
|
||||
// yeet dangerous os functions
|
||||
L.GetGlobal("os");
|
||||
|
||||
|
|
@ -118,6 +119,8 @@ internal class Sandbox
|
|||
L.PushString("getenv");
|
||||
L.PushNil();
|
||||
L.SetTable(-3);
|
||||
|
||||
L.Pop(1);
|
||||
}
|
||||
|
||||
internal static int L_Searcher(IntPtr state)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
@ -33,7 +33,7 @@ public static class Utils
|
|||
return
|
||||
(color.R << 16) +
|
||||
(color.G << 8) +
|
||||
(color.B);
|
||||
color.B;
|
||||
}
|
||||
|
||||
public static void UnpackRGB(uint packed, out byte r, out byte g, out byte b)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using KeraLua;
|
|||
|
||||
namespace ExamplePlugin;
|
||||
|
||||
public class MyPlugin : IPlugin
|
||||
public class MyPlugin : IComponent
|
||||
{
|
||||
private static IGame _game;
|
||||
public MyPlugin(IGame game)
|
||||
|
|
|
|||
18
README.md
18
README.md
|
|
@ -1,19 +1,23 @@
|
|||
<a href="https://capy64.github.io">
|
||||
<img src="https://raw.githubusercontent.com/Capy64/capy64.github.io/main/docs/assets/logo.png" alt="Capy64 Logo" title="Capy64" align="right" height="60" />
|
||||
<a href="https://capy64.alexdevs.me">
|
||||
<img src="https://raw.githubusercontent.com/Ale32bit/Capy64-docs/main/docs/assets/logo.png" alt="Capy64 Logo" title="Capy64" align="right" height="60" />
|
||||
</a>
|
||||
|
||||
# Capy64
|
||||
|
||||
[](https://github.com/Capy64/Capy64/actions/workflows/dotnet.yml)
|
||||
[](https://github.com/Capy64/Capy64/blob/main/LICENSE)
|
||||
[](https://github.com/Capy64/Capy64/releases)
|
||||
|
||||
[](https://github.com/Ale32bit/Capy64/actions/workflows/dotnet.yml)
|
||||
[](https://github.com/Ale32bit/Capy64/blob/main/LICENSE)
|
||||
[](https://github.com/Ale32bit/Capy64/releases)
|
||||
|
||||
## About Capy64
|
||||
|
||||
Capy64 is a fantasy console that runs sandbox Lua 5.4.
|
||||
|
||||
Create anything, from Hello Worlds to games!
|
||||
|
||||
## Requirements
|
||||
|
||||
* [.NET 7 Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)
|
||||
|
||||
## Building
|
||||
|
||||
### Requirements
|
||||
|
|
@ -26,6 +30,6 @@ Create anything, from Hello Worlds to games!
|
|||
|
||||
### 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.
|
||||
3. Build project
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue