Implemented Gamelist

This commit is contained in:
emmaus 2018-06-17 09:37:34 +00:00
parent 71e1f0bda6
commit f1ffb129d6
15 changed files with 1611 additions and 16 deletions

View file

@ -1,8 +1,11 @@
using System;
using System.Drawing;
using System.IO;
using System.Text;
namespace Ryujinx.HLE.Loaders.Executables
{
class Nro : IExecutable
public class Nro : IExecutable
{
public string FilePath { get; private set; }
@ -15,10 +18,11 @@ namespace Ryujinx.HLE.Loaders.Executables
public int ROOffset { get; private set; }
public int DataOffset { get; private set; }
public int BssSize { get; private set; }
public int FileSize { get; private set; }
public Nro(Stream Input, string FilePath)
{
this.FilePath = FilePath;
this.FilePath = this.FilePath;
BinaryReader Reader = new BinaryReader(Input);
@ -39,11 +43,12 @@ namespace Ryujinx.HLE.Loaders.Executables
int DataSize = Reader.ReadInt32();
int BssSize = Reader.ReadInt32();
this.Mod0Offset = Mod0Offset;
this.TextOffset = TextOffset;
this.ROOffset = ROOffset;
this.DataOffset = DataOffset;
this.BssSize = BssSize;
this.Mod0Offset = Mod0Offset;
this.TextOffset = TextOffset;
this.ROOffset = ROOffset;
this.DataOffset = DataOffset;
this.BssSize = BssSize;
this.FileSize = FileSize;
byte[] Read(long Position, int Size)
{

View file

@ -43,6 +43,16 @@ namespace Ryujinx.HLE.Logging
EnabledClasses[(int)Class] = Enabled;
}
public bool IsEnabled(LogLevel LogLevel)
{
return EnabledLevels[(int)LogLevel];
}
public bool IsFiltered(LogClass LogClass)
{
return EnabledClasses[(int)LogClass];
}
internal void PrintDebug(LogClass Class, string Message, [CallerMemberName] string Caller = "")
{
Print(LogLevel.Debug, Class, GetFormattedMessage(Class, Message, Caller));

View file

@ -3,7 +3,7 @@ using System.IO;
namespace Ryujinx.HLE
{
class VirtualFileSystem : IDisposable
public class VirtualFileSystem : IDisposable
{
private const string BasePath = "RyuFs";
private const string NandPath = "nand";

View file

@ -1,4 +1,5 @@
using Ryujinx.HLE.Input;
using Ryujinx.HLE;
using Ryujinx.HLE.Input;
using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic;
@ -14,6 +15,8 @@ namespace Ryujinx
public static string IniPath { get; set; }
public static string DefaultGameDirectory { get; set; }
public static void Read(Logger Log)
{
string IniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
@ -92,6 +95,68 @@ namespace Ryujinx
ButtonZR = Convert.ToInt16(Parser.GetValue("Controls_Right_FakeJoycon_Button_ZR"))
}
};
DefaultGameDirectory = Parser.GetValue("Default_Game_Directory");
if (string.IsNullOrWhiteSpace(DefaultGameDirectory))
{
VirtualFileSystem FS = new HLE.VirtualFileSystem();
DefaultGameDirectory = Path.Combine(FS.GetSdCardPath(), "switch");
}
}
public static void Save(Logger Log)
{
IniParser Parser = new IniParser(IniPath);
Parser.SetValue("Enable_Memory_Checks", (!AOptimizations.DisableMemoryChecks).ToString());
Parser.SetValue("Logging_Enable_Debug", Log.IsEnabled(LogLevel.Debug).ToString());
Parser.SetValue("Logging_Enable_Stub", Log.IsEnabled(LogLevel.Stub).ToString());
Parser.SetValue("Logging_Enable_Info", Log.IsEnabled(LogLevel.Info).ToString());
Parser.SetValue("Logging_Enable_Warn", Log.IsEnabled(LogLevel.Warning).ToString());
Parser.SetValue("Logging_Enable_Error", Log.IsEnabled(LogLevel.Error).ToString());
List<string> FilteredClasses = new List<string>();
foreach(LogClass LogClass in Enum.GetValues(typeof(LogClass)))
{
if (Log.IsFiltered(LogClass))
FilteredClasses.Add(LogClass.ToString());
}
Parser.SetValue("Logging_Filtered_Classes", string.Join(',', FilteredClasses));
Parser.SetValue("Controls_Left_FakeJoycon_Stick_Up", FakeJoyCon.Left.StickUp.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_Stick_Down", FakeJoyCon.Left.StickDown.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_Stick_Left", FakeJoyCon.Left.StickLeft.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_Stick_Right", FakeJoyCon.Left.StickRight.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_Stick_Button", FakeJoyCon.Left.StickButton.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_DPad_Up", FakeJoyCon.Left.DPadUp.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_DPad_Down", FakeJoyCon.Left.DPadDown.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_DPad_Left", FakeJoyCon.Left.DPadLeft.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_DPad_Right", FakeJoyCon.Left.DPadRight.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_Button_Minus", FakeJoyCon.Left.ButtonMinus.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_Button_L", FakeJoyCon.Left.ButtonL.ToString());
Parser.SetValue("Controls_Left_FakeJoycon_Button_ZL", FakeJoyCon.Left.ButtonZL.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Stick_Up", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Stick_Down", FakeJoyCon.Right.StickDown.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Stick_Left", FakeJoyCon.Right.StickLeft.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Stick_Right", FakeJoyCon.Right.StickRight.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Stick_Button", FakeJoyCon.Right.StickButton.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Button_A", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Button_B", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Button_X", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Button_Y", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Button_Plus", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Button_R", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Controls_Right_FakeJoycon_Button_ZR", FakeJoyCon.Right.StickUp.ToString());
Parser.SetValue("Default_Game_Directory", DefaultGameDirectory);
Parser.Save();
}
}

View file

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Ryujinx.UI
{
public class ControlArchive
{
public LanguageEntry[] LanguageEntries { get; set; }
public long ApplicationTitleID { get; set; }
public long BaseTitleID { get; set; }
public long ProductCode { get; set; }
public string ApplicationVersion { get; set; }
public ControlArchive(Stream Input)
{
BinaryReader Reader = new BinaryReader(Input);
byte[] LanguageEntryData = Reader.ReadBytes(0x3000);
Input.Seek(0x3060, SeekOrigin.Begin);
ApplicationVersion = Encoding.ASCII.GetString(Reader.ReadBytes(0x10));
BaseTitleID = Reader.ReadInt64();
ApplicationTitleID = Reader.ReadInt64();
Input.Seek(0x30a8, SeekOrigin.Begin);
ProductCode = Reader.ReadInt64();
LanguageEntries = new LanguageEntry[16];
using (MemoryStream LanguageStream = new MemoryStream(LanguageEntryData))
{
BinaryReader LanguageReader = new BinaryReader(LanguageStream);
for (int index = 0; index < 16; index++)
{
LanguageEntries[index] = new LanguageEntry()
{
AplicationName = Encoding.ASCII.GetString(LanguageReader.ReadBytes(0x200)).Trim('\0'),
DeveloperName = Encoding.ASCII.GetString(LanguageReader.ReadBytes(0x100)).Trim('\0')
};
}
}
}
}
public struct LanguageEntry
{
public string AplicationName;
public string DeveloperName;
}
}

View file

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Ryujinx.HLE.Loaders;
namespace Ryujinx.UI
{
class Nro : HLE.Loaders.Executables.Nro
{
public byte[] AssetRomfData { get; set; }
public byte[] IconData { get; set; }
private byte[] NACPData { get; set; }
public int AssetOffset { get; set; }
public ControlArchive ControlArchive { get; set; }
public Nro(Stream Input, string Name) : base(Input, Name)
{
BinaryReader Reader = new BinaryReader(Input);
byte[] Read(long Position, int Size)
{
Input.Seek(Position, SeekOrigin.Begin);
return Reader.ReadBytes(Size);
}
if (Input.Length > FileSize)
{
AssetOffset = FileSize;
string AssetMagic = Encoding.ASCII.GetString(Read(AssetOffset, 4));
if (AssetMagic == "ASET")
{
Input.Seek(AssetOffset, SeekOrigin.Begin);
int AssetMagic0 = Reader.ReadInt32();
int AssetFormat = Reader.ReadInt32();
byte[] IconSectionInfo = Reader.ReadBytes(0x10);
byte[] NACPSectionInfo = Reader.ReadBytes(0x10);
byte[] AssetRomfSectionInfo = Reader.ReadBytes(0x10);
long IconOffset = BitConverter.ToInt64(IconSectionInfo, 0);
long IconSize = BitConverter.ToInt64(IconSectionInfo, 8);
long NACPOffset = BitConverter.ToInt64(NACPSectionInfo, 0);
long NACPSize = BitConverter.ToInt64(NACPSectionInfo, 8);
long RomfOffset = BitConverter.ToInt64(AssetRomfSectionInfo, 0);
long RomfSize = BitConverter.ToInt64(AssetRomfSectionInfo, 8);
Input.Seek(AssetOffset + IconOffset, SeekOrigin.Begin);
IconData = Reader.ReadBytes((int)IconSize);
Input.Seek(AssetOffset + NACPOffset, SeekOrigin.Begin);
NACPData = Reader.ReadBytes((int)NACPSize);
Input.Seek(AssetOffset + RomfOffset, SeekOrigin.Begin);
AssetRomfData = Reader.ReadBytes((int)RomfSize);
}
}
if (NACPData != null)
using (MemoryStream NACPStream = new MemoryStream(NACPData))
{
ControlArchive = new ControlArchive(NACPStream);
}
}
}
}

View file

@ -57,7 +57,7 @@ namespace Ryujinx.UI
private EmulationController EmulationController;
private Page CurrentPage = Page.PackageLoader;
private Page CurrentPage = Page.GameList;
private bool EscapePressed;
@ -74,7 +74,7 @@ namespace Ryujinx.UI
IGalRenderer Renderer;
IAalOutput AudioOut;
Switch Ns;
public static Switch Ns;
public EmulationWindow() : base("Test")
{
@ -107,7 +107,7 @@ namespace Ryujinx.UI
_deltaTime = (float)e.Time;
if (UIActive)
{
StartFrame();
StartFrame();
isRunning = false;
if (ShowMainUI)
{
@ -119,6 +119,7 @@ namespace Ryujinx.UI
showMainUI = false;
RenderPauseUI();
}
ImGuiNative.igShowMetricsWindow(ref UIActive);
EndFrame();
}
else
@ -347,6 +348,7 @@ namespace Ryujinx.UI
{
Configuration,
Emulation,
GameList,
PackageLoader
}

View file

@ -13,11 +13,16 @@ namespace Ryujinx.UI.Widgets
public static JoyCon CurrentJoyConLayout;
static Page CurrentPage = Page.General;
static bool ConfigIntialized = false;
static bool OpenFolderPicker;
static string CurrentPath;
static IniParser IniParser;
static FolderPicker FolderPicker;
static ConfigurationWidget()
{
IniParser = new IniParser(Config.IniPath);
FolderPicker = FolderPicker.GetFolderPicker("FolderDialog",Config.DefaultGameDirectory);
CurrentPath = Config.DefaultGameDirectory.ToString();
}
public static void Draw()
@ -54,6 +59,33 @@ namespace Ryujinx.UI.Widgets
if (ImGui.BeginChild("generalFrame", true, WindowFlags.AlwaysAutoResize))
{
ImGui.Text("General Emulation Settings");
ImGui.Spacing();
ImGui.LabelText("","Default Game Directory");
ImGui.SameLine();
if( ImGui.Selectable(Config.DefaultGameDirectory))
{
OpenFolderPicker = true;
}
if (OpenFolderPicker)
ImGui.OpenPopup("OpenFolder");
ImGui.SetNextWindowSize(new Vector2(500, 500), Condition.FirstUseEver);
if(ImGui.BeginPopupModal("OpenFolder",WindowFlags.NoResize))
{
string output = CurrentPath;
if (FolderPicker.Draw(ref output, false))
{
if (!string.IsNullOrWhiteSpace(output))
{
Config.DefaultGameDirectory = output;
}
ImGui.CloseCurrentPopup();
OpenFolderPicker = false;
}
ImGui.EndPopup();
}
ImGui.Spacing();
ImGui.Checkbox("Disable Cpu Memory Checks", ref AOptimizations.DisableMemoryChecks);
ImGui.EndChild();
@ -83,7 +115,7 @@ namespace Ryujinx.UI.Widgets
}
if (ImGui.Button("Save", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))
{
IniParser.Save();
Config.Save(EmulationWindow.Ns.Log);
}
ImGui.SameLine();
if (ImGui.Button("Discard", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))

View file

@ -0,0 +1,127 @@
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 FolderPicker
{
private const string FilePickerID = "###FilePicker";
private static readonly Dictionary<object, FolderPicker> s_folderPickers
= new Dictionary<object, FolderPicker>();
private static readonly Vector2 DefaultFilePickerSize = new Vector2(600, 400);
public string CurrentFolder { get; set; }
public string SelectedFile { get; set; }
public static FolderPicker GetFolderPicker(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_folderPickers.TryGetValue(o, out FolderPicker fp))
{
fp = new FolderPicker();
fp.CurrentFolder = startingPath;
s_folderPickers.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();
}
}
}
}
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,198 @@
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Text;
using ImGuiNET;
using System.Numerics;
using NanoJpeg;
using OpenTK.Graphics.OpenGL;
namespace Ryujinx.UI.Widgets
{
class GameList
{
static List<GameItem> GameItems = new List<GameItem>();
static GameItem SelectedGame;
static bool OpenFolderPicker;
static FolderPicker FolderPicker;
static string CurrentPath;
static GameList()
{
Refresh(Config.DefaultGameDirectory);
FolderPicker = FolderPicker.GetFolderPicker("FolderDialog", Config.DefaultGameDirectory);
}
public unsafe static void Refresh(string Path)
{
GameItems = new List<GameItem>();
foreach (string entry in Directory.EnumerateFileSystemEntries(Path))
{
if (File.Exists(entry))
{
string Extension = System.IO.Path.GetExtension(entry).ToLower();
if (Extension == ".nro" || Extension == ".nso")
{
GameItem GameItem = new GameItem(entry);
if (GameItem.IsNro && GameItem.HasIcon)
{
GameItem.TextureID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, GameItem.TextureID);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
NanoJpeg.NJImage image = new NJImage();
image.Decode(GameItem.GetIconData());
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, image.Width, image.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb,
PixelType.UnsignedByte, new IntPtr(image.Image));
image.Dispose();
GL.BindTexture(TextureTarget.Texture2D, 0);
}
GameItems.Add(GameItem);
}
}
else if (Directory.Exists(Path))
{
}
}
}
public unsafe static void DrawList()
{
uint id = 100;
if (ImGui.Button("Refresh GameList"))
Refresh(Config.DefaultGameDirectory);
ImGui.SameLine();
if(ImGui.Button("Select Game Directory"))
{
OpenFolderPicker = true;
}
if (OpenFolderPicker)
ImGui.OpenPopup("OpenFolder");
ImGui.SetNextWindowSize(new Vector2(500, 500), Condition.FirstUseEver);
if (ImGui.BeginPopupModal("OpenFolder", WindowFlags.NoResize))
{
string output = CurrentPath;
if (FolderPicker.Draw(ref output, false))
{
if (!string.IsNullOrWhiteSpace(output))
{
Config.DefaultGameDirectory = output;
Refresh(output);
}
ImGui.CloseCurrentPopup();
OpenFolderPicker = false;
}
ImGui.EndPopup();
}
if (ImGui.BeginChildFrame(20, ImGui.GetContentRegionAvailable(), WindowFlags.AlwaysAutoResize))
{
foreach (GameItem GameItem in GameItems)
{
id++;
if (GameItem == SelectedGame)
ImGui.PushStyleColor(ColorTarget.FrameBg, Values.Color.Yellow);
if (ImGui.BeginChildFrame(id, new Vector2(ImGui.GetContentRegionAvailableWidth(), 60)
, WindowFlags.AlwaysAutoResize))
{
if (GameItem.IsNro && GameItem.HasIcon)
{
ImGui.Image(new IntPtr(GameItem.TextureID), new Vector2(50, 50), new Vector2(0, 0),
new Vector2(1, 1), new Vector4(255, 255, 255, 255), new Vector4(0, 0, 0, 255));
}
else
{
ImGui.BeginChildFrame(id + 500, new Vector2(50, 50), WindowFlags.NoResize);
ImGui.EndChildFrame();
ImGui.SameLine();
ImGui.Text(Path.GetFileName(GameItem.Path));
}
ImGui.SameLine();
ImGuiNative.igBeginGroup();
if (GameItem.IsNro)
{
if (GameItem.Nro.ControlArchive != null)
{
ImGui.Text(GameItem.Nro.ControlArchive.LanguageEntries[0].AplicationName);
ImGui.Text(GameItem.Nro.ControlArchive.LanguageEntries[0].DeveloperName);
}
}
ImGuiNative.igEndGroup();
if (GameItem == SelectedGame)
ImGui.PopStyleColor();
if (ImGui.IsMouseDoubleClicked(0) && ImGui.IsItemHovered(HoveredFlags.AllowWhenOverlapped) && GameItem == SelectedGame)
{
}
else if (ImGui.IsMouseClicked(0) && ImGui.IsItemHovered(HoveredFlags.AllowWhenOverlapped | HoveredFlags.RootAndChildWindows))
{
SelectedGame = GameItem;
}
ImGui.EndChildFrame();
}
}
ImGui.EndChildFrame();
}
}
}
class GameItem
{
public AppletType AppletType;
public string Path;
public Nro Nro;
public bool IsNro;
public bool HasIcon => Nro?.IconData != null;
public int TextureID;
public GameItem(string Path)
{
this.Path = Path;
if (File.Exists(Path))
{
AppletType = AppletType.Homebrew;
FileInfo Package = new FileInfo(Path);
if (Package.Extension.ToLower() == ".nro")
{
IsNro = true;
Nro = new Nro(File.Open(Path, FileMode.Open), new FileInfo(Path).Name);
}
}
else
AppletType = AppletType.Cartridge;
}
public Bitmap GetBitmap()
{
if (IsNro)
{
return new Bitmap(new Bitmap(new MemoryStream(Nro.IconData)),new Size(50,50));
}
else return null;
}
public byte[] GetIconData()
{
if (IsNro)
{
return Nro.IconData;
}
else return null;
}
}
enum AppletType
{
Homebrew,
Cartridge
}
}

View file

@ -24,6 +24,12 @@ namespace Ryujinx.UI
CurrentPage = Page.PackageLoader;
}
if (ImGui.Button("Game List", new System.Numerics.Vector2(Values.ButtonWidth,
Values.ButtonHeight)))
{
CurrentPage = Page.GameList;
}
if (ImGui.Button("Settings", new System.Numerics.Vector2(Values.ButtonWidth,
Values.ButtonHeight)))
{
@ -54,6 +60,9 @@ namespace Ryujinx.UI
case Page.Configuration:
Widgets.ConfigurationWidget.Draw();
break;
case Page.GameList:
Widgets.GameList.DrawList();
break;
}
ImGui.EndChildFrame();
}

File diff suppressed because it is too large Load diff

View file

@ -172,7 +172,7 @@ namespace Ryujinx.UI
GL.EnableClientState(ArrayCap.ColorArray);
GL.Enable(EnableCap.Texture2D);
GL.UseProgram(1);
GL.UseProgram(0);
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
IO io = ImGui.GetIO();
@ -194,13 +194,16 @@ namespace Ryujinx.UI
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;
DrawVert vert0 = *((DrawVert*)vtx_buffer);
DrawVert vert1 = *(((DrawVert*)vtx_buffer) + 1);
DrawVert vert2 = *(((DrawVert*)vtx_buffer) + 2);
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));
@ -220,6 +223,8 @@ namespace Ryujinx.UI
(int)(io.DisplaySize.Y - pcmd->ClipRect.W),
(int)(pcmd->ClipRect.Z - pcmd->ClipRect.X),
(int)(pcmd->ClipRect.W - pcmd->ClipRect.Y));
ushort[] indices = new ushort[pcmd->ElemCount];
for (int i = 0; i < indices.Length; i++) { indices[i] = idx_buffer[i]; }
GL.DrawElements(PrimitiveType.Triangles, (int)pcmd->ElemCount, DrawElementsType.UnsignedShort, new IntPtr(idx_buffer));
}
idx_buffer += pcmd->ElemCount;

View file

@ -17,6 +17,7 @@
<ItemGroup>
<PackageReference Include="ImGui.NET" Version="0.4.5" />
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0" />
</ItemGroup>
<ItemGroup>

View file

@ -0,0 +1,8 @@
{
"profiles": {
"Ryujinx": {
"commandName": "Project",
"commandLineArgs": "\"C:\\Users\\Emmanuel Hansen\\AppData\\Roaming\\RyuFs\\sdmc\\switch\\fruity\\fruity.nro\""
}
}
}