This commit is contained in:
NekokoTime 2018-06-14 12:27:31 +00:00 committed by GitHub
commit 7ae74b8e5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 4805 additions and 10 deletions

View file

@ -0,0 +1,70 @@
using System.IO;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.Shader.SPIRV
{
public class Assembler
{
private List<Instruction> Instructions;
public Assembler()
{
Instructions = new List<Instruction>();
}
public void Write(Stream Output)
{
uint Bound = DoBindings();
var BinaryWriter = new BinaryWriter(Output);
BinaryWriter.Write((uint)BinaryForm.MagicNumber);
BinaryWriter.Write((uint)BinaryForm.VersionNumber);
BinaryWriter.Write((uint)BinaryForm.GeneratorMagicNumber);
BinaryWriter.Write((uint)Bound);
BinaryWriter.Write((uint)0); // Reserved for instruction schema
foreach (var Instruction in Instructions)
{
Instruction.Write(BinaryWriter);
}
}
public void Add(Instruction Instruction)
{
Instructions.Add(Instruction);
}
public void Add(Instruction[] Instructions)
{
foreach (Instruction Instruction in Instructions)
{
Add(Instruction);
}
}
public void Add(List<Instruction> Instructions)
{
foreach (Instruction Instruction in Instructions)
{
Add(Instruction);
}
}
private uint DoBindings()
{
uint Bind = 1;
foreach (var Instruction in Instructions)
{
if (Instruction.HoldsResultId)
{
Instruction.ResultId = Bind;
Bind++;
}
}
return Bind;
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,151 @@
using System;
using System.IO;
using System.Text;
namespace Ryujinx.Graphics.Gal.Shader.SPIRV
{
public abstract class Operand
{
public abstract int GetWordCount();
public abstract void Write(BinaryWriter BinaryWriter);
}
public class Id: Operand
{
private Instruction Instruction;
public Id(Instruction Instruction)
{
this.Instruction = Instruction;
}
public override void Write(BinaryWriter BinaryWriter)
{
BinaryWriter.Write((uint)Instruction.ResultId);
}
public override int GetWordCount()
{
return 1;
}
}
public abstract class Literal: Operand
{
}
public class LiteralString: Literal
{
public byte[] Value;
public LiteralString(string String)
{
Value = Encoding.UTF8.GetBytes(String);
}
public override void Write(BinaryWriter BinaryWriter)
{
BinaryWriter.Write(Value);
// Write remaining zero bytes
for (int i = 0; i < 4 - (Value.Length % 4); i++)
{
BinaryWriter.Write((byte)0);
}
}
public override int GetWordCount()
{
return Value.Length / 4 + 1;
}
public override bool Equals(object Object)
{
if (Object is LiteralString Other)
{
return this.Value == Other.Value;
}
return false;
}
}
public class LiteralNumber: Literal
{
public TypeCode Type;
public int Integer;
public float Float32;
public double Float64;
public LiteralNumber(int Value)
{
Integer = Value;
Type = Value.GetTypeCode();
}
public LiteralNumber(float Value)
{
Float32 = Value;
Type = Value.GetTypeCode();
}
public LiteralNumber(double Value)
{
Float64 = Value;
Type = Value.GetTypeCode();
}
public override void Write(BinaryWriter BinaryWriter)
{
switch (Type)
{
case TypeCode.Int32:
BinaryWriter.Write(Integer);
break;
case TypeCode.Single:
BinaryWriter.Write(Float32);
break;
case TypeCode.Double:
BinaryWriter.Write(Float64);
break;
default:
throw new NotImplementedException();
}
}
public override int GetWordCount()
{
switch (Type)
{
case TypeCode.Int32:
case TypeCode.Single:
return 1;
case TypeCode.Double:
return 2;
default:
throw new NotImplementedException();
}
}
public override bool Equals(object Object)
{
if (Object is LiteralNumber Other && this.Type == Other.Type)
{
return this.Integer == Other.Integer
&& this.Float32 == Other.Float32
&& this.Float64 == Other.Float64;
}
return false;
}
}
}

114
Ryujinx.ImGui/Config.cs Normal file
View file

@ -0,0 +1,114 @@
using Ryujinx.HLE.Input;
using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Ryujinx
{
public static class Config
{
public static JoyCon FakeJoyCon { get; private set; }
public static void Read(Logger Log)
{
string IniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string IniPath = Path.Combine(IniFolder, "Ryujinx.conf");
IniParser Parser = new IniParser(IniPath);
AOptimizations.DisableMemoryChecks = !Convert.ToBoolean(Parser.Value("Enable_Memory_Checks"));
Log.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")));
Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub")));
Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info")));
Log.SetEnable(LogLevel.Warning, Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")));
Log.SetEnable(LogLevel.Error, Convert.ToBoolean(Parser.Value("Logging_Enable_Error")));
string[] FilteredLogClasses = Parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries);
//When the classes are specified on the list, we only
//enable the classes that are on the list.
//So, first disable everything, then enable
//the classes that the user added to the list.
if (FilteredLogClasses.Length > 0)
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
Log.SetEnable(Class, false);
}
}
foreach (string LogClass in FilteredLogClasses)
{
if (!string.IsNullOrEmpty(LogClass.Trim()))
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
if (Class.ToString().ToLower().Contains(LogClass.Trim().ToLower()))
{
Log.SetEnable(Class, true);
}
}
}
}
FakeJoyCon = new JoyCon
{
Left = new JoyConLeft
{
StickUp = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Stick_Up")),
StickDown = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Stick_Down")),
StickLeft = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Stick_Left")),
StickRight = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Stick_Right")),
StickButton = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Stick_Button")),
DPadUp = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_DPad_Up")),
DPadDown = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_DPad_Down")),
DPadLeft = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_DPad_Left")),
DPadRight = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_DPad_Right")),
ButtonMinus = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Button_Minus")),
ButtonL = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Button_L")),
ButtonZL = Convert.ToInt16(Parser.Value("Controls_Left_FakeJoycon_Button_ZL"))
},
Right = new JoyConRight
{
StickUp = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Stick_Up")),
StickDown = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Stick_Down")),
StickLeft = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Stick_Left")),
StickRight = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Stick_Right")),
StickButton = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Stick_Button")),
ButtonA = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Button_A")),
ButtonB = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Button_B")),
ButtonX = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Button_X")),
ButtonY = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Button_Y")),
ButtonPlus = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Button_Plus")),
ButtonR = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Button_R")),
ButtonZR = Convert.ToInt16(Parser.Value("Controls_Right_FakeJoycon_Button_ZR"))
}
};
}
}
// https://stackoverflow.com/a/37772571
public class IniParser
{
private readonly Dictionary<string, string> Values;
public IniParser(string Path)
{
Values = File.ReadLines(Path)
.Where(Line => !string.IsNullOrWhiteSpace(Line) && !Line.StartsWith('#'))
.Select(Line => Line.Split('=', 2))
.ToDictionary(Parts => Parts[0].Trim(), Parts => Parts.Length > 1 ? Parts[1].Trim() : null);
}
public string Value(string Name)
{
return Values.TryGetValue(Name, out string Value) ? Value : null;
}
}
}

View file

@ -0,0 +1,51 @@
using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic;
using System.Threading;
namespace Ryujinx
{
static class ConsoleLog
{
private static Dictionary<LogLevel, ConsoleColor> LogColors;
private static object ConsoleLock;
static ConsoleLog()
{
LogColors = new Dictionary<LogLevel, ConsoleColor>()
{
{ LogLevel.Stub, ConsoleColor.DarkGray },
{ LogLevel.Info, ConsoleColor.White },
{ LogLevel.Warning, ConsoleColor.Yellow },
{ LogLevel.Error, ConsoleColor.Red }
};
ConsoleLock = new object();
}
public static void PrintLog(object sender, LogEventArgs e)
{
string FormattedTime = e.Time.ToString(@"hh\:mm\:ss\.fff");
string CurrentThread = Thread.CurrentThread.ManagedThreadId.ToString("d4");
string Message = FormattedTime + " | " + CurrentThread + " " + e.Message;
if (LogColors.TryGetValue(e.Level, out ConsoleColor Color))
{
lock (ConsoleLock)
{
Console.ForegroundColor = Color;
Console.WriteLine(Message);
Console.ResetColor();
}
}
else
{
Console.WriteLine(Message);
}
}
}
}

312
Ryujinx.ImGui/GUI/MainUI.cs Normal file
View file

@ -0,0 +1,312 @@
using ImGuiNET;
using OpenTK;
using Ryujinx.Audio;
using Ryujinx.Audio.OpenAL;
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Gal.OpenGL;
using Ryujinx.HLE;
using Ryujinx.HLE.Input;
using OpenTK.Graphics;
using OpenTK.Input;
using System;
using System.IO;
namespace Ryujinx.UI
{
class MainUI : WindowHelper
{
//toggles
private bool ShowUI = true;
private bool ShowFileDialog = false;
private bool _isRunning = false;
private bool IsRunning
{
get => _isRunning;
set
{
_isRunning = value;
if (!value)
{
ShowUI = true;
}
}
}
private string CurrentPath = Environment.CurrentDirectory;
private string PackagePath = string.Empty;
private const int TouchScreenWidth = 1280;
private const int TouchScreenHeight = 720;
private const float TouchScreenRatioX = (float)TouchScreenWidth / TouchScreenHeight;
private const float TouchScreenRatioY = (float)TouchScreenHeight / TouchScreenWidth;
FilePicker FileDialog;
IGalRenderer Renderer;
IAalOutput AudioOut;
Switch Ns;
public MainUI() : base("Test")
{
FileDialog = FilePicker.GetFilePicker("rom",null);
Renderer = new OpenGLRenderer();
AudioOut = new OpenALAudioOut();
Ns = new Switch(Renderer, AudioOut);
Config.Read(Ns.Log);
Ns.Log.Updated += ConsoleLog.PrintLog;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
VSync = VSyncMode.On;
Renderer.SetWindowSize(Width, Height);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
_deltaTime = (float)e.Time;
if (ShowUI)
{
StartFrame();
RenderUI();
EndFrame();
}
else
{
Ns.Statistics.StartSystemFrame();
Title = $"Ryujinx Screen - (Vsync: {VSync} - FPS: {Ns.Statistics.SystemFrameRate:0} - Guest FPS: " +
$"{Ns.Statistics.GameFrameRate:0})";
Renderer.RunActions();
Renderer.Render();
SwapBuffers();
Ns.Statistics.EndSystemFrame();
Ns.Os.SignalVsync();
}
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
if (!ShowUI)
{
HidControllerButtons CurrentButton = 0;
HidJoystickPosition LeftJoystick;
HidJoystickPosition RightJoystick;
int LeftJoystickDX = 0;
int LeftJoystickDY = 0;
int RightJoystickDX = 0;
int RightJoystickDY = 0;
//RightJoystick
if (Keyboard[(Key)Config.FakeJoyCon.Left.StickUp]) LeftJoystickDY = short.MaxValue;
if (Keyboard[(Key)Config.FakeJoyCon.Left.StickDown]) LeftJoystickDY = -short.MaxValue;
if (Keyboard[(Key)Config.FakeJoyCon.Left.StickLeft]) LeftJoystickDX = -short.MaxValue;
if (Keyboard[(Key)Config.FakeJoyCon.Left.StickRight]) LeftJoystickDX = short.MaxValue;
//LeftButtons
if (Keyboard[(Key)Config.FakeJoyCon.Left.StickButton]) CurrentButton |= HidControllerButtons.KEY_LSTICK;
if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadUp]) CurrentButton |= HidControllerButtons.KEY_DUP;
if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadDown]) CurrentButton |= HidControllerButtons.KEY_DDOWN;
if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadLeft]) CurrentButton |= HidControllerButtons.KEY_DLEFT;
if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadRight]) CurrentButton |= HidControllerButtons.KEY_DRIGHT;
if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonMinus]) CurrentButton |= HidControllerButtons.KEY_MINUS;
if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonL]) CurrentButton |= HidControllerButtons.KEY_L;
if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonZL]) CurrentButton |= HidControllerButtons.KEY_ZL;
//RightJoystick
if (Keyboard[(Key)Config.FakeJoyCon.Right.StickUp]) RightJoystickDY = short.MaxValue;
if (Keyboard[(Key)Config.FakeJoyCon.Right.StickDown]) RightJoystickDY = -short.MaxValue;
if (Keyboard[(Key)Config.FakeJoyCon.Right.StickLeft]) RightJoystickDX = -short.MaxValue;
if (Keyboard[(Key)Config.FakeJoyCon.Right.StickRight]) RightJoystickDX = short.MaxValue;
//RightButtons
if (Keyboard[(Key)Config.FakeJoyCon.Right.StickButton]) CurrentButton |= HidControllerButtons.KEY_RSTICK;
if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonA]) CurrentButton |= HidControllerButtons.KEY_A;
if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonB]) CurrentButton |= HidControllerButtons.KEY_B;
if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonX]) CurrentButton |= HidControllerButtons.KEY_X;
if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonY]) CurrentButton |= HidControllerButtons.KEY_Y;
if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonPlus]) CurrentButton |= HidControllerButtons.KEY_PLUS;
if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonR]) CurrentButton |= HidControllerButtons.KEY_R;
if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonZR]) CurrentButton |= HidControllerButtons.KEY_ZR;
LeftJoystick = new HidJoystickPosition
{
DX = LeftJoystickDX,
DY = LeftJoystickDY
};
RightJoystick = new HidJoystickPosition
{
DX = RightJoystickDX,
DY = RightJoystickDY
};
bool HasTouch = false;
//Get screen touch position from left mouse click
//OpenTK always captures mouse events, even if out of focus, so check if window is focused.
if (Focused && Mouse?.GetState().LeftButton == ButtonState.Pressed)
{
int ScrnWidth = Width;
int ScrnHeight = Height;
if (Width > Height * TouchScreenRatioX)
{
ScrnWidth = (int)(Height * TouchScreenRatioX);
}
else
{
ScrnHeight = (int)(Width * TouchScreenRatioY);
}
int StartX = (Width - ScrnWidth) >> 1;
int StartY = (Height - ScrnHeight) >> 1;
int EndX = StartX + ScrnWidth;
int EndY = StartY + ScrnHeight;
if (Mouse.X >= StartX &&
Mouse.Y >= StartY &&
Mouse.X < EndX &&
Mouse.Y < EndY)
{
int ScrnMouseX = Mouse.X - StartX;
int ScrnMouseY = Mouse.Y - StartY;
int MX = (int)(((float)ScrnMouseX / ScrnWidth) * TouchScreenWidth);
int MY = (int)(((float)ScrnMouseY / ScrnHeight) * TouchScreenHeight);
HidTouchPoint CurrentPoint = new HidTouchPoint
{
X = MX,
Y = MY,
//Placeholder values till more data is acquired
DiameterX = 10,
DiameterY = 10,
Angle = 90
};
HasTouch = true;
Ns.Hid.SetTouchPoints(CurrentPoint);
}
}
if (!HasTouch)
{
Ns.Hid.SetTouchPoints();
}
Ns.Hid.SetJoyconButton(
HidControllerId.CONTROLLER_HANDHELD,
HidControllerLayouts.Handheld_Joined,
CurrentButton,
LeftJoystick,
RightJoystick);
Ns.Hid.SetJoyconButton(
HidControllerId.CONTROLLER_HANDHELD,
HidControllerLayouts.Main,
CurrentButton,
LeftJoystick,
RightJoystick);
}
}
private void RenderUI()
{
if (ShowUI)
{
ImGui.SetNextWindowPos(System.Numerics.Vector2.Zero, Condition.Always,
System.Numerics.Vector2.Zero);
ImGui.SetNextWindowSize(new System.Numerics.Vector2(Width, Height),Condition.Always);
if (ImGui.BeginWindow("MainWindow",ref ShowUI, WindowFlags.NoTitleBar
| WindowFlags.NoMove | WindowFlags.AlwaysAutoResize))
{
if(ImGui.BeginChildFrame(0, new System.Numerics.Vector2(-1,-1),
WindowFlags.AlwaysAutoResize))
{
ImGuiNative.igBeginGroup();
if(ImGui.Button("Load Package", new System.Numerics.Vector2(Values.ButtonWidth,
Values.ButtonHeight))){
ShowFileDialog = true;
}
ImGuiNative.igEndGroup();
ImGui.SameLine();
if(ImGui.BeginChildFrame(1, ImGui.GetContentRegionAvailable(),
WindowFlags.AlwaysAutoResize))
{
if (ShowFileDialog)
{
string output = CurrentPath;
if (FileDialog.Draw(ref output, false))
{
if (!string.IsNullOrWhiteSpace(output))
{
PackagePath = output;
ShowFileDialog = false;
LoadPackage(PackagePath);
}
}
}
ImGui.EndChildFrame();
}
ImGui.EndChildFrame();
}
ImGui.EndWindow();
}
}
}
public void LoadPackage(string path)
{
if (Directory.Exists(path))
{
string[] RomFsFiles = Directory.GetFiles(path, "*.istorage");
if (RomFsFiles.Length == 0)
{
RomFsFiles = Directory.GetFiles(path, "*.romfs");
}
if (RomFsFiles.Length > 0)
{
Console.WriteLine("Loading as cart with RomFS.");
Ns.LoadCart(path, RomFsFiles[0]);
}
else
{
Console.WriteLine("Loading as cart WITHOUT RomFS.");
Ns.LoadCart(path);
}
}
else if (File.Exists(path))
{
Console.WriteLine("Loading as homebrew.");
Ns.LoadProgram(path);
}
IsRunning = true;
ShowUI = false;
}
}
}

View file

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Numerics;
namespace ImGuiNET
{
public struct Values
{
public const float ButtonWidth = 170f;
public const float ButtonHeight = 50f;
public const float DefaultWindowScale = 1.0f;
public const float SelectibleHeight = 20.0f;
public static float CurrentWindowScale = 1.0f;
public static float CurrentFontScale = 1.2f;
public struct Color
{
public static Vector4 Yellow = new Vector4(1.0f, 1.0f, 0, 1.0f);
}
}
}

View file

@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
namespace ImGuiNET
{
/// <summary>
/// Adapted from Mellinoe's file picker for imgui
/// https://github.com/mellinoe/synthapp/blob/master/src/synthapp/Widgets/FilePicker.cs
/// </summary>
public class FilePicker
{
private const string FilePickerID = "###FilePicker";
private static readonly Dictionary<object, FilePicker> s_filePickers = new Dictionary<object, FilePicker>();
private static readonly Vector2 DefaultFilePickerSize = new Vector2(600, 400);
public string CurrentFolder { get; set; }
public string SelectedFile { get; set; }
public static FilePicker GetFilePicker(object o, string startingPath)
{
if (File.Exists(startingPath))
{
startingPath = new FileInfo(startingPath).DirectoryName;
}
else if (string.IsNullOrEmpty(startingPath) || !Directory.Exists(startingPath))
{
startingPath = Environment.CurrentDirectory;
if (string.IsNullOrEmpty(startingPath))
{
startingPath = AppContext.BaseDirectory;
}
}
if (!s_filePickers.TryGetValue(o, out FilePicker fp))
{
fp = new FilePicker();
fp.CurrentFolder = startingPath;
s_filePickers.Add(o, fp);
}
return fp;
}
public bool Draw(ref string selected, bool returnOnSelection)
{
bool result = false;
result = DrawFolder(ref selected, returnOnSelection);
return result;
}
private bool DrawFolder(ref string selected, bool returnOnSelection = false)
{
ImGui.Text("Current Folder: " + CurrentFolder);
bool result = false;
if (ImGui.BeginChildFrame(1, ImGui.GetContentRegionAvailable() - new Vector2(20, Values.ButtonHeight),
WindowFlags.Default))
{
DirectoryInfo di = new DirectoryInfo(CurrentFolder);
if (di.Exists)
{
if (di.Parent != null)
{
ImGui.PushStyleColor(ColorTarget.Text, Values.Color.Yellow);
if (ImGui.Selectable("../", false, SelectableFlags.DontClosePopups
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
{
CurrentFolder = di.Parent.FullName;
}
ImGui.PopStyleColor();
}
foreach (var dir in Directory.EnumerateFileSystemEntries(di.FullName))
{
if (Directory.Exists(dir))
{
string name = Path.GetFileName(dir);
bool isSelected = SelectedFile == dir;
ImGui.PushStyleColor(ColorTarget.Text, Values.Color.Yellow);
if (ImGui.Selectable(name + "/", isSelected, SelectableFlags.DontClosePopups
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
{
SelectedFile = dir;
selected = SelectedFile;
}
if (SelectedFile != null)
if (ImGui.IsMouseDoubleClicked(0) && SelectedFile.Equals(dir))
{
SelectedFile = null;
selected = null;
CurrentFolder = dir;
}
ImGui.PopStyleColor();
}
}
foreach (var file in Directory.EnumerateFiles(di.FullName))
{
string name = Path.GetFileName(file);
bool isSelected = SelectedFile == file;
if (ImGui.Selectable(name, isSelected, SelectableFlags.DontClosePopups
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
{
SelectedFile = file;
if (returnOnSelection)
{
selected = SelectedFile;
}
}
if (SelectedFile != null)
if (ImGui.IsMouseDoubleClicked(0) && SelectedFile.Equals(file))
{
selected = file;
result = true;
}
}
}
}
ImGui.EndChildFrame();
if (ImGui.Button("Cancel", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))
{
result = false;
}
if (SelectedFile != null)
{
ImGui.SameLine();
if (ImGui.Button("Open", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))
{
result = true;
selected = SelectedFile;
}
}
return result;
}
}
}

View file

@ -0,0 +1,210 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using ImGuiNET;
namespace Ryujinx.UI
{
class WindowHelper : GameWindow
{
protected float _deltaTime;
bool IsWindowOpened = false;
int s_fontTexture;
float _wheelPosition;
public WindowHelper(string title) : base(1280, 720, GraphicsMode.Default, title, GameWindowFlags.Default
, DisplayDevice.Default, 3, 3, GraphicsContextFlags.ForwardCompatible)
{
Title = title;
IsWindowOpened = true;
Location = new Point(
(DisplayDevice.Default.Width / 2) - (Width / 2),
(DisplayDevice.Default.Height / 2) - (Height / 2));
}
public void ShowDemo()
{
ImGuiNative.igShowDemoWindow(ref IsWindowOpened);
}
public void StartFrame()
{
IO io = ImGui.GetIO();
io.DisplaySize = new System.Numerics.Vector2(Width, Height);
io.DisplayFramebufferScale = new System.Numerics.Vector2(Values.CurrentWindowScale);
io.DeltaTime = _deltaTime;
ImGui.NewFrame();
HandleInput(io);
}
public unsafe void EndFrame()
{
ImGui.Render();
DrawData* data = ImGui.GetDrawData();
RenderImDrawData(data);
}
protected unsafe override void OnLoad(EventArgs e)
{
ImGui.GetIO().FontAtlas.AddDefaultFont();
IO io = ImGui.GetIO();
io.FontAllowUserScaling = true;
ImGuiNative.igGetIO()->FontGlobalScale = Values.CurrentFontScale;
// Build texture atlas
FontTextureData texData = io.FontAtlas.GetTexDataAsAlpha8();
// Create OpenGL texture
s_fontTexture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, s_fontTexture);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
GL.TexImage2D(
TextureTarget.Texture2D,
0,
PixelInternalFormat.Alpha,
texData.Width,
texData.Height,
0,
PixelFormat.Alpha,
PixelType.UnsignedByte,
new IntPtr(texData.Pixels));
// Store the texture identifier in the ImFontAtlas substructure.
io.FontAtlas.SetTexID(s_fontTexture);
// Cleanup (don't clear the input data if you want to append new fonts later)
//io.Fonts->ClearInputData();
io.FontAtlas.ClearTexData();
GL.BindTexture(TextureTarget.Texture2D, 0);
}
void HandleInput(IO io)
{
MouseState cursorState = Mouse.GetCursorState();
MouseState mouseState = Mouse.GetState();
if (Focused)
{
Point windowPoint = PointToClient(new Point(cursorState.X, cursorState.Y));
io.MousePosition = new System.Numerics.Vector2(windowPoint.X / io.DisplayFramebufferScale.X, windowPoint.Y / io.DisplayFramebufferScale.Y);
}
else
{
io.MousePosition = new System.Numerics.Vector2(-1f, -1f);
}
io.MouseDown[0] = mouseState.LeftButton == ButtonState.Pressed;
io.MouseDown[1] = mouseState.RightButton == ButtonState.Pressed;
io.MouseDown[2] = mouseState.MiddleButton == ButtonState.Pressed;
float newWheelPos = mouseState.WheelPrecise;
float delta = newWheelPos - _wheelPosition;
_wheelPosition = newWheelPos;
io.MouseWheel = delta;
}
private unsafe void RenderImDrawData(DrawData* draw_data)
{
// Rendering
int display_w, display_h;
display_w = Width;
display_h = Height;
Vector4 clear_color = new Vector4(114f / 255f, 144f / 255f, 154f / 255f, 1.0f);
GL.Viewport(0, 0, display_w, display_h);
GL.ClearColor(clear_color.X, clear_color.Y, clear_color.Z, clear_color.W);
GL.Clear(ClearBufferMask.ColorBufferBit);
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
int last_texture;
GL.GetInteger(GetPName.TextureBinding2D, out last_texture);
GL.PushAttrib(AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.TransformBit);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.Disable(EnableCap.CullFace);
GL.Disable(EnableCap.DepthTest);
GL.Enable(EnableCap.ScissorTest);
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.EnableClientState(ArrayCap.ColorArray);
GL.Enable(EnableCap.Texture2D);
GL.UseProgram(0);
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
IO io = ImGui.GetIO();
ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale);
// Setup orthographic projection matrix
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(
0.0f,
io.DisplaySize.X / io.DisplayFramebufferScale.X,
io.DisplaySize.Y / io.DisplayFramebufferScale.Y,
0.0f,
-1.0f,
1.0f);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
NativeDrawList* cmd_list = draw_data->CmdLists[n];
byte* vtx_buffer = (byte*)cmd_list->VtxBuffer.Data;
ushort* idx_buffer = (ushort*)cmd_list->IdxBuffer.Data;
GL.VertexPointer(2, VertexPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.PosOffset));
GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.UVOffset));
GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.ColOffset));
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
DrawCmd* pcmd = &(((DrawCmd*)cmd_list->CmdBuffer.Data)[cmd_i]);
if (pcmd->UserCallback != IntPtr.Zero)
{
throw new NotImplementedException();
}
else
{
GL.BindTexture(TextureTarget.Texture2D, pcmd->TextureId.ToInt32());
GL.Scissor(
(int)pcmd->ClipRect.X,
(int)(io.DisplaySize.Y - pcmd->ClipRect.W),
(int)(pcmd->ClipRect.Z - pcmd->ClipRect.X),
(int)(pcmd->ClipRect.W - pcmd->ClipRect.Y));
GL.DrawElements(PrimitiveType.Triangles, (int)pcmd->ElemCount, DrawElementsType.UnsignedShort, new IntPtr(idx_buffer));
}
idx_buffer += pcmd->ElemCount;
}
}
// Restore modified state
GL.DisableClientState(ArrayCap.ColorArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.BindTexture(TextureTarget.Texture2D, last_texture);
GL.MatrixMode(MatrixMode.Modelview);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.PopAttrib();
SwapBuffers();
}
}
}

15
Ryujinx.ImGui/Program.cs Normal file
View file

@ -0,0 +1,15 @@
using System;
namespace Ryujinx.UI
{
class Program
{
static void Main(string[] args)
{
MainUI mainUI = new MainUI();
mainUI.Run(60.0, 60.0);
Environment.Exit(0);
}
}
}

View file

@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ImGui.NET" Version="0.4.5" />
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics\Ryujinx.Graphics.csproj" />
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Ryujinx.conf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,47 @@
#Enable cpu memory checks (slow)
Enable_Memory_Checks = false
#Enable print debug logs
Logging_Enable_Debug = false
#Enable print stubbed calls logs
Logging_Enable_Stub = true
#Enable print informations logs
Logging_Enable_Info = true
#Enable print warning logs
Logging_Enable_Warn = true
#Enable print error logs
Logging_Enable_Error = true
#Filtered log classes, seperated by ", ", eg. `Logging_Filtered_Classes = Loader, ServiceFS`
Logging_Filtered_Classes =
#https://github.com/opentk/opentk/blob/develop/src/OpenTK/Input/Key.cs
Controls_Left_FakeJoycon_Stick_Up = 105
Controls_Left_FakeJoycon_Stick_Down = 101
Controls_Left_FakeJoycon_Stick_Left = 83
Controls_Left_FakeJoycon_Stick_Right = 86
Controls_Left_FakeJoycon_Stick_Button = 88
Controls_Left_FakeJoycon_DPad_Up = 45
Controls_Left_FakeJoycon_DPad_Down = 46
Controls_Left_FakeJoycon_DPad_Left = 47
Controls_Left_FakeJoycon_DPad_Right = 48
Controls_Left_FakeJoycon_Button_Minus = 120
Controls_Left_FakeJoycon_Button_L = 87
Controls_Left_FakeJoycon_Button_ZL = 99
Controls_Right_FakeJoycon_Stick_Up = 91
Controls_Right_FakeJoycon_Stick_Down = 93
Controls_Right_FakeJoycon_Stick_Left = 92
Controls_Right_FakeJoycon_Stick_Right = 94
Controls_Right_FakeJoycon_Stick_Button = 90
Controls_Right_FakeJoycon_Button_A = 108
Controls_Right_FakeJoycon_Button_B = 106
Controls_Right_FakeJoycon_Button_X = 85
Controls_Right_FakeJoycon_Button_Y = 104
Controls_Right_FakeJoycon_Button_Plus = 121
Controls_Right_FakeJoycon_Button_R = 103
Controls_Right_FakeJoycon_Button_ZR = 97

View file

@ -2,6 +2,7 @@
using Ryujinx.Graphics.Gal.Shader;
using System;
using System.IO;
using System.Text;
namespace Ryujinx.ShaderTools
{
@ -9,13 +10,11 @@ namespace Ryujinx.ShaderTools
{
static void Main(string[] args)
{
if (args.Length == 2)
if (args.Length == 4)
{
GlslDecompiler Decompiler = new GlslDecompiler();
GalShaderType ShaderType = GalShaderType.Vertex;
switch (args[0].ToLower())
switch (args[1].ToLower())
{
case "v": ShaderType = GalShaderType.Vertex; break;
case "tc": ShaderType = GalShaderType.TessControl; break;
@ -24,18 +23,34 @@ namespace Ryujinx.ShaderTools
case "f": ShaderType = GalShaderType.Fragment; break;
}
using (FileStream FS = new FileStream(args[1], FileMode.Open, FileAccess.Read))
using (FileStream Output = new FileStream(args[3], FileMode.Create))
using (FileStream FS = new FileStream(args[2], FileMode.Open, FileAccess.Read))
{
Memory Mem = new Memory(FS);
GlslProgram Program = Decompiler.Decompile(Mem, 0, ShaderType);
switch (args[0].ToLower())
{
case "glsl":
GlslDecompiler GlslDecompiler = new GlslDecompiler();
Console.WriteLine(Program.Code);
GlslProgram Program = GlslDecompiler.Decompile(Mem, 0, ShaderType);
Output.Write(System.Text.Encoding.UTF8.GetBytes(Program.Code));
break;
case "spirv":
SpirvDecompiler SpirvDecompiler = new SpirvDecompiler();
Output.Write(SpirvDecompiler.Decompile(Mem, 0, ShaderType));
break;
}
}
}
else
{
Console.WriteLine("Usage: Ryujinx.ShaderTools [v|tc|te|g|f] shader.bin");
Console.WriteLine("Usage: Ryujinx.ShaderTools [spirv|glsl] [v|tc|te|g|f] shader.bin output.bin");
}
}
}

View file

@ -15,9 +15,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics", "Ryujinx
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "Ryujinx.Audio\Ryujinx.Audio.csproj", "{5C1D818E-682A-46A5-9D54-30006E26C270}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.ShaderTools", "Ryujinx.ShaderTools\Ryujinx.ShaderTools.csproj", "{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.ShaderTools", "Ryujinx.ShaderTools\Ryujinx.ShaderTools.csproj", "{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luea", "Ryujinx.LLE\Luea.csproj", "{8E7D36DD-9626-47E2-8EF5-8F2F66751C9C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luea", "Ryujinx.LLE\Luea.csproj", "{8E7D36DD-9626-47E2-8EF5-8F2F66751C9C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.UI", "Ryujinx.ImGui\Ryujinx.UI.csproj", "{00117502-1661-4C8B-8C07-177C1A8AA455}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -57,6 +59,10 @@ Global
{8E7D36DD-9626-47E2-8EF5-8F2F66751C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E7D36DD-9626-47E2-8EF5-8F2F66751C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E7D36DD-9626-47E2-8EF5-8F2F66751C9C}.Release|Any CPU.Build.0 = Release|Any CPU
{00117502-1661-4C8B-8C07-177C1A8AA455}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00117502-1661-4C8B-8C07-177C1A8AA455}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00117502-1661-4C8B-8C07-177C1A8AA455}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00117502-1661-4C8B-8C07-177C1A8AA455}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE