forked from MeloNX/MeloNX
Add Mii Maker (and try and fail to add the Software controller)
This commit is contained in:
parent
c5736f9b15
commit
438c1a896f
@ -8,7 +8,7 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */ = {isa = PBXBuildFile; productRef = 4E0DED332D05695D00FEF007 /* SwiftUIJoystick */; };
|
||||
4E551F202CF128540096A2DF /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E80AA622CD7122800029585 /* GameController.framework */; };
|
||||
4E4854022D138D7600A446A6 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E80AA622CD7122800029585 /* GameController.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -65,6 +65,10 @@
|
||||
"Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib" = (
|
||||
CodeSignOnCopy,
|
||||
);
|
||||
"Dependencies/Dynamic Libraries/SoftwareKeyboard.framework" = (
|
||||
CodeSignOnCopy,
|
||||
RemoveHeadersOnCopy,
|
||||
);
|
||||
"Dependencies/Dynamic Libraries/libMoltenVK.dylib" = (
|
||||
CodeSignOnCopy,
|
||||
);
|
||||
@ -121,6 +125,7 @@
|
||||
"Dependencies/Dynamic Libraries/libavutil.dylib",
|
||||
"Dependencies/Dynamic Libraries/libMoltenVK.dylib",
|
||||
"Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib",
|
||||
"Dependencies/Dynamic Libraries/SoftwareKeyboard.framework",
|
||||
Dependencies/XCFrameworks/libavcodec.xcframework,
|
||||
Dependencies/XCFrameworks/libavfilter.xcframework,
|
||||
Dependencies/XCFrameworks/libavformat.xcframework,
|
||||
@ -146,8 +151,8 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4E4854022D138D7600A446A6 /* GameController.framework in Frameworks */,
|
||||
4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */,
|
||||
4E551F202CF128540096A2DF /* GameController.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -515,6 +520,8 @@
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/XCFrameworks",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
);
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = MeloNX/Info.plist;
|
||||
@ -643,6 +650,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",
|
||||
);
|
||||
MARKETING_VERSION = 0.0.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
||||
@ -669,6 +680,8 @@
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/XCFrameworks",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
);
|
||||
GCC_OPTIMIZATION_LEVEL = 3;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@ -798,6 +811,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",
|
||||
);
|
||||
MARKETING_VERSION = 0.0.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
||||
|
Binary file not shown.
@ -14,8 +14,8 @@
|
||||
filePath = "MeloNX/Views/GamesList/GameListView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "264"
|
||||
endingLineNumber = "264"
|
||||
startingLineNumber = "271"
|
||||
endingLineNumber = "271"
|
||||
landmarkName = "loadGames()"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
|
@ -0,0 +1,18 @@
|
||||
//
|
||||
// SoftwareKeyboard.h
|
||||
// SoftwareKeyboard
|
||||
//
|
||||
// Created by Stossy11 on 19/12/2024.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for SoftwareKeyboard.
|
||||
FOUNDATION_EXPORT double SoftwareKeyboardVersionNumber;
|
||||
|
||||
//! Project version string for SoftwareKeyboard.
|
||||
FOUNDATION_EXPORT const unsigned char SoftwareKeyboardVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <SoftwareKeyboard/PublicHeader.h>
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
||||
// swift-interface-format-version: 1.0
|
||||
// swift-compiler-version: Apple Swift version 6.0.3 effective-5.10 (swiftlang-6.0.3.1.4 clang-1600.0.30)
|
||||
// swift-module-flags: -target arm64-apple-ios14.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -Onone -enable-experimental-feature OpaqueTypeErasure -enable-bare-slash-regex -module-name SoftwareKeyboard
|
||||
@_exported import SoftwareKeyboard
|
||||
import Swift
|
||||
import UIKit
|
||||
import _Concurrency
|
||||
import _StringProcessing
|
||||
import _SwiftConcurrencyShims
|
||||
@objc public enum KeyboardMode : Swift.UInt32 {
|
||||
case `default` = 0
|
||||
case numeric = 1
|
||||
case ascii = 2
|
||||
case fullLatin = 3
|
||||
case alphabet = 4
|
||||
case simplifiedChinese = 5
|
||||
case traditionalChinese = 6
|
||||
case korean = 7
|
||||
case languageSet2 = 8
|
||||
case languageSet2Latin = 9
|
||||
public init?(rawValue: Swift.UInt32)
|
||||
public typealias RawValue = Swift.UInt32
|
||||
public var rawValue: Swift.UInt32 {
|
||||
get
|
||||
}
|
||||
}
|
||||
public struct SoftwareKeyboardUiArgs {
|
||||
public var keyboardMode: SoftwareKeyboard.KeyboardMode
|
||||
public var headerText: Swift.String
|
||||
public var subtitleText: Swift.String
|
||||
public var submitText: Swift.String
|
||||
public var stringLengthMin: Swift.Int32
|
||||
public var stringLengthMax: Swift.Int32
|
||||
public var initialText: Swift.String?
|
||||
}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Equatable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Hashable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.RawRepresentable {}
|
Binary file not shown.
@ -0,0 +1,38 @@
|
||||
// swift-interface-format-version: 1.0
|
||||
// swift-compiler-version: Apple Swift version 6.0.3 effective-5.10 (swiftlang-6.0.3.1.4 clang-1600.0.30)
|
||||
// swift-module-flags: -target arm64-apple-ios14.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -Onone -enable-experimental-feature OpaqueTypeErasure -enable-bare-slash-regex -module-name SoftwareKeyboard
|
||||
@_exported import SoftwareKeyboard
|
||||
import Swift
|
||||
import UIKit
|
||||
import _Concurrency
|
||||
import _StringProcessing
|
||||
import _SwiftConcurrencyShims
|
||||
@objc public enum KeyboardMode : Swift.UInt32 {
|
||||
case `default` = 0
|
||||
case numeric = 1
|
||||
case ascii = 2
|
||||
case fullLatin = 3
|
||||
case alphabet = 4
|
||||
case simplifiedChinese = 5
|
||||
case traditionalChinese = 6
|
||||
case korean = 7
|
||||
case languageSet2 = 8
|
||||
case languageSet2Latin = 9
|
||||
public init?(rawValue: Swift.UInt32)
|
||||
public typealias RawValue = Swift.UInt32
|
||||
public var rawValue: Swift.UInt32 {
|
||||
get
|
||||
}
|
||||
}
|
||||
public struct SoftwareKeyboardUiArgs {
|
||||
public var keyboardMode: SoftwareKeyboard.KeyboardMode
|
||||
public var headerText: Swift.String
|
||||
public var subtitleText: Swift.String
|
||||
public var submitText: Swift.String
|
||||
public var stringLengthMin: Swift.Int32
|
||||
public var stringLengthMax: Swift.Int32
|
||||
public var initialText: Swift.String?
|
||||
}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Equatable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Hashable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.RawRepresentable {}
|
Binary file not shown.
@ -0,0 +1,6 @@
|
||||
framework module SoftwareKeyboard {
|
||||
umbrella header "SoftwareKeyboard.h"
|
||||
export *
|
||||
|
||||
module * { export * }
|
||||
}
|
Binary file not shown.
@ -12,6 +12,7 @@ import Darwin
|
||||
import UIKit
|
||||
import MetalKit
|
||||
// import SDL
|
||||
import SoftwareKeyboard
|
||||
|
||||
struct MoltenVKSettings: Codable, Hashable {
|
||||
let string: String
|
||||
|
@ -134,6 +134,13 @@ struct GameLibraryView: View {
|
||||
} label: {
|
||||
Text("Remove Firmware")
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
self.startemu = URL(string: "MiiMaker")
|
||||
} label: {
|
||||
Text("Mii Maker")
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
@ -147,7 +154,7 @@ struct GameLibraryView: View {
|
||||
Text("Show MeloNX Folder")
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "plus")
|
||||
Image(systemName: "ellipsis")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
{
|
||||
internal class SoftwareKeyboardApplet : IApplet
|
||||
{
|
||||
private const string DefaultInputText = "Ryujinx";
|
||||
private const string DefaultInputText = "MeloNX";
|
||||
|
||||
private const int StandardBufferSize = 0x7D8;
|
||||
private const int InteractiveBufferSize = 0x7D4;
|
||||
@ -180,6 +180,10 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
return _keyboardRenderer?.DrawTo(destination, position) ?? false;
|
||||
}
|
||||
|
||||
[DllImport("SoftwareKeyboard.framework/SoftwareKeyboard", EntryPoint = "displayInputDialog", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void DisplayInputDialog(ref SoftwareKeyboardUiArgs args, out IntPtr userInput);
|
||||
|
||||
|
||||
private void ExecuteForegroundKeyboard()
|
||||
{
|
||||
string initialText = null;
|
||||
@ -188,23 +192,57 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
// InitialStringOffset points to the memory offset and InitialStringLength is the number of UTF-16 characters
|
||||
if (_transferMemory != null && _keyboardForegroundConfig.InitialStringLength > 0)
|
||||
{
|
||||
initialText = Encoding.Unicode.GetString(_transferMemory, _keyboardForegroundConfig.InitialStringOffset,
|
||||
initialText = Encoding.Unicode.GetString(
|
||||
_transferMemory,
|
||||
_keyboardForegroundConfig.InitialStringOffset,
|
||||
2 * _keyboardForegroundConfig.InitialStringLength);
|
||||
}
|
||||
|
||||
// If the max string length is 0, we set it to a large default
|
||||
// length.
|
||||
// If the max string length is 0, we set it to a large default length.
|
||||
if (_keyboardForegroundConfig.StringLengthMax == 0)
|
||||
{
|
||||
_keyboardForegroundConfig.StringLengthMax = 100;
|
||||
}
|
||||
|
||||
// If no GUI handler is set, fallback to default behavior.
|
||||
if (_device.UiHandler == null)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "GUI Handler is not set. Falling back to default");
|
||||
|
||||
_textValue = DefaultInputText;
|
||||
// Prepare the SoftwareKeyboardUiArgs struct
|
||||
var args = new SoftwareKeyboardUiArgs
|
||||
{
|
||||
KeyboardMode = _keyboardForegroundConfig.Mode,
|
||||
HeaderText = StripUnicodeControlCodes(_keyboardForegroundConfig.HeaderText),
|
||||
SubtitleText = StripUnicodeControlCodes(_keyboardForegroundConfig.SubtitleText),
|
||||
SubmitText = !string.IsNullOrWhiteSpace(_keyboardForegroundConfig.SubmitText)
|
||||
? _keyboardForegroundConfig.SubmitText
|
||||
: "OK",
|
||||
StringLengthMin = _keyboardForegroundConfig.StringLengthMin,
|
||||
StringLengthMax = _keyboardForegroundConfig.StringLengthMax,
|
||||
InitialText = initialText,
|
||||
};
|
||||
|
||||
IntPtr userInputPtr;
|
||||
|
||||
DisplayInputDialog(ref args, out userInputPtr);
|
||||
if (userInputPtr != IntPtr.Zero)
|
||||
{
|
||||
// Convert the IntPtr to a string
|
||||
string userInput = Marshal.PtrToStringAnsi(userInputPtr);
|
||||
|
||||
_textValue = userInput ?? DefaultInputText;
|
||||
_lastResult = KeyboardResult.Accept;
|
||||
|
||||
Console.WriteLine($"User input: {userInput}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No input was received or input was canceled.");
|
||||
|
||||
_textValue = DefaultInputText;
|
||||
_lastResult = KeyboardResult.Cancel;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -226,46 +264,36 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
_textValue ??= initialText ?? DefaultInputText;
|
||||
}
|
||||
|
||||
// If the game requests a string with a minimum length less
|
||||
// than our default text, repeat our default text until we meet
|
||||
// the minimum length requirement.
|
||||
// This should always be done before the text truncation step.
|
||||
// Ensure the text meets the minimum length requirement
|
||||
while (_textValue.Length < _keyboardForegroundConfig.StringLengthMin)
|
||||
{
|
||||
_textValue = String.Join(" ", _textValue, _textValue);
|
||||
_textValue = string.Join(" ", _textValue, _textValue);
|
||||
}
|
||||
|
||||
// If our default text is longer than the allowed length,
|
||||
// we truncate it.
|
||||
// Truncate the text if it exceeds the maximum length
|
||||
if (_textValue.Length > _keyboardForegroundConfig.StringLengthMax)
|
||||
{
|
||||
_textValue = _textValue[.._keyboardForegroundConfig.StringLengthMax];
|
||||
}
|
||||
|
||||
// Does the application want to validate the text itself?
|
||||
// Handle text validation if required
|
||||
if (_keyboardForegroundConfig.CheckText)
|
||||
{
|
||||
// The application needs to validate the response, so we
|
||||
// submit it to the interactive output buffer, and poll it
|
||||
// for validation. Once validated, the application will submit
|
||||
// back a validation status, which is handled in OnInteractiveDataPushIn.
|
||||
// Submit text for validation
|
||||
_foregroundState = SoftwareKeyboardState.ValidationPending;
|
||||
|
||||
PushForegroundResponse(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the application doesn't need to validate the response,
|
||||
// we push the data to the non-interactive output buffer
|
||||
// and poll it for completion.
|
||||
// Submit text as complete
|
||||
_foregroundState = SoftwareKeyboardState.Complete;
|
||||
|
||||
PushForegroundResponse(false);
|
||||
|
||||
AppletStateChanged?.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnInteractiveData(object sender, EventArgs e)
|
||||
{
|
||||
// Obtain the validation status response.
|
||||
|
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
{
|
||||
byte[] defaultUserImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/DefaultUserImage.jpg");
|
||||
|
||||
AddUser("RyuPlayer", defaultUserImage, DefaultUserId);
|
||||
AddUser("MeloNX", defaultUserImage, DefaultUserId);
|
||||
|
||||
OpenUser(DefaultUserId);
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 16 KiB |
@ -1100,6 +1100,12 @@ namespace Ryujinx.Headless.SDL2
|
||||
return;
|
||||
}
|
||||
|
||||
if (option.InputPath == "MiiMaker") {
|
||||
string contentPath = _contentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
|
||||
|
||||
option.InputPath = contentPath;
|
||||
}
|
||||
|
||||
_inputConfiguration = new List<InputConfig>();
|
||||
_enableKeyboard = option.EnableKeyboard;
|
||||
_enableMouse = option.EnableMouse;
|
||||
@ -1324,6 +1330,17 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
|
||||
|
||||
bool isFirmwareTitle = false;
|
||||
|
||||
if (path.StartsWith("@SystemContent"))
|
||||
{
|
||||
path = VirtualFileSystem.SwitchPathToSystemPath(path);
|
||||
|
||||
isFirmwareTitle = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
|
||||
@ -1392,6 +1409,17 @@ namespace Ryujinx.Headless.SDL2
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isFirmwareTitle) {
|
||||
Logger.Info?.Print(LogClass.Application, "Loading as Firmware Title (NCA).");
|
||||
|
||||
if (!_emulationContext.LoadNca(path))
|
||||
{
|
||||
_emulationContext.Dispose();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
|
||||
try
|
||||
{
|
||||
@ -1410,6 +1438,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user