diff --git a/Capy64/Assets/charset.png b/Capy64/Assets/charset.png
new file mode 100644
index 0000000..f966538
Binary files /dev/null and b/Capy64/Assets/charset.png differ
diff --git a/Capy64/Capy64.csproj b/Capy64/Capy64.csproj
index dd76ecf..8ce4db1 100644
--- a/Capy64/Capy64.csproj
+++ b/Capy64/Capy64.csproj
@@ -13,6 +13,9 @@
LICENSE
+
+ PreserveNewest
+
PreserveNewest
@@ -58,4 +61,7 @@
+
+
+
\ No newline at end of file
diff --git a/Capy64/Core/Charset.cs b/Capy64/Core/Charset.cs
new file mode 100644
index 0000000..f86ab96
--- /dev/null
+++ b/Capy64/Core/Charset.cs
@@ -0,0 +1,79 @@
+// This file is part of Capy64 - https://github.com/Ale32bit/Capy64
+// Copyright 2023 Alessandro "AlexDevs" Proto
+//
+// Licensed under the Apache License', Version 2.0 (the "License").
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing', software
+// distributed under the License is distributed on an "AS IS" BASIS',
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND', either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using Capy64.API;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using System.Collections.Generic;
+
+namespace Capy64.Core;
+
+public class Charset : IComponent
+{
+ public static int CharWidth => 6;
+ public static int CharHeight => 12;
+
+ public static readonly char[] Codepoints = new char[]
+ {
+ '\u0000', '\u263A', '\u263B', '\u2665', '\u2666', '\u2663', '\u2660', '\u2022', '\u25D8', '\u25CB', '\u25D9', '\u2642', '\u2640', '\u266A', '\u266B', '\u263C',
+ '\u25BA', '\u25C4', '\u2195', '\u203C', '\u00B6', '\u00A7', '\u25AC', '\u21A8', '\u2191', '\u2193', '\u2192', '\u2190', '\u221F', '\u2194', '\u25B2', '\u25BC',
+ '\u0020', '\u0021', '\u0022', '\u0023', '\u0024', '\u0025', '\u0026', '\u0027', '\u0028', '\u0029', '\u002A', '\u002B', '\u002C', '\u002D', '\u002E', '\u002F',
+ '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039', '\u003A', '\u003B', '\u003C', '\u003D', '\u003E', '\u003F',
+ '\u0040', '\u0041', '\u0042', '\u0043', '\u0044', '\u0045', '\u0046', '\u0047', '\u0048', '\u0049', '\u004A', '\u004B', '\u004C', '\u004D', '\u004E', '\u004F',
+ '\u0050', '\u0051', '\u0052', '\u0053', '\u0054', '\u0055', '\u0056', '\u0057', '\u0058', '\u0059', '\u005A', '\u005B', '\u005C', '\u005D', '\u005E', '\u005F',
+ '\u0060', '\u0061', '\u0062', '\u0063', '\u0064', '\u0065', '\u0066', '\u0067', '\u0068', '\u0069', '\u006A', '\u006B', '\u006C', '\u006D', '\u006E', '\u006F',
+ '\u0070', '\u0071', '\u0072', '\u0073', '\u0074', '\u0075', '\u0076', '\u0077', '\u0078', '\u0079', '\u007A', '\u007B', '\u007C', '\u007D', '\u007E', '\u2302',
+ '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5',
+ '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', '\u00DC', '\u00A2', '\u00A3', '\u00A5', '\u20A7', '\u0192',
+ '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', '\u00BF', '\u2310', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB',
+ '\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', '\u2555', '\u2563', '\u2551', '\u2557', '\u255D', '\u255C', '\u255B', '\u2510',
+ '\u2514', '\u2534', '\u252C', '\u251C', '\u2500', '\u253C', '\u255E', '\u255F', '\u255A', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256C', '\u2567',
+ '\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256B', '\u256A', '\u2518', '\u250C', '\u2588', '\u2584', '\u258C', '\u2590', '\u2580',
+ '\u03B1', '\u00DF', '\u0393', '\u03C0', '\u03A3', '\u03C3', '\u00B5', '\u03C4', '\u03A6', '\u0398', '\u03A9', '\u03B4', '\u221E', '\u03C6', '\u03B5', '\u2229',
+ '\u2261', '\u00B1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00F7', '\u2248', '\u00B0', '\u2219', '\u00B7', '\u221A', '\u207F', '\u00B2', '\u25A0', '\u00A0',
+ };
+ public static Dictionary CharDict => _charMap;
+ public static Texture2D Source => _source;
+ public static Rectangle[] Coords => _coords;
+
+ private static Dictionary _charMap = new();
+ private static Texture2D _source;
+ private static Rectangle[] _coords = new Rectangle[Codepoints.Length];
+ public Charset()
+ {
+ _source = Texture2D.FromFile(Capy64.Instance.GraphicsDevice, "Assets/charset.png");
+
+ for (int i = 0; i < Codepoints.Length; i++)
+ {
+ _coords[i] = new Rectangle
+ {
+ X = CharWidth * (i % 16),
+ Y = CharHeight * (i / 16),
+ Width = CharWidth,
+ Height = CharHeight,
+ };
+
+ _charMap[Codepoints[i]] = i;
+ }
+ }
+
+ public static int GetIndex(char c)
+ {
+ if (_charMap.TryGetValue(c, out var index))
+ return index;
+
+ return _charMap['?'];
+ }
+}
diff --git a/Capy64/Core/Drawing.cs b/Capy64/Core/Drawing.cs
index ce4e6ec..0367130 100644
--- a/Capy64/Core/Drawing.cs
+++ b/Capy64/Core/Drawing.cs
@@ -25,7 +25,7 @@ namespace Capy64.Core;
public class Drawing : IDisposable
{
- private SpriteBatch _spriteBatch;
+ public SpriteBatch SpriteBatch;
private GraphicsDevice _graphicsDevice;
private readonly FontSystem _fontSystem;
private Texture2D _whitePixel;
@@ -41,10 +41,10 @@ public class Drawing : IDisposable
if (isDrawing)
End();
_canvas = value;
- _spriteBatch = new SpriteBatch(_canvas.GraphicsDevice);
+ SpriteBatch = new SpriteBatch(_canvas.GraphicsDevice);
_graphicsDevice = _canvas.GraphicsDevice;
- _whitePixel = new Texture2D(_spriteBatch.GraphicsDevice, 1, 1, mipmap: false, SurfaceFormat.Color);
+ _whitePixel = new Texture2D(SpriteBatch.GraphicsDevice, 1, 1, mipmap: false, SurfaceFormat.Color);
_whitePixel.SetData(new Color[1] { Color.White });
if (isDrawing)
Begin();
@@ -65,7 +65,7 @@ public class Drawing : IDisposable
_isDrawing = true;
_graphicsDevice.SetRenderTarget(_canvas);
_graphicsDevice.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true, };
- _spriteBatch.Begin();
+ SpriteBatch.Begin();
}
public void End()
@@ -73,7 +73,7 @@ public class Drawing : IDisposable
if (!_isDrawing)
return;
- _spriteBatch.End();
+ SpriteBatch.End();
_graphicsDevice.SetRenderTarget(null);
foreach (var t in _disposeTextures)
@@ -86,7 +86,7 @@ public class Drawing : IDisposable
public void DrawString(Vector2 pos, string text, Color color, int size = 13)
{
var font = _fontSystem.GetFont(size);
- _spriteBatch.DrawString(font, text, pos, color, layerDepth: 0);
+ SpriteBatch.DrawString(font, text, pos, color, layerDepth: 0);
}
public Vector2 MeasureString(string text, int size = 13)
@@ -151,18 +151,18 @@ public class Drawing : IDisposable
public void DrawPoint(Vector2 point, Color color, int size = 1)
{
- _spriteBatch.DrawPoint(point, color, size);
+ SpriteBatch.DrawPoint(point, color, size);
}
public void DrawCircle(Vector2 pos, int radius, Color color, int thickness = 1, int sides = -1)
{
sides = sides < 0 ? radius * 4 : sides;
- _spriteBatch.DrawCircle(pos, radius, sides, color, thickness);
+ SpriteBatch.DrawCircle(pos, radius, sides, color, thickness);
}
public void DrawLine(Vector2 start, Vector2 end, Color color, float thickness = 1)
{
- _spriteBatch.DrawLine(start, end, color, thickness);
+ SpriteBatch.DrawLine(start, end, color, thickness);
}
public void DrawRectangle(Vector2 pos, Size2 size, Color color, int thickness = 1, float rotation = 0f)
@@ -172,13 +172,13 @@ public class Drawing : IDisposable
public void DrawPolygon(Vector2 pos, Vector2[] points, Color color, int thickness = 1)
{
- _spriteBatch.DrawPolygon(pos, points, color, thickness);
+ SpriteBatch.DrawPolygon(pos, points, color, thickness);
}
public void DrawEllipse(Vector2 pos, Vector2 radius, Color color, int thickness = 1)
{
var sides = (int)Math.Max(radius.X, radius.Y) * 4;
- _spriteBatch.DrawEllipse(pos, radius, sides, color, thickness);
+ SpriteBatch.DrawEllipse(pos, radius, sides, color, thickness);
}
public void Clear(Color? color = default)
@@ -194,10 +194,10 @@ public class Drawing : IDisposable
Vector2 position3 = new(rectangle.X, rectangle.Bottom - thickness);
Vector2 scale = new(rectangle.Width, thickness);
Vector2 scale2 = new(thickness, rectangle.Height);
- _spriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
- _spriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
- _spriteBatch.Draw(_whitePixel, position2, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
- _spriteBatch.Draw(_whitePixel, position3, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
+ SpriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
+ SpriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
+ SpriteBatch.Draw(_whitePixel, position2, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
+ SpriteBatch.Draw(_whitePixel, position3, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
}
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)
@@ -205,7 +205,7 @@ public class Drawing : IDisposable
var texture = new Texture2D(_graphicsDevice, rect.Width, rect.Height, false, SurfaceFormat.Color);
texture.SetData(buffer);
- _spriteBatch.Draw(
+ SpriteBatch.Draw(
texture, // Texture
rect.Location.ToVector2(), // Position
source, // source
@@ -222,7 +222,7 @@ public class Drawing : IDisposable
public void Dispose()
{
GC.SuppressFinalize(this);
- _spriteBatch.Dispose();
+ SpriteBatch.Dispose();
_whitePixel.Dispose();
}
}
diff --git a/Capy64/Runtime/EventEmitter.cs b/Capy64/Runtime/EventEmitter.cs
index 83ca4ca..0ea20a7 100644
--- a/Capy64/Runtime/EventEmitter.cs
+++ b/Capy64/Runtime/EventEmitter.cs
@@ -185,9 +185,10 @@ internal class EventEmitter
private void OnChar(object sender, CharEvent e)
{
+ var i = (byte)Charset.GetIndex(e.Character);
_runtime.QueueEvent("char", LK =>
{
- LK.PushString(e.Character.ToString());
+ LK.PushBuffer(new byte[] { i });
return 1;
});
diff --git a/Capy64/Runtime/Libraries/Term.cs b/Capy64/Runtime/Libraries/Term.cs
index 4ee77f7..1ddcdd5 100644
--- a/Capy64/Runtime/Libraries/Term.cs
+++ b/Capy64/Runtime/Libraries/Term.cs
@@ -14,6 +14,7 @@
// limitations under the License.
using Capy64.API;
+using Capy64.Core;
using Capy64.Eventing.Events;
using KeraLua;
using Microsoft.Xna.Framework;
@@ -25,7 +26,7 @@ namespace Capy64.Runtime.Libraries;
internal class Term : IComponent
{
- private struct Char
+ private struct TermChar
{
public char Character;
public Color Foreground;
@@ -47,7 +48,7 @@ internal class Term : IComponent
private static Vector2 _cursorPosition { get; set; }
public static Color ForegroundColor { get; set; }
public static Color BackgroundColor { get; set; }
- private static Char?[] CharGrid;
+ private static TermChar?[] CharGrid;
private static IGame _game;
private static bool cursorState = false;
@@ -204,7 +205,7 @@ internal class Term : IComponent
_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), bg, Math.Min(CharWidth, CharHeight));
//_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), Color.Red, 1);
- try
+ /*try
{
_game.Drawing.DrawString(charpos, ch.ToString(), fg);
@@ -212,7 +213,10 @@ internal class Term : IComponent
catch (ArgumentException ex) // UTF-16 fuckery
{
_game.Drawing.DrawString(charpos, "\xFFFD", fg);
- }
+ }*/
+
+ var rect = Charset.Coords[(int)ch];
+ _game.Drawing.SpriteBatch.Draw(Charset.Source, charpos, rect, fg);
if(underline)
{
@@ -222,7 +226,7 @@ internal class Term : IComponent
if (!save)
return;
- CharGrid[(int)pos.X + ((int)pos.Y * Width)] = new Char
+ CharGrid[(int)pos.X + ((int)pos.Y * Width)] = new TermChar
{
Character = ch,
Foreground = ForegroundColor,
@@ -237,7 +241,7 @@ internal class Term : IComponent
return;
var ch = CharGrid[(int)pos.X + ((int)pos.Y * Width)] ??
- new Char
+ new TermChar
{
Character = ' ',
Foreground = ForegroundColor,
@@ -312,7 +316,7 @@ internal class Term : IComponent
private static void ClearGrid()
{
- CharGrid = new Char?[CharGrid.Length];
+ CharGrid = new TermChar?[CharGrid.Length];
_game.Drawing.Clear(BackgroundColor);
}
@@ -320,7 +324,16 @@ internal class Term : IComponent
{
foreach (var ch in text)
{
- PlotChar(_cursorPosition, ch);
+ PlotChar(_cursorPosition, (char)ch);
+ _cursorPosition = new(_cursorPosition.X + 1, _cursorPosition.Y);
+ }
+ }
+
+ public static void Write(byte[] buffer)
+ {
+ foreach (var b in buffer)
+ {
+ PlotChar(_cursorPosition, (char)b);
_cursorPosition = new(_cursorPosition.X + 1, _cursorPosition.Y);
}
}
@@ -328,9 +341,9 @@ internal class Term : IComponent
private static int L_Write(IntPtr state)
{
var L = Lua.FromIntPtr(state);
- string str = "";
+ byte[] str = new byte[0];
if (!L.IsNone(1))
- str = L.ToString(1);
+ str = L.ToBuffer(1);
Write(str);
@@ -553,7 +566,7 @@ internal class Term : IComponent
}
var lineLength = Math.Abs(lines) * Width;
- var newGrid = new Char?[CharGrid.Length];
+ var newGrid = new TermChar?[CharGrid.Length];
if (lines < 0)
{
Array.Copy(CharGrid, lineLength, newGrid, 0, CharGrid.Length - lineLength);
@@ -614,7 +627,7 @@ internal class Term : IComponent
{
var L = Lua.FromIntPtr(state);
- var text = L.CheckString(1);
+ var text = L.CheckBuffer(1);
L.CheckType(2, LuaType.Table);
L.CheckType(3, LuaType.Table);