Skip to content

Commit

Permalink
Feature/skiasharp render v2 (#104)
Browse files Browse the repository at this point in the history
* New alternative C64 SkiaSharp renderers (SkiaSharp2 and SkiaSharp2b) that supports bitmap modes.
* Fixes #102 (C64 38 column mode scroll issue)
  • Loading branch information
highbyte authored Jul 16, 2024
1 parent aca5a98 commit f2e0d39
Show file tree
Hide file tree
Showing 41 changed files with 2,928 additions and 116 deletions.
Binary file added samples/Basic/C64/Text/Build/MultiColorTextMode.prg
Binary file not shown.
7 changes: 7 additions & 0 deletions samples/Basic/C64/Text/MultiColorTextMode.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
10 poke 53281,1
20 poke 53282,2
30 poke 53283,5
40 poke 53284,6

50 poke 53270,peek(53270) or 16
print chr$(149)"this is multicolor mode"
6 changes: 6 additions & 0 deletions samples/Basic/README_BUILD_BASIC_EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ $PETCAT_APP = "C:\Users\highb\Documents\C64\VICE\bin\petcat.exe"
cd C64/Text
& $PETCAT_APP -w2 -o "Build\ExtendedTextMode.prg" -- "ExtendedTextMode.txt"
´´´
´´´ pwsh
$PETCAT_APP = "C:\Users\highb\Documents\C64\VICE\bin\petcat.exe"
cd C64/Text
& $PETCAT_APP -w2 -o "Build\MultiColorTextMode.prg" -- "MultiColorTextMode.txt"
´´´


´´´ pwsh
$PETCAT_APP = "C:\Users\highb\Documents\C64\VICE\bin\petcat.exe"
Expand Down
2 changes: 1 addition & 1 deletion src/apps/Highbyte.DotNet6502.App.SilkNetNative/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

var c64HostConfig = new C64HostConfig
{
Renderer = C64HostRenderer.SilkNetOpenGl,
Renderer = C64HostRenderer.SkiaSharp2b,
SilkNetOpenGlRendererConfig = new C64SilkNetOpenGlRendererConfig()
{
UseFineScrollPerRasterLine = false, // Setting to true may work, depending on how code is written. Full screen scroll may not work (actual screen memory is not rendered in sync with raster line).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,10 @@ public void Reset()
if (EmulatorState == EmulatorState.Uninitialized)
return;

Stop();
if (_statsPanel.Visible)
ToggleStatsPanel();

_systemRunner?.Cleanup();
_systemRunner = default!;
EmulatorState = EmulatorState.Uninitialized;
Start();
Expand All @@ -320,6 +322,7 @@ public void Stop()
if (_statsPanel.Visible)
ToggleStatsPanel();

_systemRunner.Cleanup();
_systemRunner = default!;
SetUninitializedWindow();
InitRendering();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Highbyte.DotNet6502.Impl.SilkNet.Commodore64;
using Highbyte.DotNet6502.Impl.SilkNet.Commodore64.Input;
using Highbyte.DotNet6502.Impl.SilkNet.Commodore64.Video;
using Highbyte.DotNet6502.Systems;

Expand All @@ -7,19 +7,21 @@ namespace Highbyte.DotNet6502.App.SilkNetNative.SystemSetup
public enum C64HostRenderer
{
SkiaSharp,
SkiaSharp2, // Experimental render directly to pixel buffer backed by a SKBitmap + Skia shader (SKSL)
SkiaSharp2b, // Experimental render after each instruction directly to pixel buffer backed by a SKBitmap + Skia shader (SKSL)
SilkNetOpenGl
}

public class C64HostConfig : IHostSystemConfig, ICloneable
{
public C64HostRenderer Renderer { get; set; } = C64HostRenderer.SkiaSharp;
public C64SilkNetOpenGlRendererConfig SilkNetOpenGlRendererConfig { get; set; } = new C64SilkNetOpenGlRendererConfig();
public C64SilkNetConfig InputConfig { get; set; } = new C64SilkNetConfig();
public C64SilkNetInputConfig InputConfig { get; set; } = new C64SilkNetInputConfig();

public object Clone()
{
var clone = (C64HostConfig)this.MemberwiseClone();
clone.InputConfig = (C64SilkNetConfig)InputConfig.Clone();
clone.InputConfig = (C64SilkNetInputConfig)InputConfig.Clone();
clone.SilkNetOpenGlRendererConfig = (C64SilkNetOpenGlRendererConfig)SilkNetOpenGlRendererConfig.Clone();
return clone;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
using Highbyte.DotNet6502.Impl.SilkNet.Commodore64.Input;
using Highbyte.DotNet6502.Impl.SilkNet.Commodore64.Video;
using Highbyte.DotNet6502.Impl.Skia;
using Highbyte.DotNet6502.Impl.Skia.Commodore64.Video;
using Highbyte.DotNet6502.Impl.Skia.Commodore64.Video.v1;
using Highbyte.DotNet6502.Impl.Skia.Commodore64.Video.v2;
using Highbyte.DotNet6502.Systems;
using Highbyte.DotNet6502.Systems.Commodore64;
using Highbyte.DotNet6502.Systems.Commodore64.Config;
Expand Down Expand Up @@ -111,6 +112,14 @@ NAudioAudioHandlerContext audioHandlerContext
renderer = new C64SkiaRenderer();
renderContext = renderContextContainer.SkiaRenderContext;
break;
case C64HostRenderer.SkiaSharp2:
renderer = new C64SkiaRenderer2();
renderContext = renderContextContainer.SkiaRenderContext;
break;
case C64HostRenderer.SkiaSharp2b:
renderer = new C64SkiaRenderer2b();
renderContext = renderContextContainer.SkiaRenderContext;
break;
case C64HostRenderer.SilkNetOpenGl:
renderer = new C64SilkNetOpenGlRenderer(c64HostConfig.SilkNetOpenGlRendererConfig);
renderContext = renderContextContainer.SilkNetOpenGlRenderContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.0" />
<PackageReference Include="SkiaSharp.Views.Blazor" Version="2.88.6" />
<PackageReference Include="SkiaSharp.Views.Blazor" Version="3.0.0-preview.3.1" />
<PackageReference Include="PublishSPAforGitHubPages.Build" Version="2.1.0" />
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
<PackageReference Include="Toolbelt.Blazor.Gamepad" Version="8.0.0.1" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@
<div class="column">
<h4>General settings</h4>
<div class="table">
<div class="table-row">
<div class="table-cell twocol">Renderer:</div>
<div class="table-cell twocol">
<select value="@C64HostConfig.Renderer" @onchange="OnRendererChanged">
@foreach (var renderer in Enum.GetNames<C64HostRenderer>())
{
<option value="@renderer"> @renderer </option>
}
</select>
</div>
</div>
<div class="table-row">
<div class="table-cell twocol">Audio enabled (experimental):</div>
<div class="table-cell twocol"><input @bind="C64Config.AudioEnabled" @bind:event="oninput" type="checkbox" id="audioEnabled" title="Enable audio" /></div>
Expand Down Expand Up @@ -274,10 +285,14 @@
rom.Data = data;
}

private void OnRendererChanged(ChangeEventArgs e)
=> C64HostConfig.Renderer = Enum.Parse<C64HostRenderer>(e.Value!.ToString()!);

private void OnSelectJoystickChanged(ChangeEventArgs e)
=> C64HostConfig.InputConfig.CurrentJoystick = int.Parse(e.Value!.ToString()!);

private void OnSelectKeyboardJoystickChanged(ChangeEventArgs e)
=> C64Config.KeyboardJoystick = int.Parse(e.Value!.ToString()!);


}
5 changes: 4 additions & 1 deletion src/apps/Highbyte.DotNet6502.App.WASM/Pages/Index.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ protected override async Task OnInitializedAsync()
// Add systems
_systemList = new SystemList<SkiaRenderContext, AspNetInputHandlerContext, WASMAudioHandlerContext>();

var c64HostConfig = new C64HostConfig();
var c64HostConfig = new C64HostConfig
{
Renderer = C64HostRenderer.SkiaSharp,
};
var c64Setup = new C64Setup(_browserContext, LoggerFactory, c64HostConfig);
_systemList.AddSystem(c64Setup);

Expand Down
16 changes: 12 additions & 4 deletions src/apps/Highbyte.DotNet6502.App.WASM/Skia/C64HostConfig.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@

using Highbyte.DotNet6502.Impl.AspNet.Commodore64;
using Highbyte.DotNet6502.Impl.AspNet.Commodore64.Input;
using Highbyte.DotNet6502.Systems;

namespace Highbyte.DotNet6502.App.WASM.Skia
{
public enum C64HostRenderer
{
SkiaSharp,
SkiaSharp2, // Experimental render directly to pixel buffer backed by a SKBitmap + Skia shader (SKSL)
SkiaSharp2b, // Experimental render after each instruction directly to pixel buffer backed by a SKBitmap + Skia shader (SKSL)
}
public class C64HostConfig : IHostSystemConfig, ICloneable
{
public C64AspNetConfig InputConfig { get; set; } = new C64AspNetConfig();

public C64HostRenderer Renderer { get; set; } = C64HostRenderer.SkiaSharp;

public C64AspNetInputConfig InputConfig { get; set; } = new C64AspNetInputConfig();

public object Clone()
{
var clone = (C64HostConfig)MemberwiseClone();
clone.InputConfig = (C64AspNetConfig)InputConfig.Clone();
clone.InputConfig = (C64AspNetInputConfig)InputConfig.Clone();
return clone;
}
}
Expand Down
24 changes: 21 additions & 3 deletions src/apps/Highbyte.DotNet6502.App.WASM/Skia/C64Setup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using Highbyte.DotNet6502.Impl.AspNet.Commodore64.Audio;
using Highbyte.DotNet6502.Impl.AspNet.Commodore64.Input;
using Highbyte.DotNet6502.Impl.Skia;
using Highbyte.DotNet6502.Impl.Skia.Commodore64.Video;
using Highbyte.DotNet6502.Impl.Skia.Commodore64.Video.v1;
using Highbyte.DotNet6502.Impl.Skia.Commodore64.Video.v2;
using Highbyte.DotNet6502.Systems;
using Highbyte.DotNet6502.Systems.Commodore64;
using Highbyte.DotNet6502.Systems.Commodore64.Config;
Expand Down Expand Up @@ -76,12 +77,29 @@ public SystemRunner BuildSystemRunner(
WASMAudioHandlerContext audioHandlerContext
)
{
var c64 = (C64)system;
var c64HostConfig = (C64HostConfig)hostSystemConfig;

IRenderer renderer;
switch (c64HostConfig.Renderer)
{
case C64HostRenderer.SkiaSharp:
renderer = new C64SkiaRenderer();
break;
case C64HostRenderer.SkiaSharp2:
renderer = new C64SkiaRenderer2();
break;
case C64HostRenderer.SkiaSharp2b:
renderer = new C64SkiaRenderer2b();
break;
default:
throw new NotImplementedException($"Renderer {c64HostConfig.Renderer} not implemented.");
}


var renderer = new C64SkiaRenderer();
var inputHandler = new C64AspNetInputHandler(_loggerFactory, _hostConfig.InputConfig);
var audioHandler = new C64WASMAudioHandler(_loggerFactory);

var c64 = (C64)system;
renderer.Init(c64, renderContext);
inputHandler.Init(c64, inputHandlerContext);
audioHandler.Init(c64, audioHandlerContext);
Expand Down
5 changes: 3 additions & 2 deletions src/apps/Highbyte.DotNet6502.App.WASM/Skia/WasmHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ public void Cleanup()
// Clean up input handler resources
InputHandlerContext?.Cleanup();

// Stop any playing audio
_systemRunner.AudioHandler.StopPlaying();
// Cleanup system runner (including stop any playing audio)
_systemRunner.Cleanup();

// Clean up audio resources
//AudioHandlerContext?.Cleanup();
}
Expand Down
2 changes: 1 addition & 1 deletion src/apps/Highbyte.DotNet6502.App.WASM/global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "8.0.100"
"version": "8.0.303"
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Highbyte.DotNet6502.Systems.Commodore64.TimerAndPeripheral;

namespace Highbyte.DotNet6502.Impl.AspNet.Commodore64
namespace Highbyte.DotNet6502.Impl.AspNet.Commodore64.Input
{
public class C64AspNetConfig : ICloneable
public class C64AspNetInputConfig : ICloneable
{
public int CurrentJoystick = 2;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ public class C64AspNetInputHandler : IInputHandler<C64, AspNetInputHandlerContex
private AspNetInputHandlerContext? _inputHandlerContext = default!;
private readonly ILogger<C64AspNetInputHandler> _logger;
private C64AspNetKeyboard _c64AspNetKeyboard = default!;
private readonly C64AspNetConfig _c64AspNetConfig;
private readonly C64AspNetInputConfig _c64AspNetConfig;

// Instrumentations
public Instrumentations Instrumentations { get; } = new();

public C64AspNetInputHandler(ILoggerFactory loggerFactory, C64AspNetConfig c64AspNetConfig)
public C64AspNetInputHandler(ILoggerFactory loggerFactory, C64AspNetInputConfig c64AspNetConfig)
{
_logger = loggerFactory.CreateLogger<C64AspNetInputHandler>();
_c64AspNetConfig = c64AspNetConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public void Init(ISystem system, IRenderContext renderContext)
Init((C64)system, (SadConsoleRenderContext)renderContext);
}

public void Cleanup()
{
}

public void Draw(C64 c64)
{
RenderMainScreen(c64);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public void Init(ISystem system, IRenderContext renderContext)
Init((GenericComputer)system, (SadConsoleRenderContext)renderContext);
}

public void Cleanup()
{
}

public void Draw(GenericComputer system)
{
RenderMainScreen(system);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Highbyte.DotNet6502.Systems.Commodore64.TimerAndPeripheral;

namespace Highbyte.DotNet6502.Impl.SilkNet.Commodore64
namespace Highbyte.DotNet6502.Impl.SilkNet.Commodore64.Input
{
public class C64SilkNetConfig : ICloneable
public class C64SilkNetInputConfig : ICloneable
{
public int CurrentJoystick = 2;

Expand Down Expand Up @@ -36,7 +36,7 @@ public class C64SilkNetConfig : ICloneable

public object Clone()
{
return this.MemberwiseClone();
return MemberwiseClone();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ public class C64SilkNetInputHandler : IInputHandler<C64, SilkNetInputHandlerCont
//private readonly C64SilkNetGamepad _c64SilkNetGamepad;

private readonly ILogger<C64SilkNetInputHandler> _logger;
private readonly C64SilkNetConfig _c64SilkNetConfig;
private readonly C64SilkNetInputConfig _c64SilkNetConfig;
public List<string> GetDebugInfo() => new();

// Instrumentations
public Instrumentations Instrumentations { get; } = new();


public C64SilkNetInputHandler(ILoggerFactory loggerFactory, C64SilkNetConfig c64SilkNetConfig)
public C64SilkNetInputHandler(ILoggerFactory loggerFactory, C64SilkNetInputConfig c64SilkNetConfig)
{
_logger = loggerFactory.CreateLogger<C64SilkNetInputHandler>();
_c64SilkNetConfig = c64SilkNetConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ public void Init(C64 c64, SilkNetOpenGlRenderContext silkNetOpenGlRenderContext)
InitShader(c64);
}

public void Cleanup()
{
_shader?.Dispose();
_vba?.Dispose();
_vbo?.Dispose();
_uboTextData?.Dispose();
_uboCharsetData?.Dispose();
_uboBitmapData?.Dispose();
_uboColorMapData?.Dispose();
_uboScreenLineData?.Dispose();
_uboSpriteData?.Dispose();
_uboSpriteContentData?.Dispose();
}

private void InitShader(C64 c64)
{
#if DEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,17 +211,18 @@ bool GetMultiColor(uint charLine, uint charsetBitPosition, vec4 color01, vec4 co
bool GetTextModePixelColor(uint x, uint y, out bool border, out vec4 pixelColor)
{
// Detect border area, draw only border color
uint horizontalBorderOffset = uScreenLineData[y].colMode40 == 1u ? 0u : 8u;
uint horizontalLeftBorderOffset = uScreenLineData[y].colMode40 == 1u ? 0u : 7u;
uint horizontalRightBorderOffset = uScreenLineData[y].colMode40 == 1u ? 0u : 9u;
uint verticalBorderOffset = uScreenLineData[y].rowMode25 == 1u ? 0u : 4u;

// Workaround for 38 col mode (to counter fine x scroll value is set to +1 in 38 col mode)
if(horizontalBorderOffset!=0u)
x=x+1u;
// if(horizontalBorderOffset!=0u)
// x=x+1u;
// Workaround for 24 row mode (to counter fine y scroll value is set to +1 in 24 row mode)
if(verticalBorderOffset!=0u)
y=y+1u;

if((x < (uTextScreenStart.x+horizontalBorderOffset) || (x > (uTextScreenEnd.x-horizontalBorderOffset)))
if((x < (uTextScreenStart.x+horizontalLeftBorderOffset) || (x > (uTextScreenEnd.x-horizontalRightBorderOffset)))
|| (y < (uTextScreenStart.y+verticalBorderOffset) || (y > (uTextScreenEnd.y-verticalBorderOffset))) )
{
border = true;
Expand Down
Loading

0 comments on commit f2e0d39

Please sign in to comment.