[
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n**/Properties/launchSettings.json\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk \n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n# CodeRush\n.cr/\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output \nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder \n.mfractor/\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 ChendoChap\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Main.Designer.cs",
    "content": "﻿namespace PS4Saves\n{\n    partial class Main\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.components = new System.ComponentModel.Container();\n            this.ipTextBox = new System.Windows.Forms.TextBox();\n            this.connectButton = new System.Windows.Forms.Button();\n            this.setupButton = new System.Windows.Forms.Button();\n            this.userComboBox = new System.Windows.Forms.ComboBox();\n            this.dirsComboBox = new System.Windows.Forms.ComboBox();\n            this.searchButton = new System.Windows.Forms.Button();\n            this.mountButton = new System.Windows.Forms.Button();\n            this.unmountButton = new System.Windows.Forms.Button();\n            this.connectionGroupBox = new System.Windows.Forms.GroupBox();\n            this.getGamesButton = new System.Windows.Forms.Button();\n            this.gamesComboBox = new System.Windows.Forms.ComboBox();\n            this.payloadButton = new System.Windows.Forms.Button();\n            this.ipLabel = new System.Windows.Forms.Label();\n            this.createGroupBox = new System.Windows.Forms.GroupBox();\n            this.sizeLabel = new System.Windows.Forms.Label();\n            this.sizeTrackBar = new System.Windows.Forms.TrackBar();\n            this.nameLabel = new System.Windows.Forms.Label();\n            this.nameTextBox = new System.Windows.Forms.TextBox();\n            this.createButton = new System.Windows.Forms.Button();\n            this.mountGroupBox = new System.Windows.Forms.GroupBox();\n            this.infoGroupBox = new System.Windows.Forms.GroupBox();\n            this.dateTextBox = new System.Windows.Forms.TextBox();\n            this.dateLabel = new System.Windows.Forms.Label();\n            this.detailsTextBox = new System.Windows.Forms.TextBox();\n            this.detailsLabel = new System.Windows.Forms.Label();\n            this.subtitleTextBox = new System.Windows.Forms.TextBox();\n            this.subtitleLabel = new System.Windows.Forms.Label();\n            this.titleTextBox = new System.Windows.Forms.TextBox();\n            this.titleLabel = new System.Windows.Forms.Label();\n            this.sizeToolTip = new System.Windows.Forms.ToolTip(this.components);\n            this.statusLabel = new System.Windows.Forms.Label();\n            this.connectionGroupBox.SuspendLayout();\n            this.createGroupBox.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.sizeTrackBar)).BeginInit();\n            this.mountGroupBox.SuspendLayout();\n            this.infoGroupBox.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // ipTextBox\n            // \n            this.ipTextBox.Location = new System.Drawing.Point(70, 19);\n            this.ipTextBox.Name = \"ipTextBox\";\n            this.ipTextBox.Size = new System.Drawing.Size(117, 20);\n            this.ipTextBox.TabIndex = 0;\n            // \n            // connectButton\n            // \n            this.connectButton.Location = new System.Drawing.Point(284, 19);\n            this.connectButton.Name = \"connectButton\";\n            this.connectButton.Size = new System.Drawing.Size(90, 20);\n            this.connectButton.TabIndex = 2;\n            this.connectButton.Text = \"Connect\";\n            this.connectButton.UseVisualStyleBackColor = true;\n            this.connectButton.Click += new System.EventHandler(this.connectButton_Click);\n            // \n            // setupButton\n            // \n            this.setupButton.Location = new System.Drawing.Point(7, 45);\n            this.setupButton.Name = \"setupButton\";\n            this.setupButton.Size = new System.Drawing.Size(181, 21);\n            this.setupButton.TabIndex = 3;\n            this.setupButton.Text = \"Setup\";\n            this.setupButton.UseVisualStyleBackColor = true;\n            this.setupButton.Click += new System.EventHandler(this.setupButton_Click);\n            // \n            // userComboBox\n            // \n            this.userComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.userComboBox.FormattingEnabled = true;\n            this.userComboBox.Location = new System.Drawing.Point(193, 45);\n            this.userComboBox.Name = \"userComboBox\";\n            this.userComboBox.Size = new System.Drawing.Size(181, 21);\n            this.userComboBox.TabIndex = 4;\n            this.userComboBox.SelectedIndexChanged += new System.EventHandler(this.userComboBox_SelectedIndexChanged);\n            // \n            // dirsComboBox\n            // \n            this.dirsComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.dirsComboBox.FormattingEnabled = true;\n            this.dirsComboBox.Location = new System.Drawing.Point(193, 19);\n            this.dirsComboBox.Name = \"dirsComboBox\";\n            this.dirsComboBox.Size = new System.Drawing.Size(180, 21);\n            this.dirsComboBox.TabIndex = 1;\n            this.dirsComboBox.SelectedIndexChanged += new System.EventHandler(this.dirsComboBox_SelectedIndexChanged);\n            // \n            // searchButton\n            // \n            this.searchButton.Location = new System.Drawing.Point(6, 19);\n            this.searchButton.Name = \"searchButton\";\n            this.searchButton.Size = new System.Drawing.Size(181, 21);\n            this.searchButton.TabIndex = 0;\n            this.searchButton.Text = \"Search\";\n            this.searchButton.UseVisualStyleBackColor = true;\n            this.searchButton.Click += new System.EventHandler(this.searchButton_Click);\n            // \n            // mountButton\n            // \n            this.mountButton.Location = new System.Drawing.Point(6, 48);\n            this.mountButton.Name = \"mountButton\";\n            this.mountButton.Size = new System.Drawing.Size(181, 23);\n            this.mountButton.TabIndex = 2;\n            this.mountButton.Text = \"Mount\";\n            this.mountButton.UseVisualStyleBackColor = true;\n            this.mountButton.Click += new System.EventHandler(this.mountButton_Click);\n            // \n            // unmountButton\n            // \n            this.unmountButton.Location = new System.Drawing.Point(192, 48);\n            this.unmountButton.Name = \"unmountButton\";\n            this.unmountButton.Size = new System.Drawing.Size(181, 23);\n            this.unmountButton.TabIndex = 3;\n            this.unmountButton.Text = \"Unmount\";\n            this.unmountButton.UseVisualStyleBackColor = true;\n            this.unmountButton.Click += new System.EventHandler(this.unmountButton_Click);\n            // \n            // connectionGroupBox\n            // \n            this.connectionGroupBox.Controls.Add(this.getGamesButton);\n            this.connectionGroupBox.Controls.Add(this.gamesComboBox);\n            this.connectionGroupBox.Controls.Add(this.payloadButton);\n            this.connectionGroupBox.Controls.Add(this.ipLabel);\n            this.connectionGroupBox.Controls.Add(this.ipTextBox);\n            this.connectionGroupBox.Controls.Add(this.connectButton);\n            this.connectionGroupBox.Controls.Add(this.setupButton);\n            this.connectionGroupBox.Controls.Add(this.userComboBox);\n            this.connectionGroupBox.Location = new System.Drawing.Point(7, 12);\n            this.connectionGroupBox.Name = \"connectionGroupBox\";\n            this.connectionGroupBox.Size = new System.Drawing.Size(379, 105);\n            this.connectionGroupBox.TabIndex = 0;\n            this.connectionGroupBox.TabStop = false;\n            this.connectionGroupBox.Text = \"Connection\";\n            // \n            // getGamesButton\n            // \n            this.getGamesButton.Location = new System.Drawing.Point(6, 72);\n            this.getGamesButton.Name = \"getGamesButton\";\n            this.getGamesButton.Size = new System.Drawing.Size(181, 21);\n            this.getGamesButton.TabIndex = 5;\n            this.getGamesButton.Text = \"Get Games\";\n            this.getGamesButton.UseVisualStyleBackColor = true;\n            this.getGamesButton.Click += new System.EventHandler(this.getGamesButton_Click);\n            // \n            // gamesComboBox\n            // \n            this.gamesComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.gamesComboBox.FormattingEnabled = true;\n            this.gamesComboBox.Location = new System.Drawing.Point(192, 72);\n            this.gamesComboBox.Name = \"gamesComboBox\";\n            this.gamesComboBox.Size = new System.Drawing.Size(181, 21);\n            this.gamesComboBox.TabIndex = 6;\n            this.gamesComboBox.SelectedIndexChanged += new System.EventHandler(this.gamesComboBox_SelectedIndexChanged);\n            // \n            // payloadButton\n            // \n            this.payloadButton.Location = new System.Drawing.Point(192, 19);\n            this.payloadButton.Name = \"payloadButton\";\n            this.payloadButton.Size = new System.Drawing.Size(90, 20);\n            this.payloadButton.TabIndex = 1;\n            this.payloadButton.Text = \"Send Payload\";\n            this.payloadButton.UseVisualStyleBackColor = true;\n            this.payloadButton.Click += new System.EventHandler(this.payloadButton_Click);\n            // \n            // ipLabel\n            // \n            this.ipLabel.AutoSize = true;\n            this.ipLabel.Location = new System.Drawing.Point(6, 22);\n            this.ipLabel.Name = \"ipLabel\";\n            this.ipLabel.Size = new System.Drawing.Size(58, 13);\n            this.ipLabel.TabIndex = 6;\n            this.ipLabel.Text = \"ip address:\";\n            // \n            // createGroupBox\n            // \n            this.createGroupBox.Controls.Add(this.sizeLabel);\n            this.createGroupBox.Controls.Add(this.sizeTrackBar);\n            this.createGroupBox.Controls.Add(this.nameLabel);\n            this.createGroupBox.Controls.Add(this.nameTextBox);\n            this.createGroupBox.Controls.Add(this.createButton);\n            this.createGroupBox.Location = new System.Drawing.Point(7, 210);\n            this.createGroupBox.Name = \"createGroupBox\";\n            this.createGroupBox.Size = new System.Drawing.Size(379, 129);\n            this.createGroupBox.TabIndex = 2;\n            this.createGroupBox.TabStop = false;\n            this.createGroupBox.Text = \"Create New Saves\";\n            // \n            // sizeLabel\n            // \n            this.sizeLabel.AutoSize = true;\n            this.sizeLabel.Location = new System.Drawing.Point(6, 48);\n            this.sizeLabel.Name = \"sizeLabel\";\n            this.sizeLabel.Size = new System.Drawing.Size(76, 13);\n            this.sizeLabel.TabIndex = 9;\n            this.sizeLabel.Text = \"max save size:\";\n            // \n            // sizeTrackBar\n            // \n            this.sizeTrackBar.Location = new System.Drawing.Point(117, 48);\n            this.sizeTrackBar.Maximum = 32768;\n            this.sizeTrackBar.Minimum = 96;\n            this.sizeTrackBar.Name = \"sizeTrackBar\";\n            this.sizeTrackBar.Size = new System.Drawing.Size(257, 45);\n            this.sizeTrackBar.TabIndex = 1;\n            this.sizeTrackBar.Value = 96;\n            this.sizeTrackBar.Scroll += new System.EventHandler(this.sizeTrackBar_Scroll);\n            // \n            // nameLabel\n            // \n            this.nameLabel.AutoSize = true;\n            this.nameLabel.Location = new System.Drawing.Point(6, 25);\n            this.nameLabel.Name = \"nameLabel\";\n            this.nameLabel.Size = new System.Drawing.Size(105, 13);\n            this.nameLabel.TabIndex = 7;\n            this.nameLabel.Text = \"save directory name:\";\n            // \n            // nameTextBox\n            // \n            this.nameTextBox.Location = new System.Drawing.Point(117, 22);\n            this.nameTextBox.MaxLength = 31;\n            this.nameTextBox.Name = \"nameTextBox\";\n            this.nameTextBox.Size = new System.Drawing.Size(256, 20);\n            this.nameTextBox.TabIndex = 0;\n            // \n            // createButton\n            // \n            this.createButton.Location = new System.Drawing.Point(5, 99);\n            this.createButton.Name = \"createButton\";\n            this.createButton.Size = new System.Drawing.Size(367, 23);\n            this.createButton.TabIndex = 2;\n            this.createButton.Text = \"Create Save\";\n            this.createButton.UseVisualStyleBackColor = true;\n            this.createButton.Click += new System.EventHandler(this.createButton_Click);\n            // \n            // mountGroupBox\n            // \n            this.mountGroupBox.Controls.Add(this.searchButton);\n            this.mountGroupBox.Controls.Add(this.dirsComboBox);\n            this.mountGroupBox.Controls.Add(this.mountButton);\n            this.mountGroupBox.Controls.Add(this.unmountButton);\n            this.mountGroupBox.Location = new System.Drawing.Point(7, 123);\n            this.mountGroupBox.Name = \"mountGroupBox\";\n            this.mountGroupBox.Size = new System.Drawing.Size(379, 81);\n            this.mountGroupBox.TabIndex = 1;\n            this.mountGroupBox.TabStop = false;\n            this.mountGroupBox.Text = \"Mount Existing Saves\";\n            // \n            // infoGroupBox\n            // \n            this.infoGroupBox.Controls.Add(this.dateTextBox);\n            this.infoGroupBox.Controls.Add(this.dateLabel);\n            this.infoGroupBox.Controls.Add(this.detailsTextBox);\n            this.infoGroupBox.Controls.Add(this.detailsLabel);\n            this.infoGroupBox.Controls.Add(this.subtitleTextBox);\n            this.infoGroupBox.Controls.Add(this.subtitleLabel);\n            this.infoGroupBox.Controls.Add(this.titleTextBox);\n            this.infoGroupBox.Controls.Add(this.titleLabel);\n            this.infoGroupBox.Location = new System.Drawing.Point(392, 12);\n            this.infoGroupBox.Name = \"infoGroupBox\";\n            this.infoGroupBox.Size = new System.Drawing.Size(396, 327);\n            this.infoGroupBox.TabIndex = 3;\n            this.infoGroupBox.TabStop = false;\n            this.infoGroupBox.Text = \"Save Info\";\n            // \n            // dateTextBox\n            // \n            this.dateTextBox.Location = new System.Drawing.Point(9, 294);\n            this.dateTextBox.Name = \"dateTextBox\";\n            this.dateTextBox.ReadOnly = true;\n            this.dateTextBox.Size = new System.Drawing.Size(381, 20);\n            this.dateTextBox.TabIndex = 3;\n            // \n            // dateLabel\n            // \n            this.dateLabel.AutoSize = true;\n            this.dateLabel.Location = new System.Drawing.Point(6, 278);\n            this.dateLabel.Name = \"dateLabel\";\n            this.dateLabel.Size = new System.Drawing.Size(31, 13);\n            this.dateLabel.TabIndex = 6;\n            this.dateLabel.Text = \"date:\";\n            // \n            // detailsTextBox\n            // \n            this.detailsTextBox.Location = new System.Drawing.Point(9, 166);\n            this.detailsTextBox.Multiline = true;\n            this.detailsTextBox.Name = \"detailsTextBox\";\n            this.detailsTextBox.ReadOnly = true;\n            this.detailsTextBox.Size = new System.Drawing.Size(381, 109);\n            this.detailsTextBox.TabIndex = 2;\n            // \n            // detailsLabel\n            // \n            this.detailsLabel.AutoSize = true;\n            this.detailsLabel.Location = new System.Drawing.Point(6, 150);\n            this.detailsLabel.Name = \"detailsLabel\";\n            this.detailsLabel.Size = new System.Drawing.Size(40, 13);\n            this.detailsLabel.TabIndex = 4;\n            this.detailsLabel.Text = \"details:\";\n            // \n            // subtitleTextBox\n            // \n            this.subtitleTextBox.Location = new System.Drawing.Point(9, 101);\n            this.subtitleTextBox.Multiline = true;\n            this.subtitleTextBox.Name = \"subtitleTextBox\";\n            this.subtitleTextBox.ReadOnly = true;\n            this.subtitleTextBox.Size = new System.Drawing.Size(381, 46);\n            this.subtitleTextBox.TabIndex = 1;\n            // \n            // subtitleLabel\n            // \n            this.subtitleLabel.AutoSize = true;\n            this.subtitleLabel.Location = new System.Drawing.Point(6, 85);\n            this.subtitleLabel.Name = \"subtitleLabel\";\n            this.subtitleLabel.Size = new System.Drawing.Size(43, 13);\n            this.subtitleLabel.TabIndex = 2;\n            this.subtitleLabel.Text = \"subtitle:\";\n            // \n            // titleTextBox\n            // \n            this.titleTextBox.Location = new System.Drawing.Point(9, 35);\n            this.titleTextBox.Multiline = true;\n            this.titleTextBox.Name = \"titleTextBox\";\n            this.titleTextBox.ReadOnly = true;\n            this.titleTextBox.Size = new System.Drawing.Size(381, 47);\n            this.titleTextBox.TabIndex = 0;\n            // \n            // titleLabel\n            // \n            this.titleLabel.AutoSize = true;\n            this.titleLabel.Location = new System.Drawing.Point(6, 19);\n            this.titleLabel.Name = \"titleLabel\";\n            this.titleLabel.Size = new System.Drawing.Size(26, 13);\n            this.titleLabel.TabIndex = 0;\n            this.titleLabel.Text = \"title:\";\n            // \n            // statusLabel\n            // \n            this.statusLabel.AutoSize = true;\n            this.statusLabel.Location = new System.Drawing.Point(4, 342);\n            this.statusLabel.Name = \"statusLabel\";\n            this.statusLabel.Size = new System.Drawing.Size(40, 13);\n            this.statusLabel.TabIndex = 13;\n            this.statusLabel.Text = \"Status:\";\n            // \n            // Main\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.ClientSize = new System.Drawing.Size(797, 362);\n            this.Controls.Add(this.statusLabel);\n            this.Controls.Add(this.infoGroupBox);\n            this.Controls.Add(this.mountGroupBox);\n            this.Controls.Add(this.createGroupBox);\n            this.Controls.Add(this.connectionGroupBox);\n            this.Name = \"Main\";\n            this.Text = \"Playstation 4 Save Mounter 1.5 [ps4debug]\";\n            this.connectionGroupBox.ResumeLayout(false);\n            this.connectionGroupBox.PerformLayout();\n            this.createGroupBox.ResumeLayout(false);\n            this.createGroupBox.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.sizeTrackBar)).EndInit();\n            this.mountGroupBox.ResumeLayout(false);\n            this.infoGroupBox.ResumeLayout(false);\n            this.infoGroupBox.PerformLayout();\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.TextBox ipTextBox;\n        private System.Windows.Forms.Button connectButton;\n        private System.Windows.Forms.Button setupButton;\n        private System.Windows.Forms.ComboBox userComboBox;\n        private System.Windows.Forms.ComboBox dirsComboBox;\n        private System.Windows.Forms.Button searchButton;\n        private System.Windows.Forms.Button mountButton;\n        private System.Windows.Forms.Button unmountButton;\n        private System.Windows.Forms.GroupBox connectionGroupBox;\n        private System.Windows.Forms.Label ipLabel;\n        private System.Windows.Forms.GroupBox createGroupBox;\n        private System.Windows.Forms.TextBox nameTextBox;\n        private System.Windows.Forms.Button createButton;\n        private System.Windows.Forms.GroupBox mountGroupBox;\n        private System.Windows.Forms.GroupBox infoGroupBox;\n        private System.Windows.Forms.Label nameLabel;\n        private System.Windows.Forms.TrackBar sizeTrackBar;\n        private System.Windows.Forms.Label sizeLabel;\n        private System.Windows.Forms.ToolTip sizeToolTip;\n        private System.Windows.Forms.Label statusLabel;\n        private System.Windows.Forms.TextBox dateTextBox;\n        private System.Windows.Forms.Label dateLabel;\n        private System.Windows.Forms.TextBox detailsTextBox;\n        private System.Windows.Forms.Label detailsLabel;\n        private System.Windows.Forms.TextBox subtitleTextBox;\n        private System.Windows.Forms.Label subtitleLabel;\n        private System.Windows.Forms.TextBox titleTextBox;\n        private System.Windows.Forms.Label titleLabel;\n        private System.Windows.Forms.Button payloadButton;\n        private System.Windows.Forms.Button getGamesButton;\n        private System.Windows.Forms.ComboBox gamesComboBox;\n    }\n}\n\n"
  },
  {
    "path": "Main.cs",
    "content": "﻿using libdebug;\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing System.Windows.Forms;\n\nnamespace PS4Saves\n{\n    public partial class Main : Form\n    {\n        PS4DBG ps4 = new PS4DBG();\n        private int pid;\n        private ulong stub;\n        private ulong libSceUserServiceBase = 0x0;\n        private ulong libSceSaveDataBase = 0x0;\n        private ulong executableBase = 0x0;\n        private ulong libSceLibcInternalBase = 0x0;\n        private ulong GetSaveDirectoriesAddr = 0;\n        private ulong GetUsersAddr = 0;\n        private int user = 0x0;\n        private string selectedGame = null;\n        string mp = \"\";\n        bool log = false;\n        \n        public Main()\n        {\n            InitializeComponent();\n            string[] args = Environment.GetCommandLineArgs();\n            if (args.Length == 2 && args[1] == \"-log\")\n            {\n                log = true;\n            }\n\n            if (File.Exists(\"ip\"))\n            {\n                ipTextBox.Text = File.ReadAllText(\"ip\");\n            }\n        }\n        public static string FormatSize(double size)\n        {\n            const long BytesInKilobytes = 1024;\n            const long BytesInMegabytes = BytesInKilobytes * 1024;\n            const long BytesInGigabytes = BytesInMegabytes * 1024;\n            double value;\n            string str;\n            if (size < BytesInGigabytes)\n            {\n                value = size / BytesInMegabytes;\n                str = \"MB\";\n            }\n            else\n            {\n                value = size /BytesInGigabytes;\n                str = \"GB\";\n            }\n            return String.Format(\"{0:0.##} {1}\", value, str);\n        }\n        private void sizeTrackBar_Scroll(object sender, EventArgs e)\n        {\n            sizeToolTip.SetToolTip(sizeTrackBar, FormatSize((double)(sizeTrackBar.Value * 32768)));\n        }\n        private void SetStatus(string msg)\n        {\n            statusLabel.Text = $\"Status: {msg}\";\n        }\n        private void WriteLog(string msg)\n        {\n            if(log)\n            {\n\n                msg = $\"|{msg}|\";\n                var a = msg.Length / 2;\n                for (var i = 0; i < 48 - a; i++)\n                {\n                    msg = msg.Insert(0, \" \");\n                }\n\n                for (var i = msg.Length; i < 96; i++)\n                {\n                    msg += \" \";\n                }\n\n                var dateAndTime = DateTime.Now;\n                var logStr = $\"|{dateAndTime:MM/dd/yyyy} {dateAndTime:hh:mm:ss tt}| |{msg}|\";\n\n                if (File.Exists(@\"log.txt\"))\n                {\n                    File.AppendAllText(@\"log.txt\",\n                        $\"{logStr}{Environment.NewLine}\");\n                }\n                else\n                {\n                    using (var sw = File.CreateText(@\"log.txt\"))\n                    {\n                        sw.WriteLine(logStr);\n                    }\n                }\n\n                Console.WriteLine(logStr);\n            }\n        }\n        private void connectButton_Click(object sender, EventArgs e)\n        {\n            try\n            {\n                if (!checkIP(ipTextBox.Text))\n                {\n                    SetStatus(\"Invalid IP\");\n                    return;\n                }\n                ps4 = new PS4DBG(ipTextBox.Text);\n                ps4.Connect();\n                if (!ps4.IsConnected)\n                {\n                    throw new Exception();\n                }\n                SetStatus(\"Connected\");\n                if (!File.Exists(\"ip\"))\n                {\n                    File.WriteAllText(\"ip\", ipTextBox.Text);\n                }\n                else\n                {\n                    using (var sw = File.CreateText(@\"log.txt\"))\n                    {\n                        sw.Write(ipTextBox.Text);\n                    }\n                }\n            }\n            catch\n            {\n                SetStatus(\"Failed To Connect\");\n            }\n        }\n\n        private void setupButton_Click(object sender, EventArgs e)\n        {\n            if (!ps4.IsConnected)\n            {\n                SetStatus(\"Not connected to ps4\");\n                return;\n            }\n            var pl = ps4.GetProcessList();\n            var su = pl.FindProcess(\"SceShellUI\");\n            if (su == null)\n            {\n                SetStatus(\"Couldn't find SceShellUI\");\n                return;\n            }\n            pid = su.pid;\n            var pm = ps4.GetProcessMaps(pid);\n            var tmp = pm.FindEntry(\"libSceSaveData.sprx\")?.start;\n            if (tmp == null)\n            {\n                MessageBox.Show(\"savedata lib not found\", \"Error\");\n                return;\n            }\n            libSceSaveDataBase = (ulong)tmp;\n\n            tmp = pm.FindEntry(\"libSceUserService.sprx\")?.start;\n            if (tmp == null)\n            {\n                MessageBox.Show(\"user service lib not found\", \"Error\");\n                return;\n            }\n            libSceUserServiceBase = (ulong)tmp;\n\n            tmp = pm.FindEntry(\"executable\")?.start;\n            if (tmp == null)\n            {\n                MessageBox.Show(\"executable not found\", \"Error\");\n                return;\n            }\n            executableBase = (ulong)tmp;\n\n            tmp = pm.FindEntry(\"libSceLibcInternal.sprx\")?.start;\n            if (tmp == null)\n            {\n                MessageBox.Show(\"libc not found\", \"Error\");\n                return;\n            }\n            libSceLibcInternalBase = (ulong)tmp;\n            stub = pm.FindEntry(\"(NoName)clienthandler\") == null ? ps4.InstallRPC(pid) : pm.FindEntry(\"(NoName)clienthandler\").start;\n\n            \n\n            var ret = ps4.Call(pid, stub, libSceSaveDataBase + offsets.sceSaveDataInitialize3);\n            WriteLog($\"sceSaveDataInitialize3 ret = 0x{ret:X}\");\n            \n           \n            //PATCHES\n            //SAVEDATA LIBRARY PATCHES\n            ps4.WriteMemory(pid, libSceSaveDataBase + 0x32998, (byte)0x00); // 'sce_' patch\n            ps4.WriteMemory(pid, libSceSaveDataBase + 0x31699, (byte)0x00); // 'sce_sdmemory' patch\n            ps4.WriteMemory(pid, libSceSaveDataBase + 0x01119, (byte)0x30); // '_' patch\n\n            var l = ps4.GetProcessList();\n            var s = l.FindProcess(\"SceShellCore\");\n            var m = ps4.GetProcessMaps(s.pid);\n            var ex = m.FindEntry(\"executable\");\n            \n            //SHELLCORE PATCHES\n            ps4.WriteMemory(s.pid, ex.start + 0xD42843, (byte)0x00); // 'sce_sdmemory' patch\n            ps4.WriteMemory(s.pid, ex.start + 0x7E4DC0, new byte[]{0x48, 0x31, 0xC0, 0xC3}); //verify keystone patch\n            ps4.WriteMemory(s.pid, ex.start + 0x68BA0, new byte[] {0x31, 0xC0, 0xC3}); //transfer mount permission patch eg mount foreign saves with write permission\n            ps4.WriteMemory(s.pid, ex.start + 0xC54F0, new byte[] { 0x31, 0xC0, 0xC3 });//patch psn check to load saves saves foreign to current account\n            ps4.WriteMemory(s.pid, ex.start + 0x6A349, new byte[] { 0x90, 0x90 }); // ^\n            ps4.WriteMemory(s.pid, ex.start + 0x686AE, new byte[] {0x90, 0x90, 0x90, 0x90, 0x90, 0x90}); // something something patches... \n            ps4.WriteMemory(s.pid, ex.start + 0x67FCA, new byte[] { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }); // don't even remember doing this\n            ps4.WriteMemory(s.pid, ex.start + 0x67798, new byte[] { 0x90, 0x90}); //nevah jump\n            ps4.WriteMemory(s.pid, ex.start + 0x679D5, new byte[] { 0x90, 0xE9 }); //always jump\n            //WRITE CUSTOM FUNCTIONS\n            GetSaveDirectoriesAddr = ps4.AllocateMemory(pid, 0x8000);\n            ps4.WriteMemory(pid, GetSaveDirectoriesAddr, functions.GetSaveDirectories);\n            ps4.WriteMemory(pid, GetSaveDirectoriesAddr + 0x12, executableBase + 0x81E800); //opendir\n            ps4.WriteMemory(pid, GetSaveDirectoriesAddr + 0x20, executableBase + 0x81E810); //readdir\n            ps4.WriteMemory(pid, GetSaveDirectoriesAddr + 0x2E, executableBase + 0x81E7F0);//closedir\n            ps4.WriteMemory(pid, GetSaveDirectoriesAddr + 0x3C, libSceLibcInternalBase + 0x8B1A0); //strcpy\n\n            GetUsersAddr = GetSaveDirectoriesAddr + (uint)functions.GetSaveDirectories.Length + 0x20;\n            ps4.WriteMemory(pid, GetUsersAddr, functions.GetUsers);\n            ps4.WriteMemory(pid, GetUsersAddr + 0x15, libSceUserServiceBase + offsets.sceUserServiceGetLoginUserIdList);\n            ps4.WriteMemory(pid, GetUsersAddr + 0x23, libSceUserServiceBase + offsets.sceUserServiceGetUserName);\n            ps4.WriteMemory(pid, GetUsersAddr + 0x31, libSceLibcInternalBase + 0x8B1A0); //strcpy\n\n\n            var users = GetUsers();\n            userComboBox.DataSource = users;\n\n            SetStatus(\"Setup Done :)\");\n        }\n\n        private void searchButton_Click(object sender, EventArgs e)\n        {\n\n            if (!ps4.IsConnected)\n            {\n                SetStatus(\"Not connected to ps4\");\n                return;\n            }\n            if (pid == 0)\n            {\n                SetStatus(\"dont forget to click setup\");\n                return;\n            }\n            if (selectedGame == null)\n            {\n                SetStatus(\"No game selected\");\n                return;\n            }\n            var pm = ps4.GetProcessMaps(pid);\n            if (pm.FindEntry(\"(NoName)clienthandler\") == null)\n            {\n                SetStatus(\"RPC Stub Not Found\");\n                return;\n            }\n            var dirNameAddr = ps4.AllocateMemory(pid, Marshal.SizeOf(typeof(SceSaveDataDirName)) * 1024 + 0x10 + Marshal.SizeOf(typeof(SceSaveDataParam)) * 1024);\n            var titleIdAddr = dirNameAddr + (uint) Marshal.SizeOf(typeof(SceSaveDataDirName)) * 1024;\n            var paramAddr = titleIdAddr + 0x10;\n            SceSaveDataDirNameSearchCond searchCond = new SceSaveDataDirNameSearchCond\n            {\n                userId = GetUser(),\n                titleId = titleIdAddr\n            };\n            SceSaveDataDirNameSearchResult searchResult = new SceSaveDataDirNameSearchResult\n            {\n                dirNames = dirNameAddr,\n                dirNamesNum = 1024,\n                param = paramAddr,\n            };\n            ps4.WriteMemory(pid, titleIdAddr, selectedGame);\n            dirsComboBox.DataSource = Find(searchCond, searchResult);\n            ps4.FreeMemory(pid, dirNameAddr, Marshal.SizeOf(typeof(SceSaveDataDirName)) * 1024 + 0x10 + Marshal.SizeOf(typeof(SceSaveDataParam)) * 1024);\n            if (dirsComboBox.Items.Count > 0)\n            {\n                SetStatus($\"Found {dirsComboBox.Items.Count} Save Directories :D\");\n            }\n            else\n            {\n                SetStatus(\"Found 0 Save Directories :(\");\n            }\n        }\n\n        private void mountButton_Click(object sender, EventArgs e)\n        {\n            if (!ps4.IsConnected)\n            {\n                SetStatus(\"Not connected to ps4\");\n                return;\n            }\n            if (dirsComboBox.Items.Count == 0)\n            {\n                SetStatus(\"No save selected\");\n                return;\n            }\n            if (selectedGame == null)\n            {\n                SetStatus(\"No game selected\");\n                return;\n            }\n            var dirNameAddr = ps4.AllocateMemory(pid, Marshal.SizeOf(typeof(SceSaveDataDirName)) + 0x10 + 0x41);\n            var titleIdAddr = dirNameAddr + (uint)Marshal.SizeOf(typeof(SceSaveDataDirName));\n            var fingerprintAddr = titleIdAddr + 0x10;\n            ps4.WriteMemory(pid, titleIdAddr, selectedGame);\n            ps4.WriteMemory(pid, fingerprintAddr, \"0000000000000000000000000000000000000000000000000000000000000000\");\n            SceSaveDataDirName dirName = new SceSaveDataDirName\n            {\n                data = dirsComboBox.Text\n            };\n\n            SceSaveDataMount mount = new SceSaveDataMount\n            {\n                userId = GetUser(),\n                dirName = dirNameAddr,\n                blocks = 32768,\n                mountMode = 0x8 | 0x2,\n                titleId = titleIdAddr,\n                fingerprint = fingerprintAddr\n\n            };\n            SceSaveDataMountResult mountResult = new SceSaveDataMountResult\n            {\n\n            };\n            ps4.WriteMemory(pid, dirNameAddr, dirName);\n            mp = Mount(mount, mountResult);\n\n            ps4.FreeMemory(pid, dirNameAddr, Marshal.SizeOf(typeof(SceSaveDataDirName)) + 0x10 + 0x41);\n            if (mp != \"\")\n            {\n                SetStatus($\"Save Mounted in {mp}\");\n            }\n            else\n            {\n                SetStatus(\"Mounting Failed\");\n            }\n        }\n\n        private void unmountButton_Click(object sender, EventArgs e)\n        {\n            if (!ps4.IsConnected)\n            {\n                SetStatus(\"Not connected to ps4\");\n                return;\n            }\n            if (mp == \"\")\n            {\n                SetStatus(\"No save mounted\");\n                return;\n            }\n            SceSaveDataMountPoint mountPoint = new SceSaveDataMountPoint\n            {\n                data = mp,\n            };\n\n            Unmount(mountPoint);\n            mp = null;\n            SetStatus(\"Save Unmounted\");\n        }\n\n        private void createButton_Click(object sender, EventArgs e)\n        {\n            if (!ps4.IsConnected)\n            {\n                SetStatus(\"Not connected to ps4\");\n                return;\n            }\n            if (pid == 0)\n            {\n                SetStatus(\"Don't forget to setup\");\n                return;\n            }\n            if (nameTextBox.Text == \"\")\n            {\n                SetStatus(\"No Save Name\");\n                return;\n            }\n            if (selectedGame == null)\n            {\n                SetStatus(\"No game selected\");\n                return;\n            }\n            var pm = ps4.GetProcessMaps(pid);\n            if (pm.FindEntry(\"(NoName)clienthandler\") == null)\n            {\n                SetStatus(\"RPC Stub Not Found\");\n                return;\n            }\n\n            var dirNameAddr = ps4.AllocateMemory(pid, Marshal.SizeOf(typeof(SceSaveDataDirName)) + 0x10 + 0x41);\n            var titleIdAddr = dirNameAddr + (uint)Marshal.SizeOf(typeof(SceSaveDataDirName));\n            var fingerprintAddr = titleIdAddr + 0x10;\n            ps4.WriteMemory(pid, fingerprintAddr, \"0000000000000000000000000000000000000000000000000000000000000000\");\n            ps4.WriteMemory(pid, titleIdAddr, selectedGame);\n            SceSaveDataDirName dirName = new SceSaveDataDirName\n            {\n                data = nameTextBox.Text\n            };\n\n            SceSaveDataMount mount = new SceSaveDataMount\n            {\n                userId = GetUser(),\n                dirName = dirNameAddr,\n                blocks = (ulong) sizeTrackBar.Value,\n                mountMode = 4 | 2 | 8,\n                titleId = titleIdAddr,\n                fingerprint = fingerprintAddr\n\n            };\n            SceSaveDataMountResult mountResult = new SceSaveDataMountResult\n            {\n\n            };\n            ps4.WriteMemory(pid, dirNameAddr, dirName);\n            var mp = Mount(mount, mountResult);\n            ps4.FreeMemory(pid, dirNameAddr, Marshal.SizeOf(typeof(SceSaveDataDirName)) + 0x10 + 0x41);\n            if (mp != \"\")\n            {\n                SetStatus(\"Save Created\");\n                SceSaveDataMountPoint mountPoint = new SceSaveDataMountPoint\n                {\n                    data = mp,\n                };\n                Unmount(mountPoint);\n            }\n            else\n            {\n                SetStatus(\"Save Creation Failed\");\n            }\n        }\n\n        private int GetUser()\n        {\n            if(user != 0)\n            {\n                return user;\n            }\n            return InitialUser();          \n        }\n\n        private int InitialUser()\n        {\n            var bufferAddr = ps4.AllocateMemory(pid, sizeof(int));\n\n            ps4.Call(pid, stub, libSceUserServiceBase + offsets.sceUserServiceGetInitialUser, bufferAddr);\n\n            var id = ps4.ReadMemory<int>(pid, bufferAddr);\n\n            ps4.FreeMemory(pid, bufferAddr, sizeof(int));\n\n            return id;\n        }\n\n        private SearchEntry[] Find(SceSaveDataDirNameSearchCond searchCond, SceSaveDataDirNameSearchResult searchResult)\n        {\n            var searchCondAddr = ps4.AllocateMemory(pid, Marshal.SizeOf(typeof(SceSaveDataDirNameSearchCond)) + Marshal.SizeOf(typeof(SceSaveDataDirNameSearchResult)));\n            var searchResultAddr = searchCondAddr + (uint)Marshal.SizeOf(typeof(SceSaveDataDirNameSearchCond));\n\n            ps4.WriteMemory(pid, searchCondAddr, searchCond);\n            ps4.WriteMemory(pid, searchResultAddr, searchResult);\n            var ret = ps4.Call(pid, stub, libSceSaveDataBase + offsets.sceSaveDataDirNameSearch, searchCondAddr, searchResultAddr);\n            WriteLog($\"sceSaveDataDirNameSearch ret = 0x{ret:X}\");\n            if ( ret == 0)\n            {\n                searchResult = ps4.ReadMemory<SceSaveDataDirNameSearchResult>(pid, searchResultAddr);\n                SearchEntry[] sEntries = new SearchEntry[searchResult.hitNum];\n                var paramMemory = ps4.ReadMemory(pid, searchResult.param, (int)searchResult.hitNum * Marshal.SizeOf(typeof(SceSaveDataParam)));\n                var dirNamesMemory = ps4.ReadMemory(pid, searchResult.dirNames, (int)searchResult.hitNum * 32);\n                for (int i = 0; i < searchResult.hitNum; i++)\n                {\n                    SceSaveDataParam tmp = (SceSaveDataParam)PS4DBG.GetObjectFromBytes(PS4DBG.SubArray(paramMemory, i * Marshal.SizeOf(typeof(SceSaveDataParam)), Marshal.SizeOf(typeof(SceSaveDataParam))), typeof(SceSaveDataParam));\n                    sEntries[i] = new SearchEntry\n                    {\n                        dirName = System.Text.Encoding.UTF8.GetString(PS4DBG.SubArray(dirNamesMemory, i * 32, 32)),\n                        title = System.Text.Encoding.UTF8.GetString(tmp.title),\n                        subtitle = System.Text.Encoding.UTF8.GetString(tmp.subTitle),\n                        detail = System.Text.Encoding.UTF8.GetString(tmp.detail),\n                        time = new DateTime(1970, 1, 1).ToLocalTime().AddSeconds(tmp.mtime).ToString(),\n                    };\n                }\n                ps4.FreeMemory(pid, searchCondAddr, Marshal.SizeOf(typeof(SceSaveDataDirNameSearchCond)) + Marshal.SizeOf(typeof(SceSaveDataDirNameSearchResult)));\n                return sEntries;\n            }\n\n            ps4.FreeMemory(pid, searchCondAddr, Marshal.SizeOf(typeof(SceSaveDataDirNameSearchCond)) + Marshal.SizeOf(typeof(SceSaveDataDirNameSearchResult)));\n\n            return new SearchEntry[0];\n\n        }\n\n        private void Unmount(SceSaveDataMountPoint mountPoint)\n        {\n            var mountPointAddr = ps4.AllocateMemory(pid, Marshal.SizeOf(typeof(SceSaveDataMountPoint)));\n\n            ps4.WriteMemory(pid, mountPointAddr, mountPoint);\n            var ret = ps4.Call(pid, stub, libSceSaveDataBase + offsets.sceSaveDataUmount, mountPointAddr);\n            WriteLog($\"sceSaveDataUmount ret = 0x{ret:X}\");\n            ps4.FreeMemory(pid, mountPointAddr, Marshal.SizeOf(typeof(SceSaveDataMountPoint)));\n            mp = null;\n        }\n\n        private string Mount(SceSaveDataMount mount, SceSaveDataMountResult mountResult)\n        {\n            var mountAddr = ps4.AllocateMemory(pid, Marshal.SizeOf(typeof(SceSaveDataMount)) + Marshal.SizeOf(typeof(SceSaveDataMountResult)));\n            var mountResultAddr = mountAddr + (uint)Marshal.SizeOf(typeof(SceSaveDataMount));\n            ps4.WriteMemory(pid, mountAddr, mount);\n            ps4.WriteMemory(pid, mountResultAddr, mountResult);\n\n            var ret = ps4.Call(pid, stub, libSceSaveDataBase + offsets.sceSaveDataMount, mountAddr, mountResultAddr);\n            WriteLog($\"sceSaveDataMount ret = 0x{ret:X}\");\n            if (ret == 0)\n            {\n                mountResult = ps4.ReadMemory<SceSaveDataMountResult>(pid, mountResultAddr);\n\n                ps4.FreeMemory(pid, mountAddr, Marshal.SizeOf(typeof(SceSaveDataMount)) + Marshal.SizeOf(typeof(SceSaveDataMountResult)));\n\n                return mountResult.mountPoint.data;\n            }\n\n            ps4.FreeMemory(pid, mountAddr, Marshal.SizeOf(typeof(SceSaveDataMount)) + Marshal.SizeOf(typeof(SceSaveDataMountResult)));\n\n            return \"\";\n        }\n\n        class SearchEntry\n        {\n            public string dirName;\n            public string title;\n            public string subtitle;\n            public string detail;\n            public string time;\n            public override string ToString()\n            {\n                return dirName;\n            }\n        }\n\n        private void dirsComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            titleTextBox.Text = ((SearchEntry)dirsComboBox.SelectedItem).title;\n            subtitleTextBox.Text = ((SearchEntry)dirsComboBox.SelectedItem).subtitle;\n            detailsTextBox.Text = ((SearchEntry)dirsComboBox.SelectedItem).detail;\n            dateTextBox.Text = ((SearchEntry)dirsComboBox.SelectedItem).time;\n        }\n        \n        private void userComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            user = ((User)userComboBox.SelectedItem).id;\n        }\n\n        class User\n        {\n            public int id;\n            public string name;\n\n            public override string ToString()\n            {\n                return name;\n            }\n        }\n        private string[] GetSaveDirectories()\n        {\n            var dirs = new List<string>();\n            var mem = ps4.AllocateMemory(pid, 0x8000);\n            var path = mem;\n            var buffer = mem + 0x101;\n\n            ps4.WriteMemory(pid, path, $\"/user/home/{GetUser():x}/savedata/\");\n            var ret = (int)ps4.Call(pid, stub, GetSaveDirectoriesAddr, path, buffer);\n            if (ret != -1 && ret != 0)\n            {\n                var bDirs = ps4.ReadMemory(pid, buffer, ret * 0x10);\n                for (var i = 0; i < ret; i++)\n                {\n                    var sDir = System.Text.Encoding.UTF8.GetString(PS4DBG.SubArray(bDirs, i * 10, 9));\n                    dirs.Add(sDir);\n                }\n            }\n            ps4.FreeMemory(pid, mem, 0x8000);\n            return dirs.ToArray();\n        }\n\n        private User[] GetUsers()\n        {\n            List<User> users = new List<User>();\n            var mem = ps4.AllocateMemory(pid, 0x1);\n            var ret = (int)ps4.Call(pid, stub, GetUsersAddr, mem);\n            \n            if (ret != -1 && ret != 0)\n            {\n                var buffer = ps4.ReadMemory(pid, mem, (21) * 4);\n                for (int i = 0; i < 4; i++)\n                {\n                    var id = BitConverter.ToInt32(buffer, 21 * i);\n                    if (id == 0)\n                    {\n                        continue;\n                    }\n                    var name = System.Text.Encoding.UTF8.GetString(PS4DBG.SubArray(buffer, i * 21 + 4, 16));\n                    users.Add(new User { id = id, name = name });\n                }\n            }\n            ps4.FreeMemory(pid, mem, 0x1);\n            return users.ToArray();\n\n        }\n        public static bool checkIP(string IP)\n        {\n            return !string.IsNullOrEmpty(IP) && IPAddress.TryParse(IP, out _);\n        }\n        private void payloadButton_Click(object sender, EventArgs e)\n        {\n            try\n            {\n                if (!checkIP(ipTextBox.Text))\n                {\n                    SetStatus(\"Invalid IP\");\n                    return;\n                }\n\n                var assembly = System.Reflection.Assembly.GetExecutingAssembly();\n                using (var stream = assembly.GetManifestResourceStream(\"PS4Saves.ps4debug.bin\"))\n                {\n                    var buffer = new byte[stream.Length];\n                    stream.Read(buffer, 0, buffer.Length);\n                    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);\n                    IAsyncResult result = socket.BeginConnect(new IPEndPoint(IPAddress.Parse(ipTextBox.Text), 9020), null, null);\n                    var connected = result.AsyncWaitHandle.WaitOne(3000);\n                    if (connected)\n                    {\n                        socket.Send(buffer, buffer.Length, SocketFlags.None);\n                    }\n\n                    SetStatus(connected ? \"Payload sent\" : \"Failed to connect\");\n                    socket.Close();\n                }\n            }\n            catch\n            {\n                SetStatus(\"Sending payload failed\");\n            }\n        }\n\n        private void getGamesButton_Click(object sender, EventArgs e)\n        {\n            if (!ps4.IsConnected)\n            {\n                SetStatus(\"Not connected to ps4\");\n                return;\n            }\n            if (pid == 0)\n            {\n                SetStatus(\"Don't forget to press setup\");\n                return;\n            }\n            var pm = ps4.GetProcessMaps(pid);\n            if (pm.FindEntry(\"(NoName)clienthandler\") == null)\n            {\n                SetStatus(\"RPC Stub Not Found\");\n                return;\n            }\n            var dirs = GetSaveDirectories();\n            gamesComboBox.DataSource = dirs;\n        }\n\n        private void gamesComboBox_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            selectedGame = (string)gamesComboBox.SelectedItem;\n        }\n    }\n}\n"
  },
  {
    "path": "PS4Saves.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <ProjectGuid>{8F8D661C-CCD4-4360-962D-60207A3828BF}</ProjectGuid>\n    <OutputType>WinExe</OutputType>\n    <RootNamespace>PS4Saves</RootNamespace>\n    <AssemblyName>Playstation 4 Save Mounter</AssemblyName>\n    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>\n    <FileAlignment>512</FileAlignment>\n    <Deterministic>true</Deterministic>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\n    <PlatformTarget>AnyCPU</PlatformTarget>\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n    <LangVersion>7.1</LangVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\n    <PlatformTarget>AnyCPU</PlatformTarget>\n    <DebugType>none</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n    <LangVersion>7.1</LangVersion>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Deployment\" />\n    <Reference Include=\"System.Drawing\" />\n    <Reference Include=\"System.Windows.Forms\" />\n    <Reference Include=\"System.Xml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"functions.cs\" />\n    <Compile Include=\"Main.cs\">\n      <SubType>Form</SubType>\n    </Compile>\n    <Compile Include=\"Main.Designer.cs\">\n      <DependentUpon>Main.cs</DependentUpon>\n    </Compile>\n    <Compile Include=\"libdebug\\Process.cs\" />\n    <Compile Include=\"libdebug\\PS4DBG.Console.cs\" />\n    <Compile Include=\"libdebug\\PS4DBG.cs\" />\n    <Compile Include=\"libdebug\\PS4DBG.Debug.cs\" />\n    <Compile Include=\"libdebug\\PS4DBG.Kernel.cs\" />\n    <Compile Include=\"libdebug\\PS4DBG.Proc.cs\" />\n    <Compile Include=\"libdebug\\Registers.cs\" />\n    <Compile Include=\"offsets.cs\" />\n    <Compile Include=\"Program.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"structs.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <EmbeddedResource Include=\"ps4debug.bin\" />\n  </ItemGroup>\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n</Project>"
  },
  {
    "path": "Program.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Windows.Forms;\n\nnamespace PS4Saves\n{\n    static class Program\n    {\n        /// <summary>\n        /// The main entry point for the application.\n        /// </summary>\n        [STAThread]\n        static void Main()\n        {\n            Application.EnableVisualStyles();\n            Application.SetCompatibleTextRenderingDefault(false);\n            Application.Run(new Main());\n        }\n    }\n}\n"
  },
  {
    "path": "Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled through the following\n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"Playstation 4 Save Mounter\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"PS4Saves\")]\n[assembly: AssemblyCopyright(\"Copyright ©  2018 Aida & ChendoChap\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible\n// to COM components.  If you need to access a type in this assembly from\n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// The following GUID is for the ID of the typelib if this project is exposed to COM\n[assembly: Guid(\"8f8d661c-ccd4-4360-962d-60207a3828bf\")]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version\n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers\n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"1.5.0.0\")]\n[assembly: AssemblyFileVersion(\"1.5.0.0\")]\n"
  },
  {
    "path": "README.md",
    "content": "# Playstation 4 Save Mounter 1.5\n\n## Summary\nThis program allows you to mount save data with RW permission and a lot more shit, just read this damn thing\n### You can\n* Make decrypted copies of any save (as long as it's encrypted with keys <= 5.05)\n* Replace saves with modified ones\n* Replace save files with someone else's save files (share saves)\n* Create new saves\n* Export saves to 5.05+ consoles\n\n### You can't\n* Replace save files with an encrypted save (if it's encrypted with keys > 5.05)\n* Use this on unexploited consoles\n\n### You need\n* To make sure you're using a recent ps4debug version, bin of the latest ps4debug (as of 11/14) is included in the download\n* To be able to run .net framework 2.0 executables (even windows 98 can run this)\n## Prerequisites\n* PS4 5.05\n* FTP Client (eg filezilla, ...)\n## Instructions\n\n### Mounting saves\n1) Load [ps4debug](https://github.com/xemio/ps4debug)\n2) Load [FTP](https://github.com/xvortex/ps4-ftp-vtx)\n3) Open the tool\n4) Enter the ip of your ps4 and click 'Connect'\n5) Click 'Setup' & select the user you want to use in the combobox\n6) Click 'Get Games' & select the game you want to use in the combobox\n7) Click 'Search' & select the save you want to mount\n8) Click 'Mount'\n9) Your save is now mounted and accessible from ftp in /mnt/pfs/ & in /mnt/sandbox/NPXS20001_000/savedataX (it's the same just a different dir)\n10) After you're done copying/replacing files click 'Unmount'\n### Creating saves\n1) Load [ps4debug](https://github.com/xemio/ps4debug)\n2) Load [FTP](https://github.com/xvortex/ps4-ftp-vtx)\n3) Open the tool\n4) Enter the ip of your ps4 and click 'Connect'\n5) Click 'Setup' & select the user you want to use in the combobox\n6) Click 'Get Games' & select the game you want to use in the combobox\n7) Enter the desired save directory name in the textbox\n8) Use the slider to choose the save's size\n9) Click 'Create Save'\n10) Click 'Search' to refresh the save list\n### Exporting Saves to 5.05+ consoles\n1)  mount the save you want to export.\n2)  get the param.sfo file from the sce_sys directory\n3)  open it in a hex editor or a ps4 compatible sfo editor\n4)  change the psn id to the target's psn id (8 bytes, you get that by copying a save using settings, you'll need to change it to little endian) it's at 0x15C for hex editing... see video for sfo editor\n5)  save the param.sfo & replace the one in the mounted dir\n6)  unmount the save and copy the 2 save files sdimg & the .bin to your usb /PS4/SAVEDATA/{psn id}/{titleid}/\n7)  remove the sdimg_ prefix from the filename\n8)  now you should be able to copy the save to the account linked to the psn id (5.05+ console) using system settings\n## Important\n\n**- you don't need to start a game to modify its saves, it's actually better not to have one open because some games like gow 4 may overwrite parts of a save while you're busy modifying it resulting in a corrupted save.**\n\n**- don't replace files in sce_sys directory, it is unnecessary and will probably corrupt your save**  \n\n**- the workaround method is obsolete since update 1.4**  \n\n**- some games require you to create your own save data with the appropriate name & size, fallout 4 is such a game. This problem was discussed in [issue #5](https://github.com/ChendoChap/Playstation-4-Save-Mounter/issues/5)**\n\n**- Don't forget to regularly make backups of your saves and the savedata database, the ps4 deletes all your saves if the database gets corrupted while this mostly only happens when you actively mess with it, it's always better to be prepared**\n\n**- It's possible to mount someone else's encrypted saves but there's currently no 'clean' way to do it. you need to temporarily replace the sdimg_xxx and the xxx.bin files with the ones you downloaded in your user's savedata directory. Be sure to restore the original files after you extracted the save because the ps4 could throw a fit if you reboot while those files are still there. (I'll make this process easier later on)**\n\n## Resources\n### Do note that not all of these were made using the latest save mounter version so slight differences are to be expected.\n\n### Videos\n  * exporting saves to 5.05+ consoles (latest version 1.5): [how to resign PS4 saves for different PS4 and profile, fw 5 05 and higher by 'Old Gamer'](https://www.youtube.com/watch?v=OpZ9C-MciZM)\n\n  * mounting saves, transferring saves to other (regions/title ids) (old version): [PS4 Save Mounter Tutorial (Swap Saves Between Consoles & Games) by 'MODDED WARFARE'](https://www.youtube.com/watch?v=m_h4MsAaXdY)\n\n  * mounting saves, using other people's decrypted saves (old version): [Playstation 4 Save Mounter Demonstration by 'Sc0rpion'](https://www.youtube.com/watch?v=Atw6480SX5I)\n"
  },
  {
    "path": "functions.cs",
    "content": "﻿namespace PS4Saves\n{\n    internal static class functions\n    {\n        internal static byte[] GetSaveDirectories =\n        {\n            0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x50, 0x48, 0x89, 0x7D, 0xB8, 0x48, 0x89, 0x75, 0xB0, 0x48,\n            0xB8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x48, 0x89, 0x45, 0xE8, 0x48, 0xB8, 0xBB, 0xBB,\n            0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x48, 0x89, 0x45, 0xE0, 0x48, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,\n            0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x45, 0xD8, 0x48, 0xB8, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,\n            0x48, 0x89, 0x45, 0xD0, 0x48, 0x8B, 0x55, 0xB8, 0x48, 0x8B, 0x45, 0xE8, 0x48, 0x89, 0xD7, 0xFF, 0xD0,\n            0x48, 0x89, 0x45, 0xC8, 0x48, 0x83, 0x7D, 0xC8, 0x00, 0x75, 0x0A, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9,\n            0x88, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x55, 0xC8, 0x48, 0x8B, 0x45, 0xE0, 0x48, 0x89, 0xD7, 0xFF, 0xD0,\n            0x48, 0x89, 0x45, 0xF8, 0xC7, 0x45, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0x7D, 0xF8, 0x00, 0x74,\n            0x59, 0x48, 0x8B, 0x45, 0xF8, 0x0F, 0xB6, 0x40, 0x06, 0x3C, 0x04, 0x75, 0x3A, 0x48, 0x8B, 0x45, 0xF8,\n            0x0F, 0xB6, 0x40, 0x07, 0x3C, 0x09, 0x75, 0x2E, 0x48, 0x8B, 0x45, 0xF8, 0x48, 0x8D, 0x48, 0x08, 0x8B,\n            0x55, 0xF4, 0x89, 0xD0, 0xC1, 0xE0, 0x02, 0x01, 0xD0, 0x01, 0xC0, 0x48, 0x63, 0xD0, 0x48, 0x8B, 0x45,\n            0xB0, 0x48, 0x01, 0xC2, 0x48, 0x8B, 0x45, 0xD0, 0x48, 0x89, 0xCE, 0x48, 0x89, 0xD7, 0xFF, 0xD0, 0x83,\n            0x45, 0xF4, 0x01, 0x48, 0x8B, 0x55, 0xC8, 0x48, 0x8B, 0x45, 0xE0, 0x48, 0x89, 0xD7, 0xFF, 0xD0, 0x48,\n            0x89, 0x45, 0xF8, 0xEB, 0xA0, 0x48, 0x8B, 0x55, 0xC8, 0x48, 0x8B, 0x45, 0xD8, 0x48, 0x89, 0xD7, 0xFF,\n            0xD0, 0x8B, 0x45, 0xF4, 0xC9, 0xC3\n        };\n\n        internal static byte[] GetUsers =\n        {\n            0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x70, 0x48, 0x89, 0x7D, 0x98, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00,\n            0x00, 0x48, 0xB8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x48, 0x89, 0x45, 0xF0, 0x48, 0xB8, 0xBB,\n            0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x48, 0x89, 0x45, 0xE8, 0x48, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,\n            0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x45, 0xE0, 0x48, 0x8D, 0x55, 0xC0, 0x48, 0x8B, 0x45, 0xF0, 0x48, 0x89, 0xD7,\n            0xFF, 0xD0, 0x89, 0x45, 0xDC, 0x83, 0x7D, 0xDC, 0x00, 0x74, 0x0A, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0xB4,\n            0x00, 0x00, 0x00, 0xC7, 0x45, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7D, 0xF8, 0x03, 0x0F, 0x8F, 0xA0, 0x00,\n            0x00, 0x00, 0x8B, 0x45, 0xF8, 0x48, 0x98, 0x8B, 0x44, 0x85, 0xC0, 0x85, 0xC0, 0x0F, 0x8E, 0x86, 0x00, 0x00,\n            0x00, 0x8B, 0x45, 0xF8, 0x48, 0x98, 0x8B, 0x4C, 0x85, 0xC0, 0x48, 0x8D, 0x75, 0xA0, 0x48, 0x8B, 0x45, 0xE8,\n            0xBA, 0x11, 0x00, 0x00, 0x00, 0x89, 0xCF, 0xFF, 0xD0, 0x89, 0x45, 0xDC, 0x83, 0x7D, 0xDC, 0x00, 0x74, 0x07,\n            0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x68, 0x8B, 0x55, 0xF8, 0x89, 0xD0, 0xC1, 0xE0, 0x02, 0x01, 0xD0, 0xC1,\n            0xE0, 0x02, 0x01, 0xD0, 0x48, 0x98, 0x48, 0x8D, 0x14, 0x85, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x45, 0x98,\n            0x48, 0x01, 0xC2, 0x8B, 0x45, 0xF8, 0x48, 0x98, 0x8B, 0x44, 0x85, 0xC0, 0x89, 0x02, 0x8B, 0x55, 0xF8, 0x89,\n            0xD0, 0xC1, 0xE0, 0x02, 0x01, 0xD0, 0xC1, 0xE0, 0x02, 0x01, 0xD0, 0x48, 0x98, 0x48, 0x8D, 0x50, 0x04, 0x48,\n            0x8B, 0x45, 0x98, 0x48, 0x8D, 0x0C, 0x02, 0x48, 0x8D, 0x55, 0xA0, 0x48, 0x8B, 0x45, 0xE0, 0x48, 0x89, 0xD6,\n            0x48, 0x89, 0xCF, 0xFF, 0xD0, 0x83, 0x45, 0xFC, 0x01, 0x83, 0x45, 0xF8, 0x01, 0xE9, 0x56, 0xFF, 0xFF, 0xFF,\n            0x8B, 0x45, 0xFC, 0xC9, 0xC3\n        };\n    }\n}\n"
  },
  {
    "path": "libdebug/PS4DBG.Console.cs",
    "content": "using System.Text;\n\nnamespace libdebug\n{\n    public partial class PS4DBG\n    {   \n        //console\n        // packet sizes\n        // send size\n        private const int CMD_CONSOLE_PRINT_PACKET_SIZE = 4;\n        private const int CMD_CONSOLE_NOTIFY_PACKET_SIZE = 8;\n\n\n        // console\n        // note: the disconnect command actually uses the console api to end the connection\n        /// <summary>\n        /// Reboot console\n        /// </summary>\n        public void Reboot()\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_CONSOLE_REBOOT, 0);\n            IsConnected = false;\n        }\n\n        /// <summary>\n        /// Print to serial port\n        /// </summary>\n        public void Print(string str)\n        {\n            CheckConnected();\n\n            string raw = str + \"\\0\";\n\n            SendCMDPacket(CMDS.CMD_CONSOLE_PRINT, CMD_CONSOLE_PRINT_PACKET_SIZE, raw.Length);\n            SendData(Encoding.ASCII.GetBytes(raw), raw.Length);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Notify console\n        /// </summary>\n        public void Notify(int messageType, string message)\n        {\n            CheckConnected();\n\n            string raw = message + \"\\0\";\n\n            SendCMDPacket(CMDS.CMD_CONSOLE_NOTIFY, CMD_CONSOLE_NOTIFY_PACKET_SIZE, messageType, raw.Length);\n            SendData(Encoding.ASCII.GetBytes(raw), raw.Length);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Console information\n        /// </summary>\n        public void GetConsoleInformation()\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_CONSOLE_INFO, 0);\n            CheckStatus();\n\n            // TODO return the data\n        }\n    }\n}"
  },
  {
    "path": "libdebug/PS4DBG.Debug.cs",
    "content": "using System;\nusing System.Net;\nusing System.Net.Sockets;\nusing System.Runtime.InteropServices;\nusing System.Threading;\n\nnamespace libdebug\n{\n    public partial class PS4DBG\n    {\n        //debug\n        // packet sizes\n        //send size\n        private const int CMD_DEBUG_ATTACH_PACKET_SIZE = 4;\n        private const int CMD_DEBUG_BREAKPT_PACKET_SIZE = 16;\n        private const int CMD_DEBUG_WATCHPT_PACKET_SIZE = 24;\n        private const int CMD_DEBUG_STOPTHR_PACKET_SIZE = 4;\n        private const int CMD_DEBUG_RESUMETHR_PACKET_SIZE = 4;\n        private const int CMD_DEBUG_GETREGS_PACKET_SIZE = 4;\n        private const int CMD_DEBUG_SETREGS_PACKET_SIZE = 8;\n        private const int CMD_DEBUG_STOPGO_PACKET_SIZE = 4;\n        private const int CMD_DEBUG_THRINFO_PACKET_SIZE = 4;\n        //receive size\n        private const int DEBUG_INTERRUPT_SIZE = 0x4A0;\n        private const int DEBUG_THRINFO_SIZE = 40;\n        private const int DEBUG_REGS_SIZE = 0xB0;\n        private const int DEBUG_FPREGS_SIZE = 0x340;\n        private const int DEBUG_DBGREGS_SIZE = 0x80;\n\n        [StructLayout(LayoutKind.Sequential, Pack = 1)]\n        public struct DebuggerInterruptPacket\n        {\n            public uint lwpid;\n            public uint status;\n            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]\n            public string tdname;\n            public regs reg64;\n            public fpregs savefpu;\n            public dbregs dbreg64;\n        }\n        /// <summary>\n        /// Debugger interrupt callback\n        /// </summary>\n        /// <param name=\"lwpid\">Thread identifier</param>\n        /// <param name=\"status\">status</param>\n        /// <param name=\"tdname\">Thread name</param>\n        /// <param name=\"regs\">Registers</param>\n        /// <param name=\"fpregs\">Floating point registers</param>\n        /// <param name=\"dbregs\">Debug registers</param>\n        public delegate void DebuggerInterruptCallback(uint lwpid, uint status, string tdname, regs regs, fpregs fpregs, dbregs dbregs);\n        private void DebuggerThread(object obj)\n        {\n            DebuggerInterruptCallback callback = (DebuggerInterruptCallback)obj;\n\n            IPAddress ip = IPAddress.Parse(\"0.0.0.0\");\n            IPEndPoint endpoint = new IPEndPoint(ip, PS4DBG_DEBUG_PORT);\n\n            Socket server = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);\n\n            server.Bind(endpoint);\n            server.Listen(0);\n\n            IsDebugging = true;\n\n            Socket cl = server.Accept();\n\n            cl.NoDelay = true;\n            cl.Blocking = false;\n\n            while (IsDebugging)\n            {\n                if (cl.Available == DEBUG_INTERRUPT_SIZE)\n                {\n                    byte[] data = new byte[DEBUG_INTERRUPT_SIZE];\n                    int bytes = cl.Receive(data, DEBUG_INTERRUPT_SIZE, SocketFlags.None);\n                    if (bytes == DEBUG_INTERRUPT_SIZE)\n                    {\n                        DebuggerInterruptPacket packet = (DebuggerInterruptPacket)GetObjectFromBytes(data, typeof(DebuggerInterruptPacket));\n                        callback(packet.lwpid, packet.status, packet.tdname, packet.reg64, packet.savefpu, packet.dbreg64);\n                    }\n                }\n\n                Thread.Sleep(100);\n            }\n\n            server.Close();\n        }\n        /// <summary>\n        /// Attach the debugger\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"callback\">DebuggerInterruptCallback implementation</param>\n        /// <returns></returns>\n        public void AttachDebugger(int pid, DebuggerInterruptCallback callback)\n        {\n            CheckConnected();\n\n            if (IsDebugging || debugThread != null)\n            {\n                throw new Exception(\"libdbg: debugger already running?\");\n            }\n\n            IsDebugging = false;\n\n            debugThread = new Thread(DebuggerThread);\n            debugThread.Start(callback);\n\n            // wait until server is started\n            while (!IsDebugging)\n            {\n                Thread.Sleep(100);\n            }\n\n            SendCMDPacket(CMDS.CMD_DEBUG_ATTACH, CMD_DEBUG_ATTACH_PACKET_SIZE, pid);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Detach the debugger\n        /// </summary>\n        /// <returns></returns>\n        public void DetachDebugger()\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_DETACH, 0);\n            CheckStatus();\n\n            if (IsDebugging && debugThread != null)\n            {\n                IsDebugging = false;\n\n                debugThread.Join();\n                debugThread = null;\n            }\n        }\n\n        /// <summary>\n        /// Stop the current process\n        /// </summary>\n        /// <returns></returns>\n        public void ProcessStop()\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_STOPGO, CMD_DEBUG_STOPGO_PACKET_SIZE, 1);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Kill the current process, it will detach before doing so\n        /// </summary>\n        /// <returns></returns>\n        public void ProcessKill()\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_STOPGO, CMD_DEBUG_STOPGO_PACKET_SIZE, 2);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Resume the current process\n        /// </summary>\n        /// <returns></returns>\n        public void ProcessResume()\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_STOPGO, CMD_DEBUG_STOPGO_PACKET_SIZE, 0);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Change breakpoint, to remove said breakpoint send the same index but disable it (address is ignored)\n        /// </summary>\n        /// <param name=\"index\">Index</param>\n        /// <param name=\"enabled\">Enabled</param>\n        /// <param name=\"address\">Address</param>\n        /// <returns></returns>\n        public void ChangeBreakpoint(int index, bool enabled, ulong address)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            if (index >= MAX_BREAKPOINTS)\n            {\n                throw new Exception(\"libdbg: breakpoint index out of range\");\n            }\n\n            SendCMDPacket(CMDS.CMD_DEBUG_BREAKPT, CMD_DEBUG_BREAKPT_PACKET_SIZE, index, Convert.ToInt32(enabled), address);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Change watchpoint\n        /// </summary>\n        /// <param name=\"index\">Index</param>\n        /// <param name=\"enabled\">Enabled</param>\n        /// <param name=\"length\">Length</param>\n        /// <param name=\"breaktype\">Break type</param>\n        /// <param name=\"address\">Address</param>\n        /// <returns></returns>\n        public void ChangeWatchpoint(int index, bool enabled, WATCHPT_LENGTH length, WATCHPT_BREAKTYPE breaktype, ulong address)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            if (index >= MAX_WATCHPOINTS)\n            {\n                throw new Exception(\"libdbg: watchpoint index out of range\");\n            }\n\n            SendCMDPacket(CMDS.CMD_DEBUG_WATCHPT, CMD_DEBUG_WATCHPT_PACKET_SIZE, index, Convert.ToInt32(enabled), (uint)length, (uint)breaktype, address);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Get a list of threads from the current process\n        /// </summary>\n        /// <returns></returns>\n        public uint[] GetThreadList()\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_THREADS, 0);\n            CheckStatus();\n\n            byte[] data = new byte[sizeof(int)];\n            sock.Receive(data, sizeof(int), SocketFlags.None);\n            int number = BitConverter.ToInt32(data, 0);\n\n            byte[] threads = ReceiveData(number * sizeof(uint));\n            uint[] thrlist = new uint[number];\n            for (int i = 0; i < number; i++)\n            {\n                thrlist[i] = BitConverter.ToUInt32(threads, i * sizeof(uint));\n            }\n\n            return thrlist;\n        }\n\n        /// <summary>\n        /// Get thread information\n        /// </summary>\n        /// <returns></returns>\n        /// <param name=\"lwpid\">Thread identifier</param>\n        public ThreadInfo GetThreadInfo(uint lwpid)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_THRINFO, CMD_DEBUG_THRINFO_PACKET_SIZE, lwpid);\n            CheckStatus();\n\n            return (ThreadInfo)GetObjectFromBytes(ReceiveData(DEBUG_THRINFO_SIZE), typeof(ThreadInfo));\n        }\n\n        /// <summary>\n        /// Stop a thread from running\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <returns></returns>\n        public void StopThread(uint lwpid)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_STOPTHR, CMD_DEBUG_STOPTHR_PACKET_SIZE, lwpid);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Resume a thread from being stopped\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <returns></returns>\n        public void ResumeThread(uint lwpid)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_RESUMETHR, CMD_DEBUG_RESUMETHR_PACKET_SIZE, lwpid);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Get registers from thread\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <returns></returns>\n        public regs GetRegisters(uint lwpid)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_GETREGS, CMD_DEBUG_GETREGS_PACKET_SIZE, lwpid);\n            CheckStatus();\n\n            return (regs)GetObjectFromBytes(ReceiveData(DEBUG_REGS_SIZE), typeof(regs));\n        }\n\n        /// <summary>\n        /// Set thread registers\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <param name=\"regs\">Register data</param>\n        /// <returns></returns>\n        public void SetRegisters(uint lwpid, regs regs)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_SETREGS, CMD_DEBUG_SETREGS_PACKET_SIZE, lwpid, DEBUG_REGS_SIZE);\n            CheckStatus();\n            SendData(GetBytesFromObject(regs), DEBUG_REGS_SIZE);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Get floating point registers from thread\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <returns></returns>\n        public fpregs GetFloatRegisters(uint lwpid)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_GETFPREGS, CMD_DEBUG_GETREGS_PACKET_SIZE, lwpid);\n            CheckStatus();\n\n            return (fpregs)GetObjectFromBytes(ReceiveData(DEBUG_FPREGS_SIZE), typeof(fpregs));\n        }\n\n        /// <summary>\n        /// Set floating point thread registers\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <param name=\"fpregs\">Floating point register data</param>\n        /// <returns></returns>\n        public void SetFloatRegisters(uint lwpid, fpregs fpregs)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_SETFPREGS, CMD_DEBUG_SETREGS_PACKET_SIZE, lwpid, DEBUG_FPREGS_SIZE);\n            CheckStatus();\n            SendData(GetBytesFromObject(fpregs), DEBUG_FPREGS_SIZE);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Get debug registers from thread\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <returns></returns>\n        public dbregs GetDebugRegisters(uint lwpid)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_GETDBGREGS, CMD_DEBUG_GETREGS_PACKET_SIZE, lwpid);\n            CheckStatus();\n\n            return (dbregs)GetObjectFromBytes(ReceiveData(DEBUG_DBGREGS_SIZE), typeof(dbregs));\n        }\n\n        /// <summary>\n        /// Set debug thread registers\n        /// </summary>\n        /// <param name=\"lwpid\">Thread id</param>\n        /// <param name=\"dbregs\">debug register data</param>\n        /// <returns></returns>\n        public void SetDebugRegisters(uint lwpid, dbregs dbregs)\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_SETDBGREGS, CMD_DEBUG_SETREGS_PACKET_SIZE, lwpid, DEBUG_DBGREGS_SIZE);\n            CheckStatus();\n            SendData(GetBytesFromObject(dbregs), DEBUG_DBGREGS_SIZE);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Executes a single instruction\n        /// </summary>\n        public void SingleStep()\n        {\n            CheckConnected();\n            CheckDebugging();\n\n            SendCMDPacket(CMDS.CMD_DEBUG_SINGLESTEP, 0);\n            CheckStatus();\n        }\n    }\n}"
  },
  {
    "path": "libdebug/PS4DBG.Kernel.cs",
    "content": "using System;\n\nnamespace libdebug\n{\n    public partial class PS4DBG\n    {\n        // kernel\n        //packet sizes\n        //send size\n        private const int CMD_KERN_READ_PACKET_SIZE = 12;\n        private const int CMD_KERN_WRITE_PACKET_SIZE = 12;\n        //receive size\n        private const int KERN_BASE_SIZE = 8;\n\n\n        /// <summary>\n        /// Get kernel base address\n        /// </summary>\n        /// <returns></returns>\n        public ulong KernelBase()\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_KERN_BASE, 0);\n            CheckStatus();\n            return BitConverter.ToUInt64(ReceiveData(KERN_BASE_SIZE), 0);\n        }\n\n        /// <summary>\n        /// Read memory from kernel\n        /// </summary>\n        /// <param name=\"address\">Memory address</param>\n        /// <param name=\"length\">Data length</param>\n        /// <returns></returns>\n        public byte[] KernelReadMemory(ulong address, int length)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_KERN_READ, CMD_KERN_READ_PACKET_SIZE, address, length);\n            CheckStatus();\n            return ReceiveData(length);\n        }\n\n        /// <summary>\n        /// Write memory in kernel\n        /// </summary>\n        /// <param name=\"address\">Memory address</param>\n        /// <param name=\"data\">Data</param>\n        public void KernelWriteMemory(ulong address, byte[] data)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_KERN_WRITE, CMD_KERN_WRITE_PACKET_SIZE, address, data.Length);\n            CheckStatus();\n            SendData(data, data.Length);\n            CheckStatus();\n        }\n    }\n}"
  },
  {
    "path": "libdebug/PS4DBG.Proc.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Net.Sockets;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace libdebug\n{\n    public partial class PS4DBG\n    {\n        //proc\n        // packet sizes\n        // send size\n        private const int CMD_PROC_READ_PACKET_SIZE = 16;\n        private const int CMD_PROC_WRITE_PACKET_SIZE = 16;\n        private const int CMD_PROC_MAPS_PACKET_SIZE = 4;\n        private const int CMD_PROC_INSTALL_PACKET_SIZE = 4;\n        private const int CMD_PROC_CALL_PACKET_SIZE = 68;\n        private const int CMD_PROC_ELF_PACKET_SIZE = 8;\n        private const int CMD_PROC_PROTECT_PACKET_SIZE = 20;\n        private const int CMD_PROC_SCAN_PACKET_SIZE = 10;\n        private const int CMD_PROC_INFO_PACKET_SIZE = 4;\n        private const int CMD_PROC_ALLOC_PACKET_SIZE = 8;\n        private const int CMD_PROC_FREE_PACKET_SIZE = 16;\n        // receive size\n        private const int PROC_LIST_ENTRY_SIZE = 36;\n        private const int PROC_MAP_ENTRY_SIZE = 58;\n        private const int PROC_INSTALL_SIZE = 8;\n        private const int PROC_CALL_SIZE = 12;\n        private const int PROC_PROC_INFO_SIZE = 188;\n        private const int PROC_ALLOC_SIZE = 8;\n    \n\n        /// <summary>\n        /// Get current process list\n        /// </summary>\n        /// <returns></returns>\n        public ProcessList GetProcessList()\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_LIST, 0);\n            CheckStatus();\n\n            // recv count\n            byte[] bytes = new byte[4];\n            sock.Receive(bytes, 4, SocketFlags.None);\n            int number = BitConverter.ToInt32(bytes, 0);\n\n            // recv data\n            byte[] data = ReceiveData(number * PROC_LIST_ENTRY_SIZE);\n\n            // parse data\n            string[] names = new string[number];\n            int[] pids = new int[number];\n            for (int i = 0; i < number; i++)\n            {\n                int offset = i * PROC_LIST_ENTRY_SIZE;\n                names[i] = ConvertASCII(data, offset);\n                pids[i] = BitConverter.ToInt32(data, offset + 32);\n            }\n\n            return new ProcessList(number, names, pids);\n        }\n\n        /// <summary>\n        /// Read memory\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"address\">Memory address</param>\n        /// <param name=\"length\">Data length</param>\n        /// <returns></returns>\n        public byte[] ReadMemory(int pid, ulong address, int length)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_READ, CMD_PROC_READ_PACKET_SIZE, pid, address, length);\n            CheckStatus();\n            return ReceiveData(length);\n        }\n\n        /// <summary>\n        /// Write memory\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"address\">Memory address</param>\n        /// <param name=\"data\">Data</param>\n        public void WriteMemory(int pid, ulong address, byte[] data)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_WRITE, CMD_PROC_WRITE_PACKET_SIZE, pid, address, data.Length);\n            CheckStatus();\n            SendData(data, data.Length);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Get process memory maps\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <returns></returns>\n        public ProcessMap GetProcessMaps(int pid)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_MAPS, CMD_PROC_MAPS_PACKET_SIZE, pid);\n            CheckStatus();\n\n            // recv count\n            byte[] bnumber = new byte[4];\n            sock.Receive(bnumber, 4, SocketFlags.None);\n            int number = BitConverter.ToInt32(bnumber, 0);\n\n            // recv data\n            byte[] data = ReceiveData(number * PROC_MAP_ENTRY_SIZE);\n\n            // parse data\n            MemoryEntry[] entries = new MemoryEntry[number];\n            for (int i = 0; i < number; i++)\n            {\n                int offset = i * PROC_MAP_ENTRY_SIZE;\n                entries[i] = new MemoryEntry\n                {\n                    name = ConvertASCII(data, offset),\n                    start = BitConverter.ToUInt64(data, offset + 32),\n                    end = BitConverter.ToUInt64(data, offset + 40),\n                    offset = BitConverter.ToUInt64(data, offset + 48),\n                    prot = BitConverter.ToUInt16(data, offset + 56)\n                };\n\n            }\n\n            return new ProcessMap(pid, entries);\n        }\n\n        /// <summary>\n        /// Install RPC into a process, this returns a stub address that you should pass into call functions\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <returns></returns>\n        public ulong InstallRPC(int pid)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_INTALL, CMD_PROC_INSTALL_PACKET_SIZE, pid);\n            CheckStatus();\n\n            return BitConverter.ToUInt64(ReceiveData(PROC_INSTALL_SIZE), 0);\n        }\n\n        /// <summary>\n        /// Call function (returns rax)\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"rpcstub\">Stub address from InstallRPC</param>\n        /// <param name=\"address\">Address to call</param>\n        /// <param name=\"args\">Arguments array</param>\n        /// <returns></returns>\n        public ulong Call(int pid, ulong rpcstub, ulong address, params object[] args)\n        {\n            CheckConnected();\n\n            // need to do this in a custom format\n            CMDPacket packet = new CMDPacket\n            {\n                magic = CMD_PACKET_MAGIC,\n                cmd = (uint) CMDS.CMD_PROC_CALL,\n                datalen = (uint) CMD_PROC_CALL_PACKET_SIZE\n            };\n            SendData(GetBytesFromObject(packet), CMD_PACKET_SIZE);\n\n            MemoryStream rs = new MemoryStream();\n            rs.Write(BitConverter.GetBytes(pid), 0, sizeof(int));\n            rs.Write(BitConverter.GetBytes(rpcstub), 0, sizeof(ulong));\n            rs.Write(BitConverter.GetBytes(address), 0, sizeof(ulong));\n\n            int num = 0;\n            foreach (object arg in args)\n            {\n                byte[] bytes = new byte[8];\n\n                switch (arg)\n                {\n                    case char c:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(c);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(char));\n\n                            byte[] pad = new byte[sizeof(ulong) - sizeof(char)];\n                            Buffer.BlockCopy(pad, 0, bytes, sizeof(char), pad.Length);\n                            break;\n                        }\n                    case byte b:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(b);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(byte));\n\n                            byte[] pad = new byte[sizeof(ulong) - sizeof(byte)];\n                            Buffer.BlockCopy(pad, 0, bytes, sizeof(byte), pad.Length);\n                            break;\n                        }\n                    case short s:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(s);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(short));\n\n                            byte[] pad = new byte[sizeof(ulong) - sizeof(short)];\n                            Buffer.BlockCopy(pad, 0, bytes, sizeof(short), pad.Length);\n                            break;\n                        }\n                    case ushort us:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(us);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(ushort));\n\n                            byte[] pad = new byte[sizeof(ulong) - sizeof(ushort)];\n                            Buffer.BlockCopy(pad, 0, bytes, sizeof(ushort), pad.Length);\n                            break;\n                        }\n                    case int i:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(i);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(int));\n\n                            byte[] pad = new byte[sizeof(ulong) - sizeof(int)];\n                            Buffer.BlockCopy(pad, 0, bytes, sizeof(int), pad.Length);\n                            break;\n                        }\n                    case uint ui:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(ui);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(uint));\n\n                            byte[] pad = new byte[sizeof(ulong) - sizeof(uint)];\n                            Buffer.BlockCopy(pad, 0, bytes, sizeof(uint), pad.Length);\n                            break;\n                        }\n                    case long l:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(l);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(long));\n                            break;\n                        }\n                    case ulong ul:\n                        {\n                            byte[] tmp = BitConverter.GetBytes(ul);\n                            Buffer.BlockCopy(tmp, 0, bytes, 0, sizeof(ulong));\n                            break;\n                        }\n                }\n\n                rs.Write(bytes, 0, bytes.Length);\n                num++;\n            }\n\n            if (num > 6)\n            {\n                throw new Exception(\"libdbg: too many arguments\");\n            }\n\n            if (num < 6)\n            {\n                for (int i = 0; i < (6 - num); i++)\n                {\n                    rs.Write(BitConverter.GetBytes((ulong)0), 0, sizeof(ulong));\n                }\n            }\n\n            SendData(rs.ToArray(), CMD_PROC_CALL_PACKET_SIZE);\n            rs.Dispose();\n\n            CheckStatus();\n\n            byte[] data = ReceiveData(PROC_CALL_SIZE);\n            return BitConverter.ToUInt64(data, 4);\n        }\n\n        /// <summary>\n        /// Load elf\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"elf\">Elf</param>\n        public void LoadElf(int pid, byte[] elf)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_ELF, CMD_PROC_ELF_PACKET_SIZE, pid, (uint)elf.Length);\n            CheckStatus();\n            SendData(elf, elf.Length);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Load elf\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"filename\">Elf filename</param>\n        public void LoadElf(int pid, string filename)\n        {\n            LoadElf(pid, File.ReadAllBytes(filename));\n        }\n\n        public enum ScanValueType : byte\n        {\n            valTypeUInt8 = 0,\n            valTypeInt8,\n            valTypeUInt16,\n            valTypeInt16,\n            valTypeUInt32,\n            valTypeInt32,\n            valTypeUInt64,\n            valTypeInt64,\n            valTypeFloat,\n            valTypeDouble,\n            valTypeArrBytes,\n            valTypeString\n        }\n\n        public enum ScanCompareType : byte\n        {\n            ExactValue = 0,\n            FuzzyValue,\n            BiggerThan,\n            SmallerThan,\n            ValueBetween,\n            IncreasedValue,\n            IncreasedValueBy,\n            DecreasedValue,\n            DecreasedValueBy,\n            ChangedValue,\n            UnchangedValue,\n            UnknownInitialValue\n        }\n\n        public List<ulong> ScanProcess<T>(int pid, ScanCompareType compareType, T value, T extraValue = default)\n        {\n            CheckConnected();\n\n            int typeLength = 0;\n            ScanValueType valueType;\n            byte[] valueBuffer, extraValueBuffer = null;\n\n            // fill in variables\n            switch (value)\n            {\n                case bool b:\n                    valueType = ScanValueType.valTypeUInt8;\n                    typeLength = 1;\n                    valueBuffer = BitConverter.GetBytes(b);\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((bool)(object)extraValue);\n                    break;\n                case sbyte sb:\n                    valueType = ScanValueType.valTypeInt8;\n                    valueBuffer = BitConverter.GetBytes(sb);\n                    typeLength = 1;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((sbyte)(object)extraValue);\n                    break;\n                case byte b:\n                    valueType = ScanValueType.valTypeUInt8;\n                    valueBuffer = BitConverter.GetBytes(b);\n                    typeLength = 1;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((byte)(object)extraValue);\n                    break;\n                case short s:\n                    valueType = ScanValueType.valTypeInt16;\n                    valueBuffer = BitConverter.GetBytes(s);\n                    typeLength = 2;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((short)(object)extraValue);\n                    break;\n                case ushort us:\n                    valueType = ScanValueType.valTypeUInt16;\n                    valueBuffer = BitConverter.GetBytes(us);\n                    typeLength = 2;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((ushort)(object)extraValue);\n                    break;\n                case int i:\n                    valueType = ScanValueType.valTypeInt32;\n                    valueBuffer = BitConverter.GetBytes(i);\n                    typeLength = 4;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((int)(object)extraValue);\n                    break;\n                case uint ui:\n                    valueType = ScanValueType.valTypeUInt32;\n                    valueBuffer = BitConverter.GetBytes(ui);\n                    typeLength = 4;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((uint)(object)extraValue);\n                    break;\n                case long l:\n                    valueType = ScanValueType.valTypeInt64;\n                    valueBuffer = BitConverter.GetBytes(l);\n                    typeLength = 8;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((long)(object)extraValue);\n                    break;\n                case ulong ul:\n                    valueType = ScanValueType.valTypeUInt64;\n                    valueBuffer = BitConverter.GetBytes(ul);\n                    typeLength = 8;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((ulong)(object)extraValue);\n                    break;\n                case float f:\n                    valueType = ScanValueType.valTypeFloat;\n                    valueBuffer = BitConverter.GetBytes(f);\n                    typeLength = 4;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((float)(object)extraValue);\n                    break;\n                case double d:\n                    valueType = ScanValueType.valTypeDouble;\n                    valueBuffer = BitConverter.GetBytes(d);\n                    typeLength = 8;\n                    if (extraValue != null)\n                        extraValueBuffer = BitConverter.GetBytes((double)(object)extraValue);\n                    break;\n                case string s:\n                    valueType = ScanValueType.valTypeString;\n                    valueBuffer = Encoding.ASCII.GetBytes(s);\n                    typeLength = valueBuffer.Length;\n                    break;\n                case byte[] ba:\n                    valueType = ScanValueType.valTypeArrBytes;\n                    valueBuffer = ba;\n                    typeLength = valueBuffer.Length;\n                    break;\n                default:\n                    throw new NotSupportedException(\"Requested scan value type is not supported! (Feed in Byte[] instead.)\");\n                    \n            }\n            // send packet\n            SendCMDPacket(CMDS.CMD_PROC_SCAN, CMD_PROC_SCAN_PACKET_SIZE, pid, (byte)valueType, (byte)compareType, (int)(extraValue == null ? typeLength : typeLength * 2));\n            CheckStatus();\n\n            SendData(valueBuffer, typeLength);\n            if (extraValueBuffer != null)\n            {\n                SendData(extraValueBuffer, typeLength);\n            }\n\n            CheckStatus();\n\n            // receive results\n            int save = sock.ReceiveTimeout;\n            sock.ReceiveTimeout = Int32.MaxValue;\n            List<ulong> results = new List<ulong>();\n            while(true)\n            {\n                ulong result = BitConverter.ToUInt64(ReceiveData(sizeof(ulong)), 0);\n                if(result == 0xFFFFFFFFFFFFFFFF)\n                {\n                    break;\n                }\n\n                results.Add(result);\n            }\n\n            sock.ReceiveTimeout = save;\n\n            return results;\n        }\n\n        /// <summary>\n        /// Changes protection on pages in range\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"address\">Address</param>\n        /// <param name=\"length\">Length</param>\n        /// <param name=\"newprot\">New protection</param>\n        /// <returns></returns>\n        public void ChangeProtection(int pid, ulong address, uint length, VM_PROTECTIONS newProt)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_PROTECT, CMD_PROC_PROTECT_PACKET_SIZE, pid, address, length, (uint)newProt);\n            CheckStatus();\n        }\n\n        /// <summary>\n        /// Get process information\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <returns></returns>\n        public ProcessInfo GetProcessInfo(int pid)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_INFO, CMD_PROC_INFO_PACKET_SIZE, pid);\n            CheckStatus();\n\n            byte[] data = ReceiveData(PROC_PROC_INFO_SIZE);\n            return (ProcessInfo)GetObjectFromBytes(data, typeof(ProcessInfo));\n        }\n\n        /// <summary>\n        /// Allocate RWX memory in the process space\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"length\">Size of memory allocation</param>\n        /// <returns></returns>\n        public ulong AllocateMemory(int pid, int length)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_ALLOC, CMD_PROC_ALLOC_PACKET_SIZE, pid, length);\n            CheckStatus();\n            return BitConverter.ToUInt64(ReceiveData(PROC_ALLOC_SIZE), 0);\n        }\n\n        /// <summary>\n        /// Free memory in the process space\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"address\">Address of the memory allocation</param>\n        /// <param name=\"length\">Size of memory allocation</param>\n        /// <returns></returns>\n        public void FreeMemory(int pid, ulong address, int length)\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_PROC_FREE, CMD_PROC_FREE_PACKET_SIZE, pid, address, length);\n            CheckStatus();\n        }\n\n        public T ReadMemory<T>(int pid, ulong address)\n        {\n            if (typeof(T) == typeof(string))\n            {\n                string str = \"\";\n                ulong i = 0;\n\n                while (true)\n                {\n                    byte value = ReadMemory(pid, address + i, sizeof(byte))[0];\n                    if (value == 0)\n                    {\n                        break;\n                    }\n                    str += Convert.ToChar(value);\n                    i++;\n                }\n\n                return (T)(object)str;\n            }\n            \n            if (typeof(T) == typeof(byte[]))\n            {\n                throw new NotSupportedException(\"byte arrays are not supported, use ReadMemory(int pid, ulong address, int size)\");\n            }\n\n            return (T)GetObjectFromBytes(ReadMemory(pid, address, Marshal.SizeOf(typeof(T))), typeof(T));\n        }\n\n        public void WriteMemory<T>(int pid, ulong address, T value)\n        {\n            if (typeof(T) == typeof(string))\n            {\n                WriteMemory(pid, address, Encoding.ASCII.GetBytes((string)(object)value + (char)0x0));\n                return;\n            }\n\n            if (typeof(T) == typeof(byte[]))\n            {\n                WriteMemory(pid, address, (byte[])(object)value);\n                return;\n            }\n            \n            WriteMemory(pid, address, GetBytesFromObject(value));\n        }\n    }\n}"
  },
  {
    "path": "libdebug/PS4DBG.cs",
    "content": "using System;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading;\n\nnamespace libdebug\n{\n    public partial class PS4DBG\n    {\n        private Socket sock = null;\n        private IPEndPoint enp = null;\n\n        public bool IsConnected { get; private set; } = false;\n\n        public bool IsDebugging { get; private set; } = false;\n\n        private Thread debugThread = null;\n\n        // some global values\n        private const string LIBRARY_VERSION = \"1.2\";\n        private const int PS4DBG_PORT = 744;\n        private const int PS4DBG_DEBUG_PORT = 755;\n        private const int NET_MAX_LENGTH = 8192;\n\n        private const int BROADCAST_PORT = 1010;\n        private const uint BROADCAST_MAGIC = 0xFFFFAAAA;\n\n        // from protocol.h\n        // each packet starts with the magic\n        // each C# base type can translate into a packet field\n        // some packets, such as write take an additional data whose length will be specified in the cmd packet data field structure specific to that cmd type\n        // ushort - 2 bytes | uint - 4 bytes | ulong - 8 bytes\n        private const uint CMD_PACKET_MAGIC = 0xFFAABBCC;\n\n        // from debug.h\n        //struct debug_breakpoint {\n        //    uint32_t valid;\n        //    uint64_t address;\n        //    uint8_t original;\n        //};\n        public static uint MAX_BREAKPOINTS = 10;\n        public static uint MAX_WATCHPOINTS = 4;\n\n        //  struct cmd_packet {\n        //    uint32_t magic;\n        //    uint32_t cmd;\n        //    uint32_t datalen;\n        //    // (field not actually part of packet, comes after)\n        //    uint8_t* data;\n        //  }\n        //  __attribute__((packed));\n        //  #define CMD_PACKET_SIZE 12\n        private const int CMD_PACKET_SIZE = 12;\n        public enum CMDS : uint\n        {\n            CMD_VERSION = 0xBD000001,\n\n            CMD_PROC_LIST = 0xBDAA0001,\n            CMD_PROC_READ = 0xBDAA0002,\n            CMD_PROC_WRITE = 0xBDAA0003,\n            CMD_PROC_MAPS = 0xBDAA0004,\n            CMD_PROC_INTALL = 0xBDAA0005,\n            CMD_PROC_CALL = 0xBDAA0006,\n            CMD_PROC_ELF = 0xBDAA0007,\n            CMD_PROC_PROTECT = 0xBDAA0008,\n            CMD_PROC_SCAN = 0xBDAA0009,\n            CMD_PROC_INFO = 0xBDAA000A,\n            CMD_PROC_ALLOC = 0xBDAA000B,\n            CMD_PROC_FREE = 0xBDAA000C,\n\n            CMD_DEBUG_ATTACH = 0xBDBB0001,\n            CMD_DEBUG_DETACH = 0xBDBB0002,\n            CMD_DEBUG_BREAKPT = 0xBDBB0003,\n            CMD_DEBUG_WATCHPT = 0xBDBB0004,\n            CMD_DEBUG_THREADS = 0xBDBB0005,\n            CMD_DEBUG_STOPTHR = 0xBDBB0006,\n            CMD_DEBUG_RESUMETHR = 0xBDBB0007,\n            CMD_DEBUG_GETREGS = 0xBDBB0008,\n            CMD_DEBUG_SETREGS = 0xBDBB0009,\n            CMD_DEBUG_GETFPREGS = 0xBDBB000A,\n            CMD_DEBUG_SETFPREGS = 0xBDBB000B,\n            CMD_DEBUG_GETDBGREGS = 0xBDBB000C,\n            CMD_DEBUG_SETDBGREGS = 0xBDBB000D,\n            CMD_DEBUG_STOPGO = 0xBDBB0010,\n            CMD_DEBUG_THRINFO = 0xBDBB0011,\n            CMD_DEBUG_SINGLESTEP = 0xBDBB0012,\n\n            CMD_KERN_BASE = 0xBDCC0001,\n            CMD_KERN_READ = 0xBDCC0002,\n            CMD_KERN_WRITE = 0xBDCC0003,\n\n            CMD_CONSOLE_REBOOT = 0xBDDD0001,\n            CMD_CONSOLE_END = 0xBDDD0002,\n            CMD_CONSOLE_PRINT = 0xBDDD0003,\n            CMD_CONSOLE_NOTIFY = 0xBDDD0004,\n            CMD_CONSOLE_INFO = 0xBDDD0005,\n        };\n\n        public enum CMD_STATUS : uint\n        {\n            CMD_SUCCESS = 0x80000000,\n            CMD_ERROR = 0xF0000001,\n            CMD_TOO_MUCH_DATA = 0xF0000002,\n            CMD_DATA_NULL = 0xF0000003,\n            CMD_ALREADY_DEBUG = 0xF0000004,\n            CMD_INVALID_INDEX = 0xF0000005\n        };\n\n        [StructLayout(LayoutKind.Sequential, Pack = 1)]\n        public struct CMDPacket\n        {\n            public uint magic;\n            public uint cmd;\n            public uint datalen;\n        }\n\n        // enums\n        public enum VM_PROTECTIONS : uint\n        {\n            VM_PROT_NONE = 0x00,\n            VM_PROT_READ = 0x01,\n            VM_PROT_WRITE = 0x02,\n            VM_PROT_EXECUTE = 0x04,\n            VM_PROT_DEFAULT = (VM_PROT_READ | VM_PROT_WRITE),\n            VM_PROT_ALL = (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE),\n            VM_PROT_NO_CHANGE = 0x08,\n            VM_PROT_COPY = 0x10,\n            VM_PROT_WANTS_COPY = 0x10\n        };\n        public enum WATCHPT_LENGTH : uint\n        {\n            DBREG_DR7_LEN_1 = 0x00,\t/* 1 byte length */\n            DBREG_DR7_LEN_2 = 0x01,\n            DBREG_DR7_LEN_4 = 0x03,\n            DBREG_DR7_LEN_8 = 0x02,\n        };\n        public enum WATCHPT_BREAKTYPE : uint\n        {\n            DBREG_DR7_EXEC = 0x00,\t/* break on execute       */\n            DBREG_DR7_WRONLY = 0x01,\t/* break on write         */\n            DBREG_DR7_RDWR = 0x03,\t/* break on read or write */\n        };\n\n        // General helper functions, make code cleaner\n        private static string ConvertASCII(byte[] data, int offset)\n        {\n            int length = Array.IndexOf<byte>(data, 0, offset) - offset;\n            if (length < 0)\n            {\n                length = data.Length - offset;\n            }\n\n            return Encoding.ASCII.GetString(data, offset, length);\n        }\n        public static byte[] SubArray(byte[] data, int offset, int length)\n        {\n            byte[] bytes = new byte[length];\n            Buffer.BlockCopy(data, offset, bytes, 0, length);\n            return bytes;\n        }\n        public static object GetObjectFromBytes(byte[] buffer, Type type)\n        {\n            int size = Marshal.SizeOf(type);\n\n            IntPtr ptr = Marshal.AllocHGlobal(size);\n\n            Marshal.Copy(buffer, 0, ptr, size);\n            object r = Marshal.PtrToStructure(ptr, type);\n\n            Marshal.FreeHGlobal(ptr);\n\n            return r;\n        }\n        private static byte[] GetBytesFromObject(object obj)\n        {\n            int size = Marshal.SizeOf(obj);\n\n            byte[] bytes = new byte[size];\n            IntPtr ptr = Marshal.AllocHGlobal(size);\n\n            Marshal.StructureToPtr(obj, ptr, false);\n            Marshal.Copy(ptr, bytes, 0, size);\n\n            Marshal.FreeHGlobal(ptr);\n\n            return bytes;\n        }\n\n        // General networking functions\n        private static IPAddress GetBroadcastAddress(IPAddress address, IPAddress subnetMask)\n        {\n            byte[] ipAdressBytes = address.GetAddressBytes();\n            byte[] subnetMaskBytes = subnetMask.GetAddressBytes();\n\n            byte[] broadcastAddress = new byte[ipAdressBytes.Length];\n            for (int i = 0; i < broadcastAddress.Length; i++)\n            {\n                broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));\n            }\n\n            return new IPAddress(broadcastAddress);\n        }\n        private void SendCMDPacket(CMDS cmd, int length, params object[] fields)\n        {\n            CMDPacket packet = new CMDPacket\n            {\n                magic = CMD_PACKET_MAGIC,\n                cmd = (uint) cmd,\n                datalen = (uint) length\n            };\n\n            byte[] data = null;\n\n            if (length > 0)\n            {\n                MemoryStream rs = new MemoryStream();\n                foreach (object field in fields)\n                {\n                    byte[] bytes = null;\n\n                    switch (field)\n                    {\n                        case char c:\n                            bytes = BitConverter.GetBytes(c);\n                            break;\n                        case byte b:\n                            bytes = BitConverter.GetBytes(b);\n                            break;\n                        case short s:\n                            bytes = BitConverter.GetBytes(s);\n                            break;\n                        case ushort us:\n                            bytes = BitConverter.GetBytes(us);\n                            break;\n                        case int i:\n                            bytes = BitConverter.GetBytes(i);\n                            break;\n                        case uint u:\n                            bytes = BitConverter.GetBytes(u);\n                            break;\n                        case long l:\n                            bytes = BitConverter.GetBytes(l);\n                            break;\n                        case ulong ul:\n                            bytes = BitConverter.GetBytes(ul);\n                            break;\n                        case byte[] ba:\n                            bytes = ba;\n                            break;\n                    }\n\n                    if (bytes != null) rs.Write(bytes, 0, bytes.Length);\n                }\n\n                data = rs.ToArray();\n                rs.Dispose();\n            }\n\n            SendData(GetBytesFromObject(packet), CMD_PACKET_SIZE);\n\n            if (data != null)\n            {\n                SendData(data, length);\n            }\n        }\n        private void SendData(byte[] data, int length)\n        {\n            int left = length;\n            int offset = 0;\n            int sent = 0;\n\n            while (left > 0)\n            {\n                if (left > NET_MAX_LENGTH)\n                {\n                    byte[] bytes = SubArray(data, offset, NET_MAX_LENGTH);\n                    sent = sock.Send(bytes, NET_MAX_LENGTH, SocketFlags.None);\n                }\n                else\n                {\n                    byte[] bytes = SubArray(data, offset, left);\n                    sent = sock.Send(bytes, left, SocketFlags.None);\n                }\n\n                offset += sent;\n                left -= sent;\n            }\n        }\n        private byte[] ReceiveData(int length)\n        {\n            MemoryStream s = new MemoryStream();\n\n            int left = length;\n            int recv = 0;\n            while (left > 0)\n            {\n                byte[] b = new byte[NET_MAX_LENGTH];\n                recv = sock.Receive(b, NET_MAX_LENGTH, SocketFlags.None);\n                s.Write(b, 0, recv);\n                left -= recv;\n            }\n\n            byte[] data = s.ToArray();\n\n            s.Dispose();\n            GC.Collect();\n\n            return data;\n        }\n        private CMD_STATUS ReceiveStatus()\n        {\n            byte[] status = new byte[4];\n            sock.Receive(status, 4, SocketFlags.None);\n            return (CMD_STATUS)BitConverter.ToUInt32(status, 0);\n        }\n        private void CheckStatus()\n        {\n            CMD_STATUS status = ReceiveStatus();\n            if (status != CMD_STATUS.CMD_SUCCESS)\n            {\n                throw new Exception(\"libdbg status \" + ((uint)status).ToString(\"X\"));\n            }\n        }\n\n        private void CheckConnected()\n        {\n            if (!IsConnected)\n            {\n                throw new Exception(\"libdbg: not connected\");\n            }\n        }\n        private void CheckDebugging()\n        {\n            if (!IsDebugging)\n            {\n                throw new Exception(\"libdbg: not debugging\");\n            }\n        }\n\n\n        public PS4DBG()\n        {\n            enp = null;\n            sock = null;\n        }\n\n        /// <summary>\n        /// Initializes PS4DBG class\n        /// </summary>\n        /// <param name=\"addr\">PlayStation 4 address</param>\n        public PS4DBG(IPAddress addr)\n        {\n            enp = new IPEndPoint(addr, PS4DBG_PORT);\n            sock = new Socket(enp.AddressFamily, SocketType.Stream, ProtocolType.Tcp);\n        }\n\n        /// <summary>\n        /// Initializes PS4DBG class\n        /// </summary>\n        /// <param name=\"ip\">PlayStation 4 ip address</param>\n        public PS4DBG(string ip)\n        {\n            IPAddress addr = null;\n            try\n            {\n                addr = IPAddress.Parse(ip);\n            }\n            catch (FormatException ex)\n            {\n                throw ex;\n            }\n\n            enp = new IPEndPoint(addr, PS4DBG_PORT);\n            sock = new Socket(enp.AddressFamily, SocketType.Stream, ProtocolType.Tcp);\n        }\n\n        /// <summary>\n        /// Find the playstation ip\n        /// </summary>\n        public static string FindPlayStation()\n        {\n            UdpClient uc = new UdpClient();\n            IPEndPoint server = new IPEndPoint(IPAddress.Any, 0);\n            uc.EnableBroadcast = true;\n            uc.Client.ReceiveTimeout = 4000;\n\n            byte[] magic = BitConverter.GetBytes(BROADCAST_MAGIC);\n\n            IPAddress addr = null;\n            IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());\n            foreach (IPAddress ip in host.AddressList)\n            {\n                if (ip.AddressFamily == AddressFamily.InterNetwork)\n                {\n                    addr = ip;\n                }\n            }\n\n            if (addr == null)\n            {\n                throw new Exception(\"libdbg broadcast error: could not get host ip\");\n            }\n\n            uc.Send(magic, magic.Length, new IPEndPoint(GetBroadcastAddress(addr, IPAddress.Parse(\"255.255.255.0\")), BROADCAST_PORT));\n\n            byte[] resp = uc.Receive(ref server);\n            if (BitConverter.ToUInt32(resp, 0) != BROADCAST_MAGIC)\n            {\n                throw new Exception(\"libdbg broadcast error: wrong magic on udp server\");\n            }\n\n            return server.Address.ToString();\n        }\n\n        /// <summary>\n        /// Connects to PlayStation 4\n        /// </summary>\n        public void Connect()\n        {\n            if (!IsConnected)\n            {\n                sock.NoDelay = true;\n                sock.ReceiveBufferSize = NET_MAX_LENGTH;\n                sock.SendBufferSize = NET_MAX_LENGTH;\n\n                sock.ReceiveTimeout = -1;\n                IAsyncResult result = sock.BeginConnect(enp, null, null);\n                result.AsyncWaitHandle.WaitOne(3000);\n                IsConnected = sock.Connected;\n            }\n        }\n\n        /// <summary>\n        /// Disconnects from PlayStation 4\n        /// </summary>\n        public void Disconnect()\n        {\n            SendCMDPacket(CMDS.CMD_CONSOLE_END, 0);\n            sock.Shutdown(SocketShutdown.Both);\n            sock.Close();\n            IsConnected = false;\n        }\n\n        /// <summary>\n        /// Get current ps4debug version from library\n        /// </summary>\n        public string GetLibraryDebugVersion()\n        {\n            return LIBRARY_VERSION;\n        }\n\n        /// <summary>\n        /// Get the current ps4debug version from console\n        /// </summary>\n        public string GetConsoleDebugVersion()\n        {\n            CheckConnected();\n\n            SendCMDPacket(CMDS.CMD_VERSION, 0);\n\n            byte[] ldata = new byte[4];\n            sock.Receive(ldata, 4, SocketFlags.None);\n\n            int length = BitConverter.ToInt32(ldata, 0);\n\n            byte[] data = new byte[length];\n            sock.Receive(data, length, SocketFlags.None);\n\n            return ConvertASCII(data, 0);\n        }\n    }\n}"
  },
  {
    "path": "libdebug/Process.cs",
    "content": "using System.Runtime.InteropServices;\n\nnamespace libdebug\n{\n    public class Process\n    {\n        public string name;\n        public int pid;\n\n        /// <summary>\n        /// Initializes Process class\n        /// </summary>\n        /// <param name=\"name\">Process name</param>\n        /// <param name=\"pid\">Process ID</param>\n        /// <returns></returns>\n        public Process(string name, int pid)\n        {\n            this.name = name;\n            this.pid = pid;\n        }\n        public override string ToString()\n        {\n            return $\"[{pid:X}] {name}\";\n        }\n    }\n\n    public class ProcessList\n    {\n        public Process[] processes;\n\n        /// <summary>\n        /// Initializes ProcessList class\n        /// </summary>\n        /// <param name=\"number\">Number of processes</param>\n        /// <param name=\"names\">Process names</param>\n        /// <param name=\"pids\">Process IDs</param>\n        /// <returns></returns>\n        public ProcessList(int number, string[] names, int[] pids)\n        {\n            processes = new Process[number];\n            for (int i = 0; i < number; i++)\n            {\n                processes[i] = new Process(names[i], pids[i]);\n            }\n        }\n\n        /// <summary>\n        /// Finds a process based off name\n        /// </summary>\n        /// <param name=\"name\">Process name</param>\n        /// <param name=\"contains\">Condition to check if process name contains name</param>\n        /// <returns></returns>\n        public Process FindProcess(string name, bool contains = false)\n        {\n            foreach (Process p in processes)\n            {\n                if (contains)\n                {\n                    if (p.name.Contains(name))\n                    {\n                        return p;\n                    }\n                }\n                else\n                {\n                    if (p.name == name)\n                    {\n                        return p;\n                    }\n                }\n            }\n\n            return null;\n        }\n    }\n\n    public class MemoryEntry\n    {\n        public string name;\n        public ulong start;\n        public ulong end;\n        public ulong offset;\n        public uint prot;\n\n        public override string ToString()\n        {\n            return $\"{name} 0x{start:X}\";\n        }\n    }\n\n    public class ProcessMap\n    {\n        public int pid;\n        public MemoryEntry[] entries;\n\n        /// <summary>\n        /// Initializes ProcessMap class with memory entries and process ID\n        /// </summary>\n        /// <param name=\"pid\">Process ID</param>\n        /// <param name=\"entries\">Process memory entries</param>\n        /// <returns></returns>\n        public ProcessMap(int pid, MemoryEntry[] entries)\n        {\n            this.pid = pid;\n            this.entries = entries;\n        }\n\n        /// <summary>\n        /// Finds a virtual memory entry based off name\n        /// </summary>\n        /// <param name=\"name\">Virtual memory entry name</param>\n        /// <param name=\"contains\">Condition to check if entry name contains name</param>\n        /// <returns></returns>\n        public MemoryEntry FindEntry(string name, bool contains = false)\n        {\n            foreach (MemoryEntry entry in entries)\n            {\n                if (contains)\n                {\n                    if (entry.name.Contains(name))\n                    {\n                        return entry;\n                    }\n                }\n                else\n                {\n                    if (entry.name == name)\n                    {\n                        return entry;\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        /// <summary>\n        /// Finds a virtual memory entry based off size\n        /// </summary>\n        /// <param name=\"size\">Virtual memory entry size</param>\n        /// <returns></returns>\n        public MemoryEntry FindEntry(ulong size)\n        {\n            foreach (MemoryEntry entry in entries)\n            {\n                if ((entry.start - entry.end) == size)\n                {\n                    return entry;\n                }\n            }\n\n            return null;\n        }\n    }\n\n    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]\n    public struct ProcessInfo\n    {\n        public int pid;\n\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]\n        public string name;\n\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]\n        public string path;\n\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]\n        public string titleid;\n\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]\n        public string contentid;\n    }\n\n    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]\n    public struct ThreadInfo\n    {\n        public int pid;\n        public int priority;\n\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]\n        public string name;\n    }\n}"
  },
  {
    "path": "libdebug/Registers.cs",
    "content": "using System.Runtime.InteropServices;\n\nnamespace libdebug\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 1)]\n    public struct regs\n    {\n        public ulong r_r15;\n        public ulong r_r14;\n        public ulong r_r13;\n        public ulong r_r12;\n        public ulong r_r11;\n        public ulong r_r10;\n        public ulong r_r9;\n        public ulong r_r8;\n        public ulong r_rdi;\n        public ulong r_rsi;\n        public ulong r_rbp;\n        public ulong r_rbx;\n        public ulong r_rdx;\n        public ulong r_rcx;\n        public ulong r_rax;\n        public uint r_trapno;\n        public ushort r_fs;\n        public ushort r_gs;\n        public uint r_err;\n        public ushort r_es;\n        public ushort r_ds;\n        public ulong r_rip;\n        public ulong r_cs;\n        public ulong r_rflags;\n        public ulong r_rsp;\n        public ulong r_ss;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct envxmm\n    {\n        public ushort en_cw; /* control word (16bits) */\n        public ushort en_sw; /* status word (16bits) */\n        public byte en_tw; /* tag word (8bits) */\n        public byte en_zero;\n        public ushort en_opcode; /* opcode last executed (11 bits ) */\n        public ulong en_rip; /* floating point instruction pointer */\n        public ulong en_rdp; /* floating operand pointer */\n        public uint en_mxcsr; /* SSE sontorol/status register */\n        public uint en_mxcsr_mask; /* valid bits in mxcsr */\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct acc\n    {\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]\n        public byte[] fp_bytes;\n\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]\n        private byte[] fp_pad;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct xmmacc\n    {\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]\n        public byte[] xmm_bytes;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ymmacc\n    {\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]\n        public byte[] ymm_bytes;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct xstate_hdr\n    {\n        public ulong xstate_bv;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]\n        private byte[] xstate_rsrv0;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]\n        private byte[] xstate_rsrv;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct savefpu_xstate\n    {\n        public xstate_hdr sx_hd;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]\n        public ymmacc[] sx_ymm;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 64)]\n    public struct fpregs\n    {\n        public envxmm svn_env;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]\n        public acc[] sv_fp;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]\n        public xmmacc[] sv_xmm;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]\n        private byte[] sv_pad;\n        public savefpu_xstate sv_xstate;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 1)]\n    public struct dbregs\n    {\n        public ulong dr0;\n        public ulong dr1;\n        public ulong dr2;\n        public ulong dr3;\n        public ulong dr4;\n        public ulong dr5;\n        public ulong dr6;\n        public ulong dr7;\n        public ulong dr8;\n        public ulong dr9;\n        public ulong dr10;\n        public ulong dr11;\n        public ulong dr12;\n        public ulong dr13;\n        public ulong dr14;\n        public ulong dr15;\n    }\n}"
  },
  {
    "path": "offsets.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace PS4Saves\n{\n    class offsets\n    {\n        public const int sceUserServiceGetInitialUser = 0x33B0;\n        public const int sceUserServiceGetLoginUserIdList = 0x2B40;\n        public const int sceUserServiceGetUserName = 0x3F20;\n\n        public const int sceSaveDataMount = 0x248D0;\n        public const int sceSaveDataUmount = 0x250C0;\n        public const int sceSaveDataDirNameSearch = 0x25CA0;\n        public const int sceSaveDataInitialize3 = 0x24740;\n    }\n}\n"
  },
  {
    "path": "structs.cs",
    "content": "﻿using System.Runtime.InteropServices;\n\nnamespace PS4Saves\n{\n    [StructLayout(LayoutKind.Explicit, Size = 80)]\n    public struct SceSaveDataMount\n    {\n        [FieldOffset(0x0)] public int userId;\n        [FieldOffset(0x8)] public ulong titleId;\n        [FieldOffset(0x10)] public ulong dirName;\n        [FieldOffset(0x18)] public ulong fingerprint;\n        [FieldOffset(0x20)] public ulong blocks;\n        [FieldOffset(0x28)] public uint mountMode;\n    }\n\n    [StructLayout(LayoutKind.Explicit, Size = 64)]\n    public struct SceSaveDataMount2\n    {\n        [FieldOffset(0x0)] public int userId;\n        [FieldOffset(0x8)] public ulong dirName;\n        [FieldOffset(0x10)] public ulong blocks;\n        [FieldOffset(0x18)] public uint mountMode;\n    }\n    [StructLayout(LayoutKind.Explicit, Size = 64)]\n    public struct SceSaveDataMountResult\n    {\n        [FieldOffset(0x0)] public SceSaveDataMountPoint mountPoint;\n        [FieldOffset(0x20)] public ulong requiredBlocks;\n        [FieldOffset(0x28)] public uint mountStatus;\n\n    }\n\n    [StructLayout(LayoutKind.Sequential, Size = 16)]\n    public struct SceSaveDataMountPoint\n    {\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]\n        public string data;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Size = 64)]\n    public struct SceSaveDataTransferringMount\n    {\n        public int userId;\n        public ulong titleId;\n        public ulong dirName;\n        public ulong fingerprint;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Size = 16)]\n    public struct SceSaveDataTitleId\n    {\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]\n        public string data;\n    }\n    [StructLayout(LayoutKind.Sequential, Size = 32)]\n    public struct SceSaveDataDirName\n    {\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]\n        public string data;\n    }\n    [StructLayout(LayoutKind.Sequential, Size = 80)]\n    public struct SceSaveDataFingerprint\n    {\n        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]\n        public string data;\n    }\n    [StructLayout(LayoutKind.Explicit, Size = 64)]\n    public struct SceSaveDataDirNameSearchCond\n    {\n        [FieldOffset(0x0)] public int userId;\n        [FieldOffset(0x8)] public ulong titleId;\n        [FieldOffset(0x10)] public ulong dirName;\n        [FieldOffset(0x18)] public uint key;\n        [FieldOffset(0x1C)] public uint order;\n    }\n    [StructLayout(LayoutKind.Explicit, Size = 56)]\n    public struct SceSaveDataDirNameSearchResult\n    {\n        [FieldOffset(0x0)] public uint hitNum;\n        [FieldOffset(0x8)] public ulong dirNames;\n        [FieldOffset(0x10)] public uint dirNamesNum;\n        [FieldOffset(0x14)] public uint setNum;\n        [FieldOffset(0x18)] public ulong param;\n        [FieldOffset(0x20)] public ulong infos;\n    }\n    [StructLayout(LayoutKind.Explicit, Size = 1328)]\n    public struct SceSaveDataParam\n    {\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]\n        [FieldOffset(0x0)] public byte[] title;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]\n        [FieldOffset(0x80)] public byte[] subTitle;\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]\n        [FieldOffset(0x100)] public byte[] detail;\n        [FieldOffset(0x500)] public uint userParam;\n        [FieldOffset(0x508)] public long mtime;\n    }\n    [StructLayout(LayoutKind.Sequential, Size = 48)]\n    public struct SceSaveDataSearchInfo\n    {\n        public ulong blocks;\n        public ulong freeBlocks;\n    }\n}\n"
  }
]