Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sony PlayStation Vita Platform #222

Closed
Cp1N3m0 opened this issue Feb 14, 2023 · 19 comments
Closed

Sony PlayStation Vita Platform #222

Cp1N3m0 opened this issue Feb 14, 2023 · 19 comments
Labels
platforms and players This issue is related to platforms and players configuration

Comments

@Cp1N3m0
Copy link

Cp1N3m0 commented Feb 14, 2023

Please add Sony PlayStation Vita as Platform

https://vita3k.org/
https://github.com/Vita3K/Vita3K-Android

@TapiocaFox
Copy link
Owner

Sure. I have contacted vita3k author. And fortunately, they said they are working on it!

@Cp1N3m0
Copy link
Author

Cp1N3m0 commented Mar 3, 2023

Thank you

@TapiocaFox TapiocaFox added the platforms and players This issue is related to platforms and players configuration label Mar 6, 2023
@Mente2
Copy link

Mente2 commented Mar 26, 2023

Vita3k new update has came with support. So, you should add it now

@TapiocaFox TapiocaFox mentioned this issue Mar 31, 2023
@Cp1N3m0
Copy link
Author

Cp1N3m0 commented Mar 31, 2023

Vita3k new update has came with support. So, you should add it now

thanks will test it

@Cp1N3m0
Copy link
Author

Cp1N3m0 commented Mar 31, 2023

So, I have updated Daijishou and Vita3K

imported the platform,
https://github.com/magneticchen/Daijishou/blob/main/platforms/SonyPSVita.json.test

and added "Android/data/org.vita3k.emulation/files/vita/ux0/app" as a path but no games are detected, am I doing something wrong

Thanks

@Macdu
Copy link

Macdu commented Apr 2, 2023

Btw, I changed the parameter flag in V3 from AppRestartParameters to AppStartParameters in case you are wondering why this command does not work anymore. I'm not planning on changing it again.

@TapiocaFox
Copy link
Owner

Btw, I changed the parameter flag in V3 from AppRestartParameters to AppStartParameters in case you are wondering why this command does not work anymore. I'm not planning on changing it again.

Thanks. I will try this command.

@TapiocaFox
Copy link
Owner

TapiocaFox commented Apr 17, 2023

Sorry for the late update. I've tried AppStartParameters with vita's application id to launch vita game. While it works via adb command from PC. It doesn't work directly in Daijishou, however. It launched Vita3k, but only the home screen menu displayed.

I've carefully checked several times whether I've implement it incorrectly, but nothing quirky afaik. A mention that Dai implements the am start parameter directly from AOSP project. I have no idea what goes wrong preventing it working for now. Not sure if anything missing from my side.

Here is the snippet related.

/*
 * Copyright(c) 2023 Daijishou project, TapiocaFox. All rights reserved.
 * Created by TapiocaFox (magneticchen) on 21/03/2023, 09:36.
 * Last modified 17/03/2023, 06:45.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.magneticchen.daijishou.daijishou_player

import android.content.ComponentName
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log.d
import java.net.URISyntaxException
import java.util.*


/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


// See https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/content/Intent.java
// parseCommandargumentLinkedList method

internal object AmStartCommandToIntentConverter {
    @Throws(URISyntaxException::class)
    fun createIntentByCommandArgs(arguments: String, tokenReplaceList: List<Pair<String, String>>): Intent {

        val argumentSplitted = arguments.split("[\\n\\s]+".toRegex())
        val argumentsReplacedAndSplit = List(argumentSplitted.size) { i ->
            var string = argumentSplitted[i]
            tokenReplaceList.forEach{
                string = string.replace(it.first, it.second)
            }
            string
        }

        val argumentLinkedList: LinkedList<String> = LinkedList(argumentsReplacedAndSplit)
        var intent = Intent()
        var baseIntent: Intent? = intent
        var hasIntentInfo = false
        var data: Uri? = null
        var type: String? = null
        while (!argumentLinkedList.isEmpty()) {
            when (val opt = argumentLinkedList.pop()) {
                "-a" -> {
                    intent.action = argumentLinkedList.pop()
                    if (intent === baseIntent) hasIntentInfo = true
                }
                "-d" -> {
                    data = Uri.parse(argumentLinkedList.pop())
//                    d("daijishou_debug", "$data")
                    if (intent === baseIntent) hasIntentInfo = true
                }
                "-t" -> {
                    type = argumentLinkedList.pop()
                    if (intent === baseIntent) hasIntentInfo = true
                }
                "-i" -> {
                    intent.identifier = argumentLinkedList.pop()
                    if (intent === baseIntent) hasIntentInfo = true
                }
                "-c" -> {
                    intent.addCategory(argumentLinkedList.pop())
                    if (intent === baseIntent) hasIntentInfo = true
                }
                "-e", "--es" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    intent.putExtra(key, value)
                }
                "--esn" -> {
                    val key = argumentLinkedList.pop()
                    intent.putExtra(key, null as String?)
                }
                "--ei" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    intent.putExtra(key, Integer.decode(value))
                }
                "--eu" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    intent.putExtra(key, Uri.parse(value))
                }
                "--ecn" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    val cn = ComponentName.unflattenFromString(value)
                        ?: throw IllegalArgumentException("Bad component name: $value")
                    intent.putExtra(key, cn)
                }
                "--eia" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    val strings = value.split(",").toTypedArray()
                    val list = IntArray(strings.size)
                    var i = 0
                    while (i < strings.size) {
                        list[i] = Integer.decode(strings[i])
                        i++
                    }
                    intent.putExtra(key, list)
                }
                "--eial" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    val strings = value.split(",").toTypedArray()
                    val list = ArrayList<Int>(strings.size)
                    var i = 0
                    while (i < strings.size) {
                        list.add(Integer.decode(strings[i]))
                        i++
                    }
                    intent.putExtra(key, list)
                }
                "--el" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    intent.putExtra(key, java.lang.Long.valueOf(value))
                }
                "--ela" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    val strings = value.split(",").toTypedArray()
                    val list = LongArray(strings.size)
                    var i = 0
                    while (i < strings.size) {
                        list[i] = java.lang.Long.valueOf(strings[i])
                        i++
                    }
                    intent.putExtra(key, list)
                    hasIntentInfo = true
                }
                "--elal" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    val strings = value.split(",").toTypedArray()
                    val list = ArrayList<Long>(strings.size)
                    var i = 0
                    while (i < strings.size) {
                        list.add(java.lang.Long.valueOf(strings[i]))
                        i++
                    }
                    intent.putExtra(key, list)
                    hasIntentInfo = true
                }
                "--ef" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    intent.putExtra(key, java.lang.Float.valueOf(value))
                    hasIntentInfo = true
                }
                "--efa" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    val strings = value.split(",").toTypedArray()
                    val list = FloatArray(strings.size)
                    var i = 0
                    while (i < strings.size) {
                        list[i] = java.lang.Float.valueOf(strings[i])
                        i++
                    }
                    intent.putExtra(key, list)
                    hasIntentInfo = true
                }
                "--efal" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    val strings = value.split(",").toTypedArray()
                    val list = ArrayList<Float>(strings.size)
                    var i = 0
                    while (i < strings.size) {
                        list.add(java.lang.Float.valueOf(strings[i]))
                        i++
                    }
                    intent.putExtra(key, list)
                    hasIntentInfo = true
                }
                "--esa" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    // Split on commas unless they are preceeded by an escape.
                    // The escape character must be escaped for the string and
                    // again for the regex, thus four escape characters become one.
                    val strings = value.split("(?<!\\\\),").toTypedArray()
                    intent.putExtra(key, strings)
                    hasIntentInfo = true
                }
                "--esal" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop()
                    // Split on commas unless they are preceeded by an escape.
                    // The escape character must be escaped for the string and
                    // again for the regex, thus four escape characters become one.
                    val strings = value.split("(?<!\\\\),").toTypedArray()
                    val list = ArrayList<String>(strings.size)
                    var i = 0
                    while (i < strings.size) {
                        list.add(strings[i])
                        i++
                    }
                    intent.putExtra(key, list)
                    hasIntentInfo = true
                }
                "--ez" -> {
                    val key = argumentLinkedList.pop()
                    val value = argumentLinkedList.pop().lowercase(Locale.getDefault())
                    // Boolean.valueOf() results in false for anything that is not "true", which is
                    // error-prone in shell commands
                    val arg: Boolean = if ("true" == value || "t" == value) {
                        true
                    } else if ("false" == value || "f" == value) {
                        false
                    } else {
                        try {
                            Integer.decode(value) != 0
                        } catch (ex: NumberFormatException) {
                            throw IllegalArgumentException("Invalid boolean value: $value")
                        }
                    }
                    intent.putExtra(key, arg)
                }
                "-n" -> {
                    val str = argumentLinkedList.pop()
                    val cn = ComponentName.unflattenFromString(str)
                        ?: throw IllegalArgumentException("Bad component name: $str")
                    intent.component = cn
                    if (intent === baseIntent) hasIntentInfo = true
                }
                "-p" -> {
                    val str = argumentLinkedList.pop()
                    intent.setPackage(str)
                    if (intent === baseIntent) hasIntentInfo = true
                }
                "-f" -> {
                    val str = argumentLinkedList.pop()
                    intent.flags = Integer.decode(str).toInt()
                }
                "--grant-read-uri-permission" -> intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                "--grant-write-uri-permission" -> intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                "--grant-persistable-uri-permission" -> intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
                "--grant-prefix-uri-permission" -> intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION)
                "--exclude-stopped-packages" -> intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES)
                "--include-stopped-packages" -> intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
                "--debug-log-resolution" -> intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION)
                "--activity-brought-to-front" -> intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
                "--activity-clear-top" -> intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                "--activity-clear-when-task-reset" -> intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
                "--activity-exclude-from-recents" -> intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
                "--activity-launched-from-history" -> intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)
                "--activity-multiple-task" -> intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
                "--activity-no-animation" -> intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
                "--activity-no-history" -> intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
                "--activity-no-user-action" -> intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION)
                "--activity-previous-is-top" -> intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
                "--activity-reorder-to-front" -> intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
                "--activity-reset-task-if-needed" -> intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                "--activity-single-top" -> intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
                "--activity-clear-task" -> intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
                "--activity-task-on-home" -> intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME)
                "--activity-match-external" -> intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL)
                "--receiver-registered-only" -> intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                "--receiver-replace-pending" -> intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING)
                "--receiver-foreground" -> intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                "--receiver-no-abort" -> intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT)
                "--selector" -> {
                    intent.setDataAndType(data, type)
                    intent = Intent()
                }

                // Ignore below "am start" arguments key and pop value too.
                "-P", "--user", "--start-profiler", "--sampling", "--attach-agent", "--attach-agent-bind", "-R", "--receiver-permission", "--display", "--windowingMode", "--activityType", "--task" -> {
                    argumentLinkedList.pop()
                }
                // Ignore below singular "am start" arguments key.
                "", "-D", "-N", "-W", "-S", "--streaming", "--track-allocation", "--task-overlay", "--lock-task", "--allow-background-activity-starts" -> {}

                else -> throw IllegalArgumentException("Unknown option: $opt")
            }
        }
        intent.setDataAndType(data, type)
        val hasSelector = intent !== baseIntent
        if (hasSelector) {
            // A selector was specified; fix up.
            baseIntent!!.selector = intent
            intent = baseIntent
        }
        val arg = if (argumentLinkedList.isEmpty()) null else argumentLinkedList.pop()
        baseIntent = null
        if (arg == null) {
            if (hasSelector) {
                // If a selector has been specified, and no arguments
                // have been supplied for the main Intent, then we can
                // assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't
                // need to have a component name specified yet, the
                // selector will take care of that.
                baseIntent = Intent(Intent.ACTION_MAIN)
                baseIntent.addCategory(Intent.CATEGORY_LAUNCHER)
            }
        } else if (arg.indexOf(':') >= 0) {
            // The argument is a URI.  Fully parse it, and use that result
            // to fill in any data not specified so far.
            baseIntent = Intent.parseUri(
                arg, Intent.URI_INTENT_SCHEME
                        or Intent.URI_ANDROID_APP_SCHEME or Intent.URI_ALLOW_UNSAFE
            )
        } else if (arg.indexOf('/') >= 0) {
            // The argument is a component name.  Build an Intent to launch
            // it.
            baseIntent = Intent(Intent.ACTION_MAIN)
            baseIntent.addCategory(Intent.CATEGORY_LAUNCHER)
            baseIntent.component = ComponentName.unflattenFromString(arg)
        } else {
            // Assume the argument is a package name.
            baseIntent = Intent(Intent.ACTION_MAIN)
            baseIntent.addCategory(Intent.CATEGORY_LAUNCHER)
            baseIntent.setPackage(arg)
        }
        if (baseIntent != null) {
            var extras = intent.extras
            intent.replaceExtras(null as Bundle?)
            val uriExtras = baseIntent.extras
            baseIntent.replaceExtras(null as Bundle?)
            if (intent.action != null && baseIntent.categories != null) {
                val cats = HashSet(baseIntent.categories)
                for (c in cats) {
                    baseIntent.removeCategory(c)
                }
            }
            intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT or Intent.FILL_IN_SELECTOR)
            if (extras == null) {
                extras = uriExtras
            } else if (uriExtras != null) {
                uriExtras.putAll(extras)
                extras = uriExtras
            }
            intent.replaceExtras(extras)
            hasIntentInfo = true
        }
        require(hasIntentInfo) { "No intent supplied" }
        // Add addition flags for player.
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        return intent
    }
}

@Post-Mortem Post-Mortem mentioned this issue Apr 24, 2023
@mantis-droid
Copy link

Any further thoughts on this one? Working on testing this as well and encountered the same issue

@mroemore
Copy link

Has anyone had any success with this? I am running into the same issue of Daijishou only launching to the home screen. Maybe it's worth taking a look at how ES-DE does it as it works there?

@stevenbrookslv
Copy link

Seeming to have the same issue, tried putting the actual id of the game in the daijisho parameters as well as changing AppStartParameters to AppRestartParameters but neither seems to work to launch the game

@EagleFlyInSky
Copy link

EagleFlyInSky commented Mar 31, 2024

val strings = value.split("(?<!\\\\),").toTypedArray()
to
val strings = value.split("(?<!\\\\),".toRegex()).toTypedArray()

Otherwise, Kotlin cannot use regex .

It works fine with the following configuration .
"amStartArguments": "-n org.vita3k.emulator/org.vita3k.emulator.Emulator\n --esa AppStartParameters -r(?<!\\\\),{tags.game_id}",

@TapiocaFox

@Jetup13
Copy link
Collaborator

Jetup13 commented Apr 22, 2024

Thanks again, as noted in #652 I added Vita to the platform list. I will create a section in the wiki on how to create dpt files.

Added in 0588af3

If others can test and report the android version and device they are using that would be great. I confirmed it working on the Retroid Pocket 4 Pro/Android 13

@smlcr
Copy link

smlcr commented Apr 23, 2024

@Jetup13 Good day! Ayn Odin Lite, Android 11, Vita3k v11 (latest version), all is working great. I guess it's no matter what device are used, except OS version.

@salamandercc37
Copy link

I imported the recent SonyPSVita.json file located at https://github.com/TapiocaFox/Daijishou/blob/main/platforms/SonyPSVita.json
The VITA platform appears well in daijishou on my R4PPRO
On the other hand, I don't understand how to create a link with VITA3K. Create a DPT? how ? what should you put inside? Thank you for your help.

@Jetup13
Copy link
Collaborator

Jetup13 commented Apr 25, 2024

@salamandercc37 I explained how to add Vita games in the wiki here. Within that link I also pregenerated a few thousand dpt files that anyone can use.

@salamandercc37
Copy link

@salamandercc37 I explained how to add Vita games in the wiki here. Within that link I also pregenerated a few thousand dpt files that anyone can use.

Thank you for your quick reply.
I'm going to try this tonight when I get home.

@salamandercc37
Copy link

@salamandercc37 I explained how to add Vita games in the wiki here. Within that link I also pregenerated a few thousand dpt files that anyone can use.

Thank you for your help. Everything works perfectly

@TapiocaFox
Copy link
Owner

val strings = value.split("(?<!\\\\),").toTypedArray() to val strings = value.split("(?<!\\\\),".toRegex()).toTypedArray()

Otherwise, Kotlin cannot use regex .

It works fine with the following configuration . "amStartArguments": "-n org.vita3k.emulator/org.vita3k.emulator.Emulator\n --esa AppStartParameters -r(?<!\\\\),{tags.game_id}",

@TapiocaFox

I will update that on 1.4.69.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platforms and players This issue is related to platforms and players configuration
Projects
None yet
Development

No branches or pull requests