forked from MeloNX/MeloNX
WIP: Message bridge
This commit is contained in:
parent
e924da52ec
commit
23be667c7b
@ -108,6 +108,10 @@
|
|||||||
"Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib" = (
|
"Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib" = (
|
||||||
CodeSignOnCopy,
|
CodeSignOnCopy,
|
||||||
);
|
);
|
||||||
|
"Dependencies/Dynamic Libraries/RyujinxBridge.framework" = (
|
||||||
|
CodeSignOnCopy,
|
||||||
|
RemoveHeadersOnCopy,
|
||||||
|
);
|
||||||
"Dependencies/Dynamic Libraries/RyujinxKeyboard.framework" = (
|
"Dependencies/Dynamic Libraries/RyujinxKeyboard.framework" = (
|
||||||
CodeSignOnCopy,
|
CodeSignOnCopy,
|
||||||
RemoveHeadersOnCopy,
|
RemoveHeadersOnCopy,
|
||||||
@ -169,6 +173,7 @@
|
|||||||
"Dependencies/Dynamic Libraries/libavutil.dylib",
|
"Dependencies/Dynamic Libraries/libavutil.dylib",
|
||||||
"Dependencies/Dynamic Libraries/libMoltenVK.dylib",
|
"Dependencies/Dynamic Libraries/libMoltenVK.dylib",
|
||||||
"Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib",
|
"Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib",
|
||||||
|
"Dependencies/Dynamic Libraries/RyujinxBridge.framework",
|
||||||
"Dependencies/Dynamic Libraries/RyujinxKeyboard.framework",
|
"Dependencies/Dynamic Libraries/RyujinxKeyboard.framework",
|
||||||
Dependencies/XCFrameworks/libavcodec.xcframework,
|
Dependencies/XCFrameworks/libavcodec.xcframework,
|
||||||
Dependencies/XCFrameworks/libavfilter.xcframework,
|
Dependencies/XCFrameworks/libavfilter.xcframework,
|
||||||
@ -633,7 +638,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = 95J8WZ4TN8;
|
DEVELOPMENT_TEAM = D59DHVRS87;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
ENABLE_TESTABILITY = NO;
|
ENABLE_TESTABILITY = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@ -763,7 +768,7 @@
|
|||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.3.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
PRODUCT_BUNDLE_IDENTIFIER = com.xitrix.MeloNX;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h";
|
||||||
@ -781,7 +786,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = 95J8WZ4TN8;
|
DEVELOPMENT_TEAM = D59DHVRS87;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@ -911,7 +916,7 @@
|
|||||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.3.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
PRODUCT_BUNDLE_IDENTIFIER = com.xitrix.MeloNX;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h";
|
||||||
|
Binary file not shown.
@ -0,0 +1,116 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Bucket
|
||||||
|
uuid = "56EBE536-1F4C-4BCE-853B-D3E000BE57CD"
|
||||||
|
type = "1"
|
||||||
|
version = "2.0">
|
||||||
|
<Breakpoints>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "71A20387-E5D5-42A9-99A1-7D1B6BEB6A04"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "Yes"
|
||||||
|
symbolName = "UIApplicationMain"
|
||||||
|
moduleName = "">
|
||||||
|
<Actions>
|
||||||
|
<BreakpointActionProxy
|
||||||
|
ActionExtensionID = "Xcode.BreakpointAction.DebuggerCommand">
|
||||||
|
<ActionContent
|
||||||
|
consoleCommand = "process handle SIGUSR1 -n true -p true -s false">
|
||||||
|
</ActionContent>
|
||||||
|
</BreakpointActionProxy>
|
||||||
|
</Actions>
|
||||||
|
<Locations>
|
||||||
|
<Location
|
||||||
|
uuid = "71A20387-E5D5-42A9-99A1-7D1B6BEB6A04 - dc2f8c5e001177f0"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
symbolName = "UIApplicationMain"
|
||||||
|
moduleName = "UIKitCore"
|
||||||
|
usesParentBreakpointCondition = "Yes">
|
||||||
|
</Location>
|
||||||
|
</Locations>
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "2A095BA1-FC06-4890-9989-2C4A83A0F028"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "Yes"
|
||||||
|
symbolName = "UIApplicationMain"
|
||||||
|
moduleName = "">
|
||||||
|
<Actions>
|
||||||
|
<BreakpointActionProxy
|
||||||
|
ActionExtensionID = "Xcode.BreakpointAction.DebuggerCommand">
|
||||||
|
<ActionContent
|
||||||
|
consoleCommand = "process handle SIGBUS -n true -p true -s false">
|
||||||
|
</ActionContent>
|
||||||
|
</BreakpointActionProxy>
|
||||||
|
</Actions>
|
||||||
|
<Locations>
|
||||||
|
<Location
|
||||||
|
uuid = "2A095BA1-FC06-4890-9989-2C4A83A0F028 - dc2f8c5e001177f0"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
symbolName = "UIApplicationMain"
|
||||||
|
moduleName = "UIKitCore"
|
||||||
|
usesParentBreakpointCondition = "Yes">
|
||||||
|
</Location>
|
||||||
|
</Locations>
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "A363121B-631E-4ADE-8A05-D3D9538EE31D"
|
||||||
|
shouldBeEnabled = "No"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "MeloNX/App/Core/Ryujinx/RyujinxBridge.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "43"
|
||||||
|
endingLineNumber = "43"
|
||||||
|
landmarkName = "parseMessage(_:)"
|
||||||
|
landmarkType = "7">
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "482C1F2E-138F-49D2-A590-8B98AC9B790E"
|
||||||
|
shouldBeEnabled = "No"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "MeloNX/App/Core/Ryujinx/RyujinxBridge.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "32"
|
||||||
|
endingLineNumber = "32"
|
||||||
|
landmarkName = "parseMessage(_:)"
|
||||||
|
landmarkType = "7">
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "FF32B294-2681-4A6E-9DFA-0D13DA242EAF"
|
||||||
|
shouldBeEnabled = "No"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "MeloNX/App/Core/Ryujinx/RyujinxBridge.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "30"
|
||||||
|
endingLineNumber = "30"
|
||||||
|
landmarkName = "parseMessage(_:)"
|
||||||
|
landmarkType = "7">
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
|
</Breakpoints>
|
||||||
|
</Bucket>
|
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>SchemeUserState</key>
|
||||||
|
<dict>
|
||||||
|
<key>MeloNX.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<key>Ryujinx.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
</dict>
|
||||||
|
<key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -8,6 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import GameController
|
import GameController
|
||||||
|
import RyujinxBridge
|
||||||
|
|
||||||
struct Controller: Identifiable, Hashable {
|
struct Controller: Identifiable, Hashable {
|
||||||
var id: String
|
var id: String
|
||||||
@ -49,6 +50,13 @@ class Ryujinx {
|
|||||||
static let shared = Ryujinx()
|
static let shared = Ryujinx()
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
|
messageDelegate = { messagePtr in
|
||||||
|
guard let messagePtr else { return }
|
||||||
|
let message = String(cString: messagePtr)
|
||||||
|
RyujinxBridgeHelper.parseMessage(message)
|
||||||
|
print("Message: \(message)")
|
||||||
|
}
|
||||||
|
|
||||||
self.games = loadGames()
|
self.games = loadGames()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,7 +521,6 @@ class Ryujinx {
|
|||||||
var windowInfo = SDL_SysWMinfo()
|
var windowInfo = SDL_SysWMinfo()
|
||||||
SDL_GetWindowWMInfo(window, &windowInfo)
|
SDL_GetWindowWMInfo(window, &windowInfo)
|
||||||
|
|
||||||
|
|
||||||
guard let uiWindow = windowInfo.info.uikit.window,
|
guard let uiWindow = windowInfo.info.uikit.window,
|
||||||
let rootView = uiWindow.takeUnretainedValue().rootViewController?.view else {
|
let rootView = uiWindow.takeUnretainedValue().rootViewController?.view else {
|
||||||
print("Unable to get root view")
|
print("Unable to get root view")
|
||||||
|
45
src/MeloNX/MeloNX/App/Core/Ryujinx/RyujinxBridge.swift
Normal file
45
src/MeloNX/MeloNX/App/Core/Ryujinx/RyujinxBridge.swift
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// RyujinxBridge.swift
|
||||||
|
// MeloNX
|
||||||
|
//
|
||||||
|
// Created by Daniil Vinogradov on 17/02/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
struct BridgeAlertMessage: Codable {
|
||||||
|
var title: String?
|
||||||
|
var type: String?
|
||||||
|
var metadata: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BridgePayload<T> {
|
||||||
|
var type: String
|
||||||
|
var model: T
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RyujinxBridgeHelper {
|
||||||
|
static func parseMessage(_ message: String) {
|
||||||
|
guard let data = message.data(using: .utf8),
|
||||||
|
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||||
|
let type = json["type"] as? String,
|
||||||
|
let model = json["model"],
|
||||||
|
let modelData = try? JSONSerialization.data(withJSONObject: model)
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
switch type {
|
||||||
|
case "BridgeAlertMessage":
|
||||||
|
guard let model = try? JSONDecoder().decode(BridgeAlertMessage.self, from: modelData)
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// let alertVC = UIAlertController(title: model.title, message: model.type, preferredStyle: .alert)
|
||||||
|
// alertVC.addAction(.init(title: "OK", style: .cancel))
|
||||||
|
print("ALERT!!!! \(model.title) \(model.type) \(model.metadata)")
|
||||||
|
// UIApplication.shared.windows.first?.rootViewController?.present(alertVC, animated: true)
|
||||||
|
}
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
print("Type: \(type)")
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import SwiftSVG
|
//import SwiftSVG
|
||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
@Binding var config: Ryujinx.Configuration
|
@Binding var config: Ryujinx.Configuration
|
||||||
@ -439,36 +439,42 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
.tint(.blue)
|
.tint(.blue)
|
||||||
|
|
||||||
if #available(iOS 17.0.1, *) {
|
// if #available(iOS 17.0.1, *) {
|
||||||
Toggle(isOn: $jitStreamerEB) {
|
// Toggle(isOn: $jitStreamerEB) {
|
||||||
labelWithIcon("JitStreamer EB", iconName: "bolt.heart")
|
// labelWithIcon("JitStreamer EB", iconName: "bolt.heart")
|
||||||
}
|
// }
|
||||||
.tint(.blue)
|
// .tint(.blue)
|
||||||
.contextMenu {
|
// .contextMenu {
|
||||||
Button {
|
// Button {
|
||||||
if let mainWindow = UIApplication.shared.windows.last {
|
// if let mainWindow = UIApplication.shared.windows.last {
|
||||||
let alertController = UIAlertController(title: "About JitStreamer EB", message: "JitStreamer EB is an Amazing Application to Enable JIT on the go, made by one of the best iOS developers of all time jkcoxson <3", preferredStyle: .alert)
|
// let alertController = UIAlertController(title: "About JitStreamer EB", message: "JitStreamer EB is an Amazing Application to Enable JIT on the go, made by one of the best iOS developers of all time jkcoxson <3", preferredStyle: .alert)
|
||||||
|
//
|
||||||
let learnMoreButton = UIAlertAction(title: "Learn More", style: .default) {_ in
|
// let learnMoreButton = UIAlertAction(title: "Learn More", style: .default) {_ in
|
||||||
UIApplication.shared.open(URL(string: "https://jkcoxson.com/jitstreamer")!)
|
// UIApplication.shared.open(URL(string: "https://jkcoxson.com/jitstreamer")!)
|
||||||
}
|
// }
|
||||||
alertController.addAction(learnMoreButton)
|
// alertController.addAction(learnMoreButton)
|
||||||
|
//
|
||||||
let doneButton = UIAlertAction(title: "Done", style: .cancel, handler: nil)
|
// let doneButton = UIAlertAction(title: "Done", style: .cancel, handler: nil)
|
||||||
alertController.addAction(doneButton)
|
// alertController.addAction(doneButton)
|
||||||
|
//
|
||||||
mainWindow.rootViewController?.present(alertController, animated: true)
|
// mainWindow.rootViewController?.present(alertController, animated: true)
|
||||||
}
|
// }
|
||||||
} label: {
|
// } label: {
|
||||||
Text("About")
|
// Text("About")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
Toggle(isOn: $useTrollStore) {
|
Toggle(isOn: $useTrollStore) {
|
||||||
labelWithIcon("TrollStore JIT", iconName: "troll.svg")
|
HStack(spacing: 8) {
|
||||||
|
Image("troll")
|
||||||
|
.symbolRenderingMode(.hierarchical)
|
||||||
|
.foregroundStyle(.blue)
|
||||||
|
Text("TrollStore JIT")
|
||||||
|
}
|
||||||
|
.font(.body)
|
||||||
}
|
}
|
||||||
.tint(.blue)
|
.tint(.blue)
|
||||||
}
|
// }
|
||||||
|
|
||||||
Toggle(isOn: $syncqsubmits) {
|
Toggle(isOn: $syncqsubmits) {
|
||||||
labelWithIcon("MVK: Synchronous Queue Submits", iconName: "line.diagonal")
|
labelWithIcon("MVK: Synchronous Queue Submits", iconName: "line.diagonal")
|
||||||
@ -695,56 +701,11 @@ struct SettingsView: View {
|
|||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private func labelWithIcon(_ text: String, iconName: String, flipimage: Bool? = nil) -> some View {
|
private func labelWithIcon(_ text: String, iconName: String, flipimage: Bool? = nil) -> some View {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
if iconName.hasSuffix(".svg"){
|
|
||||||
if let flipimage, flipimage {
|
|
||||||
SVGView(svgName: iconName, color: .blue)
|
|
||||||
.symbolRenderingMode(.hierarchical)
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
.rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))
|
|
||||||
} else {
|
|
||||||
SVGView(svgName: iconName, color: .blue)
|
|
||||||
.symbolRenderingMode(.hierarchical)
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
}
|
|
||||||
} else if !iconName.isEmpty {
|
|
||||||
Image(systemName: iconName)
|
Image(systemName: iconName)
|
||||||
.symbolRenderingMode(.hierarchical)
|
.symbolRenderingMode(.hierarchical)
|
||||||
.foregroundStyle(.blue)
|
.foregroundStyle(.blue)
|
||||||
}
|
|
||||||
Text(text)
|
Text(text)
|
||||||
}
|
}
|
||||||
.font(.body)
|
.font(.body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct SVGView: UIViewRepresentable {
|
|
||||||
var svgName: String
|
|
||||||
var color: Color = Color.black
|
|
||||||
|
|
||||||
func makeUIView(context: Context) -> UIView {
|
|
||||||
var svgName = svgName
|
|
||||||
var hammock = UIView()
|
|
||||||
|
|
||||||
if svgName.hasSuffix(".svg") {
|
|
||||||
svgName.removeLast(4)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let svgLayer = UIView(SVGNamed: svgName) { svgLayer in
|
|
||||||
svgLayer.fillColor = UIColor(color).cgColor // Apply the provided color
|
|
||||||
svgLayer.resizeToFit(hammock.frame)
|
|
||||||
hammock.layer.addSublayer(svgLayer)
|
|
||||||
}
|
|
||||||
|
|
||||||
return hammock
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateUIView(_ uiView: UIView, context: Context) {
|
|
||||||
// Update the SVG view's fill color when the color changes
|
|
||||||
if let svgLayer = uiView.layer.sublayers?.first as? CAShapeLayer {
|
|
||||||
svgLayer.fillColor = UIColor(color).cgColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
12
src/MeloNX/MeloNX/Assets/Assets.xcassets/troll.imageset/Contents.json
vendored
Normal file
12
src/MeloNX/MeloNX/Assets/Assets.xcassets/troll.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Troll-Face.svg",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
16
src/MeloNX/MeloNX/Assets/Assets.xcassets/troll.imageset/Troll-Face.svg
vendored
Normal file
16
src/MeloNX/MeloNX/Assets/Assets.xcassets/troll.imageset/Troll-Face.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// RyujinxBridge.h
|
||||||
|
// RyujinxBridge
|
||||||
|
//
|
||||||
|
// Created by Daniil Vinogradov on 17/02/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
//! Project version number for RyujinxBridge.
|
||||||
|
FOUNDATION_EXPORT double RyujinxBridgeVersionNumber;
|
||||||
|
|
||||||
|
//! Project version string for RyujinxBridge.
|
||||||
|
FOUNDATION_EXPORT const unsigned char RyujinxBridgeVersionString[];
|
||||||
|
|
||||||
|
// In this header, you should import all the public headers of your framework using statements like #import <RyujinxBridge/PublicHeader.h>
|
||||||
|
#import <RyujinxBridge/bridge.h>
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
//
|
||||||
|
// bridge.h
|
||||||
|
// RyujinxBridge
|
||||||
|
//
|
||||||
|
// Created by Daniil Vinogradov on 17/02/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
void (*messageDelegate)(const char*);
|
Binary file not shown.
@ -0,0 +1,6 @@
|
|||||||
|
framework module RyujinxBridge {
|
||||||
|
umbrella header "RyujinxBridge.h"
|
||||||
|
export *
|
||||||
|
|
||||||
|
module * { export * }
|
||||||
|
}
|
Binary file not shown.
@ -0,0 +1,135 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>files</key>
|
||||||
|
<dict>
|
||||||
|
<key>Headers/RyujinxBridge.h</key>
|
||||||
|
<data>
|
||||||
|
DKD2r8aJ47TZL7v48UVEfod716g=
|
||||||
|
</data>
|
||||||
|
<key>Headers/bridge.h</key>
|
||||||
|
<data>
|
||||||
|
p75HJMB/G5CAZ+yTApMWmoQP7Lg=
|
||||||
|
</data>
|
||||||
|
<key>Info.plist</key>
|
||||||
|
<data>
|
||||||
|
mWbK0knhX+Q4WAm+hZd8SF0ioS0=
|
||||||
|
</data>
|
||||||
|
<key>Modules/module.modulemap</key>
|
||||||
|
<data>
|
||||||
|
+to1dvHz+3pPZcmBu4qsYsrvt4Y=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
<key>files2</key>
|
||||||
|
<dict>
|
||||||
|
<key>Headers/RyujinxBridge.h</key>
|
||||||
|
<dict>
|
||||||
|
<key>hash2</key>
|
||||||
|
<data>
|
||||||
|
xIPdWru4HW7sRYRg6G+ehIk9V4nX3Uv7kIlE2c/TnjM=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
<key>Headers/bridge.h</key>
|
||||||
|
<dict>
|
||||||
|
<key>hash2</key>
|
||||||
|
<data>
|
||||||
|
kA+OGSf2EzopJ1KM/+Lp8qHheuFQQYlkkOdMg/ywzH8=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
<key>Modules/module.modulemap</key>
|
||||||
|
<dict>
|
||||||
|
<key>hash2</key>
|
||||||
|
<data>
|
||||||
|
ZTC6KjLczI++298LFW6y9c8aoPQ1LrrsJrDJfrPnZUU=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>rules</key>
|
||||||
|
<dict>
|
||||||
|
<key>^.*</key>
|
||||||
|
<true/>
|
||||||
|
<key>^.*\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>optional</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^.*\.lproj/locversion.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1100</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Base\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1010</real>
|
||||||
|
</dict>
|
||||||
|
<key>^version.plist$</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>rules2</key>
|
||||||
|
<dict>
|
||||||
|
<key>.*\.dSYM($|/)</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>11</real>
|
||||||
|
</dict>
|
||||||
|
<key>^(.*/)?\.DS_Store$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>2000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^.*</key>
|
||||||
|
<true/>
|
||||||
|
<key>^.*\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>optional</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^.*\.lproj/locversion.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1100</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Base\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1010</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Info\.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^PkgInfo$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^embedded\.provisionprofile$</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^version\.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -2,6 +2,8 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>com.apple.developer.kernel.increased-debugging-memory-limit</key>
|
||||||
|
<true/>
|
||||||
<key>com.apple.developer.kernel.increased-memory-limit</key>
|
<key>com.apple.developer.kernel.increased-memory-limit</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
|
41
src/Ryujinx.Headless.SDL2/MessageBridge-iOS.cs
Normal file
41
src/Ryujinx.Headless.SDL2/MessageBridge-iOS.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Headless.SDL2
|
||||||
|
{
|
||||||
|
struct BridgeAlertMessage(string title, string message, string metadata = null)
|
||||||
|
{
|
||||||
|
[JsonProperty("title")]
|
||||||
|
string Title { get; set; } = title;
|
||||||
|
|
||||||
|
[JsonProperty("message")]
|
||||||
|
string Message { get; set; } = message;
|
||||||
|
|
||||||
|
[JsonProperty("metadata")]
|
||||||
|
string Metadata { get; set; } = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MessageBridge
|
||||||
|
{
|
||||||
|
[DllImport("RyujinxBridge.framework/RyujinxBridge", CallingConvention = CallingConvention.Cdecl, EntryPoint="sendMessage")]
|
||||||
|
private static extern void SendMessage(string json);
|
||||||
|
|
||||||
|
public static void SendPayload<T>(T model)
|
||||||
|
{
|
||||||
|
string jsonString = JsonConvert.SerializeObject(new BridgePayload<T>(typeof(T).Name, model));
|
||||||
|
SendMessage(jsonString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct BridgePayload<T>(string type, T model)
|
||||||
|
{
|
||||||
|
[JsonProperty("type")]
|
||||||
|
private string Type { get; set; } = type;
|
||||||
|
|
||||||
|
[JsonProperty("model")]
|
||||||
|
private T Model { get; set; } = model;
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||||
@ -85,6 +84,7 @@ using ARMeilleure.Translation;
|
|||||||
using LibHac.Ncm;
|
using LibHac.Ncm;
|
||||||
using LibHac.Tools.FsSystem.NcaUtils;
|
using LibHac.Tools.FsSystem.NcaUtils;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
@ -94,6 +94,7 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using SDL2;
|
using SDL2;
|
||||||
|
using JsonException = System.Text.Json.JsonException;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless.SDL2
|
||||||
{
|
{
|
||||||
@ -117,6 +118,13 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
|
// [UnmanagedCallersOnly(EntryPoint = "get_dlc_nca_list")]
|
||||||
|
// public static unsafe void CDeclCombine(delegate* unmanaged[Cdecl]<void> combinator) =>
|
||||||
|
// combinator(left, right);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void TestDelegate(int a, int b);
|
||||||
|
|
||||||
[UnmanagedCallersOnly(EntryPoint = "main_ryujinx_sdl")]
|
[UnmanagedCallersOnly(EntryPoint = "main_ryujinx_sdl")]
|
||||||
public static unsafe int MainExternal(int argCount, IntPtr* pArgs)
|
public static unsafe int MainExternal(int argCount, IntPtr* pArgs)
|
||||||
{
|
{
|
||||||
@ -403,6 +411,8 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
[UnmanagedCallersOnly(EntryPoint = "get_game_info")]
|
[UnmanagedCallersOnly(EntryPoint = "get_game_info")]
|
||||||
public static GameInfoNative GetGameInfoNative(int descriptor, IntPtr extensionPtr)
|
public static GameInfoNative GetGameInfoNative(int descriptor, IntPtr extensionPtr)
|
||||||
{
|
{
|
||||||
|
MessageBridge.SendPayload(new BridgeAlertMessage("Text", "Alalallala"));
|
||||||
|
|
||||||
if (_virtualFileSystem == null) {
|
if (_virtualFileSystem == null) {
|
||||||
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
||||||
}
|
}
|
||||||
|
@ -477,8 +477,8 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
public bool DisplayMessageDialog(string title, string message)
|
public bool DisplayMessageDialog(string title, string message)
|
||||||
{
|
{
|
||||||
SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, title, message, WindowHandle);
|
// SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, title, message, WindowHandle);
|
||||||
|
MessageBridge.SendPayload(new BridgeAlertMessage(title, message, "controllerApplet"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user