Skip to content

Commit

Permalink
Splitting GUI from Headless emulator. Cramming in stupid ascii art re…
Browse files Browse the repository at this point in the history
…ndering.
  • Loading branch information
davidwhitney committed Apr 19, 2020
1 parent 6c3cd14 commit 629075c
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 78 deletions.
22 changes: 22 additions & 0 deletions CoreBoy.Cli/CoreBoy.Cli.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<None Remove="mario.gb" />
</ItemGroup>

<ItemGroup>
<Content Include="mario.gb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CoreBoy\CoreBoy.csproj" />
</ItemGroup>

</Project>
99 changes: 99 additions & 0 deletions CoreBoy.Cli/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using CoreBoy.controller;
using CoreBoy.gui;
using Button = CoreBoy.controller.Button;

namespace CoreBoy.Cli
{
public class Program
{
static void Main(string[] args)
{
var cancellation = new CancellationTokenSource();
var arguments = GameboyOptions.Parse(args);
var emulator = new Emulator(arguments);

if (!arguments.RomSpecified)
{
GameboyOptions.PrintUsage(Console.Out);
Console.Out.Flush();
Environment.Exit(1);
}

var ui = new CommandLineInteractivity();

emulator.Controller = ui;
emulator.Display.OnFrameProduced += ui.UpdateDisplay;
emulator.Run(cancellation.Token);

//var inputLoop = new Thread(ui.ProcessInput);
//inputLoop.Start();

ui.ProcessInput();


cancellation.Cancel();
}
}

public class CommandLineInteractivity : IController
{
private IButtonListener _listener;
private readonly Dictionary<ConsoleKey, Button> _controls;

public CommandLineInteractivity()
{
Console.Clear();
Console.SetCursorPosition(0, 0);
Console.WindowHeight = 92;

_controls = new Dictionary<ConsoleKey, Button>
{
{ConsoleKey.LeftArrow, Button.Left},
{ConsoleKey.RightArrow, Button.Right},
{ConsoleKey.UpArrow, Button.Up},
{ConsoleKey.DownArrow, Button.Down},
{ConsoleKey.Z, Button.A},
{ConsoleKey.X, Button.B},
{ConsoleKey.Enter, Button.Start},
{ConsoleKey.Backspace, Button.Select}
};
}

public void SetButtonListener(IButtonListener listener) => _listener = listener;

public void ProcessInput()
{
Button lastButton = null;
var input = Console.ReadKey(true);
while (input.Key != ConsoleKey.Escape)
{
var button = _controls.ContainsKey(input.Key) ? _controls[input.Key] : null;

if (button != null)
{
if (lastButton != null)
{
_listener?.OnButtonRelease(lastButton);

}

_listener?.OnButtonPress(button);
lastButton = button;
}

input = Console.ReadKey(true);
}
}

public void UpdateDisplay(object sender, byte[] framedata)
{
var frame = SillyAsciiArtCreator.GenerateArt(framedata);
Console.SetCursorPosition(0, 0);
Console.WriteLine(frame);
}
}
}
85 changes: 85 additions & 0 deletions CoreBoy.Cli/SillyAsciiArtCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

namespace CoreBoy.Cli
{
public class SillyAsciiArtCreator
{
private static readonly Dictionary<float, string> Map;

static SillyAsciiArtCreator()
{
Map = new Dictionary<float, string>
{
{200, " "},
{190, " "},
{180, " "},
{170, " "},
{160, " "},
{150, "."},
{140, "o"},
{130, "O"},
{120, "+"},
{110, "#"},
{100, "@"},
{080, "%"},
{060, "░"},
{040, "▒"},
{020, "▓"},
{000, "█"},
};
}

public static string GenerateArt(byte[] jpg)
{
var image = Image.Load(jpg);
image.Mutate(x => x.Resize(106, 72));

var map = Map.OrderBy(kvp => kvp.Key).ToList();
var sb = new StringBuilder();

for (var y = 0; y < image.Height; y++)
{
for (var x = 0; x < image.Width; x++)
{
var pixel = image[x, y];
var currentChar = MapToAscii(map, pixel);

sb.Append(currentChar);
}

sb.Append(Environment.NewLine);
}

image.Dispose();

return PostProcessOutput(sb);
}

private static string MapToAscii(IEnumerable<KeyValuePair<float, string>> map, Rgba32 pixel)
{
var currentChar = "";
foreach (var (key, value) in map)
{
if (key <= pixel.R)
{
currentChar = value;
}
}
return currentChar;
}

private static string PostProcessOutput(StringBuilder sb)
{
var output = sb.ToString();
sb.Clear();
output = output.Substring(0, output.Length - Environment.NewLine.Length);
return output;
}
}
}
37 changes: 37 additions & 0 deletions CoreBoy.Windows/CoreBoy.Windows.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<LangVersion>8.0</LangVersion>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>CoreBoy.Windows</RootNamespace>
<AssemblyName>CoreBoy.Windows</AssemblyName>
<StartupObject>CoreBoy.Windows.Program</StartupObject>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>

<ItemGroup>
<None Remove="mario.gb" />
<None Remove="tetris.gb" />
</ItemGroup>

<ItemGroup>
<Content Include="mario.gb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="tetris.gb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CoreBoy\CoreBoy.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Update="WinFormsEmulatorSurface.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>

</Project>
37 changes: 37 additions & 0 deletions CoreBoy.Windows/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Threading;
using System.Windows.Forms;
using CoreBoy.gui;

namespace CoreBoy.Windows
{
public static class Program
{
[STAThread]
public static void Main(string[] args)
{
var cancellation = new CancellationTokenSource();
var arguments = GameboyOptions.Parse(args);

Application.SetCompatibleTextRenderingDefault(false);
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();

var emulator = new Emulator(arguments);

if (!arguments.RomSpecified)
{
var (success, romPath) = WinFormsEmulatorSurface.PromptForRom();
arguments.Rom = success ? romPath : string.Empty;
}

var ui = new WinFormsEmulatorSurface();
ui.Closed += (_, e) => { cancellation.Cancel(); };
emulator.Controller = ui;
emulator.Display.OnFrameProduced += ui.UpdateDisplay;

emulator.Run(cancellation.Token);
Application.Run(ui);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
using System.Threading;
using System.Windows.Forms;
using CoreBoy.controller;
using CoreBoy.gui;
using Button = CoreBoy.controller.Button;

namespace CoreBoy.gui
namespace CoreBoy.Windows
{
public partial class WinFormsEmulatorSurface : Form, IController
{
Expand Down
14 changes: 13 additions & 1 deletion CoreBoy.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreBoy", "CoreBoy\CoreBoy.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreBoy.Test.Unit", "CoreBoy.Test.Unit\CoreBoy.Test.Unit.csproj", "{89AA3401-3EB7-4C96-8429-B28E9BE93754}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreBoy.Test.Integration", "CoreBoy.Test.Integration\CoreBoy.Test.Integration.csproj", "{EAB44CCA-A65A-48CC-8ABB-096205788883}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreBoy.Test.Integration", "CoreBoy.Test.Integration\CoreBoy.Test.Integration.csproj", "{EAB44CCA-A65A-48CC-8ABB-096205788883}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreBoy.Windows", "CoreBoy.Windows\CoreBoy.Windows.csproj", "{66AA473C-2F18-4A72-8F96-5F5A3E05F706}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreBoy.Cli", "CoreBoy.Cli\CoreBoy.Cli.csproj", "{FB968AD4-425E-4BE5-8467-0DAD35591C62}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -27,6 +31,14 @@ Global
{EAB44CCA-A65A-48CC-8ABB-096205788883}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAB44CCA-A65A-48CC-8ABB-096205788883}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAB44CCA-A65A-48CC-8ABB-096205788883}.Release|Any CPU.Build.0 = Release|Any CPU
{66AA473C-2F18-4A72-8F96-5F5A3E05F706}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66AA473C-2F18-4A72-8F96-5F5A3E05F706}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66AA473C-2F18-4A72-8F96-5F5A3E05F706}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66AA473C-2F18-4A72-8F96-5F5A3E05F706}.Release|Any CPU.Build.0 = Release|Any CPU
{FB968AD4-425E-4BE5-8467-0DAD35591C62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FB968AD4-425E-4BE5-8467-0DAD35591C62}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FB968AD4-425E-4BE5-8467-0DAD35591C62}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FB968AD4-425E-4BE5-8467-0DAD35591C62}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 1 addition & 0 deletions CoreBoy.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RAM/@EntryIndexedValue">RAM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SP/@EntryIndexedValue">SP</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Blargg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=framedata/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=gameboy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hblank/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Hdma/@EntryIndexedValue">True</s:Boolean>
Expand Down
18 changes: 2 additions & 16 deletions CoreBoy/CoreBoy.csproj
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<OutputType>Library</OutputType>
<LangVersion>8.0</LangVersion>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>CoreBoy</RootNamespace>
<AssemblyName>CoreBoy</AssemblyName>
<StartupObject>CoreBoy.Program</StartupObject>
<StartupObject></StartupObject>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>

<ItemGroup>
<None Remove="mario.gb" />
<None Remove="tetris.gb" />
</ItemGroup>

<ItemGroup>
<Content Include="mario.gb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="tetris.gb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.7.82" />
<PackageReference Include="NAudio" Version="1.10.0" />
Expand Down
Loading

0 comments on commit 629075c

Please sign in to comment.