diff --git a/Ryujinx/ApplicationLibrary.cs b/Ryujinx/ApplicationLibrary.cs new file mode 100644 index 0000000000..25f4233a0d --- /dev/null +++ b/Ryujinx/ApplicationLibrary.cs @@ -0,0 +1,108 @@ +using Ryujinx.Common.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; + +namespace Ryujinx +{ + public class ApplicationLibrary + { + public static Gdk.Pixbuf RyujinxROMIcon { get; private set; } + + public static List ApplicationLibraryData { get; private set; } + + public struct ApplicationData + { + public Gdk.Pixbuf Icon; + public string Game; + public string Version; + public string DLC; + public string TP; + public string LP; + public string Path; + } + + public static void Init() + { + using (Stream iconstream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.ryujinxROMIcon.png")) + using (StreamReader reader = new StreamReader(iconstream)) + { + RyujinxROMIcon = new Gdk.Pixbuf(iconstream); + } + + string dat = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "GameDirs.dat"); + if (File.Exists(dat) == false) { File.Create(dat).Close(); } + string[] GameDirs = File.ReadAllLines(dat); + List Games = new List(); + + foreach (string GameDir in GameDirs) + { + if (Directory.Exists(GameDir) == false) { Logger.PrintError(LogClass.Application, "There is an invalid game directory in \"GameDirs.dat\""); } + + DirectoryInfo GameDirInfo = new DirectoryInfo(GameDir); + foreach (var Game in GameDirInfo.GetFiles()) + { + if ((Path.GetExtension(Game.ToString()) == ".xci") || (Path.GetExtension(Game.ToString()) == ".nca") || (Path.GetExtension(Game.ToString()) == ".nsp") || (Path.GetExtension(Game.ToString()) == ".pfs0") || (Path.GetExtension(Game.ToString()) == ".nro") || (Path.GetExtension(Game.ToString()) == ".nso")) + { + Games.Add(Game.ToString()); + } + } + } + + ApplicationLibraryData = new List(); + foreach (string GamePath in Games) + { + ApplicationData data = new ApplicationData() + { + Icon = GetGameIcon(GamePath), + Game = (Path.GetExtension(GamePath) == ".nro") ? "Application" : "", + Version = "", + DLC = "", + TP = "", + LP = "", + Path = GamePath + }; + ApplicationLibraryData.Add(data); + } + } + + internal static Gdk.Pixbuf GetGameIcon(string filePath) + { + using (FileStream Input = File.Open(filePath, FileMode.Open, FileAccess.Read)) + { + BinaryReader Reader = new BinaryReader(Input); + + if (Path.GetExtension(filePath) == ".nro") + { + Input.Seek(24, SeekOrigin.Begin); + int AssetOffset = Reader.ReadInt32(); + + byte[] Read(long Position, int Size) + { + Input.Seek(Position, SeekOrigin.Begin); + return Reader.ReadBytes(Size); + } + + if (Encoding.ASCII.GetString(Read(AssetOffset, 4)) == "ASET") + { + byte[] IconSectionInfo = Read(AssetOffset + 8, 0x10); + + long IconOffset = BitConverter.ToInt64(IconSectionInfo, 0); + long IconSize = BitConverter.ToInt64(IconSectionInfo, 8); + + byte[] IconData = Read(AssetOffset + IconOffset, (int)IconSize); + + return new Gdk.Pixbuf(IconData, 50, 50); + } + else { return RyujinxROMIcon; } + } + else + { + return RyujinxROMIcon; //temp + } + } + } + } +} diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs index 7c9182052a..ee9bc4148c 100644 --- a/Ryujinx/Configuration.cs +++ b/Ryujinx/Configuration.cs @@ -183,6 +183,8 @@ namespace Ryujinx throw new InvalidOperationException("Configuration has not been loaded yet."); } + GeneralSettings.ConfigureSettings(Instance); + GraphicsConfig.ShadersDumpPath = Instance.GraphicsShadersDumpPath; Logger.AddTarget(new AsyncLogTargetWrapper( diff --git a/Ryujinx/GeneralSettings.cs b/Ryujinx/GeneralSettings.cs index b874ef632e..5fb5d45aa3 100644 --- a/Ryujinx/GeneralSettings.cs +++ b/Ryujinx/GeneralSettings.cs @@ -1,62 +1,79 @@ using Gtk; +using GUI = Gtk.Builder.ObjectAttribute; using System; using System.IO; -using System.Reflection; namespace Ryujinx { - public class GeneralSettings + public class GeneralSettings : Window { - public static void GeneralSettingsMenu() + internal HLE.Switch device { get; private set; } + + internal static Configuration SwitchConfig { get; private set; } + + //UI Controls + [GUI] CheckButton ErrorLogToggle; + [GUI] CheckButton WarningLogToggle; + [GUI] CheckButton InfoLogToggle; + [GUI] CheckButton StubLogToggle; + [GUI] CheckButton DebugLogToggle; + [GUI] CheckButton FileLogToggle; + [GUI] CheckButton DockedModeToggle; + [GUI] CheckButton DiscordToggle; + [GUI] CheckButton VSyncToggle; + [GUI] CheckButton MultiSchedToggle; + [GUI] CheckButton FSICToggle; + [GUI] CheckButton AggrToggle; + [GUI] CheckButton IgnoreToggle; + [GUI] ComboBoxText SystemLanguageSelect; + [GUI] TextView GameDirsBox; + [GUI] Button SaveButton; + [GUI] Button CancelButton; + + public GeneralSettings(HLE.Switch _device) : this(new Builder("Ryujinx.GeneralSettings.glade"), _device) { } + + private GeneralSettings(Builder builder, HLE.Switch _device) : base(builder.GetObject("GSWin").Handle) { - Window GSWin = new Window(WindowType.Toplevel); - GSWin.Title = "General Settings"; - GSWin.Resizable = false; - GSWin.WindowPosition = WindowPosition.Center; - GSWin.SetDefaultSize(854, 360); + device = _device; - VBox box = new VBox(false, 2); + builder.Autoconnect(this); - //Load Icon - using (Stream iconstream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.ryujinxIcon.png")) - using (StreamReader reader = new StreamReader(iconstream)) - { - Gdk.Pixbuf RyujinxIcon = new Gdk.Pixbuf(iconstream); - GSWin.Icon = RyujinxIcon; - } + SaveButton.Activated += Save_Activated; + CancelButton.Activated += Cancel_Activated; - //settings stuff will replace this block - Label myLabel = new Label { Text = "General Settings" }; - box.PackStart(myLabel, true, true, 3); + if (SwitchConfig.LoggingEnableError == true) { ErrorLogToggle.Click(); } + if (SwitchConfig.LoggingEnableWarn == true) { WarningLogToggle.Click(); } + if (SwitchConfig.LoggingEnableInfo == true) { InfoLogToggle.Click(); } + if (SwitchConfig.LoggingEnableStub == true) { StubLogToggle.Click(); } + if (SwitchConfig.LoggingEnableDebug == true) { DebugLogToggle.Click(); } + if (SwitchConfig.EnableFileLog == true) { FileLogToggle.Click(); } + if (SwitchConfig.DockedMode == true) { DockedModeToggle.Click(); } + if (SwitchConfig.EnableDiscordIntergration == true) { DiscordToggle.Click(); } + if (SwitchConfig.EnableVsync == true) { VSyncToggle.Click(); } + if (SwitchConfig.EnableMulticoreScheduling == true) { MultiSchedToggle.Click(); } + if (SwitchConfig.EnableFsIntegrityChecks == true) { FSICToggle.Click(); } + if (SwitchConfig.EnableAggressiveCpuOpts == true) { AggrToggle.Click(); } + if (SwitchConfig.IgnoreMissingServices == true) { IgnoreToggle.Click(); } + SystemLanguageSelect.SetActiveId(SwitchConfig.SystemLanguage.ToString()); - HBox ButtonBox = new HBox(true, 3); - Alignment BoxAlign = new Alignment(1, 0, 0, 0); - - Button Save = new Button("Save"); - Save.Pressed += (o, args) => Save_Pressed(o, args, GSWin); - ButtonBox.Add(Save); - - Button Cancel = new Button("Cancel"); - Cancel.Pressed += (o, args) => Cancel_Pressed(o, args, GSWin); - ButtonBox.Add(Cancel); - - BoxAlign.SetPadding(0, 5, 0, 7); - BoxAlign.Add(ButtonBox); - box.PackStart(BoxAlign, false, false, 3); - - GSWin.Add(box); - GSWin.ShowAll(); + GameDirsBox.Buffer.Text = File.ReadAllText("./GameDirs.dat"); } - static void Save_Pressed(object o, EventArgs args, Window window) + public static void ConfigureSettings(Configuration Instance) { SwitchConfig = Instance; } + + //Events + private void Save_Activated(object obj, EventArgs args) { - //save settings stuff will go here - window.Destroy(); + //Saving code is about to make this a BIG boi + + File.WriteAllText("./GameDirs.dat", GameDirsBox.Buffer.Text); + + Destroy(); } - static void Cancel_Pressed(object o, EventArgs args, Window window) + private void Cancel_Activated(object obj, EventArgs args) { - window.Destroy(); + Destroy(); } } } diff --git a/Ryujinx/GeneralSettings.glade b/Ryujinx/GeneralSettings.glade new file mode 100644 index 0000000000..bbc5b411f4 --- /dev/null +++ b/Ryujinx/GeneralSettings.glade @@ -0,0 +1,366 @@ + + + + + + False + 500 + ryujinxIcon.png + + + + + + True + False + vertical + + + True + False + vertical + + + True + False + Settings - Read Only + + + False + True + 0 + + + + + True + False + + + Enable Error Logs + True + True + False + True + + + 0 + 0 + + + + + Enable File Log + True + True + False + True + + + 0 + 1 + + + + + Enable FS Integrity Checks + True + True + False + True + + + 0 + 2 + + + + + Enable Aggressive CPU Options + True + True + False + True + + + 1 + 2 + + + + + Enable Docked Mode + True + True + False + True + + + 1 + 1 + + + + + Enable Warning Logs + True + True + False + True + + + 1 + 0 + + + + + Enable Info Logs + True + True + False + True + + + 2 + 0 + + + + + Enable Discord Integration + True + True + False + True + + + 2 + 1 + + + + + Ignore Missing Services + True + True + False + True + + + 2 + 2 + + + + + Enable VSync + True + True + False + True + + + 3 + 1 + + + + + Enable Stub Logs + True + True + False + True + + + 3 + 0 + + + + + Enable Debug Logs + True + True + False + True + + + 4 + 0 + + + + + Enable Multicore Scheduling + True + True + False + True + + + 4 + 1 + + + + + True + False + + American English + British English + Canadian French + Chinese + Dutch + French + German + Italian + Japanese + Korean + Latin American Spanish + Portuguese + Russian + Simplified Chinese + Spanish + Taiwanese + Traditional Chinese + + + + 4 + 2 + + + + + True + False + System Language: + + + 3 + 2 + + + + + False + True + 1 + + + + + True + True + 0 + + + + + True + False + + + False + True + 1 + + + + + True + False + vertical + + + True + False + Game Directories + + + False + True + 0 + + + + + True + True + in + + + True + True + + + + + True + True + 1 + + + + + True + False + + + True + False + gtk-discard + + + True + True + 0 + + + + + Save + True + True + True + + + False + True + 1 + + + + + Cancel + True + True + True + + + False + True + 2 + + + + + False + True + 2 + + + + + True + True + 2 + + + + + + diff --git a/Ryujinx/MainMenu.cs b/Ryujinx/MainMenu.cs index 87eb6bb579..1aac7d0f67 100644 --- a/Ryujinx/MainMenu.cs +++ b/Ryujinx/MainMenu.cs @@ -4,7 +4,6 @@ using Ryujinx.Common.Logging; using System; using System.IO; using System.Reflection; -using System.Text; namespace Ryujinx { @@ -12,28 +11,22 @@ namespace Ryujinx { internal HLE.Switch device { get; private set; } - internal ListStore TableStore { get; private set; } + internal Application gtkapp { get; private set; } - internal static Gdk.Pixbuf RyujinxIcon { get; private set; } + internal ListStore TableStore { get; private set; } //UI Controls [GUI] Window MainWin; - [GUI] MenuBar MenuBar; - [GUI] MenuItem LoadApplicationFile; - [GUI] MenuItem LoadApplicationFolder; - [GUI] MenuItem Exit; - [GUI] MenuItem GeneralSettingsMenu; - [GUI] MenuItem ControlSettingsMenu; [GUI] MenuItem NFC; [GUI] MenuItem Debugger; - [GUI] MenuItem About; [GUI] TreeView GameTable; - public MainMenu(HLE.Switch _device) : this(new Builder("Ryujinx.MainMenu.glade"), _device) { } + public MainMenu(HLE.Switch _device, Application _gtkapp) : this(new Builder("Ryujinx.MainMenu.glade"), _device, _gtkapp) { } - private MainMenu(Builder builder, HLE.Switch _device) : base(builder.GetObject("MainWin").Handle) + private MainMenu(Builder builder, HLE.Switch _device, Application _gtkapp) : base(builder.GetObject("MainWin").Handle) { device = _device; + gtkapp = _gtkapp; if (device.System.State.DiscordIntergrationEnabled == true) { @@ -47,14 +40,6 @@ namespace Ryujinx builder.Autoconnect(this); ApplyTheme(); - //Load Icon - using (Stream iconstream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.ryujinxIcon.png")) - using (StreamReader reader = new StreamReader(iconstream)) - { - RyujinxIcon = new Gdk.Pixbuf(iconstream); - MainWin.Icon = RyujinxIcon; - } - DeleteEvent += Window_Close; //disable some buttons @@ -63,41 +48,18 @@ namespace Ryujinx //Games grid thing GameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 0); - GameTable.AppendColumn("Game", new CellRendererText(), "text" , 1); - GameTable.AppendColumn("Version", new CellRendererText(), "text" , 2); - GameTable.AppendColumn("DLC", new CellRendererText(), "text" , 3); - GameTable.AppendColumn("Time Played", new CellRendererText(), "text" , 4); - GameTable.AppendColumn("Last Played", new CellRendererText(), "text" , 5); - GameTable.AppendColumn("Path", new CellRendererText(), "text" , 6); - - string dat = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "GameDirs.dat"); - - if (File.Exists(dat) == false) { File.Create(dat).Close(); } - - string[] GameDirs = File.ReadAllLines(dat); - string[] Games = new string[] { }; - - foreach (string GameDir in GameDirs) - { - if (Directory.Exists(GameDir) == false) { Logger.PrintError(LogClass.Application, "There is an invalid game directory in \"GameDirs.dat\""); return; } - - DirectoryInfo GameDirInfo = new DirectoryInfo(GameDir); - foreach (var Game in GameDirInfo.GetFiles()) - { - if ((System.IO.Path.GetExtension(Game.ToString()) == ".xci") || (System.IO.Path.GetExtension(Game.ToString()) == ".nca") || (System.IO.Path.GetExtension(Game.ToString()) == ".nsp") || (System.IO.Path.GetExtension(Game.ToString()) == ".pfs0") || (System.IO.Path.GetExtension(Game.ToString()) == ".nro") || (System.IO.Path.GetExtension(Game.ToString()) == ".nso")) - { - Array.Resize(ref Games, Games.Length + 1); - Games[Games.Length - 1] = Game.ToString(); - } - } - } + GameTable.AppendColumn("Game", new CellRendererText(), "text", 1); + GameTable.AppendColumn("Version", new CellRendererText(), "text", 2); + GameTable.AppendColumn("DLC", new CellRendererText(), "text", 3); + GameTable.AppendColumn("Time Played", new CellRendererText(), "text", 4); + GameTable.AppendColumn("Last Played", new CellRendererText(), "text", 5); + GameTable.AppendColumn("Path", new CellRendererText(), "text", 6); TableStore = new ListStore(typeof(Gdk.Pixbuf), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string)); - foreach (string GamePath in Games) + foreach (ApplicationLibrary.ApplicationData AppData in ApplicationLibrary.ApplicationLibraryData) { - Gdk.Pixbuf GameIcon = GetIconData(GamePath); - TableStore.AppendValues(GameIcon, "", "", "", "", "", GamePath); + TableStore.AppendValues(AppData.Icon, AppData.Game, AppData.Version, AppData.DLC, AppData.TP, AppData.LP, AppData.Path); } GameTable.Model = TableStore; @@ -115,43 +77,6 @@ namespace Ryujinx StyleContext.AddProviderForScreen(Gdk.Screen.Default, css_provider, 800); } - public static Gdk.Pixbuf GetIconData(string filePath) - { - using (FileStream Input = File.Open(filePath, FileMode.Open, FileAccess.Read)) - { - BinaryReader Reader = new BinaryReader(Input); - - if (System.IO.Path.GetExtension(filePath) == ".nro") - { - Input.Seek(24, SeekOrigin.Begin); - int AssetOffset = Reader.ReadInt32(); - - byte[] Read(long Position, int Size) - { - Input.Seek(Position, SeekOrigin.Begin); - return Reader.ReadBytes(Size); - } - - if (Encoding.ASCII.GetString(Read(AssetOffset, 4)) == "ASET") - { - byte[] IconSectionInfo = Read(AssetOffset + 8, 0x10); - - long IconOffset = BitConverter.ToInt64(IconSectionInfo, 0); - long IconSize = BitConverter.ToInt64(IconSectionInfo, 8); - - byte[] IconData = Read(AssetOffset + IconOffset, (int)IconSize); - - return new Gdk.Pixbuf(IconData, 50, 50); - } - else { return RyujinxIcon; } - } - else - { - return RyujinxIcon; //temp - } - } - } - //Events private void Row_Activated(object obj, RowActivatedArgs args) { @@ -269,7 +194,12 @@ namespace Ryujinx private void General_Settings_Pressed(object o, EventArgs args) { - GeneralSettings.GeneralSettingsMenu(); + var resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); + var GSWin = new GeneralSettings(device); + + gtkapp.Register(GLib.Cancellable.Current); + gtkapp.AddWindow(GSWin); + GSWin.Show(); } private void Control_Settings_Pressed(object o, EventArgs args) @@ -299,7 +229,7 @@ namespace Ryujinx { AboutDialog about = new AboutDialog(); about.ProgramName = "Ryujinx"; - about.Icon = RyujinxIcon; + about.Icon = new Gdk.Pixbuf("./ryujinxIcon"); about.Version = "Version x.x.x"; about.Authors = new string[] { "gdkchan", "Ac_K", "LDj3SNuD", "emmauss", "MerryMage", "MS-DOS1999", "Thog", "jD", "BaronKiko", "Dr.Hacknik", "Lordmau5", "(and Xpl0itR did a bit of work too :D)" }; about.Copyright = "Unlicense"; diff --git a/Ryujinx/MainMenu.glade b/Ryujinx/MainMenu.glade index afc9708b43..cd87a8a387 100644 --- a/Ryujinx/MainMenu.glade +++ b/Ryujinx/MainMenu.glade @@ -8,6 +8,7 @@ center 1280 745 + ryujinxIcon.png center diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs index a414e49630..8df339747c 100644 --- a/Ryujinx/Program.cs +++ b/Ryujinx/Program.cs @@ -35,6 +35,8 @@ namespace Ryujinx Profile.Initialize(); + ApplicationLibrary.Init(); + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; @@ -59,11 +61,11 @@ namespace Ryujinx Gtk.Application.Init(); var resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); - var app = new Gtk.Application("Ryujinx.Ryujinx", GLib.ApplicationFlags.None); - var win = new MainMenu(device); + var gtkapp = new Gtk.Application("Ryujinx.Ryujinx", GLib.ApplicationFlags.None); + var win = new MainMenu(device, gtkapp); - app.Register(GLib.Cancellable.Current); - app.AddWindow(win); + gtkapp.Register(GLib.Cancellable.Current); + gtkapp.AddWindow(win); win.Show(); Gtk.Application.Run(); diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index 3e6e97022b..3499a53c8b 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -19,8 +19,9 @@ + - + @@ -45,6 +46,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Ryujinx/ryujinxROMIcon.png b/Ryujinx/ryujinxROMIcon.png new file mode 100644 index 0000000000..afdec7c787 Binary files /dev/null and b/Ryujinx/ryujinxROMIcon.png differ