forked from MeloNX/MeloNX
DRM Update
This commit is contained in:
parent
2d5f1d8015
commit
4f3e49a90c
@ -632,6 +632,8 @@
|
|||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
);
|
);
|
||||||
GCC_OPTIMIZATION_LEVEL = fast;
|
GCC_OPTIMIZATION_LEVEL = fast;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@ -671,6 +673,10 @@
|
|||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.0.8;
|
MARKETING_VERSION = 0.0.8;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
||||||
@ -705,6 +711,8 @@
|
|||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
);
|
);
|
||||||
GCC_OPTIMIZATION_LEVEL = fast;
|
GCC_OPTIMIZATION_LEVEL = fast;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@ -744,6 +752,10 @@
|
|||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.0.8;
|
MARKETING_VERSION = 0.0.8;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
||||||
|
Binary file not shown.
@ -12,12 +12,12 @@
|
|||||||
<key>Ryujinx.xcscheme_^#shared#^_</key>
|
<key>Ryujinx.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>1</integer>
|
<integer>2</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key>
|
<key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>2</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>SuppressBuildableAutocreation</key>
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
// Created by Stossy11 on 3/11/2024.
|
// Created by Stossy11 on 3/11/2024.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#define DRM 1
|
||||||
|
|
||||||
#ifndef RyujinxHeader
|
#ifndef RyujinxHeader
|
||||||
#define RyujinxHeader
|
#define RyujinxHeader
|
||||||
|
|
||||||
@ -13,6 +15,7 @@
|
|||||||
#include <SDL2/SDL_syswm.h>
|
#include <SDL2/SDL_syswm.h>
|
||||||
#import "utils.h"
|
#import "utils.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,12 +20,10 @@ class VirtualController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func setupVirtualController() {
|
private func setupVirtualController() {
|
||||||
// Initialize SDL if not already initialized
|
|
||||||
if SDL_WasInit(Uint32(SDL_INIT_GAMECONTROLLER)) == 0 {
|
if SDL_WasInit(Uint32(SDL_INIT_GAMECONTROLLER)) == 0 {
|
||||||
SDL_InitSubSystem(Uint32(SDL_INIT_GAMECONTROLLER))
|
SDL_InitSubSystem(Uint32(SDL_INIT_GAMECONTROLLER))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create virtual controller
|
|
||||||
var joystickDesc = SDL_VirtualJoystickDesc(
|
var joystickDesc = SDL_VirtualJoystickDesc(
|
||||||
version: UInt16(SDL_VIRTUAL_JOYSTICK_DESC_VERSION),
|
version: UInt16(SDL_VIRTUAL_JOYSTICK_DESC_VERSION),
|
||||||
type: Uint16(SDL_JOYSTICK_TYPE_GAMECONTROLLER.rawValue),
|
type: Uint16(SDL_JOYSTICK_TYPE_GAMECONTROLLER.rawValue),
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Screenshot.swift
|
||||||
|
// MeloNX
|
||||||
|
//
|
||||||
|
// Created by Stossy11 on 09/02/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIView {
|
||||||
|
func screenshot() -> UIImage? {
|
||||||
|
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0)
|
||||||
|
defer { UIGraphicsEndImageContext() }
|
||||||
|
|
||||||
|
self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
|
||||||
|
return UIGraphicsGetImageFromCurrentImageContext()
|
||||||
|
}
|
||||||
|
}
|
@ -87,7 +87,7 @@ class Ryujinx {
|
|||||||
var macroHLE: Bool
|
var macroHLE: Bool
|
||||||
var ignoreMissingServices: Bool
|
var ignoreMissingServices: Bool
|
||||||
var expandRam: Bool
|
var expandRam: Bool
|
||||||
|
var dfsIntegrityChecks: Bool
|
||||||
|
|
||||||
|
|
||||||
init(gamepath: String,
|
init(gamepath: String,
|
||||||
@ -108,7 +108,8 @@ class Ryujinx {
|
|||||||
macroHLE: Bool = false,
|
macroHLE: Bool = false,
|
||||||
ignoreMissingServices: Bool = false,
|
ignoreMissingServices: Bool = false,
|
||||||
hypervisor: Bool = false,
|
hypervisor: Bool = false,
|
||||||
expandRam: Bool = false
|
expandRam: Bool = false,
|
||||||
|
dfsIntegrityChecks: Bool = false
|
||||||
) {
|
) {
|
||||||
self.gamepath = gamepath
|
self.gamepath = gamepath
|
||||||
self.inputids = inputids
|
self.inputids = inputids
|
||||||
@ -129,6 +130,7 @@ class Ryujinx {
|
|||||||
self.expandRam = expandRam
|
self.expandRam = expandRam
|
||||||
self.ignoreMissingServices = ignoreMissingServices
|
self.ignoreMissingServices = ignoreMissingServices
|
||||||
self.hypervisor = hypervisor
|
self.hypervisor = hypervisor
|
||||||
|
self.dfsIntegrityChecks = dfsIntegrityChecks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,13 +234,17 @@ class Ryujinx {
|
|||||||
args.append("--use-hypervisor")
|
args.append("--use-hypervisor")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.dfsIntegrityChecks {
|
||||||
|
args.append("--disable-fs-integrity-checks")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if config.resscale != 1.0 {
|
if config.resscale != 1.0 {
|
||||||
args.append(contentsOf: ["--resolution-scale", String(config.resscale)])
|
args.append(contentsOf: ["--resolution-scale", String(config.resscale)])
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.expandRam {
|
if config.expandRam {
|
||||||
args.append(contentsOf: ["--expand-ram", String(config.maxAnisotropy)])
|
args.append(contentsOf: ["--expand-ram", String(config.expandRam)])
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.ignoreMissingServices {
|
if config.ignoreMissingServices {
|
||||||
|
@ -59,8 +59,12 @@ struct ContentView: View {
|
|||||||
// MoltenVKSettings(string: "MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS", value: "1"),
|
// MoltenVKSettings(string: "MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS", value: "1"),
|
||||||
// MoltenVKSettings(string: "MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS", value: "2"),
|
// MoltenVKSettings(string: "MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS", value: "2"),
|
||||||
// Metal Private API isn't needed and causes more stutters
|
// Metal Private API isn't needed and causes more stutters
|
||||||
MoltenVKSettings(string: "MVK_USE_METAL_PRIVATE_API", value: "0"),
|
MoltenVKSettings(string: "MVK_USE_METAL_PRIVATE_API", value: "1"),
|
||||||
MoltenVKSettings(string: "MVK_CONFIG_USE_METAL_PRIVATE_API", value: "0"),
|
MoltenVKSettings(string: "MVK_CONFIG_USE_METAL_PRIVATE_API", value: "1"),
|
||||||
|
MoltenVKSettings(string: "MVK_DEBUG", value: "1"),
|
||||||
|
MoltenVKSettings(string: "MVK_CONFIG_LOG_LEVEL", value: "2"),
|
||||||
|
// MVK_CONFIG_LOG_LEVEL
|
||||||
|
//MVK_DEBUG
|
||||||
// Uses more ram but makes performance higher, may add an option in settings to change or enable / disable this value (default 64 or 192 depending on what i decide)
|
// Uses more ram but makes performance higher, may add an option in settings to change or enable / disable this value (default 64 or 192 depending on what i decide)
|
||||||
MoltenVKSettings(string: "MVK_CONFIG_MAX_ACTIVE_METAL_COMMAND_BUFFERS_PER_QUEUE", value: "1024"),
|
MoltenVKSettings(string: "MVK_CONFIG_MAX_ACTIVE_METAL_COMMAND_BUFFERS_PER_QUEUE", value: "1024"),
|
||||||
]
|
]
|
||||||
@ -76,21 +80,29 @@ struct ContentView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
if game != nil, quits == false {
|
if game != nil, quits == false {
|
||||||
if isLoading {
|
if isLoading {
|
||||||
emulationView
|
if Air.shared.connected {
|
||||||
.onAppear() {
|
Text("")
|
||||||
// This is fro the old exiting game feature that didn't work properly. will look into it and figure out a better alternative
|
.onAppear() {
|
||||||
/*
|
Air.play(AnyView(emulationView))
|
||||||
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
|
|
||||||
timer.invalidate()
|
|
||||||
quits = quit
|
|
||||||
|
|
||||||
if quits {
|
|
||||||
quit = false
|
|
||||||
timer.invalidate()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
} else {
|
||||||
}
|
|
||||||
|
emulationView
|
||||||
|
.onAppear() {
|
||||||
|
// This is fro the old exiting game feature that didn't work properly. will look into it and figure out a better alternative
|
||||||
|
/*
|
||||||
|
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
|
||||||
|
timer.invalidate()
|
||||||
|
quits = quit
|
||||||
|
|
||||||
|
if quits {
|
||||||
|
quit = false
|
||||||
|
timer.invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is when the game starts to stop the animation
|
// This is when the game starts to stop the animation
|
||||||
EmulationView()
|
EmulationView()
|
||||||
@ -187,7 +199,7 @@ struct ContentView: View {
|
|||||||
|
|
||||||
|
|
||||||
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
|
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
|
||||||
if Ryujinx.shared.metalLayer != nil {
|
if get_current_fps() != 0 {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
isLoading = false
|
isLoading = false
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import SwiftUI
|
|||||||
// Emulation View
|
// Emulation View
|
||||||
struct EmulationView: View {
|
struct EmulationView: View {
|
||||||
@AppStorage("isVirtualController") var isVCA: Bool = true
|
@AppStorage("isVirtualController") var isVCA: Bool = true
|
||||||
|
@AppStorage("showScreenShotButton") var ssb: Bool = false
|
||||||
@State var isAirplaying = Air.shared.connected
|
@State var isAirplaying = Air.shared.connected
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
@ -29,6 +30,30 @@ struct EmulationView: View {
|
|||||||
if isVCA {
|
if isVCA {
|
||||||
ControllerView() // Virtual Controller
|
ControllerView() // Virtual Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ssb {
|
||||||
|
Group {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
|
||||||
|
Button {
|
||||||
|
if let screenshot = Ryujinx.shared.emulationUIView.screenshot() {
|
||||||
|
UIImageWriteToSavedPhotosAlbum(screenshot, nil, nil, nil)
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "square.and.arrow.up")
|
||||||
|
}
|
||||||
|
.frame(width: UIDevice.current.systemName.contains("iPadOS") ? 60 * 1.2 : 45, height: UIDevice.current.systemName.contains("iPadOS") ? 60 * 1.2 : 45)
|
||||||
|
.padding()
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
Air.shared.connectionCallbacks.append { cool in
|
Air.shared.connectionCallbacks.append { cool in
|
||||||
|
100
src/MeloNX/MeloNX/App/Views/Logging/Logs.swift
Normal file
100
src/MeloNX/MeloNX/App/Views/Logging/Logs.swift
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// LogEntry.swift
|
||||||
|
// MeloNX
|
||||||
|
//
|
||||||
|
// Created by Stossy11 on 09/02/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct LogEntry: Identifiable, Equatable {
|
||||||
|
let id = UUID()
|
||||||
|
let text: String
|
||||||
|
|
||||||
|
static func == (lhs: LogEntry, rhs: LogEntry) -> Bool {
|
||||||
|
return lhs.id == rhs.id && lhs.text == rhs.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LogViewer: View {
|
||||||
|
@State private var logs: [LogEntry] = []
|
||||||
|
@State private var latestLogFilePath: String?
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
VStack {
|
||||||
|
ForEach(logs) { log in
|
||||||
|
Text(log.text)
|
||||||
|
.padding(4)
|
||||||
|
.background(Color.black.opacity(0.7))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.cornerRadius(8)
|
||||||
|
.transition(.move(edge: .top).combined(with: .opacity))
|
||||||
|
.animation(.easeOut(duration: 2), value: logs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
.onAppear {
|
||||||
|
findNewestLogFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findNewestLogFile() {
|
||||||
|
let logsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("logs")
|
||||||
|
|
||||||
|
guard let directory = logsDirectory else { return }
|
||||||
|
|
||||||
|
do {
|
||||||
|
let logFiles = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: [.contentModificationDateKey], options: .skipsHiddenFiles)
|
||||||
|
|
||||||
|
// Sort files by modification date (newest first)
|
||||||
|
let sortedFiles = logFiles.sorted {
|
||||||
|
(try? $0.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) ?? Date.distantPast >
|
||||||
|
(try? $1.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) ?? Date.distantPast
|
||||||
|
}
|
||||||
|
|
||||||
|
if let newestLogFile = sortedFiles.first {
|
||||||
|
latestLogFilePath = newestLogFile.path
|
||||||
|
startReadingLogFile()
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
print("Error reading log files: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func startReadingLogFile() {
|
||||||
|
guard let path = latestLogFilePath else { return }
|
||||||
|
let fileHandle = try? FileHandle(forReadingAtPath: path)
|
||||||
|
fileHandle?.seekToEndOfFile()
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(forName: .NSFileHandleDataAvailable, object: fileHandle, queue: .main) { _ in
|
||||||
|
if let data = fileHandle?.availableData, !data.isEmpty {
|
||||||
|
if let logLine = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
withAnimation {
|
||||||
|
logs.append(LogEntry(text: logLine))
|
||||||
|
}
|
||||||
|
// Remove old logs after a delay
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
|
withAnimation {
|
||||||
|
removelogfirst()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileHandle?.waitForDataInBackgroundAndNotify()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileHandle?.waitForDataInBackgroundAndNotify()
|
||||||
|
}
|
||||||
|
|
||||||
|
func removelogfirst() {
|
||||||
|
logs.removeFirst()
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,8 @@ struct SettingsView: View {
|
|||||||
@AppStorage("RyuDemoControls") var ryuDemo: Bool = false
|
@AppStorage("RyuDemoControls") var ryuDemo: Bool = false
|
||||||
@AppStorage("MTL_HUD_ENABLED") var metalHUDEnabled: Bool = false
|
@AppStorage("MTL_HUD_ENABLED") var metalHUDEnabled: Bool = false
|
||||||
|
|
||||||
|
@AppStorage("showScreenShotButton") var ssb: Bool = false
|
||||||
|
|
||||||
@AppStorage("MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS") var mVKPreFillBuffer: Bool = false
|
@AppStorage("MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS") var mVKPreFillBuffer: Bool = false
|
||||||
|
|
||||||
@AppStorage("performacehud") var performacehud: Bool = false
|
@AppStorage("performacehud") var performacehud: Bool = false
|
||||||
@ -103,7 +105,7 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Slider(value: $config.resscale, in: 0.1...3.0, step: 0.1) {
|
Slider(value: $config.resscale, in: 0.1...3.0, step: 0.05) {
|
||||||
Text("Resolution Scale")
|
Text("Resolution Scale")
|
||||||
} minimumValueLabel: {
|
} minimumValueLabel: {
|
||||||
Text("0.1x")
|
Text("0.1x")
|
||||||
@ -347,6 +349,11 @@ struct SettingsView: View {
|
|||||||
// Other Settings
|
// Other Settings
|
||||||
Section {
|
Section {
|
||||||
|
|
||||||
|
Toggle(isOn: $ssb) {
|
||||||
|
labelWithIcon("Screenshot Button", iconName: "square.and.arrow.up")
|
||||||
|
}
|
||||||
|
.tint(.blue)
|
||||||
|
|
||||||
Toggle(isOn: $useTrollStore) {
|
Toggle(isOn: $useTrollStore) {
|
||||||
labelWithIcon("TrollStore", iconName: "troll.svg")
|
labelWithIcon("TrollStore", iconName: "troll.svg")
|
||||||
}
|
}
|
||||||
@ -361,13 +368,15 @@ struct SettingsView: View {
|
|||||||
labelWithIcon("Trace Logs", iconName: "waveform.path")
|
labelWithIcon("Trace Logs", iconName: "waveform.path")
|
||||||
}
|
}
|
||||||
.tint(.blue)
|
.tint(.blue)
|
||||||
|
|
||||||
|
|
||||||
} header: {
|
} header: {
|
||||||
Text("Miscellaneous Options")
|
Text("Miscellaneous Options")
|
||||||
.font(.title3.weight(.semibold))
|
.font(.title3.weight(.semibold))
|
||||||
.textCase(nil)
|
.textCase(nil)
|
||||||
.headerProminence(.increased)
|
.headerProminence(.increased)
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("Enable logs for troubleshooting and Enable automatic TrollStore JIT.")
|
Text("Enable trace and debug logs for troubleshooting, enable Screenshotting without distractions and Enable automatic TrollStore JIT.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advanced
|
// Advanced
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>MeloID</key>
|
<key>MeloID</key>
|
||||||
<string>1d0e26921bac938456ee7210ff4f2fa701dc16c02de1760e0aa757db28818ec7</string>
|
<string>83f67a0a96bd8628a150d7853e360db5bae64e7769524fae399c4b8e7e6aff17</string>
|
||||||
<key>UIFileSharingEnabled</key>
|
<key>UIFileSharingEnabled</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
<key>UTExportedTypeDeclarations</key>
|
||||||
|
@ -9,46 +9,81 @@ import SwiftUI
|
|||||||
import UIKit
|
import UIKit
|
||||||
import CryptoKit
|
import CryptoKit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct MeloNXApp: App {
|
struct MeloNXApp: App {
|
||||||
|
|
||||||
@AppStorage("showeddrmcheck") var showed = true
|
@State var showed = false
|
||||||
|
|
||||||
init() {
|
|
||||||
DispatchQueue.main.async { [self] in
|
var body: some Scene {
|
||||||
// drmcheck()
|
WindowGroup {
|
||||||
InitializeRyujinx() { bool in
|
ZStack {
|
||||||
if bool {
|
if showed {
|
||||||
print("Ryujinx Files Initialized Successfully")
|
ContentView()
|
||||||
} else {
|
} else {
|
||||||
// exit(0)
|
Group {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text("Loading...")
|
||||||
|
ProgressView()
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text(UIDevice.current.identifierForVendor?.uuidString ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
initR()
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.background(Color.black.opacity(1))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initR() {
|
||||||
|
if DRM == 1 {
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
|
// drmcheck()
|
||||||
|
InitializeRyujinx() { bool in
|
||||||
|
if bool {
|
||||||
|
print("Ryujinx Files Initialized Successfully")
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
|
withAnimation {
|
||||||
|
showed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
||||||
|
InitializeRyujinx() { bool in
|
||||||
|
if !bool {
|
||||||
|
withAnimation {
|
||||||
|
showed = false
|
||||||
|
}
|
||||||
|
showDMCAAlert()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
showDMCAAlert()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
|
||||||
InitializeRyujinx() { bool in
|
|
||||||
if !bool {
|
|
||||||
// exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some Scene {
|
|
||||||
WindowGroup {
|
|
||||||
if showed {
|
|
||||||
ContentView()
|
|
||||||
} else {
|
|
||||||
HStack {
|
|
||||||
Text("Loading...")
|
|
||||||
ProgressView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func showAlert() {
|
func showAlert() {
|
||||||
// Create the alert controller
|
// Create the alert controller
|
||||||
@ -87,8 +122,21 @@ struct MeloNXApp: App {
|
|||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showDMCAAlert() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if let mainWindow = UIApplication.shared.windows.last {
|
||||||
|
let alertController = UIAlertController(title: "Unauthorized Copy Notice", message: "This app was illegally leaked. Please report the download on the MeloNX Discord. In the meantime, check out Pomelo! \n -Stossy11", preferredStyle: .alert)
|
||||||
|
|
||||||
|
mainWindow.rootViewController!.present(alertController, animated: true, completion: nil)
|
||||||
|
} else {
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func drmcheck(completion: @escaping (Bool) -> Void) {
|
func drmcheck(completion: @escaping (Bool) -> Void) {
|
||||||
@ -132,22 +180,47 @@ func drmcheck(completion: @escaping (Bool) -> Void) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func InitializeRyujinx(completion: @escaping (Bool) -> Void) {
|
func InitializeRyujinx(completion: @escaping (Bool) -> Void) {
|
||||||
let path = "aHR0cHM6Ly9zdG9zc3kxMS5jb20vd293LnR4dA=="
|
let path = "aHR0cHM6Ly9teC5zdG9zc3kxMS5jb20v"
|
||||||
|
|
||||||
guard let value = Bundle.main.object(forInfoDictionaryKey: "MeloID") as? String, !value.isEmpty else {
|
guard let value = Bundle.main.object(forInfoDictionaryKey: "MeloID") as? String, !value.isEmpty else {
|
||||||
exit(0)
|
completion(false)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (detectRoms(path: path) != value) {
|
if (detectRoms(path: path) != value) {
|
||||||
exit(0)
|
completion(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
let task = URLSession.shared.dataTask(with: URL(string: addFolders(path)!)!) { data, response, error in
|
let configuration = URLSessionConfiguration.default
|
||||||
let text = String(data: data ?? Data(), encoding: .utf8) ?? ""
|
configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
|
||||||
print(text)
|
configuration.urlCache = nil
|
||||||
completion(text.contains("true"))
|
|
||||||
|
let session = URLSession(configuration: configuration)
|
||||||
|
|
||||||
|
guard let url = URL(string: addFolders(path)!) else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let task = session.dataTask(with: url) { data, response, error in
|
||||||
|
if error != nil {
|
||||||
|
completion(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
guard let httpResponse = response as? HTTPURLResponse else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if httpResponse.statusCode == 200 {
|
||||||
|
completion(true)
|
||||||
|
} else {
|
||||||
|
completion(false)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
task.resume()
|
task.resume()
|
||||||
}
|
}
|
||||||
@ -163,8 +236,15 @@ func detectRoms(path string: String) -> String {
|
|||||||
func addFolders(_ folderPath: String) -> String? {
|
func addFolders(_ folderPath: String) -> String? {
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
if let data = Data(base64Encoded: folderPath),
|
if let data = Data(base64Encoded: folderPath),
|
||||||
let decodedString = String(data: data, encoding: .utf8) {
|
let decodedString = String(data: data, encoding: .utf8), let fileURL = UIDevice.current.identifierForVendor?.uuidString {
|
||||||
return decodedString
|
return decodedString + "auth/" + fileURL + "/"
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
|
||||||
|
func print() {
|
||||||
|
Swift.print(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -26,6 +26,8 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK
|
|||||||
if (OperatingSystem.IsIOSVersionAtLeast(17)) {
|
if (OperatingSystem.IsIOSVersionAtLeast(17)) {
|
||||||
config.SemaphoreSupportStyle = MVKVkSemaphoreSupportStyle.MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE;
|
config.SemaphoreSupportStyle = MVKVkSemaphoreSupportStyle.MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.MaxActiveMetalCommandBuffersPerQueue = 1024;
|
||||||
|
|
||||||
config.SynchronousQueueSubmits = false;
|
config.SynchronousQueueSubmits = false;
|
||||||
|
|
||||||
|
@ -450,23 +450,12 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
};
|
};
|
||||||
renderLoopThread.Start();
|
renderLoopThread.Start();
|
||||||
|
|
||||||
Thread nvidiaStutterWorkaround = null;
|
|
||||||
if (Renderer is OpenGLRenderer)
|
|
||||||
{
|
|
||||||
nvidiaStutterWorkaround = new Thread(NvidiaStutterWorkaround)
|
|
||||||
{
|
|
||||||
Name = "GUI.NvidiaStutterWorkaround",
|
|
||||||
};
|
|
||||||
nvidiaStutterWorkaround.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
MainLoop();
|
MainLoop();
|
||||||
|
|
||||||
// NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
|
// NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
|
||||||
// We only need to wait for all commands submitted during the main gpu loop to be processed.
|
// We only need to wait for all commands submitted during the main gpu loop to be processed.
|
||||||
_gpuDoneEvent.WaitOne();
|
_gpuDoneEvent.WaitOne();
|
||||||
_gpuDoneEvent.Dispose();
|
_gpuDoneEvent.Dispose();
|
||||||
nvidiaStutterWorkaround?.Join();
|
|
||||||
|
|
||||||
Exit();
|
Exit();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user