Daijishou
Daijishou copied to clipboard
Sony PlayStation Vita Platform
Please add Sony PlayStation Vita as Platform
https://vita3k.org/ https://github.com/Vita3K/Vita3K-Android
Sure. I have contacted vita3k author. And fortunately, they said they are working on it!
Thank you
Vita3k new update has came with support. So, you should add it now
Vita3k new update has came with support. So, you should add it now
thanks will test it
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
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.
Btw, I changed the parameter flag in V3 from
AppRestartParameterstoAppStartParametersin 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.
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
}
}
Any further thoughts on this one? Working on testing this as well and encountered the same issue
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?
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
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
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
@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.
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.
@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 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 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
val strings = value.split("(?<!\\\\),").toTypedArray()toval 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.