Project: Add barebones OpenTK frontend

This hopefully works on Linux...
This commit is contained in:
Blue 2020-06-21 22:16:15 +02:00
parent 4f5f276b2e
commit a90ff95999
5 changed files with 264 additions and 0 deletions

View file

@ -0,0 +1,66 @@
using System;
using OpenToolkit.Audio.OpenAL;
using OpenToolkit.Mathematics;
namespace ProjectPSX.OpenTK {
public class AudioPlayer {
int audioSource;
ALDevice audioDevice;
ALContext audioContext;
int queueLength = 0;
public bool fastForward;
public bool audioDisabled;
public AudioPlayer() {
audioDevice = ALC.OpenDevice(null);
if (audioDevice == null) {
Console.WriteLine("Unable to create audio device");
return;
}
audioContext = ALC.CreateContext(audioDevice, (int[])null);
ALC.MakeContextCurrent(audioContext);
audioSource = AL.GenSource();
AL.Listener(ALListener3f.Position, 0, 0, 0);
AL.Listener(ALListener3f.Velocity, 0, 0, 0);
var orientation = new Vector3(0, 0, 0);
AL.Listener(ALListenerfv.Orientation, ref orientation, ref orientation);
fastForward = false;
audioDisabled = false;
}
public unsafe void UpdateAudio(byte[] samples) {
int processed = 0;
int alBuffer = 0;
while (true) {
AL.GetSource(audioSource, ALGetSourcei.BuffersProcessed, out processed);
while (processed-- > 0) {
AL.SourceUnqueueBuffers(audioSource, 1, ref alBuffer);
AL.DeleteBuffer(alBuffer);
queueLength--;
}
if (queueLength < 5 || fastForward) break;
}
if (queueLength < 5) {
alBuffer = AL.GenBuffer();
AL.BufferData(alBuffer, ALFormat.Stereo16, samples, samples.Length, 44100);
AL.SourceQueueBuffer(audioSource, alBuffer);
queueLength++;
}
if (AL.GetSourceState(audioSource) != ALSourceState.Playing)
AL.SourcePlay(audioSource);
}
// Is this automatically called by GC?
~AudioPlayer() {
ALC.DestroyContext(audioContext);
ALC.CloseDevice(audioDevice);
}
}
}

View file

@ -0,0 +1,25 @@
using OpenToolkit.Mathematics;
using OpenToolkit.Windowing.Desktop;
using System;
namespace ProjectPSX.OpenTK {
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
GameWindowSettings settings = new GameWindowSettings();
settings.RenderFrequency = 60;
settings.UpdateFrequency = 60;
NativeWindowSettings nativeWindow = new NativeWindowSettings();
nativeWindow.Size = new Vector2i(1024, 512);
nativeWindow.Title = "ProjectPSX";
nativeWindow.Profile = OpenToolkit.Windowing.Common.ContextProfile.Compatability;
Window window = new Window(settings, nativeWindow);
window.VSync = OpenToolkit.Windowing.Common.VSyncMode.On;
window.Run();
}
}
}

View file

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK" Version="4.0.0-pre9.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProjectPSX\ProjectPSX.csproj" />
</ItemGroup>
</Project>

136
ProjectPSX.OpenTK/Window.cs Normal file
View file

@ -0,0 +1,136 @@
using OpenToolkit.Windowing.Common;
using OpenToolkit.Windowing.Desktop;
using OpenToolkit.Graphics.OpenGL;
using System.Collections.Generic;
using OpenToolkit.Windowing.Common.Input;
using ProjectPSX.Devices.Input;
using System;
namespace ProjectPSX.OpenTK {
public class Window : GameWindow, IHostWindow {
private ProjectPSX psx;
private int[] displayBuffer;
private Dictionary<Key, GamepadInputsEnum> _gamepadKeyMap;
private AudioPlayer audioPlayer = new AudioPlayer();
public Window(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings) {
psx = new ProjectPSX(this, @"C:\Users\Wapens\source\repos\ProjectPSX\ProjectPSX\bin\r4.bin");
psx.POWER_ON();
_gamepadKeyMap = new Dictionary<Key, GamepadInputsEnum>() {
{ Key.Space, GamepadInputsEnum.Space},
{ Key.Z , GamepadInputsEnum.Z },
{ Key.C , GamepadInputsEnum.C },
{ Key.Enter , GamepadInputsEnum.Enter },
{ Key.Up , GamepadInputsEnum.Up },
{ Key.Right , GamepadInputsEnum.Right },
{ Key.Down , GamepadInputsEnum.Down },
{ Key.Left , GamepadInputsEnum.Left },
{ Key.F1 , GamepadInputsEnum.D1 },
{ Key.F3 , GamepadInputsEnum.D3 },
{ Key.Q , GamepadInputsEnum.Q },
{ Key.E , GamepadInputsEnum.E },
{ Key.W , GamepadInputsEnum.W },
{ Key.D , GamepadInputsEnum.D },
{ Key.S , GamepadInputsEnum.S },
{ Key.A , GamepadInputsEnum.A },
};
}
protected override void OnLoad() {
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
GL.Enable(EnableCap.Texture2D);
GL.ClearColor(1, 1, 1, 1);
}
protected override void OnRenderFrame(FrameEventArgs args) {
//Console.WriteLine(this.RenderFrequency);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
int id = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, id);
GL.TexImage2D(TextureTarget.Texture2D, 0,
PixelInternalFormat.Rgb,
1024, 512, 0,
PixelFormat.Bgra,
PixelType.UnsignedByte,
displayBuffer);
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0, 1); GL.Vertex2(-1, -1);
GL.TexCoord2(1, 1); GL.Vertex2(1, -1);
GL.TexCoord2(1, 0); GL.Vertex2(1, 1);
GL.TexCoord2(0, 0); GL.Vertex2(-1, 1);
GL.End();
GL.DeleteTexture(id);
SwapBuffers();
//Console.WriteLine("painting");
}
protected override void OnUpdateFrame(FrameEventArgs args) {
base.OnUpdateFrame(args);
psx.RunFrame();
}
protected override void OnKeyDown(KeyboardKeyEventArgs e) {
GamepadInputsEnum? button = GetGamepadButton(e.Key);
if (button != null)
psx.JoyPadDown(button.Value);
}
protected override void OnKeyUp(KeyboardKeyEventArgs e) {
GamepadInputsEnum? button = GetGamepadButton(e.Key);
if (button != null)
psx.JoyPadUp(button.Value);
}
private GamepadInputsEnum? GetGamepadButton(Key keyCode) {
if (_gamepadKeyMap.TryGetValue(keyCode, out GamepadInputsEnum gamepadButtonValue))
return gamepadButtonValue;
return null;
}
public void Update(int[] bits) {
displayBuffer = bits;
}
public int GetFPS() {
return (int)RenderFrequency;
}
public void SetWindowText(string newText) {
this.Title = newText;
}
public void SetDisplayMode(int horizontalRes, int verticalRes, bool is24BitDepth) {
//throw new System.NotImplementedException();
}
public void SetHorizontalRange(ushort displayX1, ushort displayX2) {
//throw new System.NotImplementedException();
}
public void SetVRAMStart(ushort displayVRAMXStart, ushort displayVRAMYStart) {
//throw new System.NotImplementedException();
}
public void SetVerticalRange(ushort displayY1, ushort displayY2) {
//throw new System.NotImplementedException();
}
public void Play(byte[] samples) {
audioPlayer.UpdateAudio(samples);
}
}
}

View file

@ -10,6 +10,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectPSX.WinForms", "Proj
{6351ED6D-2403-43EE-8DD8-EB7E796B41EB} = {6351ED6D-2403-43EE-8DD8-EB7E796B41EB}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectPSX.OpenTK", "ProjectPSX.OpenTK\ProjectPSX.OpenTK.csproj", "{8206B712-6B1E-4DEE-8156-5757EDBD3315}"
ProjectSection(ProjectDependencies) = postProject
{6351ED6D-2403-43EE-8DD8-EB7E796B41EB} = {6351ED6D-2403-43EE-8DD8-EB7E796B41EB}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -44,6 +49,18 @@ Global
{826358E3-4610-4688-96DD-86963BE51A58}.Release|x64.Build.0 = Release|Any CPU
{826358E3-4610-4688-96DD-86963BE51A58}.Release|x86.ActiveCfg = Release|Any CPU
{826358E3-4610-4688-96DD-86963BE51A58}.Release|x86.Build.0 = Release|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Debug|x64.ActiveCfg = Debug|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Debug|x64.Build.0 = Debug|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Debug|x86.ActiveCfg = Debug|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Debug|x86.Build.0 = Debug|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Release|Any CPU.Build.0 = Release|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Release|x64.ActiveCfg = Release|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Release|x64.Build.0 = Release|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Release|x86.ActiveCfg = Release|Any CPU
{8206B712-6B1E-4DEE-8156-5757EDBD3315}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE